|
21 | 21 |
|
22 | 22 | import java.util.Arrays; |
23 | 23 | import java.util.List; |
| 24 | +import java.util.Objects; |
24 | 25 | import java.util.Optional; |
25 | 26 | import java.util.stream.Collectors; |
26 | 27 | import java.util.stream.Stream; |
|
45 | 46 | import org.sonar.plugins.python.api.tree.Tree; |
46 | 47 | import org.sonar.plugins.python.api.tree.Tree.Kind; |
47 | 48 | import org.sonar.plugins.python.api.tree.UnaryExpression; |
| 49 | +import org.sonar.plugins.python.api.tree.WithItem; |
| 50 | +import org.sonar.plugins.python.api.tree.WithStatement; |
48 | 51 | import org.sonar.python.tree.TreeUtils; |
49 | 52 |
|
50 | 53 | @Rule(key = "S905") |
@@ -110,9 +113,26 @@ private static void checkNode(SubscriptionContext ctx) { |
110 | 113 | if (parent == null || !parent.is(Kind.EXPRESSION_STMT)) { |
111 | 114 | return; |
112 | 115 | } |
| 116 | + if (isWithinContextlibSuppress(tree)) { |
| 117 | + return; |
| 118 | + } |
113 | 119 | ctx.addIssue(tree, MESSAGE); |
114 | 120 | } |
115 | 121 |
|
| 122 | + private static boolean isWithinContextlibSuppress(Tree tree) { |
| 123 | + Tree withParent = TreeUtils.firstAncestorOfKind(tree, Kind.WITH_STMT); |
| 124 | + if (withParent != null) { |
| 125 | + WithStatement withStatement = (WithStatement) withParent; |
| 126 | + return withStatement.withItems().stream() |
| 127 | + .map(WithItem::test) |
| 128 | + .filter(item -> item.is(Kind.CALL_EXPR)) |
| 129 | + .map(item -> ((CallExpression) item).calleeSymbol()) |
| 130 | + .filter(Objects::nonNull) |
| 131 | + .anyMatch(s -> "contextlib.suppress".equals(s.fullyQualifiedName())); |
| 132 | + } |
| 133 | + return false; |
| 134 | + } |
| 135 | + |
116 | 136 | private static boolean isBooleanExpressionWithCalls(Tree tree) { |
117 | 137 | return (tree.is(Kind.AND) || tree.is(Kind.OR) || tree.is(Kind.NOT)) && (TreeUtils.hasDescendant(tree, t -> t.is(Kind.CALL_EXPR))); |
118 | 138 | } |
@@ -172,8 +192,8 @@ private void checkBinaryExpression(SubscriptionContext ctx) { |
172 | 192 |
|
173 | 193 | private static boolean couldBePython2PrintStatement(BinaryExpression binaryExpression) { |
174 | 194 | return TreeUtils.hasDescendant(binaryExpression, t -> t.is(Kind.CALL_EXPR) |
175 | | - && ((CallExpression) t).callee().is(Kind.NAME) |
176 | | - && ((Name) ((CallExpression) t).callee()).name().equals("print")); |
| 195 | + && ((CallExpression) t).callee().is(Kind.NAME) |
| 196 | + && ((Name) ((CallExpression) t).callee()).name().equals("print")); |
177 | 197 | } |
178 | 198 |
|
179 | 199 | private void checkUnaryExpression(SubscriptionContext ctx) { |
|
0 commit comments