Renderers use less memory when generating reports.

The previous implementation built the entire report as a single String. Testing
all rules on the JDK generates a report larger than 100M and that created a
spike in memory usage at the very end.


git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4814 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Xavier Le Vourch
2006-11-19 01:54:09 +00:00
parent 22bca13115
commit 4bc641bf51
16 changed files with 175 additions and 92 deletions

View File

@ -42,6 +42,7 @@ Better 'create rule XML' panel in Designer.
use of entrySet to iterate over Maps. use of entrySet to iterate over Maps.
1.6 added as a valid option for targetjdk. 1.6 added as a valid option for targetjdk.
PMD now allows rules to use Type Resolution. This was referenced in patch 1257259. PMD now allows rules to use Type Resolution. This was referenced in patch 1257259.
Renderers use less memory when generating reports.
Performance Refactoring, XPath rules re-written as Java: Performance Refactoring, XPath rules re-written as Java:
AssignmentInOperand AssignmentInOperand
AvoidDollarSigns AvoidDollarSigns

View File

@ -17,6 +17,7 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
@ -274,7 +275,10 @@ public class PMD {
try { try {
Renderer r = opts.createRenderer(); Renderer r = opts.createRenderer();
System.out.println(r.render(ctx.getReport())); OutputStreamWriter w = new OutputStreamWriter(System.out);
r.render(w, ctx.getReport());
w.flush();
System.out.println();
} catch (Exception e) { } catch (Exception e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
System.out.println(opts.usage()); System.out.println(opts.usage());

View File

@ -127,8 +127,8 @@ public class Formatter {
} }
private void outputReportTo(Writer writer, Report report, boolean consoleRenderer) throws IOException { private void outputReportTo(Writer writer, Report report, boolean consoleRenderer) throws IOException {
String renderedReport = getRenderer(consoleRenderer).render(report) + PMD.EOL; getRenderer(consoleRenderer).render(writer, report);
writer.write(renderedReport, 0, renderedReport.length()); writer.write(PMD.EOL);
writer.close(); writer.close();
} }

View File

@ -1,5 +1,8 @@
package net.sourceforge.pmd.renderers; package net.sourceforge.pmd.renderers;
import java.io.IOException;
import java.io.StringWriter;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
public abstract class AbstractRenderer implements Renderer { public abstract class AbstractRenderer implements Renderer {
@ -10,5 +13,14 @@ public abstract class AbstractRenderer implements Renderer {
this.showSuppressedViolations = show; this.showSuppressedViolations = show;
} }
public abstract String render(Report report); public String render(Report report) {
StringWriter w = new StringWriter();
try {
render(w, report);
} catch (IOException e) {
throw new Error("StringWriter doesn't throw IOException", e);
}
return w.toString();
}
} }

View File

@ -8,11 +8,13 @@ import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.util.StringUtil; import net.sourceforge.pmd.util.StringUtil;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
public class CSVRenderer extends AbstractRenderer implements Renderer { public class CSVRenderer extends AbstractRenderer {
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer(300); StringBuffer buf = new StringBuffer(300);
quoteAndCommify(buf, "Problem"); quoteAndCommify(buf, "Problem");
quoteAndCommify(buf, "Package"); quoteAndCommify(buf, "Package");
@ -23,15 +25,16 @@ public class CSVRenderer extends AbstractRenderer implements Renderer {
quoteAndCommify(buf, "Rule set"); quoteAndCommify(buf, "Rule set");
quote(buf, "Rule"); quote(buf, "Rule");
buf.append(PMD.EOL); buf.append(PMD.EOL);
writer.write(buf.toString());
addViolations(report, buf); addViolations(writer, report, buf);
return buf.toString();
} }
private void addViolations(Report report, StringBuffer buf) { private void addViolations(Writer writer, Report report, StringBuffer buf) throws IOException {
int violationCount = 1; int violationCount = 1;
IRuleViolation rv; IRuleViolation rv;
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
buf.setLength(0);
rv = (IRuleViolation) i.next(); rv = (IRuleViolation) i.next();
quoteAndCommify(buf, Integer.toString(violationCount)); quoteAndCommify(buf, Integer.toString(violationCount));
quoteAndCommify(buf, rv.getPackageName()); quoteAndCommify(buf, rv.getPackageName());
@ -42,6 +45,7 @@ public class CSVRenderer extends AbstractRenderer implements Renderer {
quoteAndCommify(buf, rv.getRule().getRuleSetName()); quoteAndCommify(buf, rv.getRule().getRuleSetName());
quote(buf, rv.getRule().getName()); quote(buf, rv.getRule().getName());
buf.append(PMD.EOL); buf.append(PMD.EOL);
writer.write(buf.toString());
violationCount++; violationCount++;
} }
} }

View File

@ -6,20 +6,23 @@ package net.sourceforge.pmd.renderers;
import net.sourceforge.pmd.IRuleViolation; import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
public class EmacsRenderer extends AbstractRenderer implements Renderer { public class EmacsRenderer extends AbstractRenderer {
protected static final String EOL = System.getProperty("line.separator", "\n"); protected static final String EOL = System.getProperty("line.separator", "\n");
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
buf.setLength(0);
buf.append(EOL).append(rv.getFilename()); buf.append(EOL).append(rv.getFilename());
buf.append(':').append(Integer.toString(rv.getBeginLine())); buf.append(':').append(Integer.toString(rv.getBeginLine()));
buf.append(": ").append(rv.getDescription()); buf.append(": ").append(rv.getDescription());
writer.write(buf.toString());
} }
return buf.toString();
} }
} }

View File

@ -8,9 +8,11 @@ import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.util.StringUtil; import net.sourceforge.pmd.util.StringUtil;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
public class HTMLRenderer extends AbstractRenderer implements Renderer { public class HTMLRenderer extends AbstractRenderer {
private String linkPrefix; private String linkPrefix;
private String linePrefix; private String linePrefix;
@ -25,31 +27,30 @@ public class HTMLRenderer extends AbstractRenderer implements Renderer {
this(null, null); this(null, null);
} }
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer("<html><head><title>PMD</title></head><body>" + PMD.EOL); writer.write("<html><head><title>PMD</title></head><body>" + PMD.EOL);
buf.append(renderBody(report)); renderBody(writer, report);
buf.append("</body></html>"); writer.write("</body></html>");
return buf.toString();
} }
public String renderBody(Report report) { public void renderBody(Writer writer, Report report) throws IOException {
StringBuffer buf = glomIRuleViolations(report); glomIRuleViolations(writer, report);
glomProcessingErrors(report, buf); glomProcessingErrors(writer, report);
if (showSuppressedViolations) { if (showSuppressedViolations) {
glomSuppressions(report, buf); glomSuppressions(writer, report);
} }
return buf.toString();
} }
private StringBuffer glomIRuleViolations(Report report) { private void glomIRuleViolations(Writer writer, Report report) throws IOException {
boolean colorize = true; boolean colorize = true;
int violationCount = 1; int violationCount = 1;
StringBuffer buf = new StringBuffer(500); StringBuffer buf = new StringBuffer(500);
buf.append("<center><h3>PMD report</h3></center>"); writer.write("<center><h3>PMD report</h3></center>");
buf.append("<center><h3>Problems found</h3></center>"); writer.write("<center><h3>Problems found</h3></center>");
buf.append("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL); writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
buf.setLength(0);
buf.append("<tr"); buf.append("<tr");
if (colorize) { if (colorize) {
buf.append(" bgcolor=\"lightgrey\""); buf.append(" bgcolor=\"lightgrey\"");
@ -67,26 +68,28 @@ public class HTMLRenderer extends AbstractRenderer implements Renderer {
} }
buf.append("<td width=\"*\">" + d + "</td>" + PMD.EOL); buf.append("<td width=\"*\">" + d + "</td>" + PMD.EOL);
buf.append("</tr>" + PMD.EOL); buf.append("</tr>" + PMD.EOL);
writer.write(buf.toString());
violationCount++; violationCount++;
} }
if (violationCount > 0) { if (violationCount > 0) {
buf.append("</table>"); writer.write("</table>");
} }
return buf;
} }
private void glomProcessingErrors(Report report, StringBuffer buf) { private void glomProcessingErrors(Writer writer, Report report) throws IOException {
boolean colorize = true; boolean colorize = true;
int violationCount; int violationCount;
// errors // errors
if (report.errors().hasNext()) { if (report.errors().hasNext()) {
buf.append("<hr/>"); writer.write("<hr/>");
buf.append("<center><h3>Processing errors</h3></center>"); writer.write("<center><h3>Processing errors</h3></center>");
buf.append("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>File</th><th>Problem</th></tr>" + PMD.EOL); writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>File</th><th>Problem</th></tr>" + PMD.EOL);
} }
violationCount = 0; violationCount = 0;
StringBuffer buf = new StringBuffer(500);
for (Iterator i = report.errors(); i.hasNext();) { for (Iterator i = report.errors(); i.hasNext();) {
Report.ProcessingError pe = (Report.ProcessingError) i.next(); Report.ProcessingError pe = (Report.ProcessingError) i.next();
buf.setLength(0);
buf.append("<tr"); buf.append("<tr");
if (colorize) { if (colorize) {
buf.append(" bgcolor=\"lightgrey\""); buf.append(" bgcolor=\"lightgrey\"");
@ -96,24 +99,27 @@ public class HTMLRenderer extends AbstractRenderer implements Renderer {
buf.append("<td>" + pe.getFile() + "</td>" + PMD.EOL); buf.append("<td>" + pe.getFile() + "</td>" + PMD.EOL);
buf.append("<td>" + pe.getMsg() + "</td>" + PMD.EOL); buf.append("<td>" + pe.getMsg() + "</td>" + PMD.EOL);
buf.append("</tr>" + PMD.EOL); buf.append("</tr>" + PMD.EOL);
writer.write(buf.toString());
violationCount++; violationCount++;
} }
if (violationCount > 0) { if (violationCount > 0) {
buf.append("</table>"); writer.write("</table>");
} }
} }
private void glomSuppressions(Report report, StringBuffer buf) { private void glomSuppressions(Writer writer, Report report) throws IOException {
boolean colorize = true; boolean colorize = true;
boolean hasSuppressedViolations = !report.getSuppressedRuleViolations().isEmpty(); boolean hasSuppressedViolations = !report.getSuppressedRuleViolations().isEmpty();
if (hasSuppressedViolations) { if (hasSuppressedViolations) {
buf.append("<hr/>"); writer.write("<hr/>");
buf.append("<center><h3>Suppressed warnings</h3></center>"); writer.write("<center><h3>Suppressed warnings</h3></center>");
buf.append("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>File</th><th>Line</th><th>Rule</th><th>NOPMD or Annotation</th><th>Reason</th></tr>" + PMD.EOL); writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>File</th><th>Line</th><th>Rule</th><th>NOPMD or Annotation</th><th>Reason</th></tr>" + PMD.EOL);
} }
Report.SuppressedViolation sv; Report.SuppressedViolation sv;
StringBuffer buf = new StringBuffer(500);
for (Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext();) { for (Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext();) {
sv = (Report.SuppressedViolation) i.next(); sv = (Report.SuppressedViolation) i.next();
buf.setLength(0);
buf.append("<tr"); buf.append("<tr");
if (colorize) { if (colorize) {
buf.append(" bgcolor=\"lightgrey\""); buf.append(" bgcolor=\"lightgrey\"");
@ -126,9 +132,10 @@ public class HTMLRenderer extends AbstractRenderer implements Renderer {
buf.append("<td align=\"center\">" + (sv.suppressedByNOPMD() ? "NOPMD" : "Annotation") + "</td>" + PMD.EOL); buf.append("<td align=\"center\">" + (sv.suppressedByNOPMD() ? "NOPMD" : "Annotation") + "</td>" + PMD.EOL);
buf.append("<td align=\"center\">" + (sv.getUserMessage() == null ? "" : sv.getUserMessage()) + "</td>" + PMD.EOL); buf.append("<td align=\"center\">" + (sv.getUserMessage() == null ? "" : sv.getUserMessage()) + "</td>" + PMD.EOL);
buf.append("</tr>" + PMD.EOL); buf.append("</tr>" + PMD.EOL);
writer.write(buf.toString());
} }
if (hasSuppressedViolations) { if (hasSuppressedViolations) {
buf.append("</table>"); writer.write("</table>");
} }
} }

View File

@ -7,12 +7,14 @@ import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import java.io.IOException;
import java.io.Writer;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
public class IDEAJRenderer extends AbstractRenderer implements Renderer { public class IDEAJRenderer extends AbstractRenderer {
private static final String FILE_SEPARATOR = System.getProperty("file.separator"); private static final String FILE_SEPARATOR = System.getProperty("file.separator");
private static final String PATH_SEPARATOR = System.getProperty("path.separator"); private static final String PATH_SEPARATOR = System.getProperty("path.separator");
@ -44,38 +46,41 @@ public class IDEAJRenderer extends AbstractRenderer implements Renderer {
this.args = args; this.args = args;
} }
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
if (args[4].equals(".method")) { if (args[4].equals(".method")) {
// working on a directory tree // working on a directory tree
String sourcePath = args[3]; String sourcePath = args[3];
return render(report, sourcePath); render(writer, report, sourcePath);
return;
} }
// working on one file // working on one file
String classAndMethodName = args[4]; String classAndMethodName = args[4];
String singleFileName = args[5]; String singleFileName = args[5];
return render(report, classAndMethodName, singleFileName); render(writer, report, classAndMethodName, singleFileName);
} }
private String render(Report report, String sourcePathString) { private void render(Writer writer, Report report, String sourcePathString) throws IOException {
SourcePath sourcePath = new SourcePath(sourcePathString); SourcePath sourcePath = new SourcePath(sourcePathString);
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
buf.setLength(0);
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
buf.append(rv.getDescription() + PMD.EOL); buf.append(rv.getDescription() + PMD.EOL);
buf.append(" at ").append(getFullyQualifiedClassName(rv.getFilename(), sourcePath)).append(".method("); buf.append(" at ").append(getFullyQualifiedClassName(rv.getFilename(), sourcePath)).append(".method(");
buf.append(getSimpleFileName(rv.getFilename())).append(':').append(rv.getBeginLine()).append(')').append(PMD.EOL); buf.append(getSimpleFileName(rv.getFilename())).append(':').append(rv.getBeginLine()).append(')').append(PMD.EOL);
writer.write(buf.toString());
} }
return buf.toString();
} }
private String render(Report report, String classAndMethod, String file) { private void render(Writer writer, Report report, String classAndMethod, String file) throws IOException {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
buf.setLength(0);
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
buf.append(rv.getDescription()).append(PMD.EOL); buf.append(rv.getDescription()).append(PMD.EOL);
buf.append(" at ").append(classAndMethod).append('(').append(file).append(':').append(rv.getBeginLine()).append(')').append(PMD.EOL); buf.append(" at ").append(classAndMethod).append('(').append(file).append(':').append(rv.getBeginLine()).append(')').append(PMD.EOL);
writer.write(buf.toString());
} }
return buf.toString();
} }
private String getFullyQualifiedClassName(String in, SourcePath sourcePath) { private String getFullyQualifiedClassName(String in, SourcePath sourcePath) {

View File

@ -11,6 +11,7 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -44,7 +45,7 @@ import java.util.Map;
* colorization is atm only supported under *nix terminals accepting ansi escape * colorization is atm only supported under *nix terminals accepting ansi escape
* sequences, such as xterm, rxvt et cetera.</p> * sequences, such as xterm, rxvt et cetera.</p>
*/ */
public class PapariTextRenderer extends AbstractRenderer implements Renderer { public class PapariTextRenderer extends AbstractRenderer {
/** /**
* Directory from where java was invoked. * Directory from where java was invoked.
*/ */
@ -78,7 +79,7 @@ public class PapariTextRenderer extends AbstractRenderer implements Renderer {
} }
} }
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer(PMD.EOL); StringBuffer buf = new StringBuffer(PMD.EOL);
initializeColorsIfSupported(); initializeColorsIfSupported();
String lastFile = null; String lastFile = null;
@ -86,6 +87,7 @@ public class PapariTextRenderer extends AbstractRenderer implements Renderer {
int numberOfWarnings = 0; int numberOfWarnings = 0;
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
buf.setLength(0);
numberOfWarnings++; numberOfWarnings++;
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
if (!rv.getFilename().equals(lastFile)) { if (!rv.getFilename().equals(lastFile)) {
@ -96,17 +98,21 @@ public class PapariTextRenderer extends AbstractRenderer implements Renderer {
buf.append(this.green + " rule: " + this.colorReset + rv.getRule().getName() + PMD.EOL); buf.append(this.green + " rule: " + this.colorReset + rv.getRule().getName() + PMD.EOL);
buf.append(this.green + " msg: " + this.colorReset + rv.getDescription() + PMD.EOL); buf.append(this.green + " msg: " + this.colorReset + rv.getDescription() + PMD.EOL);
buf.append(this.green + " code: " + this.colorReset + this.getLine(lastFile, rv.getBeginLine()) + PMD.EOL + PMD.EOL); buf.append(this.green + " code: " + this.colorReset + this.getLine(lastFile, rv.getBeginLine()) + PMD.EOL + PMD.EOL);
writer.write(buf.toString());
} }
buf.append(PMD.EOL + PMD.EOL); writer.write(PMD.EOL + PMD.EOL);
buf.append("Summary:" + PMD.EOL + PMD.EOL); writer.write("Summary:" + PMD.EOL + PMD.EOL);
Map summary = report.getCountSummary(); Map summary = report.getCountSummary();
for (Iterator i = summary.entrySet().iterator(); i.hasNext();) { for (Iterator i = summary.entrySet().iterator(); i.hasNext();) {
buf.setLength(0);
Map.Entry entry = (Map.Entry) i.next(); Map.Entry entry = (Map.Entry) i.next();
String key = (String) entry.getKey(); String key = (String) entry.getKey();
buf.append(key + " : " + ((Integer) entry.getValue()).intValue() + PMD.EOL); buf.append(key + " : " + ((Integer) entry.getValue()).intValue() + PMD.EOL);
writer.write(buf.toString());
} }
for (Iterator i = report.errors(); i.hasNext();) { for (Iterator i = report.errors(); i.hasNext();) {
buf.setLength(0);
numberOfErrors++; numberOfErrors++;
Report.ProcessingError error = (Report.ProcessingError) i.next(); Report.ProcessingError error = (Report.ProcessingError) i.next();
if (error.getFile().equals(lastFile)) { if (error.getFile().equals(lastFile)) {
@ -114,15 +120,14 @@ public class PapariTextRenderer extends AbstractRenderer implements Renderer {
buf.append(this.redBold + "*" + this.colorReset + " file: " + this.whiteBold + this.getRelativePath(lastFile) + this.colorReset + PMD.EOL); buf.append(this.redBold + "*" + this.colorReset + " file: " + this.whiteBold + this.getRelativePath(lastFile) + this.colorReset + PMD.EOL);
} }
buf.append(this.green + " err: " + this.cyan + error.getMsg() + this.colorReset + PMD.EOL + PMD.EOL); buf.append(this.green + " err: " + this.cyan + error.getMsg() + this.colorReset + PMD.EOL + PMD.EOL);
writer.write(buf.toString());
} }
// adding error message count, if any // adding error message count, if any
if (numberOfErrors > 0) { if (numberOfErrors > 0) {
buf.append(this.redBold + "*" + this.colorReset + " errors: " + this.whiteBold + numberOfWarnings + this.colorReset + PMD.EOL); writer.write(this.redBold + "*" + this.colorReset + " errors: " + this.whiteBold + numberOfWarnings + this.colorReset + PMD.EOL);
} }
buf.append(this.yellowBold + "*" + this.colorReset + " warnings: " + this.whiteBold + numberOfWarnings + this.colorReset + PMD.EOL); writer.write(this.yellowBold + "*" + this.colorReset + " warnings: " + this.whiteBold + numberOfWarnings + this.colorReset + PMD.EOL);
return buf.toString();
} }
/** /**

View File

@ -3,10 +3,23 @@
*/ */
package net.sourceforge.pmd.renderers; package net.sourceforge.pmd.renderers;
import java.io.IOException;
import java.io.Writer;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
public interface Renderer { public interface Renderer {
void showSuppressedViolations(boolean show); void showSuppressedViolations(boolean show);
/**
*
* @deprecated This method consumes too much memory.
* Use the render method with the Writer argument instead.
*
*/
String render(Report report); String render(Report report);
void render(Writer writer, Report report) throws IOException;
} }

View File

@ -3,10 +3,12 @@ package net.sourceforge.pmd.renderers;
import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
public class SummaryHTMLRenderer extends AbstractRenderer implements Renderer { public class SummaryHTMLRenderer extends AbstractRenderer {
private String linePrefix,linkPrefix; private String linePrefix,linkPrefix;
public SummaryHTMLRenderer(String linkPrefix, String linePrefix) { public SummaryHTMLRenderer(String linkPrefix, String linePrefix) {
this.linePrefix = linePrefix; this.linePrefix = linePrefix;
@ -17,32 +19,33 @@ public class SummaryHTMLRenderer extends AbstractRenderer implements Renderer {
this(null,null); this(null,null);
} }
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer("<html><head><title>PMD</title></head><body>" + PMD.EOL); writer.write("<html><head><title>PMD</title></head><body>" + PMD.EOL);
buf.append(renderSummary(report)); renderSummary(writer, report);
buf.append("<h2><center>Detail</h2></center>"); writer.write("<h2><center>Detail</h2></center>");
buf.append("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL); writer.write("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>" + PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL);
buf.append(new HTMLRenderer(linkPrefix,linePrefix).renderBody(report)); new HTMLRenderer(linkPrefix,linePrefix).renderBody(writer, report);
buf.append("</table></body></html>"); writer.write("</table></body></html>");
return buf.toString();
} }
public String renderSummary(Report report) { public void renderSummary(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
buf.append("<h2><center>Summary</h2></center>"); buf.append("<h2><center>Summary</h2></center>");
buf.append("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\">"); buf.append("<table align=\"center\" cellspacing=\"0\" cellpadding=\"3\">");
buf.append("<th>Rule name</th>"); buf.append("<th>Rule name</th>");
buf.append("<th>Number of violations</th>"); buf.append("<th>Number of violations</th>");
writer.write(buf.toString());
Map summary = report.getSummary(); Map summary = report.getSummary();
for (Iterator i = summary.entrySet().iterator(); i.hasNext();) { for (Iterator i = summary.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next(); Map.Entry entry = (Map.Entry) i.next();
String ruleName = (String) entry.getKey(); String ruleName = (String) entry.getKey();
buf.setLength(0);
buf.append("<tr>"); buf.append("<tr>");
buf.append("<td>" + ruleName + "</td>"); buf.append("<td>" + ruleName + "</td>");
buf.append("<td align=center>" + ((Integer) entry.getValue()).intValue() + "</td>"); buf.append("<td align=center>" + ((Integer) entry.getValue()).intValue() + "</td>");
buf.append("</tr>"); buf.append("</tr>");
writer.write(buf.toString());
} }
buf.append("</table>"); writer.write("</table>");
return buf.toString();
} }
} }

View File

@ -7,6 +7,8 @@ import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
/** /**
@ -24,8 +26,8 @@ import java.util.Iterator;
* *
* @author Jeff Epstein, based upon <a href="EmacsRenderer.html">EmacsRenderer</a>, Tuesday, September 23, 2003 * @author Jeff Epstein, based upon <a href="EmacsRenderer.html">EmacsRenderer</a>, Tuesday, September 23, 2003
*/ */
public class TextPadRenderer extends AbstractRenderer implements Renderer { public class TextPadRenderer extends AbstractRenderer {
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
Iterator i; Iterator i;
try { try {
@ -35,6 +37,7 @@ public class TextPadRenderer extends AbstractRenderer implements Renderer {
} }
while (i.hasNext()) { while (i.hasNext()) {
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
buf.setLength(0);
//Filename //Filename
buf.append(PMD.EOL).append(rv.getFilename() + "("); buf.append(PMD.EOL).append(rv.getFilename() + "(");
//Line number //Line number
@ -43,7 +46,7 @@ public class TextPadRenderer extends AbstractRenderer implements Renderer {
buf.append(rv.getRule().getName()).append("): "); buf.append(rv.getRule().getName()).append("): ");
//Specific violation message //Specific violation message
buf.append(rv.getDescription()); buf.append(rv.getDescription());
writer.write(buf.toString());
} }
return buf.toString();
} }
} }

View File

@ -7,11 +7,13 @@ import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
public class TextRenderer extends AbstractRenderer implements Renderer { public class TextRenderer extends AbstractRenderer {
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
if (report.isEmpty()) { if (report.isEmpty()) {
@ -19,28 +21,33 @@ public class TextRenderer extends AbstractRenderer implements Renderer {
if (showSuppressedViolations) { if (showSuppressedViolations) {
addSuppressed(report, buf); addSuppressed(report, buf);
} }
return buf.toString(); writer.write(buf.toString());
return;
} }
Iterator i; Iterator i;
for (i = report.iterator(); i.hasNext();) { for (i = report.iterator(); i.hasNext();) {
buf.setLength(0);
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
buf.append(PMD.EOL).append(rv.getFilename()); buf.append(PMD.EOL).append(rv.getFilename());
buf.append(':').append(Integer.toString(rv.getBeginLine())); buf.append(':').append(Integer.toString(rv.getBeginLine()));
buf.append('\t').append(rv.getDescription()); buf.append('\t').append(rv.getDescription());
writer.write(buf.toString());
} }
for (i = report.errors(); i.hasNext();) { for (i = report.errors(); i.hasNext();) {
buf.setLength(0);
Report.ProcessingError error = (Report.ProcessingError) i.next(); Report.ProcessingError error = (Report.ProcessingError) i.next();
buf.append(PMD.EOL).append(error.getFile()); buf.append(PMD.EOL).append(error.getFile());
buf.append("\t-\t").append(error.getMsg()); buf.append("\t-\t").append(error.getMsg());
writer.write(buf.toString());
} }
if (showSuppressedViolations) { if (showSuppressedViolations) {
buf.setLength(0);
addSuppressed(report, buf); addSuppressed(report, buf);
writer.write(buf.toString());
} }
return buf.toString();
} }
private void addSuppressed(Report report, StringBuffer buf) { private void addSuppressed(Report report, StringBuffer buf) {

View File

@ -7,17 +7,19 @@ import net.sourceforge.pmd.IRuleViolation;
import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator; import java.util.Iterator;
/** /**
* @author Vladimir * @author Vladimir
* @version $Revision$ $Date$ * @version $Revision$ $Date$
*/ */
public class VBHTMLRenderer extends AbstractRenderer implements Renderer { public class VBHTMLRenderer extends AbstractRenderer {
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
if (report.isEmpty()) { if (report.isEmpty()) {
return ""; return;
} }
StringBuffer sb = new StringBuffer(header()); StringBuffer sb = new StringBuffer(header());
@ -27,6 +29,7 @@ public class VBHTMLRenderer extends AbstractRenderer implements Renderer {
boolean colorize = false; boolean colorize = false;
for (Iterator iter = report.iterator(); iter.hasNext();) { for (Iterator iter = report.iterator(); iter.hasNext();) {
sb.setLength(0);
IRuleViolation rv = (IRuleViolation) iter.next(); IRuleViolation rv = (IRuleViolation) iter.next();
if (!rv.getFilename().equals(filename)) { // New File if (!rv.getFilename().equals(filename)) { // New File
if (filename != null) { if (filename != null) {
@ -50,15 +53,17 @@ public class VBHTMLRenderer extends AbstractRenderer implements Renderer {
sb.append("<td><font class=body>" + rv.getDescription() + "</font></td>"); sb.append("<td><font class=body>" + rv.getDescription() + "</font></td>");
sb.append("</tr>"); sb.append("</tr>");
sb.append(lineSep); sb.append(lineSep);
writer.write(sb.toString());
} }
if (filename != null) { if (filename != null) {
sb.append("</table>"); writer.write("</table>");
} }
sb.append("<br>"); writer.write("<br>");
// output the problems // output the problems
Iterator iter = report.errors(); Iterator iter = report.errors();
if (iter.hasNext()) { if (iter.hasNext()) {
sb.setLength(0);
sb.append("<table border=\"0\" width=\"80%\">"); sb.append("<table border=\"0\" width=\"80%\">");
sb.append("<tr id=TableHeader><td><font class=title>&nbsp;Problems found</font></td></tr>"); sb.append("<tr id=TableHeader><td><font class=title>&nbsp;Problems found</font></td></tr>");
colorize = false; colorize = false;
@ -72,11 +77,10 @@ public class VBHTMLRenderer extends AbstractRenderer implements Renderer {
sb.append("<td><font class=body>").append(iter.next()).append("\"</font></td></tr>"); sb.append("<td><font class=body>").append(iter.next()).append("\"</font></td></tr>");
} }
sb.append("</table>"); sb.append("</table>");
writer.write(sb.toString());
} }
sb.append(footer()); writer.write(footer());
return sb.toString();
} }
private String header() { private String header() {

View File

@ -8,19 +8,23 @@ import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.util.StringUtil; import net.sourceforge.pmd.util.StringUtil;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
public class XMLRenderer extends AbstractRenderer implements Renderer { public class XMLRenderer extends AbstractRenderer {
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
StringBuffer buf = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + PMD.EOL + createVersionAttr() + createTimestampAttr() + createTimeElapsedAttr(report) + '>' + PMD.EOL); StringBuffer buf = new StringBuffer();
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + PMD.EOL + createVersionAttr() + createTimestampAttr() + createTimeElapsedAttr(report) + '>' + PMD.EOL);
String filename = null; String filename = null;
// rule violations // rule violations
for (Iterator i = report.iterator(); i.hasNext();) { for (Iterator i = report.iterator(); i.hasNext();) {
buf.setLength(0);
IRuleViolation rv = (IRuleViolation) i.next(); IRuleViolation rv = (IRuleViolation) i.next();
if (!rv.getFilename().equals(filename)) { // New File if (!rv.getFilename().equals(filename)) { // New File
if (filename != null) {// Not first file ? if (filename != null) {// Not first file ?
@ -50,24 +54,29 @@ public class XMLRenderer extends AbstractRenderer implements Renderer {
buf.append(PMD.EOL); buf.append(PMD.EOL);
buf.append("</violation>"); buf.append("</violation>");
buf.append(PMD.EOL); buf.append(PMD.EOL);
writer.write(buf.toString());
} }
if (filename != null) { // Not first file ? if (filename != null) { // Not first file ?
buf.append("</file>").append(PMD.EOL); writer.write("</file>");
writer.write(PMD.EOL);
} }
// errors // errors
for (Iterator i = report.errors(); i.hasNext();) { for (Iterator i = report.errors(); i.hasNext();) {
buf.setLength(0);
Report.ProcessingError pe = (Report.ProcessingError) i.next(); Report.ProcessingError pe = (Report.ProcessingError) i.next();
buf.append("<error ").append("filename=\""); buf.append("<error ").append("filename=\"");
StringUtil.appendXmlEscaped(buf, pe.getFile()); StringUtil.appendXmlEscaped(buf, pe.getFile());
buf.append("\" msg=\""); buf.append("\" msg=\"");
StringUtil.appendXmlEscaped(buf, pe.getMsg()); StringUtil.appendXmlEscaped(buf, pe.getMsg());
buf.append("\"/>").append(PMD.EOL); buf.append("\"/>").append(PMD.EOL);
writer.write(buf.toString());
} }
// suppressed violations // suppressed violations
if (showSuppressedViolations) { if (showSuppressedViolations) {
for (Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext();) { for (Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext();) {
buf.setLength(0);
Report.SuppressedViolation suppressed = (Report.SuppressedViolation) i.next(); Report.SuppressedViolation suppressed = (Report.SuppressedViolation) i.next();
buf.append("<suppressedviolation ").append("filename=\""); buf.append("<suppressedviolation ").append("filename=\"");
StringUtil.appendXmlEscaped(buf, suppressed.getRuleViolation().getFilename()); StringUtil.appendXmlEscaped(buf, suppressed.getRuleViolation().getFilename());
@ -78,11 +87,11 @@ public class XMLRenderer extends AbstractRenderer implements Renderer {
buf.append("\" usermsg=\""); buf.append("\" usermsg=\"");
StringUtil.appendXmlEscaped(buf, suppressed.getUserMessage()); StringUtil.appendXmlEscaped(buf, suppressed.getUserMessage());
buf.append("\"/>").append(PMD.EOL); buf.append("\"/>").append(PMD.EOL);
writer.write(buf.toString());
} }
} }
buf.append("</pmd>"); writer.write("</pmd>");
return buf.toString();
} }
private void maybeAdd(String attr, String value, StringBuffer buf) { private void maybeAdd(String attr, String value, StringBuffer buf) {

View File

@ -1,15 +1,18 @@
package net.sourceforge.pmd.renderers; package net.sourceforge.pmd.renderers;
import java.io.IOException;
import java.io.Writer;
import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.dfa.report.ReportHTMLPrintVisitor; import net.sourceforge.pmd.dfa.report.ReportHTMLPrintVisitor;
import net.sourceforge.pmd.dfa.report.ReportTree; import net.sourceforge.pmd.dfa.report.ReportTree;
public class YAHTMLRenderer extends AbstractRenderer implements Renderer { public class YAHTMLRenderer extends AbstractRenderer {
public String render(Report report) { public void render(Writer writer, Report report) throws IOException {
ReportTree tree = report.getViolationTree(); ReportTree tree = report.getViolationTree();
tree.getRootNode().accept(new ReportHTMLPrintVisitor()); tree.getRootNode().accept(new ReportHTMLPrintVisitor());
return "<h3 align=\"center\">The HTML files are created above the project directory.</h3>"; writer.write("<h3 align=\"center\">The HTML files are created above the project directory.</h3>");
} }
} }