Merge branch 'pr-2414'

[core] Fix HTMLRenderer not using linkPrefix/linePrefix #2414
This commit is contained in:
Andreas Dangel
2020-04-23 11:13:35 +02:00
7 changed files with 116 additions and 18 deletions

View File

@ -82,8 +82,11 @@ Example:
HTML format.
This renderer provides two properties. If these are provided, then a link to the source where the violations
have been found is rendered. The following example has been created with `-property linkPrefix=https://github.com/pmd/pmd/blob/master/ -property linePrefix=L -shortnames -d pmd`.
This renderer provides two properties to render a link to the source where the violations
have been found. The following example has been created with `-property linkPrefix=https://github.com/pmd/pmd/blob/master/ -property linePrefix=L -shortnames -d pmd`.
If "linkPrefix" is not set, then "linePrefix" has no effect anyway: just the filename will
be rendered, with no html link. Otherwise if "linePrefix" is not set, then the link will
not contain a line number.
When using [Maven JXR Plugin](https://maven.apache.org/jxr/maven-jxr-plugin/index.html) to generate a html view
of the project's sources, then the property "htmlExtension" needs to be set to "true". This will then replace the

View File

@ -77,6 +77,7 @@ See [the documentation and example](https://pmd.github.io/latest/pmd_userdocs_re
* doc
* [#2355](https://github.com/pmd/pmd/issues/2355): \[doc] Improve documentation about incremental analysis
* [#2356](https://github.com/pmd/pmd/issues/2356): \[doc] Add missing doc about pmd.github.io
* [#2412](https://github.com/pmd/pmd/issues/2412): \[core] HTMLRenderer doesn't render links to source files
* [#2413](https://github.com/pmd/pmd/issues/2413): \[doc] Improve documentation about the available renderers (PMD/CPD)
* java
* [#2378](https://github.com/pmd/pmd/issues/2378): \[java] AbstractJUnitRule has bad performance on large code bases

View File

@ -15,7 +15,10 @@ import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Report.ConfigurationError;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.properties.PropertyDescriptor;
import net.sourceforge.pmd.properties.PropertyFactory;
import net.sourceforge.pmd.properties.StringProperty;
/**
@ -32,9 +35,15 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
public static final StringProperty LINE_PREFIX = new StringProperty("linePrefix",
"Prefix for line number anchor in the source file.", null, 1);
public static final StringProperty LINK_PREFIX = new StringProperty("linkPrefix", "Path to HTML source.", null, 0);
public static final PropertyDescriptor<Boolean> HTML_EXTENSION = PropertyFactory.booleanProperty("htmlExtension")
.desc("Replace file extension with .html for the links (default: false)")
// default value is false - to have the old (pre 6.23.0) behavior, this needs to be set to true.
.defaultValue(false)
.build();
private String linkPrefix;
private String linePrefix;
private boolean replaceHtmlExtension;
private int violationCount = 1;
boolean colorize = true;
@ -44,6 +53,7 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
definePropertyDescriptor(LINK_PREFIX);
definePropertyDescriptor(LINE_PREFIX);
definePropertyDescriptor(HTML_EXTENSION);
}
@Override
@ -61,6 +71,7 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
public void renderBody(Writer writer, Report report) throws IOException {
linkPrefix = getProperty(LINK_PREFIX);
linePrefix = getProperty(LINE_PREFIX);
replaceHtmlExtension = getProperty(HTML_EXTENSION);
writer.write("<center><h3>PMD report</h3></center>");
writer.write("<center><h3>Problems found</h3></center>");
@ -78,6 +89,10 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
@Override
public void start() throws IOException {
linkPrefix = getProperty(LINK_PREFIX);
linePrefix = getProperty(LINE_PREFIX);
replaceHtmlExtension = getProperty(HTML_EXTENSION);
writer.write("<html><head><title>PMD</title></head><body>" + PMD.EOL);
writer.write("<center><h3>PMD report</h3></center>");
writer.write("<center><h3>Problems found</h3></center>");
@ -116,8 +131,7 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
buf.append("> " + PMD.EOL);
buf.append("<td align=\"center\">" + violationCount + "</td>" + PMD.EOL);
buf.append("<td width=\"*%\">"
+ maybeWrap(StringEscapeUtils.escapeHtml4(determineFileName(rv.getFilename())),
linePrefix == null ? "" : linePrefix + Integer.toString(rv.getBeginLine()))
+ renderFileName(rv.getFilename(), rv.getBeginLine())
+ "</td>" + PMD.EOL);
buf.append("<td align=\"center\" width=\"5%\">" + Integer.toString(rv.getBeginLine()) + "</td>" + PMD.EOL);
@ -134,6 +148,20 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
}
}
private String renderFileName(String filename, int beginLine) {
return maybeWrap(StringEscapeUtils.escapeHtml4(determineFileName(filename)),
linePrefix == null || beginLine < 0 ? "" : linePrefix + beginLine);
}
private String renderRuleName(Rule rule) {
String name = rule.getName();
String infoUrl = rule.getExternalInfoUrl();
if (StringUtils.isNotBlank(infoUrl)) {
return "<a href=\"" + infoUrl + "\">" + name + "</a>";
}
return name;
}
private void glomProcessingErrors(Writer writer, List<Report.ProcessingError> errors) throws IOException {
if (errors.isEmpty()) {
@ -155,7 +183,7 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
}
colorize = !colorize;
buf.append("> " + PMD.EOL);
buf.append("<td>" + determineFileName(pe.getFile()) + "</td>" + PMD.EOL);
buf.append("<td>" + renderFileName(pe.getFile(), -1) + "</td>" + PMD.EOL);
buf.append("<td><pre>" + pe.getDetail() + "</pre></td>" + PMD.EOL);
buf.append("</tr>" + PMD.EOL);
writer.write(buf.toString());
@ -183,9 +211,10 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
}
colorize = !colorize;
buf.append("> " + PMD.EOL);
buf.append("<td align=\"left\">" + determineFileName(sv.getRuleViolation().getFilename()) + "</td>" + PMD.EOL);
buf.append("<td align=\"center\">" + sv.getRuleViolation().getBeginLine() + "</td>" + PMD.EOL);
buf.append("<td align=\"center\">" + sv.getRuleViolation().getRule().getName() + "</td>" + PMD.EOL);
RuleViolation rv = sv.getRuleViolation();
buf.append("<td align=\"left\">" + renderFileName(rv.getFilename(), rv.getBeginLine()) + "</td>" + PMD.EOL);
buf.append("<td align=\"center\">" + rv.getBeginLine() + "</td>" + PMD.EOL);
buf.append("<td align=\"center\">" + renderRuleName(rv.getRule()) + "</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);
@ -215,7 +244,7 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
}
colorize = !colorize;
buf.append("> " + PMD.EOL);
buf.append("<td>" + ce.rule().getName() + "</td>" + PMD.EOL);
buf.append("<td>" + renderRuleName(ce.rule()) + "</td>" + PMD.EOL);
buf.append("<td>" + ce.issue() + "</td>" + PMD.EOL);
buf.append("</tr>" + PMD.EOL);
writer.write(buf.toString());
@ -227,11 +256,16 @@ public class HTMLRenderer extends AbstractIncrementingRenderer {
if (StringUtils.isBlank(linkPrefix)) {
return filename;
}
String newFileName = filename;
int index = filename.lastIndexOf('.');
if (index >= 0) {
newFileName = filename.substring(0, index).replace('\\', '/');
String newFileName = filename.replace('\\', '/');
if (replaceHtmlExtension) {
int index = filename.lastIndexOf('.');
if (index >= 0) {
newFileName = filename.substring(0, index);
}
}
return "<a href=\"" + linkPrefix + newFileName + ".html#" + line + "\">" + newFileName + "</a>";
return "<a href=\"" + linkPrefix + newFileName + (replaceHtmlExtension ? ".html#" : "#") + line + "\">"
+ newFileName + "</a>";
}
}

View File

@ -24,6 +24,7 @@ public class SummaryHTMLRenderer extends AbstractAccumulatingRenderer {
// Renderer
definePropertyDescriptor(HTMLRenderer.LINK_PREFIX);
definePropertyDescriptor(HTMLRenderer.LINE_PREFIX);
definePropertyDescriptor(HTMLRenderer.HTML_EXTENSION);
}
@Override
@ -41,6 +42,7 @@ public class SummaryHTMLRenderer extends AbstractAccumulatingRenderer {
HTMLRenderer htmlRenderer = new HTMLRenderer();
htmlRenderer.setProperty(HTMLRenderer.LINK_PREFIX, getProperty(HTMLRenderer.LINK_PREFIX));
htmlRenderer.setProperty(HTMLRenderer.LINE_PREFIX, getProperty(HTMLRenderer.LINE_PREFIX));
htmlRenderer.setProperty(HTMLRenderer.HTML_EXTENSION, getProperty(HTMLRenderer.HTML_EXTENSION));
htmlRenderer.setShowSuppressedViolations(showSuppressedViolations);
htmlRenderer.setUseShortNames(inputPathPrefixes);
htmlRenderer.renderBody(writer, report);

View File

@ -61,7 +61,7 @@ public abstract class AbstractRendererTest {
getRenderer().renderFileReport(null);
}
private Report reportOneViolation() {
protected Report reportOneViolation() {
Report report = new Report();
report.addRuleViolation(newRuleViolation(1));
return report;

View File

@ -4,9 +4,17 @@
package net.sourceforge.pmd.renderers;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.junit.Test;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Report.ConfigurationError;
import net.sourceforge.pmd.Report.ProcessingError;
import net.sourceforge.pmd.ReportTest;
public class HTMLRendererTest extends AbstractRendererTest {
@ -26,9 +34,18 @@ public class HTMLRendererTest extends AbstractRendererTest {
@Override
public String getExpected() {
return getExpected(null, null);
}
private String getExpected(String linkPrefix, String lineAnchor) {
String filename = getEscapedFilename();
if (linkPrefix != null) {
filename = "<a href=\"" + linkPrefix + filename + "#" + lineAnchor + "\">"
+ filename + "</a>";
}
return getHeader()
+ "<tr bgcolor=\"lightgrey\"> " + PMD.EOL + "<td align=\"center\">1</td>" + PMD.EOL
+ "<td width=\"*%\">" + getEscapedFilename() + "</td>" + PMD.EOL + "<td align=\"center\" width=\"5%\">1</td>" + PMD.EOL
+ "<td width=\"*%\">" + filename + "</td>" + PMD.EOL + "<td align=\"center\" width=\"5%\">1</td>" + PMD.EOL
+ "<td width=\"*\">blah</td>" + PMD.EOL + "</tr>" + PMD.EOL + "</table></body></html>" + PMD.EOL;
}
@ -72,4 +89,44 @@ public class HTMLRendererTest extends AbstractRendererTest {
+ "<center><h3>PMD report</h3></center><center><h3>Problems found</h3></center><table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>"
+ PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL;
}
@Test
public void testLinkPrefix() throws IOException {
final HTMLRenderer renderer = new HTMLRenderer();
final String linkPrefix = "https://github.com/pmd/pmd/blob/master/";
final String linePrefix = "L";
renderer.setProperty(HTMLRenderer.LINK_PREFIX, linkPrefix);
renderer.setProperty(HTMLRenderer.LINE_PREFIX, linePrefix);
renderer.setProperty(HTMLRenderer.HTML_EXTENSION, false);
Report rep = reportOneViolation();
String actual = ReportTest.render(renderer, rep);
assertEquals(filter(getExpected(linkPrefix, "L1")), filter(actual));
}
@Test
public void testLinePrefixNotSet() throws IOException {
final HTMLRenderer renderer = new HTMLRenderer();
final String linkPrefix = "https://github.com/pmd/pmd/blob/master/";
renderer.setProperty(HTMLRenderer.LINK_PREFIX, linkPrefix);
// dont set line prefix renderer.setProperty(HTMLRenderer.LINE_PREFIX, linePrefix);
renderer.setProperty(HTMLRenderer.HTML_EXTENSION, false);
Report rep = reportOneViolation();
String actual = ReportTest.render(renderer, rep);
assertEquals(filter(getExpected(linkPrefix, "")), filter(actual));
}
@Test
public void testEmptyLinePrefix() throws IOException {
final HTMLRenderer renderer = new HTMLRenderer();
final String linkPrefix = "https://github.com/pmd/pmd/blob/master/";
renderer.setProperty(HTMLRenderer.LINK_PREFIX, linkPrefix);
renderer.setProperty(HTMLRenderer.LINE_PREFIX, "");
renderer.setProperty(HTMLRenderer.HTML_EXTENSION, false);
Report rep = reportOneViolation();
String actual = ReportTest.render(renderer, rep);
assertEquals(filter(getExpected(linkPrefix, "1")), filter(actual));
}
}

View File

@ -28,6 +28,7 @@ public class SummaryHTMLRendererTest extends AbstractRendererTest {
Renderer result = new SummaryHTMLRenderer();
result.setProperty(HTMLRenderer.LINK_PREFIX, "link_prefix");
result.setProperty(HTMLRenderer.LINE_PREFIX, "line_prefix");
result.setProperty(HTMLRenderer.HTML_EXTENSION, true);
return result;
}
@ -95,7 +96,7 @@ public class SummaryHTMLRendererTest extends AbstractRendererTest {
+ PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL
+ "</table><hr/><center><h3>Processing errors</h3></center><table align=\"center\" cellspacing=\"0\" cellpadding=\"3\"><tr>"
+ PMD.EOL + "<th>File</th><th>Problem</th></tr>" + PMD.EOL + "<tr bgcolor=\"lightgrey\"> " + PMD.EOL
+ "<td>file</td>" + PMD.EOL + "<td><pre>" + error.getDetail() + "</pre></td>" + PMD.EOL + "</tr>" + PMD.EOL
+ "<td><a href=\"link_prefixfile.html#\">file</a></td>" + PMD.EOL + "<td><pre>" + error.getDetail() + "</pre></td>" + PMD.EOL + "</tr>" + PMD.EOL
+ "</table></tr></table></body></html>" + PMD.EOL;
}
@ -129,7 +130,7 @@ public class SummaryHTMLRendererTest extends AbstractRendererTest {
+ PMD.EOL + "<th>#</th><th>File</th><th>Line</th><th>Problem</th></tr>" + PMD.EOL
+ "</table><hr/><center><h3>Suppressed warnings</h3></center><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 + "<tr bgcolor=\"lightgrey\"> " + PMD.EOL + "<td align=\"left\"></td>" + PMD.EOL
+ PMD.EOL + "<tr bgcolor=\"lightgrey\"> " + PMD.EOL + "<td align=\"left\"><a href=\"link_prefix.html#line_prefix1\"></a></td>" + PMD.EOL
+ "<td align=\"center\">1</td>" + PMD.EOL + "<td align=\"center\">Foo</td>" + PMD.EOL
+ "<td align=\"center\">NOPMD</td>" + PMD.EOL + "<td align=\"center\">test</td>" + PMD.EOL + "</tr>"
+ PMD.EOL + "</table></tr></table></body></html>" + PMD.EOL, actual);