diff --git a/annotations/com/intellij/usages/impl/annotations.xml b/annotations/com/intellij/usages/impl/annotations.xml new file mode 100644 index 00000000000..019280d6e1b --- /dev/null +++ b/annotations/com/intellij/usages/impl/annotations.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 8012da58c76..1fd9b6e8928 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -164,6 +164,7 @@ + ())?.let { container -> + PsiNamedElementUsageGroupBase(container) + } + } + } + + override fun getUsageGroupingRule(project: Project): UsageGroupingRule = KotlinDeclarationGroupingRule() +} + + diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.0.kt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.0.kt new file mode 100644 index 00000000000..062cb4d6101 --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.0.kt @@ -0,0 +1,14 @@ +// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetClass +// GROUPING_RULES: org.jetbrains.jet.plugin.findUsages.KotlinDeclarationGroupRuleProvider$KotlinDeclarationGroupingRule +// OPTIONS: usages, constructorUsages +package server + +open class Server { + class object { + val NAME = "Server" + } + + open fun work() { + println("Server") + } +} \ No newline at end of file diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.1.kt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.1.kt new file mode 100644 index 00000000000..de27808debe --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.1.kt @@ -0,0 +1,42 @@ +package client + +import server.Server + +class Client(name: String = Server.NAME): Server() { + var nextServer: Server? = new Server() + val name = Server.NAME + + fun foo(s: Server) { + val server: Server = s + println("Server: $server") + } + + fun getNextServer(): Server? { + return nextServer + } + + override fun work() { + super.work() + println("Client") + } + + class object: Server() { + + } +} + +object ClientObject: Server() { + +} + +fun Client.bar(s: Server = Server.NAME) { + foo(s) +} + +fun Client.hasNextServer(): Boolean { + return getNextServer() != null +} + +fun Any.asServer(): Server? { + return if (this is Server) this as Server else null +} \ No newline at end of file diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.results.txt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.results.txt new file mode 100644 index 00000000000..ed5f88380fa --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.results.txt @@ -0,0 +1,16 @@ +Class/object property type (Client) (6: 21) var nextServer: Server? = new Server() +Function return types (Client) (14: 26) fun getNextServer(): Server? { +Function return types (asServer) (40: 21) fun Any.asServer(): Server? { +Local variable declaration (Client) (10: 21) val server: Server = s +Nested class/object (Client) (5: 29) class Client(name: String = Server.NAME): Server() { +Nested class/object (Client) (7: 16) val name = Server.NAME +Nested class/object (bar) (32: 28) fun Client.bar(s: Server = Server.NAME) { +Parameter type (Client) (9: 16) fun foo(s: Server) { +Parameter type (bar) (32: 19) fun Client.bar(s: Server = Server.NAME) { +Super type qualifier (Client) (19: 15) super.work() +Supertype (Client) (23: 19) class object: Server() { +Supertype (Client) (5: 43) class Client(name: String = Server.NAME): Server() { +Supertype (ClientObject) (28: 22) object ClientObject: Server() { +Target type of 'is' operation (asServer) (41: 24) return if (this is Server) this as Server else null +Usage in cast target type (asServer) (41: 40) return if (this is Server) this as Server else null +Usage in import (3: 15) import server.Server diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.0.kt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.0.kt new file mode 100644 index 00000000000..a6debcf3a0c --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.0.kt @@ -0,0 +1,13 @@ +// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetNamedFunction +// GROUPING_RULES: org.jetbrains.jet.plugin.findUsages.KotlinDeclarationGroupRuleProvider$KotlinDeclarationGroupingRule +// OPTIONS: usages +package server; + +public open class Server() { + open fun processRequest() = "foo" +} + +public class ServerEx(): Server() { + override fun processRequest() = "foofoo" +} + diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.1.kt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.1.kt new file mode 100644 index 00000000000..17b7c749d69 --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.1.kt @@ -0,0 +1,8 @@ +import server.*; + +class Client { + public fun foo() { + Server().processRequest() + ServerEx().processRequest() + } +} diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.results.txt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.results.txt new file mode 100644 index 00000000000..2a13adaa78c --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.results.txt @@ -0,0 +1,2 @@ +Function call (Client) (5: 18) Server().processRequest() +Function call (Client) (6: 20) ServerEx().processRequest() diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.0.kt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.0.kt new file mode 100644 index 00000000000..f16598e9708 --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.0.kt @@ -0,0 +1,20 @@ +// PSI_ELEMENT: org.jetbrains.jet.lang.psi.JetProperty +// GROUPING_RULES: org.jetbrains.jet.plugin.findUsages.KotlinDeclarationGroupRuleProvider$KotlinDeclarationGroupingRule +// OPTIONS: usages +package server; + +open class A { + open var foo: T +} + +open class B: A() { + open var foo: String + get() { + println("get") + return super.foo + } + set(value: String) { + println("set:" + value) + super.foo = value + } +} diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.1.kt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.1.kt new file mode 100644 index 00000000000..e468d09d3f0 --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.1.kt @@ -0,0 +1,13 @@ +import server.*; + +class Client { + public fun foo() { + val a = A() + a.foo = "a" + println("a.foo = ${a.foo}") + + val b = B() + b.foo = "b" + println("b.foo = ${b.foo}") + } +} diff --git a/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.results.txt b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.results.txt new file mode 100644 index 00000000000..b5600581b1e --- /dev/null +++ b/idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.results.txt @@ -0,0 +1,6 @@ +Value read (B) (14: 29) return super.foo +Value read (Client) (11: 30) println("b.foo = ${b.foo}") +Value read (Client) (7: 30) println("a.foo = ${a.foo}") +Value write (B) (18: 22) super.foo = value +Value write (Client) (10: 11) b.foo = "b" +Value write (Client) (6: 11) a.foo = "a" diff --git a/idea/tests/org/jetbrains/jet/findUsages/AbstractJetFindUsagesTest.java b/idea/tests/org/jetbrains/jet/findUsages/AbstractJetFindUsagesTest.java index 35f40e5a504..9c9e9fdd1cc 100644 --- a/idea/tests/org/jetbrains/jet/findUsages/AbstractJetFindUsagesTest.java +++ b/idea/tests/org/jetbrains/jet/findUsages/AbstractJetFindUsagesTest.java @@ -33,13 +33,17 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.usageView.UsageInfo; +import com.intellij.usages.UsageGroup; import com.intellij.usages.UsageInfo2UsageAdapter; import com.intellij.usages.UsageViewPresentation; import com.intellij.usages.impl.rules.UsageType; import com.intellij.usages.impl.rules.UsageTypeProvider; import com.intellij.usages.rules.UsageFilteringRule; +import com.intellij.usages.rules.UsageGroupingRule; import com.intellij.util.ArrayUtil; import com.intellij.util.CommonProcessors; +import kotlin.Function1; +import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.InTextDirectivesUtils; @@ -303,19 +307,38 @@ public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureT FindUsagesOptions options = parser != null ? parser.parse(mainFileText, getProject()) : null; Collection usageInfos = findUsages(caretElement, options); - Collection filteredUsages = getUsageAdapters( - getTestFilteringRules(mainFileText, "// FILTERING_RULES: "), - usageInfos); + Collection filteringRules = instantiateClasses(mainFileText, "// FILTERING_RULES: "); + final Collection groupingRules = instantiateClasses(mainFileText, "// GROUPING_RULES: "); + + Collection filteredUsages = getUsageAdapters(filteringRules, usageInfos); Function convertToString = new Function() { @Override - public String apply(@Nullable UsageInfo2UsageAdapter usageAdapter) { + public String apply(@Nullable final UsageInfo2UsageAdapter usageAdapter) { assert usageAdapter != null; + String groupAsString = Joiner.on(", ").join( + KotlinPackage.map( + groupingRules, + new Function1() { + @Override + public String invoke(UsageGroupingRule rule) { + UsageGroup group = rule.groupUsage(usageAdapter); + return group != null ? group.getText(null) : ""; + } + } + ) + ); + if (!groupAsString.isEmpty()) { + groupAsString = "(" + groupAsString + ") "; + } + UsageType usageType = getUsageType(usageAdapter.getElement()); String usageTypeAsString = usageType == null ? "null" : usageType.toString(USAGE_VIEW_PRESENTATION); - return usageTypeAsString + " " + Joiner.on("").join(Arrays.asList(usageAdapter.getPresentation().getText())); + return usageTypeAsString + " " + + groupAsString + + Joiner.on("").join(Arrays.asList(usageAdapter.getPresentation().getText())); } }; @@ -386,14 +409,14 @@ public abstract class AbstractJetFindUsagesTest extends LightCodeInsightFixtureT return UsageType.UNCLASSIFIED; } - private static Collection getTestFilteringRules(String mainFileText, String directive) + private static Collection instantiateClasses(String mainFileText, String directive) throws ClassNotFoundException, InstantiationException, IllegalAccessException { List filteringRuleClassNames = InTextDirectivesUtils.findLinesWithPrefixesRemoved(mainFileText, directive); - Collection filters = new ArrayList(); + Collection filters = new ArrayList(); for (String filteringRuleClassName : filteringRuleClassNames) { //noinspection unchecked - Class klass = (Class) Class.forName(filteringRuleClassName); + Class klass = (Class) Class.forName(filteringRuleClassName); filters.add(klass.newInstance()); } diff --git a/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTestGenerated.java b/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTestGenerated.java index b69010d1800..86dd5c2ae31 100644 --- a/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/findUsages/JetFindUsagesTestGenerated.java @@ -16,24 +16,21 @@ package org.jetbrains.jet.findUsages; -import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; - -import java.io.File; -import java.util.regex.Pattern; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.InnerTestClasses; import org.jetbrains.jet.test.TestMetadata; -import org.jetbrains.jet.findUsages.AbstractJetFindUsagesTest; +import java.io.File; +import java.util.regex.Pattern; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @InnerTestClasses({JetFindUsagesTestGenerated.Kotlin.class, JetFindUsagesTestGenerated.Java.class}) public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest { @TestMetadata("idea/testData/findUsages/kotlin") - @InnerTestClasses({Kotlin.FindClassUsages.class, Kotlin.FindFunctionUsages.class, Kotlin.FindObjectUsages.class, Kotlin.FindParameterUsages.class, Kotlin.FindPropertyUsages.class, Kotlin.FindTypeParameterUsages.class, Kotlin.FindWithFilteringImports.class, Kotlin.UnresolvedAnnotation.class}) + @InnerTestClasses({Kotlin.FindClassUsages.class, Kotlin.FindFunctionUsages.class, Kotlin.FindObjectUsages.class, Kotlin.FindParameterUsages.class, Kotlin.FindPropertyUsages.class, Kotlin.FindTypeParameterUsages.class, Kotlin.FindWithFilteringImports.class, Kotlin.FindWithStructuralGrouping.class, Kotlin.UnresolvedAnnotation.class}) public static class Kotlin extends AbstractJetFindUsagesTest { public void testAllFilesPresentInKotlin() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/findUsages/kotlin"), Pattern.compile("^(.+)\\.0\\.kt$"), true); @@ -540,6 +537,29 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest { } + @TestMetadata("idea/testData/findUsages/kotlin/findWithStructuralGrouping") + public static class FindWithStructuralGrouping extends AbstractJetFindUsagesTest { + public void testAllFilesPresentInFindWithStructuralGrouping() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/findUsages/kotlin/findWithStructuralGrouping"), Pattern.compile("^(.+)\\.0\\.kt$"), true); + } + + @TestMetadata("kotlinClassAllUsages.0.kt") + public void testKotlinClassAllUsages() throws Exception { + doTest("idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinClassAllUsages.0.kt"); + } + + @TestMetadata("kotlinMethodUsages.0.kt") + public void testKotlinMethodUsages() throws Exception { + doTest("idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinMethodUsages.0.kt"); + } + + @TestMetadata("kotlinPropertyUsages.0.kt") + public void testKotlinPropertyUsages() throws Exception { + doTest("idea/testData/findUsages/kotlin/findWithStructuralGrouping/kotlinPropertyUsages.0.kt"); + } + + } + @TestMetadata("idea/testData/findUsages/kotlin/unresolvedAnnotation") public static class UnresolvedAnnotation extends AbstractJetFindUsagesTest { public void testAllFilesPresentInUnresolvedAnnotation() throws Exception { @@ -563,6 +583,7 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest { suite.addTestSuite(FindPropertyUsages.class); suite.addTestSuite(FindTypeParameterUsages.class); suite.addTestSuite(FindWithFilteringImports.class); + suite.addTestSuite(FindWithStructuralGrouping.class); suite.addTestSuite(UnresolvedAnnotation.class); return suite; }