View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2020 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;
21  
22  import java.util.regex.Pattern;
23  
24  import com.puppycrawl.tools.checkstyle.StatelessCheck;
25  import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26  import com.puppycrawl.tools.checkstyle.api.DetailAST;
27  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
28  
29  /**
30   * <p>
31   * Checks for {@code TODO:} comments. Actually it is a generic
32   * <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html">
33   * regular expression</a> matcher on Java comments. To check for other patterns
34   * in Java comments, set the {@code format} property.
35   * </p>
36   * <p>
37   * Using {@code TODO:} comments is a great way to keep track of tasks that need to be done.
38   * Having them reported by Checkstyle makes it very hard to forget about them.
39   * </p>
40   * <ul>
41   * <li>
42   * Property {@code format} - Specify pattern to match comments against.
43   * Type is {@code java.util.regex.Pattern}.
44   * Default value is {@code "TODO:"}.
45   * </li>
46   * </ul>
47   * <p>
48   * To configure the check:
49   * </p>
50   * <pre>
51   * &lt;module name="TodoComment"/&gt;
52   * </pre>
53   * <p>
54   * Example:
55   * </p>
56   * <pre>
57   * i++; // TODO: do differently in future   // violation
58   * i++; // todo: do differently in future   // OK
59   * </pre>
60   * <p>
61   * To configure the check for comments that contain {@code TODO} and {@code FIXME}:
62   * </p>
63   * <pre>
64   * &lt;module name="TodoComment"&gt;
65   *   &lt;property name="format" value="(TODO)|(FIXME)"/&gt;
66   * &lt;/module&gt;
67   * </pre>
68   * <p>
69   * Example:
70   * </p>
71   * <pre>
72   * i++;   // TODO: do differently in future   // violation
73   * i++;   // todo: do differently in future   // OK
74   * i=i/x; // FIXME: handle x = 0 case         // violation
75   * i=i/x; // FIX :  handle x = 0 case         // OK
76   * </pre>
77   * <p>
78   * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
79   * </p>
80   * <p>
81   * Violation Message Keys:
82   * </p>
83   * <ul>
84   * <li>
85   * {@code todo.match}
86   * </li>
87   * </ul>
88   *
89   * @since 3.0
90   */
91  @StatelessCheck
92  public class TodoCommentCheck
93          extends AbstractCheck {
94  
95      /**
96       * A key is pointing to the warning message text in "messages.properties"
97       * file.
98       */
99      public static final String MSG_KEY = "todo.match";
100 
101     /**
102      * Specify pattern to match comments against.
103      */
104     private Pattern format = Pattern.compile("TODO:");
105 
106     @Override
107     public boolean isCommentNodesRequired() {
108         return true;
109     }
110 
111     /**
112      * Setter to specify pattern to match comments against.
113      *
114      * @param pattern
115      *        pattern of 'todo' comment.
116      */
117     public void setFormat(Pattern pattern) {
118         format = pattern;
119     }
120 
121     @Override
122     public int[] getDefaultTokens() {
123         return getRequiredTokens();
124     }
125 
126     @Override
127     public int[] getAcceptableTokens() {
128         return getRequiredTokens();
129     }
130 
131     @Override
132     public int[] getRequiredTokens() {
133         return new int[] {TokenTypes.COMMENT_CONTENT };
134     }
135 
136     @Override
137     public void visitToken(DetailAST ast) {
138         final String[] lines = ast.getText().split("\n");
139 
140         for (String line : lines) {
141             if (format.matcher(line).find()) {
142                 log(ast, MSG_KEY, format.pattern());
143             }
144         }
145     }
146 
147 }