diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyInconsistentReturnsInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyInconsistentReturnsInspection.kt index 244d49c022f6..96ba34917adc 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyInconsistentReturnsInspection.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyInconsistentReturnsInspection.kt @@ -14,6 +14,8 @@ import com.jetbrains.python.psi.PyReturnStatement * or none of them should. If any return statement returns an expression, any return statements where no value * is returned should explicitly state this as return None, and an explicit return statement should be present * at the end of the function (if reachable). + * + * @see PyMakeReturnsExplicitFix for tests */ class PyInconsistentReturnsInspection : PyInspection() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 223aed10ccfa..cd1b91c5efd6 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -405,7 +405,10 @@ public class PyFunctionImpl extends PyBaseElementImpl implements if (instruction instanceof PyRaiseInstruction) { return ControlFlowUtil.Operation.CONTINUE; } - if (instruction instanceof PyWithContextExitInstruction withExit && !withExit.isSuppressingExceptions(context)) { + if (instruction instanceof PyWithContextExitInstruction withExit) { + if (collectImplicitReturn && withExit.isSuppressingExceptions(context)) { + returnPoints.add(PsiTreeUtil.getParentOfType(withExit.getElement(), PyWithStatement.class)); + } return ControlFlowUtil.Operation.CONTINUE; } final PsiElement element = instruction.getElement(); diff --git a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/addReturnsFromAnnotation.py b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/addReturnsFromAnnotation.py deleted file mode 100644 index 077dc7909e56..000000000000 --- a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/addReturnsFromAnnotation.py +++ /dev/null @@ -1,5 +0,0 @@ -def f(x) -> int | None: - if x == 1: - return 42 - elif x == 2: - return \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/addReturnsFromAnnotation_after.py b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/addReturnsFromAnnotation_after.py deleted file mode 100644 index 9a4cd15bef3b..000000000000 --- a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/addReturnsFromAnnotation_after.py +++ /dev/null @@ -1,6 +0,0 @@ -def f(x) -> int | None: - if x == 1: - return 42 - elif x == 2: - return None - return None \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerNotSuppressingException.py b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerNotSuppressingException.py new file mode 100644 index 000000000000..2b5accae7edd --- /dev/null +++ b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerNotSuppressingException.py @@ -0,0 +1,11 @@ +class NotSuppressingContext: + def __enter__(self): + ... + def __exit__(self, exc_type, exc_val, exc_tb) -> bool | None: + ... + +def foo(): + with NotSuppressingContext() as st: + foo() + if bool(): + return 1 \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerNotSuppressingException_after.py b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerNotSuppressingException_after.py new file mode 100644 index 000000000000..c0c97aacf1e9 --- /dev/null +++ b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerNotSuppressingException_after.py @@ -0,0 +1,12 @@ +class NotSuppressingContext: + def __enter__(self): + ... + def __exit__(self, exc_type, exc_val, exc_tb) -> bool | None: + ... + +def foo(): + with NotSuppressingContext() as st: + foo() + if bool(): + return 1 + return None \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerSuppressingException.py b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerSuppressingException.py new file mode 100644 index 000000000000..512095e3cb86 --- /dev/null +++ b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerSuppressingException.py @@ -0,0 +1,10 @@ +class SuppressingContext: + def __enter__(self): + ... + def __exit__(self, exc_type, exc_val, exc_tb) -> bool: + ... + +def foo(): + with SuppressingContext() as st: + foo() + return 1 \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerSuppressingException_after.py b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerSuppressingException_after.py new file mode 100644 index 000000000000..480e471506a8 --- /dev/null +++ b/python/testData/quickFixes/PyMakeReturnsExplicitFixTest/contextManagerSuppressingException_after.py @@ -0,0 +1,11 @@ +class SuppressingContext: + def __enter__(self): + ... + def __exit__(self, exc_type, exc_val, exc_tb) -> bool: + ... + +def foo(): + with SuppressingContext() as st: + foo() + return 1 + return None \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyMakeReturnsExplicitFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyMakeReturnsExplicitFixTest.java index bc593486f9cc..d4c59aaeb690 100644 --- a/python/testSrc/com/jetbrains/python/quickFixes/PyMakeReturnsExplicitFixTest.java +++ b/python/testSrc/com/jetbrains/python/quickFixes/PyMakeReturnsExplicitFixTest.java @@ -13,6 +13,16 @@ public class PyMakeReturnsExplicitFixTest extends PyQuickFixTestCase { doQuickFixTest(PyInconsistentReturnsInspection.class, PyPsiBundle.message("QFIX.NAME.make.return.stmts.explicit")); } + // PY-80493 + public void testContextManagerSuppressingException() { + doQuickFixTest(PyInconsistentReturnsInspection.class, PyPsiBundle.message("QFIX.NAME.make.return.stmts.explicit")); + } + + // PY-80493 + public void testContextManagerNotSuppressingException() { + doQuickFixTest(PyInconsistentReturnsInspection.class, PyPsiBundle.message("QFIX.NAME.make.return.stmts.explicit")); + } + @Override protected void doQuickFixTest(final Class inspectionClass, final String hint) { final String testFileName = getTestName(true);