ExplicitInitializationCheck.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 com.puppycrawl.tools.checkstyle.StatelessCheck;
23
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
24
import com.puppycrawl.tools.checkstyle.api.DetailAST;
25
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
26
import com.puppycrawl.tools.checkstyle.utils.CheckUtils;
27
import com.puppycrawl.tools.checkstyle.utils.ScopeUtils;
28
29
/**
30
 * <p>
31
 * Checks if any class or object member explicitly initialized
32
 * to default for its type value ({@code null} for object
33
 * references, zero for numeric types and {@code char}
34
 * and {@code false} for {@code boolean}.
35
 * </p>
36
 * <p>
37
 * Rationale: each instance variable gets
38
 * initialized twice, to the same value.  Java
39
 * initializes each instance variable to its default
40
 * value (0 or null) before performing any
41
 * initialization specified in the code.  So in this case,
42
 * x gets initialized to 0 twice, and bar gets initialized
43
 * to null twice.  So there is a minor inefficiency.  This style of
44
 * coding is a hold-over from C/C++ style coding,
45
 * and it shows that the developer isn't really confident that
46
 * Java really initializes instance variables to default
47
 * values.
48
 * </p>
49
 *
50
 * @author o_sukhodolsky
51
 */
52
@StatelessCheck
53
public class ExplicitInitializationCheck extends AbstractCheck {
54
55
    /**
56
     * A key is pointing to the warning message text in "messages.properties"
57
     * file.
58
     */
59
    public static final String MSG_KEY = "explicit.init";
60
61
    /** Whether only explicit initialization made to null should be checked.**/
62
    private boolean onlyObjectReferences;
63
64
    @Override
65
    public final int[] getDefaultTokens() {
66 1 1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
67
    }
68
69
    @Override
70
    public final int[] getRequiredTokens() {
71 1 1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {TokenTypes.VARIABLE_DEF};
72
    }
73
74
    @Override
75
    public final int[] getAcceptableTokens() {
76 1 1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getRequiredTokens();
77
    }
78
79
    /**
80
     * Sets whether only explicit initialization made to null should be checked.
81
     * @param onlyObjectReferences whether only explicit initialization made to null
82
     *                             should be checked
83
     */
84
    public void setOnlyObjectReferences(boolean onlyObjectReferences) {
85
        this.onlyObjectReferences = onlyObjectReferences;
86
    }
87
88
    @Override
89
    public void visitToken(DetailAST ast) {
90 1 1. visitToken : negated conditional → KILLED
        if (!isSkipCase(ast)) {
91
            final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
92
            final DetailAST exprStart =
93
                assign.getFirstChild().getFirstChild();
94
            final DetailAST type = ast.findFirstToken(TokenTypes.TYPE);
95 1 1. visitToken : negated conditional → KILLED
            if (isObjectType(type)
96 1 1. visitToken : negated conditional → KILLED
                && exprStart.getType() == TokenTypes.LITERAL_NULL) {
97
                final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
98 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED
                log(ident, MSG_KEY, ident.getText(), "null");
99
            }
100 1 1. visitToken : negated conditional → KILLED
            if (!onlyObjectReferences) {
101 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::validateNonObjects → KILLED
                validateNonObjects(ast);
102
            }
103
        }
104
    }
105
106
    /**
107
     * Checks for explicit initializations made to 'false', '0' and '\0'.
108
     * @param ast token being checked for explicit initializations
109
     */
110
    private void validateNonObjects(DetailAST ast) {
111
        final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
112
        final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
113
        final DetailAST exprStart =
114
                assign.getFirstChild().getFirstChild();
115
        final DetailAST type = ast.findFirstToken(TokenTypes.TYPE);
116
        final int primitiveType = type.getFirstChild().getType();
117 1 1. validateNonObjects : negated conditional → KILLED
        if (primitiveType == TokenTypes.LITERAL_BOOLEAN
118 1 1. validateNonObjects : negated conditional → KILLED
                && exprStart.getType() == TokenTypes.LITERAL_FALSE) {
119 1 1. validateNonObjects : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED
            log(ident, MSG_KEY, ident.getText(), "false");
120
        }
121 2 1. validateNonObjects : negated conditional → KILLED
2. validateNonObjects : negated conditional → KILLED
        if (isNumericType(primitiveType) && isZero(exprStart)) {
122 1 1. validateNonObjects : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED
            log(ident, MSG_KEY, ident.getText(), "0");
123
        }
124 1 1. validateNonObjects : negated conditional → KILLED
        if (primitiveType == TokenTypes.LITERAL_CHAR
125 1 1. validateNonObjects : negated conditional → KILLED
                && isZeroChar(exprStart)) {
126 1 1. validateNonObjects : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED
            log(ident, MSG_KEY, ident.getText(), "\\0");
127
        }
128
    }
129
130
    /**
131
     * Examine char literal for initializing to default value.
132
     * @param exprStart expression
133
     * @return true is literal is initialized by zero symbol
134
     */
135
    private static boolean isZeroChar(DetailAST exprStart) {
136 2 1. isZeroChar : negated conditional → KILLED
2. isZeroChar : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return isZero(exprStart)
137 1 1. isZeroChar : negated conditional → KILLED
            || exprStart.getType() == TokenTypes.CHAR_LITERAL
138 1 1. isZeroChar : negated conditional → KILLED
            && "'\\0'".equals(exprStart.getText());
139
    }
140
141
    /**
142
     * Checks for cases that should be skipped: no assignment, local variable, final variables.
143
     * @param ast Variable def AST
144
     * @return true is that is a case that need to be skipped.
145
     */
146
    private static boolean isSkipCase(DetailAST ast) {
147
        boolean skipCase = true;
148
149
        // do not check local variables and
150
        // fields declared in interface/annotations
151 1 1. isSkipCase : negated conditional → KILLED
        if (!ScopeUtils.isLocalVariableDef(ast)
152 1 1. isSkipCase : negated conditional → KILLED
                && !ScopeUtils.isInInterfaceOrAnnotationBlock(ast)) {
153
            final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
154
155 1 1. isSkipCase : negated conditional → KILLED
            if (assign != null) {
156
                final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
157 1 1. isSkipCase : negated conditional → KILLED
                skipCase = modifiers.findFirstToken(TokenTypes.FINAL) != null;
158
            }
159
        }
160 1 1. isSkipCase : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return skipCase;
161
    }
162
163
    /**
164
     * Determines if a given type is an object type.
165
     * @param type type to check.
166
     * @return true if it is an object type.
167
     */
168
    private static boolean isObjectType(DetailAST type) {
169
        final int objectType = type.getFirstChild().getType();
170 4 1. isObjectType : negated conditional → KILLED
2. isObjectType : negated conditional → KILLED
3. isObjectType : negated conditional → KILLED
4. isObjectType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return objectType == TokenTypes.IDENT || objectType == TokenTypes.DOT
171
                || objectType == TokenTypes.ARRAY_DECLARATOR;
172
    }
173
174
    /**
175
     * Determine if a given type is a numeric type.
176
     * @param type code of the type for check.
177
     * @return true if it's a numeric type.
178
     * @see TokenTypes
179
     */
180
    private static boolean isNumericType(int type) {
181 7 1. isNumericType : negated conditional → KILLED
2. isNumericType : negated conditional → KILLED
3. isNumericType : negated conditional → KILLED
4. isNumericType : negated conditional → KILLED
5. isNumericType : negated conditional → KILLED
6. isNumericType : negated conditional → KILLED
7. isNumericType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return type == TokenTypes.LITERAL_BYTE
182
                || type == TokenTypes.LITERAL_SHORT
183
                || type == TokenTypes.LITERAL_INT
184
                || type == TokenTypes.LITERAL_FLOAT
185
                || type == TokenTypes.LITERAL_LONG
186
                || type == TokenTypes.LITERAL_DOUBLE;
187
    }
188
189
    /**
190
     * Checks if given node contains numeric constant for zero.
191
     *
192
     * @param expr node to check.
193
     * @return true if given node contains numeric constant for zero.
194
     */
195
    private static boolean isZero(DetailAST expr) {
196
        final int type = expr.getType();
197
        final boolean isZero;
198
        switch (type) {
199
            case TokenTypes.NUM_FLOAT:
200
            case TokenTypes.NUM_DOUBLE:
201
            case TokenTypes.NUM_INT:
202
            case TokenTypes.NUM_LONG:
203
                final String text = expr.getText();
204 1 1. isZero : negated conditional → KILLED
                isZero = Double.compare(CheckUtils.parseDouble(text, type), 0.0) == 0;
205
                break;
206
            default:
207
                isZero = false;
208
        }
209 1 1. isZero : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return isZero;
210
    }
211
212
}

Mutations

66

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

71

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

76

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

90

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

95

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

96

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

98

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED

100

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

101

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::validateNonObjects → KILLED

117

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

118

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

119

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED

121

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

2.2
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

122

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED

124

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

125

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

126

1.1
Location : validateNonObjects
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/coding/ExplicitInitializationCheck::log → KILLED

136

1.1
Location : isZeroChar
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

2.2
Location : isZeroChar
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

137

1.1
Location : isZeroChar
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

138

1.1
Location : isZeroChar
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

151

1.1
Location : isSkipCase
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

152

1.1
Location : isSkipCase
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

155

1.1
Location : isSkipCase
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

157

1.1
Location : isSkipCase
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

160

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

170

1.1
Location : isObjectType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

2.2
Location : isObjectType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

3.3
Location : isObjectType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

4.4
Location : isObjectType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

181

1.1
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

2.2
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

3.3
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

4.4
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

5.5
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

6.6
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

7.7
Location : isNumericType
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

204

1.1
Location : isZero
Killed by : com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest.testDefault(com.puppycrawl.tools.checkstyle.checks.coding.ExplicitInitializationCheckTest)
negated conditional → KILLED

209

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

Active mutators

Tests examined


Report generated by PIT 1.3.1