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.checks.coding;
21  
22  import java.util.Objects;
23  import java.util.regex.Pattern;
24  
25  import com.puppycrawl.tools.checkstyle.StatelessCheck;
26  import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
27  import com.puppycrawl.tools.checkstyle.api.DetailAST;
28  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
30  
31  /**
32   * <div>
33   * Checks specified tokens text for matching an illegal pattern.
34   * By default, no tokens are specified.
35   * </div>
36   *
37   * @since 3.2
38   */
39  @StatelessCheck
40  public class IllegalTokenTextCheck
41      extends AbstractCheck {
42  
43      /**
44       * A key is pointing to the warning message text in "messages.properties"
45       * file.
46       */
47      public static final String MSG_KEY = "illegal.token.text";
48  
49      /**
50       * Define the message which is used to notify about violations;
51       * if empty then the default message is used.
52       */
53      private String message = "";
54  
55      /** The format string of the regexp. */
56      private String formatString = "^$";
57  
58      /** Define the RegExp for illegal pattern. */
59      private Pattern format = Pattern.compile(formatString);
60  
61      /** Control whether to ignore case when matching. */
62      private boolean ignoreCase;
63  
64      @Override
65      public int[] getDefaultTokens() {
66          return CommonUtil.EMPTY_INT_ARRAY;
67      }
68  
69      @Override
70      public int[] getAcceptableTokens() {
71          return new int[] {
72              TokenTypes.NUM_DOUBLE,
73              TokenTypes.NUM_FLOAT,
74              TokenTypes.NUM_INT,
75              TokenTypes.NUM_LONG,
76              TokenTypes.IDENT,
77              TokenTypes.COMMENT_CONTENT,
78              TokenTypes.STRING_LITERAL,
79              TokenTypes.CHAR_LITERAL,
80              TokenTypes.TEXT_BLOCK_CONTENT,
81          };
82      }
83  
84      @Override
85      public int[] getRequiredTokens() {
86          return CommonUtil.EMPTY_INT_ARRAY;
87      }
88  
89      @Override
90      public boolean isCommentNodesRequired() {
91          return true;
92      }
93  
94      @Override
95      public void visitToken(DetailAST ast) {
96          final String text = ast.getText();
97          if (format.matcher(text).find()) {
98              String customMessage = message;
99              if (customMessage.isEmpty()) {
100                 customMessage = MSG_KEY;
101             }
102             log(
103                 ast,
104                 customMessage,
105                 formatString);
106         }
107     }
108 
109     /**
110      * Setter to define the message which is used to notify about violations;
111      * if empty then the default message is used.
112      *
113      * @param message custom message which should be used
114      *                 to report about violations.
115      * @since 3.2
116      */
117     public void setMessage(String message) {
118         this.message = Objects.requireNonNullElse(message, "");
119     }
120 
121     /**
122      * Setter to define the RegExp for illegal pattern.
123      *
124      * @param format a {@code String} value
125      * @since 3.2
126      */
127     public void setFormat(String format) {
128         formatString = format;
129         updateRegexp();
130     }
131 
132     /**
133      * Setter to control whether to ignore case when matching.
134      *
135      * @param caseInsensitive true if the match is case-insensitive.
136      * @since 3.2
137      */
138     public void setIgnoreCase(boolean caseInsensitive) {
139         ignoreCase = caseInsensitive;
140         updateRegexp();
141     }
142 
143     /**
144      * Updates the {@link #format} based on the values from {@link #formatString} and
145      * {@link #ignoreCase}.
146      */
147     private void updateRegexp() {
148         final int compileFlags;
149         if (ignoreCase) {
150             compileFlags = Pattern.CASE_INSENSITIVE;
151         }
152         else {
153             compileFlags = 0;
154         }
155         format = CommonUtil.createPattern(formatString, compileFlags);
156     }
157 
158 }