mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
functional expressions: implementations view
This commit is contained in:
+12
-1
@@ -18,11 +18,13 @@ package com.intellij.codeInsight.navigation;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFunctionalExpression;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.DefinitionsScopedSearch;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -34,7 +36,16 @@ public class ClassImplementationsSearch implements QueryExecutor<PsiElement, Def
|
||||
return !(sourceElement instanceof PsiClass) || processImplementations((PsiClass)sourceElement, consumer, queryParameters.getScope());
|
||||
}
|
||||
|
||||
public static boolean processImplementations(final PsiClass psiClass, final Processor<? super PsiClass> processor, SearchScope scope) {
|
||||
public static boolean processImplementations(final PsiClass psiClass, final Processor<PsiElement> processor, SearchScope scope) {
|
||||
if (!FunctionalExpressionSearch.search(psiClass, scope).forEach(new Processor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean process(PsiFunctionalExpression expression) {
|
||||
return processor.process(expression);
|
||||
}
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces");
|
||||
return ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(new PsiElementProcessor<PsiClass>() {
|
||||
public boolean execute(@NotNull PsiClass element) {
|
||||
|
||||
+22
-4
@@ -16,12 +16,14 @@
|
||||
package com.intellij.codeInsight.navigation;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFunctionalExpression;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.DefinitionsScopedSearch;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -29,21 +31,37 @@ import java.util.ArrayList;
|
||||
|
||||
public class MethodImplementationsSearch implements QueryExecutor<PsiElement, DefinitionsScopedSearch.SearchParameters> {
|
||||
@Override
|
||||
public boolean execute(@NotNull DefinitionsScopedSearch.SearchParameters queryParameters, @NotNull Processor<PsiElement> consumer) {
|
||||
public boolean execute(final @NotNull DefinitionsScopedSearch.SearchParameters queryParameters, final @NotNull Processor<PsiElement> consumer) {
|
||||
final PsiElement sourceElement = queryParameters.getElement();
|
||||
if (sourceElement instanceof PsiMethod) {
|
||||
PsiMethod[] implementations = getMethodImplementations((PsiMethod)sourceElement, queryParameters.getScope());
|
||||
return ContainerUtil.process(implementations, consumer);
|
||||
return processImplementations((PsiMethod)sourceElement, consumer, queryParameters.getScope());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean processImplementations(final PsiMethod psiMethod, final Processor<PsiElement> consumer,
|
||||
final SearchScope searchScope) {
|
||||
if (!FunctionalExpressionSearch.search(psiMethod, searchScope).forEach(new Processor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean process(PsiFunctionalExpression expression) {
|
||||
return consumer.process(expression);
|
||||
}
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
final ArrayList<PsiMethod> methods = new ArrayList<PsiMethod>();
|
||||
getOverridingMethods(psiMethod, methods, searchScope);
|
||||
return ContainerUtil.process(methods, consumer);
|
||||
}
|
||||
|
||||
public static void getOverridingMethods(PsiMethod method, ArrayList<PsiMethod> list, SearchScope scope) {
|
||||
for (PsiMethod psiMethod : OverridingMethodsSearch.search(method, scope, true)) {
|
||||
list.add(psiMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@Deprecated
|
||||
public static PsiMethod[] getMethodImplementations(final PsiMethod method, SearchScope scope) {
|
||||
ArrayList<PsiMethod> result = new ArrayList<PsiMethod>();
|
||||
|
||||
|
||||
+6
-1
@@ -47,7 +47,12 @@ public class JavaFunctionalExpressionSearcher implements QueryExecutor<PsiFuncti
|
||||
}) || !PsiUtil.isLanguageLevel8OrHigher(aClass)) {
|
||||
return true;
|
||||
}
|
||||
return collectFunctionalExpressions(aClass, queryParameters.getEffectiveSearchScope(), consumer);
|
||||
return collectFunctionalExpressions(aClass, ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
@Override
|
||||
public SearchScope compute() {
|
||||
return queryParameters.getEffectiveSearchScope();
|
||||
}
|
||||
}), consumer);
|
||||
}
|
||||
|
||||
public static boolean collectFunctionalExpressions(final PsiClass aClass,
|
||||
|
||||
+88
-5
@@ -2,12 +2,14 @@ package com.intellij.codeInsight.daemon;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.codeInsight.hint.ImplementationViewComponent;
|
||||
import com.intellij.codeInsight.navigation.ClassImplementationsSearch;
|
||||
import com.intellij.codeInsight.navigation.MethodImplementationsSearch;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.*;
|
||||
@@ -80,6 +82,20 @@ public class ImplementationsViewTest extends LightCodeInsightFixtureTestCase {
|
||||
" }", newText);
|
||||
}
|
||||
|
||||
private static Collection<PsiElement> getClassImplementations(final PsiClass psiClass) {
|
||||
CommonProcessors.CollectProcessor<PsiElement> processor = new CommonProcessors.CollectProcessor<PsiElement>();
|
||||
ClassImplementationsSearch.processImplementations(psiClass, processor, psiClass.getUseScope());
|
||||
|
||||
return processor.getResults();
|
||||
}
|
||||
|
||||
private static Collection<PsiElement> getMethodImplementations(final PsiMethod psiMethod) {
|
||||
CommonProcessors.CollectProcessor<PsiElement> processor = new CommonProcessors.CollectProcessor<PsiElement>();
|
||||
MethodImplementationsSearch.processImplementations( psiMethod, processor, psiMethod.getUseScope());
|
||||
|
||||
return processor.getResults();
|
||||
}
|
||||
|
||||
public void testInnerClasses() {
|
||||
myFixture.configureByText("a.java", "abstract class AF<caret>oo{\n" +
|
||||
" abstract boolean aaa();\n" +
|
||||
@@ -107,8 +123,8 @@ public class ImplementationsViewTest extends LightCodeInsightFixtureTestCase {
|
||||
(PsiClass)TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.getInstance().getAllAccepted());
|
||||
|
||||
assert psiClass != null;
|
||||
final Collection<PsiClass> classes = ClassInheritorsSearch.search(psiClass).findAll();
|
||||
List<PsiClass> all = new ArrayList<PsiClass>();
|
||||
final Collection<PsiElement> classes = getClassImplementations(psiClass);
|
||||
List<PsiElement> all = new ArrayList<PsiElement>();
|
||||
all.add(psiClass);
|
||||
all.addAll(classes);
|
||||
final ImplementationViewComponent component =
|
||||
@@ -126,6 +142,70 @@ public class ImplementationsViewTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testFunctionalInterface() {
|
||||
myFixture.configureByText("a.java", "interface AF<caret>oo{\n" +
|
||||
" boolean aaa();\n" +
|
||||
"}\n" +
|
||||
"class AFooImpl {\n" +
|
||||
" {\n" +
|
||||
" AFoo a = () -> {return false;};\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
PsiClass psiClass =
|
||||
(PsiClass)TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.getInstance().getAllAccepted());
|
||||
|
||||
assert psiClass != null;
|
||||
final Collection<PsiElement> classes = getClassImplementations(psiClass);
|
||||
List<PsiElement> all = new ArrayList<PsiElement>();
|
||||
all.add(psiClass);
|
||||
all.addAll(classes);
|
||||
final ImplementationViewComponent component = new ImplementationViewComponent(all.toArray(new PsiElement[all.size()]), 0);
|
||||
assertContent(component, new String[]{"a.java (AFoo)", "a.java"});
|
||||
}
|
||||
|
||||
public void testInterfaceMethodOfFunctionalInterface() {
|
||||
myFixture.configureByText("a.java", "interface AFoo{\n" +
|
||||
" boolean a<caret>aa();\n" +
|
||||
"}\n" +
|
||||
"class AFooImpl {\n" +
|
||||
" {\n" +
|
||||
" AFoo a = () -> {return false;};\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
PsiMethod psiMethod =
|
||||
(PsiMethod)TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.getInstance().getAllAccepted());
|
||||
|
||||
assert psiMethod != null;
|
||||
final Collection<PsiElement> methods = getMethodImplementations(psiMethod);
|
||||
List<PsiElement> all = new ArrayList<PsiElement>();
|
||||
all.add(psiMethod);
|
||||
all.addAll(methods);
|
||||
final ImplementationViewComponent component = new ImplementationViewComponent(all.toArray(new PsiElement[all.size()]), 0);
|
||||
assertContent(component, new String[]{"a.java (AFoo)", "a.java"});
|
||||
}
|
||||
|
||||
public void testDefaultMethodOfFunctionalInterface() {
|
||||
myFixture.configureByText("a.java", "interface AFoo{\n" +
|
||||
" default boolean a<caret>aa(){}\n" +
|
||||
" boolean bbb();" +
|
||||
"}\n" +
|
||||
"class AFooImpl {\n" +
|
||||
" {\n" +
|
||||
" AFoo a = () -> {return false;};\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
PsiMethod psiMethod =
|
||||
(PsiMethod)TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.getInstance().getAllAccepted());
|
||||
|
||||
assert psiMethod != null;
|
||||
final Collection<PsiElement> methods = getMethodImplementations(psiMethod);
|
||||
List<PsiElement> all = new ArrayList<PsiElement>();
|
||||
all.add(psiMethod);
|
||||
all.addAll(methods);
|
||||
final ImplementationViewComponent component = new ImplementationViewComponent(all.toArray(new PsiElement[all.size()]), 0);
|
||||
assertContent(component, new String[]{"a.java (AFoo)"});
|
||||
}
|
||||
|
||||
public void testMethodsInInnerClasses() {
|
||||
myFixture.configureByText("a.java", "abstract class AFoo{\n" +
|
||||
" abstract boolean a<caret>aa();\n" +
|
||||
@@ -168,10 +248,13 @@ public class ImplementationsViewTest extends LightCodeInsightFixtureTestCase {
|
||||
});
|
||||
final ImplementationViewComponent component =
|
||||
new ImplementationViewComponent(all.toArray(new PsiElement[all.size()]), 0);
|
||||
assertContent(component, new String[]{"a.java (AFoo)", "a.java (AFoo1 in AFoo)", "a.java (AFoo2 in AFoo)", "a.java (AFoo3 in AFoo)"});
|
||||
}
|
||||
|
||||
public static void assertContent(ImplementationViewComponent component, String[] expects) {
|
||||
try {
|
||||
final String[] visibleFiles = component.getVisibleFiles();
|
||||
Assert.assertArrayEquals(Arrays.toString(visibleFiles),
|
||||
new String[]{"a.java (AFoo)", "a.java (AFoo1 in AFoo)", "a.java (AFoo2 in AFoo)", "a.java (AFoo3 in AFoo)"}, visibleFiles);
|
||||
Assert.assertArrayEquals(Arrays.toString(visibleFiles), expects, visibleFiles);
|
||||
}
|
||||
finally {
|
||||
component.removeNotify();
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
@@ -26,8 +27,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class GotoImplementationTest extends CodeInsightTestCase {
|
||||
|
||||
private static Collection<PsiClass> getClassImplementations(final PsiClass psiClass) {
|
||||
CommonProcessors.CollectProcessor<PsiClass> processor = new CommonProcessors.CollectProcessor<PsiClass>();
|
||||
private static Collection<PsiElement> getClassImplementations(final PsiClass psiClass) {
|
||||
CommonProcessors.CollectProcessor<PsiElement> processor = new CommonProcessors.CollectProcessor<PsiElement>();
|
||||
ClassImplementationsSearch.processImplementations(psiClass, processor, psiClass.getUseScope());
|
||||
|
||||
return processor.getResults();
|
||||
@@ -64,29 +65,31 @@ public class GotoImplementationTest extends CodeInsightTestCase {
|
||||
PsiClass test1 = myJavaFacade.findClass("com.test.TestI", moduleScope);
|
||||
PsiClass test2 = myJavaFacade.findClass("com.test.TestI", GlobalSearchScope.moduleScope(module2));
|
||||
PsiClass test3 = myJavaFacade.findClass("com.test.TestI", GlobalSearchScope.moduleScope(module3));
|
||||
HashSet<PsiClass> expectedImpls1 = new HashSet<PsiClass>(Arrays.asList(
|
||||
HashSet<PsiElement> expectedImpls1 = new HashSet<PsiElement>(Arrays.asList(
|
||||
myJavaFacade.findClass("com.test.TestIImpl1", moduleScope),
|
||||
myJavaFacade.findClass("com.test.TestIImpl2", moduleScope)
|
||||
));
|
||||
assertEquals(expectedImpls1, new HashSet<PsiClass>(getClassImplementations(test1)));
|
||||
assertEquals(expectedImpls1, new HashSet<PsiElement>(getClassImplementations(test1)));
|
||||
|
||||
PsiMethod psiMethod = test1.findMethodsByName("test", false)[0];
|
||||
Set<PsiMethod> expectedMethodImpl1 = new HashSet<PsiMethod>(Arrays.asList(
|
||||
Set<PsiElement> expectedMethodImpl1 = new HashSet<PsiElement>(Arrays.asList(
|
||||
myJavaFacade.findClass("com.test.TestIImpl1", moduleScope).findMethodsByName("test",false)[0],
|
||||
myJavaFacade.findClass("com.test.TestIImpl2", moduleScope).findMethodsByName("test",false)[0]
|
||||
));
|
||||
assertEquals(expectedMethodImpl1, new HashSet<PsiMethod>(Arrays.asList(MethodImplementationsSearch.getMethodImplementations(psiMethod, moduleScope))));
|
||||
CommonProcessors.CollectProcessor<PsiElement> processor = new CommonProcessors.CollectProcessor<PsiElement>();
|
||||
MethodImplementationsSearch.processImplementations(psiMethod, processor, moduleScope);
|
||||
assertEquals(expectedMethodImpl1, new HashSet<PsiElement>(processor.getResults()));
|
||||
|
||||
HashSet<PsiClass> expectedImpls2 = new HashSet<PsiClass>(Arrays.asList(
|
||||
HashSet<PsiElement> expectedImpls2 = new HashSet<PsiElement>(Arrays.asList(
|
||||
myJavaFacade.findClass("com.test.TestIImpl1", GlobalSearchScope.moduleScope(module2)),
|
||||
myJavaFacade.findClass("com.test.TestIImpl3", GlobalSearchScope.moduleScope(module2))
|
||||
));
|
||||
assertEquals(expectedImpls2, new HashSet<PsiClass>(getClassImplementations(test2)));
|
||||
assertEquals(expectedImpls2, new HashSet<PsiElement>(getClassImplementations(test2)));
|
||||
|
||||
HashSet<PsiClass> expectedImpls3 = new HashSet<PsiClass>(Arrays.asList(
|
||||
HashSet<PsiElement> expectedImpls3 = new HashSet<PsiElement>(Arrays.asList(
|
||||
myJavaFacade.findClass("com.test.TestIImpl1", GlobalSearchScope.moduleScope(module3))
|
||||
));
|
||||
assertEquals(expectedImpls3, new HashSet<PsiClass>(getClassImplementations(test3)));
|
||||
assertEquals(expectedImpls3, new HashSet<PsiElement>(getClassImplementations(test3)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
+13
-14
@@ -17,11 +17,10 @@ package org.jetbrains.plugins.groovy.findUsages;
|
||||
|
||||
import com.intellij.codeInsight.navigation.MethodImplementationsSearch;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.DefinitionsScopedSearch;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
|
||||
@@ -40,19 +39,19 @@ public class GroovyImplementationSearch implements QueryExecutor<PsiElement, Def
|
||||
GrField property = ((GrAccessorMethod)source).getProperty();
|
||||
return consumer.process(property);
|
||||
}
|
||||
else if (source instanceof GrMethod) {
|
||||
GrReflectedMethod[] reflectedMethods = ((GrMethod)source).getReflectedMethods();
|
||||
for (GrReflectedMethod reflectedMethod : reflectedMethods) {
|
||||
PsiMethod[] implementations = MethodImplementationsSearch.getMethodImplementations(reflectedMethod, queryParameters.getScope());
|
||||
if (!ContainerUtil.process(implementations, consumer)) return false;
|
||||
else {
|
||||
final SearchScope searchScope = queryParameters.getScope();
|
||||
if (source instanceof GrMethod) {
|
||||
GrReflectedMethod[] reflectedMethods = ((GrMethod)source).getReflectedMethods();
|
||||
for (GrReflectedMethod reflectedMethod : reflectedMethods) {
|
||||
if (!MethodImplementationsSearch.processImplementations(reflectedMethod, consumer, searchScope)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (source instanceof GrField) {
|
||||
for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors((GrField)source)) {
|
||||
|
||||
PsiMethod[] implementations = MethodImplementationsSearch.getMethodImplementations(method, queryParameters.getScope());
|
||||
if (!ContainerUtil.process(implementations, consumer)) return false;
|
||||
|
||||
else if (source instanceof GrField) {
|
||||
for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors((GrField)source)) {
|
||||
if (!MethodImplementationsSearch.processImplementations(method, consumer, searchScope)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user