UncommentedMainCheck.java

1
////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2017 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;
21
22
import java.util.Optional;
23
import java.util.regex.Pattern;
24
25
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26
import com.puppycrawl.tools.checkstyle.api.DetailAST;
27
import com.puppycrawl.tools.checkstyle.api.FullIdent;
28
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29
30
/**
31
 * Detects uncommented main methods. Basically detects
32
 * any main method, since if it is detectable
33
 * that means it is uncommented.
34
 *
35
 * <pre class="body">
36
 * &lt;module name=&quot;UncommentedMain&quot;/&gt;
37
 * </pre>
38
 *
39
 * @author Michael Yui
40
 * @author o_sukhodolsky
41
 */
42
public class UncommentedMainCheck
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 = "uncommented.main";
50
51
    /** Compiled regexp to exclude classes from check. */
52
    private Pattern excludedClasses = Pattern.compile("^$");
53
    /** Current class name. */
54
    private String currentClass;
55
    /** Current package. */
56
    private FullIdent packageName;
57
    /** Class definition depth. */
58
    private int classDepth;
59
60
    /**
61
     * Set the excluded classes pattern.
62
     * @param excludedClasses a pattern
63
     */
64
    public void setExcludedClasses(Pattern excludedClasses) {
65
        this.excludedClasses = excludedClasses;
66
    }
67
68
    @Override
69
    public int[] getAcceptableTokens() {
70 1 1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return new int[] {
71
            TokenTypes.METHOD_DEF,
72
            TokenTypes.CLASS_DEF,
73
            TokenTypes.PACKAGE_DEF,
74
        };
75
    }
76
77
    @Override
78
    public int[] getDefaultTokens() {
79 1 1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getAcceptableTokens();
80
    }
81
82
    @Override
83
    public int[] getRequiredTokens() {
84 1 1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED
        return getAcceptableTokens();
85
    }
86
87
    @Override
88
    public void beginTree(DetailAST rootAST) {
89
        packageName = FullIdent.createFullIdent(null);
90
        currentClass = null;
91
        classDepth = 0;
92
    }
93
94
    @Override
95
    public void leaveToken(DetailAST ast) {
96 1 1. leaveToken : negated conditional → KILLED
        if (ast.getType() == TokenTypes.CLASS_DEF) {
97 1 1. leaveToken : negated conditional → SURVIVED
            if (classDepth == 1) {
98
                currentClass = null;
99
            }
100 1 1. leaveToken : Replaced integer subtraction with addition → KILLED
            classDepth--;
101
        }
102
    }
103
104
    @Override
105
    public void visitToken(DetailAST ast) {
106
107
        switch (ast.getType()) {
108
            case TokenTypes.PACKAGE_DEF:
109 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::visitPackageDef → KILLED
                visitPackageDef(ast);
110
                break;
111
            case TokenTypes.CLASS_DEF:
112 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::visitClassDef → KILLED
                visitClassDef(ast);
113
                break;
114
            case TokenTypes.METHOD_DEF:
115 1 1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::visitMethodDef → KILLED
                visitMethodDef(ast);
116
                break;
117
            default:
118
                throw new IllegalStateException(ast.toString());
119
        }
120
    }
121
122
    /**
123
     * Sets current package.
124
     * @param packageDef node for package definition
125
     */
126
    private void visitPackageDef(DetailAST packageDef) {
127
        packageName = FullIdent.createFullIdent(packageDef.getLastChild()
128
                .getPreviousSibling());
129
    }
130
131
    /**
132
     * If not inner class then change current class name.
133
     * @param classDef node for class definition
134
     */
135
    private void visitClassDef(DetailAST classDef) {
136
        // we are not use inner classes because they can not
137
        // have static methods
138 1 1. visitClassDef : negated conditional → KILLED
        if (classDepth == 0) {
139
            final DetailAST ident = classDef.findFirstToken(TokenTypes.IDENT);
140
            currentClass = packageName.getText() + "." + ident.getText();
141 1 1. visitClassDef : Replaced integer addition with subtraction → KILLED
            classDepth++;
142
        }
143
    }
144
145
    /**
146
     * Checks method definition if this is
147
     * {@code public static void main(String[])}.
148
     * @param method method definition node
149
     */
150
    private void visitMethodDef(DetailAST method) {
151 1 1. visitMethodDef : negated conditional → KILLED
        if (classDepth == 1
152
                // method not in inner class or in interface definition
153 1 1. visitMethodDef : negated conditional → KILLED
                && checkClassName()
154 1 1. visitMethodDef : negated conditional → KILLED
                && checkName(method)
155 1 1. visitMethodDef : negated conditional → KILLED
                && checkModifiers(method)
156 1 1. visitMethodDef : negated conditional → KILLED
                && checkType(method)
157 1 1. visitMethodDef : negated conditional → KILLED
                && checkParams(method)) {
158 1 1. visitMethodDef : removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::log → KILLED
            log(method.getLineNo(), MSG_KEY);
159
        }
160
    }
161
162
    /**
163
     * Checks that current class is not excluded.
164
     * @return true if check passed, false otherwise
165
     */
166
    private boolean checkClassName() {
167 2 1. checkClassName : negated conditional → KILLED
2. checkClassName : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return !excludedClasses.matcher(currentClass).find();
168
    }
169
170
    /**
171
     * Checks that method name is @quot;main@quot;.
172
     * @param method the METHOD_DEF node
173
     * @return true if check passed, false otherwise
174
     */
175
    private static boolean checkName(DetailAST method) {
176
        final DetailAST ident = method.findFirstToken(TokenTypes.IDENT);
177 1 1. checkName : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return "main".equals(ident.getText());
178
    }
179
180
    /**
181
     * Checks that method has final and static modifiers.
182
     * @param method the METHOD_DEF node
183
     * @return true if check passed, false otherwise
184
     */
185
    private static boolean checkModifiers(DetailAST method) {
186
        final DetailAST modifiers =
187
            method.findFirstToken(TokenTypes.MODIFIERS);
188
189 2 1. checkModifiers : negated conditional → KILLED
2. checkModifiers : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return modifiers.branchContains(TokenTypes.LITERAL_PUBLIC)
190 1 1. checkModifiers : negated conditional → KILLED
            && modifiers.branchContains(TokenTypes.LITERAL_STATIC);
191
    }
192
193
    /**
194
     * Checks that return type is {@code void}.
195
     * @param method the METHOD_DEF node
196
     * @return true if check passed, false otherwise
197
     */
198
    private static boolean checkType(DetailAST method) {
199
        final DetailAST type =
200
            method.findFirstToken(TokenTypes.TYPE).getFirstChild();
201 2 1. checkType : negated conditional → KILLED
2. checkType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return type.getType() == TokenTypes.LITERAL_VOID;
202
    }
203
204
    /**
205
     * Checks that method has only {@code String[]} or only {@code String...} param.
206
     * @param method the METHOD_DEF node
207
     * @return true if check passed, false otherwise
208
     */
209
    private static boolean checkParams(DetailAST method) {
210
        boolean checkPassed = false;
211
        final DetailAST params = method.findFirstToken(TokenTypes.PARAMETERS);
212
213 1 1. checkParams : negated conditional → KILLED
        if (params.getChildCount() == 1) {
214
            final DetailAST parameterType = params.getFirstChild().findFirstToken(TokenTypes.TYPE);
215
            final Optional<DetailAST> arrayDecl = Optional.ofNullable(
216
                parameterType.findFirstToken(TokenTypes.ARRAY_DECLARATOR));
217
            final Optional<DetailAST> varargs = Optional.ofNullable(
218
                params.getFirstChild().findFirstToken(TokenTypes.ELLIPSIS));
219
220 1 1. checkParams : negated conditional → KILLED
            if (arrayDecl.isPresent()) {
221
                checkPassed = isStringType(arrayDecl.get().getFirstChild());
222
            }
223 1 1. checkParams : negated conditional → KILLED
            else if (varargs.isPresent()) {
224
                checkPassed = isStringType(parameterType.getFirstChild());
225
            }
226
        }
227 1 1. checkParams : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return checkPassed;
228
    }
229
230
    /**
231
     * Whether the type is java.lang.String.
232
     * @param typeAst the type to check.
233
     * @return true, if the type is java.lang.String.
234
     */
235
    private static boolean isStringType(DetailAST typeAst) {
236
        final FullIdent type = FullIdent.createFullIdent(typeAst);
237 2 1. isStringType : negated conditional → KILLED
2. isStringType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED
        return "String".equals(type.getText())
238 1 1. isStringType : negated conditional → KILLED
            || "java.lang.String".equals(type.getText());
239
    }
240
}

Mutations

70

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

79

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

84

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

96

1.1
Location : leaveToken
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

97

1.1
Location : leaveToken
Killed by : none
negated conditional → SURVIVED

100

1.1
Location : leaveToken
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
Replaced integer subtraction with addition → KILLED

109

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::visitPackageDef → KILLED

112

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::visitClassDef → KILLED

115

1.1
Location : visitToken
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::visitMethodDef → KILLED

138

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

141

1.1
Location : visitClassDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
Replaced integer addition with subtraction → KILLED

151

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

153

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

154

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testWrongName(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

155

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

156

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

157

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

158

1.1
Location : visitMethodDef
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
removed call to com/puppycrawl/tools/checkstyle/checks/UncommentedMainCheck::log → KILLED

167

1.1
Location : checkClassName
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

2.2
Location : checkClassName
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

177

1.1
Location : checkName
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testWrongName(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

189

1.1
Location : checkModifiers
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

2.2
Location : checkModifiers
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

190

1.1
Location : checkModifiers
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

201

1.1
Location : checkType
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

2.2
Location : checkType
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

213

1.1
Location : checkParams
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

220

1.1
Location : checkParams
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

223

1.1
Location : checkParams
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testDefaults(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

227

1.1
Location : checkParams
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

237

1.1
Location : isStringType
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

2.2
Location : isStringType
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testVisitPackage(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED

238

1.1
Location : isStringType
Killed by : com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest.testWrongArrayType(com.puppycrawl.tools.checkstyle.checks.UncommentedMainCheckTest)
negated conditional → KILLED

Active mutators

Tests examined


Report generated by PIT 1.2.2