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.naming;
21
22 import java.util.Arrays;
23 import java.util.HashSet;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.stream.Collectors;
28
29 import com.puppycrawl.tools.checkstyle.StatelessCheck;
30 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
31 import com.puppycrawl.tools.checkstyle.api.DetailAST;
32 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
33 import com.puppycrawl.tools.checkstyle.utils.CheckUtil;
34 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 @StatelessCheck
69 public class AbbreviationAsWordInNameCheck extends AbstractCheck {
70
71
72
73
74 public static final String MSG_KEY = "abbreviation.as.word";
75
76
77
78
79 private static final int DEFAULT_ALLOWED_ABBREVIATIONS_LENGTH = 3;
80
81
82
83
84
85
86 private int allowedAbbreviationLength =
87 DEFAULT_ALLOWED_ABBREVIATIONS_LENGTH;
88
89
90
91
92 private Set<String> allowedAbbreviations = new HashSet<>();
93
94
95 private boolean ignoreFinal = true;
96
97
98 private boolean ignoreStatic = true;
99
100
101 private boolean ignoreStaticFinal = true;
102
103
104
105
106
107 private boolean ignoreOverriddenMethods = true;
108
109
110
111
112
113
114
115
116 public void setIgnoreFinal(boolean ignoreFinal) {
117 this.ignoreFinal = ignoreFinal;
118 }
119
120
121
122
123
124
125
126
127 public void setIgnoreStatic(boolean ignoreStatic) {
128 this.ignoreStatic = ignoreStatic;
129 }
130
131
132
133
134
135
136
137
138 public void setIgnoreStaticFinal(boolean ignoreStaticFinal) {
139 this.ignoreStaticFinal = ignoreStaticFinal;
140 }
141
142
143
144
145
146
147
148
149
150 public void setIgnoreOverriddenMethods(boolean ignoreOverriddenMethods) {
151 this.ignoreOverriddenMethods = ignoreOverriddenMethods;
152 }
153
154
155
156
157
158
159
160
161
162
163 public void setAllowedAbbreviationLength(int allowedAbbreviationLength) {
164 this.allowedAbbreviationLength = allowedAbbreviationLength;
165 }
166
167
168
169
170
171
172
173
174 public void setAllowedAbbreviations(String... allowedAbbreviations) {
175 if (allowedAbbreviations != null) {
176 this.allowedAbbreviations =
177 Arrays.stream(allowedAbbreviations).collect(Collectors.toUnmodifiableSet());
178 }
179 }
180
181 @Override
182 public int[] getDefaultTokens() {
183 return new int[] {
184 TokenTypes.CLASS_DEF,
185 TokenTypes.INTERFACE_DEF,
186 TokenTypes.ENUM_DEF,
187 TokenTypes.ANNOTATION_DEF,
188 TokenTypes.ANNOTATION_FIELD_DEF,
189 TokenTypes.PARAMETER_DEF,
190 TokenTypes.VARIABLE_DEF,
191 TokenTypes.METHOD_DEF,
192 TokenTypes.PATTERN_VARIABLE_DEF,
193 TokenTypes.RECORD_DEF,
194 TokenTypes.RECORD_COMPONENT_DEF,
195 };
196 }
197
198 @Override
199 public int[] getAcceptableTokens() {
200 return new int[] {
201 TokenTypes.CLASS_DEF,
202 TokenTypes.INTERFACE_DEF,
203 TokenTypes.ENUM_DEF,
204 TokenTypes.ANNOTATION_DEF,
205 TokenTypes.ANNOTATION_FIELD_DEF,
206 TokenTypes.PARAMETER_DEF,
207 TokenTypes.VARIABLE_DEF,
208 TokenTypes.METHOD_DEF,
209 TokenTypes.ENUM_CONSTANT_DEF,
210 TokenTypes.PATTERN_VARIABLE_DEF,
211 TokenTypes.RECORD_DEF,
212 TokenTypes.RECORD_COMPONENT_DEF,
213 };
214 }
215
216 @Override
217 public int[] getRequiredTokens() {
218 return CommonUtil.EMPTY_INT_ARRAY;
219 }
220
221 @Override
222 public void visitToken(DetailAST ast) {
223 if (!isIgnoreSituation(ast)) {
224 final DetailAST nameAst = ast.findFirstToken(TokenTypes.IDENT);
225 final String typeName = nameAst.getText();
226
227 final String abbr = getDisallowedAbbreviation(typeName);
228 if (abbr != null) {
229 log(nameAst, MSG_KEY, typeName, allowedAbbreviationLength + 1);
230 }
231 }
232 }
233
234
235
236
237
238
239
240
241 private boolean isIgnoreSituation(DetailAST ast) {
242 final DetailAST modifiers = ast.getFirstChild();
243
244 final boolean result;
245 if (ast.getType() == TokenTypes.VARIABLE_DEF) {
246 if (isInterfaceDeclaration(ast)) {
247
248 result = ignoreStaticFinal;
249 }
250 else {
251 result = hasIgnoredModifiers(modifiers);
252 }
253 }
254 else if (ast.getType() == TokenTypes.METHOD_DEF) {
255 result = ignoreOverriddenMethods && hasOverrideAnnotation(modifiers);
256 }
257 else {
258 result = CheckUtil.isReceiverParameter(ast);
259 }
260 return result;
261 }
262
263
264
265
266
267
268
269 private boolean hasIgnoredModifiers(DetailAST modifiers) {
270 final boolean isStatic = modifiers.findFirstToken(TokenTypes.LITERAL_STATIC) != null;
271 final boolean isFinal = modifiers.findFirstToken(TokenTypes.FINAL) != null;
272 final boolean result;
273 if (isStatic && isFinal) {
274 result = ignoreStaticFinal;
275 }
276 else {
277 result = ignoreStatic && isStatic || ignoreFinal && isFinal;
278 }
279 return result;
280 }
281
282
283
284
285
286
287
288
289 private static boolean isInterfaceDeclaration(DetailAST variableDefAst) {
290 boolean result = false;
291 final DetailAST astBlock = variableDefAst.getParent();
292 final DetailAST astParent2 = astBlock.getParent();
293
294 if (astParent2.getType() == TokenTypes.INTERFACE_DEF
295 || astParent2.getType() == TokenTypes.ANNOTATION_DEF) {
296 result = true;
297 }
298 return result;
299 }
300
301
302
303
304
305
306
307
308
309 private static boolean hasOverrideAnnotation(DetailAST methodModifiersAST) {
310 boolean result = false;
311 for (DetailAST child : getChildren(methodModifiersAST)) {
312 final DetailAST annotationIdent = child.findFirstToken(TokenTypes.IDENT);
313
314 if (annotationIdent != null && "Override".equals(annotationIdent.getText())) {
315 result = true;
316 break;
317 }
318 }
319 return result;
320 }
321
322
323
324
325
326
327
328
329
330 private String getDisallowedAbbreviation(String str) {
331 int beginIndex = 0;
332 boolean abbrStarted = false;
333 String result = null;
334
335 for (int index = 0; index < str.length(); index++) {
336 final char symbol = str.charAt(index);
337
338 if (Character.isUpperCase(symbol)) {
339 if (!abbrStarted) {
340 abbrStarted = true;
341 beginIndex = index;
342 }
343 }
344 else if (abbrStarted) {
345 abbrStarted = false;
346
347 final int endIndex;
348 final int allowedLength;
349 if (symbol == '_') {
350 endIndex = index;
351 allowedLength = allowedAbbreviationLength + 1;
352 }
353 else {
354 endIndex = index - 1;
355 allowedLength = allowedAbbreviationLength;
356 }
357 result = getAbbreviationIfIllegal(str, beginIndex, endIndex, allowedLength);
358 if (result != null) {
359 break;
360 }
361 beginIndex = -1;
362 }
363 }
364
365 if (abbrStarted) {
366 final int endIndex = str.length() - 1;
367 result = getAbbreviationIfIllegal(str, beginIndex, endIndex, allowedAbbreviationLength);
368 }
369 return result;
370 }
371
372
373
374
375
376
377
378
379
380
381
382
383 private String getAbbreviationIfIllegal(String str, int beginIndex, int endIndex,
384 int allowedLength) {
385 String result = null;
386 final int abbrLength = endIndex - beginIndex;
387 if (abbrLength > allowedLength) {
388 final String abbr = getAbbreviation(str, beginIndex, endIndex);
389 if (!allowedAbbreviations.contains(abbr)) {
390 result = abbr;
391 }
392 }
393 return result;
394 }
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 private static String getAbbreviation(String str, int beginIndex, int endIndex) {
417 final String result;
418 if (endIndex == str.length() - 1) {
419 result = str.substring(beginIndex);
420 }
421 else {
422 result = str.substring(beginIndex, endIndex);
423 }
424 return result;
425 }
426
427
428
429
430
431
432
433
434
435 private static List<DetailAST> getChildren(final DetailAST node) {
436 final List<DetailAST> result = new LinkedList<>();
437 DetailAST curNode = node.getFirstChild();
438 while (curNode != null) {
439 result.add(curNode);
440 curNode = curNode.getNextSibling();
441 }
442 return result;
443 }
444
445 }