From 234fdbfc4f77022554b6c90c1ef2d378d43800c6 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 5 Nov 2014 19:31:52 +0100 Subject: [PATCH] find functional expressions by method type parameter --- .../JavaFunctionalExpressionSearcher.java | 7 +++++- .../java/stubs/JavaMethodElementType.java | 24 +++++++++++++++++-- .../MethodArgumentByTypeParameter.java | 11 +++++++++ .../lambda/FindFunctionalInterfaceTest.java | 14 ++++++++++- 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/MethodArgumentByTypeParameter.java diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaFunctionalExpressionSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaFunctionalExpressionSearcher.java index e7da21e37b51..fcaf5b726f9f 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaFunctionalExpressionSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaFunctionalExpressionSearcher.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; +import com.intellij.psi.impl.java.stubs.JavaMethodElementType; import com.intellij.psi.impl.java.stubs.index.JavaMethodParameterTypesIndex; import com.intellij.psi.search.EverythingGlobalScope; import com.intellij.psi.search.GlobalSearchScope; @@ -33,6 +34,7 @@ import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.LinkedHashSet; public class JavaFunctionalExpressionSearcher implements QueryExecutor { @@ -78,7 +80,10 @@ public class JavaFunctionalExpressionSearcher implements QueryExecutor compute() { final String functionalInterfaceName = aClass.getName(); final GlobalSearchScope useClassScope = classScope instanceof GlobalSearchScope ? (GlobalSearchScope)classScope : scope; - return JavaMethodParameterTypesIndex.getInstance().get(functionalInterfaceName, project, useClassScope); + JavaMethodParameterTypesIndex parameterTypesIndex = JavaMethodParameterTypesIndex.getInstance(); + LinkedHashSet methods = new LinkedHashSet(parameterTypesIndex.get(functionalInterfaceName, project, useClassScope)); + methods.addAll(parameterTypesIndex.get(JavaMethodElementType.TYPE_PARAMETER_PSEUDO_NAME, project, GlobalSearchScope.allScope(project))); + return methods; } }); for (PsiMethod psiMethod : lambdaCandidates) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java index 368d8b3be9e0..3474384183e4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java @@ -41,12 +41,15 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * @author max */ public abstract class JavaMethodElementType extends JavaStubElementType { + public static final String TYPE_PARAMETER_PSEUDO_NAME = "$TYPE_PARAMETER$"; public JavaMethodElementType(@NonNls final String name) { super(name); } @@ -147,11 +150,28 @@ public abstract class JavaMethodElementType extends JavaStubElementType methodTypeParams = null; for (StubElement stubElement : stub.getChildrenStubs()) { - if (stubElement instanceof PsiParameterListStub) { + if (stubElement instanceof PsiTypeParameterListStub) { + for (Object tStub : stubElement.getChildrenStubs()) { + if (tStub instanceof PsiTypeParameterStub) { + if (methodTypeParams == null) { + methodTypeParams = new HashSet(); + } + methodTypeParams.add(((PsiTypeParameterStub)tStub).getName()); + } + } + } + else if (stubElement instanceof PsiParameterListStub) { for (StubElement paramStub : ((PsiParameterListStub)stubElement).getChildrenStubs()) { if (paramStub instanceof PsiParameterStub) { - sink.occurrence(JavaStubIndexKeys.METHOD_TYPES, ((PsiParameterStub)paramStub).getType(false).getShortTypeText()); + TypeInfo type = ((PsiParameterStub)paramStub).getType(false); + String typeName = type.getShortTypeText(); + sink.occurrence(JavaStubIndexKeys.METHOD_TYPES, typeName); + if (methodTypeParams != null && methodTypeParams.contains(typeName)) { + sink.occurrence(JavaStubIndexKeys.METHOD_TYPES, TYPE_PARAMETER_PSEUDO_NAME); + methodTypeParams = null; + } } } break; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/MethodArgumentByTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/MethodArgumentByTypeParameter.java new file mode 100644 index 000000000000..7ce4a2af53d3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/MethodArgumentByTypeParameter.java @@ -0,0 +1,11 @@ +interface SAM { + void foo(); +} + +class Test { + { + SAM sam = bar(() -> {}); + } + + T bar(T t){ return t;} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java index 2427748b22d4..64b013d44df7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java @@ -42,7 +42,19 @@ public class FindFunctionalInterfaceTest extends LightCodeInsightFixtureTestCase assertEquals("() -> {}", next.getText()); } - @Bombed(day = 30, month = Calendar.SEPTEMBER) + public void testMethodArgumentByTypeParameter() throws Exception { + myFixture.configureByFile(getTestName(false) + ".java"); + final PsiElement elementAtCaret = myFixture.getElementAtCaret(); + assertNotNull(elementAtCaret); + final PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class, false); + assertTrue(psiClass != null && psiClass.isInterface()); + final Collection expressions = FunctionalExpressionSearch.search(psiClass).findAll(); + assertTrue(expressions.size() == 1); + final PsiFunctionalExpression next = expressions.iterator().next(); + assertNotNull(next); + assertEquals("() -> {}", next.getText()); + } + public void testFieldFromAnonymousClassScope() throws Exception { myFixture.configureByFile(getTestName(false) + ".java"); final PsiElement elementAtCaret = myFixture.getElementAtCaret();