View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.internal;
21  
22  import java.beans.PropertyDescriptor;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.stream.Collectors;
30  
31  import org.apache.commons.beanutils.PropertyUtils;
32  import org.junit.jupiter.api.Assertions;
33  import org.junit.jupiter.api.Test;
34  
35  import com.puppycrawl.tools.checkstyle.internal.utils.CheckUtil;
36  import com.puppycrawl.tools.checkstyle.internal.utils.XdocUtil;
37  
38  public class XdocsExampleFileTest {
39  
40      private static final Set<String> COMMON_PROPERTIES = Set.of(
41          "severity",
42          "id",
43          "fileExtensions",
44          "tabWidth",
45          "fileContents",
46          "tokens",
47          "javadocTokens",
48          "violateExecutionOnNonTightHtml"
49      );
50  
51      // This list is temporarily suppressed.
52      // Until: https://github.com/checkstyle/checkstyle/issues/17449
53      private static final Map<String, Set<String>> SUPPRESSED_PROPERTIES_BY_CHECK = Map.ofEntries(
54              Map.entry("MissingJavadocMethodCheck", Set.of("minLineCount")),
55              Map.entry("TrailingCommentCheck", Set.of("legalComment")),
56              Map.entry("IllegalTypeCheck", Set.of("legalAbstractClassNames")),
57              Map.entry("MethodNameCheck", Set.of("applyToPackage", "applyToPrivate")),
58              Map.entry("JavadocMetadataScraper", Set.of("writeXmlOutput")),
59              Map.entry("MissingJavadocTypeCheck", Set.of("skipAnnotations")),
60              Map.entry("JavadocStyleCheck", Set.of("endOfSentenceFormat", "checkEmptyJavadoc")),
61              Map.entry("ConstantNameCheck", Set.of("applyToPackage", "applyToPrivate")),
62              Map.entry("JavaNCSSCheck", Set.of("recordMaximum")),
63              Map.entry("WhitespaceAroundCheck", Set.of("allowEmptySwitchBlockStatements")),
64              Map.entry("FinalLocalVariableCheck", Set.of("validateUnnamedVariables")),
65              Map.entry("SuppressWarningsHolder", Set.of("aliasList")),
66              Map.entry("IllegalTokenTextCheck", Set.of("message")),
67              Map.entry("IndentationCheck", Set.of(
68                      "basicOffset",
69                      "lineWrappingIndentation",
70                      "throwsIndent",
71                      "arrayInitIndent",
72                      "braceAdjustment"
73              )),
74              Map.entry("MethodCountCheck", Set.of("maxPrivate", "maxPackage", "maxProtected")),
75              Map.entry("ClassMemberImpliedModifierCheck", Set.of(
76                      "violateImpliedStaticOnNestedEnum",
77                      "violateImpliedStaticOnNestedRecord",
78                      "violateImpliedStaticOnNestedInterface"
79              )),
80              Map.entry("TypeNameCheck", Set.of("applyToPublic", "applyToPackage")),
81              Map.entry("DescendantTokenCheck", Set.of("minimumMessage")),
82              Map.entry("InterfaceMemberImpliedModifierCheck", Set.of(
83                      "violateImpliedFinalField",
84                      "violateImpliedPublicField",
85                      "violateImpliedStaticField",
86                      "violateImpliedPublicMethod",
87                      "violateImpliedAbstractMethod"
88              ))
89      );
90  
91      @Test
92      public void testAllCheckPropertiesAreUsedInXdocsExamples() throws Exception {
93          final Map<String, Set<String>> usedPropertiesByCheck =
94              XdocUtil.extractUsedPropertiesFromXdocsExamples();
95          final List<String> failures = new ArrayList<>();
96  
97          for (Class<?> checkClass : CheckUtil.getCheckstyleChecks()) {
98              final String checkSimpleName = checkClass.getSimpleName();
99  
100             final Set<String> definedProperties = Arrays.stream(
101                     PropertyUtils.getPropertyDescriptors(checkClass))
102                 .filter(descriptor -> descriptor.getWriteMethod() != null)
103                 .map(PropertyDescriptor::getName)
104                 .filter(property -> !COMMON_PROPERTIES.contains(property))
105                 .collect(Collectors.toUnmodifiableSet());
106 
107             final Set<String> usedProperties =
108                 usedPropertiesByCheck.getOrDefault(checkSimpleName, Collections.emptySet());
109 
110             final Set<String> suppressedProps =
111                 SUPPRESSED_PROPERTIES_BY_CHECK.getOrDefault(
112                     checkSimpleName, Collections.emptySet());
113 
114             for (String property : definedProperties) {
115                 if (!usedProperties.contains(property)
116                         && !suppressedProps.contains(property)) {
117                     failures.add("Missing property in xdoc: '"
118                             + property + "' of " + checkSimpleName);
119                 }
120             }
121         }
122         if (!failures.isEmpty()) {
123             Assertions.fail("Xdocs are missing properties:\n" + String.join("\n", failures));
124         }
125     }
126 }