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 * <module name="TodoComment"/>
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 * <module name="TodoComment">
65 * <property name="format" value="(TODO)|(FIXME)"/>
66 * </module>
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 }