Vern247 16 Newbie Poster

http://sourceforge.net/projects/pmd/

PMD is a Java source code analyzer. It finds unused variables, empty catch blocks, unnecessary object creation, and so forth.

I've been tasked to write customised rules to find the following:

  • Instances where Double.ValueOf was used to parse a string to a double
  • Instances where Float.valueOf was used to parse a string to a Float

Now, I wrote the following code to handle this:

AvoidUsingDoubleValueOf

/**
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */
package net.sourceforge.pmd.rules;

import net.sourceforge.pmd.ast.*;
import net.sourceforge.pmd.AbstractJavaRule;

public class AvoidUsingDoubleValueOf extends AbstractJavaRule {
	public Object visit(ASTVariableInitializer node, Object data) {
		if (containsDoubleValueOf(node)){
			addViolation(data, node);
		}
		return data;
	}
	
	private static final String instanceOfString = "Double.valueOf";
	
	private boolean containsDoubleValueOf(SimpleNode node) {
		return (node.getImage().contains(instanceOfString));
	}
}

AvoidUsingFloatValueOf

/**
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */
package net.sourceforge.pmd.rules;

import net.sourceforge.pmd.ast.*;
import net.sourceforge.pmd.AbstractJavaRule;

public class AvoidUsingFloatValueOf extends AbstractJavaRule {
	public Object visit(ASTVariableInitializer node, Object data) {
		if (containsFloatValueOf(node)){
			addViolation(data, node);
		}
		return data;
	}
	
	private static final String instanceOfString = "Float.valueOf";
	
	private boolean containsFloatValueOf(SimpleNode node) {
		return (node.getImage().contains(instanceOfString));
	}
}

And this is the custom ruleset file for these rules:

<?xml version="1.0"?>
<ruleset name="My custom rules"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">
    <description>A collection of custum rules</description>
  <rule  name="AvoidUsingDoubleValueOf"
  message="Avoid using the Double.valueOf method to parse a string into a double value in line {0}"
  class="net.sourceforge.pmd.rules.AvoidUsingDoubleOf">
  <description>
    The Double.valueOf(String s) method uses the default system locale to parse the
    String into a Double value. Thus, if the default locale on the system is not as
    expected, for whatever reason, then this method will give the wrong result or
    give a NumberFormatException.

    In order to be consistent and to show that the locale is not an oversight,
    it would be better to call a method that does that explicitly parses the string to a double value, like:


    public static double parseUsingDefaultLocale(String s) throws ParseException {
        DecimalFormat decimalFormatter =
        (DecimalFormat)DecimalFormat.getInstance();
        return (Double)decimalFormatter.parse(s).doubleValue();
    }

    This rule searches for all instances of Double.valueOf and reports it as a violation.
  </description>
  <priority>1</priority>
  <example>
  <![CDATA[
    class Example {
	    String strSummaryTotal = "25.75";
	    double summaryTotal = Double.valueOf(decimalFormat.format(strSummaryTotal));
    }

    ]]>
  </example>
</rule>
<rule  name="AvoidUsingFloatValueOf"
  message="Avoid using the Float.valueOf method to parse a string into a Float value in line {0}"
  class="net.sourceforge.pmd.rules.AvoidUsingDoubleOf">
  <description>
    The Float.valueOf(String s) method uses the default system locale to parse the
    String into a Float value. Thus, if the default locale on the system is not as
    expected, for whatever reason, then this method will give the wrong result or
    give a NumberFormatException.

    In order to be consistent and to show that the locale is not an oversight,
    it would be better to call a method that does that explicitly parses the string to a Float value, like:


    public static Float parseUsingDefaultLocale(String s) throws ParseException {
        DecimalFormat decimalFormatter =
        (DecimalFormat)DecimalFormat.getInstance();
        return (Float)decimalFormatter.parse(s).FloatValue();
    }

    This rule searches for all instances of Float.valueOf and reports it as a violation.
  </description>
  <priority>1</priority>
  <example>
  <![CDATA[
    class Example {
	    String strSummaryTotal = "25.7525";
	    Float summaryTotal = Float.valueOf(decimalFormat.format(strSummaryTotal));
    }

    ]]>
  </example>
</rule>
</ruleset>

On trying to run these rules, I found the following:

C:\pmd-4.2.5\bin>pmd c:\Testing\DPR\forms xml rulesets/mycustomrules.xml
<?xml version="1.0" encoding="UTF-8"?>
<pmd version="4.2.5" timestamp="2011-07-01T11:32:11.218">
</pmd>

C:\pmd-4.2.5\bin>

The bold part is an empty xml report, meaning that pmd is either not detecting the code violations, which in turn could mean that my code is not right.

I searched the pmd forums and found that no one has yet successfully implemented custom rules in PMD so this is kind of big.

Is there anyone on here familiar with this? I could do with all the help that I can get.

peter_budo commented: Interesting question +16