1
2
3
4 package net.sourceforge.pmd.lang.rule;
5
6 import java.util.regex.Pattern;
7
8 import net.sourceforge.pmd.PropertyDescriptor;
9 import net.sourceforge.pmd.Rule;
10 import net.sourceforge.pmd.RuleContext;
11 import net.sourceforge.pmd.RuleViolation;
12 import net.sourceforge.pmd.lang.ast.Node;
13 import net.sourceforge.pmd.util.StringUtil;
14
15 public class ParametricRuleViolation<T extends Node> implements RuleViolation {
16
17 protected final Rule rule;
18 protected final String description;
19 protected boolean suppressed;
20 protected String filename;
21
22 protected int beginLine;
23 protected int beginColumn;
24
25 protected int endLine;
26 protected int endColumn;
27
28 protected String packageName = "";
29 protected String className = "";
30 protected String methodName = "";
31 protected String variableName = "";
32
33
34 public ParametricRuleViolation(Rule theRule, RuleContext ctx, T node, String message) {
35 rule = theRule;
36 description = message;
37 filename = ctx.getSourceCodeFilename();
38 if (filename == null) {
39 filename = "";
40 }
41 if (node != null) {
42 beginLine = node.getBeginLine();
43 beginColumn = node.getBeginColumn();
44 endLine = node.getEndLine();
45 endColumn = node.getEndColumn();
46 }
47
48
49 if (node != null && rule != null) {
50 setSuppression(rule, node);
51 }
52
53 }
54
55 private void setSuppression(Rule rule, T node) {
56
57 String regex = rule.getProperty(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR);
58 if (regex != null && description != null) {
59 if (Pattern.matches(regex, description)) {
60 suppressed = true;
61 }
62 }
63
64 if (!suppressed) {
65 String xpath = rule.getProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR);
66 if (xpath != null) {
67 suppressed = node.hasDescendantMatchingXPath(xpath);
68 }
69 }
70 }
71
72 protected String expandVariables(String message) {
73
74 if (message.indexOf("${") < 0) return message;
75
76 StringBuilder buf = new StringBuilder(message);
77 int startIndex = -1;
78 while ((startIndex = buf.indexOf("${", startIndex + 1)) >= 0) {
79 final int endIndex = buf.indexOf("}", startIndex);
80 if (endIndex >= 0) {
81 final String name = buf.substring(startIndex + 2, endIndex);
82 if (isVariable(name)) {
83 buf.replace(startIndex, endIndex + 1, getVariableValue(name));
84 }
85 }
86 }
87 return buf.toString();
88 }
89
90 protected boolean isVariable(String name) {
91 return
92 StringUtil.isAnyOf(name, "variableName", "methodName", "className", "packageName") ||
93 rule.getPropertyDescriptor(name) != null;
94 }
95
96 protected String getVariableValue(String name) {
97 if ("variableName".equals(name)) {
98 return variableName;
99 } else if ("methodName".equals(name)) {
100 return methodName;
101 } else if ("className".equals(name)) {
102 return className;
103 } else if ("packageName".equals(name)) {
104 return packageName;
105 } else {
106 final PropertyDescriptor<?> propertyDescriptor = rule.getPropertyDescriptor(name);
107 return String.valueOf(rule.getProperty(propertyDescriptor));
108 }
109 }
110
111 public Rule getRule() {
112 return rule;
113 }
114
115 public String getDescription() {
116 return expandVariables(description);
117 }
118
119 public boolean isSuppressed() {
120 return suppressed;
121 }
122
123 public String getFilename() {
124 return filename;
125 }
126
127 public int getBeginLine() {
128 return beginLine;
129 }
130
131 public int getBeginColumn() {
132 return beginColumn;
133 }
134
135 public int getEndLine() {
136 return endLine;
137 }
138
139 public int getEndColumn() {
140 return endColumn;
141 }
142
143 public String getPackageName() {
144 return packageName;
145 }
146
147 public String getClassName() {
148 return className;
149 }
150
151 public String getMethodName() {
152 return methodName;
153 }
154
155 public String getVariableName() {
156 return variableName;
157 }
158
159 public void setLines(int theBeginLine, int theEndLine) {
160 beginLine = theBeginLine;
161 endLine = theEndLine;
162 }
163
164 @Override
165 public String toString() {
166 return getFilename() + ':' + getRule() + ':' + getDescription() + ':' + beginLine;
167 }
168 }