mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
Java: Avoid duplicates for shadowed members in completion list for arguments of reflection calls. Simplify building the list of method names with PsiClass.getVisibleSignatures() (IDEA-167250)
This commit is contained in:
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -30,7 +31,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil.*;
|
||||
@@ -119,16 +119,19 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
|
||||
|
||||
case DECLARED_FIELD:
|
||||
return Arrays.stream(psiClass.getFields())
|
||||
.filter(field -> field.getName() != null)
|
||||
.sorted(Comparator.comparing(PsiField::getName))
|
||||
.map(field -> lookupField(field))
|
||||
.toArray();
|
||||
|
||||
case FIELD:
|
||||
case FIELD: {
|
||||
final Set<String> uniqueNames = new THashSet<>();
|
||||
return Arrays.stream(psiClass.getAllFields())
|
||||
.filter(field -> isPotentiallyAccessible(field, psiClass))
|
||||
.filter(field -> isPotentiallyAccessible(field, psiClass) && field.getName() != null && uniqueNames.add(field.getName()))
|
||||
.sorted(Comparator.comparingInt((PsiField field) -> isPublic(field) ? 0 : 1).thenComparing(PsiField::getName))
|
||||
.map(field -> withPriority(lookupField(field), isPublic(field)))
|
||||
.toArray();
|
||||
}
|
||||
|
||||
case DECLARED_METHOD:
|
||||
return Arrays.stream(psiClass.getMethods())
|
||||
@@ -138,16 +141,10 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
|
||||
.toArray();
|
||||
|
||||
case METHOD: {
|
||||
final List<PsiMethod> methods = ContainerUtil.filter(
|
||||
psiClass.getAllMethods(), method -> isRegularMethod(method) && isPotentiallyAccessible(method, psiClass));
|
||||
|
||||
final Set<PsiMethod> superMethods = new THashSet<>();
|
||||
for (PsiMethod method : methods) {
|
||||
ContainerUtil.addAll(superMethods, method.findSuperMethods());
|
||||
}
|
||||
|
||||
return methods.stream()
|
||||
.filter(method -> !superMethods.contains(method))
|
||||
return psiClass.getVisibleSignatures()
|
||||
.stream()
|
||||
.map(MethodSignatureBackedByPsiMethod::getMethod)
|
||||
.filter(method -> isRegularMethod(method) && isPotentiallyAccessible(method, psiClass))
|
||||
.sorted(Comparator.comparingInt((PsiMethod method) -> getMethodSortOrder(method)).thenComparing(PsiMethod::getName))
|
||||
.map(method -> withPriority(lookupMethod(method), -getMethodSortOrder(method)))
|
||||
.toArray();
|
||||
|
||||
@@ -23,4 +23,5 @@ class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
int num1;
|
||||
private int num0;
|
||||
}
|
||||
@@ -23,4 +23,5 @@ class Test {
|
||||
public int num;
|
||||
public int num2;
|
||||
int num1;
|
||||
private int num0;
|
||||
}
|
||||
@@ -23,6 +23,7 @@ class Test {
|
||||
public void method(){}
|
||||
public void method2(A a, B b){}
|
||||
void method1(){}
|
||||
private void method0(C c) {}
|
||||
}
|
||||
|
||||
class A {}
|
||||
|
||||
@@ -23,6 +23,7 @@ class Test {
|
||||
public void method(){}
|
||||
public void method2(A a, B b){}
|
||||
void method1(){}
|
||||
private void method0(C c) {}
|
||||
}
|
||||
|
||||
class A {}
|
||||
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
int num3;
|
||||
private int num5;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
private int num6;
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
int num3;
|
||||
private int num5;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
private int num6;
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
private void method5(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
private void method6(){}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
private void method5(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
private void method6(){}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
void int num3;
|
||||
private int num5;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
private int num6;
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public int num;
|
||||
void int num3;
|
||||
private int num5;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int num2;
|
||||
int num4;
|
||||
private int num6;
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
private void method5(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
private void method6(){}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ class Main {
|
||||
class Test extends Parent {
|
||||
public void method(){}
|
||||
void method3(){}
|
||||
private void method5(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public void method2(){}
|
||||
void method4(){}
|
||||
private void method6(){}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public int shadowed;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int shadowed;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getField("shadowed");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public int shadowed;
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public int shadowed;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getField("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
}
|
||||
|
||||
class Parent extends Grand {
|
||||
public int shadowed;
|
||||
}
|
||||
|
||||
class Grand extends GrandGrand {
|
||||
public int shadowed;
|
||||
}
|
||||
|
||||
class GrandGrand {
|
||||
public int shadowed;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getField("shadowed");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
}
|
||||
|
||||
class Parent extends Grand {
|
||||
public int shadowed;
|
||||
}
|
||||
|
||||
class Grand extends GrandGrand {
|
||||
public int shadowed;
|
||||
}
|
||||
|
||||
class GrandGrand {
|
||||
public int shadowed;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public static void overloaded(int n){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public static void overloaded(String s){}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("overloaded", String.class);
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public static void overloaded(int n){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public static void overloaded(String s){}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void overloaded(){}
|
||||
public void overloaded(int n){}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("overloaded", int.class);
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
public void overloaded(){}
|
||||
public void overloaded(int n){}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("<caret>");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public static void shadowed(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public static void shadowed(){}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Main {
|
||||
void foo() {
|
||||
Test.class.getMethod("shadowed");
|
||||
}
|
||||
}
|
||||
|
||||
class Test extends Parent {
|
||||
public static void shadowed(){}
|
||||
}
|
||||
|
||||
class Parent {
|
||||
public static void shadowed(){}
|
||||
}
|
||||
@@ -45,6 +45,18 @@ class JavaReflectionCompletionOverloadTest : LightFixtureCompletionTestCase() {
|
||||
"gpMethod(A a,B b)", "method()", "pMethod(C c)",
|
||||
"equals(java.lang.Object obj)")
|
||||
|
||||
fun testShadowedMethod() = doTest(0,
|
||||
"shadowed()",
|
||||
"equals(java.lang.Object obj)")
|
||||
|
||||
fun testOverloadedMethod() = doTest(1,
|
||||
"overloaded()", "overloaded(int n)",
|
||||
"equals(java.lang.Object obj)")
|
||||
|
||||
fun testOverloadedInheritedMethod() = doTest(1,
|
||||
"overloaded(int n)", "overloaded(java.lang.String s)",
|
||||
"equals(java.lang.Object obj)")
|
||||
|
||||
|
||||
private fun doTest(index: Int, vararg expected: String) {
|
||||
configureByFile(getTestName(false) + ".java")
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -34,11 +35,11 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
}
|
||||
|
||||
public void testDeclaredField() throws Exception {
|
||||
doTest(2, "num", "num1", "num2");
|
||||
doTest(2, "num", "num1", "num2", "num0");
|
||||
}
|
||||
|
||||
public void testDeclaredMethod() throws Exception {
|
||||
doTest(2, "method", "method1", "method2");
|
||||
doTest(2, "method", "method1", "method2", "method0");
|
||||
}
|
||||
|
||||
public void testDeclaredMethod2() throws Exception {
|
||||
@@ -46,7 +47,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
}
|
||||
|
||||
public void testMethod() throws Exception {
|
||||
doTest(1, "method", "method2", "method3");
|
||||
doTestFirst(1, "method", "method2", "method3");
|
||||
}
|
||||
|
||||
public void testForNameDeclaredMethod() throws Exception {
|
||||
@@ -54,7 +55,7 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
}
|
||||
|
||||
public void testForNameMethod() throws Exception {
|
||||
doTest(1, "method", "method2", "method3");
|
||||
doTestFirst(1, "method", "method2", "method3");
|
||||
}
|
||||
|
||||
public void testForNameField() throws Exception {
|
||||
@@ -71,31 +72,39 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
|
||||
public void testGenerics() throws Exception {
|
||||
myFixture.addFileToProject("a.properties", "foo=bar"); // check that property variants don't override reflection ones
|
||||
doTest(0, "foo");
|
||||
doTestFirst(0, "foo");
|
||||
}
|
||||
|
||||
public void testInheritedMethod() throws Exception {
|
||||
doTest(1, "method", "method2", "method3");
|
||||
doTestFirst(1, "method", "method2", "method3", "method5");
|
||||
}
|
||||
|
||||
public void testInheritedDeclaredMethod() throws Exception {
|
||||
doTest(1, "method", "method3");
|
||||
doTest(1, "method", "method3", "method5");
|
||||
}
|
||||
|
||||
public void testInheritedField() throws Exception {
|
||||
doTest(1, "num", "num2", "num3");
|
||||
doTest(1, "num", "num2", "num3", "num5");
|
||||
}
|
||||
|
||||
public void testInheritedDeclaredField() throws Exception {
|
||||
doTest(1, "num", "num3");
|
||||
doTest(1, "num", "num3", "num5");
|
||||
}
|
||||
|
||||
public void testShadowedField() {
|
||||
doTest(0, "shadowed");
|
||||
}
|
||||
|
||||
public void testShadowedSuperField() {
|
||||
doTest(0, "shadowed");
|
||||
}
|
||||
|
||||
public void testInitRaw() throws Exception {
|
||||
doTest(1, "method", "method2");
|
||||
doTestFirst(1, "method", "method2");
|
||||
}
|
||||
|
||||
public void testInitWithType() throws Exception {
|
||||
doTest(1, "method", "method2");
|
||||
doTestFirst(1, "method", "method2");
|
||||
}
|
||||
|
||||
public void testInitChain() throws Exception {
|
||||
@@ -115,15 +124,15 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
}
|
||||
|
||||
public void testJdk14() throws Exception {
|
||||
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_4, () -> doTest(0, "method"));
|
||||
IdeaTestUtil.withLevel(myFixture.getModule(), LanguageLevel.JDK_1_4, () -> doTestFirst(0, "method"));
|
||||
}
|
||||
|
||||
public void testWildcard() throws Exception {
|
||||
doTest(0, "method");
|
||||
doTestFirst(0, "method");
|
||||
}
|
||||
|
||||
public void testConstantMethod() throws Exception {
|
||||
doTest(0, "method", "method2");
|
||||
doTestFirst(0, "method", "method2");
|
||||
}
|
||||
|
||||
public void testDistantDefinition() throws Exception {
|
||||
@@ -166,13 +175,21 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
}
|
||||
|
||||
public void testHasConstructor() {
|
||||
doTest(2, "method", "method2", "method1");
|
||||
doTestFirst(2, "method", "method2", "method1");
|
||||
}
|
||||
|
||||
|
||||
private void doTest(int index, String... expected) {
|
||||
doTest(index, () -> assertStringItems(expected));
|
||||
}
|
||||
|
||||
private void doTestFirst(int index, String... expected) {
|
||||
doTest(index, () -> assertFirstStringItems(ArrayUtil.mergeArrays(expected, "equals")));
|
||||
}
|
||||
|
||||
private void doTest(int index, Runnable assertion) {
|
||||
configureByFile(getTestName(false) + ".java");
|
||||
assertFirstStringItems(expected);
|
||||
assertion.run();
|
||||
if (index >= 0) selectItem(getLookup().getItems().get(index));
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user