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 }