[MPMD-281] Display found violations grouped by priority
* New property pmd.renderViolationsByPriority
diff --git a/src/it/MPMD-128-xref-link/pom.xml b/src/it/MPMD-128-xref-link/pom.xml
index 32dcaba..f3728ce 100644
--- a/src/it/MPMD-128-xref-link/pom.xml
+++ b/src/it/MPMD-128-xref-link/pom.xml
@@ -51,6 +51,7 @@
<rulesets>
<ruleset>src/main/config/pmd/rules.xml</ruleset>
</rulesets>
+ <renderViolationsByPriority>false</renderViolationsByPriority>
</configuration>
</plugin>
<plugin>
diff --git a/src/it/MPMD-253-xref-link-multi-module/pom.xml b/src/it/MPMD-253-xref-link-multi-module/pom.xml
index b0be09e..d9d0f85 100644
--- a/src/it/MPMD-253-xref-link-multi-module/pom.xml
+++ b/src/it/MPMD-253-xref-link-multi-module/pom.xml
@@ -52,7 +52,8 @@
<rulesets>
<ruleset>src/main/config/pmd/rules.xml</ruleset>
</rulesets>
- <aggregate>true</aggregate>
+ <aggregate>true</aggregate>
+ <renderViolationsByPriority>false</renderViolationsByPriority>
</configuration>
</plugin>
<plugin>
diff --git a/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java b/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
index 054af56..f88c89a 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
@@ -236,6 +236,15 @@
@Parameter( property = "pmd.renderRuleViolationPriority", defaultValue = "true" )
private boolean renderRuleViolationPriority = true;
+ /**
+ * Add a section in the HTML report, that groups the found violations by rule priority
+ * in addition to grouping by file.
+ *
+ * @since 3.12.0
+ */
+ @Parameter( property = "pmd.renderViolationsByPriority", defaultValue = "true" )
+ private boolean renderViolationsByPriority = true;
+
@Component
private DependencyResolver dependencyResolver;
@@ -561,6 +570,7 @@
Sink sink = getSink();
PmdReportGenerator doxiaRenderer = new PmdReportGenerator( getLog(), sink, getBundle( locale ), aggregate );
doxiaRenderer.setRenderRuleViolationPriority( renderRuleViolationPriority );
+ doxiaRenderer.setRenderViolationsByPriority( renderViolationsByPriority );
doxiaRenderer.setFiles( filesToProcess );
doxiaRenderer.setViolations( renderer.getViolations() );
if ( renderProcessingErrors )
diff --git a/src/main/java/org/apache/maven/plugins/pmd/PmdReportGenerator.java b/src/main/java/org/apache/maven/plugins/pmd/PmdReportGenerator.java
index 1d744b8..83e32ce 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/PmdReportGenerator.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/PmdReportGenerator.java
@@ -25,6 +25,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -36,6 +37,7 @@
import org.codehaus.plexus.util.StringUtils;
import net.sourceforge.pmd.Report.ProcessingError;
+import net.sourceforge.pmd.RulePriority;
import net.sourceforge.pmd.RuleViolation;
/**
@@ -62,6 +64,8 @@
private boolean renderRuleViolationPriority;
+ private boolean renderViolationsByPriority;
+
private Map<File, PmdFileInfo> files;
// private List<Metric> metrics = new ArrayList<Metric>();
@@ -142,16 +146,16 @@
return fileInfo;
}
- private void startFileSection( String currentFilename, PmdFileInfo fileInfo )
+ private void startFileSection( int level, String currentFilename, PmdFileInfo fileInfo )
{
- sink.section2();
- sink.sectionTitle2();
+ sink.section( level, null );
+ sink.sectionTitle( level, null );
// prepare the filename
this.currentFilename = shortenFilename( currentFilename, fileInfo );
sink.text( makeFileSectionName( this.currentFilename, fileInfo ) );
- sink.sectionTitle2_();
+ sink.sectionTitle_( level );
sink.table();
sink.tableRow();
@@ -173,10 +177,10 @@
sink.tableRow_();
}
- private void endFileSection()
+ private void endFileSection( int level )
{
sink.table_();
- sink.section2_();
+ sink.section_( level );
}
private void processSingleRuleViolation( RuleViolation ruleViolation, PmdFileInfo fileInfo )
@@ -216,7 +220,7 @@
// PMD might run the analysis multi-threaded, so the violations might be reported
// out of order. We sort them here by filename and line number before writing them to
// the report.
- private void processViolations()
+ private void renderViolations()
throws IOException
{
sink.section1();
@@ -227,7 +231,73 @@
// TODO files summary
List<RuleViolation> violations2 = new ArrayList<>( violations );
- Collections.sort( violations2, new Comparator<RuleViolation>()
+ renderViolationsTable( 2, violations2 );
+
+ sink.section1_();
+ }
+
+ private void renderViolationsByPriority() throws IOException
+ {
+ if ( !renderViolationsByPriority )
+ {
+ return;
+ }
+
+ boolean oldPriorityColumn = this.renderRuleViolationPriority;
+ this.renderRuleViolationPriority = false;
+
+ sink.section1();
+ sink.sectionTitle1();
+ sink.text( bundle.getString( "report.pmd.violationsByPriority" ) );
+ sink.sectionTitle1_();
+
+ Map<RulePriority, List<RuleViolation>> violationsByPriority = new HashMap<>();
+ for ( RuleViolation violation : violations )
+ {
+ RulePriority priority = violation.getRule().getPriority();
+ List<RuleViolation> violationSegment = violationsByPriority.get( priority );
+ if ( violationSegment == null )
+ {
+ violationSegment = new ArrayList<>();
+ violationsByPriority.put( priority, violationSegment );
+ }
+ violationsByPriority.get( violation.getRule().getPriority() ).add( violation );
+ }
+
+ for ( RulePriority priority : RulePriority.values() )
+ {
+ List<RuleViolation> violationsWithPriority = violationsByPriority.get( priority );
+ if ( violationsWithPriority == null || violationsWithPriority.isEmpty() )
+ {
+ continue;
+ }
+
+ sink.section2();
+ sink.sectionTitle2();
+ sink.text( bundle.getString( "report.pmd.priority" ) + " " + priority.getPriority() );
+ sink.sectionTitle2_();
+
+ renderViolationsTable( 3, violationsWithPriority );
+
+ sink.section2_();
+ }
+
+ if ( violations.isEmpty() )
+ {
+ sink.paragraph();
+ sink.text( bundle.getString( "report.pmd.noProblems" ) );
+ sink.paragraph_();
+ }
+
+ sink.section1_();
+
+ this.renderRuleViolationPriority = oldPriorityColumn;
+ }
+
+ private void renderViolationsTable( int level, List<RuleViolation> violationSegment )
+ throws IOException
+ {
+ Collections.sort( violationSegment, new Comparator<RuleViolation>()
{
/** {@inheritDoc} */
public int compare( RuleViolation o1, RuleViolation o2 )
@@ -246,19 +316,19 @@
boolean fileSectionStarted = false;
String previousFilename = null;
- for ( RuleViolation ruleViolation : violations2 )
+ for ( RuleViolation ruleViolation : violationSegment )
{
String currentFn = ruleViolation.getFilename();
PmdFileInfo fileInfo = determineFileInfo( currentFn );
if ( !currentFn.equalsIgnoreCase( previousFilename ) && fileSectionStarted )
{
- endFileSection();
+ endFileSection( level );
fileSectionStarted = false;
}
if ( !fileSectionStarted )
{
- startFileSection( currentFn, fileInfo );
+ startFileSection( level, currentFn, fileInfo );
fileSectionStarted = true;
}
@@ -269,17 +339,8 @@
if ( fileSectionStarted )
{
- endFileSection();
+ endFileSection( level );
}
-
- if ( violations.isEmpty() )
- {
- sink.paragraph();
- sink.text( bundle.getString( "report.pmd.noProblems" ) );
- sink.paragraph_();
- }
-
- sink.section1_();
}
private void outputLineLink( int line, PmdFileInfo fileInfo )
@@ -403,7 +464,18 @@
public void render()
throws IOException
{
- processViolations();
+ if ( !violations.isEmpty() )
+ {
+ renderViolationsByPriority();
+
+ renderViolations();
+ }
+ else
+ {
+ sink.paragraph();
+ sink.text( bundle.getString( "report.pmd.noProblems" ) );
+ sink.paragraph_();
+ }
if ( !processingErrors.isEmpty() )
{
@@ -437,4 +509,9 @@
{
this.renderRuleViolationPriority = renderRuleViolationPriority;
}
+
+ public void setRenderViolationsByPriority( boolean renderViolationsByPriority )
+ {
+ this.renderViolationsByPriority = renderViolationsByPriority;
+ }
}
diff --git a/src/main/resources/pmd-report.properties b/src/main/resources/pmd-report.properties
index df6632f..afe9460 100644
--- a/src/main/resources/pmd-report.properties
+++ b/src/main/resources/pmd-report.properties
@@ -24,6 +24,8 @@
report.pmd.column.line=Line
report.pmd.pmdlink=The following document contains the results of
report.pmd.files=Files
+report.pmd.violationsByPriority=Violations By Priority
+report.pmd.priority=Priority
report.pmd.noProblems=PMD found no problems in your source code.
report.pmd.processingErrors.title=Processing Errors
report.pmd.processingErrors.column.filename=Filename
diff --git a/src/main/resources/pmd-report_de.properties b/src/main/resources/pmd-report_de.properties
index 6cdcd10..83f72d4 100644
--- a/src/main/resources/pmd-report_de.properties
+++ b/src/main/resources/pmd-report_de.properties
@@ -24,6 +24,8 @@
report.pmd.column.line=Zeile
report.pmd.pmdlink=Dieses Dokument enth\u00e4lt die Ergebnisse von
report.pmd.files=Dateien
+report.pmd.violationsByPriority=Verst\u00f6\u00dfe nach Priorit\u00e4t
+report.pmd.priority=Priorit\u00e4t
report.pmd.noProblems=PMD hat keine Probleme in dem Quellcode gefunden.
report.pmd.processingErrors.title=Verarbeitungsprobleme
report.pmd.processingErrors.column.filename=Datei
diff --git a/src/test/java/org/apache/maven/plugins/pmd/PmdReportTest.java b/src/test/java/org/apache/maven/plugins/pmd/PmdReportTest.java
index 1ed3647..a92ed4c 100644
--- a/src/test/java/org/apache/maven/plugins/pmd/PmdReportTest.java
+++ b/src/test/java/org/apache/maven/plugins/pmd/PmdReportTest.java
@@ -95,6 +95,13 @@
assertTrue( str.contains( "<th>Rule</th>" ) );
// along with a link to the rule
assertTrue( str.contains( "pmd_rules_java_bestpractices.html#unusedprivatefield\">UnusedPrivateField</a>" ) );
+
+ // there should be the section Violations By Priority
+ assertTrue( str.contains( "Violations By Priority</h2>" ) );
+ assertTrue( str.contains( "Priority 3</h3>" ) );
+ assertTrue( str.contains( "Priority 4</h3>" ) );
+ // the file App.java is mentioned 3 times: in prio 3, in prio 4 and in the files section
+ assertEquals( 3, StringUtils.countMatches( str, "def/configuration/App.java" ) );
}
public void testDefaultConfigurationNotRenderRuleViolationPriority()
@@ -117,9 +124,37 @@
String str = readFile( generatedFile );
// check that there's no priority column
- assertFalse( str.contains( "Priority" ) );
+ assertFalse( str.contains( "<th>Priority</th>" ) );
}
+ public void testDefaultConfigurationNoRenderViolationsByPriority()
+ throws Exception
+ {
+ FileUtils.copyDirectoryStructure( new File( getBasedir(),
+ "src/test/resources/unit/default-configuration/jxr-files" ),
+ new File( getBasedir(), "target/test/unit/default-configuration/target/site" ) );
+
+ File testPom =
+ new File( getBasedir(),
+ "src/test/resources/unit/default-configuration/pmd-report-no-render-violations-by-priority.xml" );
+ PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
+ mojo.execute();
+
+ File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
+ renderer( mojo, generatedFile );
+ assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
+
+ String str = readFile( generatedFile );
+
+ // there should be no section Violations By Priority
+ assertFalse( str.contains( "Violations By Priority</h2>" ) );
+ assertFalse( str.contains( "Priority 3</h3>" ) );
+ assertFalse( str.contains( "Priority 4</h3>" ) );
+ // the file App.java is mentioned once: in the files section
+ assertEquals( 1, StringUtils.countMatches( str, "def/configuration/App.java" ) );
+ }
+
+
public void testDefaultConfigurationWithAnalysisCache()
throws Exception
{
@@ -344,7 +379,10 @@
assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
String str = readFile( generatedFile );
assertFalse( lowerCaseContains( str, "Hello.java" ) );
- assertTrue( str.contains( "PMD found no problems in your source code." ) );
+ assertEquals( 1, StringUtils.countMatches( str, "PMD found no problems in your source code." ) );
+ // no sections files or violations by priority
+ assertFalse( str.contains( "Files</h2>" ) );
+ assertFalse( str.contains( "Violations By Priority</h2>" ) );
}
public void testInvalidFormat()
diff --git a/src/test/resources/unit/default-configuration/pmd-report-no-render-violations-by-priority.xml b/src/test/resources/unit/default-configuration/pmd-report-no-render-violations-by-priority.xml
new file mode 100644
index 0000000..1c58040
--- /dev/null
+++ b/src/test/resources/unit/default-configuration/pmd-report-no-render-violations-by-priority.xml
@@ -0,0 +1,67 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>def.configuration</groupId>
+ <artifactId>default-configuration</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <inceptionYear>2006</inceptionYear>
+ <name>Maven PMD Plugin Default Configuration Test</name>
+ <url>http://maven.apache.org</url>
+ <build>
+ <finalName>default-configuration</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <configuration>
+ <project implementation="org.apache.maven.plugins.pmd.stubs.DefaultConfigurationMavenProjectStub"/>
+ <outputDirectory>${basedir}/target/test/unit/default-configuration/target/site</outputDirectory>
+ <targetDirectory>${basedir}/target/test/unit/default-configuration/target</targetDirectory>
+ <format>xml</format>
+ <linkXRef>true</linkXRef>
+ <xrefLocation>${basedir}/target/test/unit/default-configuration/target/site/xref</xrefLocation>
+ <sourceEncoding>UTF-8</sourceEncoding>
+ <compileSourceRoots>
+ <compileSourceRoot>${basedir}/src/test/resources/unit/default-configuration/</compileSourceRoot>
+ </compileSourceRoots>
+
+ <renderViolationsByPriority>false</renderViolationsByPriority>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>pmd</groupId>
+ <artifactId>pmd</artifactId>
+ <version>3.6</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>