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;
}