Java: Improved completion for arguments of getField() and getMethod() - extract the type information from forName() and getClass() to provide code assistance (IDEA-167250)

This commit is contained in:
Pavel Dolgov
2017-02-06 15:26:07 +03:00
parent 4a405a6bcd
commit 69b3a8c6cb
16 changed files with 365 additions and 136 deletions

View File

@@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.resolve.reference.impl;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
@@ -26,12 +25,14 @@ import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,10 +42,15 @@ import java.util.Arrays;
* @author Konstantin Bulenkov
*/
public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExpression> implements InsertHandler<LookupElement> {
private static final String FIELD = "getField";
private static final String DECLARED_FIELD = "getDeclaredField";
private static final String METHOD = "getMethod";
private static final String DECLARED_METHOD = "getDeclaredMethod";
private static final RecursionGuard ourGuard = RecursionManager.createGuard("JavaLangClassMemberReference");
private final PsiExpression myContext;
public JavaLangClassMemberReference(PsiLiteralExpression literal, PsiExpression context) {
public JavaLangClassMemberReference(@NotNull PsiLiteralExpression literal, @NotNull PsiExpression context) {
super(literal);
myContext = context;
}
@@ -56,30 +62,38 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
@Override
public PsiElement resolve() {
final String name = (String)getElement().getValue();
final Type type = getType();
Object value = myElement.getValue();
if (value instanceof String) {
final String name = (String)value;
final String type = getMemberType();
if (type != null) {
final PsiClass psiClass = getPsiClass();
if (psiClass != null) {
switch (type) {
if (type != null) {
final PsiClass psiClass = getPsiClass();
if (psiClass != null) {
switch (type) {
case FIELD: {
PsiField field = psiClass.findFieldByName(name, true);
return isPublic(field) ? field : null;
}
case FIELD: {
return psiClass.findFieldByName(name, true);
}
case DECLARED_FIELD:
return psiClass.findFieldByName(name, false);
case DECLARED_FIELD: {
PsiField field = psiClass.findFieldByName(name, false);
return isReachable(field, psiClass) ? field : null;
}
case METHOD: {
final PsiMethod[] methods = psiClass.findMethodsByName(name, true);
return ContainerUtil.find(methods, JavaLangClassMemberReference::isPublic);
}
case METHOD: {
final PsiMethod[] methods = psiClass.findMethodsByName(name, true);
final PsiMethod publicMethod = ContainerUtil.find(methods, method -> isRegularMethod(method) && isPublic(method));
if (publicMethod != null) {
return publicMethod;
}
return ContainerUtil.find(methods, method -> isRegularMethod(method));
}
case DECLARED_METHOD: {
final PsiMethod[] methods = psiClass.findMethodsByName(name, false);
return methods.length == 0 ? null : methods[0];
case DECLARED_METHOD: {
final PsiMethod[] methods = psiClass.findMethodsByName(name, false);
return ContainerUtil.find(methods, method -> isRegularMethod(method) && isReachable(method, psiClass));
}
}
}
}
@@ -100,88 +114,88 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
return PsiTypesUtil.getPsiClass(operand.getType());
}
PsiType type = context.getType();
if (type instanceof PsiClassType) {
PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
if (!isJavaLangClass(resolveResult.getElement())) return null;
PsiTypeParameter[] parameters = resolveResult.getElement().getTypeParameters();
if (parameters.length == 1) {
PsiType typeArgument = resolveResult.getSubstitutor().substitute(parameters[0]);
PsiClass argumentClass = PsiTypesUtil.getPsiClass(typeArgument);
if (argumentClass != null) return argumentClass;
}
}
if (context instanceof PsiMethodCallExpression) {
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)context;
if ("forName".equals(methodCall.getMethodExpression().getReferenceName())) {
final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)context;
final String methodReferenceName = methodCall.getMethodExpression().getReferenceName();
if ("forName".equals(methodReferenceName)) {
final PsiMethod method = methodCall.resolveMethod();
if (method != null && isJavaLangClass(method.getContainingClass())) {
final PsiExpression[] expressions = methodCall.getArgumentList().getExpressions();
if (expressions.length == 1 && expressions[0] instanceof PsiLiteralExpression) {
final Object value = ((PsiLiteralExpression)expressions[0]).getValue();
if (expressions.length == 1) {
PsiExpression argument = ParenthesesUtils.stripParentheses(expressions[0]);
if (argument instanceof PsiReferenceExpression) {
argument = findVariableDefinition(((PsiReferenceExpression)argument));
}
final Object value = JavaConstantExpressionEvaluator.computeConstantExpression(argument, false);
if (value instanceof String) {
final Project project = context.getProject();
return JavaPsiFacade.getInstance(project).findClass(String.valueOf(value), GlobalSearchScope.allScope(project));
return JavaPsiFacade.getInstance(project).findClass((String)value, GlobalSearchScope.allScope(project));
}
}
}
}
else if ("getClass".equals(methodReferenceName) && methodCall.getArgumentList().getExpressions().length == 0) {
final PsiMethod method = methodCall.resolveMethod();
if (method != null && isJavaLangObject(method.getContainingClass())) {
final PsiExpression qualifier = ParenthesesUtils.stripParentheses(methodCall.getMethodExpression().getQualifierExpression());
if (qualifier instanceof PsiReferenceExpression) {
final PsiExpression definition = findVariableDefinition((PsiReferenceExpression)qualifier);
if (definition != null) {
final PsiClass actualClass = PsiTypesUtil.getPsiClass(definition.getType());
if (actualClass != null) {
return actualClass;
}
}
}
//TODO type of the qualifier may be a supertype of the actual value - need to compute the type of the actual value
// otherwise getDeclaredField and getDeclaredMethod may work not reliably
if (qualifier != null) {
return PsiTypesUtil.getPsiClass(qualifier.getType());
}
}
}
}
PsiType type = context.getType();
if (type instanceof PsiClassType) {
PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
if (!isJavaLangClass(resolveResult.getElement())) return null;
final PsiTypeParameter[] parameters = resolveResult.getElement().getTypeParameters();
if (parameters.length == 1) {
PsiType typeArgument = resolveResult.getSubstitutor().substitute(parameters[0]);
if (typeArgument instanceof PsiCapturedWildcardType) {
typeArgument = ((PsiCapturedWildcardType)typeArgument).getUpperBound();
}
final PsiClass argumentClass = PsiTypesUtil.getPsiClass(typeArgument);
if (argumentClass != null && !isJavaLangObject(argumentClass)) {
return argumentClass;
}
}
}
if (context instanceof PsiReferenceExpression) {
PsiElement resolved = ((PsiReferenceExpression)context).resolve();
final PsiElement resolved = ((PsiReferenceExpression)context).resolve();
if (resolved instanceof PsiVariable) {
PsiExpression initializer = getInitializer((PsiVariable)resolved, context);
if (initializer != null) {
return ourGuard.doPreventingRecursion(resolved, false, () -> getPsiClass(initializer));
final PsiExpression definition = findVariableDefinition((PsiReferenceExpression)context, (PsiVariable)resolved);
if (definition != null) {
return ourGuard.doPreventingRecursion(resolved, false, () -> getPsiClass(definition));
}
}
}
return null;
}
private static PsiExpression getInitializer(@NotNull PsiVariable variable, @NotNull PsiExpression usage) {
PsiExpression initializer = variable.getInitializer();
if (initializer != null) {
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
private static PsiExpression findVariableDefinition(@NotNull PsiReferenceExpression referenceExpression) {
final PsiElement resolved = referenceExpression.resolve();
return resolved instanceof PsiVariable ? findVariableDefinition(referenceExpression, (PsiVariable)resolved) : null;
}
private static PsiExpression findVariableDefinition(@NotNull PsiReferenceExpression referenceExpression, @NotNull PsiVariable variable) {
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
final PsiExpression initializer = variable.getInitializer();
if (initializer != null) {
return initializer;
}
if (variable instanceof PsiLocalVariable) {
PsiDeclarationStatement declarationStatement = ObjectUtils.tryCast(variable.getParent(), PsiDeclarationStatement.class);
if (declarationStatement != null) {
PsiStatement usageStatement = PsiTreeUtil.getParentOfType(usage, PsiStatement.class);
if (PsiTreeUtil.getNextSiblingOfType(declarationStatement, PsiStatement.class) == usageStatement) {
return initializer;
}
PsiElement scope = PsiUtil.getVariableCodeBlock(variable, usage);
if (scope != null && HighlightControlFlowUtil.isEffectivelyFinal(variable, scope, null)) {
return initializer;
}
}
}
}
PsiStatement usageStatement = PsiTreeUtil.getParentOfType(usage, PsiStatement.class);
if (usageStatement != null) {
return getAssignedVisibleInUsage(variable, usageStatement);
}
// TODO: handle other initializations and assignments where the class can be resolved unambiguously
return null;
}
@Nullable
private static PsiExpression getAssignedVisibleInUsage(@NotNull PsiVariable variable, PsiStatement usageStatement) {
PsiStatement previousStatement = PsiTreeUtil.getPrevSiblingOfType(usageStatement, PsiStatement.class);
if (previousStatement instanceof PsiExpressionStatement) {
PsiExpression expression = ((PsiExpressionStatement)previousStatement).getExpression();
if (expression instanceof PsiAssignmentExpression &&
JavaTokenType.EQ.equals(((PsiAssignmentExpression)expression).getOperationTokenType())) {
PsiExpression lExpression = ((PsiAssignmentExpression)expression).getLExpression();
lExpression = ParenthesesUtils.stripParentheses(lExpression);
if (lExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)lExpression).resolve() == variable) {
return ((PsiAssignmentExpression)expression).getRExpression();
}
}
}
return null;
return DeclarationSearchUtils.findDefinition(referenceExpression, variable);
}
private static boolean isJavaLangClass(PsiClass aClass) {
@@ -193,19 +207,15 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
}
@Nullable
private Type getType() {
PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(myElement, PsiMethodCallExpression.class);
if (methodCall != null) {
String name = methodCall.getMethodExpression().getReferenceName();
return Type.fromString(name);
}
return null;
private String getMemberType() {
final PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(myElement, PsiMethodCallExpression.class);
return methodCall != null ? methodCall.getMethodExpression().getReferenceName() : null;
}
@NotNull
@Override
public Object[] getVariants() {
final Type type = getType();
final String type = getMemberType();
if (type != null) {
final PsiClass psiClass = getPsiClass();
if (psiClass != null) {
@@ -215,17 +225,17 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
return psiClass.getFields();
case FIELD:
return ContainerUtil.filter(psiClass.getAllFields(), JavaLangClassMemberReference::isPublic).toArray();
return ContainerUtil.filter(psiClass.getAllFields(), field -> isReachable(field, psiClass)).toArray();
case DECLARED_METHOD:
return Arrays.stream(psiClass.getMethods())
.filter(method -> !method.isConstructor())
.filter(method -> isRegularMethod(method))
.map(this::lookupMethod)
.toArray();
case METHOD:
return Arrays.stream(psiClass.getAllMethods())
.filter(method -> isPublic(method) && !method.isConstructor() && !isJavaLangObject(method.getContainingClass()))
.filter(method -> isRegularMethod(method) && isReachable(method, psiClass) && !isJavaLangObject(method.getContainingClass()))
.map(this::lookupMethod)
.toArray();
}
@@ -258,11 +268,24 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
}
}
private static boolean isPublic(final PsiMember psiField) {
return psiField.hasModifierProperty(PsiModifier.PUBLIC);
@Contract("null -> false")
private static boolean isRegularMethod(PsiMethod method) {
return method != null && !method.isConstructor();
}
private static String getMethodTypes(PsiMethod method) {
/**
* Non-public members of superclass/superinterface can't be obtained via reflection, they need to be filtered out.
*/
@Contract("null, _ -> false")
private static boolean isReachable(PsiMember member, PsiClass psiClass) {
return member != null && (member.getContainingClass() == psiClass || isPublic(member));
}
private static boolean isPublic(@NotNull PsiMember member) {
return member.hasModifierProperty(PsiModifier.PUBLIC);
}
private static String getMethodTypes(@NotNull PsiMethod method) {
final StringBuilder buf = new StringBuilder();
for (PsiParameter parameter : method.getParameterList().getParameters()) {
PsiType type = TypeConversionUtil.erasure(parameter.getType());
@@ -273,18 +296,4 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
}
return buf.toString();
}
enum Type {
FIELD, DECLARED_FIELD, METHOD, DECLARED_METHOD;
@Nullable
static Type fromString(String s) {
if ("getField".equals(s)) return FIELD;
if ("getDeclaredField".equals(s)) return DECLARED_FIELD;
if ("getMethod".equals(s)) return METHOD;
if ("getDeclaredMethod".equals(s)) return DECLARED_METHOD;
return null;
}
}
}

View File

@@ -35,9 +35,7 @@ public class JavaReflectionReferenceProvider extends PsiReferenceProvider {
if (grandParent instanceof PsiMethodCallExpression) {
PsiReferenceExpression methodReference = ((PsiMethodCallExpression)grandParent).getMethodExpression();
PsiExpression qualifier = methodReference.getQualifierExpression();
if (qualifier instanceof PsiClassObjectAccessExpression ||
qualifier instanceof PsiMethodCallExpression ||
qualifier instanceof PsiReferenceExpression) {
if (qualifier != null) {
return new PsiReference[]{new JavaLangClassMemberReference(literal, qualifier)};
}
}

View File

@@ -0,0 +1,16 @@
class Main {
final Parent test = new Test();
void foo() {
test.getClass().getField("<caret>");
}
}
class Test extends Parent {
public int num;
int num2;
}
class Parent {
public int num3;
int num4;
}

View File

@@ -0,0 +1,16 @@
class Main {
final Parent test = new Test();
void foo() {
test.getClass().getField("num2");
}
}
class Test extends Parent {
public int num;
int num2;
}
class Parent {
public int num3;
int num4;
}

View File

@@ -0,0 +1,11 @@
class Main {
final Class<?> clazz = Test.class;
void foo() {
clazz.getMethod("<caret>");
}
}
class Test {
public void method(){}
void method2(int n){}
}

View File

@@ -0,0 +1,11 @@
class Main {
final Class<?> clazz = Test.class;
void foo() {
clazz.getMethod("method");
}
}
class Test {
public void method(){}
void method2(int n){}
}

View File

@@ -0,0 +1,16 @@
class Main {
void foo() {
Class<?> d = d();
d = d();
int i = 0;
(d).getDeclaredMethod("<caret>");
}
Class<Test> d() {
return Test.class;
}
}
class Test {
public int method() {}
int method2(int n) {}
}

View File

@@ -0,0 +1,16 @@
class Main {
void foo() {
Class<?> d = d();
d = d();
int i = 0;
(d).getDeclaredMethod("method2", int.class);
}
Class<Test> d() {
return Test.class;
}
}
class Test {
public int method() {}
int method2(int n) {}
}

View File

@@ -0,0 +1,12 @@
class Main {
void foo() {
bar().getClass().getField("<caret>");
}
Test bar() { return null; }
}
class Test {
public int num;
public int num2;
int num3;
}

View File

@@ -0,0 +1,12 @@
class Main {
void foo() {
bar().getClass().getField("num2");
}
Test bar() { return null; }
}
class Test {
public int num;
public int num2;
int num3;
}

View File

@@ -0,0 +1,12 @@
class Main {
Test test;
void foo() {
test.getClass().getField("<caret>");
}
}
class Test {
public int num;
public int num2;
int num3;
}

View File

@@ -0,0 +1,12 @@
class Main {
Test test;
void foo() {
test.getClass().getField("num2");
}
}
class Test {
public int num;
public int num2;
int num3;
}

View File

@@ -0,0 +1,10 @@
class Main {
void foo() throws NoSuchMethodException {
clazz().getMethod("<caret>");
}
private Class<? extends Test> clazz() {return Test.class;}
}
class Test {
public void method(){}
}

View File

@@ -0,0 +1,10 @@
class Main {
void foo() throws NoSuchMethodException {
clazz().getMethod("method");
}
private Class<? extends Test> clazz() {return Test.class;}
}
class Test {
public void method(){}
}

View File

@@ -30,7 +30,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testField() throws Exception {
doTest(1, "num", "num2");
doTest(1, "num", "num2", "num3");
}
public void testDeclaredField() throws Exception {
@@ -46,7 +46,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testMethod() throws Exception {
doTest(1, "method", "method2");
doTest(1, "method", "method2", "method3");
}
public void testForNameDeclaredMethod() throws Exception {
@@ -54,11 +54,11 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testForNameMethod() throws Exception {
doTest(1, "method", "method2");
doTest(1, "method", "method2", "method3");
}
public void testForNameField() throws Exception {
doTest(1, "num", "num2");
doTest(1, "num", "num2", "num3");
}
public void testForNameDeclaredField() throws Exception {
@@ -75,7 +75,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testInheritedMethod() throws Exception {
doTest(1, "method", "method2");
doTest(1, "method", "method2", "method3");
}
public void testInheritedDeclaredMethod() throws Exception {
@@ -83,7 +83,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
}
public void testInheritedField() throws Exception {
doTest(1, "num", "num2");
doTest(1, "num", "num2", "num3");
}
public void testInheritedDeclaredField() throws Exception {
@@ -118,6 +118,30 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_4, () -> doTest(0, "method"));
}
public void testWildcard() throws Exception {
doTest(0, "method");
}
public void testConstantMethod() throws Exception {
doTest(0, "method", "method2");
}
public void testDistantDefinition() throws Exception {
doTest(1, "method", "method2");
}
public void testVariableGetClassField() throws Exception {
doTest(1, "num", "num2", "num3");
}
public void testConstantGetClassField() throws Exception {
doTest(1, "num", "num2", "num3");
}
public void testExpressionGetClassField() throws Exception {
doTest(1, "num", "num2", "num3");
}
private void doTest(int index, String... expected) {
configureByFile(getTestName(false) + ".java");
assertStringItems(expected);

View File

@@ -15,12 +15,13 @@
*/
package com.intellij.codeInsight.navigation;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiReference;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.intellij.lang.annotations.Language;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
@@ -35,33 +36,76 @@ public class JavaReflectionNavigationTest extends LightCodeInsightFixtureTestCas
public void testField() {doTest("field", FIELD);}
public void testField2() {doNegativeTest("field2", FIELD);}
public void testField2() {doTest("field2", FIELD);}
public void testDeclaredField() {doTest("field2", DF);}
public void testNonexistentField() {doNegativeTest("nonexistent", FIELD);}
public void testMethod() {doTest("method", METHOD);}
public void testMethod2() {doNegativeTest("method2", METHOD);}
public void testMethod2() {doTest("method2", METHOD);}
public void testDeclaredMethod() {doTest("method2", DM);}
public void testNonexistentMethod() {doNegativeTest("nonexistent", METHOD);}
public void testInheritedField() {doTest("field3", FIELD);}
public void testInheritedField2() {doNegativeTest("field4", FIELD);}
public void testInheritedField2() {doTest("field4", FIELD);}
public void testInheritedDeclaredField() {doNegativeTest("field3", DF);}
public void testInheritedMethod() {doTest("method3", METHOD);}
public void testInheritedMethod2() {doNegativeTest("method4", METHOD);}
public void testInheritedMethod2() {doTest("method4", METHOD);}
public void testInheritedDeclaredMethod() {doNegativeTest("method3", DM);}
public void testConstantClassName() {
doCustomTest("method2",
"class Main {" +
" static final String NAME = \"Test\";" +
" void foo() throws ReflectiveOperationException {" +
" Class.forName(NAME).getMethod(\"<caret>method2\", int.class);" +
" }" +
"}");
}
public void testVariableClassName() {
doCustomTest("method",
"class Main {" +
" void foo() throws ReflectiveOperationException {" +
" String name;" +
" name = \"Te\" + \"st\";" +
" Class.forName(name).getMethod(\"<caret>method\");" +
" }" +
"}");
}
public void testExpressionClassName() {
doCustomTest("method3",
"class Main {" +
" void foo() throws ReflectiveOperationException {" +
" Class.forName(\"Pa\" + \"rent\").getMethod(\"<caret>method3\");" +
" }" +
"}");
}
private void doTest(String name,
@MagicConstant(stringValues = {FIELD, METHOD, DF, DM}) String type) {
PsiReference reference = getReference(name, type);
doTestImpl(name, getMainClassText(name, type));
}
private void doCustomTest(String name,
@NotNull @NonNls @Language("JAVA") String mainClassText) {
doTestImpl(name, mainClassText);
}
private void doTestImpl(String name, String mainClassText) {
PsiReference reference = getReference(mainClassText);
assertEquals("Reference text", name, reference.getCanonicalText());
PsiElement resolved = reference.resolve();
assertNotNull("Reference is not resolved: " + reference.getCanonicalText(), resolved);
@@ -72,15 +116,14 @@ public class JavaReflectionNavigationTest extends LightCodeInsightFixtureTestCas
private void doNegativeTest(String name,
@MagicConstant(stringValues = {FIELD, METHOD, DF, DM}) String type) {
PsiReference reference = getReference(name, type);
PsiReference reference = getReference(getMainClassText(name, type));
assertEquals("Reference text", name, reference.getCanonicalText());
PsiElement resolved = reference.resolve();
assertNull("Reference shouldn't resolve: " + reference.getCanonicalText(), resolved);
}
@NotNull
private PsiReference getReference(String name,
@MagicConstant(stringValues = {FIELD, METHOD, DF, DM}) String type) {
private PsiReference getReference(String mainClassText) {
myFixture.addClass("class Parent {\n" +
" public int field3;\n" +
" int field4;\n" +
@@ -93,12 +136,7 @@ public class JavaReflectionNavigationTest extends LightCodeInsightFixtureTestCas
" public void method() {}\n" +
" void method2(int n) {}\n" +
"}");
myFixture.configureByText("Main.java",
"class Main {\n" +
" void foo() throws ReflectiveOperationException {\n" +
" Test.class.get" + type + "(\"<caret>" + name + "\");\n" +
" }\n" +
"}");
myFixture.configureByText("Main.java", mainClassText);
int offset = myFixture.getCaretOffset();
PsiReference reference = myFixture.getFile().findReferenceAt(offset);
@@ -107,6 +145,12 @@ public class JavaReflectionNavigationTest extends LightCodeInsightFixtureTestCas
}
@NotNull
@Override
protected String getTestDataPath() {return PathManagerEx.getTestDataPath() + "/codeInsight/navigation/reflection";}
private static String getMainClassText(String name,
@MagicConstant(stringValues = {FIELD, METHOD, DF, DM}) String type) {
return "class Main {\n" +
" void foo() throws ReflectiveOperationException {\n" +
" Test.class.get" + type + "(\"<caret>" + name + "\");\n" +
" }\n" +
"}";
}
}