1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.CheckUtil;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 @FileStatefulCheck
48 public final class ParameterAssignmentCheck extends AbstractCheck {
49
50
51
52
53
54 public static final String MSG_KEY = "parameter.assignment";
55
56
57 private final Deque<Set<String>> parameterNamesStack = new ArrayDeque<>();
58
59 private Set<String> parameterNames;
60
61 @Override
62 public int[] getDefaultTokens() {
63 return getRequiredTokens();
64 }
65
66 @Override
67 public int[] getRequiredTokens() {
68 return new int[] {
69 TokenTypes.CTOR_DEF,
70 TokenTypes.METHOD_DEF,
71 TokenTypes.ASSIGN,
72 TokenTypes.PLUS_ASSIGN,
73 TokenTypes.MINUS_ASSIGN,
74 TokenTypes.STAR_ASSIGN,
75 TokenTypes.DIV_ASSIGN,
76 TokenTypes.MOD_ASSIGN,
77 TokenTypes.SR_ASSIGN,
78 TokenTypes.BSR_ASSIGN,
79 TokenTypes.SL_ASSIGN,
80 TokenTypes.BAND_ASSIGN,
81 TokenTypes.BXOR_ASSIGN,
82 TokenTypes.BOR_ASSIGN,
83 TokenTypes.INC,
84 TokenTypes.POST_INC,
85 TokenTypes.DEC,
86 TokenTypes.POST_DEC,
87 };
88 }
89
90 @Override
91 public int[] getAcceptableTokens() {
92 return getRequiredTokens();
93 }
94
95 @Override
96 public void beginTree(DetailAST rootAST) {
97
98 parameterNamesStack.clear();
99 parameterNames = Collections.emptySet();
100 }
101
102 @Override
103 public void visitToken(DetailAST ast) {
104 switch (ast.getType()) {
105 case TokenTypes.CTOR_DEF:
106 case TokenTypes.METHOD_DEF:
107 visitMethodDef(ast);
108 break;
109 case TokenTypes.ASSIGN:
110 case TokenTypes.PLUS_ASSIGN:
111 case TokenTypes.MINUS_ASSIGN:
112 case TokenTypes.STAR_ASSIGN:
113 case TokenTypes.DIV_ASSIGN:
114 case TokenTypes.MOD_ASSIGN:
115 case TokenTypes.SR_ASSIGN:
116 case TokenTypes.BSR_ASSIGN:
117 case TokenTypes.SL_ASSIGN:
118 case TokenTypes.BAND_ASSIGN:
119 case TokenTypes.BXOR_ASSIGN:
120 case TokenTypes.BOR_ASSIGN:
121 visitAssign(ast);
122 break;
123 case TokenTypes.INC:
124 case TokenTypes.POST_INC:
125 case TokenTypes.DEC:
126 case TokenTypes.POST_DEC:
127 visitIncDec(ast);
128 break;
129 default:
130 throw new IllegalStateException(ast.toString());
131 }
132 }
133
134 @Override
135 public void leaveToken(DetailAST ast) {
136 switch (ast.getType()) {
137 case TokenTypes.CTOR_DEF:
138 case TokenTypes.METHOD_DEF:
139 leaveMethodDef();
140 break;
141 case TokenTypes.ASSIGN:
142 case TokenTypes.PLUS_ASSIGN:
143 case TokenTypes.MINUS_ASSIGN:
144 case TokenTypes.STAR_ASSIGN:
145 case TokenTypes.DIV_ASSIGN:
146 case TokenTypes.MOD_ASSIGN:
147 case TokenTypes.SR_ASSIGN:
148 case TokenTypes.BSR_ASSIGN:
149 case TokenTypes.SL_ASSIGN:
150 case TokenTypes.BAND_ASSIGN:
151 case TokenTypes.BXOR_ASSIGN:
152 case TokenTypes.BOR_ASSIGN:
153 case TokenTypes.INC:
154 case TokenTypes.POST_INC:
155 case TokenTypes.DEC:
156 case TokenTypes.POST_DEC:
157
158 break;
159 default:
160 throw new IllegalStateException(ast.toString());
161 }
162 }
163
164
165
166
167
168 private void visitAssign(DetailAST ast) {
169 checkIdent(ast);
170 }
171
172
173
174
175
176 private void visitIncDec(DetailAST ast) {
177 checkIdent(ast);
178 }
179
180
181
182
183
184 private void checkIdent(DetailAST ast) {
185 if (!parameterNames.isEmpty()) {
186 final DetailAST identAST = ast.getFirstChild();
187
188 if (identAST != null
189 && identAST.getType() == TokenTypes.IDENT
190 && parameterNames.contains(identAST.getText())) {
191 log(ast, MSG_KEY, identAST.getText());
192 }
193 }
194 }
195
196
197
198
199
200 private void visitMethodDef(DetailAST ast) {
201 parameterNamesStack.push(parameterNames);
202 parameterNames = new HashSet<>();
203
204 visitMethodParameters(ast.findFirstToken(TokenTypes.PARAMETERS));
205 }
206
207
208 private void leaveMethodDef() {
209 parameterNames = parameterNamesStack.pop();
210 }
211
212
213
214
215
216 private void visitMethodParameters(DetailAST ast) {
217 DetailAST parameterDefAST =
218 ast.findFirstToken(TokenTypes.PARAMETER_DEF);
219
220 while (parameterDefAST != null) {
221 if (parameterDefAST.getType() == TokenTypes.PARAMETER_DEF
222 && !CheckUtil.isReceiverParameter(parameterDefAST)) {
223 final DetailAST param =
224 parameterDefAST.findFirstToken(TokenTypes.IDENT);
225 parameterNames.add(param.getText());
226 }
227 parameterDefAST = parameterDefAST.getNextSibling();
228 }
229 }
230
231 }