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 CommentRequiredRule() {
63 definePropertyDescriptor(HEADER_CMT_REQUIREMENT_DESCRIPTOR);
64 definePropertyDescriptor(FIELD_CMT_REQUIREMENT_DESCRIPTOR);
65 definePropertyDescriptor(PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR);
66 definePropertyDescriptor(PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR);
67 definePropertyDescriptor(ENUM_CMT_REQUIREMENT_DESCRIPTOR);
68 }
69
70 private CommentRequirement getCommentRequirement(String label) {
71 if (CommentRequirement.Ignored.label.equals(label)) {
72 return CommentRequirement.Ignored;
73 } else if (CommentRequirement.Required.label.equals(label)) {
74 return CommentRequirement.Required;
75 } else if (CommentRequirement.Unwanted.label.equals(label)) {
76 return CommentRequirement.Unwanted;
77 } else {
78 return null;
79 }
80 }
81
82 @Override
83 public Object visit(ASTClassOrInterfaceDeclaration decl, Object data) {
84 CommentRequirement headerRequirement = getCommentRequirement(getProperty(
85 HEADER_CMT_REQUIREMENT_DESCRIPTOR).toString());
86
87 if (headerRequirement != CommentRequirement.Ignored) {
88 if (headerRequirement == CommentRequirement.Required) {
89 if (decl.comment() == null) {
90 addViolationWithMessage(data, decl,
91 HEADER_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
92 + CommentRequirement.Required,
93 decl.getBeginLine(), decl.getEndLine());
94 }
95 } else {
96 if (decl.comment() != null) {
97 addViolationWithMessage(data, decl,
98 HEADER_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
99 + CommentRequirement.Unwanted,
100 decl.getBeginLine(), decl.getEndLine());
101 }
102 }
103 }
104
105 return super.visit(decl, data);
106 }
107
108 @Override
109 public Object visit(ASTConstructorDeclaration decl, Object data) {
110 checkComment(decl, data);
111 return super.visit(decl, data);
112 }
113
114 @Override
115 public Object visit(ASTMethodDeclaration decl, Object data) {
116 checkComment(decl, data);
117 return super.visit(decl, data);
118 }
119
120 private void checkComment(AbstractJavaAccessNode decl, Object data) {
121 CommentRequirement pubMethodRequirement = getCommentRequirement(getProperty(
122 PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR).toString());
123 CommentRequirement protMethodRequirement = getCommentRequirement(getProperty(
124 PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR).toString());
125
126 if (decl.isPublic()) {
127 if (pubMethodRequirement != CommentRequirement.Ignored) {
128 if (pubMethodRequirement == CommentRequirement.Required) {
129 if (decl.comment() == null) {
130 addViolationWithMessage(data, decl,
131 PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
132 + " " + CommentRequirement.Required,
133 decl.getBeginLine(), decl.getEndLine());
134 }
135 } else {
136 if (decl.comment() != null) {
137 addViolationWithMessage(data, decl,
138 PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
139 + " " + CommentRequirement.Unwanted,
140 decl.getBeginLine(), decl.getEndLine());
141 }
142 }
143 }
144 } else if (decl.isProtected()) {
145 if (protMethodRequirement != CommentRequirement.Ignored) {
146 if (protMethodRequirement == CommentRequirement.Required) {
147 if (decl.comment() == null) {
148 addViolationWithMessage(data, decl,
149 PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
150 + " " + CommentRequirement.Required,
151 decl.getBeginLine(), decl.getEndLine());
152 }
153 } else {
154 if (decl.comment() != null) {
155 addViolationWithMessage(data, decl,
156 PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR.name()
157 + " " + CommentRequirement.Unwanted,
158 decl.getBeginLine(), decl.getEndLine());
159 }
160 }
161 }
162 }
163 }
164
165 @Override
166 public Object visit(ASTFieldDeclaration decl, Object data) {
167 CommentRequirement fieldRequirement = getCommentRequirement(getProperty(
168 FIELD_CMT_REQUIREMENT_DESCRIPTOR).toString());
169
170 if (fieldRequirement != CommentRequirement.Ignored) {
171 if (fieldRequirement == CommentRequirement.Required) {
172 if (decl.comment() == null) {
173 addViolationWithMessage(data, decl,
174 FIELD_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
175 + CommentRequirement.Required,
176 decl.getBeginLine(), decl.getEndLine());
177 }
178 } else {
179 if (decl.comment() != null) {
180 addViolationWithMessage(data, decl,
181 FIELD_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
182 + CommentRequirement.Unwanted,
183 decl.getBeginLine(), decl.getEndLine());
184 }
185 }
186 }
187
188 return super.visit(decl, data);
189 }
190
191 @Override
192 public Object visit(ASTEnumDeclaration decl, Object data) {
193
194 CommentRequirement enumRequirement = getCommentRequirement(getProperty(
195 ENUM_CMT_REQUIREMENT_DESCRIPTOR).toString());
196
197 if (enumRequirement != CommentRequirement.Ignored) {
198 if (enumRequirement == CommentRequirement.Required) {
199 if (decl.comment() == null) {
200 addViolationWithMessage(data, decl,
201 ENUM_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
202 + CommentRequirement.Required,
203 decl.getBeginLine(), decl.getEndLine());
204 }
205 } else {
206 if (decl.comment() != null) {
207 addViolationWithMessage(data, decl,
208 ENUM_CMT_REQUIREMENT_DESCRIPTOR.name() + " "
209 + CommentRequirement.Unwanted,
210 decl.getBeginLine(), decl.getEndLine());
211 }
212 }
213 }
214
215 return super.visit(decl, data);
216 }
217
218 @Override
219 public Object visit(ASTCompilationUnit cUnit, Object data) {
220 assignCommentsToDeclarations(cUnit);
221
222 return super.visit(cUnit, data);
223 }
224
225 public boolean allCommentsAreIgnored() {
226
227 return getProperty(HEADER_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
228 && getProperty(FIELD_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
229 && getProperty(PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored
230 && getProperty(PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR) == CommentRequirement.Ignored;
231 }
232
233
234
235
236 @Override
237 public String dysfunctionReason() {
238 return allCommentsAreIgnored() ? "All comment types are ignored" : null;
239 }
240 }