Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private static void checkCfg(@Nullable ControlFlowGraph cfg, SubscriptionContext
.filter(block -> cfgBlock.equals(block.syntacticSuccessor()))
.map(block -> block.elements().get(block.elements().size() - 1))
.collect(Collectors.toList());
if (isInsideFinallyClause(firstElement) || jumpStatements.stream().anyMatch(AfterJumpStatementCheck::isRaiseInsideWithStatement)) {
if (isInsideFinallyClause(firstElement)) {
continue;
}
Tree lastElement = cfgBlock.elements().get(cfgBlock.elements().size() - 1);
Expand All @@ -68,12 +68,6 @@ private static void checkCfg(@Nullable ControlFlowGraph cfg, SubscriptionContext
}
}

// To avoid FP, we assume that exception raised inside with statement will be suppressed by __exit__() method of Context Manager
// see https://docs.python.org/3/reference/compound_stmts.html#the-with-statement
private static boolean isRaiseInsideWithStatement(Tree element) {
return element.is(Kind.RAISE_STMT) && TreeUtils.firstAncestorOfKind(element, Kind.WITH_STMT) != null;
}

// due to CFG limitation on jump statements inside try blocks, we exclude finally clause to avoid FP.
// TODO: After SONARPY-448 is implemented, we should remove this exclusion
private static boolean isInsideFinallyClause(Tree element) {
Expand Down
5 changes: 5 additions & 0 deletions python-checks/src/test/resources/checks/afterJumpStatement.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,8 @@ def while_dead_code_in_else_clause_condition_true(x):
else:
print('dead code!') # FN, we don't take into account while condition being always true
print("end of loop")

def code_after_with():
with A():
return e
return False
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private PythonCfgBlock build(List<Statement> statements, PythonCfgBlock successo
private PythonCfgBlock build(Statement statement, PythonCfgBlock currentBlock) {
switch (statement.getKind()) {
case WITH_STMT:
return build(((WithStatement) statement).statements().statements(), currentBlock);
return buildWithStatement((WithStatement) statement, currentBlock);
case CLASSDEF:
return build(((ClassDef) statement).body().statements(), currentBlock);
case RETURN_STMT:
Expand All @@ -155,6 +155,13 @@ private PythonCfgBlock build(Statement statement, PythonCfgBlock currentBlock) {
return currentBlock;
}

private PythonCfgBlock buildWithStatement(WithStatement withStatement, PythonCfgBlock successor) {
PythonCfgBlock withBodyBlock = build(withStatement.statements().statements(), createSimpleBlock(successor));
// exceptions may be raised inside with block and be caught by context manager
// see https://docs.python.org/3/reference/compound_stmts.html#the-with-statement
return createBranchingBlock(withStatement, withBodyBlock, successor);
}

private PythonCfgBlock tryStatement(TryStatement tryStatement, PythonCfgBlock successor) {
PythonCfgBlock finallyOrAfterTryBlock = successor;
FinallyClause finallyClause = tryStatement.finallyClause();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,9 @@ public void raise_in_try() {
@Test
public void with_statement() {
verifyCfg(
"before(succ = [if_body, END])",
"before(succ = [with_block, END])",
"with A() as a:",
" if cond:",
" if with_block(succ = [if_body, END]):",
" if_body(succ = [END])"
);
}
Expand Down