Repository: checkstyle/checkstyle

Problem statement:
Assert that properties are ordered alphabetically in xdoc
As suggested in https://github.com/checkstyle/checkstyle/pull/13407#discussion_r1309128616

We need to rearrange properties in alphabetical order(xdoc and javadoc since they are connected) and add a test for that. This will ease reviews when applying the properties macro to checks.

https://checkstyle.org/checks/annotation/annotationusestyle.html for example, has properties that do not follow alphabetical order:

- elementStyle
- closingParens
- trailingArrayComma

Edit: This issue is only for adding the test with suppressions. I will deal with ordering the properties at https://github.com/checkstyle/checkstyle/issues/13668

Update: almost all are ordered with reference to this issue. #13668 is closed. 



Hints:
Do we still want to keep `tokens`/`javadocTokens` at the end or do we want true alphabetical order?

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/annotation/AnnotationUseStyleCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/annotation/AnnotationUseStyleCheck.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/annotation/AnnotationUseStyleCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/annotation/AnnotationUseStyleCheck.java
@@ -98,18 +98,18 @@
  * </p>
  * <ul>
  * <li>
- * Property {@code elementStyle} - Define the annotation element styles.
- * Type is {@code
- * com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck$ElementStyleOption}.
- * Default value is {@code compact_no_array}.
- * </li>
- * <li>
  * Property {@code closingParens} - Define the policy for ending parenthesis.
  * Type is {@code
  * com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck$ClosingParensOption}.
  * Default value is {@code never}.
  * </li>
  * <li>
+ * Property {@code elementStyle} - Define the annotation element styles.
+ * Type is {@code
+ * com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck$ElementStyleOption}.
+ * Default value is {@code compact_no_array}.
+ * </li>
+ * <li>
  * Property {@code trailingArrayComma} - Define the policy for trailing comma in arrays.
  * Type is {@code
  * com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck$TrailingArrayCommaOption}.


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/internal/XdocsPagesTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/internal/XdocsPagesTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/XdocsPagesTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/internal/XdocsPagesTest.java
@@ -226,6 +226,78 @@ public class XdocsPagesTest {
     private static final Set<String> GOOGLE_MODULES = Collections.unmodifiableSet(
         CheckUtil.getConfigGoogleStyleModules());
 
+    // until https://github.com/checkstyle/checkstyle/issues/13666
+    private static final Set<String> MODULES_WITH_UNORDERED_PROPERTIES = Set.of(
+        "Checker",
+        "MissingJavadocMethod",
+        "VariableDeclarationUsageDistance",
+        "LocalVariableName",
+        "JavadocTagContinuationIndentation",
+        "ClassFanOutComplexity",
+        "Translation",
+        "MethodCount",
+        "SummaryJavadoc",
+        "ClassDataAbstractionCoupling",
+        "JavadocMethod",
+        "VisibilityModifier",
+        "MethodLength",
+        "Regexp",
+        "Indentation",
+        "MethodName",
+        "AtclauseOrder",
+        "SuppressWithNearbyTextFilter",
+        "SuppressWithPlainTextCommentFilter",
+        "MemberName",
+        "AvoidStarImport",
+        "ReturnCount",
+        "StaticVariableName",
+        "AvoidEscapedUnicodeCharacters",
+        "ParameterNumber",
+        "RecordComponentNumber",
+        "RegexpSingleline",
+        "RegexpOnFilename",
+        "JavaNCSS",
+        "EmptyCatchBlock",
+        "ParameterName",
+        "IllegalThrows",
+        "HiddenField",
+        "SuppressionXpathSingleFilter",
+        "WhitespaceAround",
+        "RegexpSinglelineJava",
+        "ImportOrder",
+        "IllegalType",
+        "ConstantName",
+        "MutableException",
+        "JavadocType",
+        "CustomImportOrder",
+        "AnnotationLocation",
+        "Header",
+        "DescendantToken",
+        "RegexpMultiline",
+        "JavadocVariable",
+        "SuppressionSingleFilter",
+        "InterfaceMemberImpliedModifier",
+        "IllegalImport",
+        "NewlineAtEndOfFile",
+        "SingleLineJavadoc",
+        "MissingJavadocType",
+        "FileLength",
+        "RegexpHeader",
+        "ThrowsCount",
+        "SuppressionCommentFilter",
+        "TypeName",
+        "MagicNumber",
+        "NeedBraces",
+        "SeverityMatchFilter",
+        "SuppressWithNearbyCommentFilter",
+        "MultipleStringLiterals",
+        "LeftCurly",
+        "AbbreviationAsWordInName",
+        "EmptyLineSeparator",
+        "JavadocStyle",
+        "JavadocParagraph"
+    );
+
     /**
      * Generate xdoc content from templates before validation.
      * This method will be removed once
@@ -797,6 +869,10 @@ private static void validatePropertySection(String fileName, String sectionName,
                 .that(table.getNodeName())
                 .isEqualTo("table");
 
+            if (!MODULES_WITH_UNORDERED_PROPERTIES.contains(sectionName)) {
+                validatePropertySectionPropertiesOrder(fileName, sectionName, table, properties);
+            }
+
             validatePropertySectionProperties(fileName, sectionName, table, instance,
                     properties);
         }
@@ -807,6 +883,43 @@ private static void validatePropertySection(String fileName, String sectionName,
             .isEmpty();
     }
 
+    private static void validatePropertySectionPropertiesOrder(String fileName, String sectionName,
+                                                               Node table, Set<String> properties) {
+        final Set<Node> rows = XmlUtil.getChildrenElements(table);
+        final List<String> orderedPropertyNames = new ArrayList<>(properties);
+        final List<String> tablePropertyNames = new ArrayList<>();
+
+        // javadocTokens and tokens should be last
+        if (orderedPropertyNames.contains("javadocTokens")) {
+            orderedPropertyNames.remove("javadocTokens");
+            orderedPropertyNames.add("javadocTokens");
+        }
+        if (orderedPropertyNames.contains("tokens")) {
+            orderedPropertyNames.remove("tokens");
+            orderedPropertyNames.add("tokens");
+        }
+
+        rows
+            .stream()
+            // First row is header row
+            .skip(1)
+            .forEach(row -> {
+                final List<Node> columns = new ArrayList<>(XmlUtil.getChildrenElements(row));
+                assertWithMessage(fileName + " section '" + sectionName
+                        + "' should have the requested columns")
+                    .that(columns)
+                    .hasSize(5);
+
+                final String propertyName = columns.get(0).getTextContent();
+                tablePropertyNames.add(propertyName);
+            });
+
+        assertWithMessage(fileName + " section '" + sectionName
+                + "' should have properties in the requested order")
+            .that(tablePropertyNames)
+            .isEqualTo(orderedPropertyNames);
+    }
+
     private static void fixCapturedProperties(String sectionName, Object instance, Class<?> clss,
             Set<String> properties) {
         // remove global properties that don't need documentation