Initial revision

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Tom Copeland
2002-06-24 13:23:28 +00:00
parent 153dae3124
commit 4267964e0d
158 changed files with 18147 additions and 0 deletions

1147
pmd/etc/Java1.2-b.jjt Normal file

File diff suppressed because it is too large Load Diff

1146
pmd/etc/Java1.4-c.jjt Normal file

File diff suppressed because it is too large Load Diff

102
pmd/etc/build.xml Normal file
View File

@ -0,0 +1,102 @@
<project name="pmd" default="compile" basedir="../">
<property name="lib" value="lib\"/>
<property name="src" value="src\"/>
<property name="build" value="build\"/>
<property name="regress" value="regress\"/>
<property name="reports" value="reports\"/>
<target name="delete">
<delete dir="${build}"/>
<delete file="${lib}\pmd.jar"/>
<mkdir dir="${build}"/>
</target>
<target name="compile">
<javac deprecation="false"
debug="true"
optimize="false"
srcdir="${src}:${regress}"
destdir="${build}">
</javac>
</target>
<target name="jar">
<mkdir dir="${lib}"/>
<jar jarfile="${lib}\pmd.jar" basedir="${build}"/>
</target>
<target name="pmd">
<taskdef name="pmd" classname="com.infoether.pmd.PMDTask"/>
<pmd reportFile="c:\foo.txt" verbose="true" rulesettype="all">
<fileset dir="c:\data\pmd\pmd\src\">
<include name="**/*.java"/>
</fileset>
</pmd>
</target>
<target name="test">
<junit printsummary="yes" haltonfailure="yes">
<classpath>
<pathelement location="${build}" />
<pathelement path="${java.class.path}" />
</classpath>
<formatter type="plain" />
<batchtest fork="no" todir="${build}">
<fileset dir="${regress}">
<include name="test/**/*Test.java" />
</fileset>
</batchtest>
</junit>
</target>
<path id="quilt.classpath">
<pathelement location="${lib.repo}/quilt-0.4.jar" />
<pathelement location="${lib.repo}/bcel-5.1-dev.jar" />
<pathelement location="${lib.repo}/commons-graph.jar" />
<pathelement location="${lib.repo}/commons-collections.jar" />
<pathelement location="${lib.repo}/colt.jar" />
</path>
<target name="cover">
<taskdef name="quilt" classname="junit.quilt.ant.AntQuiltRunner" classpathref="quilt.classpath" />
<quilt reportdir="${reports}"
register="junit.quilt.cover.ball94.B94Registry"
reporter="junit.quilt.reports.XMLSummary"
packages="com.infoether.pmd">
<classpath>
<pathelement location="${build}" />
</classpath>
<fileset dir="${src}">
<include name="**/*Test.java" />
</fileset>
</quilt>
</target>
<target name="jjtree">
<mkdir dir="tmp"/>
<copy overwrite="yes" todir="tmp">
<fileset dir="src/com/infoether/pmd/ast" includes="SimpleNode.java,JavaParserVisitorAdapter.java"/>
</copy>
<delete>
<fileset dir="src/com/infoether/pmd/ast" includes="*.java,*.jj"/>
</delete>
<jjtree target="etc/Java1.4-c.jjt" outputdirectory="src/com/infoether/pmd/ast" javacchome="c:/javacc2.1"/>
<javacc target="src/com/infoether/pmd/ast/Java1.4-c.jj" outputdirectory="src/com/infoether/pmd/ast" javacchome="c:/javacc2.1"/>
<copy overwrite="yes" todir="src/com/infoether/pmd/ast">
<fileset dir="tmp" includes="*.java"/>
</copy>
<delete file="src/com/infoether/pmd/ast/Java1.4-c.jj"/>
<delete dir="tmp"/>
</target>
<target name="clean" depends="delete,compile"/>
<target name="dist" depends="clean,jar"/>
</project>

5
pmd/etc/go.bat Executable file
View File

@ -0,0 +1,5 @@
@echo off
set MAIN=com.infoether.pmd.PMD
set TEST_FILE=c:\\data\\pmd\\pmd\\test-data\\%1%.java
java %MAIN% %TEST_FILE%

5
pmd/etc/scp.bat Executable file
View File

@ -0,0 +1,5 @@
set CVSROOT=:ext:tomcopeland@cvs.pmd.sourceforge.net:/cvsroot/pmd
set HOME=c:
set CVS_RSH=c:\bin\ssh\ssh
set CLASSPATH=../build/
set CLASSPATH=%CLASSPATH%;c:\javacc2.1\bin\lib\JavaCC.zip

1
pmd/etc/upload.bat Executable file
View File

@ -0,0 +1 @@
pscp ..\lib\pmd.jar build@cvs.ultralog.net:/home/build

View File

@ -0,0 +1,185 @@
/*
* User: tom
* Date: Jun 17, 2002
* Time: 3:19:33 PM
*/
package test.com.infoether.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.*;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
public class FunctionalTest extends TestCase{
public FunctionalTest(String name) {
super(name);
}
public void testUnusedLocal1() {
Report report = process(new File(root() + "Unused1.java"));
assertEquals(1, report.getSize());
assertEquals(new UnusedLocalVariableRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testUnusedLocal2() {
Report report = process(new File(root() + "Unused2.java"));
assertEquals(1, report.getSize());
assertEquals(new UnusedLocalVariableRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testUnusedLocal3() {
Report report = process(new File(root() + "Unused3.java"));
assertEquals(1, report.getSize());
assertEquals(new UnusedLocalVariableRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testUnusedLocal4() {
Report report = process(new File(root() + "Unused4.java"));
assertTrue(report.empty());
}
public void testUnusedLocal5() {
Report report = process(new File(root() + "Unused5.java"));
assertEquals(1, report.getSize());
assertEquals(new UnusedLocalVariableRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testUnusedLocal6() {
Report report = process(new File(root() + "Unused6.java"));
assertTrue(report.empty());
}
public void testUnusedLocal7() {
Report report = process(new File(root() + "Unused7.java"));
assertTrue(report.empty());
}
public void testUnusedLocal8() {
Report report = process(new File(root() + "Unused8.java"));
assertEquals(1, report.getSize());
assertEquals(new SystemPropsRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testUnusedLocal9() {
Report report = process(new File(root() + "Unused9.java"));
assertEquals(2, report.getSize());
Iterator i = report.iterator();
assertEquals(new UnusedLocalVariableRule(), ((RuleViolation)i.next()).getRule());
assertEquals(new UnusedLocalVariableRule(), ((RuleViolation)i.next()).getRule());
}
public void testUnusedLocal10() {
Report report = process(new File(root() + "Unused10.java"));
assertTrue(report.empty());
}
public void testEmptyCatchBlock() {
Report report = process(new File(root() + "EmptyCatchBlock.java"));
assertEquals(1, report.getSize());
assertEquals(new EmptyCatchBlockRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testUnnecessaryTemporaries() {
Report report = process(new File(root() + "UnnecessaryTemporary.java"));
assertEquals(6, report.getSize());
assertEquals(new UnnecessaryConversionTemporaryRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testProps() {
Report report = process(new File(root() + "ContainsSystemGetProps.java"));
assertEquals(3, report.getSize());
assertEquals(new SystemPropsRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testSystemIn() {
Report report = process(new File(root() + "ContainsSystemIn.java"));
assertEquals(3, report.getSize());
assertEquals(new SystemOutRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testSystemOut() {
Report report = process(new File(root() + "ContainsSystemOut.java"));
assertEquals(1, report.getSize());
assertEquals(new SystemOutRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testCreateAThread() {
Report report = process(new File(root() + "CreatesAThread.java"));
assertEquals(1, report.getSize());
assertEquals(new DontCreateThreadsRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testCreateATimer() {
Report report = process(new File(root() + "CreatesATimer.java"));
assertEquals(1, report.getSize());
assertEquals(new DontCreateTimersRule(), ((RuleViolation)report.iterator().next()).getRule());
}
public void testEmptyIf() {
Report report = process(new File(root() + "EmptyIfStmtRule.java"));
assertEquals(1, report.getSize());
assertEquals(new EmptyIfStmtRule(), ((RuleViolation)report.iterator().next()).getRule());
}
/*
public void testUnusedPrivateInstanceVar1() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar1.java"));
assertEquals(1, report.getSize());
Iterator i = report.iterator();
assertEquals(new UnusedPrivateInstanceVariableRule(), ((RuleViolation)i.next()).getRule());
}
public void testUnusedPrivateInstanceVar2() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar2.java"));
assertTrue(report.empty());
}
public void testUnusedPrivateInstanceVar3() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar3.java"));
assertEquals(1, report.getSize());
Iterator i = report.iterator();
assertEquals(new UnusedPrivateInstanceVariableRule(), ((RuleViolation)i.next()).getRule());
}
public void testUnusedPrivateInstanceVar4() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar4.java"));
assertTrue(report.empty());
}
public void testUnusedPrivateInstanceVar6() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar6.java"));
assertTrue(report.empty());
}
public void testUnusedPrivateInstanceVar7() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar7.java"));
assertTrue(report.empty());
}
public void testUnusedPrivateInstanceVar8() {
Report report = process(new File(root() + "UnusedPrivateInstanceVar8.java"));
assertTrue(report.empty());
}
*/
// TODO
// there's another test here that needs to work, see UnusedPrivateInstanceVar5.java
// 'foo' should be marked as an unused instance variable, but it isn't because the
// anonymous inner classes are broken for that rule because the "doingIDTraversal" is an
// instance variable
// TODO
private Report process(File file) {
PMD p = new PMD();
return p.processFile(file, RuleFactory.ALL);
}
private String root() {
if (System.getProperty("os.name").indexOf("Linux") != -1) {
return "/home/build/hourly/working/pmd/test-data" + System.getProperty("file.separator");
}
return "c:\\data\\pmd\\pmd\\test-data" + System.getProperty("file.separator");
}
}

View File

@ -0,0 +1,32 @@
/*
* User: tom
* Date: Jun 21, 2002
* Time: 2:21:44 PM
*/
package test.com.infoether.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.Namespace;
import com.infoether.pmd.SymbolTable;
public class NamespaceTest extends TestCase{
public NamespaceTest(String name) {
super(name);
}
public void testBasic() {
Namespace nameSpace = new Namespace();
nameSpace.addTable();
assertEquals(1, nameSpace.size());
nameSpace.removeTable();
assertEquals(0, nameSpace.size());
}
public void testParent() {
Namespace nameSpace = new Namespace();
nameSpace.addTable();
SymbolTable parent = nameSpace.peek();
nameSpace.addTable();
assertEquals(parent, nameSpace.peek().getParent());
}
}

View File

@ -0,0 +1,47 @@
/*
* User: tom
* Date: Jun 14, 2002
* Time: 1:18:30 PM
*/
package test.com.infoether.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.Report;
import com.infoether.pmd.RuleViolation;
import com.infoether.pmd.Rule;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ReportTest extends TestCase {
private static class MyInv implements InvocationHandler {
private String in;
public MyInv() {}
public MyInv(String in) {
this.in = in;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return in;
}
}
public ReportTest(String name) {
super(name);
}
public void testBasic() {
Report r = new Report("foo");
Rule rule = (Rule) Proxy.newProxyInstance(Rule.class.getClassLoader(), new Class[] {Rule.class }, new MyInv());
r.addRuleViolation(new RuleViolation(rule, 5));
assertTrue(!r.empty());
}
public void testRender() {
Report r = new Report("foo");
InvocationHandler ih = new MyInv("foo");
Rule rule = (Rule) Proxy.newProxyInstance(Rule.class.getClassLoader(), new Class[] {Rule.class }, ih);
r.addRuleViolation(new RuleViolation(rule, 5));
assertTrue(r.renderToText().indexOf("foo") != -1);
}
}

View File

@ -0,0 +1,47 @@
/*
* User: tom
* Date: Jun 20, 2002
* Time: 8:43:20 AM
*/
package test.com.infoether.pmd;
import junit.framework.TestCase;
import java.util.List;
import com.infoether.pmd.RuleFactory;
import com.infoether.pmd.Rule;
import com.infoether.pmd.DontCreateTimersRule;
import com.infoether.pmd.EmptyIfStmtRule;
public class RuleFactoryTest extends TestCase {
public RuleFactoryTest(String name) {
super(name);
}
public void testCougaar() {
List r = RuleFactory.createRules(RuleFactory.COUGAAR);
assertTrue(r.contains(new DontCreateTimersRule()));
}
public void testAll() {
List r = RuleFactory.createRules(RuleFactory.ALL);
assertTrue(r.contains(new EmptyIfStmtRule()));
}
public void testGeneral() {
List r = RuleFactory.createRules(RuleFactory.GENERAL);
assertTrue(r.contains(new EmptyIfStmtRule()));
assertTrue(!r.contains(new DontCreateTimersRule()));
}
public void testException() {
try {
RuleFactory.createRules("blah");
} catch (Exception e) {
return; // cool
}
throw new RuntimeException("Should have thrown RuntimeException");
}
}

View File

@ -0,0 +1,27 @@
package test.com.infoether.pmd;
import junit.framework.*;
import com.infoether.pmd.*;
import java.util.*;
public class RuleViolationTest extends TestCase {
public RuleViolationTest(String name) {
super(name);
}
public void testBasic() {
RuleViolation r = new RuleViolation(new Rule() {
public String getName() {return "name";}
public String getDescription() {return "desc";}
}, 2);
assertTrue(r.getText().indexOf("name") != -1);
}
public void testBasic2() {
RuleViolation r = new RuleViolation(new Rule() {
public String getName() {return "name";}
public String getDescription() {return "desc";}
}, 2, "foo");
assertTrue(r.getText().indexOf("foo") != -1);
}
}

View File

@ -0,0 +1,95 @@
/*
* User: tom
* Date: Jun 19, 2002
* Time: 11:09:06 AM
*/
package test.com.infoether.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.SymbolTable;
import com.infoether.pmd.Symbol;
import java.util.HashMap;
public class SymbolTableTest extends TestCase {
private static final Symbol FOO = new Symbol("foo", 10);
public SymbolTableTest(String name) {
super(name);
}
public void testAdd() {
SymbolTable s = new SymbolTable();
s.add(FOO);
try {
s.add(FOO);
} catch (RuntimeException e) {
return; // cool
}
throw new RuntimeException("Should have thrown RuntimeException");
}
public void testParent() {
SymbolTable parent = new SymbolTable();
SymbolTable child = new SymbolTable(parent);
assertEquals(child.getParent(), parent);
}
public void testAddSameSymbol() {
SymbolTable parent = new SymbolTable();
parent.add(FOO);
SymbolTable child = new SymbolTable(parent);
try {
child.add(FOO);
} catch (RuntimeException e) {
return; // cool
}
throw new RuntimeException("Should have thrown RuntimeException");
}
public void testParentContains2() {
SymbolTable parent = new SymbolTable();
SymbolTable child = new SymbolTable(parent);
child.add(new Symbol("bar", 12));
child.add(new Symbol("baz", 12));
assertTrue(!parent.getUnusedSymbols().hasNext());
assertTrue(child.getUnusedSymbols().hasNext());
}
public void testRecordUsage() {
SymbolTable s = new SymbolTable();
s.add(FOO);
assertTrue(s.getUnusedSymbols().hasNext());
s.recordPossibleUsageOf(FOO);
assertTrue(!s.getUnusedSymbols().hasNext());
}
public void testRecordPossibleUsage() {
SymbolTable parent = new SymbolTable();
SymbolTable child = new SymbolTable(parent);
child.recordPossibleUsageOf(new Symbol("bar", 10));
assertTrue(!parent.getUnusedSymbols().hasNext());
}
public void testRecordPossibleUsage2() {
SymbolTable s = new SymbolTable();
s.recordPossibleUsageOf(new Symbol("bar", 10));
assertTrue(!s.getUnusedSymbols().hasNext());
}
public void testRecordUsageParent() {
SymbolTable parent = new SymbolTable();
parent.add(FOO);
SymbolTable child = new SymbolTable(parent);
assertEquals(FOO, parent.getUnusedSymbols().next());
}
public void testRecordUsageParent2() {
SymbolTable parent = new SymbolTable();
parent.add(FOO);
SymbolTable child = new SymbolTable(parent);
child.recordPossibleUsageOf(FOO);
assertTrue(!parent.getUnusedSymbols().hasNext());
}
}

View File

@ -0,0 +1,24 @@
/*
* User: tom
* Date: Jun 19, 2002
* Time: 11:59:24 AM
*/
package test.com.infoether.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.Symbol;
public class SymbolTest extends TestCase {
public SymbolTest(String name) {
super(name);
}
public void testBasic() {
Symbol s = new Symbol("foo", 10);
assertEquals(10, s.getLine());
assertEquals("foo", s.getImage());
assertEquals(s, new Symbol("foo", 5));
assertEquals(s.hashCode(), new Symbol("foo", 6).hashCode());
}
}

View File

@ -0,0 +1,21 @@
/*
* User: tom
* Date: Jun 17, 2002
* Time: 5:44:22 PM
*/
package com.infoether.pmd;
import com.infoether.pmd.ast.JavaParserVisitorAdapter;
public abstract class AbstractRule extends JavaParserVisitorAdapter {
public String getName() {return getClass().getName();}
public boolean equals(Object o) {
Rule r = (Rule)o;
return r.getName().equals(getName());
}
public int hashCode() {
return getName().hashCode();
}
}

View File

@ -0,0 +1,20 @@
package com.infoether.pmd;
import com.infoether.pmd.ast.JavaParserVisitorAdapter;
import com.infoether.pmd.ast.ASTAllocationExpression;
import com.infoether.pmd.ast.ASTName;
import java.util.*;
public class DontCreateThreadsRule extends AbstractRule implements Rule {
public String getDescription() {return "Don't create threads, use the ThreadService instead";}
public Object visit(ASTAllocationExpression node, Object data){
if ((node.jjtGetChild(0) instanceof ASTName) // this avoids "new <primitive-type>", i.e., "new int[]"
&& ((ASTName)node.jjtGetChild(0)).getImage().equals("Thread")) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node, data);
}
}

View File

@ -0,0 +1,20 @@
package com.infoether.pmd;
import com.infoether.pmd.ast.JavaParserVisitorAdapter;
import com.infoether.pmd.ast.ASTAllocationExpression;
import com.infoether.pmd.ast.ASTName;
import java.util.*;
public class DontCreateTimersRule extends AbstractRule implements Rule {
public String getDescription() {return "Don't create java.util.Timers, use the Cougaar alarm service instead";}
public Object visit(ASTAllocationExpression node, Object data){
if ((node.jjtGetChild(0) instanceof ASTName) // this avoids "new <primitive-type>", i.e., "new int[]"
&& ((ASTName)node.jjtGetChild(0)).getImage().equals("Timer")) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node, data);
}
}

View File

@ -0,0 +1,21 @@
/*
* User: tom
* Date: Jun 14, 2002
* Time: 12:13:55 PM
*/
package com.infoether.pmd;
import com.infoether.pmd.ast.*;
public class EmptyCatchBlockRule extends AbstractRule implements Rule {
public String getDescription() {return "Avoid empty catch blocks";}
public Object visit(ASTBlock node, Object data){
if ((node.jjtGetParent() instanceof ASTTryStatement) && node.jjtGetNumChildren()==0) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node, data);
}
}

View File

@ -0,0 +1,23 @@
/*
* User: tom
* Date: Jun 17, 2002
* Time: 4:23:30 PM
*/
package com.infoether.pmd;
import com.infoether.pmd.ast.JavaParserVisitorAdapter;
import com.infoether.pmd.ast.ASTBlock;
import com.infoether.pmd.ast.ASTTryStatement;
import com.infoether.pmd.ast.ASTIfStatement;
public class EmptyIfStmtRule extends AbstractRule implements Rule {
public String getDescription() {return "Avoid empty IF statements";}
public Object visit(ASTBlock node, Object data){
if ((node.jjtGetParent().jjtGetParent() instanceof ASTIfStatement) && node.jjtGetNumChildren()==0) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node, data);
}
}

View File

@ -0,0 +1,63 @@
/*
* User: tom
* Date: Jun 21, 2002
* Time: 2:11:15 PM
*/
package com.infoether.pmd;
import java.util.Stack;
/**
*
* Here's the problem:
*
* public class Outer
* {
* private String foo;
* public void foo() {
* bar(new Runnable() {public void run() {String foo;}});
* }
* private void bar(Runnable r) {}
* }
*
* In this example, Outer.foo and the Runnable.foo are two different variables - even though
* Runnable.foo looks like its inside Outer, they don't conflict.
*
* So, a couple of SymbolTables are grouped into a Namespace. SymbolTables are grouped so that inner classes have their own
* "group" of symbol tables. So a class with an inner class would look like this:
*
* ST
* ST
* NS2
* ST ST ST
* ST ST ST
* NS1 NS1 NS1
*
* That way the scopes work out nicely and inner classes can be arbitrarily nested.
*/
public class Namespace {
private Stack tables = new Stack();
public void addTable() {
if (tables.empty()) {
tables.push(new SymbolTable());
} else {
tables.push(new SymbolTable((SymbolTable)tables.peek()));
}
}
public void removeTable() {
tables.pop();
}
public SymbolTable peek() {
return (SymbolTable)tables.peek();
}
public int size() {
return tables.size();
}
}

View File

@ -0,0 +1,65 @@
/*
* User: tom
* Date: Jun 17, 2002
* Time: 3:23:17 PM
*/
package com.infoether.pmd;
import com.infoether.pmd.ast.JavaParser;
import com.infoether.pmd.ast.ASTCompilationUnit;
import com.infoether.pmd.ast.JavaParserVisitor;
import com.infoether.pmd.ast.ParseException;
import java.io.*;
import java.util.List;
import java.util.Iterator;
public class PMD {
public Report processFile(InputStream is) {
return null;
}
public Report processFile(FileReader fr) {
return null; }
public Report processFile(File file, String ruleSetType) {
Report report = new Report(file.getAbsolutePath());
List rules = RuleFactory.createRules(ruleSetType);
try {
Reader reader = new BufferedReader(new FileReader(file));
JavaParser parser = new JavaParser(reader);
ASTCompilationUnit c = parser.CompilationUnit();
//c.dump("");
for (Iterator iterator = rules.iterator(); iterator.hasNext();) {
JavaParserVisitor rule = (JavaParserVisitor)iterator.next();
c.childrenAccept(rule, report);
}
reader.close();
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (ParseException pe) {
System.out.println("Error while parsing " + file.getAbsolutePath() + " at line " + pe.currentToken.beginLine + "; continuing...");
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Throwable t) {
System.out.println("Error while parsing " + file.getAbsolutePath() + "; "+ t.getMessage() + "; continuing...");
//t.printStackTrace();
}
return report;
}
public static void main(String[] args) {
if (args.length == 0) {
throw new RuntimeException("Pass a filename in");
}
File input = new File(args[0]);
if (!input.exists()) {
throw new RuntimeException("File " + args[0] + " doesn't exist");
}
PMD pmd = new PMD();
Report report = pmd.processFile(input, RuleFactory.ALL);
System.out.println(report.renderToText());
}
}

View File

@ -0,0 +1,68 @@
package com.infoether.pmd;
import org.apache.tools.ant.*;
import org.apache.tools.ant.types.*;
import java.util.*;
import java.io.*;
import com.infoether.pmd.ast.JavaParser;
import com.infoether.pmd.ast.JavaParserVisitor;
import com.infoether.pmd.ast.ParseException;
import com.infoether.pmd.ast.ASTCompilationUnit;
public class PMDTask extends Task {
private List filesets = new ArrayList();
private String reportFile;
private boolean verbose;
private String ruleSetType;
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
public void setRuleSetType(String ruleSetType) {
this.ruleSetType = ruleSetType;
}
public void addFileset(FileSet set) {
filesets.add(set);
}
public void setReportFile(String reportFile) {
this.reportFile = reportFile;
}
public void execute() throws BuildException {
if (reportFile == null) {
throw new BuildException("No report file specified");
}
if (ruleSetType == null) {
throw new BuildException("No rule set type specified");
}
StringBuffer buf = new StringBuffer();
for (Iterator i = filesets.iterator(); i.hasNext();) {
FileSet fs = (FileSet) i.next();
DirectoryScanner ds = fs.getDirectoryScanner(project);
String[] srcFiles = ds.getIncludedFiles();
for (int j=0; j<srcFiles.length; j++) {
File file = new File(ds.getBasedir() + System.getProperty("file.separator") + srcFiles[j]);
if (verbose) System.out.println(file.getAbsoluteFile());
PMD pmd = new PMD();
Report report = pmd.processFile(file, ruleSetType);
if (!report.empty()) {
buf.append(report.renderToText());
buf.append(System.getProperty("line.separator"));
}
}
}
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(reportFile)));
writer.write(buf.toString(), 0, buf.length());
writer.close();
} catch (IOException ioe) {
throw new BuildException(ioe.getMessage());
}
}
}

View File

@ -0,0 +1,40 @@
package com.infoether.pmd;
import java.util.*;
public class Report {
private List violations = new ArrayList();
private String filename;
public Report(String filename) {
this.filename = filename;
}
public void addRuleViolation(RuleViolation violation) {
violations.add(violation);
}
public String renderToText() {
StringBuffer buf = new StringBuffer();
for (Iterator i = violations.iterator(); i.hasNext();) {
if (buf.length() != 0) {
buf.append(System.getProperty("line.separator"));
}
buf.append(filename + ":" + ((RuleViolation)i.next()).getText());
}
return buf.toString();
}
public boolean empty() {
return violations.size() == 0;
}
public Iterator iterator() {
return violations.iterator();
}
public int getSize() {
return violations.size();
}
}

View File

@ -0,0 +1,8 @@
package com.infoether.pmd;
import java.util.*;
public interface Rule {
public String getName();
public String getDescription();
}

View File

@ -0,0 +1,55 @@
/*
* User: tom
* Date: Jun 10, 2002
* Time: 11:27:51 AM
*/
package com.infoether.pmd;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class RuleFactory {
public static final String ALL = "all";
public static final String GENERAL = "general";
public static final String COUGAAR = "cougaar";
public static List createRules(String ruleSetType) {
if (ruleSetType.equals(ALL)) {
return createAllRules();
} else if (ruleSetType.equals(GENERAL)) {
return createGeneralRules();
} else if (ruleSetType.equals(COUGAAR)) {
return createCougaarRules();
}
throw new RuntimeException("Unknown rule set type " + ruleSetType);
}
private static List createAllRules() {
List list = new ArrayList();
list.addAll(createCougaarRules());
list.addAll(createGeneralRules());
return list;
}
private static List createCougaarRules() {
List list = new ArrayList();
list.add(new DontCreateThreadsRule());
list.add(new DontCreateTimersRule());
list.add(new SystemOutRule());
list.add(new SystemPropsRule());
return list;
}
private static List createGeneralRules() {
List list = new ArrayList();
list.add(new EmptyCatchBlockRule());
list.add(new EmptyIfStmtRule());
list.add(new UnnecessaryConversionTemporaryRule());
list.add(new UnusedLocalVariableRule());
//list.add(new UnusedPrivateInstanceVariableRule());
return list;
}
}

View File

@ -0,0 +1,26 @@
package com.infoether.pmd;
public class RuleViolation {
private int line;
private Rule rule;
private String specificDescription;
public RuleViolation(Rule rule, int line) {
this(rule, line, rule.getDescription());
}
public RuleViolation(Rule rule, int line, String specificDescription) {
this.line = line;
this.rule = rule;
this.specificDescription = specificDescription;
}
public String getText() {
return rule.getName() +":" + specificDescription + ":" + line;
}
public Rule getRule() {
return rule;
}
}

View File

@ -0,0 +1,38 @@
/*
* User: tom
* Date: Jun 19, 2002
* Time: 11:48:50 AM
*/
package com.infoether.pmd;
public class Symbol {
private String image;
private int line;
public Symbol(String image, int line) {
this.image = image;
this.line = line;
}
public int getLine() {
return line;
}
public String getImage() {
return image;
}
public boolean equals(Object o) {
Symbol s = (Symbol)o;
return s.image.equals(this.image);
}
public int hashCode() {
return image.hashCode();
}
public String toString() {
return image + ":" + line;
}
}

View File

@ -0,0 +1,83 @@
/*
* User: tom
* Date: Jun 19, 2002
* Time: 9:31:16 AM
*/
package com.infoether.pmd;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class SymbolTable {
private SymbolTable parent;
private HashMap usageCounts = new HashMap();
public SymbolTable() {}
public SymbolTable(SymbolTable parent) {
this.parent = parent;
}
public SymbolTable getParent() {
return parent;
}
public void add(Symbol symbol) {
if (usageCounts.containsKey(symbol)) {
throw new RuntimeException(symbol + " is already in the symbol table");
}
if (parent != null && parent.contains(symbol)) {
throw new RuntimeException(symbol + " is already in the parent symbol table");
}
usageCounts.put(symbol, new Integer(0));
}
public void recordPossibleUsageOf(Symbol symbol) {
if (!usageCounts.containsKey(symbol) && parent != null) {
parent.recordPossibleUsageOf(symbol);
return;
}
if (!usageCounts.containsKey(symbol) ) {
return;
}
Integer usageCount = (Integer)usageCounts.get(symbol);
usageCount = new Integer(usageCount.intValue() + 1);
usageCounts.put(symbol, usageCount);
}
public Iterator getUnusedSymbols() {
List list = new ArrayList();
for (Iterator i = usageCounts.keySet().iterator(); i.hasNext();) {
Symbol symbol = (Symbol)i.next();
int usageCount = ((Integer)(usageCounts.get(symbol))).intValue();
if (usageCount == 0) {
list.add(symbol);
}
}
return list.iterator();
}
public String toString() {
StringBuffer buf = new StringBuffer();
for (Iterator i = usageCounts.keySet().iterator(); i.hasNext();) {
Symbol symbol = (Symbol)i.next();
int usageCount = ((Integer)(usageCounts.get(symbol))).intValue();
buf.append(symbol + "," + usageCount +":");
}
return buf.toString();
}
protected boolean contains(Symbol symbol) {
if (usageCounts.containsKey(symbol)) {
return true;
}
if (parent == null) {
return false;
}
return parent.contains(symbol);
}
}

View File

@ -0,0 +1,18 @@
package com.infoether.pmd;
import com.infoether.pmd.ast.JavaParserVisitorAdapter;
import com.infoether.pmd.ast.ASTName;
import java.util.*;
public class SystemOutRule extends AbstractRule implements Rule {
public String getDescription() {return "Don't use System.out/in/err, use the Cougaar logging service instead";}
public Object visit(ASTName node, Object data){
if (node.getImage() != null && (node.getImage().startsWith("System.out") || node.getImage().startsWith("System.err") || node.getImage().startsWith("System.in"))) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node,data);
}
}

View File

@ -0,0 +1,19 @@
package com.infoether.pmd;
import com.infoether.pmd.ast.ASTName;
import com.infoether.pmd.ast.JavaParserVisitorAdapter;
import com.infoether.pmd.ast.SimpleNode;
import java.util.*;
public class SystemPropsRule extends AbstractRule implements Rule {
public String getDescription() {return "Don't use System.getProperty()/getProperties()/setProperty";}
public Object visit(ASTName node, Object data){
if (node.getImage() != null && (node.getImage().startsWith("System.getProperty") || node.getImage().startsWith("System.setProperty") || node.getImage().startsWith("System.getProperties"))) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node,data);
}
}

View File

@ -0,0 +1,58 @@
/*
* User: tom
* Date: Jun 20, 2002
* Time: 1:35:27 PM
*/
package com.infoether.pmd;
import com.infoether.pmd.ast.*;
public class UnnecessaryConversionTemporaryRule extends AbstractRule implements Rule{
private boolean inPrimaryExpressionContext;
private boolean usingPrimitiveWrapperAllocation;
public String getDescription() {
return "Avoid unnecessay temporaries when converting primitives to Strings";
}
public Object visit(ASTPrimaryExpression node, Object data) {
if (node.jjtGetNumChildren() == 0 || ((SimpleNode)node.jjtGetChild(0)).jjtGetNumChildren() == 0 || !(node.jjtGetChild(0).jjtGetChild(0) instanceof ASTAllocationExpression)) {
return super.visit(node, data);
}
inPrimaryExpressionContext = true;
Object report = super.visit(node, data);
inPrimaryExpressionContext = false;
usingPrimitiveWrapperAllocation = false;
return report;
}
public Object visit(ASTAllocationExpression node, Object data) {
if (!inPrimaryExpressionContext) {
return super.visit(node, data);
}
if (!(node.jjtGetChild(0) instanceof ASTName)) {
return super.visit(node, data);
}
SimpleNode child = (SimpleNode)node.jjtGetChild(0);
if (!isPrimitiveWrapperType(child.getImage())) {
return super.visit(node, data);
}
usingPrimitiveWrapperAllocation = true;
return super.visit(node, data);
}
public Object visit(ASTPrimarySuffix node, Object data) {
if (!inPrimaryExpressionContext || !usingPrimitiveWrapperAllocation) {
return super.visit(node, data);
}
if (node.getImage() != null && node.getImage().equals("toString")) {
((Report)data).addRuleViolation(new RuleViolation(this, node.getBeginLine()));
}
return super.visit(node, data);
}
private boolean isPrimitiveWrapperType(String name) {
return name.equals("Integer") || name.equals("Boolean") || name.equals("Double") || name.equals("Long") || name.equals("Short") || name.equals("Byte") || name.equals("Float");
}
}

Some files were not shown because too many files have changed in this diff Show More