1
2
3
4 package net.sourceforge.pmd.lang.java.rule.comments;
5
6 import java.util.Arrays;
7
8 import net.sourceforge.pmd.PropertySource;
9 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
10 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
11 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
12 import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
13 import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
14 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
15 import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode;
16 import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty;
17
18
19
20
21 public class CommentRequiredRule extends AbstractCommentRule {
22
23 enum CommentRequirement {
24 Required("Required"), Ignored("Ignored"), Unwanted("Unwanted");
25
26 private final String label;
27
28 CommentRequirement(String theLabel) {
29 label = theLabel;
30 }
31
32 public static String[] labels() {
33 String[] labels = new String[values().length];
34 int i = 0;
35 for (CommentRequirement requirement : values()) {
36 labels[i++] = requirement.label;
37 }
38 return labels;
39 }
40 }
41
42 public static final EnumeratedProperty<CommentRequirement> HEADER_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
43 "headerCommentRequirement", "Header comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
44 CommentRequirement.labels(), CommentRequirement.values(), 0, 1.0f);
45
46 public static final EnumeratedProperty<CommentRequirement> FIELD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
47 "fieldCommentRequirement", "Field comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
48 CommentRequirement.labels(), CommentRequirement.values(), 0, 2.0f);
49
50 public static final EnumeratedProperty<CommentRequirement> PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
51 "publicMethodCommentRequirement", "Public method and constructor comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
52 CommentRequirement.labels(), CommentRequirement.values(), 0, 3.0f);
53
54 public static final EnumeratedProperty<CommentRequirement> PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
55 "protectedMethodCommentRequirement", "Protected method constructor comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
56 CommentRequirement.labels(), CommentRequirement.values(), 0, 4.0f);
57
58 public static final EnumeratedProperty<CommentRequirement> ENUM_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
59 "enumCommentRequirement", "Enum comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
60 CommentRequirement.labels(), CommentRequirement.values(), 0, 5.0f);
61
62 public static final EnumeratedProperty<CommentRequirement> SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
63 "serialVersionUIDCommentRequired", "serial version UID commts. Possible values: " + Arrays.toString(CommentRequirement.values()),
64 CommentRequirement.labels(), CommentRequirement.values(), 1, 6.0f);
65
66 public CommentRequiredRule() {
67 definePropertyDescriptor(HEADER_CMT_REQUIREMENT_DESCRIPTOR);
68 definePropertyDescriptor(FIELD_CMT_REQUIREMENT_DESCRIPTOR);
69 definePropertyDescriptor(PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR);
70 definePropertyDescriptor(PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR);
71 definePropertyDescriptor(ENUM_CMT_REQUIREMENT_DESCRIPTOR);
72 definePropertyDescriptor(SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR);
73 }
74
75 private CommentRequirement getCommentRequirement(String label) {
76 if (CommentRequirement.Ignored.label.equals(label)) {
77 return CommentRequirement.Ignored;
78 } else if (CommentRequirement.Required.label.equals(label)) {
79 return CommentRequirement.Required;
80 } else if (CommentRequirement.Unwanted.label.equals(label)) {
81 return CommentRequirement.Unwanted;
82 } else {
83 return null;
84 }
85 }
86
87 @Override
88 public Object visit(ASTClassOrInterfaceDeclaration decl, Object data) {
89 CommentRequirement headerRequirement = getCommentRequirement(getProperty(
90 HEADER_CMT_REQUIREMENT_DESCRIPTOR).toString());
91
92 if (headerRequirement != CommentRequirement.Ignored) {
93 if (headerRequirement == CommentRequirement.Required) {
94 if (decl.comment() == null) {
95 addViolationWithMessage(data, decl,
96 HEADER_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
97 + CommentRequirement.Required,
98 decl.getBeginLine(), decl.getEndLine());
99 }
100 } else {
101 if (decl.comment() != null) {
102 addViolationWithMessage(data, decl,
103 HEADER_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
104 + CommentRequirement.Unwanted,
105 decl.getBeginLine(), decl.getEndLine());
106 }
107 }
108 }
109
110 return super.visit(decl, data);
111 }
112
113 @Override
114 public Object visit(ASTConstructorDeclaration decl, Object data) {
115 checkComment(decl, data);
116 return super.visit(decl, data);
117 }
118
119 @Override
120 public Object visit(ASTMethodDeclaration decl, Object data) {
121 checkComment(decl, data);
122 return super.visit(decl, data);
123 }
124
125 private void checkComment(AbstractJavaAccessNode decl, Object data) {
126 CommentRequirement pubMethodRequirement = getCommentRequirement(getProperty(
127 PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR).toString());
128 CommentRequirement protMethodRequirement = getCommentRequirement(getProperty(
129 PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR).toString());
130
131 if (decl.isPublic()) {
132 if (pubMethodRequirement != CommentRequirement.Ignored) {
133 if (pubMethodRequirement == CommentRequirement.Required) {
134 if (decl.comment() == null) {
135 addViolationWithMessage(data, decl,
136 PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
137 + " " + CommentRequirement.Required,
138 decl.getBeginLine(), decl.getEndLine());
139 }
140 } else {
141 if (decl.comment() != null) {
142 addViolationWithMessage(data, decl,
143 PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
144 + " " + CommentRequirement.Unwanted,
145 decl.getBeginLine(), decl.getEndLine());
146 }
147 }
148 }
149 } else if (decl.isProtected()) {
150 if (protMethodRequirement != CommentRequirement.Ignored) {
151 if (protMethodRequirement == CommentRequirement.Required) {
152 if (decl.comment() == null) {
153 addViolationWithMessage(data, decl,
154 PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
155 + " " + CommentRequirement.Required,
156 decl.getBeginLine(), decl.getEndLine());
157 }
158 } else {
159 if (decl.comment() != null) {
160 addViolationWithMessage(data, decl,
161 PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
162 + " " + CommentRequirement.Unwanted,
163 decl.getBeginLine(), decl.getEndLine());
164 }
165 }
166 }
167 }
168 }
169
170 @Override
171 public Object visit(ASTFieldDeclaration decl, Object data) {
172 CommentRequirement fieldRequirement = getCommentRequirement(getProperty(
173 FIELD_CMT_REQUIREMENT_DESCRIPTOR).toString());
174
175
176 if (fieldRequirement != CommentRequirement.Ignored) {
177 if (isSerialVersionUID(decl)) {
178 checkSerialVersionUID(decl, data, fieldRequirement);
179 } else
180 if (fieldRequirement == CommentRequirement.Required) {
181 if (decl.comment() == null) {
182 addViolationWithMessage(data, decl,
183 FIELD_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
184 + CommentRequirement.Required,
185 decl.getBeginLine(), decl.getEndLine());
186 }
187 } else {
188 if (decl.comment() != null) {
189 addViolationWithMessage(data, decl,
190 FIELD_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
191 + CommentRequirement.Unwanted,
192 decl.getBeginLine(), decl.getEndLine());
193 }
194 }
195 }
196
197 return super.visit(decl, data);
198 }
199
200 private void checkSerialVersionUID(ASTFieldDeclaration decl, Object data, CommentRequirement fieldRequirement) {
201 CommentRequirement serialVersionUIDReq = getCommentRequirement(getProperty(SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR).toString());
202 if (serialVersionUIDReq != CommentRequirement.Ignored) {
203 if (fieldRequirement == CommentRequirement.Required) {
204 if (decl.comment() == null) {
205 addViolationWithMessage(data, decl,
206 SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
207 + CommentRequirement.Required,
208 decl.getBeginLine(), decl.getEndLine());
209 }
210 } else {
211 if (decl.comment() != null) {
212 addViolationWithMessage(data, decl,
213 SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
214 + CommentRequirement.Unwanted,
215 decl.getBeginLine(), decl.getEndLine());
216 }
217 }
218 }
219 }
220
221 private boolean isSerialVersionUID(ASTFieldDeclaration field) {
222 if ("serialVersionUID".equals(field.getVariableName())
223 && field.isStatic() && field.isFinal()
224 && field.getType() == long.class) {
225 return true;
226 }
227 return false;
228 }
229
230 @Override
231 public Object visit(ASTEnumDeclaration decl, Object data) {
232
233 CommentRequirement enumRequirement = getCommentRequirement(getProperty(
234 ENUM_CMT_REQUIREMENT_DESCRIPTOR).toString());
235
236 if (enumRequirement != CommentRequirement.Ignored) {
237 if (enumRequirement == CommentRequirement.Required) {
238 if (decl.comment() == null) {
239 addViolationWithMessage(data, decl,
240 ENUM_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
241 + CommentRequirement.Required,
242 decl.getBeginLine(), decl.getEndLine());
243 }
244 } else {
245 if (decl.comment() != null) {
246 addViolationWithMessage(data, decl,
247 ENUM_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
248 + CommentRequirement.Unwanted,
249 decl.getBeginLine(), decl.getEndLine());
250 }
251 }
252 }
253
254 return super.visit(decl, data);
255 }
256
257 @Override
258 public Object visit(ASTCompilationUnit cUnit, Object data) {
259 assignCommentsToDeclarations(cUnit);
260
261 return super.visit(cUnit, data);
262 }
263
264 public boolean allCommentsAreIgnored() {
265
266 return getProperty(HEADER_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
267 && getProperty(FIELD_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
268 && getProperty(PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
269 && getProperty(PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
270 && getProperty(SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored;
271 }
272
273
274
275
276 @Override
277 public String dysfunctionReason() {
278 return allCommentsAreIgnored() ? "All comment types are ignored" : null;
279 }
280 }