Repository: checkstyle/checkstyle

Problem statement:
SuppressionCommentFilter ignores messageFormat when matching on ID
```
$ cat TestClass.java
package com.puppycrawl.tools.checkstyle.filters.suppressioncommentfilter;

public class InputSuppressionCommentFilter {
    // CSOFF naming
    public int ABC;
    // CSON naming
}

$ cat TestConfig.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>
    <property name="severity" value="warning"/>
    <property name="haltOnException" value="false"/>
    <module name="TreeWalker">
        <module name="MemberName">
            <property name="id" value="naming"/>
        </module>
        <module name="SuppressionCommentFilter">
            <property name="offCommentFormat" value="CSOFF naming"/>
            <property name="onCommentFormat" value="CSON naming"/>
            <property name="checkFormat" value="^naming$"/>
            <property name="messageFormat" value="NonMatchingMessage"/>
        </module>
    </module>
</module>

$ java -jar checkstyle-8.22-all.jar -c TestConfig.xml TestClass.java
Starting audit...
Audit done.
```

---------------

Identified in https://github.com/checkstyle/checkstyle/pull/6876#discussion_r300830774, this is an edge case where if the filter matches on the module ID (`naming`) rather than the source name (`MemberName`), the `messageFormat` is ignored. 

In the example above, the configured `"NonMatchingMessage"` message format does not match the `"Name 'ABC' must match pattern ..."` message, so the violation should not be suppressed.

Expected output:
```
$ java -jar checkstyle-8.22-all.jar -c TestConfig.xml TestClass.java
Starting audit...
[WARN] TestClass.java:5:16: Name 'ABC' must match pattern '^[a-z][a-zA-Z0-9]*$'. [naming]
Audit done.
```



Hints:

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java
@@ -707,24 +707,50 @@ public int hashCode() {
          * @return true if the source of event matches the text of this tag.
          */
         public boolean isMatch(TreeWalkerAuditEvent event) {
+            return (isCheckMatch(event) || isIdMatch(event)) && isMessageMatch(event);
+        }
+
+        /**
+         * Checks whether {@link TreeWalkerAuditEvent} source name matches the check format.
+         * @param event {@link TreeWalkerAuditEvent} instance.
+         * @return true if the {@link TreeWalkerAuditEvent} source name matches the check format.
+         */
+        private boolean isCheckMatch(TreeWalkerAuditEvent event) {
+            final Matcher checkMatcher = tagCheckRegexp.matcher(event.getSourceName());
+            return checkMatcher.find();
+        }
+
+        /**
+         * Checks whether the {@link TreeWalkerAuditEvent} module ID matches the ID format.
+         * @param event {@link TreeWalkerAuditEvent} instance.
+         * @return true if the {@link TreeWalkerAuditEvent} module ID matches the ID format.
+         */
+        private boolean isIdMatch(TreeWalkerAuditEvent event) {
             boolean match = false;
-            final Matcher tagMatcher = tagCheckRegexp.matcher(event.getSourceName());
-            if (tagMatcher.find()) {
-                if (tagMessageRegexp == null) {
-                    match = true;
-                }
-                else {
-                    final Matcher messageMatcher = tagMessageRegexp.matcher(event.getMessage());
-                    match = messageMatcher.find();
-                }
-            }
-            else if (event.getModuleId() != null) {
+            if (event.getModuleId() != null) {
                 final Matcher idMatcher = tagCheckRegexp.matcher(event.getModuleId());
                 match = idMatcher.find();
             }
             return match;
         }
 
+        /**
+         * Checks whether the {@link TreeWalkerAuditEvent} message matches the message format.
+         * @param event {@link TreeWalkerAuditEvent} instance.
+         * @return true if the {@link TreeWalkerAuditEvent} message matches the message format.
+         */
+        private boolean isMessageMatch(TreeWalkerAuditEvent event) {
+            final boolean match;
+            if (tagMessageRegexp == null) {
+                match = true;
+            }
+            else {
+                final Matcher messageMatcher = tagMessageRegexp.matcher(event.getMessage());
+                match = messageMatcher.find();
+            }
+            return match;
+        }
+
         @Override
         public String toString() {
             return "Tag[text='" + text + '\''


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java
@@ -390,6 +390,50 @@ public void testSuppressById() throws Exception {
             "15:18: "
                 + getCheckMessage(AbstractNameCheck.class,
                     MSG_INVALID_PATTERN, "ID", "^[a-z][a-zA-Z0-9]*$"),
+            "18:17: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "DEF", "^[a-z][a-zA-Z0-9]*$"),
+            "21:17: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "XYZ", "^[a-z][a-zA-Z0-9]*$"),
+            };
+
+        verifySuppressed(filterConfig, getPath("InputSuppressionCommentFilterSuppressById.java"),
+                expectedViolationMessages, suppressedViolationMessages);
+    }
+
+    @Test
+    public void testSuppressByIdAndMessage() throws Exception {
+        final DefaultConfiguration filterConfig =
+            createModuleConfig(SuppressionCommentFilter.class);
+        filterConfig.addAttribute("offCommentFormat", "CSOFF (\\w+) \\(allow (\\w+)\\)");
+        filterConfig.addAttribute("onCommentFormat", "CSON (\\w+)");
+        filterConfig.addAttribute("checkFormat", "$1");
+        filterConfig.addAttribute("messageFormat", "$2");
+        final String[] suppressedViolationMessages = {
+            "18:17: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "DEF", "^[a-z][a-zA-Z0-9]*$"),
+            };
+        final String[] expectedViolationMessages = {
+            "6:17: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "A1", "^[a-z][a-zA-Z0-9]*$"),
+            "9:30: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "abc", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"),
+            "12:9: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "line_length", "^[a-z][a-zA-Z0-9]*$"),
+            "15:18: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "ID", "^[a-z][a-zA-Z0-9]*$"),
+            "18:17: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "DEF", "^[a-z][a-zA-Z0-9]*$"),
+            "21:17: "
+                + getCheckMessage(AbstractNameCheck.class,
+                    MSG_INVALID_PATTERN, "XYZ", "^[a-z][a-zA-Z0-9]*$"),
             };
 
         verifySuppressed(filterConfig, getPath("InputSuppressionCommentFilterSuppressById.java"),
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressioncommentfilter/InputSuppressionCommentFilterSuppressById.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressioncommentfilter/InputSuppressionCommentFilterSuppressById.java
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressioncommentfilter/InputSuppressionCommentFilterSuppressById.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressioncommentfilter/InputSuppressionCommentFilterSuppressById.java
@@ -13,4 +13,10 @@ public class InputSuppressionCommentFilterSuppressById {
     //CSON ignore
 
     private long ID = 1;
+
+    // CSOFF ignore (allow DEF)
+    private int DEF = 2;
+
+    // CSOFF ignore (allow xyz)
+    private int XYZ = 3;
 }