mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-1243 "Unreachable code" false positive with try/finally and raised exception
This commit is contained in:
@@ -476,46 +476,49 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
|
||||
final Ref<Instruction> finallyRef = new Ref<Instruction>(finallyInstruction);
|
||||
final Ref<Instruction> lastFinallyRef = new Ref<Instruction>(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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
try:
|
||||
raise KeyboardInterrupt
|
||||
finally:
|
||||
print 'test'
|
||||
@@ -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
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
<problem>
|
||||
<file>unreachable.py</file>
|
||||
<line>40</line>
|
||||
<line>46</line>
|
||||
<description>This code is unreachable</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
@@ -115,7 +115,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testExit() throws Exception {
|
||||
public void testTryRaiseFinally() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user