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 java.util.ArrayDeque; | |
23 | import java.util.Collections; | |
24 | import java.util.Deque; | |
25 | import java.util.HashSet; | |
26 | import java.util.Set; | |
27 | ||
28 | import com.puppycrawl.tools.checkstyle.FileStatefulCheck; | |
29 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
30 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
31 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
32 | import com.puppycrawl.tools.checkstyle.utils.CheckUtils; | |
33 | ||
34 | /** | |
35 | * <p> | |
36 | * Disallow assignment of parameters. | |
37 | * </p> | |
38 | * <p> | |
39 | * Rationale: | |
40 | * Parameter assignment is often considered poor | |
41 | * programming practice. Forcing developers to declare | |
42 | * parameters as final is often onerous. Having a check | |
43 | * ensure that parameters are never assigned would give | |
44 | * the best of both worlds. | |
45 | * </p> | |
46 | * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a> | |
47 | */ | |
48 | @FileStatefulCheck | |
49 | public final class ParameterAssignmentCheck extends AbstractCheck { | |
50 | ||
51 | /** | |
52 | * A key is pointing to the warning message text in "messages.properties" | |
53 | * file. | |
54 | */ | |
55 | public static final String MSG_KEY = "parameter.assignment"; | |
56 | ||
57 | /** Stack of methods' parameters. */ | |
58 | private final Deque<Set<String>> parameterNamesStack = new ArrayDeque<>(); | |
59 | /** Current set of parameters. */ | |
60 | private Set<String> parameterNames; | |
61 | ||
62 | @Override | |
63 | public int[] getDefaultTokens() { | |
64 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
65 | } | |
66 | ||
67 | @Override | |
68 | public int[] getRequiredTokens() { | |
69 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] { |
70 | TokenTypes.CTOR_DEF, | |
71 | TokenTypes.METHOD_DEF, | |
72 | TokenTypes.ASSIGN, | |
73 | TokenTypes.PLUS_ASSIGN, | |
74 | TokenTypes.MINUS_ASSIGN, | |
75 | TokenTypes.STAR_ASSIGN, | |
76 | TokenTypes.DIV_ASSIGN, | |
77 | TokenTypes.MOD_ASSIGN, | |
78 | TokenTypes.SR_ASSIGN, | |
79 | TokenTypes.BSR_ASSIGN, | |
80 | TokenTypes.SL_ASSIGN, | |
81 | TokenTypes.BAND_ASSIGN, | |
82 | TokenTypes.BXOR_ASSIGN, | |
83 | TokenTypes.BOR_ASSIGN, | |
84 | TokenTypes.INC, | |
85 | TokenTypes.POST_INC, | |
86 | TokenTypes.DEC, | |
87 | TokenTypes.POST_DEC, | |
88 | }; | |
89 | } | |
90 | ||
91 | @Override | |
92 | public int[] getAcceptableTokens() { | |
93 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
94 | } | |
95 | ||
96 | @Override | |
97 | public void beginTree(DetailAST rootAST) { | |
98 | // clear data | |
99 |
1
1. beginTree : removed call to java/util/Deque::clear → KILLED |
parameterNamesStack.clear(); |
100 | parameterNames = Collections.emptySet(); | |
101 | } | |
102 | ||
103 | @Override | |
104 | public void visitToken(DetailAST ast) { | |
105 | switch (ast.getType()) { | |
106 | case TokenTypes.CTOR_DEF: | |
107 | case TokenTypes.METHOD_DEF: | |
108 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::visitMethodDef → KILLED |
visitMethodDef(ast); |
109 | break; | |
110 | case TokenTypes.ASSIGN: | |
111 | case TokenTypes.PLUS_ASSIGN: | |
112 | case TokenTypes.MINUS_ASSIGN: | |
113 | case TokenTypes.STAR_ASSIGN: | |
114 | case TokenTypes.DIV_ASSIGN: | |
115 | case TokenTypes.MOD_ASSIGN: | |
116 | case TokenTypes.SR_ASSIGN: | |
117 | case TokenTypes.BSR_ASSIGN: | |
118 | case TokenTypes.SL_ASSIGN: | |
119 | case TokenTypes.BAND_ASSIGN: | |
120 | case TokenTypes.BXOR_ASSIGN: | |
121 | case TokenTypes.BOR_ASSIGN: | |
122 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::visitAssign → KILLED |
visitAssign(ast); |
123 | break; | |
124 | case TokenTypes.INC: | |
125 | case TokenTypes.POST_INC: | |
126 | case TokenTypes.DEC: | |
127 | case TokenTypes.POST_DEC: | |
128 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::visitIncDec → KILLED |
visitIncDec(ast); |
129 | break; | |
130 | default: | |
131 | throw new IllegalStateException(ast.toString()); | |
132 | } | |
133 | } | |
134 | ||
135 | @Override | |
136 | public void leaveToken(DetailAST ast) { | |
137 | switch (ast.getType()) { | |
138 | case TokenTypes.CTOR_DEF: | |
139 | case TokenTypes.METHOD_DEF: | |
140 |
1
1. leaveToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::leaveMethodDef → KILLED |
leaveMethodDef(); |
141 | break; | |
142 | case TokenTypes.ASSIGN: | |
143 | case TokenTypes.PLUS_ASSIGN: | |
144 | case TokenTypes.MINUS_ASSIGN: | |
145 | case TokenTypes.STAR_ASSIGN: | |
146 | case TokenTypes.DIV_ASSIGN: | |
147 | case TokenTypes.MOD_ASSIGN: | |
148 | case TokenTypes.SR_ASSIGN: | |
149 | case TokenTypes.BSR_ASSIGN: | |
150 | case TokenTypes.SL_ASSIGN: | |
151 | case TokenTypes.BAND_ASSIGN: | |
152 | case TokenTypes.BXOR_ASSIGN: | |
153 | case TokenTypes.BOR_ASSIGN: | |
154 | case TokenTypes.INC: | |
155 | case TokenTypes.POST_INC: | |
156 | case TokenTypes.DEC: | |
157 | case TokenTypes.POST_DEC: | |
158 | // Do nothing | |
159 | break; | |
160 | default: | |
161 | throw new IllegalStateException(ast.toString()); | |
162 | } | |
163 | } | |
164 | ||
165 | /** | |
166 | * Checks if this is assignments of parameter. | |
167 | * @param ast assignment to check. | |
168 | */ | |
169 | private void visitAssign(DetailAST ast) { | |
170 |
1
1. visitAssign : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::checkIdent → KILLED |
checkIdent(ast); |
171 | } | |
172 | ||
173 | /** | |
174 | * Checks if this is increment/decrement of parameter. | |
175 | * @param ast dec/inc to check. | |
176 | */ | |
177 | private void visitIncDec(DetailAST ast) { | |
178 |
1
1. visitIncDec : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::checkIdent → KILLED |
checkIdent(ast); |
179 | } | |
180 | ||
181 | /** | |
182 | * Check if ident is parameter. | |
183 | * @param ast ident to check. | |
184 | */ | |
185 | private void checkIdent(DetailAST ast) { | |
186 |
1
1. checkIdent : negated conditional → KILLED |
if (!parameterNames.isEmpty()) { |
187 | final DetailAST identAST = ast.getFirstChild(); | |
188 | ||
189 |
1
1. checkIdent : negated conditional → KILLED |
if (identAST != null |
190 |
1
1. checkIdent : negated conditional → KILLED |
&& identAST.getType() == TokenTypes.IDENT |
191 |
1
1. checkIdent : negated conditional → KILLED |
&& parameterNames.contains(identAST.getText())) { |
192 |
1
1. checkIdent : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::log → KILLED |
log(ast.getLineNo(), ast.getColumnNo(), |
193 | MSG_KEY, identAST.getText()); | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
198 | /** | |
199 | * Creates new set of parameters and store old one in stack. | |
200 | * @param ast a method to process. | |
201 | */ | |
202 | private void visitMethodDef(DetailAST ast) { | |
203 |
1
1. visitMethodDef : removed call to java/util/Deque::push → KILLED |
parameterNamesStack.push(parameterNames); |
204 | parameterNames = new HashSet<>(); | |
205 | ||
206 |
1
1. visitMethodDef : removed call to com/puppycrawl/tools/checkstyle/checks/coding/ParameterAssignmentCheck::visitMethodParameters → KILLED |
visitMethodParameters(ast.findFirstToken(TokenTypes.PARAMETERS)); |
207 | } | |
208 | ||
209 | /** Restores old set of parameters. */ | |
210 | private void leaveMethodDef() { | |
211 | parameterNames = parameterNamesStack.pop(); | |
212 | } | |
213 | ||
214 | /** | |
215 | * Creates new parameter set for given method. | |
216 | * @param ast a method for process. | |
217 | */ | |
218 | private void visitMethodParameters(DetailAST ast) { | |
219 | DetailAST parameterDefAST = | |
220 | ast.findFirstToken(TokenTypes.PARAMETER_DEF); | |
221 | ||
222 |
1
1. visitMethodParameters : negated conditional → KILLED |
while (parameterDefAST != null) { |
223 |
1
1. visitMethodParameters : negated conditional → KILLED |
if (parameterDefAST.getType() == TokenTypes.PARAMETER_DEF |
224 |
1
1. visitMethodParameters : negated conditional → KILLED |
&& !CheckUtils.isReceiverParameter(parameterDefAST)) { |
225 | final DetailAST param = | |
226 | parameterDefAST.findFirstToken(TokenTypes.IDENT); | |
227 | parameterNames.add(param.getText()); | |
228 | } | |
229 | parameterDefAST = parameterDefAST.getNextSibling(); | |
230 | } | |
231 | } | |
232 | ||
233 | } | |
Mutations | ||
64 |
1.1 |
|
69 |
1.1 |
|
93 |
1.1 |
|
99 |
1.1 |
|
108 |
1.1 |
|
122 |
1.1 |
|
128 |
1.1 |
|
140 |
1.1 |
|
170 |
1.1 |
|
178 |
1.1 |
|
186 |
1.1 |
|
189 |
1.1 |
|
190 |
1.1 |
|
191 |
1.1 |
|
192 |
1.1 |
|
203 |
1.1 |
|
206 |
1.1 |
|
222 |
1.1 |
|
223 |
1.1 |
|
224 |
1.1 |