From 78048abb15ce2858361245f0018e6e469e1db7f4 Mon Sep 17 00:00:00 2001 From: Lada Gagina Date: Thu, 18 Mar 2021 00:28:12 +0300 Subject: [PATCH] PY-47247 Suggest subpackages and submodules in module attributes completion IJ-MR-7312 GitOrigin-RevId: 2333fdc6ef9974b0f80bbe4d829c1211dde722ac --- ...vedModuleAttributeCompletionContributor.kt | 28 +++++++++++++++++-- .../NoImportForSubmodules/main.after.py | 1 + .../NoImportForSubmodules/main.py | 1 + .../mypackage/__init__.py | 0 .../mypackage/mysubpackage/__init__.py | 0 .../mypackage/mysubpackage/mysubmodule.py | 0 .../NoImportForSubpackages/main.after.py | 1 + .../NoImportForSubpackages/main.py | 1 + .../mypackage/__init__.py | 0 .../mypackage/mysubpackage/__init__.py | 0 .../main.after.py | 1 + .../main.py | 1 + .../numpy/__init__.py | 0 .../numpy/core/__init__.py | 0 ...otImportedQualifiedNameCompletionTest.java | 15 ++++++++++ 15 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.after.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/__init__.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/mysubpackage/__init__.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/mysubpackage/mysubmodule.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.after.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/mypackage/__init__.py create mode 100644 python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/mypackage/mysubpackage/__init__.py create mode 100644 python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.after.py create mode 100644 python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.py create mode 100644 python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/numpy/__init__.py create mode 100644 python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/numpy/core/__init__.py diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyUnresolvedModuleAttributeCompletionContributor.kt b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyUnresolvedModuleAttributeCompletionContributor.kt index 14fdf93cd2b0..f4b17f5729fa 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyUnresolvedModuleAttributeCompletionContributor.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/completion/PyUnresolvedModuleAttributeCompletionContributor.kt @@ -3,6 +3,7 @@ package com.jetbrains.python.codeInsight.completion import com.intellij.codeInsight.completion.* import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementBuilder +import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.util.Key @@ -26,6 +27,7 @@ import com.jetbrains.python.psi.search.PySearchUtilBase import com.jetbrains.python.psi.stubs.PyModuleNameIndex import com.jetbrains.python.psi.stubs.PyQualifiedNameCompletionMatcher import com.jetbrains.python.psi.stubs.PyQualifiedNameCompletionMatcher.QualifiedNameMatcher +import com.jetbrains.python.psi.types.PyModuleType class PyUnresolvedModuleAttributeCompletionContributor : CompletionContributor() { @@ -113,9 +115,29 @@ class PyUnresolvedModuleAttributeCompletionContributor : CompletionContributor() val packageNameForAlias = PyPackageAliasesProvider.commonImportAliases[qualifier.toString()] val packageName = if (packageNameForAlias != null) QualifiedName.fromDottedString(packageNameForAlias) else qualifier val resultMatchingCompleteReference = result.withPrefixMatcher(QualifiedNameMatcher(qualifiedName)) - PyModuleNameIndex.find(packageName.lastComponent!!, project, true).asSequence() - .filter { QualifiedNameFinder.findShortestImportableQName(it) == packageName } - .flatMap { it.iterateNames().asSequence() } + + val availableModules = PyModuleNameIndex.findByQualifiedName(packageName, project, + PySearchUtilBase.defaultSuggestionScope(parameters.originalFile)) + .asSequence() + + if (packageNameForAlias == null) { + availableModules.filter { PyUtil.isPackage(it) } + .flatMap { PyModuleType.getSubModuleVariants(it.containingDirectory, it, null) } + .filterNot { it.lookupString.startsWith('_') } + .mapNotNull { + val qualifiedNameToSuggest = "$qualifier.${it.lookupString}" + if (suggestedQualifiedNames.add(qualifiedNameToSuggest)) { + object : LookupElementDecorator(it) { + override fun getLookupString(): String = qualifiedNameToSuggest + override fun getAllLookupStrings(): MutableSet = mutableSetOf(lookupString) + } + } + else null + } + .forEach { resultMatchingCompleteReference.addElement(it) } + } + + availableModules.flatMap { it.iterateNames() } .filter { it.containingFile != null } .filterNot { it is PsiFileSystemItem } .filterNot { it.name == null || it.name!!.startsWith('_') } diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.after.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.after.py new file mode 100644 index 000000000000..4fb6901f2c24 --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.after.py @@ -0,0 +1 @@ +mypackage.mysubpackage.mysubmodule \ No newline at end of file diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.py new file mode 100644 index 000000000000..00832a7f5ac7 --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/main.py @@ -0,0 +1 @@ +mypackage.mysubpackage. \ No newline at end of file diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/__init__.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/mysubpackage/__init__.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/mysubpackage/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/mysubpackage/mysubmodule.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubmodules/mypackage/mysubpackage/mysubmodule.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.after.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.after.py new file mode 100644 index 000000000000..3bb6538cb005 --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.after.py @@ -0,0 +1 @@ +mypackage.mysubpackage \ No newline at end of file diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.py new file mode 100644 index 000000000000..91679980a529 --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/main.py @@ -0,0 +1 @@ +mypackage. \ No newline at end of file diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/mypackage/__init__.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/mypackage/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/mypackage/mysubpackage/__init__.py b/python/testData/completion/notImportedQualifiedName/NoImportForSubpackages/mypackage/mysubpackage/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.after.py b/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.after.py new file mode 100644 index 000000000000..6a57744d07cc --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.after.py @@ -0,0 +1 @@ +np. \ No newline at end of file diff --git a/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.py b/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.py new file mode 100644 index 000000000000..d2f2fe0ab847 --- /dev/null +++ b/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/main.py @@ -0,0 +1 @@ +np. \ No newline at end of file diff --git a/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/numpy/__init__.py b/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/numpy/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/numpy/core/__init__.py b/python/testData/completion/notImportedQualifiedName/ShouldNotSuggestSubmodulesForAliases/numpy/core/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java b/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java index 584eaf642cd4..b5496a75ea5c 100644 --- a/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PyNotImportedQualifiedNameCompletionTest.java @@ -99,6 +99,21 @@ public class PyNotImportedQualifiedNameCompletionTest extends PyTestCase { doTestBasicCompletion(); } + //PY-47247 + public void testNoImportForSubpackages() { + doTestBasicCompletion(); + } + + //PY-47247 + public void testNoImportForSubmodules() { + doTestBasicCompletion(); + } + + //PY-47247 + public void testShouldNotSuggestSubmodulesForAliases() { + doTestBasicCompletion(); + } + private void doTestBasicCompletion() { final String testName = getTestName(false); myFixture.copyDirectoryToProject(testName, "");