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   * Default value is {@code "TODO:"}.
44   * </li>
45   * </ul>
46   * <p>
47   * To configure the check:
48   * </p>
49   * <pre>
50   * &lt;module name="TodoComment"/&gt;
51   * </pre>
52   * <p>
53   * Example:
54   * </p>
55   * <pre>
56   * i++; // TODO: do differently in future   // violation
57   * i++; // todo: do differently in future   // OK
58   * </pre>
59   * <p>
60   * To configure the check for comments that contain {@code TODO} and {@code FIXME}:
61   * </p>
62   * <pre>
63   * &lt;module name="TodoComment"&gt;
64   *   &lt;property name="format" value="(TODO)|(FIXME)"/&gt;
65   * &lt;/module&gt;
66   * </pre>
67   * <p>
68   * Example:
69   * </p>
70   * <pre>
71   * i++;   // TODO: do differently in future   // violation
72   * i++;   // todo: do differently in future   // OK
73   * i=i/x; // FIXME: handle x = 0 case         // violation
74   * i=i/x; // FIX :  handle x = 0 case         // OK
75   * </pre>
76   *
77   * @since 3.0
78   */
79  @StatelessCheck
80  public class TodoCommentCheck
81          extends AbstractCheck {
82  
83      /**
84       * A key is pointing to the warning message text in "messages.properties"
85       * file.
86       */
87      public static final String MSG_KEY = "todo.match";
88  
89      /**
90       * Specify pattern to match comments against.
91       */
92      private Pattern format = Pattern.compile("TODO:");
93  
94      @Override
95      public boolean isCommentNodesRequired() {
96          return true;
97      }
98  
99      /**
100      * Setter to specify pattern to match comments against.
101      *
102      * @param pattern
103      *        pattern of 'todo' comment.
104      */
105     public void setFormat(Pattern pattern) {
106         format = pattern;
107     }
108 
109     @Override
110     public int[] getDefaultTokens() {
111         return getRequiredTokens();
112     }
113 
114     @Override
115     public int[] getAcceptableTokens() {
116         return getRequiredTokens();
117     }
118 
119     @Override
120     public int[] getRequiredTokens() {
121         return new int[] {TokenTypes.COMMENT_CONTENT };
122     }
123 
124     @Override
125     public void visitToken(DetailAST ast) {
126         final String[] lines = ast.getText().split("\n");
127 
128         for (int i = 0; i < lines.length; i++) {
129             if (format.matcher(lines[i]).find()) {
130                 log(ast.getLineNo() + i, MSG_KEY, format.pattern());
131             }
132         }
133     }
134 
135 }