package org.fandev.lang.fan.psi.impl.statements.typedefs.members; import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.impl.PsiSuperMethodImplUtil; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.NamedStub; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.MethodSignatureUtil; import org.fandev.icons.Icons; import org.fandev.lang.fan.psi.api.statements.params.FanParameterList; import org.fandev.lang.fan.psi.api.statements.typeDefs.members.FanMethod; import org.fandev.lang.fan.psi.api.types.FanTypeElement; import org.fandev.lang.fan.psi.impl.PsiImplUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.ArrayList; /** * @author Dror Bereznitsky * @date Jan 10, 2009 6:59:12 PM */ public abstract class FanMethodBaseImpl<T extends NamedStub> extends FanSlotElementImpl<T> implements FanMethod { public FanMethodBaseImpl(final T t, @NotNull final IStubElementType iStubElementType) { super(t, iStubElementType); } public FanMethodBaseImpl(final ASTNode astNode) { super(astNode); } @Override public Icon getIconInner() { return Icons.METHOD; } public PsiType getReturnType() { final FanTypeElement typeElement = findChildByClass(FanTypeElement.class); if (typeElement != null) { return typeElement.getType(); } return PsiType.VOID; } public PsiType getReturnTypeNoResolve() { return getReturnType(); } public PsiTypeElement getReturnTypeElement() { return null; } @NotNull public PsiParameterList getParameterList() { final FanParameterList parameterList = findChildByClass(FanParameterList.class); assert parameterList != null; return parameterList; } @NotNull public PsiReferenceList getThrowsList() { return null; //To change body of implemented methods use File | Settings | File Templates. } public PsiCodeBlock getBody() { return findChildByClass(PsiCodeBlock.class); } public boolean isVarArgs() { return false; } @NotNull public MethodSignature getSignature(@NotNull final PsiSubstitutor substitutor) { return MethodSignatureBackedByPsiMethod.create(this, substitutor); } @NotNull public PsiMethod[] findSuperMethods() { final PsiClass containingClass = getContainingClass(); if (containingClass == null) { return PsiMethod.EMPTY_ARRAY; } final Set<PsiMethod> methods = new HashSet<PsiMethod>(); findSuperMethodRecursilvely(methods, containingClass, false, new HashSet<PsiClass>(), createMethodSignature(this), new HashSet<MethodSignature>()); return methods.toArray(new PsiMethod[0]); } @NotNull public PsiMethod[] findSuperMethods(final boolean checkAccess) { final PsiClass containingClass = getContainingClass(); final Set<PsiMethod> methods = new HashSet<PsiMethod>(); findSuperMethodRecursilvely(methods, containingClass, false, new HashSet<PsiClass>(), createMethodSignature(this), new HashSet<MethodSignature>()); return methods.toArray(new PsiMethod[0]); } @NotNull public PsiMethod[] findSuperMethods(final PsiClass parentClass) { final Set<PsiMethod> methods = new HashSet<PsiMethod>(); findSuperMethodRecursilvely(methods, parentClass, false, new HashSet<PsiClass>(), createMethodSignature(this), new HashSet<MethodSignature>()); return methods.toArray(new PsiMethod[0]); } @NotNull public List<MethodSignatureBackedByPsiMethod> findSuperMethodSignaturesIncludingStatic(final boolean checkAccess) { final PsiClass containingClass = getContainingClass(); final Set<PsiMethod> methods = new HashSet<PsiMethod>(); final MethodSignature signature = createMethodSignature(this); findSuperMethodRecursilvely(methods, containingClass, true, new HashSet<PsiClass>(), signature, new HashSet<MethodSignature>()); final List<MethodSignatureBackedByPsiMethod> result = new ArrayList<MethodSignatureBackedByPsiMethod>(); for (final PsiMethod method : methods) { result.add(method.getHierarchicalMethodSignature()); } return result; } /* * @deprecated use {@link #findDeepestSuperMethods()} instead */ public PsiMethod findDeepestSuperMethod() { return null; } @NotNull public PsiMethod[] findDeepestSuperMethods() { return new PsiMethod[0]; //To change body of implemented methods use File | Settings | File Templates. } @NotNull public HierarchicalMethodSignature getHierarchicalMethodSignature() { return PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this); } public void setBlock(final PsiCodeBlock newBlock) { final ASTNode newNode = newBlock.getNode().copyElement(); final PsiCodeBlock oldBlock = getBody(); if (oldBlock == null) { getNode().addChild(newNode); return; } getNode().replaceChild(oldBlock.getNode(), newNode); } public static MethodSignature createMethodSignature(final PsiMethod method) { final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiType[] types = new PsiType[parameters.length]; for (int i = 0; i < types.length; i++) { types[i] = parameters[i].getType(); } return MethodSignatureUtil.createMethodSignature(method.getName(), types, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); } private void findSuperMethodRecursilvely(final Set<PsiMethod> methods, final PsiClass psiClass, final boolean allowStatic, final Set<PsiClass> visited, final MethodSignature signature, @NotNull final Set<MethodSignature> discoveredSupers) { if (psiClass == null) return; if (visited.contains(psiClass)) return; visited.add(psiClass); final PsiClassType[] superClassTypes = psiClass.getSuperTypes(); for (final PsiClassType superClassType : superClassTypes) { final PsiClass resolvedSuperClass = superClassType.resolve(); if (resolvedSuperClass == null) continue; final PsiMethod[] superClassMethods = resolvedSuperClass.getMethods(); final HashSet<MethodSignature> supers = new HashSet<MethodSignature>(3); for (final PsiMethod superClassMethod : superClassMethods) { final MethodSignature superMethodSignature = createMethodSignature(superClassMethod); if (PsiImplUtil.isExtendsSignature(superMethodSignature, signature)) { if (allowStatic || !superClassMethod.getModifierList().hasExplicitModifier(PsiModifier.STATIC)) { methods.add(superClassMethod); supers.add(superMethodSignature); discoveredSupers.add(superMethodSignature); } } } findSuperMethodRecursilvely(methods, resolvedSuperClass, allowStatic, visited, signature, discoveredSupers); discoveredSupers.removeAll(supers); } } }