Reputation: 1
I am writing a custom rule for SonarQube in Java. I want to implement the rule that "When the variable type in the parentheses of a switch statement is String and this variable is an external parameter, a null check is required." Anyone has done that before? I failed to find a similar one in github. Thanks.
class AvoidSwitchNullRule{
public void aMethod(String a){
switch (a){ // Noncompliant {{When the variable type in the parentheses of a switch statement is String and this variable is an external parameter, a null check is required.}}
case "1":{
System.out.println(1);
break;
} case "2":{
System.out.println(2);
break;
} default:{
System.out.println("default");
}
}
}
public void bMethod(String a) {
if(StringUtils.isEmpty(a)){
return;
}
switch (a){ // Compliant
case "1":{
System.out.println(1);
break;
} case "2":{
System.out.println(2);
break;
} default:{
System.out.println("default");
}
}
}
}
The above is my example, the below is my rule. Obviously it's long before finished.
@Rule(key = "AvoidSwitchNullRule")
public class AvoidSwitchNullRule extends IssuableSubscriptionVisitor {
@Override
public List<Tree.Kind> nodesToVisit() {
return Arrays.asList(Tree.Kind.SWITCH_STATEMENT);
}
@Override
@ParametersAreNonnullByDefault
public void visitNode(Tree tree) {
SwitchStatementTree switchStatementTree = (SwitchStatementTree) tree;
IdentifierTree identifierTree = (IdentifierTree) switchStatementTree.expression();
if(identifierTree.symbolType().is("java.lang.String") && identifierTree.name().isEmpty()) {
this.context.reportIssue(this,tree, "Switch Parameter must not be null");
}
}
}
Upvotes: 0
Views: 53
Reputation: 1
private boolean isParameter(IdentifierTree identifierTree) {
Symbol symbol = identifierTree.symbol();
MethodTree methodTree = (MethodTree) Objects.requireNonNull(symbol.owner()).declaration();
return symbol.owner().isMethodSymbol() && methodTree.parameters().stream()
.anyMatch(param -> param.simpleName().toString().equals(identifierTree.name()));
}
private boolean hasNullCheckBefore(SwitchStatementTree switchStatementTree, String variableName) {
BlockTree parentBlock = (BlockTree) switchStatementTree.parent();
for (StatementTree statement : parentBlock.body()) {
if (statement.equals(switchStatementTree)) {
break;
}
if (statement.is(Tree.Kind.IF_STATEMENT)) {
IfStatementTree ifStatement = (IfStatementTree) statement;
// StringUtils.isEmpty(b)
if(ifStatement.condition() instanceof MethodInvocationTree){
MethodInvocationTree condition = (MethodInvocationTree) ifStatement.condition();
if(condition.methodSelect() instanceof MemberSelectExpressionTree){
MemberSelectExpressionTree expressionTree = (MemberSelectExpressionTree) condition.methodSelect();
if(expressionTree.expression() instanceof IdentifierTree){
IdentifierTree identifierTree = (IdentifierTree) expressionTree.expression();
IdentifierTree identifierTree1 = expressionTree.identifier();
return ("StringUtils".equals(identifierTree.name()) && "isEmpty".equals(identifierTree1.name()));
}
}
}
// c==null || null==c
if (ifStatement.condition() instanceof BinaryExpressionTree) {
BinaryExpressionTree binaryExpression = (BinaryExpressionTree) ifStatement.condition();
if (("==").equals(binaryExpression.operatorToken().text()) || ("!=").equals(binaryExpression.operatorToken().text())) {
ExpressionTree leftOperand = binaryExpression.leftOperand();
ExpressionTree rightOperand = binaryExpression.rightOperand();
return (leftOperand.is(Tree.Kind.IDENTIFIER) && ((IdentifierTree) leftOperand).name().equals(variableName) &&
rightOperand.is(Tree.Kind.NULL_LITERAL) && "null".equals(((LiteralTree) rightOperand).value())) ||
(rightOperand.is(Tree.Kind.IDENTIFIER) && ((IdentifierTree) rightOperand).name().equals(variableName) &&
leftOperand.is(Tree.Kind.NULL_LITERAL) && "null".equals(((LiteralTree) leftOperand).value()));
}
}
}
}
return false;
}
Upvotes: 0