diff --git a/python/src/com/jetbrains/python/codeInsight/imports/PythonImportUtils.java b/python/src/com/jetbrains/python/codeInsight/imports/PythonImportUtils.java index ec7b0fdba416..479928a87fd0 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/PythonImportUtils.java +++ b/python/src/com/jetbrains/python/codeInsight/imports/PythonImportUtils.java @@ -212,8 +212,11 @@ public final class PythonImportUtils { } private static boolean isPossibleModuleReference(PyElement node) { - if (node.getParent() instanceof PyCallExpression && node == ((PyCallExpression) node.getParent()).getCallee()) { - return false; + final PyCallExpression callExpression = as(node.getParent(), PyCallExpression.class); + if (callExpression != null && node == callExpression.getCallee()) { + final PyDecorator decorator = as(callExpression, PyDecorator.class); + // getArgumentList() still returns empty (but not null) element in this case + return decorator != null && !decorator.hasArgumentList(); } if (node.getParent() instanceof PyArgumentList) { final PyArgumentList argumentList = (PyArgumentList)node.getParent(); diff --git a/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/main.py b/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/main.py new file mode 100644 index 000000000000..15060df445ae --- /dev/null +++ b/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/main.py @@ -0,0 +1,3 @@ +@pytest +def test_skipped(): + pass \ No newline at end of file diff --git a/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/main_after.py b/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/main_after.py new file mode 100644 index 000000000000..e4eb41611d3d --- /dev/null +++ b/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/main_after.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest +def test_skipped(): + pass \ No newline at end of file diff --git a/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/pytest.py b/python/testData/quickFixes/PyAddImportQuickFixTest/availableForUnqualifiedDecoratorWithoutArguments/pytest.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/quickFixes/PyAddImportQuickFixTest/unavailableForUnqualifiedDecoratorWithArguments/main.py b/python/testData/quickFixes/PyAddImportQuickFixTest/unavailableForUnqualifiedDecoratorWithArguments/main.py new file mode 100644 index 000000000000..6442899e1588 --- /dev/null +++ b/python/testData/quickFixes/PyAddImportQuickFixTest/unavailableForUnqualifiedDecoratorWithArguments/main.py @@ -0,0 +1,3 @@ +@pytest() +def test_skipped(): + pass \ No newline at end of file diff --git a/python/testData/quickFixes/PyAddImportQuickFixTest/unavailableForUnqualifiedDecoratorWithArguments/pytest.py b/python/testData/quickFixes/PyAddImportQuickFixTest/unavailableForUnqualifiedDecoratorWithArguments/pytest.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyAddImportQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyAddImportQuickFixTest.java index 7ffb73ffe9a0..a69fd3ac4964 100644 --- a/python/testSrc/com/jetbrains/python/quickFixes/PyAddImportQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/quickFixes/PyAddImportQuickFixTest.java @@ -119,15 +119,22 @@ public class PyAddImportQuickFixTest extends PyQuickFixTestCase { doMultiFileAutoImportTest("Import 'ClassB from foo.bar.baz'"); } + // PY-24450 + public void testAvailableForUnqualifiedDecoratorWithoutArguments() { + doMultiFileAutoImportTest("Import 'pytest'"); + } + + // PY-24450 + public void testUnavailableForUnqualifiedDecoratorWithArguments() { + doMultiFileNegativeTest("Import 'pytest'"); + } + private void doMultiFileAutoImportTest(@NotNull String hintPrefix) { doMultiFileAutoImportTest(hintPrefix, null); } private void doMultiFileAutoImportTest(@NotNull String hintPrefix, @Nullable Processor checkQuickfix) { - myFixture.copyDirectoryToProject(getTestName(true), ""); - myFixture.enableInspections(PyUnresolvedReferencesInspection.class); - myFixture.configureByFile("main.py"); - myFixture.checkHighlighting(true, false, false); + configureMultiFileProject(); final PsiElement hostUnderCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); final PyReferenceExpression hostRefExpr = PsiTreeUtil.getParentOfType(hostUnderCaret, PyReferenceExpression.class); @@ -147,4 +154,16 @@ public class PyAddImportQuickFixTest extends PyQuickFixTestCase { myFixture.checkResultByFile(getTestName(true) + "/main_after.py", true); } } + + private void doMultiFileNegativeTest(@NotNull String hintPrefix) { + configureMultiFileProject(); + assertEmpty(myFixture.filterAvailableIntentions(hintPrefix)); + } + + private void configureMultiFileProject() { + myFixture.copyDirectoryToProject(getTestName(true), ""); + myFixture.enableInspections(PyUnresolvedReferencesInspection.class); + myFixture.configureByFile("main.py"); + myFixture.checkHighlighting(true, false, false); + } }