diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java index 3ff0a32375e..109966f7901 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.java @@ -14,6 +14,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.Navigatable; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.ui.LayeredIcon; import com.intellij.util.Function; @@ -30,9 +31,12 @@ import org.jetbrains.jet.renderer.DescriptorRenderer; import javax.swing.*; import java.awt.*; +import java.util.HashSet; +import java.util.Set; public class KotlinCallHierarchyNodeDescriptor extends HierarchyNodeDescriptor implements Navigatable { - private int usageCount = 1; + private int usageCount = 0; + private final Set references = new HashSet(); private final CallHierarchyNodeDescriptor javaDelegate; public KotlinCallHierarchyNodeDescriptor(@NotNull Project project, @@ -48,8 +52,11 @@ public class KotlinCallHierarchyNodeDescriptor extends HierarchyNodeDescriptor i return javaDelegate; } - public final void incrementUsageCount(){ - usageCount++; + public final void addReference(PsiReference reference) { + if (references.add(reference)) { + usageCount++; + } + javaDelegate.addReference(reference); } public final PsiElement getTargetElement(){ @@ -210,18 +217,16 @@ public class KotlinCallHierarchyNodeDescriptor extends HierarchyNodeDescriptor i @Override public void navigate(boolean requestFocus) { - if (myElement instanceof Navigatable) { - ((Navigatable)myElement).navigate(requestFocus); - } + javaDelegate.navigate(requestFocus); } @Override public boolean canNavigate() { - return myElement instanceof Navigatable && ((Navigatable) myElement).canNavigate(); + return javaDelegate.canNavigate(); } @Override public boolean canNavigateToSource() { - return canNavigate(); + return javaDelegate.canNavigateToSource(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java index 364997273af..ca6f5ef04b1 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallTreeStructure.java @@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; import jet.Function1; @@ -16,14 +17,13 @@ import org.jetbrains.jet.asJava.LightClassUtil; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage; -import java.util.List; import java.util.Map; public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { protected final String scopeType; public KotlinCallTreeStructure(@NotNull Project project, PsiElement element, String scopeType) { - super(project, createNodeDescriptor(project, element, null)); + super(project, createNodeDescriptor(project, element, null, false)); this.scopeType = scopeType; } @@ -33,11 +33,13 @@ public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { : null; } - protected static HierarchyNodeDescriptor createNodeDescriptor(Project project, PsiElement element, HierarchyNodeDescriptor parent) { + protected static HierarchyNodeDescriptor createNodeDescriptor( + Project project, PsiElement element, HierarchyNodeDescriptor parent, boolean navigateToReference + ) { boolean root = (parent == null); return element instanceof JetElement - ? new KotlinCallHierarchyNodeDescriptor(project, parent, element, root, false) - : new CallHierarchyNodeDescriptor(project, parent, element, root, false); + ? new KotlinCallHierarchyNodeDescriptor(project, parent, element, root, navigateToReference) + : new CallHierarchyNodeDescriptor(project, parent, element, root, navigateToReference); } protected static PsiElement getTargetElement(HierarchyNodeDescriptor descriptor) { @@ -102,34 +104,40 @@ public abstract class KotlinCallTreeStructure extends HierarchyTreeStructure { } protected Object[] collectNodeDescriptors( - HierarchyNodeDescriptor descriptor, List calleeElements, PsiClass basePsiClass + HierarchyNodeDescriptor descriptor, Map referencesToCalleeElements, PsiClass basePsiClass ) { HashMap declarationToDescriptorMap = new HashMap(); - for (PsiElement callee : calleeElements) { + for (Map.Entry refToCallee : referencesToCalleeElements.entrySet()) { + PsiReference ref = refToCallee.getKey(); + PsiElement callee = refToCallee.getValue(); + if (basePsiClass != null && !isInScope(basePsiClass, callee, scopeType)) continue; - addNodeDescriptorForElement(callee, declarationToDescriptorMap, descriptor); + addNodeDescriptorForElement(ref, callee, declarationToDescriptorMap, descriptor); } return declarationToDescriptorMap.values().toArray(new Object[declarationToDescriptorMap.size()]); } protected final void addNodeDescriptorForElement( + PsiReference reference, PsiElement element, Map declarationToDescriptorMap, HierarchyNodeDescriptor descriptor ) { HierarchyNodeDescriptor d = declarationToDescriptorMap.get(element); if (d == null) { - d = createNodeDescriptor(myProject, element, descriptor); + d = createNodeDescriptor(myProject, element, descriptor, true); declarationToDescriptorMap.put(element, d); } - else { - if (d instanceof CallHierarchyNodeDescriptor) { - ((CallHierarchyNodeDescriptor) d).incrementUsageCount(); - } - else if (d instanceof KotlinCallHierarchyNodeDescriptor) { - ((KotlinCallHierarchyNodeDescriptor) d).incrementUsageCount(); - } + else if (d instanceof CallHierarchyNodeDescriptor) { + ((CallHierarchyNodeDescriptor) d).incrementUsageCount(); + } + + if (d instanceof CallHierarchyNodeDescriptor) { + ((CallHierarchyNodeDescriptor) d).addReference(reference); + } + else if (d instanceof KotlinCallHierarchyNodeDescriptor) { + ((KotlinCallHierarchyNodeDescriptor) d).addReference(reference); } } diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java index 43af8124691..00651e3951c 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCalleeMethodsTreeStructure.java @@ -23,13 +23,16 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { private final CalleeMethodsTreeStructure javaTreeStructure; @@ -45,7 +48,7 @@ public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { this.javaTreeStructure = new CalleeMethodsTreeStructure(project, representativePsiMethod, scopeType); } - private static List getCalleeElements(@NotNull JetElement rootElement) { + private static Map getReferencesToCalleeElements(@NotNull JetElement rootElement) { List elementsToAnalyze = new ArrayList(); if (rootElement instanceof JetNamedFunction) { elementsToAnalyze.add(((JetNamedFunction) rootElement).getBodyExpression()); @@ -78,19 +81,19 @@ public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { } } - final ArrayList result = new ArrayList(); + final Map referencesToCalleeElements = new HashMap(); for (JetElement element : elementsToAnalyze) { element.accept( new CalleeReferenceVisitorBase(AnalyzerFacadeWithCache.getContextForElement(element), false) { @Override protected void processDeclaration(JetReferenceExpression reference, PsiElement declaration) { - result.add(declaration); + referencesToCalleeElements.put(reference.getReference(), declaration); } } ); } - return result; + return referencesToCalleeElements; } @NotNull @@ -126,7 +129,7 @@ public class KotlinCalleeMethodsTreeStructure extends KotlinCallTreeStructure { } private Object[] buildChildrenByKotlinTarget(HierarchyNodeDescriptor descriptor, JetElement targetElement) { - List calleeDescriptors = getCalleeElements(targetElement); - return collectNodeDescriptors(descriptor, calleeDescriptors, representativePsiClass); + Map referencesToCalleeElements = getReferencesToCalleeElements(targetElement); + return collectNodeDescriptors(descriptor, referencesToCalleeElements, representativePsiClass); } } diff --git a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java index d6a964bfa42..2edcfec82a2 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java @@ -66,7 +66,7 @@ public abstract class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStr BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement((JetElement) element); - final ArrayList result = new ArrayList(); + final Map referencesToElements = new HashMap(); codeBlockForLocalDeclaration.accept(new CalleeReferenceVisitorBase(bindingContext, true) { @Override protected void processDeclaration(JetReferenceExpression reference, PsiElement declaration) { @@ -80,11 +80,11 @@ public abstract class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStr } if (container != null) { - result.add(container); + referencesToElements.put(reference.getReference(), container); } } }); - return collectNodeDescriptors(descriptor, result, null); + return collectNodeDescriptors(descriptor, referencesToElements, null); } } @@ -230,7 +230,7 @@ public abstract class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStr } if (element != null) { - addNodeDescriptorForElement(element, methodToDescriptorMap, descriptor); + addNodeDescriptorForElement(ref, element, methodToDescriptorMap, descriptor); } return true;