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