diff --git a/pmd-rx/regress/test/net/sourceforge/pmd/rx/rules/DroolsRuleTst.java b/pmd-rx/regress/test/net/sourceforge/pmd/rx/rules/DroolsRuleTst.java new file mode 100644 index 0000000000..d446955169 --- /dev/null +++ b/pmd-rx/regress/test/net/sourceforge/pmd/rx/rules/DroolsRuleTst.java @@ -0,0 +1,47 @@ +package test.net.sourceforge.pmd.rx.rules; + +import java.io.StringReader; + +import java.util.Set; + +import org.drools.*; +import org.drools.spi.Rule; + +import net.sourceforge.pmd.rx.*; +import net.sourceforge.pmd.ast.*; +import net.sourceforge.pmd.rx.facts.*; + +import test.net.sourceforge.pmd.rx.*; + +import junit.framework.TestCase; + +public class DroolsRuleTst + extends TestCase +{ + public DroolsRuleTst(String name) { + super( name ); + } + + public Set collectViolations( Rule IUT, String javaCode ) + throws Throwable + { + RuleBase rules = new RuleBase(); + FactCollector collector = new FactCollector( RuleViolationFact.class ); + + rules.addRule( collector ); + rules.addRule( IUT ); + + JavaParser parser = + new JavaParser( new StringReader( javaCode )); + ASTCompilationUnit acu = + parser.CompilationUnit(); + + WorkingMemory memory = rules.createWorkingMemory(); + + DroolsVisitor visitor = new DroolsVisitor( memory ); + visitor.visit( acu, null ); + + return collector.getFacts(); + } + +} diff --git a/pmd-rx/regress/test/net/sourceforge/pmd/rx/rules/DuplicateImportTest.java b/pmd-rx/regress/test/net/sourceforge/pmd/rx/rules/DuplicateImportTest.java new file mode 100644 index 0000000000..5ba628deac --- /dev/null +++ b/pmd-rx/regress/test/net/sourceforge/pmd/rx/rules/DuplicateImportTest.java @@ -0,0 +1,87 @@ +package test.net.sourceforge.pmd.rx.rules; + +import java.util.Set; +import java.util.Iterator; + +import net.sourceforge.pmd.rx.facts.*; +import net.sourceforge.pmd.rx.rules.*; + +import test.net.sourceforge.pmd.rx.*; + +public class DuplicateImportTest + extends DroolsRuleTst +{ + private String testName = null; + + private String JAVA_NO_DUPE = + "import java.util.*;" + + "public class HelloWorld { }"; + + private String JAVA_DUPE_ON_DEMAND = + "import java.util.*;" + + "import java.util.*;" + + "public class HelloWorld { }"; + + private String JAVA_DUPE_NO_DEMAND = + "import java.util.List;" + + "import java.util.List;" + + "public class HelloWorld { }"; + + private String JAVA_DUPE_ON_NO_DEMAND = + "import java.util.*;" + + "import java.util.List;" + + "public class HelloWorld { }"; + + public DuplicateImportTest(String name) { + super( name ); + this.testName = name; + } + + public void testNoDupes() + throws Throwable + { + Set results = collectViolations( new DuplicateImport(), + JAVA_NO_DUPE ); + Iterator rvs = results.iterator(); + while (rvs.hasNext()) { + RuleViolationFact rvFact = (RuleViolationFact) rvs.next(); + ImportFact impFact = (ImportFact) rvFact.getFact(); + + System.err.println("DuplicateImport: " + impFact.getACU() + "/" + + impFact.getImportPackage() + "/" + + Integer.toString( impFact.getLineNumber() )); + } + + assertEquals("Expecting no violations", + 0, results.size() ); + } + + public void testDupeOnDemand() + throws Throwable + { + Set results = collectViolations( new DuplicateImport(), + JAVA_DUPE_ON_DEMAND ); + + assertEquals("Expecting 2 violations", + 2, results.size() ); + } + + public void testDupeNoDemand() + throws Throwable + { + Set results = collectViolations( new DuplicateImport(), + JAVA_DUPE_NO_DEMAND ); + assertEquals("Expecting 2 violations", + 2, results.size() ); + } + + public void testDupeOnNoDemand() + throws Throwable + { + Set results = collectViolations( new DuplicateImport(), + JAVA_DUPE_ON_NO_DEMAND ); + assertEquals("Expecting 2 violations", + 2, results.size() ); + } + +} diff --git a/pmd-rx/src/net/sourceforge/pmd/rx/DroolsVisitor.java b/pmd-rx/src/net/sourceforge/pmd/rx/DroolsVisitor.java index b8b1f58b5e..c3e5ed6d53 100644 --- a/pmd-rx/src/net/sourceforge/pmd/rx/DroolsVisitor.java +++ b/pmd-rx/src/net/sourceforge/pmd/rx/DroolsVisitor.java @@ -53,7 +53,8 @@ public class DroolsVisitor String importName = importNameNode.getImage(); ImportFact imp = new ImportFact( acu, importName, - node.isImportOnDemand()); + node.isImportOnDemand(), + node.getBeginLine()); memory.assertObject( imp ); return node.childrenAccept( this, data ); diff --git a/pmd-rx/src/net/sourceforge/pmd/rx/facts/ImportFact.java b/pmd-rx/src/net/sourceforge/pmd/rx/facts/ImportFact.java index 10430569d1..92b22f2e72 100644 --- a/pmd-rx/src/net/sourceforge/pmd/rx/facts/ImportFact.java +++ b/pmd-rx/src/net/sourceforge/pmd/rx/facts/ImportFact.java @@ -4,12 +4,14 @@ public class ImportFact { private ACUFact acu = null; private String importPackage = null; private boolean onDemand = true; + private int lineNumber = -1; public ImportFact( ACUFact acu, String importPackage, - boolean onDemand ) { + boolean onDemand, int lineNumber ) { this.acu = acu; this.importPackage = importPackage; this.onDemand = onDemand; + this.lineNumber = lineNumber; } public ACUFact getACU() { @@ -23,4 +25,16 @@ public class ImportFact { public boolean isOnDemand() { return onDemand; } + + public int getLineNumber() { + return lineNumber; + } + + public String toString() { + if (onDemand) { + return Integer.toString(lineNumber) + ": " + importPackage + ".*"; + } else { + return Integer.toString(lineNumber) + ": " + importPackage; + } + } } diff --git a/pmd-rx/src/net/sourceforge/pmd/rx/facts/RuleViolation.java b/pmd-rx/src/net/sourceforge/pmd/rx/facts/RuleViolationFact.java similarity index 74% rename from pmd-rx/src/net/sourceforge/pmd/rx/facts/RuleViolation.java rename to pmd-rx/src/net/sourceforge/pmd/rx/facts/RuleViolationFact.java index 8003b1e52d..94b3c16688 100644 --- a/pmd-rx/src/net/sourceforge/pmd/rx/facts/RuleViolation.java +++ b/pmd-rx/src/net/sourceforge/pmd/rx/facts/RuleViolationFact.java @@ -1,10 +1,10 @@ package net.sourceforge.pmd.rx.facts; -public class RuleViolation { +public class RuleViolationFact { private String desc = null; private Object fact = null; - public RuleViolation(String desc, Object fact) { + public RuleViolationFact(Object fact, String desc) { this.desc = desc; this.fact = fact; } diff --git a/pmd-rx/src/net/sourceforge/pmd/rx/rules/DuplicateImport.java b/pmd-rx/src/net/sourceforge/pmd/rx/rules/DuplicateImport.java new file mode 100644 index 0000000000..820d830759 --- /dev/null +++ b/pmd-rx/src/net/sourceforge/pmd/rx/rules/DuplicateImport.java @@ -0,0 +1,100 @@ +package net.sourceforge.pmd.rx.rules; + +import net.sourceforge.pmd.rx.facts.*; + +import org.drools.*; +import org.drools.spi.*; +import org.drools.semantic.java.*; + +public class DuplicateImport + extends org.drools.spi.Rule + implements Action, FilterCondition +{ + private Declaration req[] = new Declaration[2]; + + public DuplicateImport() { + super("DuplicateImport"); + + try { + req[0] = new Declaration( new JavaObjectType( ImportFact.class ), + "import-0" ); + req[1] = new Declaration( new JavaObjectType( ImportFact.class ), + "import-1" ); + + addParameterDeclaration( req[0] ); + addParameterDeclaration( req[1] ); + + addFilterCondition( this ); + + setAction( this ); + + } catch (DeclarationAlreadyCompleteException dce) { + // Shouldn't happen. . . + dce.printStackTrace(); + throw new RuntimeException( dce.getMessage() ); + } + } + + // FilterCondition + public Declaration[] getRequiredTupleMembers() { + return req; + } + + public String getPackage( ImportFact impFact ) { + if (impFact.isOnDemand()) { + return impFact.getImportPackage(); + } else { + String impPack = impFact.getImportPackage(); + return impPack.substring( 0, + impPack.lastIndexOf(".")); + } + } + + public boolean isAllowed( Tuple tuple ) { + ImportFact import0 = (ImportFact) tuple.get( req[0] ); + ImportFact import1 = (ImportFact) tuple.get( req[1] ); + + if (import0.getACU() != import1.getACU()) { + return false; + } + + if (import0.getLineNumber() == import1.getLineNumber()) { + return false; + } + + if (import0.isOnDemand()) { + return getPackage( import0 ).equals( getPackage( import1 )); + } + + if (import1.isOnDemand()) { + return getPackage( import0 ).equals( getPackage( import1 )); + } + + return import0.getImportPackage().equals( import1.getImportPackage()); + } + + public void invoke(Tuple tuple, + WorkingMemory memory ) { + try { + System.err.println("---- invoke ----"); + System.err.println( tuple.get(req[0]) ); + System.err.println( tuple.get(req[1]) ); + + if (tuple.get(req[0]) == null) return; + if (tuple.get(req[1]) == null) return; + + if (isAllowed( tuple )) { + ImportFact import0 = (ImportFact) tuple.get(req[0]); + ImportFact import1 = (ImportFact) tuple.get(req[1]); + + memory.assertObject(new RuleViolationFact( import0, + "Duplicate Import" )); + memory.assertObject(new RuleViolationFact( import1, + "Duplicate Import" )); + } else { return; } + } catch (AssertionException ase) { + ase.printStackTrace(); + throw new RuntimeException( ase.getMessage()); + } + } +}