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.
This commit is contained in:
Mikhail Golubev
2017-04-17 19:22:54 +03:00
parent bcb02af54c
commit 2514a8b515
3 changed files with 20 additions and 18 deletions
@@ -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);
@@ -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();
}
}
}
@@ -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();