find functional expressions by method type parameter

This commit is contained in:
Anna Kozlova
2014-11-05 19:31:52 +01:00
parent 027d201051
commit 234fdbfc4f
4 changed files with 52 additions and 4 deletions
@@ -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<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
@@ -78,7 +80,10 @@ public class JavaFunctionalExpressionSearcher implements QueryExecutor<PsiFuncti
public Collection<PsiMethod> 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<PsiMethod> methods = new LinkedHashSet<PsiMethod>(parameterTypesIndex.get(functionalInterfaceName, project, useClassScope));
methods.addAll(parameterTypesIndex.get(JavaMethodElementType.TYPE_PARAMETER_PSEUDO_NAME, project, GlobalSearchScope.allScope(project)));
return methods;
}
});
for (PsiMethod psiMethod : lambdaCandidates) {
@@ -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<PsiMethodStub, PsiMethod> {
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<PsiMetho
}
}
Set<String> 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<String>();
}
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;
@@ -0,0 +1,11 @@
interface SA<caret>M {
void foo();
}
class Test {
{
SAM sam = bar(() -> {});
}
<T> T bar(T t){ return t;}
}
@@ -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<PsiFunctionalExpression> 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();