PY-84710 Don't suggest creating functions and classes for import mod.unresolved or from mod.unresolved import x

Because top-level definitions cannot be referenced in imports like that.

GitOrigin-RevId: 9a78ddd87e5d78c0f353aaaed69a407f8e37746c
This commit is contained in:
Mikhail Golubev
2025-10-22 19:02:14 +00:00
committed by intellij-monorepo-bot
parent 0514a0ab95
commit 8ffe90fe08
6 changed files with 45 additions and 9 deletions
@@ -780,7 +780,9 @@ public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor
return null;
}
private @NotNull List<LocalQuickFix> getCreateMemberFromUsageFixes(PyType type, PsiReference reference, String refText) {
private @NotNull List<LocalQuickFix> getCreateMemberFromUsageFixes(@NotNull PyType type,
@NotNull PsiReference reference,
@NotNull String refText) {
List<LocalQuickFix> result = new ArrayList<>();
PsiElement element = reference.getElement();
if (type instanceof PyClassTypeImpl) {
@@ -794,14 +796,18 @@ public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor
}
}
}
else if (type instanceof PyModuleType) {
PyFile file = ((PyModuleType)type).getModule();
LocalQuickFix createClassQuickFix = getCreateClassFix(refText, element);
if (createClassQuickFix != null) {
result.add(createClassQuickFix);
}
else {
result.add(new AddFunctionQuickFix(refText, file.getName()));
else if (type instanceof PyModuleType moduleType) {
boolean isQualifiedRefInsideImport = element instanceof PyReferenceExpression re && re.isQualified() &&
PsiTreeUtil.getParentOfType(re, PyImportStatementBase.class) != null;
if (!isQualifiedRefInsideImport) {
PyFile file = moduleType.getModule();
LocalQuickFix createClassQuickFix = getCreateClassFix(refText, element);
if (createClassQuickFix != null) {
result.add(createClassQuickFix);
}
else {
result.add(new AddFunctionQuickFix(refText, file.getName()));
}
}
}
return result;
@@ -0,0 +1 @@
from mod.<caret><error descr="Cannot find reference 'unresolved' in 'mod.py'">unresolved</error> import <error descr="Unresolved reference 'something'">something</error>
@@ -0,0 +1 @@
import mod.<caret><error descr="No module named 'unresolved'">unresolved</error>
@@ -455,6 +455,22 @@ class PyQuickFixTest : PyTestCase() {
)
}
// PY-84710
fun testDoNotAddFunctionInsideImport() {
doMultiFilesNegativeInspectionTest(
PyUnresolvedReferencesInspection::class.java,
PyPsiBundle.message("QFIX.create.function.in.module", "unresolved", "mod.py")
)
}
// PY-84710
fun testDoNotAddFunctionInsideFromImportSource() {
doMultiFilesNegativeInspectionTest(
PyUnresolvedReferencesInspection::class.java,
PyPsiBundle.message("QFIX.create.function.in.module", "unresolved", "mod.py")
)
}
// PY-1470
fun testRedundantParentheses() {
val testFiles = arrayOf("RedundantParentheses.py")
@@ -1390,6 +1406,18 @@ class PyQuickFixTest : PyTestCase() {
myFixture.checkResultByFile(modifiedFile, expectedFile, true)
}
private fun doMultiFilesNegativeInspectionTest(
inspectionClass: Class<out LocalInspectionTool>,
intentionStr: String,
) {
myFixture.enableInspections(inspectionClass)
myFixture.copyDirectoryToProject(getTestName(true), "")
myFixture.configureFromTempProjectFile(getTestName(true) + ".py")
myFixture.checkHighlighting(true, false, false)
val intentions = myFixture.filterAvailableIntentions(intentionStr)
assertEmpty("Quick fix \"$intentionStr\" should not be available", intentions)
}
companion object {
// Turns "name.ext" to "name_insertion.ext"
@NonNls