show implementations: ensure functional expressions are not missed when search over usage (IDEA-147691)

This commit is contained in:
Anna Kozlova
2015-11-11 20:32:37 +01:00
parent a0ef7d2adf
commit ce44bbb5e4
2 changed files with 54 additions and 7 deletions
@@ -22,6 +22,7 @@ import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
import com.intellij.psi.util.*;
import com.intellij.util.Processor;
import com.intellij.util.ThreeState;
@@ -310,7 +311,7 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
@Override
@Nullable
public SearchScope getSearchScope(Editor editor, @NotNull PsiElement element) {
public SearchScope getSearchScope(Editor editor, @NotNull final PsiElement element) {
final PsiReferenceExpression referenceExpression = editor != null ? findReferenceExpression(editor) : null;
if (referenceExpression != null && element instanceof PsiMethod) {
final PsiClass[] memberClass = getMemberClass(referenceExpression, element);
@@ -326,9 +327,13 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
for (PsiClass psiClass : classesToSearch) {
supers.addAll(InheritanceUtil.getSuperClasses(psiClass));
}
classesToSearch.addAll(supers);
return new Result<SearchScope>(new LocalSearchScope(PsiUtilCore.toPsiElementArray(classesToSearch)), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
final List<PsiElement> elements = new ArrayList<PsiElement>();
elements.addAll(classesToSearch);
elements.addAll(supers);
elements.addAll(FunctionalExpressionSearch.search((PsiMethod)element).findAll());
return new Result<SearchScope>(new LocalSearchScope(PsiUtilCore.toPsiElementArray(elements)), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
}
@@ -17,14 +17,25 @@
package com.intellij.navigation;
import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.codeInsight.hint.actions.ShowImplementationsAction;
import com.intellij.ide.DataManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
public class ShowImplementationHandlerTest extends JavaCodeInsightFixtureTestCase {
@Override
protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception {
super.tuneFixture(moduleBuilder);
moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8);
}
public void testMultipleImplsFromAbstractCall() throws Throwable {
PsiFile file = myFixture.addFileToProject("Foo.java", "public abstract class Hello {" +
" {" +
@@ -41,4 +52,35 @@ public class ShowImplementationHandlerTest extends JavaCodeInsightFixtureTestCas
assertEquals(CommonClassNames.JAVA_LANG_RUNNABLE, qualifiedName);
}
public void testFunctionExpressionsOnReference() throws Exception {
myFixture.addClass("public interface I {void m();}");
myFixture.addClass("public class Usage {{I i = () -> {};}}");
PsiFile file = myFixture.addFileToProject("Foo.java", "public abstract class Hello {" +
" void foo(I i) {" +
" i.<caret>m();\n" +
" }\n" +
"}\n" +
"\n");
myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
final PsiElement[] implementations = getImplementations();
assertEquals(2, implementations.length);
assertInstanceOf(implementations[1], PsiLambdaExpression.class);
}
private static PsiElement[] getImplementations() {
final Ref<PsiElement[]> ref = new Ref<>();
new ShowImplementationsAction() {
@Override
protected void showImplementations(@NotNull PsiElement[] impls, @NotNull Project project, String text, Editor editor, PsiFile file,
PsiElement element,
boolean invokedFromEditor,
boolean invokedByShortcut) {
ref.set(impls);
}
}.performForContext(DataManager.getInstance().getDataContext());
return ref.get();
}
}