mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: Improved completion for arguments of reflection calls getField() and getMethod() - extract the actual type from Class.forName and from generic type parameter to provide the code assistance (IDEA-167250)
This commit is contained in:
+133
-49
@@ -18,27 +18,30 @@ 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;
|
||||
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.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
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.ParenthesesUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExpression> implements InsertHandler<LookupElement> {
|
||||
private static final RecursionGuard ourGuard = RecursionManager.createGuard("JavaLangClassMemberReference");
|
||||
private final PsiExpression myContext;
|
||||
|
||||
public JavaLangClassMemberReference(PsiLiteralExpression literal, PsiExpression context) {
|
||||
@@ -76,42 +79,115 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
|
||||
|
||||
@Nullable
|
||||
private PsiClass getPsiClass() {
|
||||
if (myContext instanceof PsiClassObjectAccessExpression) {
|
||||
return PsiTypesUtil.getPsiClass(((PsiClassObjectAccessExpression)myContext).getOperand().getType());
|
||||
} else if (myContext instanceof PsiMethodCallExpression) {
|
||||
final PsiMethod method = ((PsiMethodCallExpression)myContext).resolveMethod();
|
||||
if (method != null && "forName".equals(method.getName()) && isClass(method.getContainingClass())) {
|
||||
final PsiExpression[] expressions = ((PsiMethodCallExpression)myContext).getArgumentList().getExpressions();
|
||||
if (expressions.length == 1 && expressions[0] instanceof PsiLiteralExpression) {
|
||||
final Object value = ((PsiLiteralExpression)expressions[0]).getValue();
|
||||
if (value instanceof String) {
|
||||
final Project project = myContext.getProject();
|
||||
return JavaPsiFacade.getInstance(project).findClass(String.valueOf(value), GlobalSearchScope.allScope(project));
|
||||
return getPsiClass(myContext);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getPsiClass(PsiExpression context) {
|
||||
context = ParenthesesUtils.stripParentheses(context);
|
||||
if (context instanceof PsiClassObjectAccessExpression) { // special case for JDK 1.4
|
||||
PsiTypeElement operand = ((PsiClassObjectAccessExpression)context).getOperand();
|
||||
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 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 (value instanceof String) {
|
||||
final Project project = context.getProject();
|
||||
return JavaPsiFacade.getInstance(project).findClass(String.valueOf(value), GlobalSearchScope.allScope(project));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (context instanceof PsiReferenceExpression) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isClass(PsiClass aClass) {
|
||||
private static PsiExpression getInitializer(@NotNull PsiVariable variable, @NotNull PsiExpression usage) {
|
||||
PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null) {
|
||||
if (variable.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
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;
|
||||
}
|
||||
|
||||
private static boolean isJavaLangClass(PsiClass aClass) {
|
||||
return aClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(aClass.getQualifiedName());
|
||||
}
|
||||
|
||||
private static boolean isJavaLangObject(PsiClass aClass) {
|
||||
return aClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Type getType() {
|
||||
boolean selfFound = false;
|
||||
for (PsiElement child : myContext.getParent().getChildren()) {
|
||||
if (!selfFound) {
|
||||
if (child == myContext) {
|
||||
selfFound = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child instanceof PsiIdentifier) {
|
||||
return Type.fromString(child.getText());
|
||||
}
|
||||
PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(myElement, PsiMethodCallExpression.class);
|
||||
if (methodCall != null) {
|
||||
String name = methodCall.getMethodExpression().getReferenceName();
|
||||
return Type.fromString(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -120,31 +196,39 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
final Type type = getType();
|
||||
final PsiClass psiClass = getPsiClass();
|
||||
if (psiClass != null && type != null) {
|
||||
if (type == Type.DECLARED_FIELD) {
|
||||
return psiClass.getFields();
|
||||
} else if (type == Type.FIELD) {
|
||||
final List<PsiField> fields = new ArrayList<>();
|
||||
for (PsiField field : psiClass.getFields()) {
|
||||
if (isPublic(field)) {
|
||||
fields.add(field);
|
||||
}
|
||||
if (type != null) {
|
||||
final PsiClass psiClass = getPsiClass();
|
||||
if (psiClass != null) {
|
||||
switch (type) {
|
||||
|
||||
case DECLARED_FIELD:
|
||||
return psiClass.getFields();
|
||||
|
||||
case FIELD:
|
||||
return ContainerUtil.filter(psiClass.getAllFields(), JavaLangClassMemberReference::isPublic).toArray();
|
||||
|
||||
case DECLARED_METHOD:
|
||||
return Arrays.stream(psiClass.getMethods())
|
||||
.filter(method -> !method.isConstructor())
|
||||
.map(this::lookupMethod)
|
||||
.toArray();
|
||||
|
||||
case METHOD:
|
||||
return Arrays.stream(psiClass.getAllMethods())
|
||||
.filter(method -> isPublic(method) && !method.isConstructor() && !isJavaLangObject(method.getContainingClass()))
|
||||
.map(this::lookupMethod)
|
||||
.toArray();
|
||||
}
|
||||
return fields.toArray();
|
||||
} else if (type == Type.DECLARED_METHOD || type == Type.METHOD) {
|
||||
final List<LookupElementBuilder> elements = new ArrayList<>();
|
||||
for (PsiMethod method : psiClass.getMethods()) {
|
||||
if (type == Type.DECLARED_METHOD || isPublic(method)) {
|
||||
elements.add(JavaLookupElementBuilder.forMethod(method, PsiSubstitutor.EMPTY).withInsertHandler(this));
|
||||
}
|
||||
}
|
||||
return elements.toArray();
|
||||
}
|
||||
}
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LookupElementBuilder lookupMethod(PsiMethod method) {
|
||||
return JavaLookupElementBuilder.forMethod(method, PsiSubstitutor.EMPTY).withInsertHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
final Object object = item.getObject();
|
||||
|
||||
+14
-21
@@ -16,10 +16,8 @@
|
||||
package com.intellij.psi.impl.source.resolve.reference.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -29,28 +27,23 @@ public class JavaReflectionReferenceProvider extends PsiReferenceProvider {
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
if (element instanceof PsiLiteralExpression) {
|
||||
String value = getValue(((PsiLiteralExpression)element));
|
||||
final PsiElement expressionList;
|
||||
if (value != null && (expressionList = element.getParent()) instanceof PsiExpressionList) {
|
||||
final PsiElement methodCall = expressionList.getParent();
|
||||
final PsiExpression classAccess;
|
||||
if (methodCall != null && (classAccess = getContext(methodCall)) != null) {
|
||||
return new PsiReference[]{new JavaLangClassMemberReference((PsiLiteralExpression)element, classAccess)};
|
||||
PsiLiteralExpression literal = (PsiLiteralExpression)element;
|
||||
if (literal.getValue() instanceof String) {
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
PsiElement grandParent = parent.getParent();
|
||||
if (grandParent instanceof PsiMethodCallExpression) {
|
||||
PsiReferenceExpression methodReference = ((PsiMethodCallExpression)grandParent).getMethodExpression();
|
||||
PsiExpression qualifier = methodReference.getQualifierExpression();
|
||||
if (qualifier instanceof PsiClassObjectAccessExpression ||
|
||||
qualifier instanceof PsiMethodCallExpression ||
|
||||
qualifier instanceof PsiReferenceExpression) {
|
||||
return new PsiReference[]{new JavaLangClassMemberReference(literal, qualifier)};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiExpression getContext(PsiElement methodCall) {
|
||||
final PsiClassObjectAccessExpression expression = PsiTreeUtil.findChildOfType(methodCall, PsiClassObjectAccessExpression.class);
|
||||
return expression == null ? PsiTreeUtil.findChildOfType(methodCall, PsiMethodCallExpression.class) : expression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getValue(PsiLiteralExpression element) {
|
||||
final Object value = element.getValue();
|
||||
return value instanceof String ? (String)value : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> a,b,c,d;
|
||||
a = Class.forName("Test");
|
||||
b = a;
|
||||
c = b;
|
||||
d = c;
|
||||
d.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> a,b,c,d;
|
||||
a = Class.forName("Test");
|
||||
b = a;
|
||||
c = b;
|
||||
d = c;
|
||||
d.getField("num2");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> a,b,c,d;
|
||||
d = Class.forName("Test");
|
||||
a = d;
|
||||
b = a;
|
||||
c = b;
|
||||
d = c;
|
||||
d.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> a,b,c,d;
|
||||
d = Class.forName("Test");
|
||||
a = d;
|
||||
b = a;
|
||||
c = b;
|
||||
d = c;
|
||||
d.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class Main {
|
||||
void foo() throws ReflectiveOperationException {
|
||||
bar().getField("<caret>");
|
||||
}
|
||||
|
||||
Class<Test> bar() throws ClassNotFoundException { return (Class<Test>) Class.forName("Test"); }
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public void method(){}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class Main {
|
||||
void foo() throws ReflectiveOperationException {
|
||||
bar().getField("num");
|
||||
}
|
||||
|
||||
Class<Test> bar() throws ClassNotFoundException { return (Class<Test>) Class.forName("Test"); }
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public void method(){}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getDeclaredField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
int num3;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getDeclaredField("num3");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
int num3;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getDeclaredMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getDeclaredMethod("method3");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
void int num3;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getField("num2");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
void int num3;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("method2");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> a = Class.forName("Test");
|
||||
Class<?> b = a;
|
||||
Class<?> c = b;
|
||||
Class<?> d = c;
|
||||
Class<?> e = d;
|
||||
Class<?> f = e;
|
||||
Class<?> g = f;
|
||||
Class<?> h = g;
|
||||
Class<?> i = h;
|
||||
Class<?> j = i;
|
||||
Class<?> k = j;
|
||||
k.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> a = Class.forName("Test");
|
||||
Class<?> b = a;
|
||||
Class<?> c = b;
|
||||
Class<?> d = c;
|
||||
Class<?> e = d;
|
||||
Class<?> f = e;
|
||||
Class<?> g = f;
|
||||
Class<?> h = g;
|
||||
Class<?> i = h;
|
||||
Class<?> j = i;
|
||||
Class<?> k = j;
|
||||
k.getField("num2");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> c = Test.class;
|
||||
c.getMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void method(){}
|
||||
public void method2(int n){}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<?> c = Test.class;
|
||||
c.getMethod("method2", int.class);
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void method(){}
|
||||
public void method2(int n){}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<Test> c = bar();
|
||||
c.getMethod("<caret>");
|
||||
}
|
||||
|
||||
Class bar() { return Test.class; }
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void method(){}
|
||||
public void method2(int n){}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Class<Test> c = bar();
|
||||
c.getMethod("method2", int.class);
|
||||
}
|
||||
|
||||
Class bar() { return Test.class; }
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void method(){}
|
||||
public void method2(int n){}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void method(){}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("method");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void method(){}
|
||||
}
|
||||
+47
-1
@@ -16,6 +16,8 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -72,10 +74,54 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
doTest(0, "foo");
|
||||
}
|
||||
|
||||
public void testInheritedMethod() throws Exception {
|
||||
doTest(1, "method", "method2");
|
||||
}
|
||||
|
||||
public void testInheritedDeclaredMethod() throws Exception {
|
||||
doTest(1, "method", "method3");
|
||||
}
|
||||
|
||||
public void testInheritedField() throws Exception {
|
||||
doTest(1, "num", "num2");
|
||||
}
|
||||
|
||||
public void testInheritedDeclaredField() throws Exception {
|
||||
doTest(1, "num", "num3");
|
||||
}
|
||||
|
||||
public void testInitRaw() throws Exception {
|
||||
doTest(1, "method", "method2");
|
||||
}
|
||||
|
||||
public void testInitWithType() throws Exception {
|
||||
doTest(1, "method", "method2");
|
||||
}
|
||||
|
||||
public void testInitChain() throws Exception {
|
||||
doTest(1, "num", "num2");
|
||||
}
|
||||
|
||||
public void testAssignChain() throws Exception {
|
||||
doTest(1, "num", "num2");
|
||||
}
|
||||
|
||||
public void testAssignCycle() throws Exception {
|
||||
doTest(-1); // check that the recursion guard breaks the cycle
|
||||
}
|
||||
|
||||
public void testCallChain() throws Exception {
|
||||
doTest(0, "num");
|
||||
}
|
||||
|
||||
public void testJdk14() throws Exception {
|
||||
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_4, () -> doTest(0, "method"));
|
||||
}
|
||||
|
||||
private void doTest(int index, String... expected) {
|
||||
configureByFile(getTestName(false) + ".java");
|
||||
assertStringItems(expected);
|
||||
selectItem(getLookup().getItems().get(index));
|
||||
if (index >= 0) selectItem(getLookup().getItems().get(index));
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.java");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user