From 683e18f67edc00c020ddb69230eb001d9ed021ab Mon Sep 17 00:00:00 2001 From: David Dixon-Peugh Date: Fri, 9 Aug 2002 01:13:10 +0000 Subject: [PATCH] Adding Statistical Rule (in package net.sourceforge.pmd.stat) Requires "getDoubleParameter" and "hasParameter" git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@665 51baf565-9d33-0410-a72c-fc3788e3496d --- .../test/net/sourceforge/pmd/MockRule.java | 8 ++ .../sourceforge/pmd/RuleSetFactoryTest.java | 12 ++- pmd/src/net/sourceforge/pmd/AbstractRule.java | 7 ++ pmd/src/net/sourceforge/pmd/Rule.java | 2 + .../pmd/rules/design/LongClassRule.java | 14 +-- .../net/sourceforge/pmd/stat/DataPoint.java | 100 ++++++++++++++++++ .../sourceforge/pmd/stat/StatisticalRule.java | 84 +++++++++++++++ 7 files changed, 219 insertions(+), 8 deletions(-) create mode 100644 pmd/src/net/sourceforge/pmd/stat/DataPoint.java create mode 100644 pmd/src/net/sourceforge/pmd/stat/StatisticalRule.java diff --git a/pmd/regress/test/net/sourceforge/pmd/MockRule.java b/pmd/regress/test/net/sourceforge/pmd/MockRule.java index 9a2d07f8fb..31a69fe6bd 100644 --- a/pmd/regress/test/net/sourceforge/pmd/MockRule.java +++ b/pmd/regress/test/net/sourceforge/pmd/MockRule.java @@ -29,6 +29,10 @@ public class MockRule implements Rule { this.description = description; } + public boolean hasProperty( String name ) { + return properties.containsKey( name ); + } + public void addProperty(String name, String value) { properties.put(name, value); } @@ -37,6 +41,10 @@ public class MockRule implements Rule { return Integer.parseInt(properties.getProperty(name)); } + public double getDoubleProperty(String name) { + return Double.parseDouble(properties.getProperty(name)); + } + public boolean getBooleanProperty(String name) { return Boolean.valueOf(properties.getProperty(name)).booleanValue(); } diff --git a/pmd/regress/test/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd/regress/test/net/sourceforge/pmd/RuleSetFactoryTest.java index dc16d3c3e9..e2a3843e3b 100644 --- a/pmd/regress/test/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd/regress/test/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -35,7 +35,7 @@ public class RuleSetFactoryTest extends TestCase { private static final String SINGLE_RULE_WITH_PROPS = "" + "\r\ntestdesc" + "" + - "testdesc2" + + "testdesc2" + ""; private static final String SINGLE_RULE_NO_PROPS = "" + @@ -51,10 +51,20 @@ public class RuleSetFactoryTest extends TestCase { RuleSetFactory rsf = new RuleSetFactory(); RuleSet rs = rsf.createRuleSet(new ByteArrayInputStream(SINGLE_RULE_WITH_PROPS.getBytes())); Rule r = (Rule)rs.getRules().iterator().next(); + + assertTrue( r.hasProperty("foo")); assertEquals("bar", r.getStringProperty("foo")); assertEquals(2, r.getIntProperty("fooint")); + + assertTrue( r.hasProperty("fooBoolean")); assertTrue(r.getBooleanProperty("fooBoolean")); assertEquals("testdesc2", r.getDescription()); + + assertTrue( r.hasProperty("fooDouble")); + assertEquals( 1.0, r.getDoubleProperty("fooDouble"), + 0.05 ); + + assertTrue( !r.hasProperty("BuggleFish")); } public void testCreateSingleRuleNoPropsSet() { diff --git a/pmd/src/net/sourceforge/pmd/AbstractRule.java b/pmd/src/net/sourceforge/pmd/AbstractRule.java index c60b6685f1..34a880f336 100644 --- a/pmd/src/net/sourceforge/pmd/AbstractRule.java +++ b/pmd/src/net/sourceforge/pmd/AbstractRule.java @@ -31,11 +31,18 @@ public abstract class AbstractRule this.description = description; } + public boolean hasProperty( String name ) { + return properties.containsKey( name ); + } public void addProperty(String name, String value) { properties.put(name, value); } + public double getDoubleProperty(String name) { + return Double.parseDouble(properties.getProperty(name)); + } + public int getIntProperty(String name) { return Integer.parseInt(properties.getProperty(name)); } diff --git a/pmd/src/net/sourceforge/pmd/Rule.java b/pmd/src/net/sourceforge/pmd/Rule.java index bf14f57789..f2d44ff955 100644 --- a/pmd/src/net/sourceforge/pmd/Rule.java +++ b/pmd/src/net/sourceforge/pmd/Rule.java @@ -10,8 +10,10 @@ public interface Rule { public void setMessage(String message); public void setDescription(String description); public void apply(List astCompilationUnits, RuleContext ctx); + public boolean hasProperty(String name); public void addProperty(String name, String value); public int getIntProperty(String name); public boolean getBooleanProperty(String name); public String getStringProperty(String name); + public double getDoubleProperty(String name); } diff --git a/pmd/src/net/sourceforge/pmd/rules/design/LongClassRule.java b/pmd/src/net/sourceforge/pmd/rules/design/LongClassRule.java index 62db92f262..2510ac05f5 100644 --- a/pmd/src/net/sourceforge/pmd/rules/design/LongClassRule.java +++ b/pmd/src/net/sourceforge/pmd/rules/design/LongClassRule.java @@ -16,13 +16,13 @@ public class LongClassRule public LongClassRule() { } public Object visit( ASTClassDeclaration decl, Object data ) { - RuleContext ctx = (RuleContext) data; + RuleContext ctx = (RuleContext) data; - if ((decl.getEndLine() - decl.getBeginLine()) > getIntProperty("minimumLength")) { - ctx.getReport().addRuleViolation( createRuleViolation( ctx, - decl.getBeginLine(), - getMessage() )); - } - return null; + if ((decl.getEndLine() - decl.getBeginLine()) > getIntProperty("minimumLength")) { + ctx.getReport().addRuleViolation( createRuleViolation( ctx, + decl.getBeginLine(), + getMessage() )); + } + return null; } } diff --git a/pmd/src/net/sourceforge/pmd/stat/DataPoint.java b/pmd/src/net/sourceforge/pmd/stat/DataPoint.java new file mode 100644 index 0000000000..5ad0260a1e --- /dev/null +++ b/pmd/src/net/sourceforge/pmd/stat/DataPoint.java @@ -0,0 +1,100 @@ +package net.sourceforge.pmd.stat; + +import net.sourceforge.pmd.Rule; + +/** + * @author David Dixon-Peugh + * Aug 8, 2002 DataPoint.java + */ +public class DataPoint + implements java.lang.Comparable +{ + private int lineNumber; + private double score; + private String message; + private Rule rule; + /** + * Constructor for DataPoint. + */ + public DataPoint() { + super(); + } + + public int compareTo( Object object) { + Double lhs = new Double( score ); + Double rhs = new Double( ((DataPoint) object).getScore()); + return lhs.compareTo(rhs); + } + /** + * Returns the lineNumber. + * @return int + */ + public int getLineNumber() { + return lineNumber; + } + + /** + * Sets the lineNumber. + * @param lineNumber The lineNumber to set + */ + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + + /** + * Returns the message. + * @return String + */ + public String getMessage() { + return message; + } + + /** + * Returns the rule. + * @return Rule + */ + public Rule getRule() { + return rule; + } + + /** + * Sets the message. + * @param message The message to set + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * Sets the rule. + * @param rule The rule to set + */ + public void setRule(Rule rule) { + this.rule = rule; + } + + /** + * Returns the score. + * @return double + */ + public double getScore() { + return score; + } + + /** + * Sets the score. + * @param score The score to set + */ + public void setScore(double score) { + this.score = score; + } + + /** + * Sets the score. + * @param score The score to set + */ + public void setScore(int score) { + this.score = (double) score; + } + +} diff --git a/pmd/src/net/sourceforge/pmd/stat/StatisticalRule.java b/pmd/src/net/sourceforge/pmd/stat/StatisticalRule.java new file mode 100644 index 0000000000..0b9cc9f6fc --- /dev/null +++ b/pmd/src/net/sourceforge/pmd/stat/StatisticalRule.java @@ -0,0 +1,84 @@ +package net.sourceforge.pmd.stat; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import net.sourceforge.pmd.AbstractRule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleViolation; + +/** + * @author David Dixon-Peugh + * Aug 8, 2002 StatisticalRule.java + */ +public abstract class StatisticalRule extends AbstractRule { + private SortedSet dataPoints = + new TreeSet(); + + public void addDataPoint( DataPoint point ) + { + } + + public void apply( List acus, RuleContext ctx ) { + visitAll( acus, ctx ); + + if (hasProperty("minimum")) { + applyMinimumValue( ctx, getDoubleProperty("minimumValue") ); + } + + if (hasProperty("sigma")) { + applySigma( ctx, getDoubleProperty("sigma")); + } + + if (hasProperty("topscore")) { + applyTopScore(ctx, getIntProperty("topscore")); + } + } + + protected void applyMinimumValue( RuleContext ctx, + double minValue ) + { + Iterator points = dataPoints.iterator(); + + while (points.hasNext()) { + DataPoint point = (DataPoint) points.next(); + + if (point.getScore() > minValue) { + ctx.getReport().addRuleViolation( + this.createRuleViolation( + ctx, + point.getLineNumber(), + point.getMessage())); + } + } + } + + protected void applySigma( RuleContext ctx, + double sigma ) + { + Iterator points = dataPoints.iterator(); + + int count = 0; + double total = 0.0; + double mean = 0.0; + + while (points.hasNext()) { + count++; + DataPoint point = (DataPoint) points.next(); + total += point.getScore(); + } + + mean = total / count; + // TODO: Calculate StdDev + // TODO: Identify things outside range. + } + + protected void applyTopScore( RuleContext ctx, + int topScore ) + { + // TODO: Identify the top scorers + } +}