diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index 9fdb3388098c..9aa1c5381e26 100644 --- a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -476,46 +476,49 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { final Ref finallyRef = new Ref(finallyInstruction); final Ref lastFinallyRef = new Ref(lastFinallyInstruction); myBuilder.processPending(new ControlFlowBuilder.PendingProcessor() { + @SuppressWarnings({"ConstantConditions"}) public void process(final PsiElement pendingScope, final Instruction instruction) { final PsiElement pendingElement = instruction.getElement(); - if (pendingElement == null || !PsiTreeUtil.isAncestor(tryPart, pendingElement, false)) { - myBuilder.addPendingEdge(pendingScope, instruction); - return; - } - // Process raise statements - if (PsiTreeUtil.isAncestor(tryPart, pendingElement, false) && - PsiTreeUtil.getParentOfType(pendingElement, PyRaiseStatement.class) != null) { - for (Instruction rescueInstruction : exceptInstructions) { - myBuilder.addEdge(instruction, rescueInstruction); + // Handle raise statements inside try part + if (isRaiseInstruction(pendingElement) && PsiTreeUtil.isAncestor(tryPart, pendingElement, false)) { + for (Instruction inst : exceptInstructions) { + myBuilder.addEdge(instruction, inst); + } + if (finallyPart!=null) { + myBuilder.addEdge(instruction, finallyRef.get()); } - myBuilder.addPendingEdge(pendingScope, instruction); return; } - - // Add except statements - if (PsiTreeUtil.isAncestor(tryPart, pendingElement, false)) { - for (Instruction rescueInstruction : exceptInstructions) { - myBuilder.addEdge(instruction, rescueInstruction); + else if (pendingElement != null && PsiTreeUtil.isAncestor(tryPart, pendingElement, false)){ + for (Instruction inst : exceptInstructions) { + myBuilder.addEdge(instruction, inst); } } - // Process finally - if (!finallyRef.isNull()) { + // handle return pending instructions inside try if final block exists + if (!finallyRef.isNull() && + PsiTreeUtil.isAncestor(tryPart, pendingElement, false)) { myBuilder.addEdge(instruction, finallyRef.get()); - if (!lastFinallyRef.isNull() && - PsiTreeUtil.getParentOfType(pendingElement, PyReturnStatement.class, false) != null) { - myBuilder.addPendingEdge(null, lastFinallyRef.get()); - } + myBuilder.addPendingEdge(null, lastFinallyRef.get()); return; } + // Handle pending instructions inside try with final block + if (finallyPart!=null && pendingScope !=finallyPart && + PsiTreeUtil.isAncestor(tryPart, pendingElement, false)) { + myBuilder.addEdge(instruction, finallyRef.get()); + return; + } myBuilder.addPendingEdge(pendingScope, instruction); - } }); } + private boolean isRaiseInstruction(final PsiElement pendingElement) { + return pendingElement != null && PsiTreeUtil.getParentOfType(pendingElement, PyRaiseStatement.class) != null; + } + @Override public void visitPyComprehensionElement(final PyComprehensionElement node) { myBuilder.startNode(node); diff --git a/python/testData/codeInsight/controlflow/raise.txt b/python/testData/codeInsight/controlflow/raise.txt index e3f9d533f122..1461a143404e 100644 --- a/python/testData/codeInsight/controlflow/raise.txt +++ b/python/testData/codeInsight/controlflow/raise.txt @@ -2,7 +2,7 @@ 1(2) element: PyTryExceptStatement 2(3) element: PyTryPart 3(4) element: PyRaiseStatement -4(5,11) READ ACCESS: Exception +4(5) READ ACCESS: Exception 5(6) element: PyExceptPart 6(7) element: PyAssignmentStatement 7(8) READ ACCESS: Exception diff --git a/python/testData/codeInsight/controlflow/tryraisefinally.py b/python/testData/codeInsight/controlflow/tryraisefinally.py new file mode 100644 index 000000000000..be0820484dca --- /dev/null +++ b/python/testData/codeInsight/controlflow/tryraisefinally.py @@ -0,0 +1,4 @@ +try: + raise KeyboardInterrupt +finally: + print 'test' \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/tryraisefinally.txt b/python/testData/codeInsight/controlflow/tryraisefinally.txt new file mode 100644 index 000000000000..886370066158 --- /dev/null +++ b/python/testData/codeInsight/controlflow/tryraisefinally.txt @@ -0,0 +1,8 @@ +0(1) element: null +1(2) element: PyTryExceptStatement +2(3) element: PyTryPart +3(4) element: PyRaiseStatement +4(5) READ ACCESS: KeyboardInterrupt +5(6) element: PyFinallyPart +6(7) element: PyPrintStatement +7() element: null \ No newline at end of file diff --git a/python/testData/inspections/PyUnreachableCodeInspection/expected.xml b/python/testData/inspections/PyUnreachableCodeInspection/expected.xml index ebe5d1dbbce6..f455dfd911bb 100644 --- a/python/testData/inspections/PyUnreachableCodeInspection/expected.xml +++ b/python/testData/inspections/PyUnreachableCodeInspection/expected.xml @@ -35,7 +35,7 @@ unreachable.py - 40 + 46 This code is unreachable diff --git a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java index 2d9127bc314a..01994d34ad9a 100644 --- a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java +++ b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java @@ -115,7 +115,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { doTest(); } - public void testExit() throws Exception { + public void testTryRaiseFinally() throws Exception { doTest(); }