Add support of extension search

This commit is contained in:
Alexey Sedunov
2013-08-08 17:02:41 +04:00
parent 1881d17b67
commit 76c81aa3f0
8 changed files with 192 additions and 244 deletions
@@ -464,7 +464,7 @@ public class GenerateTests {
"idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides", "Server.kt", "testFindMethodJavaUsages"
),
testModelWithFileName(
"idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages", "Server.kt", "testFindMethodKotlinUsages"
"idea/testData/findUsages/findMethodUsages/kotlinExtensionAndOverloadUsages", "Server.kt", "testFindMethodKotlinUsages"
),
testModelWithFileName(
"idea/testData/findUsages/findPropertyUsages/javaPropertyUsages", "Server.kt", "testFindPropertyJavaUsages"
@@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.plugin.findUsages.KotlinFindUsagesHandlerFactory;
import org.jetbrains.jet.plugin.findUsages.dialogs.KotlinFindMethodUsagesDialog;
import org.jetbrains.jet.plugin.findUsages.options.KotlinMethodFindUsagesOptions;
import org.jetbrains.jet.plugin.search.KotlinExtensionSearch;
import java.util.Collection;
@@ -123,12 +124,22 @@ public class KotlinFindFunctionUsagesHandler extends KotlinFindUsagesHandler<Jet
);
}
if (kotlinOptions.isIncludeOverloadUsages) {
String name = ((PsiNamedElement)element).getName();
if (name == null) return true;
for (PsiReference ref : KotlinExtensionSearch.search(lightMethod, searchScope).findAll()) {
processUsage(processor, ref, kotlinOptions);
}
}
return true;
}
@Override
protected boolean isSearchForTextOccurencesAvailable(@NotNull PsiElement psiElement, boolean isSingleFile) {
return psiElement instanceof JetNamedFunction || psiElement instanceof PsiMethod;
if (isSingleFile) return false;
return psiElement instanceof JetNamedFunction;
}
@NotNull
@@ -0,0 +1,151 @@
package org.jetbrains.jet.plugin.search;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.psi.*;
import com.intellij.psi.search.*;
import com.intellij.psi.search.searches.ReferenceDescriptor;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.JetClsMethod;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
import java.util.List;
public class KotlinExtensionSearch extends QueryFactory<PsiReference, KotlinExtensionSearch.SearchParameters> {
public static final KotlinExtensionSearch INSTANCE = new KotlinExtensionSearch();
public static class SearchParameters {
private final PsiMethod method;
private final SearchScope searchScope;
private final SearchRequestCollector optimizer = new SearchRequestCollector(new SearchSession());
public SearchParameters(@NotNull PsiMethod method, @NotNull SearchScope searchScope) {
this.searchScope = searchScope;
this.method = method;
}
public PsiMethod getMethod() {
return method;
}
public SearchScope getSearchScope() {
return searchScope;
}
public SearchRequestCollector getOptimizer() {
return optimizer;
}
}
private static class ExtensionTextOccurenceProcessor extends RequestResultProcessor {
private final SearchParameters parameters;
private ExtensionTextOccurenceProcessor(SearchParameters parameters, @NotNull Object... equality) {
super(equality);
this.parameters = parameters;
}
private void processElement(
@NotNull PsiReference ref,
@Nullable PsiElement refTarget,
@NotNull Processor<PsiReference> consumer
) {
if (!(refTarget instanceof JetSimpleNameExpression)) return;
BindingContext bindingContext =
AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) refTarget.getContainingFile()).getBindingContext();
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) refTarget);
if (!(descriptor instanceof FunctionDescriptor)) return;
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
ReceiverParameterDescriptor receiverParameterDescriptor = functionDescriptor.getReceiverParameter();
if (receiverParameterDescriptor == null) return;
JetType receiverType = receiverParameterDescriptor.getType();
ClassifierDescriptor receiverDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
if (!(receiverDescriptor instanceof ClassDescriptor)) return;
PsiElement originalMethod = parameters.getMethod();
if (originalMethod instanceof JetClsMethod) {
originalMethod = ((JetClsMethod) originalMethod).getOrigin();
}
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, originalMethod);
if (declarationDescriptor == null) return;
DeclarationDescriptor containingDescriptor = declarationDescriptor.getContainingDeclaration();
if (!(containingDescriptor instanceof ClassDescriptor)) return;
if (DescriptorUtils.isSubclass((ClassDescriptor) containingDescriptor, (ClassDescriptor) receiverDescriptor)) {
consumer.process(ref);
}
}
@Override
public boolean processTextOccurrence(
@NotNull PsiElement element,
int offsetInElement,
@NotNull Processor<PsiReference> consumer
) {
List<PsiReference> references = PsiReferenceService.getService().getReferences(
element, PsiReferenceService.Hints.NO_HINTS
);
for (PsiReference ref : references) {
if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
processElement(ref, ref.getElement(), consumer);
}
}
return true;
}
}
private KotlinExtensionSearch() {
registerExecutor(
new QueryExecutorBase<PsiReference, SearchParameters>() {
@Override
public void processQuery(@NotNull final SearchParameters p, @NotNull Processor<PsiReference> consumer) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
p.getOptimizer().searchWord(
p.getMethod().getName(),
p.getSearchScope(),
UsageSearchContext.IN_CODE,
true,
new ExtensionTextOccurenceProcessor(p)
);
}
});
}
}
);
}
public static Query<PsiReference> search(@NotNull PsiMethod method, @NotNull SearchScope scope) {
return search(new SearchParameters(method, scope));
}
public static Query<PsiReference> search(SearchParameters parameters) {
Query<PsiReference> result = INSTANCE.createQuery(parameters);
SearchRequestCollector requests = parameters.getOptimizer();
return uniqueResults(new MergeQuery<PsiReference>(result, new SearchRequestQuery(parameters.getMethod().getProject(), requests)));
}
private static UniqueResultsQuery<PsiReference, ReferenceDescriptor> uniqueResults(@NotNull Query<PsiReference> composite) {
return new UniqueResultsQuery<PsiReference, ReferenceDescriptor>(
composite, ContainerUtil.<ReferenceDescriptor>canonicalStrategy(), ReferenceDescriptor.MAPPER
);
}
}
@@ -4,7 +4,7 @@ open class B: A<String>() {
}
open fun baz(a: A<String>) {
a.foo("", 0)
foo("", 0)
}
open fun baz(a: A<Number>) {
@@ -1,5 +1,16 @@
// OPTIONS: overloadUsages
open class A<T> {
trait X<T> {
}
fun <T> X<T>.foo(a: Number, b: Number) {
println("$a$b")
}
fun bar(x: X<String>) {
x.foo(1, 2)
}
open class A<T>: X<T> {
open fun <caret>foo(t: T) {
println(t)
}
@@ -14,7 +25,11 @@ fun <T> A<T>.foo(t: T, x: String) {
println(x)
}
fun A<String>.foo(s: String, n: Number) {
fun bar(a: A<Number>) {
a.foo(1, "")
}
fun B.foo(s: String, n: Number) {
fun <T> A<T>.foo(t: T, x: String) {
foo(t)
println(x)
@@ -22,4 +37,8 @@ fun A<String>.foo(s: String, n: Number) {
foo(s)
println(n)
}
fun bar(b: B) {
b.foo("", 0)
}
@@ -0,0 +1,6 @@
Function call (10: 7) x.foo(1, 2)
Function call (11: 11) a.foo(0, "")
Function call (24: 5) foo(t)
Function call (29: 7) a.foo(1, "")
Function call (34: 9) foo(t)
Function call (3: 18) super<A>.foo(t)
@@ -1,4 +0,0 @@
Function call (13: 5) foo(t)
Function call (19: 9) foo(t)
Function call (23: 5) foo(s)
Function call (3: 18) super<A>.foo(t)
@@ -1,235 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@InnerTestClasses({JetFindUsagesTest.JavaClassUsages.class, JetFindUsagesTest.KotlinClassUsages1.class, JetFindUsagesTest.KotlinClassUsages2.class, JetFindUsagesTest.KotlinClassUsages3.class, JetFindUsagesTest.JavaObjectUsages.class, JetFindUsagesTest.KotlinObjectUsages.class, JetFindUsagesTest.JavaMethodUsages.class, JetFindUsagesTest.KotlinMethodUsages.class, JetFindUsagesTest.JavaAndKotlinOverrides.class, JetFindUsagesTest.KotlinOverloadUsages.class, JetFindUsagesTest.JavaPropertyUsages.class, JetFindUsagesTest.KotlinPropertyUsages.class, JetFindUsagesTest.FindWithFilteringImports.class, JetFindUsagesTest.UnresolvedAnnotation.class})
public class JetFindUsagesTest extends AbstractJetFindUsagesTest {
@TestMetadata("idea/testData/findUsages/findClassUsages/javaClassUsages")
public static class JavaClassUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindClassJavaUsages("idea/testData/findUsages/findClassUsages/javaClassUsages/Server.kt");
}
public void testAllFilesPresentInJavaClassUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findClassUsages/javaClassUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findClassUsages/kotlinClassUsages1")
public static class KotlinClassUsages1 extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindClassKotlinUsages("idea/testData/findUsages/findClassUsages/kotlinClassUsages1/Server.kt");
}
public void testAllFilesPresentInKotlinClassUsages1() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findClassUsages/kotlinClassUsages1"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findClassUsages/kotlinClassUsages2")
public static class KotlinClassUsages2 extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindClassKotlinUsages("idea/testData/findUsages/findClassUsages/kotlinClassUsages2/Server.kt");
}
public void testAllFilesPresentInKotlinClassUsages2() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findClassUsages/kotlinClassUsages2"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findClassUsages/kotlinClassUsages3")
public static class KotlinClassUsages3 extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindClassKotlinUsages("idea/testData/findUsages/findClassUsages/kotlinClassUsages3/Server.kt");
}
public void testAllFilesPresentInKotlinClassUsages3() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findClassUsages/kotlinClassUsages3"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findObjectUsages/javaObjectUsages")
public static class JavaObjectUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindObjectJavaUsages("idea/testData/findUsages/findObjectUsages/javaObjectUsages/Server.kt");
}
public void testAllFilesPresentInJavaObjectUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findObjectUsages/javaObjectUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findObjectUsages/kotlinObjectUsages")
public static class KotlinObjectUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindObjectKotlinUsages("idea/testData/findUsages/findObjectUsages/kotlinObjectUsages/Server.kt");
}
public void testAllFilesPresentInKotlinObjectUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findObjectUsages/kotlinObjectUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findMethodUsages/javaMethodUsages")
public static class JavaMethodUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindMethodJavaUsages("idea/testData/findUsages/findMethodUsages/javaMethodUsages/Server.kt");
}
public void testAllFilesPresentInJavaMethodUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findMethodUsages/javaMethodUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findMethodUsages/kotlinMethodUsages")
public static class KotlinMethodUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindMethodKotlinUsages("idea/testData/findUsages/findMethodUsages/kotlinMethodUsages/Server.kt");
}
public void testAllFilesPresentInKotlinMethodUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findMethodUsages/kotlinMethodUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides")
public static class JavaAndKotlinOverrides extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindMethodJavaUsages("idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides/Server.kt");
}
public void testAllFilesPresentInJavaAndKotlinOverrides() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findMethodUsages/javaAndKotlinOverrides"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages")
public static class KotlinOverloadUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindMethodKotlinUsages("idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages/Server.kt");
}
public void testAllFilesPresentInKotlinOverloadUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findMethodUsages/kotlinOverloadUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findPropertyUsages/javaPropertyUsages")
public static class JavaPropertyUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindPropertyJavaUsages("idea/testData/findUsages/findPropertyUsages/javaPropertyUsages/Server.kt");
}
public void testAllFilesPresentInJavaPropertyUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findPropertyUsages/javaPropertyUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findPropertyUsages/kotlinPropertyUsages")
public static class KotlinPropertyUsages extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindPropertyKotlinUsages("idea/testData/findUsages/findPropertyUsages/kotlinPropertyUsages/Server.kt");
}
public void testAllFilesPresentInKotlinPropertyUsages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findPropertyUsages/kotlinPropertyUsages"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/findWithFilteringImports")
public static class FindWithFilteringImports extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindWithFilteringImports("idea/testData/findUsages/findWithFilteringImports/Server.kt");
}
public void testAllFilesPresentInFindWithFilteringImports() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/findWithFilteringImports"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
@TestMetadata("idea/testData/findUsages/unresolvedAnnotation")
public static class UnresolvedAnnotation extends AbstractJetFindUsagesTest {
@TestMetadata("Server.kt")
public void test() throws Exception {
testFindUsagesUnresolvedAnnotation("idea/testData/findUsages/unresolvedAnnotation/Server.kt");
}
public void testAllFilesPresentInUnresolvedAnnotation() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/findUsages/unresolvedAnnotation"), Pattern.compile("^(.*)Server.kt$"), true);
}
}
public static Test suite() {
TestSuite suite = new TestSuite("JetFindUsagesTest");
suite.addTestSuite(JavaClassUsages.class);
suite.addTestSuite(KotlinClassUsages1.class);
suite.addTestSuite(KotlinClassUsages2.class);
suite.addTestSuite(KotlinClassUsages3.class);
suite.addTestSuite(JavaObjectUsages.class);
suite.addTestSuite(KotlinObjectUsages.class);
suite.addTestSuite(JavaMethodUsages.class);
suite.addTestSuite(KotlinMethodUsages.class);
suite.addTestSuite(JavaAndKotlinOverrides.class);
suite.addTestSuite(KotlinOverloadUsages.class);
suite.addTestSuite(JavaPropertyUsages.class);
suite.addTestSuite(KotlinPropertyUsages.class);
suite.addTestSuite(FindWithFilteringImports.class);
suite.addTestSuite(UnresolvedAnnotation.class);
return suite;
}
}