mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 05:21:29 +07:00
Java: Implemented sorting the candidates pop-up and added icons in that pup-up for "MethodHandle/VarHandle type mismatch" (IDEA-167318), refactored upon review feedback (IDEA-CR-19455)
This commit is contained in:
@@ -27,7 +27,6 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -44,14 +43,13 @@ import static com.intellij.psi.impl.source.resolve.reference.impl.JavaReflection
|
||||
* @author Pavel.Dolgov
|
||||
*/
|
||||
public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
public static final Key<List<String>> DEFAULT_SIGNATURE = Key.create("DEFAULT_SIGNATURE");
|
||||
public static final Key<ReflectiveSignature> DEFAULT_SIGNATURE = Key.create("DEFAULT_SIGNATURE");
|
||||
public static final Key<List<LookupElement>> POSSIBLE_SIGNATURES = Key.create("POSSIBLE_SIGNATURES");
|
||||
|
||||
private static final String FIND_CONSTRUCTOR = "findConstructor";
|
||||
private static final Set<String> KNOWN_METHOD_NAMES = Collections.unmodifiableSet(
|
||||
ContainerUtil.union(Arrays.asList(HANDLE_FACTORY_METHOD_NAMES), Collections.singletonList(FIND_CONSTRUCTOR)));
|
||||
|
||||
private static final List<String> NO_ARGUMENT_CONSTRUCTOR_SIGNATURE = Collections.singletonList(PsiKeyword.VOID);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
@@ -129,13 +127,13 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
private static void checkConstructor(@NotNull PsiClass ownerClass,
|
||||
@NotNull PsiExpression constructorTypeExpression,
|
||||
@NotNull ProblemsHolder holder) {
|
||||
final List<String> constructorSignature = composeMethodSignature(constructorTypeExpression);
|
||||
final ReflectiveSignature constructorSignature = composeMethodSignature(constructorTypeExpression);
|
||||
if (constructorSignature != null) {
|
||||
final List<PsiMethod> constructors = ContainerUtil.filter(ownerClass.getMethods(), PsiMethod::isConstructor);
|
||||
List<List<String>> validSignatures = null;
|
||||
List<ReflectiveSignature> validSignatures = null;
|
||||
if (constructors.isEmpty()) {
|
||||
if (!constructorSignature.equals(NO_ARGUMENT_CONSTRUCTOR_SIGNATURE)) {
|
||||
validSignatures = Collections.singletonList(NO_ARGUMENT_CONSTRUCTOR_SIGNATURE);
|
||||
if (!constructorSignature.equals(ReflectiveSignature.NO_ARGUMENT_CONSTRUCTOR_SIGNATURE)) {
|
||||
validSignatures = Collections.singletonList(ReflectiveSignature.NO_ARGUMENT_CONSTRUCTOR_SIGNATURE);
|
||||
}
|
||||
}
|
||||
else if (!matchMethodSignature(constructors, constructorSignature)) {
|
||||
@@ -222,10 +220,10 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> methodSignature = composeMethodSignature(methodTypeExpression);
|
||||
final ReflectiveSignature methodSignature = composeMethodSignature(methodTypeExpression);
|
||||
if (methodSignature != null && !matchMethodSignature(filteredMethods, methodSignature)) {
|
||||
final String declarationText = getMethodDeclarationText(methodName, methodSignature);
|
||||
final List<List<String>> validSignatures = filteredMethods.stream()
|
||||
final List<ReflectiveSignature> validSignatures = filteredMethods.stream()
|
||||
.map(JavaReflectionReferenceUtil::getMethodSignature)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
@@ -236,31 +234,29 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getMethodDeclarationText(@NotNull String name, @NotNull List<String> methodSignature) {
|
||||
final String argumentTypes = methodSignature.stream().skip(1).collect(Collectors.joining(", "));
|
||||
final String returnType = !methodSignature.isEmpty() ? methodSignature.get(0) : "";
|
||||
return returnType + " " + name + "(" + argumentTypes + ")";
|
||||
private static String getMethodDeclarationText(@NotNull String methodName, @NotNull ReflectiveSignature methodSignature) {
|
||||
final String returnType = methodSignature.getShortReturnType();
|
||||
return returnType + " " + methodName + methodSignature.getShortArgumentTypes();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getConstructorDeclarationText(@NotNull PsiClass ownerClass, @NotNull List<String> methodSignature) {
|
||||
private static String getConstructorDeclarationText(@NotNull PsiClass ownerClass, @NotNull ReflectiveSignature methodSignature) {
|
||||
final String className = ownerClass.getName();
|
||||
if (className != null && !methodSignature.isEmpty()) {
|
||||
if (className != null) {
|
||||
return getConstructorDeclarationText(className, methodSignature);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getConstructorDeclarationText(@NotNull String className, @NotNull List<String> methodSignature) {
|
||||
private static String getConstructorDeclarationText(@NotNull String className, @NotNull ReflectiveSignature methodSignature) {
|
||||
// Return type of the constructor should be 'void'. If it isn't so let's make that mistake more noticeable.
|
||||
final String returnType = methodSignature.get(0);
|
||||
final String returnType = methodSignature.getShortReturnType();
|
||||
final String fakeReturnType = !PsiKeyword.VOID.equals(returnType) ? returnType + " " : "";
|
||||
final String argumentTypes = methodSignature.stream().skip(1).collect(Collectors.joining(", "));
|
||||
return fakeReturnType + className + "(" + argumentTypes + ")";
|
||||
return fakeReturnType + className + methodSignature.getShortArgumentTypes();
|
||||
}
|
||||
|
||||
private static boolean matchMethodSignature(@NotNull List<PsiMethod> methods, @NotNull List<String> expectedMethodSignature) {
|
||||
private static boolean matchMethodSignature(@NotNull List<PsiMethod> methods, @NotNull ReflectiveSignature expectedMethodSignature) {
|
||||
return methods.stream()
|
||||
.map(JavaReflectionReferenceUtil::getMethodSignature)
|
||||
.anyMatch(expectedMethodSignature::equals);
|
||||
@@ -271,13 +267,13 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
* from arguments of MethodType.methodType(Class...) and MethodType.genericMethodType(int, boolean?)
|
||||
*/
|
||||
@Nullable
|
||||
private static List<String> composeMethodSignature(@Nullable PsiExpression methodTypeExpression) {
|
||||
private static ReflectiveSignature composeMethodSignature(@Nullable PsiExpression methodTypeExpression) {
|
||||
final PsiExpression typeDefinition = findDefinition(methodTypeExpression);
|
||||
if (typeDefinition instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)typeDefinition;
|
||||
final String referenceName = methodCallExpression.getMethodExpression().getReferenceName();
|
||||
|
||||
Function<PsiExpression[], List<String>> composer = null;
|
||||
Function<PsiExpression[], ReflectiveSignature> composer = null;
|
||||
if (METHOD_TYPE.equals(referenceName)) {
|
||||
composer = JavaLangInvokeHandleSignatureInspection::composeMethodSignatureFromTypes;
|
||||
}
|
||||
@@ -300,17 +296,16 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<String> composeMethodSignatureFromTypes(@NotNull PsiExpression[] returnAndParameterTypes) {
|
||||
final List<String> typeNames = Arrays.stream(returnAndParameterTypes)
|
||||
.map(JavaReflectionReferenceUtil::getTypeText)
|
||||
.collect(Collectors.toList());
|
||||
return !typeNames.isEmpty() && !typeNames.contains(null) ? typeNames : null;
|
||||
private static ReflectiveSignature composeMethodSignatureFromTypes(@NotNull PsiExpression[] returnAndParameterTypes) {
|
||||
final List<String> typeTexts = ContainerUtil.map(returnAndParameterTypes, JavaReflectionReferenceUtil::getTypeText);
|
||||
return ReflectiveSignature.create(typeTexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* All the types in the method signature are either unbounded type parameters or java.lang.Object (with possible vararg)
|
||||
*/
|
||||
private static List<String> composeGenericMethodSignature(@NotNull PsiExpression[] genericSignatureShape) {
|
||||
@Nullable
|
||||
private static ReflectiveSignature composeGenericMethodSignature(@NotNull PsiExpression[] genericSignatureShape) {
|
||||
if (genericSignatureShape.length == 0 || genericSignatureShape.length > 2) {
|
||||
return null;
|
||||
}
|
||||
@@ -335,7 +330,7 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
if (finalArray) {
|
||||
typeNames.add(CommonClassNames.JAVA_LANG_OBJECT + "[]");
|
||||
}
|
||||
return typeNames;
|
||||
return ReflectiveSignature.create(typeNames);
|
||||
}
|
||||
|
||||
private static class FieldTypeQuickFix implements LocalQuickFix {
|
||||
@@ -404,13 +399,13 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
|
||||
private static class ReplaceSignatureQuickFix extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
private String myName;
|
||||
private List<List<String>> mySignatures;
|
||||
private boolean myIsConstructor;
|
||||
private final String myName;
|
||||
private final List<ReflectiveSignature> mySignatures;
|
||||
private final boolean myIsConstructor;
|
||||
|
||||
public ReplaceSignatureQuickFix(@Nullable PsiElement element,
|
||||
@NotNull String name,
|
||||
@NotNull List<List<String>> signatures,
|
||||
@NotNull List<ReflectiveSignature> signatures,
|
||||
boolean isConstructor) {
|
||||
super(element);
|
||||
myName = name;
|
||||
@@ -449,10 +444,11 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
final PsiElement element = myStartElement.getElement();
|
||||
if (editor != null && element != null) {
|
||||
final List<String> signature = editor.getUserData(DEFAULT_SIGNATURE);
|
||||
final ReflectiveSignature signature = editor.getUserData(DEFAULT_SIGNATURE);
|
||||
if (signature != null && mySignatures.contains(signature)) {
|
||||
applyFix(project, element, signature);
|
||||
}
|
||||
editor.putUserData(POSSIBLE_SIGNATURES, createLookupElements());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -465,17 +461,24 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
}
|
||||
|
||||
private void showLookup(@NotNull Project project, @NotNull Editor editor) {
|
||||
final List<LookupElement> items = mySignatures.stream()
|
||||
@NotNull
|
||||
private List<LookupElement> createLookupElements() {
|
||||
return mySignatures.stream()
|
||||
.sorted(ReflectiveSignature::compareTo)
|
||||
.map(signature -> LookupElementBuilder.create(signature, "")
|
||||
.withIcon(PlatformIcons.METHOD_ICON)
|
||||
.withPresentableText(getDeclarationText(signature)))
|
||||
.withIcon(signature.getIcon())
|
||||
.withPresentableText(myName + signature.getShortArgumentTypes())
|
||||
.withTypeText(!myIsConstructor ? signature.getShortReturnType() : null))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void showLookup(@NotNull Project project, @NotNull Editor editor) {
|
||||
|
||||
// Unfortunately, LookupManager.showLookup() doesn't invoke InsertHandler. A workaround with LookupListener is used.
|
||||
// To let the workaround work we need to make sure that noting is actually replaced by the default behavior of showLookup().
|
||||
editor.getSelectionModel().removeSelection();
|
||||
|
||||
final List<LookupElement> items = createLookupElements();
|
||||
final LookupManager lookupManager = LookupManager.getInstance(project);
|
||||
final LookupEx lookup = lookupManager.showLookup(editor, items.toArray(LookupElement.EMPTY_ARRAY));
|
||||
if (lookup != null) {
|
||||
@@ -486,9 +489,8 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
if (item != null) {
|
||||
final PsiElement element = myStartElement.getElement();
|
||||
final Object object = item.getObject();
|
||||
if (element != null && object instanceof List) {
|
||||
@SuppressWarnings("unchecked") final List<String> signature = (List<String>)object;
|
||||
WriteAction.run(() -> applyFix(project, element, signature));
|
||||
if (element != null && object instanceof ReflectiveSignature) {
|
||||
WriteAction.run(() -> applyFix(project, element, (ReflectiveSignature)object));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -496,7 +498,7 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyFix(@NotNull Project project, @NotNull PsiElement element, @NotNull List<String> signature) {
|
||||
private static void applyFix(@NotNull Project project, @NotNull PsiElement element, @NotNull ReflectiveSignature signature) {
|
||||
final String replacementText = getMethodTypeExpressionText(signature);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
final PsiExpression replacement = factory.createExpressionFromText(replacementText, element);
|
||||
@@ -505,14 +507,14 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getDeclarationText(@NotNull List<String> signature) {
|
||||
private String getDeclarationText(@NotNull ReflectiveSignature signature) {
|
||||
return myIsConstructor ? getConstructorDeclarationText(myName, signature) : getMethodDeclarationText(myName, signature);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LocalQuickFix createFix(@Nullable PsiElement element,
|
||||
@NotNull String methodName,
|
||||
@NotNull List<List<String>> methodSignatures,
|
||||
@NotNull List<ReflectiveSignature> methodSignatures,
|
||||
boolean isConstructor, boolean isOnTheFly) {
|
||||
if (isOnTheFly && !methodSignatures.isEmpty() || methodSignatures.size() == 1) {
|
||||
return new ReplaceSignatureQuickFix(element, methodName, methodSignatures, isConstructor);
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -181,7 +180,7 @@ public class JavaLangInvokeHandleReference extends PsiReferenceBase<PsiLiteralEx
|
||||
final Object object = item.getObject();
|
||||
|
||||
if (object instanceof PsiMethod) {
|
||||
final List<String> signature = getMethodSignature((PsiMethod)object);
|
||||
final ReflectiveSignature signature = getMethodSignature((PsiMethod)object);
|
||||
if (signature != null) {
|
||||
final String text = ", " + getMethodTypeExpressionText(signature);
|
||||
replaceText(context, text);
|
||||
|
||||
@@ -20,24 +20,30 @@ import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
|
||||
import com.intellij.codeInsight.completion.PrioritizedLookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
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.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author Pavel.Dolgov
|
||||
@@ -281,7 +287,7 @@ public class JavaReflectionReferenceUtil {
|
||||
|
||||
@Contract("null -> null")
|
||||
@Nullable
|
||||
public static List<String> getMethodSignature(@Nullable PsiMethod method) {
|
||||
public static ReflectiveSignature getMethodSignature(@Nullable PsiMethod method) {
|
||||
if (method != null) {
|
||||
final List<String> types = new ArrayList<>();
|
||||
final PsiType returnType = !method.isConstructor() ? method.getReturnType() : PsiType.VOID;
|
||||
@@ -290,15 +296,14 @@ public class JavaReflectionReferenceUtil {
|
||||
for (PsiParameter parameter : method.getParameterList().getParameters()) {
|
||||
types.add(getTypeText(parameter.getType(), method));
|
||||
}
|
||||
if (!types.contains(null)) {
|
||||
return types;
|
||||
}
|
||||
final Icon icon = method.getIcon(Iconable.ICON_FLAG_VISIBILITY);
|
||||
return ReflectiveSignature.create(icon, types);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getMethodTypeExpressionText(@NotNull List<String> signature) {
|
||||
public static String getMethodTypeExpressionText(@NotNull ReflectiveSignature signature) {
|
||||
final String types = signature.stream()
|
||||
.map(text -> text + ".class")
|
||||
.collect(Collectors.joining(", "));
|
||||
@@ -388,4 +393,91 @@ public class JavaReflectionReferenceUtil {
|
||||
return psiClass != null ? new ReflectiveType(psiClass, null, 0) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReflectiveSignature implements Comparable<ReflectiveSignature> {
|
||||
public static final ReflectiveSignature NO_ARGUMENT_CONSTRUCTOR_SIGNATURE =
|
||||
new ReflectiveSignature(null, PsiKeyword.VOID, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
|
||||
private final Icon myIcon;
|
||||
@NotNull private final String myReturnType;
|
||||
@NotNull private final String[] myArgumentTypes;
|
||||
|
||||
@Nullable
|
||||
public static ReflectiveSignature create(@NotNull List<String> typeTexts) {
|
||||
return create(null, typeTexts);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ReflectiveSignature create(@Nullable Icon icon, @NotNull List<String> typeTexts) {
|
||||
if (!typeTexts.isEmpty() && !typeTexts.contains(null)) {
|
||||
final String[] argumentTypes = ArrayUtil.toStringArray(typeTexts.subList(1, typeTexts.size()));
|
||||
return new ReflectiveSignature(icon, typeTexts.get(0), argumentTypes);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ReflectiveSignature(@Nullable Icon icon, @NotNull String returnType, @NotNull String[] argumentTypes) {
|
||||
myIcon = icon;
|
||||
myReturnType = returnType;
|
||||
myArgumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Stream<String> stream() {
|
||||
return Stream.concat(Stream.of(myReturnType), Arrays.stream(myArgumentTypes));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getShortReturnType() {
|
||||
return getShortTypeText(myReturnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getShortArgumentTypes() {
|
||||
final StringJoiner joiner = new StringJoiner(", ", "(", ")");
|
||||
for (String argumentType : myArgumentTypes) {
|
||||
joiner.add(getShortTypeText(argumentType));
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getShortTypeText(String text) {
|
||||
final int pos = text.lastIndexOf('.');
|
||||
return pos < 0 ? text : text.substring(pos + 1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Icon getIcon() {
|
||||
return myIcon != null ? myIcon : PlatformIcons.METHOD_ICON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull ReflectiveSignature other) {
|
||||
int c = myArgumentTypes.length - other.myArgumentTypes.length;
|
||||
if (c != 0) return c;
|
||||
c = ArrayUtil.lexicographicCompare(myArgumentTypes, other.myArgumentTypes);
|
||||
if (c != 0) return c;
|
||||
return myReturnType.compareTo(other.myReturnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ReflectiveSignature)) return false;
|
||||
final ReflectiveSignature other = (ReflectiveSignature)o;
|
||||
return Objects.equals(myReturnType, other.myReturnType) &&
|
||||
Arrays.equals(myArgumentTypes, other.myArgumentTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(myReturnType, myArgumentTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myReturnType + " " + Arrays.toString(myArgumentTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Test()
|
||||
// Test(int)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -8,6 +10,6 @@ class Main {
|
||||
}
|
||||
|
||||
class Test {
|
||||
public Test() {}
|
||||
public Test(int a) {}
|
||||
public Test() {}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// Test(int)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Test()
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Test()
|
||||
// Test(int)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -9,6 +12,6 @@ class Main {
|
||||
|
||||
class Test {
|
||||
public <T> T method(T a) {return null;}
|
||||
public <T> T method(T a, T... b) {return null;}
|
||||
public <T> T method(T a, String b) {return null;}
|
||||
public <T> T method(T a, T... b) {return null;}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
public class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -9,6 +12,6 @@ class Main {
|
||||
|
||||
class Test {
|
||||
public void method() {}
|
||||
public String method(String a) {return a;}
|
||||
public String method(String a, String... b) {return a;}
|
||||
public String method(String a) {return a;}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -8,7 +11,7 @@ class Main {
|
||||
}
|
||||
|
||||
class Test {
|
||||
public String method(String a, String... b) {return a;}
|
||||
public void method() {}
|
||||
public String method(String a) {return a;}
|
||||
public String method(String a, String... b) {return a;}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// Test()
|
||||
// Test(int)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -8,6 +10,6 @@ class Main {
|
||||
}
|
||||
|
||||
class Test {
|
||||
public Test() {}
|
||||
public Test(int a) {}
|
||||
public Test() {}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// Test(int)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Test()
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Test()
|
||||
// Test(int)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -9,6 +12,6 @@ class Main {
|
||||
|
||||
class Test {
|
||||
public <T> T method(T a) {return null;}
|
||||
public <T> T method(T a, T... b) {return null;}
|
||||
public <T> T method(T a, String b) {return null;}
|
||||
public <T> T method(T a, T... b) {return null;}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Object method(Object)
|
||||
// Object method(Object, Object[])
|
||||
// Object method(Object, String)
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
public class Main {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -9,6 +12,6 @@ class Main {
|
||||
|
||||
class Test {
|
||||
public void method() {}
|
||||
public String method(String a) {return a;}
|
||||
public String method(String a, String... b) {return a;}
|
||||
public String method(String a) {return a;}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
// void method()
|
||||
// String method(String)
|
||||
// String method(String, String[])
|
||||
import java.lang.invoke.*;
|
||||
|
||||
class Main {
|
||||
@@ -8,7 +11,7 @@ class Main {
|
||||
}
|
||||
|
||||
class Test {
|
||||
public String method(String a, String... b) {return a;}
|
||||
public void method() {}
|
||||
public String method(String a) {return a;}
|
||||
public String method(String a, String... b) {return a;}
|
||||
}
|
||||
@@ -17,9 +17,15 @@ package com.intellij.codeInsight.daemon.quickFix
|
||||
|
||||
import com.intellij.JavaTestUtil
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||
import com.intellij.codeInspection.InspectionsBundle.message
|
||||
import com.intellij.codeInspection.reflectiveAccess.JavaLangInvokeHandleSignatureInspection
|
||||
import com.intellij.codeInspection.reflectiveAccess.JavaLangInvokeHandleSignatureInspection.DEFAULT_SIGNATURE
|
||||
import com.intellij.codeInspection.reflectiveAccess.JavaLangInvokeHandleSignatureInspection.POSSIBLE_SIGNATURES
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil.ReflectiveSignature
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
|
||||
@@ -64,12 +70,13 @@ class JavaLangInvokeMethodHandleSignatureFixTest : LightCodeInsightFixtureTestCa
|
||||
|
||||
fun doTest(actionPrefix: String, vararg withSignature: String) {
|
||||
val testName = getTestName(false)
|
||||
myFixture.configureByFile("before$testName.java")
|
||||
val file = myFixture.configureByFile("before$testName.java")
|
||||
|
||||
val action = findAction(actionPrefix)
|
||||
val signature = listOf(*withSignature)
|
||||
val signature = ReflectiveSignature.create(listOf(*withSignature)) ?: ReflectiveSignature.NO_ARGUMENT_CONSTRUCTOR_SIGNATURE
|
||||
|
||||
launchAction(action, signature)
|
||||
val lookupElements = launchAction(action, signature)
|
||||
checkLookupElements(file, lookupElements)
|
||||
myFixture.checkResultByFile("after$testName.java")
|
||||
}
|
||||
|
||||
@@ -93,16 +100,33 @@ class JavaLangInvokeMethodHandleSignatureFixTest : LightCodeInsightFixtureTestCa
|
||||
return familyActions[0]
|
||||
}
|
||||
|
||||
private fun launchAction(action: IntentionAction, signature: List<String>) {
|
||||
private fun launchAction(action: IntentionAction, signature: ReflectiveSignature): List<LookupElement>? {
|
||||
myFixture.editor.putUserData(DEFAULT_SIGNATURE, signature)
|
||||
try {
|
||||
myFixture.launchAction(action)
|
||||
return myFixture.editor.getUserData(POSSIBLE_SIGNATURES)
|
||||
}
|
||||
finally {
|
||||
myFixture.editor.putUserData(DEFAULT_SIGNATURE, null)
|
||||
myFixture.editor.putUserData(POSSIBLE_SIGNATURES, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkLookupElements(file: PsiFile?, lookupElements: List<LookupElement>?) {
|
||||
val expected = (file?.children ?: arrayOf())
|
||||
.filter { it is PsiComment }
|
||||
.map { it.text.removePrefix("//").trim() }
|
||||
|
||||
val actual = (lookupElements ?: listOf())
|
||||
.map {
|
||||
val presentation = LookupElementPresentation()
|
||||
it.renderElement(presentation)
|
||||
val typeText = presentation.typeText
|
||||
if (typeText != null) "${typeText} ${presentation.itemText}" else presentation.itemText
|
||||
}
|
||||
assertEquals("Popup menu", expected, actual)
|
||||
}
|
||||
|
||||
private val VOID = "void"
|
||||
private val INT = "int"
|
||||
private val OBJECT = "java.lang.Object"
|
||||
|
||||
Reference in New Issue
Block a user