1 package net.sourceforge.pmd.lang.java.rule.comments;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Set;
8
9 import net.sourceforge.pmd.PropertyDescriptor;
10 import net.sourceforge.pmd.PropertySource;
11 import net.sourceforge.pmd.Rule;
12 import net.sourceforge.pmd.RuleContext;
13 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
14 import net.sourceforge.pmd.lang.java.ast.Comment;
15 import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
16 import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty;
17 import net.sourceforge.pmd.util.CollectionUtil;
18 import net.sourceforge.pmd.util.StringUtil;
19
20
21
22
23
24
25
26
27 public class CommentContentRule extends AbstractCommentRule {
28
29 private boolean caseSensitive;
30 private boolean wordsAreRegex;
31 private String[] originalBadWords;
32 private String[] currentBadWords;
33
34 private static final String[] badWords = new String[] { "idiot", "jerk" };
35
36 public static final BooleanProperty WORDS_ARE_REGEX_DESCRIPTOR = new BooleanProperty("wordsAreRegex",
37 "Use regular expressions", false, 1.0f);
38
39
40 public static final BooleanProperty CASE_SENSITIVE_DESCRIPTOR = new BooleanProperty("caseSensitive",
41 "Case sensitive", false, 2.0f);
42
43 public static final StringMultiProperty DISSALLOWED_TERMS_DESCRIPTOR = new StringMultiProperty("disallowedTerms",
44 "Illegal terms or phrases", badWords, 3.0f, '|');
45
46 private static final Set<PropertyDescriptor<?>> NonRegexProperties;
47 static {
48 NonRegexProperties = new HashSet<PropertyDescriptor<?>>(1);
49 NonRegexProperties.add(CASE_SENSITIVE_DESCRIPTOR);
50 }
51
52 public CommentContentRule() {
53 definePropertyDescriptor(WORDS_ARE_REGEX_DESCRIPTOR);
54 definePropertyDescriptor(CASE_SENSITIVE_DESCRIPTOR);
55 definePropertyDescriptor(DISSALLOWED_TERMS_DESCRIPTOR);
56 }
57
58
59
60
61 @Override
62 public void start(RuleContext ctx) {
63 wordsAreRegex = getProperty(WORDS_ARE_REGEX_DESCRIPTOR);
64 originalBadWords = getProperty(DISSALLOWED_TERMS_DESCRIPTOR);
65 caseSensitive = getProperty(CASE_SENSITIVE_DESCRIPTOR);
66 if (caseSensitive) {
67 currentBadWords = originalBadWords;
68 } else {
69 currentBadWords = new String[originalBadWords.length];
70 for (int i=0; i<currentBadWords.length; i++) {
71 currentBadWords[i] = originalBadWords[i].toUpperCase();
72 }
73 }
74 }
75
76 @Override
77 public Set<PropertyDescriptor<?>> ignoredProperties() {
78 return getProperty(WORDS_ARE_REGEX_DESCRIPTOR) ?
79 NonRegexProperties :
80 Collections.EMPTY_SET;
81 }
82
83
84
85
86 @Override
87 public void end(RuleContext ctx) {
88
89 }
90
91 private List<String> illegalTermsIn(Comment comment) {
92
93 if (currentBadWords.length == 0) return Collections.emptyList();
94
95 String commentText = filteredCommentIn(comment);
96 if (StringUtil.isEmpty(commentText)) return Collections.emptyList();
97
98 if (!caseSensitive) commentText = commentText.toUpperCase();
99
100 List<String> foundWords = new ArrayList<String>();
101
102 for (int i=0; i<currentBadWords.length; i++) {
103 if (commentText.indexOf(currentBadWords[i]) >= 0) {
104 foundWords.add(originalBadWords[i]);
105 }
106 }
107
108 return foundWords;
109 }
110
111 private String errorMsgFor(List<String> badWords) {
112 StringBuilder msg = new StringBuilder(this.getMessage()).append(": ");
113 if (badWords.size() == 1 ) {
114 msg.append("Invalid term: '").append(badWords.get(0)).append('\'');
115 } else {
116 msg.append("Invalid terms: '");
117 msg.append(badWords.get(0));
118 for (int i=1; i<badWords.size(); i++) {
119 msg.append("', '").append(badWords.get(i));
120 }
121 msg.append('\'');
122 }
123 return msg.toString();
124 }
125
126 @Override
127 public Object visit(ASTCompilationUnit cUnit, Object data) {
128
129
130 if (currentBadWords == null) start(null);
131
132 for (Comment comment : cUnit.getComments()) {
133 List<String> badWords = illegalTermsIn(comment);
134 if (badWords.isEmpty()) continue;
135
136 addViolationWithMessage(data, cUnit, errorMsgFor(badWords), comment.getBeginLine(), comment.getEndLine());
137 }
138
139 return super.visit(cUnit, data);
140 }
141
142 public boolean hasDissallowedTerms() {
143 String[] terms = getProperty(DISSALLOWED_TERMS_DESCRIPTOR);
144 return CollectionUtil.isNotEmpty(terms);
145 }
146
147
148
149
150 @Override
151 public String dysfunctionReason() {
152
153 return hasDissallowedTerms() ?
154 null :
155 "No disallowed terms specified";
156 }
157 }