From 5ca605ccab873ec46a6a56c71c69a86e0522e800 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 15 Feb 2022 16:56:44 +0200 Subject: [PATCH] PY-47962 Put non-imported module names last among completion variants By giving them an explicit priority lower than the default. Unfortunately, it doesn't remedy the problem with short module names, such as "re" or "sys", always being on top when they completely match the entered prefix. At the moment this behavior is hard-coded in the platform and cannot be altered by language plugins. It's not caused by the "liftShorter" classifier. Also, explicitly prioritizing various lookup elements has become quite messy and scattered across PyCompletionWeigher and specific contributors. It begs to be refactored, but will be addressed separately. GitOrigin-RevId: d6f6ad06f5d68f3de7b866b8240a95b785604649 --- .../completion/PyModuleNameCompletionContributor.kt | 4 +++- .../codeInsight/completion/PythonCompletionWeigher.java | 2 ++ .../NonImportedModulesSuggestedLast/config.py | 0 .../NonImportedModulesSuggestedLast/contrib.py | 0 .../NonImportedModulesSuggestedLast/main.py | 4 ++++ .../python/PyNotImportedQualifiedNameCompletionTest.java | 7 +++++++ 6 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/config.py create mode 100644 python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/contrib.py create mode 100644 python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/main.py diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyModuleNameCompletionContributor.kt b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyModuleNameCompletionContributor.kt index a80f0982d357..5c9ee03e599f 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyModuleNameCompletionContributor.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyModuleNameCompletionContributor.kt @@ -4,6 +4,7 @@ package com.jetbrains.python.codeInsight.completion import com.intellij.codeInsight.completion.CompletionContributor import com.intellij.codeInsight.completion.CompletionParameters import com.intellij.codeInsight.completion.CompletionResultSet +import com.intellij.codeInsight.completion.PrioritizedLookupElement import com.intellij.codeInsight.lookup.LookupElement import com.intellij.openapi.project.DumbAware import com.intellij.psi.MultiplePsiFilesPerDocumentFileViewProvider @@ -14,6 +15,7 @@ import com.intellij.psi.util.QualifiedName import com.intellij.util.ProcessingContext import com.jetbrains.python.PyNames import com.jetbrains.python.PythonRuntimeService +import com.jetbrains.python.codeInsight.completion.PythonCompletionWeigher.NOT_IMPORTED_MODULE_WEIGHT import com.jetbrains.python.psi.PyFile import com.jetbrains.python.psi.PyImportStatementBase import com.jetbrains.python.psi.PyReferenceExpression @@ -54,7 +56,7 @@ class PyModuleNameCompletionContributor : CompletionContributor(), DumbAware { getCompletionVariants(parameters.position.parent, parameters.originalFile, otherVariants).asSequence() .filterIsInstance() .filterNot { it.lookupString.startsWith('_') } - .forEach { result.addElement(it) } + .forEach { result.addElement(PrioritizedLookupElement.withPriority(it, NOT_IMPORTED_MODULE_WEIGHT.toDouble())) } } private fun getCompletionVariants(element: PsiElement, file: PsiElement, otherVariants: Set): List { diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java index 0481471196a7..aa219e6b42ac 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PythonCompletionWeigher.java @@ -36,12 +36,14 @@ import org.jetbrains.annotations.NotNull; */ public class PythonCompletionWeigher extends CompletionWeigher { + // TODO Unify different ways of detecting and weighing elements public static final int PRIORITY_WEIGHT = 5; public static final int WEIGHT_FOR_MULTIPLE_ARGUMENTS = 5; public static final int WEIGHT_FOR_KEYWORDS = 0; private static final Logger LOG = Logger.getInstance(PythonCompletionWeigher.class); public static final String COLLECTION_KEY = "dict key"; private static final int COLLECTION_KEY_WEIGHT = 10; + public static final int NOT_IMPORTED_MODULE_WEIGHT = -1; @Override public Comparable weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) { diff --git a/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/config.py b/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/config.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/contrib.py b/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/contrib.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/main.py b/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/main.py new file mode 100644 index 000000000000..877dbed9236a --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/NonImportedModulesSuggestedLast/main.py @@ -0,0 +1,4 @@ +def func(configuration=): + pass + +func(con) diff --git a/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java b/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java index a2325f5f99c9..3346b4ab5ced 100644 --- a/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java @@ -173,6 +173,13 @@ public class PyNotImportedQualifiedNameCompletionTest extends PyTestCase { assertEquals(1, ContainerUtil.count(variants, "foo"::equals)); } + // PY-47962 + public void testNonImportedModulesSuggestedLast() { + doBasicCompletion(); + myFixture.assertPreferredCompletionItems(0, "configuration="); + assertContainsElements(myFixture.getLookupElementStrings(), "config", "contrib"); + } + @Nullable private List doBasicCompletion() { myFixture.copyDirectoryToProject(getTestName(false), "");