Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0cc3184
Strongly typed AST: PyFileInputTree
andreaguarino Aug 19, 2019
0f96cd0
Use PyFileInput as root tree
benzonico Aug 19, 2019
e6ec231
Refactor impl to dedicated package and bootstrap statement creation
benzonico Aug 19, 2019
b7de74c
bootstrap PyIfStatementTree
andreaguarino Aug 19, 2019
39918ed
add missing license header
andreaguarino Aug 19, 2019
2e99755
PyIfStatementTree: convert elif and else in PythonTreeMaker
andreaguarino Aug 19, 2019
963188d
Get statements from STMT_LIST and STATEMENT, move PyTree and PythonTr…
andreaguarino Aug 20, 2019
6cf247d
add PyPrintStatementTree
andreaguarino Aug 20, 2019
db997bc
Add PyExecStatementTree
andreaguarino Aug 20, 2019
f7e9a2c
Add PyAssertStatementTree
andreaguarino Aug 20, 2019
965b069
Add PyPassStatementTree
andreaguarino Aug 20, 2019
757bd16
Add PyDelStatementTree
andreaguarino Aug 20, 2019
1d1bab3
add PyReturnStatementTree, dispatch statements conversion
andreaguarino Aug 20, 2019
f4854ae
Migrate Collapsible ifStatement to strongly typed
benzonico Aug 20, 2019
691a6b3
Add PyYieldStatement and PyYieldExpression
andreaguarino Aug 20, 2019
04ec865
Add PyRaiseStatement
andreaguarino Aug 20, 2019
d9994dd
Add PyBreakStatement and PyContinueStatement
andreaguarino Aug 20, 2019
71bdfb5
Function definition statement
benzonico Aug 21, 2019
298f920
Make PyfunctionDefTree a statement
benzonico Aug 21, 2019
c83180d
Class definition tree
benzonico Aug 21, 2019
38adacf
Add ImportName, ImportFrom, AliasedName, DottedName
andreaguarino Aug 21, 2019
7e49566
Add for statement
benzonico Aug 21, 2019
72cb459
Add PyGlobalStatement and PyNonlocalStatement
andreaguarino Aug 21, 2019
fc99312
Add while statement
benzonico Aug 21, 2019
eb612ce
add PyExpressionStatement, add test for PyNonlocalStatement
andreaguarino Aug 21, 2019
d0c7442
ExpressionStatement: implement accept and getKind
andreaguarino Aug 21, 2019
cb7ea52
Add PyTryStatement
andreaguarino Aug 21, 2019
ed02d19
Handle
andreaguarino Aug 22, 2019
574412e
Add with statement
benzonico Aug 22, 2019
bd16f3e
Handle `async with`
andreaguarino Aug 22, 2019
fbbbce8
Improve exception message when a statement is not converted, move Pyt…
andreaguarino Aug 22, 2019
ff22090
Test failure in case of unexpected statement
benzonico Aug 22, 2019
e779db6
adding more test for PythonCheckTree
benzonico Aug 22, 2019
f95a34f
Add test for missing tokens
benzonico Aug 22, 2019
e5fc2ae
add test for BaseTreeVisitor
andreaguarino Aug 22, 2019
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 @@ -23,11 +23,11 @@
import com.sonar.sslr.api.AstNodeType;
import java.util.Collections;
import java.util.Set;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.semantic.Symbol;

public abstract class AbstractCallExpressionCheck extends PythonCheck {
public abstract class AbstractCallExpressionCheck extends PythonCheckAstNode {

protected abstract Set<String> functionsToCheck();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
package org.sonar.python.checks;

import java.util.regex.Pattern;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;

public abstract class AbstractNameCheck extends PythonCheck {
public abstract class AbstractNameCheck extends PythonCheckAstNode {

private Pattern pattern = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import com.sonar.sslr.api.AstNodeType;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;

@Rule(key = AfterJumpStatementCheck.CHECK_KEY)
public class AfterJumpStatementCheck extends PythonCheck {
public class AfterJumpStatementCheck extends PythonCheckAstNode {

public static final String CHECK_KEY = "S1763";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
import java.util.Collections;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonTokenType;

@Rule(key = "S1717")
public class BackslashInStringCheck extends PythonCheck {
public class BackslashInStringCheck extends PythonCheckAstNode {

private static final String MESSAGE = "Remove this \"\\\", add another \"\\\" to escape it, or make this a raw string.";
private static final String VALID_ESCAPED_CHARACTERS = "abfnrtvxnNrtuU\\'\"0123456789\n\r";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
import java.util.Collections;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.api.PythonPunctuator;

@Rule(key = BackticksUsageCheck.CHECK_KEY)
public class BackticksUsageCheck extends PythonCheck {
public class BackticksUsageCheck extends PythonCheckAstNode {
public static final String CHECK_KEY = "BackticksUsage";

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import com.sonar.sslr.api.AstNodeType;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;

@Rule(key = BreakContinueOutsideLoopCheck.CHECK_KEY)
public class BreakContinueOutsideLoopCheck extends PythonCheck {
public class BreakContinueOutsideLoopCheck extends PythonCheckAstNode {

private static final String MESSAGE = "Remove this \"%s\" statement";
public static final String CHECK_KEY = "S1716";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
*/
package org.sonar.python.checks;

import org.sonar.python.PythonCheck;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import org.sonar.python.checks.hotspots.CommandLineArgsCheck;
import org.sonar.python.checks.hotspots.DebugModeCheck;
import org.sonar.python.checks.hotspots.DynamicCodeExecutionCheck;
Expand All @@ -38,7 +40,7 @@ private CheckList() {
}

public static Iterable<Class> getChecks() {
return PythonCheck.immutableSet(
return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
AfterJumpStatementCheck.class,
BackslashInStringCheck.class,
BackticksUsageCheck.class,
Expand Down Expand Up @@ -102,7 +104,7 @@ public static Iterable<Class> getChecks() {
UselessParenthesisAfterKeywordCheck.class,
UselessParenthesisCheck.class,
XPathCheck.class
);
)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.metrics.ComplexityVisitor;

@Rule(key = "ClassComplexity")
public class ClassComplexityCheck extends PythonCheck {
public class ClassComplexityCheck extends PythonCheckAstNode {
private static final int DEFAULT_MAXIMUM_CLASS_COMPLEXITY_THRESHOLD = 200;
private static final String MESSAGE = "Class has a complexity of %s which is greater than %s authorized.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.python.IssueLocation;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.metrics.CognitiveComplexityVisitor;

@Rule(key = CognitiveComplexityFunctionCheck.CHECK_KEY)
public class CognitiveComplexityFunctionCheck extends PythonCheck {
public class CognitiveComplexityFunctionCheck extends PythonCheckAstNode {

private static final String MESSAGE = "Refactor this function to reduce its Cognitive Complexity from %s to the %s allowed.";
public static final String CHECK_KEY = "S3776";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,54 +19,50 @@
*/
package org.sonar.python.checks;

import com.sonar.sslr.api.AstNode;
import com.sonar.sslr.api.AstNodeType;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.api.PythonKeyword;
import org.sonar.sslr.ast.AstSelect;
import org.sonar.python.PythonCheckTree;
import org.sonar.python.PythonVisitorContext;
import org.sonar.python.api.tree.PyIfStatementTree;
import org.sonar.python.api.tree.PyStatementTree;
import org.sonar.python.api.tree.Tree;

@Rule(key = CollapsibleIfStatementsCheck.CHECK_KEY)
public class CollapsibleIfStatementsCheck extends PythonCheck {
public class CollapsibleIfStatementsCheck extends PythonCheckTree {
public static final String CHECK_KEY = "S1066";
private static final String MESSAGE = "Merge this if statement with the enclosing one.";

private Set<Tree> ignored = new HashSet<>();

@Override
public Set<AstNodeType> subscribedKinds() {
return Collections.singleton(PythonGrammar.IF_STMT);
public void scanFile(PythonVisitorContext visitorContext) {
ignored.clear();
super.scanFile(visitorContext);
}

@Override
public void visitNode(AstNode node) {
AstNode suite = node.getLastChild(PythonGrammar.SUITE);
if (suite.getPreviousSibling().getPreviousSibling().is(PythonKeyword.ELSE)) {
return;
}
AstNode singleIfChild = singleIfChild(suite);
if (singleIfChild != null && !hasElseOrElif(singleIfChild)) {
addIssue(singleIfChild.getToken(), MESSAGE)
.secondary(node.getFirstChild(), "enclosing");
public void visitIfStatement(PyIfStatementTree ifStatement) {
List<PyStatementTree> statements = ifStatement.body();
if (!ifStatement.elifBranches().isEmpty()) {
if (ifStatement.elseBranch() == null) {
ignored.addAll(ifStatement.elifBranches().subList(0, ifStatement.elifBranches().size() - 1));
} else {
ignored.addAll(ifStatement.elifBranches());
}
}
}

private static boolean hasElseOrElif(AstNode ifNode) {
return ifNode.hasDirectChildren(PythonKeyword.ELIF) || ifNode.hasDirectChildren(PythonKeyword.ELSE);
}

private static AstNode singleIfChild(AstNode suite) {
List<AstNode> statements = suite.getChildren(PythonGrammar.STATEMENT);
if (statements.size() == 1) {
AstSelect nestedIf = statements.get(0).select()
.children(PythonGrammar.COMPOUND_STMT)
.children(PythonGrammar.IF_STMT);
if (nestedIf.size() == 1) {
return nestedIf.get(0);
if (!ignored.contains(ifStatement)
&& ifStatement.elseBranch() == null
&& ifStatement.elifBranches().isEmpty()
&& statements.size() == 1
&& statements.get(0).is(Tree.Kind.IF_STMT)) {
PyIfStatementTree singleIfChild = (PyIfStatementTree) statements.get(0);
if (singleIfChild.isElif() || singleIfChild.elseBranch() != null || !singleIfChild.elifBranches().isEmpty()) {
return;
}
addIssue(singleIfChild.keyword(), MESSAGE).secondary(ifStatement.astNode(), "enclosing");
}
return null;
super.visitIfStatement(ifStatement);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
import java.util.regex.Pattern;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;

@Rule(key = CommentRegularExpressionCheck.CHECK_KEY)
public class CommentRegularExpressionCheck extends PythonCheck {
public class CommentRegularExpressionCheck extends PythonCheckAstNode {
public static final String CHECK_KEY = "CommentRegularExpression";
private static final String DEFAULT_REGULAR_EXPRESSION = "";
private static final String DEFAULT_MESSAGE = "The regular expression matches this comment";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@
import java.util.Set;
import javax.annotation.Nullable;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.PythonConfiguration;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.api.PythonTokenType;
import org.sonar.python.parser.PythonParser;

@Rule(key = CommentedCodeCheck.CHECK_KEY)
public class CommentedCodeCheck extends PythonCheck {
public class CommentedCodeCheck extends PythonCheckAstNode {

public static final String CHECK_KEY = "S125";
public static final String MESSAGE = "Remove this commented out code.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
import java.util.List;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.sslr.ast.AstSelect;

@Rule(key = DuplicatedMethodFieldNamesCheck.CHECK_KEY)
public class DuplicatedMethodFieldNamesCheck extends PythonCheck {
public class DuplicatedMethodFieldNamesCheck extends PythonCheckAstNode {

public static final String CHECK_KEY = "S1845";
private static final String MESSAGE = "Rename %s \"%s\" to prevent any misunderstanding/clash with %s \"%s\" defined on line %s";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
import java.util.Set;
import java.util.function.Predicate;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.sslr.ast.AstSelect;

@Rule(key = EmptyNestedBlockCheck.CHECK_KEY)
public class EmptyNestedBlockCheck extends PythonCheck {
public class EmptyNestedBlockCheck extends PythonCheckAstNode {
public static final String CHECK_KEY = "S108";
private static final Predicate<AstNode> NOT_PASS_PREDICATE = new NotPassPredicate();
private static final String MESSAGE = "Either remove or fill this block of code.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
import java.util.Collections;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;

@Rule(key = ExecStatementUsageCheck.CHECK_KEY)
public class ExecStatementUsageCheck extends PythonCheck {
public class ExecStatementUsageCheck extends PythonCheckAstNode {
public static final String CHECK_KEY = "ExecStatementUsage";
@Override
public Set<AstNodeType> subscribedKinds() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.IssueLocation;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.api.PythonPunctuator;

@Rule(key = ExitHasBadArgumentsCheck.CHECK_KEY)
public class ExitHasBadArgumentsCheck extends PythonCheck {
public class ExitHasBadArgumentsCheck extends PythonCheckAstNode {

public static final String MESSAGE_ADD = "Add the missing argument.";
public static final String MESSAGE_REMOVE = "Remove the unnecessary argument.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
import java.util.List;
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;

@Rule(key = FieldDuplicatesClassNameCheck.CHECK_KEY)
public class FieldDuplicatesClassNameCheck extends PythonCheck {
public class FieldDuplicatesClassNameCheck extends PythonCheckAstNode {

public static final String CHECK_KEY = "S1700";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
import java.util.regex.Pattern;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;

@Rule(key = FieldNameCheck.CHECK_KEY)
public class FieldNameCheck extends PythonCheck {
public class FieldNameCheck extends PythonCheckAstNode {

public static final String CHECK_KEY = "S116";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import java.text.MessageFormat;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.metrics.ComplexityVisitor;

@Rule(key = "FileComplexity")
public class FileComplexityCheck extends PythonCheck {
public class FileComplexityCheck extends PythonCheckAstNode {
private static final int DEFAULT_MAXIMUM_FILE_COMPLEXITY_THRESHOLD = 200;

@RuleProperty(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
import com.sonar.sslr.api.Trivia;
import java.util.regex.Pattern;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;

@Rule(key = FixmeCommentCheck.CHECK_KEY)
public class FixmeCommentCheck extends PythonCheck {
public class FixmeCommentCheck extends PythonCheckAstNode {

public static final String CHECK_KEY = "S1134";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
import java.util.Set;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonGrammar;
import org.sonar.python.metrics.ComplexityVisitor;

@Rule(key = "FunctionComplexity")
public class FunctionComplexityCheck extends PythonCheck {
public class FunctionComplexityCheck extends PythonCheckAstNode {
private static final int DEFAULT_MAXIMUM_FUNCTION_COMPLEXITY_THRESHOLD = 15;
private static final String MESSAGE = "Function has a complexity of %s which is greater than %s authorized.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.sonar.check.Rule;
import org.sonar.python.PythonCheck;
import org.sonar.python.PythonCheckAstNode;
import org.sonar.python.api.PythonTokenType;

@Rule(key = HardcodedIPCheck.CHECK_KEY)
public class HardcodedIPCheck extends PythonCheck {
public class HardcodedIPCheck extends PythonCheckAstNode {
public static final String CHECK_KEY = "S1313";

private static final String IPV4_ALONE = "(?<ipv4>(?:\\d{1,3}\\.){3}\\d{1,3})";
Expand Down
Loading