From 2514a8b5156de85b61e5528c5c8a83b80a18ab4a Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 5 Apr 2017 18:24:14 +0300 Subject: [PATCH] PY-23150 Show the canonized qualified name of a source module as type in completion instead of the much more computationally expensive canonical import name. It still an open question, though, how to reduce the cost of computing the preferred import path of re-exported symbols in case of a large hierarchy of packages where names from the leaf modules are propagated higher using wildcard imports. Check https://github.com/JetBrains/intellij-community/pull/532 for the related dicussion. --- .../userSkeletons/PyUserSkeletonsUtil.java | 9 +++------ .../resolve/CompletionVariantsProcessor.java | 10 ++++------ .../psi/resolve/QualifiedNameFinder.java | 19 +++++++++++++------ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java index baf0bdfdbe2e..92630437d351 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java @@ -17,7 +17,6 @@ package com.jetbrains.python.codeInsight.userSkeletons; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Key; @@ -198,11 +197,9 @@ public class PyUserSkeletonsUtil { return null; } final QualifiedName qName = QualifiedName.fromDottedString(moduleName); - for (PyCanonicalPathProvider provider : Extensions.getExtensions(PyCanonicalPathProvider.EP_NAME)) { - final QualifiedName restored = provider.getCanonicalPath(qName, null); - if (restored != null) { - moduleName = restored.toString(); - } + final QualifiedName restored = QualifiedNameFinder.canonizeQualifiedName(qName, null); + if (restored != null) { + moduleName = restored.toString(); } final PyFile skeletonFile = getUserSkeletonForModuleQName(moduleName, file); file.putUserData(HAS_SKELETON, skeletonFile != null); diff --git a/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java b/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java index 3f1653fc7774..df0944e8bb9e 100644 --- a/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java +++ b/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java @@ -23,7 +23,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; -import com.intellij.util.Function; +import com.intellij.util.ObjectUtils; import com.intellij.util.PlatformIcons; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.completion.PyClassInsertHandler; @@ -32,6 +32,7 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; +import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.Nullable; @@ -101,12 +102,9 @@ public class CompletionVariantsProcessor extends VariantsProcessor { source = cls.getName(); } else if (myContext == null || !PyUtil.inSameFile(myContext, element)) { - QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(element, null); + final QualifiedName path = QualifiedNameFinder.findShortestImportableQName(PyPsiUtils.getFileSystemItem(element)); if (path != null) { - if (element instanceof PyFile) { - path = path.removeLastComponent(); - } - source = path.toString(); + source = ObjectUtils.chooseNotNull(QualifiedNameFinder.canonizeQualifiedName(path, null), path).toString(); } } } diff --git a/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java b/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java index 3fc8cb5cbe3c..d7aa971e1d88 100644 --- a/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java +++ b/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java @@ -155,16 +155,23 @@ public class QualifiedNameFinder { } final QualifiedName qname = findShortestImportableQName(foothold != null ? foothold : symbol, virtualFile); if (qname != null) { - for (PyCanonicalPathProvider provider : Extensions.getExtensions(PyCanonicalPathProvider.EP_NAME)) { - final QualifiedName restored = provider.getCanonicalPath(qname, foothold); - if (restored != null) { - return restored; - } - } + final QualifiedName restored = canonizeQualifiedName(qname, foothold); + if (restored != null) return restored; } return qname; } + @Nullable + public static QualifiedName canonizeQualifiedName(QualifiedName qname, PsiElement foothold) { + for (PyCanonicalPathProvider provider : Extensions.getExtensions(PyCanonicalPathProvider.EP_NAME)) { + final QualifiedName restored = provider.getCanonicalPath(qname, foothold); + if (restored != null) { + return restored; + } + } + return null; + } + @Nullable public static String getQualifiedName(@NotNull PyElement element) { final String name = element.getName();