From 25afffeb7035dc41bc4e6123ca9b66e768c5a8fc Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Thu, 23 Mar 2017 13:12:16 +0300 Subject: [PATCH] Java: Filter by 'static' modifier in MethodHandle/VarHandle completion assistance (IDEA-167319, IDEA-CR-19610) --- ...vaLangInvokeHandleSignatureInspection.java | 20 +++++++++---------- ...JavaMethodHandleCompletionContributor.java | 18 +++++++++++------ .../completion/invokeHandle/StaticType.java | 2 +- .../invokeHandle/StaticType_after.java | 2 +- .../invokeHandleSignature/Getter.java | 3 +++ .../OverloadedMethod.java | 2 +- .../invokeHandleSignature/Setter.java | 3 +++ .../invokeHandleSignature/StaticMethod.java | 2 +- .../invokeHandleSignature/VarHandle.java | 3 +++ .../JavaLangInvokeHandleCompletionTest.kt | 20 +++++++++++-------- 10 files changed, 47 insertions(+), 28 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/reflectiveAccess/JavaLangInvokeHandleSignatureInspection.java b/java/java-impl/src/com/intellij/codeInspection/reflectiveAccess/JavaLangInvokeHandleSignatureInspection.java index 4da7fb00204f..e4a41936eb87 100644 --- a/java/java-impl/src/com/intellij/codeInspection/reflectiveAccess/JavaLangInvokeHandleSignatureInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/reflectiveAccess/JavaLangInvokeHandleSignatureInspection.java @@ -161,7 +161,7 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI @NotNull String fieldName, @NotNull PsiExpression fieldNameExpression, @NotNull PsiExpression fieldTypeExpression, - boolean isStatic, + boolean isStaticExpected, @NotNull PsiReferenceExpression factoryMethodExpression, @NotNull ProblemsHolder holder) { final PsiField field = ownerClass.findFieldByName(fieldName, true); @@ -170,13 +170,13 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI return; } - if (field.hasModifierProperty(PsiModifier.STATIC) != isStatic) { + if (field.hasModifierProperty(PsiModifier.STATIC) != isStaticExpected) { final String factoryMethodName = factoryMethodExpression.getReferenceName(); final PsiElement factoryMethodNameElement = factoryMethodExpression.getReferenceNameElement(); if (factoryMethodName != null && factoryMethodNameElement != null) { - final LocalQuickFix fix = SwitchStaticnessQuickFix.createFix(factoryMethodName, isStatic); + final LocalQuickFix fix = SwitchStaticnessQuickFix.createFix(factoryMethodName, isStaticExpected); final String message = InspectionsBundle.message( - isStatic ? "inspection.handle.signature.field.static" : "inspection.handle.signature.field.not.static", fieldName); + isStaticExpected ? "inspection.handle.signature.field.not.static" : "inspection.handle.signature.field.static", fieldName); holder.registerProblem(factoryMethodNameElement, message, fix); return; } @@ -196,7 +196,7 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI @NotNull String methodName, @NotNull PsiExpression methodNameExpression, @NotNull PsiExpression methodTypeExpression, - boolean isStatic, + boolean isStaticExpected, @NotNull PsiReferenceExpression factoryMethodExpression, @NotNull ProblemsHolder holder) { @@ -207,14 +207,14 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI } final List filteredMethods = - ContainerUtil.filter(methods, method -> method.hasModifierProperty(PsiModifier.STATIC) == isStatic); + ContainerUtil.filter(methods, method -> method.hasModifierProperty(PsiModifier.STATIC) == isStaticExpected); if (filteredMethods.isEmpty()) { final String factoryMethodName = factoryMethodExpression.getReferenceName(); final PsiElement factoryMethodNameElement = factoryMethodExpression.getReferenceNameElement(); if (factoryMethodName != null && factoryMethodNameElement != null) { - final LocalQuickFix fix = SwitchStaticnessQuickFix.createFix(factoryMethodName, isStatic); + final LocalQuickFix fix = SwitchStaticnessQuickFix.createFix(factoryMethodName, isStaticExpected); final String message = InspectionsBundle.message( - isStatic ? "inspection.handle.signature.method.static" : "inspection.handle.signature.method.not.static", methodName); + isStaticExpected ? "inspection.handle.signature.method.not.static" : "inspection.handle.signature.method.static", methodName); holder.registerProblem(factoryMethodNameElement, message, fix); return; } @@ -392,8 +392,8 @@ public class JavaLangInvokeHandleSignatureInspection extends BaseJavaBatchLocalI } @Nullable - public static LocalQuickFix createFix(@NotNull String methodName, boolean isStatic) { - final String replacementName = isStatic ? STATIC_TO_NON_STATIC.get(methodName) : NON_STATIC_TO_STATIC.get(methodName); + public static LocalQuickFix createFix(@NotNull String methodName, boolean wasStatic) { + final String replacementName = wasStatic ? STATIC_TO_NON_STATIC.get(methodName) : NON_STATIC_TO_STATIC.get(methodName); return replacementName != null ? new SwitchStaticnessQuickFix(replacementName) : null; } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaMethodHandleCompletionContributor.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaMethodHandleCompletionContributor.java index 79a02edbbfa6..81a6d6c1207c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaMethodHandleCompletionContributor.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaMethodHandleCompletionContributor.java @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.intellij.codeInsight.completion.JavaCompletionContributor.isInJavaContext; import static com.intellij.patterns.PsiJavaPatterns.*; @@ -105,7 +106,7 @@ public class JavaMethodHandleCompletionContributor extends CompletionContributor case FIND_SPECIAL: final String name = arguments.length > 1 ? computeConstantExpression(arguments[1], String.class) : null; if (!StringUtil.isEmpty(name)) { - addMethodSignatures(psiClass, name, result); + addMethodSignatures(psiClass, name, FIND_STATIC.equals(methodName), result); } break; } @@ -119,7 +120,7 @@ public class JavaMethodHandleCompletionContributor extends CompletionContributor if (className != null) { final PsiMethod[] constructors = psiClass.getConstructors(); if (constructors.length != 0) { - lookupMethodTypes(constructors, result); + lookupMethodTypes(Arrays.stream(constructors), result); } else { result.addElement(lookupSignature(ReflectiveSignature.NO_ARGUMENT_CONSTRUCTOR_SIGNATURE)); @@ -127,15 +128,20 @@ public class JavaMethodHandleCompletionContributor extends CompletionContributor } } - private static void addMethodSignatures(@NotNull PsiClass psiClass, @NotNull String methodName, @NotNull CompletionResultSet result) { + private static void addMethodSignatures(@NotNull PsiClass psiClass, + @NotNull String methodName, + boolean isStaticExpected, + @NotNull CompletionResultSet result) { final PsiMethod[] methods = psiClass.findMethodsByName(methodName, false); if (methods.length != 0) { - lookupMethodTypes(methods, result); + final Stream methodStream = Arrays.stream(methods) + .filter(method -> method.hasModifierProperty(PsiModifier.STATIC) == isStaticExpected); + lookupMethodTypes(methodStream, result); } } - private static void lookupMethodTypes(@NotNull PsiMethod[] methods, @NotNull CompletionResultSet result) { - Arrays.stream(methods) + private static void lookupMethodTypes(@NotNull Stream methods, @NotNull CompletionResultSet result) { + methods .map(JavaReflectionReferenceUtil::getMethodSignature) .filter(Objects::nonNull) .sorted(ReflectiveSignature::compareTo) diff --git a/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType.java b/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType.java index f4340a93089c..e4a5b4e47f52 100644 --- a/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType.java +++ b/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType.java @@ -3,6 +3,6 @@ import java.lang.invoke.*; public class Main { void foo() throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); - lookup.findStatic(Types.class, "sObjMethod", ); + lookup.findStatic(Types.class, "objMethod", ); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType_after.java b/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType_after.java index bc1a5088d8dd..5e8bbfbbf05d 100644 --- a/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType_after.java +++ b/java/java-tests/testData/codeInsight/completion/invokeHandle/StaticType_after.java @@ -3,6 +3,6 @@ import java.lang.invoke.*; public class Main { void foo() throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); - lookup.findStatic(Types.class, "sObjMethod", MethodType.methodType(Object.class, Object.class)); + lookup.findStatic(Types.class, "objMethod", MethodType.methodType(Object.class, Object.class)); } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/invokeHandleSignature/Getter.java b/java/java-tests/testData/inspection/invokeHandleSignature/Getter.java index 56e4a8a9dda7..743af3af1084 100644 --- a/java/java-tests/testData/inspection/invokeHandleSignature/Getter.java +++ b/java/java-tests/testData/inspection/invokeHandleSignature/Getter.java @@ -27,6 +27,9 @@ class Main { l.findStaticGetter(Test.class, "ourInt", void.class); l.findStaticGetter(Test.class, "ourInts", int.class); l.findStaticGetter(Test.class, "ourString", List.class); + + l.findGetter(Test.class, "ourString", String.class); + l.findStaticGetter(Test.class, "myString", String.class); } } diff --git a/java/java-tests/testData/inspection/invokeHandleSignature/OverloadedMethod.java b/java/java-tests/testData/inspection/invokeHandleSignature/OverloadedMethod.java index 1e3238435ab1..34f249d17360 100644 --- a/java/java-tests/testData/inspection/invokeHandleSignature/OverloadedMethod.java +++ b/java/java-tests/testData/inspection/invokeHandleSignature/OverloadedMethod.java @@ -23,7 +23,7 @@ class Main { l.findVirtual(Test.class, "method", MethodType.methodType(Object[].class, Object[].class)); l.findVirtual(Test.class, "method", MethodType.methodType(Object[][].class, Object[][].class)); - l.findStatic(Test.class, "method", MethodType.methodType(void.class)); + l.findStatic(Test.class, "method", MethodType.methodType(void.class)); l.findVirtual(Test.class, "doesntExist", MethodType.methodType(void.class)); } } diff --git a/java/java-tests/testData/inspection/invokeHandleSignature/Setter.java b/java/java-tests/testData/inspection/invokeHandleSignature/Setter.java index 570fc69aaca8..c6ccb0d17afc 100644 --- a/java/java-tests/testData/inspection/invokeHandleSignature/Setter.java +++ b/java/java-tests/testData/inspection/invokeHandleSignature/Setter.java @@ -27,6 +27,9 @@ class Main { l.findStaticSetter(Test.class, "ourInt", void.class); l.findStaticSetter(Test.class, "ourInts", int.class); l.findStaticSetter(Test.class, "ourString", List.class); + + l.findStaticSetter(Test.class, "myString", String.class); + l.findSetter(Test.class, "ourString", String.class); } } diff --git a/java/java-tests/testData/inspection/invokeHandleSignature/StaticMethod.java b/java/java-tests/testData/inspection/invokeHandleSignature/StaticMethod.java index fd1366cbee14..cc56ec686d6e 100644 --- a/java/java-tests/testData/inspection/invokeHandleSignature/StaticMethod.java +++ b/java/java-tests/testData/inspection/invokeHandleSignature/StaticMethod.java @@ -12,7 +12,7 @@ class Main { l.findStatic(Test.class, "method2", MethodType.methodType(int.class, String.class)); l.findStatic(Test.class, "method3", MethodType.methodType(String.class)); - l.findVirtual(Test.class, "method1", MethodType.methodType(void.class)); + l.findVirtual(Test.class, "method1", MethodType.methodType(void.class)); l.findStatic(Test.class, "doesntExist", MethodType.methodType(String.class)); } } diff --git a/java/java-tests/testData/inspection/invokeHandleSignature/VarHandle.java b/java/java-tests/testData/inspection/invokeHandleSignature/VarHandle.java index 15cdf0c5db08..b72214be0278 100644 --- a/java/java-tests/testData/inspection/invokeHandleSignature/VarHandle.java +++ b/java/java-tests/testData/inspection/invokeHandleSignature/VarHandle.java @@ -27,6 +27,9 @@ class Main { l.findStaticVarHandle(Test.class, "ourInt", void.class); l.findStaticVarHandle(Test.class, "ourInts", int.class); l.findStaticVarHandle(Test.class, "ourString", List.class); + + l.findStaticVarHandle(Test.class, "myString", String.class); + l.findVarHandle(Test.class, "ourString", String.class); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaLangInvokeHandleCompletionTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaLangInvokeHandleCompletionTest.kt index 4e50cffedb77..90a09de7b66e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaLangInvokeHandleCompletionTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaLangInvokeHandleCompletionTest.kt @@ -45,8 +45,10 @@ class JavaLangInvokeHandleCompletionTest : LightFixtureCompletionTestCase() { fun testStaticVarHandle() = doTest(0, "psf1", "sf1", "sf2") - fun testVirtualType() = doTestTypes(0, "MethodType.methodType(String.class)") - fun testStaticType() = doTestTypes(0, "MethodType.methodType(Object.class, Object.class)") + fun testVirtualType() = doTestTypes(0, "MethodType.methodType(String.class)", "MethodType.methodType(String.class, int.class, int.class)") + fun testStaticType() = doTestTypes(1, + "MethodType.methodType(Object.class, int.class, int.class)", + "MethodType.methodType(Object.class, Object.class)") fun testGetterType() = doTestTypes(0, "int.class") fun testSetterType() = doTestTypes(0, "float.class") @@ -86,7 +88,13 @@ public class Types extends Parent { static Object sObj; String strMethod() {return "";} - static Object sObjMethod(Object o) {return this;} + String strMethod(int n, int m) {return "";} + static String strMethod(int n) {return "";} + + static Object objMethod(Object o) {return o;} + static Object objMethod(int n, int m) {return n;} + Object objMethod(int n) {return n;} + T genericMethod(T t, String s) {return t;} static T sGenericMethod(List lst, T... ts) {return ts[0];} }""") @@ -105,11 +113,7 @@ public class Constructed { private fun assertLookupTexts(compareFirst: Boolean, vararg expected: String) { val elements = myFixture.lookupElements assertNotNull(elements) - val lookupTexts = elements!!.map { - val presentation = LookupElementPresentation() - it.renderElement(presentation) - presentation.itemText - } + val lookupTexts = elements!!.map { LookupElementPresentation.renderElement(it).itemText } val actual = if (compareFirst) lookupTexts.subList(0, Math.min(expected.size, lookupTexts.size)) else lookupTexts assertOrderedEquals(actual, *expected)