*** empty log message ***

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@16 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Tom Copeland 2002-06-24 15:50:34 +00:00
parent f8f1722140
commit e65dfc8a04
126 changed files with 1036 additions and 123 deletions

View File

@ -33,7 +33,7 @@ Runs a set of PMD rules on a set of files and generates a report.
<h3>Examples</h3>
<pre>
&lt;target name="pmd"&gt;
&lt;taskdef name="pmd" classname="com.infoether.pmd.PMDTask"/&gt;
&lt;taskdef name="pmd" classname="net.sourceforge.pmd.PMDTask"/&gt;
&lt;pmd reportFile="c:\foo.txt" verbose="false" rulesettype="general"&gt;
&lt;fileset dir="c:\j2sdk1.4.0\src\"&gt;
&lt;include name="**/*.java"/&gt;

View File

@ -3,16 +3,16 @@
* Date: Jun 17, 2002
* Time: 3:19:33 PM
*/
package test.com.infoether.pmd;
package test.net.sourceforge.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.*;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
import net.sourceforge.pmd.*;
public class FunctionalTest extends TestCase{
public FunctionalTest(String name) {

View File

@ -3,11 +3,11 @@
* Date: Jun 21, 2002
* Time: 2:21:44 PM
*/
package test.com.infoether.pmd;
package test.net.sourceforge.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.Namespace;
import com.infoether.pmd.SymbolTable;
import net.sourceforge.pmd.Namespace;
import net.sourceforge.pmd.SymbolTable;
public class NamespaceTest extends TestCase{
public NamespaceTest(String name) {

View File

@ -3,12 +3,12 @@
* Date: Jun 14, 2002
* Time: 1:18:30 PM
*/
package test.com.infoether.pmd;
package test.net.sourceforge.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.Report;
import com.infoether.pmd.RuleViolation;
import com.infoether.pmd.Rule;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.Rule;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;

View File

@ -3,16 +3,16 @@
* Date: Jun 20, 2002
* Time: 8:43:20 AM
*/
package test.com.infoether.pmd;
package test.net.sourceforge.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;
import net.sourceforge.pmd.RuleFactory;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.DontCreateTimersRule;
import net.sourceforge.pmd.EmptyIfStmtRule;
public class RuleFactoryTest extends TestCase {
public RuleFactoryTest(String name) {

View File

@ -1,9 +1,11 @@
package test.com.infoether.pmd;
package test.net.sourceforge.pmd;
import junit.framework.*;
import com.infoether.pmd.*;
import java.util.*;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleViolation;
public class RuleViolationTest extends TestCase {
public RuleViolationTest(String name) {
super(name);

View File

@ -3,11 +3,11 @@
* Date: Jun 19, 2002
* Time: 11:09:06 AM
*/
package test.com.infoether.pmd;
package test.net.sourceforge.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.SymbolTable;
import com.infoether.pmd.Symbol;
import net.sourceforge.pmd.SymbolTable;
import net.sourceforge.pmd.Symbol;
import java.util.HashMap;

View File

@ -3,10 +3,10 @@
* Date: Jun 19, 2002
* Time: 11:59:24 AM
*/
package test.com.infoether.pmd;
package test.net.sourceforge.pmd;
import junit.framework.TestCase;
import com.infoether.pmd.Symbol;
import net.sourceforge.pmd.Symbol;
public class SymbolTest extends TestCase {

View File

@ -0,0 +1,21 @@
/*
* User: tom
* Date: Jun 17, 2002
* Time: 5:44:22 PM
*/
package net.sourceforge.pmd;
import net.sourceforge.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 net.sourceforge.pmd;
import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
import net.sourceforge.pmd.ast.ASTAllocationExpression;
import net.sourceforge.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 net.sourceforge.pmd;
import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
import net.sourceforge.pmd.ast.ASTAllocationExpression;
import net.sourceforge.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,22 @@
/*
* User: tom
* Date: Jun 14, 2002
* Time: 12:13:55 PM
*/
package net.sourceforge.pmd;
import net.sourceforge.pmd.ast.ASTBlock;
import net.sourceforge.pmd.ast.ASTTryStatement;
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 net.sourceforge.pmd;
import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
import net.sourceforge.pmd.ast.ASTBlock;
import net.sourceforge.pmd.ast.ASTTryStatement;
import net.sourceforge.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 net.sourceforge.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 net.sourceforge.pmd;
import net.sourceforge.pmd.ast.JavaParser;
import net.sourceforge.pmd.ast.ASTCompilationUnit;
import net.sourceforge.pmd.ast.JavaParserVisitor;
import net.sourceforge.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 net.sourceforge.pmd;
import org.apache.tools.ant.*;
import org.apache.tools.ant.types.*;
import java.util.*;
import java.io.*;
import net.sourceforge.pmd.ast.JavaParser;
import net.sourceforge.pmd.ast.JavaParserVisitor;
import net.sourceforge.pmd.ast.ParseException;
import net.sourceforge.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 net.sourceforge.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 net.sourceforge.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 net.sourceforge.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,27 @@
package net.sourceforge.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 net.sourceforge.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 net.sourceforge.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 net.sourceforge.pmd;
import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
import net.sourceforge.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 net.sourceforge.pmd;
import net.sourceforge.pmd.ast.ASTName;
import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
import net.sourceforge.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 net.sourceforge.pmd;
import net.sourceforge.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");
}
}

View File

@ -0,0 +1,80 @@
/*
* User: tom
* Date: Jun 18, 2002
* Time: 11:02:09 AM
*/
package net.sourceforge.pmd;
import java.util.Iterator;
import java.util.Stack;
import net.sourceforge.pmd.ast.*;
public class UnusedLocalVariableRule extends AbstractRule implements Rule{
private Stack tableGroups = new Stack();
public String getDescription() {
return "Avoid unused local variables";
}
public Object createGroup(SimpleNode node, Object data) {
tableGroups.push(new Namespace());
Object report = super.visit(node, data);
tableGroups.pop();
return report;
}
// these AST types trigger creation of a new symbol table group
public Object visit(ASTClassBody node, Object data) {return createGroup(node, data);}
public Object visit(ASTInterfaceDeclaration node, Object data) {return createGroup(node, data);}
// these AST types trigger creation of a new symbol table group
// these AST types trigger creation of a new symbol table
public Object visit(ASTBlock node, Object data){return addTable(node, data);}
public Object visit(ASTConstructorDeclaration node, Object data){return addTable(node, data);}
public Object visit(ASTMethodDeclaration node, Object data){return addTable(node, data);}
public Object visit(ASTFieldDeclaration node, Object data){return addTable(node, data);}
public Object visit(ASTTryStatement node, Object data){return addTable(node, data);}
public Object visit(ASTForStatement node, Object data){return addTable(node, data);}
// these AST types trigger creation of a new symbol table
// these AST types are variable/name usages
public Object visit(ASTVariableDeclaratorId node, Object data) {
//System.out.println("ASTVariableDeclaratorId.getImage() = " + node.getImage());
if (!(node.jjtGetParent().jjtGetParent() instanceof ASTLocalVariableDeclaration)) {
return super.visit(node, data);
}
Namespace group = (Namespace)tableGroups.peek();
group.peek().add(new Symbol(node.getImage(), node.getBeginLine()));
return super.visit(node, data);
}
public Object visit(ASTName node, Object data) {
//System.out.println("ASTName.getImage() = " + node.getImage() + "; " + node.getBeginLine());
if (node.jjtGetParent() instanceof ASTPrimaryPrefix) {
String img = (node.getImage().indexOf('.') == -1) ? node.getImage() : node.getImage().substring(0, node.getImage().indexOf('.'));
Namespace group = (Namespace)tableGroups.peek();
group.peek().recordPossibleUsageOf(new Symbol(img, node.getBeginLine()));
}
return super.visit(node, data);
}
// these AST types are variable/name usages
private void reportUnusedLocals(Report report, SymbolTable table) {
for (Iterator i = table.getUnusedSymbols(); i.hasNext();) {
Symbol symbol = (Symbol)i.next();
report.addRuleViolation(new RuleViolation(this, symbol.getLine(), "Found unused local variable '" + symbol.getImage() + "'"));
}
}
private Object addTable(SimpleNode node, Object data) {
Namespace group = (Namespace)tableGroups.peek();
group.addTable();
Object RC = super.visit(node, data);
reportUnusedLocals((Report)data, group.peek());
group.removeTable();
return RC;
}
}

View File

@ -0,0 +1,90 @@
/*
* User: tom
* Date: Jun 21, 2002
* Time: 11:26:34 AM
*/
package net.sourceforge.pmd;
import java.util.Iterator;
import java.util.Stack;
import net.sourceforge.pmd.ast.*;
public class UnusedPrivateInstanceVariableRule extends AbstractRule implements Rule {
private Stack nameSpaces = new Stack();
// TODO
// this being an instance variable totally hoses up the recursion
// need to attach it to the report or the stack or something
// TODO
private boolean doingIDTraversal;
public String getDescription() {
return "Avoid unused private instance variables";
}
/**
* Skip interfaces because they don't have instance variables.
*/
public Object visit(ASTInterfaceDeclaration node, Object data) {
return data;
}
public Object visit(ASTClassBody node, Object data) {
doingIDTraversal = true;
Namespace nameSpace = new Namespace();
nameSpaces.push(nameSpace);
nameSpace.addTable();
Object report = super.visit(node, data);
doingIDTraversal = false;
//System.out.println("data = " + data);
report = super.visit(node, data);
reportUnusedInstanceVars((Report)report, nameSpace.peek());
nameSpace.removeTable();
nameSpaces.pop();
return report;
}
public Object visit(ASTVariableDeclaratorId node, Object data) {
if (!doingIDTraversal) {
return super.visit(node, data);
}
//System.out.println("ASTVariableDeclaratorId.getImage() = " + node.getImage() + "; " + node.getBeginLine());
SimpleNode grandparent = (SimpleNode)node.jjtGetParent().jjtGetParent();
if (!(grandparent instanceof ASTFieldDeclaration) || grandparent.getImage().indexOf("private") == -1 || grandparent.getImage().indexOf("static") != -1) {
return super.visit(node, data);
}
Namespace group = (Namespace)nameSpaces.peek();
group.peek().add(new Symbol(node.getImage(), node.getBeginLine()));
return super.visit(node, data);
}
public Object visit(ASTPrimarySuffix node, Object data) {
if (!doingIDTraversal && (node.jjtGetParent() instanceof ASTPrimaryExpression) && (node.getImage() != null)) {
recordPossibleUsage(node, data);
}
return super.visit(node, data);
}
public Object visit(ASTName node, Object data) {
if (!doingIDTraversal && (node.jjtGetParent() instanceof ASTPrimaryPrefix)) {
recordPossibleUsage(node, data);
}
return super.visit(node, data);
}
private void recordPossibleUsage(SimpleNode node, Object data) {
String img = (node.getImage().indexOf('.') == -1) ? node.getImage() : node.getImage().substring(0, node.getImage().indexOf('.'));
Namespace group = (Namespace)nameSpaces.peek();
group.peek().recordPossibleUsageOf(new Symbol(img, node.getBeginLine()));
}
private void reportUnusedInstanceVars(Report report, SymbolTable table) {
for (Iterator i = table.getUnusedSymbols(); i.hasNext();) {
Symbol symbol = (Symbol)i.next();
report.addRuleViolation(new RuleViolation(this, symbol.getLine(), "Found unused private instance variable '" + symbol.getImage() + "'"));
}
}
}

View File

@ -1,6 +1,7 @@
/* Generated By:JJTree: Do not edit this line. ASTAdditiveExpression.java */
package com.infoether.pmd.ast;
package net.sourceforge.pmd.ast;
public class ASTAdditiveExpression extends SimpleNode {
public ASTAdditiveExpression(int id) {

View File

@ -1,6 +1,7 @@
/* Generated By:JJTree: Do not edit this line. ASTAllocationExpression.java */
package com.infoether.pmd.ast;
package net.sourceforge.pmd.ast;
public class ASTAllocationExpression extends SimpleNode {
public ASTAllocationExpression(int id) {

View File

@ -1,6 +1,7 @@
/* Generated By:JJTree: Do not edit this line. ASTAndExpression.java */
package com.infoether.pmd.ast;
package net.sourceforge.pmd.ast;
public class ASTAndExpression extends SimpleNode {
public ASTAndExpression(int id) {

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