View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
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   * @author Brian Remedios
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 	 * @see PropertySource#dysfunctionReason()
235 	 */
236 	@Override
237 	public String dysfunctionReason() {
238 		return allCommentsAreIgnored() ? "All comment types are ignored" : null;
239 	}
240 }