View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 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      /**
65       * Creates a new {@code IllegalTokenTextCheck} instance.
66       */
67      public IllegalTokenTextCheck() {
68          // no code by default
69      }
70  
71      @Override
72      public int[] getDefaultTokens() {
73          return CommonUtil.EMPTY_INT_ARRAY;
74      }
75  
76      @Override
77      public int[] getAcceptableTokens() {
78          return new int[] {
79              TokenTypes.NUM_DOUBLE,
80              TokenTypes.NUM_FLOAT,
81              TokenTypes.NUM_INT,
82              TokenTypes.NUM_LONG,
83              TokenTypes.IDENT,
84              TokenTypes.COMMENT_CONTENT,
85              TokenTypes.STRING_LITERAL,
86              TokenTypes.CHAR_LITERAL,
87              TokenTypes.TEXT_BLOCK_CONTENT,
88          };
89      }
90  
91      @Override
92      public int[] getRequiredTokens() {
93          return CommonUtil.EMPTY_INT_ARRAY;
94      }
95  
96      @Override
97      public boolean isCommentNodesRequired() {
98          return true;
99      }
100 
101     @Override
102     public void visitToken(DetailAST ast) {
103         final String text = ast.getText();
104         if (format.matcher(text).find()) {
105             String customMessage = message;
106             if (customMessage.isEmpty()) {
107                 customMessage = MSG_KEY;
108             }
109             log(
110                 ast,
111                 customMessage,
112                 formatString);
113         }
114     }
115 
116     /**
117      * Setter to define the message which is used to notify about violations;
118      * if empty then the default message is used.
119      *
120      * @param message custom message which should be used
121      *                 to report about violations.
122      * @since 3.2
123      */
124     public void setMessage(String message) {
125         this.message = Objects.requireNonNullElse(message, "");
126     }
127 
128     /**
129      * Setter to define the RegExp for illegal pattern.
130      *
131      * @param format a {@code String} value
132      * @since 3.2
133      */
134     public void setFormat(String format) {
135         formatString = format;
136         updateRegexp();
137     }
138 
139     /**
140      * Setter to control whether to ignore case when matching.
141      *
142      * @param caseInsensitive true if the match is case-insensitive.
143      * @since 3.2
144      */
145     public void setIgnoreCase(boolean caseInsensitive) {
146         ignoreCase = caseInsensitive;
147         updateRegexp();
148     }
149 
150     /**
151      * Updates the {@link #format} based on the values from {@link #formatString} and
152      * {@link #ignoreCase}.
153      */
154     private void updateRegexp() {
155         final int compileFlags;
156         if (ignoreCase) {
157             compileFlags = Pattern.CASE_INSENSITIVE;
158         }
159         else {
160             compileFlags = 0;
161         }
162         format = CommonUtil.createPattern(formatString, compileFlags);
163     }
164 
165 }