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
38 private static final String[] BAD_WORDS = new String[] { "idiot", "jerk" };
39
40 public static final BooleanProperty WORDS_ARE_REGEX_DESCRIPTOR = new BooleanProperty("wordsAreRegex",
41 "Use regular expressions", false, 1.0f);
42
43
44 public static final BooleanProperty CASE_SENSITIVE_DESCRIPTOR = new BooleanProperty("caseSensitive",
45 "Case sensitive", false, 2.0f);
46
47 public static final StringMultiProperty DISSALLOWED_TERMS_DESCRIPTOR = new StringMultiProperty("disallowedTerms",
48 "Illegal terms or phrases", BAD_WORDS, 3.0f, '|');
49
50 private static final Set<PropertyDescriptor<?>> NON_REGEX_PROPERTIES;
51 static {
52 NON_REGEX_PROPERTIES = new HashSet<PropertyDescriptor<?>>(1);
53 NON_REGEX_PROPERTIES.add(CASE_SENSITIVE_DESCRIPTOR);
54 }
55
56 public CommentContentRule() {
57 definePropertyDescriptor(WORDS_ARE_REGEX_DESCRIPTOR);
58 definePropertyDescriptor(CASE_SENSITIVE_DESCRIPTOR);
59 definePropertyDescriptor(DISSALLOWED_TERMS_DESCRIPTOR);
60 }
61
62
63
64
65 @Override
66 public void start(RuleContext ctx) {
67 wordsAreRegex = getProperty(WORDS_ARE_REGEX_DESCRIPTOR);
68 originalBadWords = getProperty(DISSALLOWED_TERMS_DESCRIPTOR);
69 caseSensitive = getProperty(CASE_SENSITIVE_DESCRIPTOR);
70 if (caseSensitive) {
71 currentBadWords = originalBadWords;
72 } else {
73 currentBadWords = new String[originalBadWords.length];
74 for (int i = 0; i < currentBadWords.length; i++) {
75 currentBadWords[i] = originalBadWords[i].toUpperCase();
76 }
77 }
78 }
79
80 @Override
81 public Set<PropertyDescriptor<?>> ignoredProperties() {
82 return getProperty(WORDS_ARE_REGEX_DESCRIPTOR) ? NON_REGEX_PROPERTIES : Collections.EMPTY_SET;
83 }
84
85
86
87
88 @Override
89 public void end(RuleContext ctx) {
90
91 }
92
93 private List<String> illegalTermsIn(Comment comment) {
94
95 if (currentBadWords.length == 0) {
96 return Collections.emptyList();
97 }
98
99 String commentText = filteredCommentIn(comment);
100 if (StringUtil.isEmpty(commentText)) {
101 return Collections.emptyList();
102 }
103
104 if (!caseSensitive) {
105 commentText = commentText.toUpperCase();
106 }
107
108 List<String> foundWords = new ArrayList<String>();
109
110 for (int i = 0; i < currentBadWords.length; i++) {
111 if (commentText.indexOf(currentBadWords[i]) >= 0) {
112 foundWords.add(originalBadWords[i]);
113 }
114 }
115
116 return foundWords;
117 }
118
119 private String errorMsgFor(List<String> badWords) {
120 StringBuilder msg = new StringBuilder(this.getMessage()).append(": ");
121 if (badWords.size() == 1) {
122 msg.append("Invalid term: '").append(badWords.get(0)).append('\'');
123 } else {
124 msg.append("Invalid terms: '");
125 msg.append(badWords.get(0));
126 for (int i = 1; i < badWords.size(); i++) {
127 msg.append("', '").append(badWords.get(i));
128 }
129 msg.append('\'');
130 }
131 return msg.toString();
132 }
133
134 @Override
135 public Object visit(ASTCompilationUnit cUnit, Object data) {
136
137
138 if (currentBadWords == null) {
139 start(null);
140 }
141
142 for (Comment comment : cUnit.getComments()) {
143 List<String> badWords = illegalTermsIn(comment);
144 if (badWords.isEmpty()) {
145 continue;
146 }
147
148 addViolationWithMessage(data, cUnit, errorMsgFor(badWords), comment.getBeginLine(), comment.getEndLine());
149 }
150
151 return super.visit(cUnit, data);
152 }
153
154 public boolean hasDissallowedTerms() {
155 String[] terms = getProperty(DISSALLOWED_TERMS_DESCRIPTOR);
156 return CollectionUtil.isNotEmpty(terms);
157 }
158
159
160
161
162 @Override
163 public String dysfunctionReason() {
164 return hasDissallowedTerms() ? null : "No disallowed terms specified";
165 }
166 }