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