Committed Philippe's latest CPD task changes

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@1848 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Tom Copeland
2003-04-22 15:10:05 +00:00
parent 1bc0e86ebf
commit 682a47dbb2
10 changed files with 200 additions and 69 deletions

View File

@ -137,8 +137,8 @@
<target name="cpd">
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />
<cpd minimumTokenCount="100" outputFile="cpd.txt" verbose="false">
<fileset dir="/home/tom/data/pmd/pmd/src">
<cpd format="xml" minimumTokenCount="30" outputFile="cpd.xml">
<fileset dir="/usr/local/java/src/java/lang/ref">
<include name="**/*.java"/>
</fileset>
</cpd>

View File

@ -1,4 +1,5 @@
????? - 1.06:
Removed "verbose" attribute from CPD Ant task; now it uses built in logging so you can do a "ant -verbose cpd". Thanks to Philippe T'Seyen for the code.
TODO - fix it so tests and rules don't duplicate the xpath expressions
April 17 - 1.05:

View File

@ -0,0 +1,72 @@
package test.net.sourceforge.pmd.cpd;
import junit.framework.TestCase;
import net.sourceforge.pmd.cpd.FileReporter;
import net.sourceforge.pmd.cpd.ReportException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
/**
* @author Philippe T'Seyen
*/
public class FileReporterTest extends TestCase
{
public void testCreation() {
try {
FileReporter fileReporter = new FileReporter(null);
fail("expected NullPointerException");
} catch (NullPointerException npe) {
}
}
public void testEmptyReport() throws ReportException {
File reportFile = new File("report.tmp");
FileReporter fileReporter = new FileReporter(reportFile);
fileReporter.report("");
assertTrue(reportFile.exists());
assertEquals(0, reportFile.length());
assertTrue(reportFile.delete());
}
public void testReport() throws ReportException, IOException {
String testString = "first line\nsecond line";
File reportFile = new File("report.tmp");
FileReporter fileReporter = new FileReporter(reportFile);
fileReporter.report(testString);
assertEquals(testString, readFile(reportFile));
assertTrue(reportFile.delete());
}
public void testInvalidFile() {
File reportFile = new File("/invalid_folder/report.tmp");
FileReporter fileReporter = new FileReporter(reportFile);
try {
fileReporter.report("");
fail("expected ReportException");
} catch (ReportException re) {
}
}
private String readFile(File file) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
StringBuffer buffer = new StringBuffer();
String line = reader.readLine();
while (line != null) {
buffer.append(line);
line = reader.readLine();
if (line != null) {
buffer.append("\n");
}
}
return buffer.toString();
} finally {
if (reader != null) reader.close();
}
}
}

View File

@ -2,20 +2,17 @@ package net.sourceforge.pmd.cpd;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.sourceforge.pmd.ant.PathChecker;
/**
* CPDTask
*
@ -34,65 +31,78 @@ import net.sourceforge.pmd.ant.PathChecker;
*
* Required: minimumTokenCount, outputFile, and at least one file
* Optional: verbose
*
* TODO Perhaps come up with another renderer such as XML and
* allow user to plug that render in via ant...
*
* @since Mar 26, 2003
* @author aglover
*/
public class CPDTask extends Task {
private boolean verbose;
private static final String TEXT_FORMAT = "text";
private static final String XML_FORMAT = "xml";
private String format = TEXT_FORMAT;
private int minimumTokenCount;
private String outputFile;
private File outputFile;
private List filesets = new ArrayList();
public void execute() throws BuildException{
try{
validateFields();
CPD cpd = new CPD(minimumTokenCount, new JavaLanguage());
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]);
printIfVerbose("Tokenizing " + file.getAbsoluteFile().toString());
cpd.add(file);
}
}
printIfVerbose("Starting to analyze code ");
long start = System.currentTimeMillis();
cpd.go();
long stop = System.currentTimeMillis();
printIfVerbose("That took " + (stop-start) + " milliseconds");
if (!cpd.getMatches().hasNext()) {
printIfVerbose("No duplicates over " + minimumTokenCount + " tokens found");
write("No problems found");
} else {
printIfVerbose("Duplicates found; putting a report in " + outputFile);
write(new SimpleRenderer().render(cpd.getMatches()));
}
} catch(IOException ex){
ex.printStackTrace();
throw new BuildException("IOException in task", ex);
}
}
public void execute() throws BuildException {
try {
validateFields();
private void write(String content) throws IOException {
Writer writer = getToFileWriter(project.getBaseDir().toString());
writer.write(content);
writer.close();
log("Tokenizing files", Project.MSG_INFO);
CPD cpd = new CPD(minimumTokenCount, new JavaLanguage());
tokenizeFiles(cpd);
log("Starting to analyze code", Project.MSG_INFO);
long timeTaken = analyzeCode(cpd);
log("Done analyzing code; that took " + timeTaken + " milliseconds");
log("Generating report", Project.MSG_INFO);
report(cpd);
} catch (IOException ioe) {
log(ioe.toString(), Project.MSG_ERR);
throw new BuildException("IOException during task execution", ioe);
} catch (ReportException re) {
log(re.toString(), Project.MSG_ERR);
throw new BuildException("ReportException during task execution", re);
}
}
private Writer getToFileWriter(String baseDir) throws IOException {
String outFile = outputFile;
PathChecker pc = new PathChecker(System.getProperty("os.name"));
if (!pc.isAbsolute(outputFile)) {
outFile = baseDir + System.getProperty("file.separator") + outputFile;
private void report(CPD cpd) throws ReportException {
if (!cpd.getMatches().hasNext()) {
log("No duplicates over " + minimumTokenCount + " tokens found", Project.MSG_INFO);
}
Renderer renderer = createRenderer();
if (outputFile.isAbsolute()) {
new FileReporter(outputFile).report(renderer.render(cpd.getMatches()));
} else {
new FileReporter(new File(project.getBaseDir(), outputFile.toString()));
}
}
private void tokenizeFiles(CPD cpd) throws IOException {
for (Iterator iterator = filesets.iterator(); iterator.hasNext();) {
FileSet fileSet = (FileSet) iterator.next();
DirectoryScanner directoryScanner = fileSet.getDirectoryScanner(project);
String[] includedFiles = directoryScanner.getIncludedFiles();
for (int i = 0; i < includedFiles.length; i++) {
File file = new File(directoryScanner.getBasedir() + System.getProperty("file.separator") + includedFiles[i]);
log("Tokenizing " + file.getAbsolutePath(), Project.MSG_VERBOSE);
cpd.add(file);
}
return new BufferedWriter(new FileWriter(new File(outFile)));
}
}
private long analyzeCode(CPD cpd) {
long start = System.currentTimeMillis();
cpd.go();
long stop = System.currentTimeMillis();
return stop - start;
}
private Renderer createRenderer() {
if (format.equals(TEXT_FORMAT)) {
return new SimpleRenderer();
} else
return new XMLRenderer();
}
private void validateFields() throws BuildException{
@ -114,16 +124,19 @@ public class CPDTask extends Task {
this.minimumTokenCount = minimumTokenCount;
}
public void setOutputFile(String outputFile) {
public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
public void setFormat(FormatAttribute formatAttribute) {
format = formatAttribute.getValue();
}
private void printIfVerbose(String in) {
if (verbose)
System.out.println(in);
public static class FormatAttribute extends EnumeratedAttribute {
private String[] formats = new String[] {XML_FORMAT, TEXT_FORMAT};
public String[] getValues() {
return formats;
}
}
}

View File

@ -1,7 +1,7 @@
package net.sourceforge.pmd.cpd;
import java.io.FilenameFilter;
import java.io.File;
import java.io.FilenameFilter;
public class CPPLanguage implements Language{

View File

@ -1,16 +1,16 @@
package net.sourceforge.pmd.cpd;
import net.sourceforge.pmd.cpd.cppast.TokenMgrError;
import net.sourceforge.pmd.cpd.cppast.CPPParser;
import net.sourceforge.pmd.cpd.cppast.CPPParserTokenManager;
import net.sourceforge.pmd.cpd.cppast.Token;
import net.sourceforge.pmd.cpd.cppast.CPPParser;
import net.sourceforge.pmd.cpd.cppast.TokenMgrError;
import java.io.Reader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
public class CPPTokenizer implements Tokenizer {
protected String EOL = System.getProperty("line.separator", "\n");

View File

@ -0,0 +1,34 @@
package net.sourceforge.pmd.cpd;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @author Philippe T'Seyen
*/
public class FileReporter
{
private File reportFile;
public FileReporter(File reportFile) {
if (reportFile == null) throw new NullPointerException("reportFile can not be null");
this.reportFile = reportFile;
}
public void report(String content) throws ReportException {
try {
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(reportFile));
writer.write(content);
} finally {
if (writer != null) writer.close();
}
} catch (IOException ioe) {
throw new ReportException(ioe);
}
}
}

View File

@ -1,7 +1,7 @@
package net.sourceforge.pmd.cpd;
import java.io.FilenameFilter;
import java.io.File;
import java.io.FilenameFilter;
public class JavaLanguage implements Language {

View File

@ -0,0 +1,11 @@
package net.sourceforge.pmd.cpd;
/**
* @author Philippe T'Seyen
*/
public class ReportException extends Exception
{
public ReportException(Throwable cause) {
super(cause);
}
}

View File

@ -10,11 +10,11 @@
<section name="Credits">
<subsection name="Individuals">
<ul>
<li>Philippe T'Seyen - refactoring and cleanup of the CPD Ant task, an XML renderer (with unit tests!) for CPD</li>
<li>Michael Montuori - bug reports on the Gel IDE plugin</li>
<li>Michael Hosier - bug reports on the Gel IDE plugin</li>
<li>Ian Shef - bug reports on the Gel IDE plugin</li>
<li>Matthew Harrah - script bug report</li>
<li>Philippe T'Seyen - an XML renderer (with unit tests!) for CPD</li>
<li>Richard Jenson - CPD on Win32 troubleshooting</li>
<li>Daniel Bruguier - CPD on Win32 troubleshooting</li>
<li>Mario Claerhout - CPD optimizations and suggestions</li>