diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java index b2d041bbd925..b56b75ca4adf 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java @@ -15,6 +15,7 @@ import com.jetbrains.python.PyPsiBundle; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyImportElement; import com.jetbrains.python.psi.impl.PyPsiUtils; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,7 +70,7 @@ public class AutoImportQuickFix extends LocalQuickFixOnPsiElement implements Hig * @param file the file which is the source of the importable * @param importElement an existing import element that can be a source for the importable. */ - public void addImport(@NotNull PsiElement importable, @NotNull PsiFile file, @Nullable PyImportElement importElement) { + public void addImport(@NotNull PsiNamedElement importable, @NotNull PsiFile file, @Nullable PyImportElement importElement) { myImports.add(new ImportCandidateHolder(importable, file, importElement, null)); } @@ -79,14 +80,42 @@ public class AutoImportQuickFix extends LocalQuickFixOnPsiElement implements Hig * @param file the file which is the source of the importable * @param path import path for the file, as a qualified name (a.b.c) */ - public void addImport(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file, @Nullable QualifiedName path) { + public void addImport(@NotNull PsiNamedElement importable, @NotNull PsiFileSystemItem file, @Nullable QualifiedName path) { myImports.add(new ImportCandidateHolder(importable, file, null, path)); } - public void addImport(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file, @Nullable QualifiedName path, @Nullable String asName) { + /** + * @deprecated Use {@link #addImport(PsiNamedElement, PsiFileSystemItem, QualifiedName)} accepting a named element. + */ + @ApiStatus.ScheduledForRemoval(inVersion = "2021.3") + @Deprecated + public void addImport(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file, @Nullable QualifiedName path) { + if (importable instanceof PsiNamedElement) { + addImport((PsiNamedElement)importable, file, path); + } + } + + public void addImport(@NotNull PsiNamedElement importable, + @NotNull PsiFileSystemItem file, + @Nullable QualifiedName path, + @Nullable String asName) { myImports.add(new ImportCandidateHolder(importable, file, null, path, asName)); } + /** + * @deprecated Use {@link #addImport(PsiNamedElement, PsiFileSystemItem, QualifiedName, String)} accepting a named element. + */ + @ApiStatus.ScheduledForRemoval(inVersion = "2021.3") + @Deprecated + public void addImport(@NotNull PsiElement importable, + @NotNull PsiFileSystemItem file, + @Nullable QualifiedName path, + @Nullable String asName) { + if (importable instanceof PsiNamedElement) { + addImport((PsiNamedElement)importable, file, path, asName); + } + } + @Override @NotNull public String getText() { diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java index f74f7301b911..af8007ee4bf5 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java @@ -31,11 +31,11 @@ import java.util.List; // visibility is intentionally package-level public class ImportCandidateHolder implements Comparable { private static final Logger LOG = Logger.getInstance(ImportCandidateHolder.class); - @NotNull private final SmartPsiElementPointer myImportable; + @NotNull private final SmartPsiElementPointer myImportable; @Nullable private final SmartPsiElementPointer myImportElement; @NotNull private final SmartPsiElementPointer myFile; @Nullable private final QualifiedName myPath; - private final String myImportableName; + @NotNull private final String myImportableName; @Nullable private final String myAsName; private final int myRelevance; @@ -51,12 +51,13 @@ public class ImportCandidateHolder implements Comparable * (empty for modules and packages located at source roots). * */ - public ImportCandidateHolder(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file, + public ImportCandidateHolder(@NotNull PsiNamedElement importable, @NotNull PsiFileSystemItem file, @Nullable PyImportElement importElement, @Nullable QualifiedName path, @Nullable String asName) { SmartPointerManager pointerManager = SmartPointerManager.getInstance(importable.getProject()); myFile = pointerManager.createSmartPsiElementPointer(file); myImportable = pointerManager.createSmartPsiElementPointer(importable); - myImportableName = importable instanceof PsiNamedElement ? PyUtil.getElementNameWithoutExtension(((PsiNamedElement)importable)) : null; + myImportableName = PyUtil.getElementNameWithoutExtension(importable); + assert myImportableName != null; myImportElement = importElement != null ? pointerManager.createSmartPsiElementPointer(importElement) : null; myPath = path; myAsName = asName; @@ -65,17 +66,17 @@ public class ImportCandidateHolder implements Comparable assert importElement != null || path != null; // one of these must be present } - public ImportCandidateHolder(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file, + public ImportCandidateHolder(@NotNull PsiNamedElement importable, @NotNull PsiFileSystemItem file, @Nullable PyImportElement importElement, @Nullable QualifiedName path) { this(importable, file, importElement, path, null); } @Nullable - public PsiElement getImportable() { + public PsiNamedElement getImportable() { return myImportable.getElement(); } - public String getImportableName() { + public @NotNull String getImportableName() { return myImportableName; } diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportCollector.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportCollector.java index 3643e151cd69..b67a34af40d4 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportCollector.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportCollector.java @@ -87,16 +87,17 @@ public class PyImportCollector { PyFile sourceFile = as(PyUtil.turnDirIntoInit(source), PyFile.class); if (sourceFile instanceof PyFileImpl) { - PsiElement res = sourceFile.findExportedName(myRefText); - final String name = res instanceof PyQualifiedNameOwner ? ((PyQualifiedNameOwner)res).getQualifiedName() : null; + PsiElement variant = sourceFile.findExportedName(myRefText); + final String name = variant instanceof PyQualifiedNameOwner ? ((PyQualifiedNameOwner)variant).getQualifiedName() : null; if (name != null && seenCandidateNames.contains(name)) { return existingImportFile; } + PsiNamedElement definition = as(variant, PsiNamedElement.class); // allow importing from this source if it either declares the name itself or represents a higher-level package that reexports the name - if (res != null && !(res instanceof PyFile) && !(res instanceof PyImportElement) && res.getContainingFile() != null && - PsiTreeUtil.isAncestor(source, res.getContainingFile(), false)) { + if (definition != null && !(definition instanceof PyFile || definition instanceof PyImportElement) && + definition.getContainingFile() != null && PsiTreeUtil.isAncestor(source, definition.getContainingFile(), false)) { existingImportFile = sourceFile; - fix.addImport(res, sourceFile, importElement); + fix.addImport(definition, sourceFile, importElement); if (name != null) { seenCandidateNames.add(name); } @@ -107,7 +108,7 @@ public class PyImportCollector { private void addSymbolImportCandidates(PsiFile existingImportFile) { Project project = myNode.getProject(); - List symbols = new ArrayList<>(PyClassNameIndex.find(myRefText, project, true)); + List symbols = new ArrayList<>(PyClassNameIndex.find(myRefText, project, true)); GlobalSearchScope scope = PySearchUtilBase.excludeSdkTestsScope(myNode); if (!isQualifier()) { symbols.addAll(PyFunctionNameIndex.find(myRefText, project, scope)); @@ -120,7 +121,7 @@ public class PyImportCollector { symbols.addAll(findImportableModules(packageQName, project, scope)); } } - for (PsiElement symbol : symbols) { + for (PsiNamedElement symbol : symbols) { if (isIndexableTopLevel(symbol)) { // we only want top-level symbols PsiFileSystemItem srcfile = symbol instanceof PsiFileSystemItem ? ((PsiFileSystemItem)symbol).getParent() : symbol.getContainingFile(); @@ -132,10 +133,7 @@ public class PyImportCollector { if (symbol instanceof PsiFileSystemItem) { importPath = importPath.removeTail(1); } - if (!(symbol instanceof PsiNamedElement)) { - continue; - } - String name = PyUtil.getElementNameWithoutExtension((PsiNamedElement)symbol); + String name = PyUtil.getElementNameWithoutExtension(symbol); final String symbolImportQName = importPath.append(name).toString(); if (seenCandidateNames.add(symbolImportQName)) { String alias = name.equals(myRefText) ? null : myRefText;