SimplifyBooleanReturnCheck.java

1
////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2018 the original author or authors.
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
// Lesser General Public License for more details.
14
//
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
////////////////////////////////////////////////////////////////////////////////
19
20
package com.puppycrawl.tools.checkstyle.checks.coding;
21
22
import antlr.collections.AST;
23
import com.puppycrawl.tools.checkstyle.StatelessCheck;
24
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
25
import com.puppycrawl.tools.checkstyle.api.DetailAST;
26
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
27
28
/**
29
 * <p>
30
 * Checks for overly complicated boolean return statements.
31
 * Idea shamelessly stolen from the equivalent PMD rule (pmd.sourceforge.net).
32
 * </p>
33
 * <p>
34
 * An example of how to configure the check is:
35
 * </p>
36
 * <pre>
37
 * &lt;module name="SimplifyBooleanReturn"/&gt;
38
 * </pre>
39
 * @author Lars Kühne
40
 */
41
@StatelessCheck
42
public class SimplifyBooleanReturnCheck
43
    extends AbstractCheck {
44
45
    /**
46
     * A key is pointing to the warning message text in "messages.properties"
47
     * file.
48
     */
49
    public static final String MSG_KEY = "simplify.boolReturn";
50
51
    @Override
52
    public int[] getAcceptableTokens() {
53 1 1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
54
    }
55
56
    @Override
57
    public int[] getDefaultTokens() {
58 1 1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
59
    }
60
61
    @Override
62
    public int[] getRequiredTokens() {
63 1 1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {TokenTypes.LITERAL_IF};
64
    }
65
66
    @Override
67
    public void visitToken(DetailAST ast) {
68
        // LITERAL_IF has the following four or five children:
69
        // '('
70
        // condition
71
        // ')'
72
        // thenStatement
73
        // [ LITERAL_ELSE (with the elseStatement as a child) ]
74
75
        // don't bother if this is not if then else
76
        final AST elseLiteral =
77
            ast.findFirstToken(TokenTypes.LITERAL_ELSE);
78 1 1. visitToken : negated conditional → KILLED
        if (elseLiteral != null) {
79
            final AST elseStatement = elseLiteral.getFirstChild();
80
81
            // skip '(' and ')'
82
            final AST condition = ast.getFirstChild().getNextSibling();
83
            final AST thenStatement = condition.getNextSibling().getNextSibling();
84
85 1 1. visitToken : negated conditional → KILLED
            if (canReturnOnlyBooleanLiteral(thenStatement)
86 1 1. visitToken : negated conditional → KILLED
                && canReturnOnlyBooleanLiteral(elseStatement)) {
87 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::log → KILLED
                log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY);
88
            }
89
        }
90
    }
91
92
    /**
93
     * Returns if an AST is a return statement with a boolean literal
94
     * or a compound statement that contains only such a return statement.
95
     *
96
     * <p>Returns {@code true} iff ast represents
97
     * <br/>
98
     * <pre>
99
     * return true/false;
100
     * </pre>
101
     * or
102
     * <br/>
103
     * <pre>
104
     * {
105
     *   return true/false;
106
     * }
107
     * </pre>
108
     *
109
     * @param ast the syntax tree to check
110
     * @return if ast is a return statement with a boolean literal.
111
     */
112
    private static boolean canReturnOnlyBooleanLiteral(AST ast) {
113
        boolean result = true;
114 1 1. canReturnOnlyBooleanLiteral : negated conditional → KILLED
        if (!isBooleanLiteralReturnStatement(ast)) {
115
            final AST firstStatement = ast.getFirstChild();
116
            result = isBooleanLiteralReturnStatement(firstStatement);
117
        }
118 1 1. canReturnOnlyBooleanLiteral : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return result;
119
    }
120
121
    /**
122
     * Returns if an AST is a return statement with a boolean literal.
123
     *
124
     * <p>Returns {@code true} iff ast represents
125
     * <br/>
126
     * <pre>
127
     * return true/false;
128
     * </pre>
129
     *
130
     * @param ast the syntax tree to check
131
     * @return if ast is a return statement with a boolean literal.
132
     */
133
    private static boolean isBooleanLiteralReturnStatement(AST ast) {
134
        boolean booleanReturnStatement = false;
135
136 2 1. isBooleanLiteralReturnStatement : negated conditional → KILLED
2. isBooleanLiteralReturnStatement : negated conditional → KILLED
        if (ast != null && ast.getType() == TokenTypes.LITERAL_RETURN) {
137
            final AST expr = ast.getFirstChild();
138
139 1 1. isBooleanLiteralReturnStatement : negated conditional → KILLED
            if (expr.getType() != TokenTypes.SEMI) {
140
                final AST value = expr.getFirstChild();
141
                booleanReturnStatement = isBooleanLiteralType(value.getType());
142
            }
143
        }
144 1 1. isBooleanLiteralReturnStatement : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return booleanReturnStatement;
145
    }
146
147
    /**
148
     * Checks if a token type is a literal true or false.
149
     * @param tokenType the TokenType
150
     * @return true iff tokenType is LITERAL_TRUE or LITERAL_FALSE
151
     */
152
    private static boolean isBooleanLiteralType(final int tokenType) {
153 1 1. isBooleanLiteralType : negated conditional → KILLED
        final boolean isTrue = tokenType == TokenTypes.LITERAL_TRUE;
154 1 1. isBooleanLiteralType : negated conditional → KILLED
        final boolean isFalse = tokenType == TokenTypes.LITERAL_FALSE;
155 3 1. isBooleanLiteralType : negated conditional → KILLED
2. isBooleanLiteralType : negated conditional → KILLED
3. isBooleanLiteralType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return isTrue || isFalse;
156
    }
157
158
}

Mutations

53

1.1
Location : getAcceptableTokens
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testTokensNotNull(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED

58

1.1
Location : getDefaultTokens
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testTokensNotNull(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED

63

1.1
Location : getRequiredTokens
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testTokensNotNull(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED

78

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

85

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

86

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

87

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/SimplifyBooleanReturnCheck::log → KILLED

114

1.1
Location : canReturnOnlyBooleanLiteral
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

118

1.1
Location : canReturnOnlyBooleanLiteral
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

136

1.1
Location : isBooleanLiteralReturnStatement
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

2.2
Location : isBooleanLiteralReturnStatement
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

139

1.1
Location : isBooleanLiteralReturnStatement
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

144

1.1
Location : isBooleanLiteralReturnStatement
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

153

1.1
Location : isBooleanLiteralType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

154

1.1
Location : isBooleanLiteralType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

155

1.1
Location : isBooleanLiteralType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

2.2
Location : isBooleanLiteralType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
negated conditional → KILLED

3.3
Location : isBooleanLiteralType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest.testIt(com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

Active mutators

Tests examined


Report generated by PIT 1.3.1