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) {
75 return message;
76 }
77
78 StringBuilder buf = new StringBuilder(message);
79 int startIndex = -1;
80 while ((startIndex = buf.indexOf("${", startIndex + 1)) >= 0) {
81 final int endIndex = buf.indexOf("}", startIndex);
82 if (endIndex >= 0) {
83 final String name = buf.substring(startIndex + 2, endIndex);
84 if (isVariable(name)) {
85 buf.replace(startIndex, endIndex + 1, getVariableValue(name));
86 }
87 }
88 }
89 return buf.toString();
90 }
91
92 protected boolean isVariable(String name) {
93 return
94 StringUtil.isAnyOf(name, "variableName", "methodName", "className", "packageName") ||
95 rule.getPropertyDescriptor(name) != null;
96 }
97
98 protected String getVariableValue(String name) {
99 if ("variableName".equals(name)) {
100 return variableName;
101 } else if ("methodName".equals(name)) {
102 return methodName;
103 } else if ("className".equals(name)) {
104 return className;
105 } else if ("packageName".equals(name)) {
106 return packageName;
107 } else {
108 final PropertyDescriptor<?> propertyDescriptor = rule.getPropertyDescriptor(name);
109 return String.valueOf(rule.getProperty(propertyDescriptor));
110 }
111 }
112
113 public Rule getRule() {
114 return rule;
115 }
116
117 public String getDescription() {
118 return expandVariables(description);
119 }
120
121 public boolean isSuppressed() {
122 return suppressed;
123 }
124
125 public String getFilename() {
126 return filename;
127 }
128
129 public int getBeginLine() {
130 return beginLine;
131 }
132
133 public int getBeginColumn() {
134 return beginColumn;
135 }
136
137 public int getEndLine() {
138 return endLine;
139 }
140
141 public int getEndColumn() {
142 return endColumn;
143 }
144
145 public String getPackageName() {
146 return packageName;
147 }
148
149 public String getClassName() {
150 return className;
151 }
152
153 public String getMethodName() {
154 return methodName;
155 }
156
157 public String getVariableName() {
158 return variableName;
159 }
160
161 public void setLines(int theBeginLine, int theEndLine) {
162 beginLine = theBeginLine;
163 endLine = theEndLine;
164 }
165
166 @Override
167 public String toString() {
168 return getFilename() + ':' + getRule() + ':' + getDescription() + ':' + beginLine;
169 }
170 }