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:
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
|
||||
|
@ -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");
|
||||
|
34
pmd/src/net/sourceforge/pmd/cpd/FileReporter.java
Normal file
34
pmd/src/net/sourceforge/pmd/cpd/FileReporter.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
|
11
pmd/src/net/sourceforge/pmd/cpd/ReportException.java
Normal file
11
pmd/src/net/sourceforge/pmd/cpd/ReportException.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
Reference in New Issue
Block a user