From 3e6f879571d0efcf9b5e900cc1b817507f2b7b61 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 15 Jan 2014 16:18:40 +0400 Subject: [PATCH] Show call sites of overriden members in "Caller Hierarchy" #KT-4395 Fixed --- .../KotlinCallerMethodsTreeStructure.java | 48 ++++++++++++++----- .../javaMethod/JavaMethod_verification.xml | 10 ++-- .../calls/callers/javaMethod/main0.java | 18 +++++-- .../calls/callers/javaMethod/main1.kt | 6 +-- .../KotlinFunction_verification.xml | 20 ++++---- .../calls/callers/kotlinFunction/main0.kt | 24 ++++++---- .../calls/callers/kotlinFunction/main1.java | 4 +- .../KotlinProperty_verification.xml | 12 ++--- .../calls/callers/kotlinProperty/main0.kt | 31 +++++++----- .../calls/callers/kotlinProperty/main1.java | 4 +- 10 files changed, 113 insertions(+), 64 deletions(-) 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 604c1f3b234..2ad7f23aa61 100644 --- a/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java +++ b/idea/src/org/jetbrains/jet/plugin/hierarchy/calls/KotlinCallerMethodsTreeStructure.java @@ -29,9 +29,10 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.FilteringProcessor; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; +import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.asJava.LightClassUtil; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -40,8 +41,7 @@ import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; import org.jetbrains.jet.plugin.references.JetPsiReference; import org.jetbrains.jet.plugin.search.usagesSearch.UsagesSearchPackage; -import java.util.ArrayList; -import java.util.Map; +import java.util.*; public abstract class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStructure { private static class WithLocalRoot extends KotlinCallerMethodsTreeStructure { @@ -110,17 +110,18 @@ public abstract class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStr Object[] javaCallers = null; if (element instanceof PsiMethod) { javaCallers = javaTreeStructure.getChildElements(getJavaNodeDescriptor(descriptor)); - processPsiMethodCallers((PsiMethod) element, descriptor, methodToDescriptorMap, searchScope, true); + processPsiMethodCallers( + Collections.singleton((PsiMethod) element), descriptor, methodToDescriptorMap, searchScope, true + ); } if (element instanceof JetNamedFunction) { PsiMethod lightMethod = LightClassUtil.getLightClassMethod((JetNamedFunction) element); - processPsiMethodCallers(lightMethod, descriptor, methodToDescriptorMap, searchScope, false); + processPsiMethodCallers(Collections.singleton(lightMethod), descriptor, methodToDescriptorMap, searchScope, false); } if (element instanceof JetProperty) { LightClassUtil.PropertyAccessorsPsiMethods propertyMethods = LightClassUtil.getLightClassPropertyMethods((JetProperty) element); - processPsiMethodCallers(propertyMethods.getGetter(), descriptor, methodToDescriptorMap, searchScope, false); - processPsiMethodCallers(propertyMethods.getSetter(), descriptor, methodToDescriptorMap, searchScope, false); + processPsiMethodCallers(propertyMethods, descriptor, methodToDescriptorMap, searchScope, false); } if (element instanceof JetClassOrObject) { processJetClassOrObjectCallers((JetClassOrObject) element, descriptor, methodToDescriptorMap, searchScope); @@ -131,15 +132,40 @@ public abstract class KotlinCallerMethodsTreeStructure extends KotlinCallTreeStr } private void processPsiMethodCallers( - @Nullable PsiMethod lightMethod, + Iterable lightMethods, HierarchyNodeDescriptor descriptor, Map methodToDescriptorMap, SearchScope searchScope, boolean kotlinOnly ) { - if (lightMethod == null) return; - MethodReferencesSearch.search(lightMethod, searchScope, true) - .forEach(defaultQueryProcessor(descriptor, methodToDescriptorMap, kotlinOnly)); + Set methodsToFind = new HashSet(); + for (PsiMethod lightMethod : lightMethods) { + if (lightMethod == null) continue; + + PsiMethod[] superMethods = lightMethod.findDeepestSuperMethods(); + methodsToFind.add(lightMethod); + ContainerUtil.addAll(methodsToFind, superMethods); + } + + if (methodsToFind.isEmpty()) return; + + Set references = ContainerUtil.newTroveSet( + new TObjectHashingStrategy() { + @Override + public int computeHashCode(PsiReference object) { + return object.getElement().hashCode(); + } + + @Override + public boolean equals(PsiReference o1, PsiReference o2) { + return o1.getElement().equals(o2.getElement()); + } + } + ); + for (PsiMethod superMethod: methodsToFind) { + ContainerUtil.addAll(references, MethodReferencesSearch.search(superMethod, searchScope, true)); + } + ContainerUtil.process(references, defaultQueryProcessor(descriptor, methodToDescriptorMap, kotlinOnly)); } private void processJetClassOrObjectCallers( diff --git a/idea/testData/hierarchy/calls/callers/javaMethod/JavaMethod_verification.xml b/idea/testData/hierarchy/calls/callers/javaMethod/JavaMethod_verification.xml index 8992cec2e2e..52751e5f0e7 100644 --- a/idea/testData/hierarchy/calls/callers/javaMethod/JavaMethod_verification.xml +++ b/idea/testData/hierarchy/calls/callers/javaMethod/JavaMethod_verification.xml @@ -1,7 +1,7 @@ - - - - - + + + + + diff --git a/idea/testData/hierarchy/calls/callers/javaMethod/main0.java b/idea/testData/hierarchy/calls/callers/javaMethod/main0.java index bd49d048794..ee378693e47 100644 --- a/idea/testData/hierarchy/calls/callers/javaMethod/main0.java +++ b/idea/testData/hierarchy/calls/callers/javaMethod/main0.java @@ -1,6 +1,13 @@ -class KA { - public final String name = "A" +class KBase { + public String foo(String s) { + return s; + } +} +class KA extends KBase { + public final String name = "A"; + + @Override public final String foo(String s) { return "A " + s; } @@ -8,16 +15,17 @@ class KA { class KClient { { + new KBase().foo(""); new KA().foo(""); } - public static final String a = new KA().foo(""); + public static final String a = new KBase().foo("") + new KA().foo(""); public final String getBar() { - return new KA().foo(""); + return new KBase().foo("") + new KA().foo(""); } public final String bar() { - return new KA().foo(""); + return new KBase().foo("") + new KA().foo(""); } } \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/javaMethod/main1.kt b/idea/testData/hierarchy/calls/callers/javaMethod/main1.kt index 25eadaa3b58..74c4ae46041 100644 --- a/idea/testData/hierarchy/calls/callers/javaMethod/main1.kt +++ b/idea/testData/hierarchy/calls/callers/javaMethod/main1.kt @@ -1,7 +1,7 @@ open class JA() { - public var name: String = KA().foo("") + public var name: String = KBase().foo("") + KA().foo("") public open fun foo(): String { - return KA().foo("") + return KBase().foo("") + KA().foo("") } -} +} \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml index 53c5b586e54..6f0dd05218f 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml +++ b/idea/testData/hierarchy/calls/callers/kotlinFunction/KotlinFunction_verification.xml @@ -1,12 +1,12 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/idea/testData/hierarchy/calls/callers/kotlinFunction/main0.kt b/idea/testData/hierarchy/calls/callers/kotlinFunction/main0.kt index 3baf3fc9af6..114dd8449f8 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinFunction/main0.kt +++ b/idea/testData/hierarchy/calls/callers/kotlinFunction/main0.kt @@ -1,31 +1,37 @@ -class KA { - val name = "A" - fun foo(s: String): String = "A: $s" +open class KBase { + open fun foo(s: String): String = s } -fun packageFun(s: String): String = KA().foo(s) +class KA: KBase() { + val name = "A" + override fun foo(s: String): String = "A: $s" +} -val packageVal = KA().foo("") +fun packageFun(s: String): String = KBase().foo("") + KA().foo(s) + +val packageVal = KBase().foo("") + KA().foo("") class KClient { { KA().foo("") + KBase().foo("") } class object { - val a = KA().foo("") + val a = KBase().foo("") + KA().foo("") } val bar: String - get() = KA().foo("") + get() = KBase().foo("") + KA().foo("") fun bar() { - fun localFun() = KA().foo("") + fun localFun() = KBase().foo("") + KA().foo("") KA().foo("") + KBase().foo("") } } object KClientObj { - val a = KA().foo("") + val a = KBase().foo("") + KA().foo("") } \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/kotlinFunction/main1.java b/idea/testData/hierarchy/calls/callers/kotlinFunction/main1.java index 5f5d2903bea..ec8d3fdb5a2 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinFunction/main1.java +++ b/idea/testData/hierarchy/calls/callers/kotlinFunction/main1.java @@ -1,7 +1,7 @@ class JA { - public String name = new KA().foo(""); + public String name = new KBase().foo("") + new KA().foo(""); public String foo() { - return new KA().foo(""); + return new KBase().foo("") + new KA().foo(""); } } \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml b/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml index 40a8a3154d7..79eab2ec097 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml +++ b/idea/testData/hierarchy/calls/callers/kotlinProperty/KotlinProperty_verification.xml @@ -1,12 +1,12 @@ + + - - + + - - - - + + diff --git a/idea/testData/hierarchy/calls/callers/kotlinProperty/main0.kt b/idea/testData/hierarchy/calls/callers/kotlinProperty/main0.kt index 06941927ef7..4bc20bd0f5e 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinProperty/main0.kt +++ b/idea/testData/hierarchy/calls/callers/kotlinProperty/main0.kt @@ -1,35 +1,44 @@ -class KA { - var name = "A" +open class KBase { + open var name = "" +} + +class KA: KBase() { + override var name = "A" fun foo(s: String): String = "A: $s" } -fun packageFun(s: String): String = KA().name +fun packageFun(s: String): String = KBase().name + KA().name -val packageVal = KA().name +val packageVal = KBase().name + KA().name class KClient { { + KBase().name = "" KA().name = "" } class object { - val a = KA().name + val a = KBase().name + KA().name } - val bar: String - get() = KA().name - set(value: String) {KA().name = value} + var bar: String + get() = KBase().name + KA().name + set(value: String) { + KBase().name = value + KA().name = value + } fun bar() { - fun localFun() = KA().name + fun localFun() = KBase().name + KA().name - val s = KA().name + val s = KBase().name + KA().name } } object KClientObj { - val a = KA().name + val a = KBase().name + KA().name { + KBase().name = "" KA().name = "" } } \ No newline at end of file diff --git a/idea/testData/hierarchy/calls/callers/kotlinProperty/main1.java b/idea/testData/hierarchy/calls/callers/kotlinProperty/main1.java index aa0728f4147..c8bd33d60b9 100644 --- a/idea/testData/hierarchy/calls/callers/kotlinProperty/main1.java +++ b/idea/testData/hierarchy/calls/callers/kotlinProperty/main1.java @@ -1,7 +1,7 @@ class JA { - public String name = new KA().getName(); + public String name = new KBase().getName() + new KA().getName(); public String getName() { - return new KA().getName(); + return new KBase().getName() + new KA().getName(); } } \ No newline at end of file