Alex Halawin
Alex Halawin

Reputation: 1

custom rule for SonarQube in Java : null check for switch statement

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

Answers (1)

Alex Halawin
Alex Halawin

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

Related Questions