From 28e27205c423a97c711c371c5ceab755a27d9d0e Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Fri, 19 Feb 2010 17:19:51 +0300 Subject: [PATCH] PY-579 Incorrect "code is unreachable" warning --- .../controlflow/PyControlFlowBuilder.java | 19 +++++++++++++------ .../jetbrains/python/psi/PyForStatement.java | 3 +-- .../codeInsight/controlflow/trybreak.py | 7 +++++++ .../codeInsight/controlflow/trybreak.txt | 12 ++++++++++++ .../python/PyControlFlowBuilderTest.java | 8 ++++++++ 5 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 python/testData/codeInsight/controlflow/trybreak.py create mode 100644 python/testData/codeInsight/controlflow/trybreak.txt diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index 55e43a9ef6a5..139dd0a325c4 100644 --- a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -3,6 +3,8 @@ package com.jetbrains.python.codeInsight.controlflow; import com.intellij.codeInsight.controlflow.ControlFlowBuilder; import com.intellij.codeInsight.controlflow.ControlFlow; import com.intellij.codeInsight.controlflow.Instruction; +import com.intellij.codeInsight.controlflow.impl.InstructionImpl; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; @@ -12,6 +14,7 @@ import com.jetbrains.python.psi.impl.PyImportStatementNavigator; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.List; /** * @author oleg @@ -259,10 +262,7 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { myBuilder.prevInstruction = head; if (elsePart != null) { elsePart.accept(this); - myBuilder.addPendingEdge(node, myBuilder.prevInstruction); // exit - } - else { - myBuilder.addPendingEdge(null, myBuilder.prevInstruction); + myBuilder.addPendingEdge(node, myBuilder.prevInstruction); } myBuilder.flowAbrupted(); } @@ -346,14 +346,21 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { } final ArrayList exceptInstructions = new ArrayList(); + // Store pending and clear it + final List> myPending = myBuilder.pending; + myBuilder.pending = new ArrayList>(); for (PyExceptPart exceptPart : node.getExceptParts()) { myBuilder.prevInstruction = lastBlockInstruction; - final Instruction exceptInstruction = myBuilder.startNode(exceptPart); + final Instruction exceptInstruction = new InstructionImpl(myBuilder, exceptPart); + myBuilder.addNode(exceptInstruction); exceptInstructions.add(exceptInstruction); exceptPart.accept(this); myBuilder.addPendingEdge(node, myBuilder.prevInstruction); } - + // Restore pending + for (Pair pair : myPending) { + myBuilder.addPendingEdge(pair.first, pair.second); + } final PyFinallyPart finallyPart = node.getFinallyPart(); Instruction finallyInstruction = null; Instruction lastFinallyInstruction = null; diff --git a/python/src/com/jetbrains/python/psi/PyForStatement.java b/python/src/com/jetbrains/python/psi/PyForStatement.java index 613884d92c1a..a3466860317a 100644 --- a/python/src/com/jetbrains/python/psi/PyForStatement.java +++ b/python/src/com/jetbrains/python/psi/PyForStatement.java @@ -22,8 +22,7 @@ import org.jetbrains.annotations.Nullable; /** * The 'for/else' statement. */ -public interface PyForStatement extends PyStatement, NameDefiner { +public interface PyForStatement extends PyLoopStatement, NameDefiner { @NotNull PyForPart getForPart(); @Nullable PyElsePart getElsePart(); - } diff --git a/python/testData/codeInsight/controlflow/trybreak.py b/python/testData/codeInsight/controlflow/trybreak.py new file mode 100644 index 000000000000..32dc0919d63d --- /dev/null +++ b/python/testData/codeInsight/controlflow/trybreak.py @@ -0,0 +1,7 @@ +def foo(): + try: + for i in bar: + break + except: + raise Exception() + return 3 \ No newline at end of file diff --git a/python/testData/codeInsight/controlflow/trybreak.txt b/python/testData/codeInsight/controlflow/trybreak.txt new file mode 100644 index 000000000000..f45feedfe5dd --- /dev/null +++ b/python/testData/codeInsight/controlflow/trybreak.txt @@ -0,0 +1,12 @@ +0(1) element: null +1(2) element: PyTryExceptStatement +2(3) element: PyTryPart +3(4) element: PyForStatement +4(5,10) READ ACCESS: bar +5(6) element: PyStatementList +6(7) WRITE ACCESS: i +7(10) element: PyBreakStatement +8(9) element: PyExceptPart +9(11) element: PyRaiseStatement +10(11) element: PyReturnStatement +11() element: null \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java index 391d56c820c8..a1d40aa6b4f3 100644 --- a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java +++ b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java @@ -82,6 +82,14 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { doTest(); } + public void testTryBreak() throws Exception { + final String testName = getTestName(false).toLowerCase(); + configureByFile(testName + ".py"); + final ControlFlow flow = ((PyFunction)((PyFile)myFile).getStatements().get(0)).getControlFlow(); + final String fullPath = getTestDataPath() + testName + ".txt"; + check(fullPath, flow); + } + public void testFunction() throws Exception { final String testName = getTestName(false).toLowerCase(); configureByFile(testName + ".py");