View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
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      // FUTURE Fix to understand when a violation _must_ have a Node, and when it must not (to prevent erroneous Rules silently logging w/o a Node).  Modify RuleViolationFactory to support identifying without a Node, and update Rule base classes too.
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  	// Apply Rule specific suppressions
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);	// Regex
58      	if (regex != null && description != null) {
59      		if (Pattern.matches(regex, description)) {
60      			suppressed = true;
61      		}
62      	}
63      
64      	if (!suppressed) {	// XPath
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 }