From d55416e473d9e13a9884e05da3b086a80aceb39c Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Tue, 4 Jul 2017 11:17:59 +0300 Subject: [PATCH] java smart completion sorting: split getter kind into 3 kinds with different priority (getter should have a higher priority then any relevant method chain) --- .../completion/PreferByKindWeigher.java | 23 +++++++++++---- .../TestCompletion.java | 26 +++++++++++++++++ .../TestIndex.java | 28 +++++++++++++++++++ .../MethodChainsCompletionTest.java | 14 ++++++---- 4 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestCompletion.java create mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestIndex.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index 071e348d88c4..d322ceaceb01 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -73,12 +73,13 @@ public class PreferByKindWeigher extends LookupElementWeigher { psiElement(PsiReferenceExpression.class).withParent(PsiResourceExpression.class))); private final CompletionType myCompletionType; + @NotNull private final PsiElement myPosition; private final Set myNonInitializedFields; private final Condition myRequiredSuper; private final ExpectedTypeInfo[] myExpectedTypes; - public PreferByKindWeigher(CompletionType completionType, final PsiElement position, ExpectedTypeInfo[] expectedTypes) { + public PreferByKindWeigher(CompletionType completionType, @NotNull final PsiElement position, ExpectedTypeInfo[] expectedTypes) { super("kind"); myCompletionType = completionType; myPosition = position; @@ -134,12 +135,14 @@ public class PreferByKindWeigher extends LookupElementWeigher { probableKeyword, castVariable, variable, + getter, qualifiedWithField, qualifiedWithGetter, superMethodParameters, expectedTypeConstant, expectedTypeArgument, - getter, + getterQualifiedByMethod, + accessibleFieldGetter, normal, collectionFactory, expectedTypeMethod, @@ -209,12 +212,15 @@ public class PreferByKindWeigher extends LookupElementWeigher { if (chain.getQualifier().getUserData(INTRODUCED_VARIABLE) == Boolean.TRUE) { return MyResult.introducedVariable; } + if (myCompletionType == CompletionType.SMART && qualifier instanceof PsiMethod && isGetter(object)) { + return MyResult.getterQualifiedByMethod; + } } - if (myCompletionType == CompletionType.SMART) { - if (isGetter(object)) return MyResult.getter; - + if (isGetter(object)) { + return chain == null && isAccessibleFieldGetter(object) ? MyResult.accessibleFieldGetter : MyResult.getter; + } return MyResult.normal; } @@ -281,6 +287,13 @@ public class PreferByKindWeigher extends LookupElementWeigher { return ThreeState.UNSURE; } + private boolean isAccessibleFieldGetter(Object object) { + if (!(object instanceof PsiMethod)) return false; + + PsiField field = PropertyUtil.getFieldOfGetter((PsiMethod)object); + return field != null && PsiResolveHelper.SERVICE.getInstance(myPosition.getProject()).isAccessible(field, myPosition, null); + } + static boolean isInMethodTypeArg(PsiElement position) { return psiElement().inside(PsiReferenceParameterList.class).accepts(position); } diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestCompletion.java new file mode 100644 index 000000000000..d0de47283a60 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestCompletion.java @@ -0,0 +1,26 @@ +class EditorFactory { + + static EditorFactory getInstance() { + return null; + } + + Editor getEditor() { + return null; + } +} + +class Editor { +} + +class Main { + + + void stats() { + Editor e = + } + + Editor getEditor() { + return null; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestIndex.java new file mode 100644 index 000000000000..588b737e06ec --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testPreferGetterToMethodChain/TestIndex.java @@ -0,0 +1,28 @@ +class EditorFactory { + + static EditorFactory getInstance() { + return null; + } + + Editor getEditor() { + return null; + } +} + +class Editor { +} + +class Main { + + + void stats() { + EditorFactory.getInstance().getEditor(); + EditorFactory.getInstance().getEditor(); + EditorFactory.getInstance().getEditor(); + EditorFactory.getInstance().getEditor(); + EditorFactory.getInstance().getEditor(); + EditorFactory.getInstance().getEditor(); + EditorFactory.getInstance().getEditor(); + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MethodChainsCompletionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MethodChainsCompletionTest.java index 7ccbeea9c0ab..abe47ffca614 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MethodChainsCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MethodChainsCompletionTest.java @@ -172,6 +172,11 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest { assertEmpty(doCompletion()); } + public void testPreferGetterToMethodChain() { + compileAndComplete(); + myFixture.assertPreferredCompletionItems(0, "getEditor", "getInstance().getEditor"); + } + public void testResultOrdering() { List lookupElements = doCompletion(); assertSize(4, lookupElements); @@ -267,8 +272,7 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest { } private List doCompletion() { - compileAndIndexData(TEST_INDEX_FILE_NAME); - LookupElement[] allLookupElements = runCompletion(); + LookupElement[] allLookupElements = compileAndComplete(); List targetLookupElements = new SmartList<>(); for (LookupElement lookupElement : allLookupElements) { if (lookupElement instanceof JavaRelevantChainLookupElement) { @@ -278,10 +282,10 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest { return targetLookupElements; } - private LookupElement[] runCompletion() { + private LookupElement[] compileAndComplete() { + compileAndIndexData(TEST_INDEX_FILE_NAME); myFixture.configureByFiles(getTestCompletionFilePath()); - LookupElement[] lookupElements = - myFixture.complete(CompletionType.SMART); + LookupElement[] lookupElements = myFixture.complete(CompletionType.SMART); return lookupElements == null ? LookupElement.EMPTY_ARRAY : lookupElements; }