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.internal;
21
22 import java.lang.reflect.Field;
23 import java.lang.reflect.Modifier;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Map.Entry;
32 import java.util.Properties;
33 import java.util.Set;
34 import java.util.TreeMap;
35 import java.util.stream.Collectors;
36 import java.util.stream.Stream;
37
38 import org.junit.Assert;
39 import org.junit.Test;
40
41 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
42 import com.puppycrawl.tools.checkstyle.Checker;
43 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
44 import com.puppycrawl.tools.checkstyle.FileStatefulCheck;
45 import com.puppycrawl.tools.checkstyle.GlobalStatefulCheck;
46 import com.puppycrawl.tools.checkstyle.ModuleFactory;
47 import com.puppycrawl.tools.checkstyle.StatelessCheck;
48 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
49 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
50 import com.puppycrawl.tools.checkstyle.api.Configuration;
51 import com.puppycrawl.tools.checkstyle.checks.imports.ImportControlCheck;
52 import com.puppycrawl.tools.checkstyle.internal.utils.CheckUtil;
53 import com.puppycrawl.tools.checkstyle.internal.utils.ConfigurationUtil;
54 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
55 import com.puppycrawl.tools.checkstyle.internal.utils.XdocUtil;
56 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
57 import com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil;
58
59 public class AllChecksTest extends AbstractModuleTestSupport {
60
61 private static final Locale[] ALL_LOCALES = {
62 Locale.GERMAN,
63 new Locale("es"),
64 new Locale("fi"),
65 Locale.FRENCH,
66 Locale.JAPANESE,
67 new Locale("pt"),
68 new Locale("tr"),
69 Locale.CHINESE,
70 Locale.ENGLISH,
71 };
72
73 private static final Map<String, Set<String>> CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE =
74 new HashMap<>();
75 private static final Map<String, Set<String>> GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE =
76 new HashMap<>();
77
78 static {
79
80
81 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NoWhitespaceBefore", Stream.of(
82
83 "GENERIC_START", "GENERIC_END").collect(Collectors.toSet()));
84 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("AbbreviationAsWordInName", Stream.of(
85
86 "ENUM_CONSTANT_DEF").collect(Collectors.toSet()));
87 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("FinalLocalVariable", Stream.of(
88
89
90 "PARAMETER_DEF").collect(Collectors.toSet()));
91
92 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("IllegalToken",
93 Stream.of("LITERAL_SUPER", "LITERAL_ASSERT", "ENUM_CONSTANT_DEF",
94 "TYPE_PARAMETERS", "TYPE_UPPER_BOUNDS", "NUM_DOUBLE", "LITERAL_SWITCH",
95 "ANNOTATIONS", "LITERAL_SHORT", "LITERAL_PROTECTED", "FOR_CONDITION",
96 "FOR_INIT", "LITERAL_LONG", "MINUS", "OBJBLOCK", "LITERAL_NULL",
97 "ANNOTATION", "LITERAL_TRUE", "COMMENT_CONTENT", "LITERAL_CHAR",
98 "PARAMETER_DEF", "POST_DEC", "ANNOTATION_FIELD_DEF", "BLOCK_COMMENT_END",
99 "TYPE", "LITERAL_INT", "BSR", "ENUM", "ANNOTATION_MEMBER_VALUE_PAIR",
100 "TYPECAST", "LITERAL_SYNCHRONIZED", "PLUS_ASSIGN", "DOT", "LPAREN",
101 "LITERAL_IF", "LITERAL_CATCH", "BAND", "INTERFACE_DEF", "LOR", "BNOT",
102 "METHOD_CALL", "AT", "ELLIPSIS", "ARRAY_INIT", "FOR_EACH_CLAUSE",
103 "LITERAL_THROWS", "CHAR_LITERAL", "CASE_GROUP", "POST_INC", "SEMI",
104 "LITERAL_FINALLY", "ASSIGN", "RESOURCE_SPECIFICATION", "STATIC_IMPORT",
105 "GENERIC_START", "IMPORT", "SL", "VARIABLE_DEF", "LITERAL_DOUBLE",
106 "RCURLY", "RESOURCE", "SR", "COMMA", "BAND_ASSIGN", "METHOD_DEF",
107 "LITERAL_VOID", "NUM_LONG", "LITERAL_TRANSIENT", "LITERAL_THIS", "LCURLY",
108 "MINUS_ASSIGN", "TYPE_LOWER_BOUNDS", "TYPE_ARGUMENT", "LITERAL_CLASS",
109 "INSTANCE_INIT", "DIV", "STAR", "UNARY_MINUS", "FOR_ITERATOR", "NOT_EQUAL",
110 "LE", "LITERAL_INTERFACE", "LITERAL_FLOAT", "LITERAL_INSTANCEOF",
111 "BOR_ASSIGN", "LT", "SL_ASSIGN", "ELIST", "ANNOTATION_ARRAY_INIT",
112 "MODIFIERS", "LITERAL_BREAK", "EXTENDS_CLAUSE", "TYPE_PARAMETER",
113 "LITERAL_DEFAULT", "STATIC_INIT", "BSR_ASSIGN", "TYPE_EXTENSION_AND",
114 "BOR", "LITERAL_PRIVATE", "LITERAL_THROW", "LITERAL_BYTE", "BXOR",
115 "WILDCARD_TYPE", "FINAL", "PARAMETERS", "RPAREN", "SR_ASSIGN",
116 "UNARY_PLUS", "EMPTY_STAT", "LITERAL_STATIC", "LITERAL_CONTINUE",
117 "STAR_ASSIGN", "LAMBDA", "RBRACK", "BXOR_ASSIGN", "CTOR_CALL",
118 "LITERAL_FALSE", "DO_WHILE", "LITERAL_PUBLIC", "LITERAL_WHILE", "PLUS",
119 "INC", "CTOR_DEF", "GENERIC_END", "DIV_ASSIGN", "SLIST", "LNOT", "LAND",
120 "LITERAL_ELSE", "ABSTRACT", "STRICTFP", "QUESTION", "LITERAL_NEW",
121 "LITERAL_RETURN", "SINGLE_LINE_COMMENT", "INDEX_OP", "EXPR",
122 "BLOCK_COMMENT_BEGIN", "PACKAGE_DEF", "IMPLEMENTS_CLAUSE", "NUM_FLOAT",
123 "LITERAL_DO", "EOF", "GE", "RESOURCES", "MOD", "DEC", "EQUAL",
124 "LITERAL_BOOLEAN", "CLASS_DEF", "COLON", "LITERAL_TRY", "ENUM_DEF", "GT",
125 "NUM_INT", "ANNOTATION_DEF", "METHOD_REF", "TYPE_ARGUMENTS",
126 "DOUBLE_COLON", "IDENT", "MOD_ASSIGN", "LITERAL_FOR", "SUPER_CTOR_CALL",
127 "STRING_LITERAL", "ARRAY_DECLARATOR", "LITERAL_CASE").collect(
128 Collectors.toSet()));
129
130 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("IllegalTokenText",
131 Stream.of("NUM_DOUBLE", "NUM_FLOAT", "NUM_INT", "NUM_LONG", "IDENT",
132 "COMMENT_CONTENT", "STRING_LITERAL", "CHAR_LITERAL")
133 .collect(Collectors.toSet()));
134
135 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("WriteTag",
136 Stream.of("ENUM_CONSTANT_DEF", "METHOD_DEF", "CTOR_DEF", "ANNOTATION_FIELD_DEF")
137 .collect(Collectors.toSet()));
138
139
140 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("AnnotationLocation",
141 Stream.of("CLASS_DEF", "CTOR_DEF", "ENUM_DEF", "INTERFACE_DEF",
142 "METHOD_DEF", "VARIABLE_DEF").collect(Collectors.toSet()));
143 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NoLineWrap", Stream.of(
144
145
146 "METHOD_DEF", "CTOR_DEF",
147
148
149 "CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF")
150 .collect(Collectors.toSet()));
151 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NoWhitespaceAfter", Stream.of(
152
153 "TYPECAST", "LITERAL_SYNCHRONIZED").collect(Collectors.toSet()));
154 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("SeparatorWrap", Stream.of(
155
156
157 "LPAREN", "RPAREN").collect(Collectors.toSet()));
158 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NeedBraces", Stream.of(
159
160
161 "LITERAL_DEFAULT", "LITERAL_CASE").collect(Collectors.toSet()));
162 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("FinalParameters", Stream.of(
163
164 "FOR_EACH_CLAUSE", "LITERAL_CATCH").collect(Collectors.toSet()));
165 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE.put("WhitespaceAround", Stream.of(
166
167 "ARRAY_INIT",
168 "ELLIPSIS",
169
170 "WILDCARD_TYPE", "GENERIC_END", "GENERIC_START").collect(Collectors.toSet()));
171
172
173 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("AnnotationLocation", Stream.of(
174
175
176 "ANNOTATION_DEF", "ANNOTATION_FIELD_DEF", "ENUM_CONSTANT_DEF", "PACKAGE_DEF",
177 "PARAMETER_DEF")
178 .collect(Collectors.toSet()));
179 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("AbbreviationAsWordInName", Stream.of(
180
181 "ENUM_CONSTANT_DEF").collect(Collectors.toSet()));
182 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NoLineWrap", Stream.of(
183
184
185 "METHOD_DEF", "CTOR_DEF", "CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF")
186 .collect(Collectors.toSet()));
187 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("SeparatorWrap", Stream.of(
188
189
190 "RBRACK",
191
192
193 "AT",
194
195
196 "SEMI",
197
198
199 "LPAREN", "RPAREN").collect(Collectors.toSet()));
200 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NeedBraces", Stream.of(
201
202 "LAMBDA", "LITERAL_DEFAULT", "LITERAL_CASE").collect(Collectors.toSet()));
203 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("EmptyBlock", Stream.of(
204
205 "LITERAL_DEFAULT", "LITERAL_CASE",
206
207 "LITERAL_CATCH",
208
209 "ARRAY_INIT",
210
211
212 "INSTANCE_INIT", "LITERAL_DO", "LITERAL_FOR", "LITERAL_SYNCHRONIZED",
213 "LITERAL_WHILE", "STATIC_INIT").collect(Collectors.toSet()));
214 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("WhitespaceAround", Stream.of(
215
216 "ARRAY_INIT",
217
218 "ELLIPSIS",
219
220 "GENERIC_START", "GENERIC_END", "WILDCARD_TYPE")
221 .collect(Collectors.toSet()));
222 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("IllegalTokenText", Stream.of(
223
224 "NUM_DOUBLE", "NUM_FLOAT", "NUM_INT", "NUM_LONG", "IDENT",
225 "COMMENT_CONTENT", "STRING_LITERAL", "CHAR_LITERAL")
226 .collect(Collectors.toSet()));
227 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("OperatorWrap", Stream.of(
228
229
230 "DIV_ASSIGN", "BOR_ASSIGN", "SL_ASSIGN", "ASSIGN", "BSR_ASSIGN", "BAND_ASSIGN",
231 "PLUS_ASSIGN", "MINUS_ASSIGN", "SR_ASSIGN", "STAR_ASSIGN", "BXOR_ASSIGN",
232 "MOD_ASSIGN",
233
234
235 "COLON", "TYPE_EXTENSION_AND").collect(Collectors.toSet()));
236 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE.put("NoWhitespaceBefore", Stream.of(
237
238 "GENERIC_START", "GENERIC_END").collect(Collectors.toSet()));
239 }
240
241 @Override
242 protected String getPackageLocation() {
243 return "com/puppycrawl/tools/checkstyle/internal/allchecks";
244 }
245
246 @Test
247 public void testAllModulesWithDefaultConfiguration() throws Exception {
248 final String inputFilePath = getPath("InputAllChecksDefaultConfig.java");
249 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
250
251 for (Class<?> module : CheckUtil.getCheckstyleModules()) {
252 if (ModuleReflectionUtil.isRootModule(module)) {
253 continue;
254 }
255
256 final DefaultConfiguration moduleConfig = createModuleConfig(module);
257 final Checker checker;
258 if (module.equals(ImportControlCheck.class)) {
259
260
261 moduleConfig.addAttribute("file", getPath(
262 "InputAllChecksImportControl.xml"));
263 }
264 checker = createChecker(moduleConfig);
265 verify(checker, inputFilePath, expected);
266 }
267 }
268
269 @Test
270 public void testDefaultTokensAreSubsetOfAcceptableTokens() throws Exception {
271 for (Class<?> check : CheckUtil.getCheckstyleChecks()) {
272 if (AbstractCheck.class.isAssignableFrom(check)) {
273 final AbstractCheck testedCheck = (AbstractCheck) check.getDeclaredConstructor()
274 .newInstance();
275 final int[] defaultTokens = testedCheck.getDefaultTokens();
276 final int[] acceptableTokens = testedCheck.getAcceptableTokens();
277
278 if (!isSubset(defaultTokens, acceptableTokens)) {
279 final String errorMessage = String.format(Locale.ROOT,
280 "%s's default tokens must be a subset"
281 + " of acceptable tokens.", check.getName());
282 Assert.fail(errorMessage);
283 }
284 }
285 }
286 }
287
288 @Test
289 public void testRequiredTokensAreSubsetOfAcceptableTokens() throws Exception {
290 for (Class<?> check : CheckUtil.getCheckstyleChecks()) {
291 if (AbstractCheck.class.isAssignableFrom(check)) {
292 final AbstractCheck testedCheck = (AbstractCheck) check.getDeclaredConstructor()
293 .newInstance();
294 final int[] requiredTokens = testedCheck.getRequiredTokens();
295 final int[] acceptableTokens = testedCheck.getAcceptableTokens();
296
297 if (!isSubset(requiredTokens, acceptableTokens)) {
298 final String errorMessage = String.format(Locale.ROOT,
299 "%s's required tokens must be a subset"
300 + " of acceptable tokens.", check.getName());
301 Assert.fail(errorMessage);
302 }
303 }
304 }
305 }
306
307 @Test
308 public void testRequiredTokensAreSubsetOfDefaultTokens() throws Exception {
309 for (Class<?> check : CheckUtil.getCheckstyleChecks()) {
310 if (AbstractCheck.class.isAssignableFrom(check)) {
311 final AbstractCheck testedCheck = (AbstractCheck) check.getDeclaredConstructor()
312 .newInstance();
313 final int[] defaultTokens = testedCheck.getDefaultTokens();
314 final int[] requiredTokens = testedCheck.getRequiredTokens();
315
316 if (!isSubset(requiredTokens, defaultTokens)) {
317 final String errorMessage = String.format(Locale.ROOT,
318 "%s's required tokens must be a subset"
319 + " of default tokens.", check.getName());
320 Assert.fail(errorMessage);
321 }
322 }
323 }
324 }
325
326 @Test
327 public void testAllModulesHaveMultiThreadAnnotation() throws Exception {
328 for (Class<?> module : CheckUtil.getCheckstyleModules()) {
329 if (ModuleReflectionUtil.isRootModule(module)
330 || ModuleReflectionUtil.isFilterModule(module)
331 || ModuleReflectionUtil.isFileFilterModule(module)
332 || ModuleReflectionUtil.isTreeWalkerFilterModule(module)) {
333 continue;
334 }
335
336 Assert.assertTrue(
337 "module '" + module.getSimpleName()
338 + "' must contain a multi-thread annotation",
339 module.isAnnotationPresent(GlobalStatefulCheck.class)
340 || module.isAnnotationPresent(FileStatefulCheck.class)
341 || module.isAnnotationPresent(StatelessCheck.class));
342 }
343 }
344
345 @Test
346 public void testAllModulesAreReferencedInConfigFile() throws Exception {
347 final Set<String> modulesReferencedInConfig = CheckUtil.getConfigCheckStyleModules();
348 final Set<String> moduleNames = CheckUtil.getSimpleNames(CheckUtil.getCheckstyleModules());
349
350 moduleNames.stream().filter(check -> !modulesReferencedInConfig.contains(check))
351 .forEach(check -> {
352 final String errorMessage = String.format(Locale.ROOT,
353 "%s is not referenced in checkstyle_checks.xml", check);
354 Assert.fail(errorMessage);
355 });
356 }
357
358 @Test
359 public void testAllCheckTokensAreReferencedInCheckstyleConfigFile() throws Exception {
360 final Configuration configuration = ConfigurationUtil
361 .loadConfiguration("config/checkstyle_checks.xml");
362
363 validateAllCheckTokensAreReferencedInConfigFile("checkstyle", configuration,
364 CHECKSTYLE_TOKENS_IN_CONFIG_TO_IGNORE);
365 }
366
367 @Test
368 public void testAllCheckTokensAreReferencedInGoogleConfigFile() throws Exception {
369 final Configuration configuration = ConfigurationUtil
370 .loadConfiguration("src/main/resources/google_checks.xml");
371
372 validateAllCheckTokensAreReferencedInConfigFile("google", configuration,
373 GOOGLE_TOKENS_IN_CONFIG_TO_IGNORE);
374 }
375
376 private static void validateAllCheckTokensAreReferencedInConfigFile(String configName,
377 Configuration configuration, Map<String, Set<String>> tokensToIgnore) throws Exception {
378 final ModuleFactory moduleFactory = TestUtil.getPackageObjectFactory();
379 final Set<Configuration> configChecks = ConfigurationUtil.getChecks(configuration);
380
381 final Map<String, Set<String>> configCheckTokens = new HashMap<>();
382 final Map<String, Set<String>> checkTokens = new HashMap<>();
383
384 for (Configuration checkConfig : configChecks) {
385 final String checkName = checkConfig.getName();
386 final Object instance;
387
388 try {
389 instance = moduleFactory.createModule(checkName);
390 }
391 catch (CheckstyleException ex) {
392 throw new CheckstyleException("Couldn't find check: " + checkName, ex);
393 }
394
395 if (instance instanceof AbstractCheck) {
396 final AbstractCheck check = (AbstractCheck) instance;
397
398 Set<String> configTokens = configCheckTokens.get(checkName);
399
400 if (configTokens == null) {
401 configTokens = new HashSet<>();
402
403 configCheckTokens.put(checkName, configTokens);
404
405
406 final Set<String> overrideTokens = tokensToIgnore.get(checkName);
407
408 if (overrideTokens != null) {
409 configTokens.addAll(overrideTokens);
410 }
411
412 configTokens.addAll(CheckUtil.getTokenNameSet(check.getRequiredTokens()));
413 checkTokens.put(checkName,
414 CheckUtil.getTokenNameSet(check.getAcceptableTokens()));
415 }
416
417 try {
418 configTokens.addAll(Arrays.asList(checkConfig.getAttribute("tokens").trim()
419 .split(",\\s*")));
420 }
421 catch (CheckstyleException ex) {
422
423 configTokens.addAll(CheckUtil.getTokenNameSet(check.getDefaultTokens()));
424 }
425 }
426 }
427
428 for (Entry<String, Set<String>> entry : checkTokens.entrySet()) {
429 Assert.assertEquals("'" + entry.getKey()
430 + "' should have all acceptable tokens from check in " + configName
431 + " config or specify an override to ignore the specific tokens",
432 entry.getValue(), configCheckTokens.get(entry.getKey()));
433 }
434 }
435
436 @Test
437 public void testAllCheckstyleModulesHaveXdocDocumentation() throws Exception {
438 final Set<String> checkstyleModulesNames = CheckUtil.getSimpleNames(CheckUtil
439 .getCheckstyleModules());
440 final Set<String> modulesNamesWhichHaveXdocs = XdocUtil.getModulesNamesWhichHaveXdoc();
441
442
443 checkstyleModulesNames.remove("TreeWalker");
444 checkstyleModulesNames.remove("Checker");
445
446 checkstyleModulesNames.stream()
447 .filter(moduleName -> !modulesNamesWhichHaveXdocs.contains(moduleName))
448 .forEach(moduleName -> {
449 final String missingModuleMessage = String.format(Locale.ROOT,
450 "Module %s does not have xdoc documentation.",
451 moduleName);
452 Assert.fail(missingModuleMessage);
453 });
454 }
455
456 @Test
457 public void testAllCheckstyleModulesInCheckstyleConfig() throws Exception {
458 final Set<String> configChecks = CheckUtil.getConfigCheckStyleModules();
459 final Set<String> moduleNames = CheckUtil.getSimpleNames(CheckUtil.getCheckstyleModules());
460
461 for (String moduleName : moduleNames) {
462 Assert.assertTrue("checkstyle_checks.xml is missing module: " + moduleName,
463 configChecks.contains(moduleName));
464 }
465 }
466
467 @Test
468 public void testAllCheckstyleChecksHaveMessage() throws Exception {
469 for (Class<?> module : CheckUtil.getCheckstyleChecks()) {
470 final String name = module.getSimpleName();
471
472 Assert.assertFalse(name
473 + " should have at least one 'MSG_*' field for error messages", CheckUtil
474 .getCheckMessages(module).isEmpty());
475 }
476 }
477
478 @Test
479 public void testAllCheckstyleMessages() throws Exception {
480 final Map<String, List<String>> usedMessages = new TreeMap<>();
481
482
483 for (Class<?> module : CheckUtil.getCheckstyleModules()) {
484 for (Field message : CheckUtil.getCheckMessages(module)) {
485 Assert.assertEquals(module.getSimpleName() + "." + message.getName()
486 + " should be 'public static final'", Modifier.PUBLIC | Modifier.STATIC
487 | Modifier.FINAL, message.getModifiers());
488
489
490 if (!message.isAccessible()) {
491 message.setAccessible(true);
492 }
493
494 verifyCheckstyleMessage(usedMessages, module, message);
495 }
496 }
497
498
499 for (Entry<String, List<String>> entry : usedMessages.entrySet()) {
500 final Properties pr = new Properties();
501 pr.load(AllChecksTest.class.getResourceAsStream(
502 "/" + entry.getKey().replace('.', '/') + "/messages.properties"));
503
504 for (Object key : pr.keySet()) {
505
506 if ("translation.wrongLanguageCode".equals(key)) {
507 continue;
508 }
509
510 Assert.assertTrue("property '" + key + "' isn't used by any check in package '"
511 + entry.getKey() + "'", entry.getValue().contains(key.toString()));
512 }
513 }
514 }
515
516 private static void verifyCheckstyleMessage(Map<String, List<String>> usedMessages,
517 Class<?> module, Field message) throws Exception {
518 final String messageString = message.get(null).toString();
519 final String packageName = module.getPackage().getName();
520 List<String> packageMessages = usedMessages.get(packageName);
521
522 if (packageMessages == null) {
523 packageMessages = new ArrayList<>();
524 usedMessages.put(packageName, packageMessages);
525 }
526
527 packageMessages.add(messageString);
528
529 for (Locale locale : ALL_LOCALES) {
530 String result = null;
531
532 try {
533 result = CheckUtil.getCheckMessage(module, locale, messageString);
534 }
535 catch (IllegalArgumentException ex) {
536 Assert.fail(module.getSimpleName() + " with the message '" + messageString
537 + "' in locale '" + locale.getLanguage() + "' failed with: "
538 + ex.getClass().getSimpleName() + " - " + ex.getMessage());
539 }
540
541 Assert.assertNotNull(
542 module.getSimpleName() + " should have text for the message '"
543 + messageString + "' in locale " + locale.getLanguage() + "'",
544 result);
545 Assert.assertFalse(
546 module.getSimpleName() + " should have non-empty text for the message '"
547 + messageString + "' in locale '" + locale.getLanguage() + "'",
548 result.trim().isEmpty());
549 Assert.assertFalse(
550 module.getSimpleName() + " should have non-TODO text for the message '"
551 + messageString + "' in locale " + locale.getLanguage() + "'",
552 !"todo.match".equals(messageString)
553 && result.trim().startsWith("TODO"));
554 }
555 }
556
557
558
559
560
561
562
563 private static boolean isSubset(int[] array, int... arrayToCheckIn) {
564 Arrays.sort(arrayToCheckIn);
565 boolean result = true;
566 for (final int element : array) {
567 if (Arrays.binarySearch(arrayToCheckIn, element) < 0) {
568 result = false;
569 break;
570 }
571 }
572 return result;
573 }
574
575 }