1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.javadoc;
21
22 import java.util.regex.Matcher;
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.FileContents;
29 import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
30 import com.puppycrawl.tools.checkstyle.api.TextBlock;
31 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
32 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 @StatelessCheck
67 public class WriteTagCheck
68 extends AbstractCheck {
69
70
71
72
73
74 public static final String MSG_MISSING_TAG = "type.missingTag";
75
76
77
78
79
80 public static final String MSG_WRITE_TAG = "javadoc.writeTag";
81
82
83
84
85
86 public static final String MSG_TAG_FORMAT = "type.tagFormat";
87
88
89 private Pattern tagRegExp;
90
91 private Pattern tagFormat;
92
93
94 private String tag;
95
96 private SeverityLevel tagSeverity = SeverityLevel.INFO;
97
98
99
100
101
102 public void setTag(String tag) {
103 this.tag = tag;
104 tagRegExp = CommonUtil.createPattern(tag + "\\s*(.*$)");
105 }
106
107
108
109
110
111 public void setTagFormat(Pattern pattern) {
112 tagFormat = pattern;
113 }
114
115
116
117
118
119
120
121 public final void setTagSeverity(SeverityLevel severity) {
122 tagSeverity = severity;
123 }
124
125 @Override
126 public int[] getDefaultTokens() {
127 return new int[] {TokenTypes.INTERFACE_DEF,
128 TokenTypes.CLASS_DEF,
129 TokenTypes.ENUM_DEF,
130 TokenTypes.ANNOTATION_DEF,
131 };
132 }
133
134 @Override
135 public int[] getAcceptableTokens() {
136 return new int[] {TokenTypes.INTERFACE_DEF,
137 TokenTypes.CLASS_DEF,
138 TokenTypes.ENUM_DEF,
139 TokenTypes.ANNOTATION_DEF,
140 TokenTypes.METHOD_DEF,
141 TokenTypes.CTOR_DEF,
142 TokenTypes.ENUM_CONSTANT_DEF,
143 TokenTypes.ANNOTATION_FIELD_DEF,
144 };
145 }
146
147 @Override
148 public int[] getRequiredTokens() {
149 return CommonUtil.EMPTY_INT_ARRAY;
150 }
151
152 @Override
153 public void visitToken(DetailAST ast) {
154 final FileContents contents = getFileContents();
155 final int lineNo = ast.getLineNo();
156 final TextBlock cmt =
157 contents.getJavadocBefore(lineNo);
158 if (cmt == null) {
159 log(lineNo, MSG_MISSING_TAG, tag);
160 }
161 else {
162 checkTag(lineNo, cmt.getText());
163 }
164 }
165
166
167
168
169
170
171 private void checkTag(int lineNo, String... comment) {
172 if (tagRegExp != null) {
173 boolean hasTag = false;
174 for (int i = 0; i < comment.length; i++) {
175 final String commentValue = comment[i];
176 final Matcher matcher = tagRegExp.matcher(commentValue);
177 if (matcher.find()) {
178 hasTag = true;
179 final int contentStart = matcher.start(1);
180 final String content = commentValue.substring(contentStart);
181 if (tagFormat == null || tagFormat.matcher(content).find()) {
182 logTag(lineNo + i - comment.length, tag, content);
183 }
184 else {
185 log(lineNo + i - comment.length, MSG_TAG_FORMAT, tag, tagFormat.pattern());
186 }
187 }
188 }
189 if (!hasTag) {
190 log(lineNo, MSG_MISSING_TAG, tag);
191 }
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 private void logTag(int line, String tagName, String tagValue) {
205 final String originalSeverity = getSeverity();
206 setSeverity(tagSeverity.getName());
207
208 log(line, MSG_WRITE_TAG, tagName, tagValue);
209
210 setSeverity(originalSeverity);
211 }
212
213 }