View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.checkstyle;
6   
7   import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
8   import com.puppycrawl.tools.checkstyle.api.DetailAST;
9   import com.puppycrawl.tools.checkstyle.api.TokenTypes;
10  import java.util.regex.Matcher;
11  import java.util.regex.Pattern;
12  
13  /**
14   * Multi line comment checker.
15   * Used by the checkstyle process multiple times as a singleton.
16   *
17   * @since 0.23.1
18   */
19  public final class MultiLineCommentCheck extends AbstractCheck {
20  
21      /**
22       * Pattern that matches an empty string only.
23       */
24      private static final Pattern EMPTY = Pattern.compile("^$");
25  
26      /**
27       * Pattern for check.
28       * It is not final as it is initialized from the configuration.
29       */
30      private Pattern format;
31  
32      /**
33       * The message to report for a match.
34       * It is not final as it is initialized from the configuration.
35       */
36      private String message;
37  
38      /**
39       * Comment line.
40       * It is not final because the visitToken method is called many times
41       * during the class under test and the field is reinitialized with a new object.
42       */
43      @SuppressWarnings("PMD.AvoidStringBufferField")
44      private final StringBuilder text;
45  
46      /**
47       * Default constructor.
48       */
49      public MultiLineCommentCheck() {
50          this.format = MultiLineCommentCheck.EMPTY;
51          this.message = "";
52          this.text = new StringBuilder();
53      }
54  
55      @Override
56      public boolean isCommentNodesRequired() {
57          return true;
58      }
59  
60      @Override
61      public int[] getDefaultTokens() {
62          return new int[]{
63              TokenTypes.BLOCK_COMMENT_BEGIN,
64              TokenTypes.COMMENT_CONTENT,
65              TokenTypes.BLOCK_COMMENT_END,
66          };
67      }
68  
69      @Override
70      public int[] getAcceptableTokens() {
71          return this.getDefaultTokens();
72      }
73  
74      @Override
75      public int[] getRequiredTokens() {
76          return this.getDefaultTokens();
77      }
78  
79      @Override
80      public void visitToken(final DetailAST ast) {
81          if (ast.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
82              this.text.setLength(0);
83              this.text.append(ast.getText());
84          } else if (ast.getType() == TokenTypes.COMMENT_CONTENT) {
85              this.text.append(ast.getText());
86          } else {
87              this.text.append(ast.getText());
88              final Matcher matcher = this.format.matcher(this.text.toString());
89              if (matcher.matches()) {
90                  this.log(ast, this.message);
91              }
92          }
93      }
94  
95      /**
96       * The method is called from checkstyle to configure this class.
97       * The parameter is set from the checks.xml file
98       * {@code <module name="com.qulice.checkstyle.MultiLineCommentCheck"/>} and
99       * {@code <property name="format" value=" this regexp "/>} property
100      *
101      * @param fmt Validatig regexp
102      */
103     public void setFormat(final String fmt) {
104         this.format = Pattern.compile(fmt);
105     }
106 
107     /**
108      * The method is called from checkstyle to configure this class.
109      * The parameter is set from the checks.xml file
110      * {@code <module name="com.qulice.checkstyle.MultiLineCommentCheck"/>} and
111      * {@code <property name="message" value="First sentence in a comment ..."/>}
112      * property
113      *
114      * @param msg Error message
115      */
116     public void setMessage(final String msg) {
117         this.message = msg;
118     }
119 }