diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java index e3ef583f62ea..e5564b956d8b 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java @@ -780,7 +780,9 @@ public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor return null; } - private @NotNull List getCreateMemberFromUsageFixes(PyType type, PsiReference reference, String refText) { + private @NotNull List getCreateMemberFromUsageFixes(@NotNull PyType type, + @NotNull PsiReference reference, + @NotNull String refText) { List 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; diff --git a/python/testData/inspections/doNotAddFunctionInsideFromImportSource/doNotAddFunctionInsideFromImportSource.py b/python/testData/inspections/doNotAddFunctionInsideFromImportSource/doNotAddFunctionInsideFromImportSource.py new file mode 100644 index 000000000000..fb52d5e3b60c --- /dev/null +++ b/python/testData/inspections/doNotAddFunctionInsideFromImportSource/doNotAddFunctionInsideFromImportSource.py @@ -0,0 +1 @@ +from mod.unresolved import something diff --git a/python/testData/inspections/doNotAddFunctionInsideFromImportSource/mod.py b/python/testData/inspections/doNotAddFunctionInsideFromImportSource/mod.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/inspections/doNotAddFunctionInsideImport/doNotAddFunctionInsideImport.py b/python/testData/inspections/doNotAddFunctionInsideImport/doNotAddFunctionInsideImport.py new file mode 100644 index 000000000000..4ba1e6a61725 --- /dev/null +++ b/python/testData/inspections/doNotAddFunctionInsideImport/doNotAddFunctionInsideImport.py @@ -0,0 +1 @@ +import mod.unresolved diff --git a/python/testData/inspections/doNotAddFunctionInsideImport/mod.py b/python/testData/inspections/doNotAddFunctionInsideImport/mod.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.kt b/python/testSrc/com/jetbrains/python/PyQuickFixTest.kt index cdc959671aa1..db9e667edf18 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.kt +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.kt @@ -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, + 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