From efce6b9729753a1c7806c0b25562d2450f242911 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 28 Jun 2024 17:47:54 -0700 Subject: [PATCH] Added failOnError (PMD 7.3.0) support --- .../rife/bld/extension/PmdOperationBuild.java | 4 +- .../java/rife/bld/extension/PmdOperation.java | 45 +++++++++++++++---- .../rife/bld/extension/PmdOperationTest.java | 26 ++++++++--- src/test/resources/pmd.xml | 4 +- src/test/resources/xml/basic.xml | 4 +- src/test/resources/xml/old.xml | 8 ++++ 6 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 src/test/resources/xml/old.xml diff --git a/src/bld/java/rife/bld/extension/PmdOperationBuild.java b/src/bld/java/rife/bld/extension/PmdOperationBuild.java index 7ea5d9b..3f23dd1 100644 --- a/src/bld/java/rife/bld/extension/PmdOperationBuild.java +++ b/src/bld/java/rife/bld/extension/PmdOperationBuild.java @@ -32,7 +32,7 @@ public class PmdOperationBuild extends Project { public PmdOperationBuild() { pkg = "rife.bld.extension"; name = "bld-pmd"; - version = version(1, 1, 1); + version = version(1, 1, 2); javaRelease = 17; @@ -40,7 +40,7 @@ public class PmdOperationBuild extends Project { autoDownloadPurge = true; repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES); - var pmd = version(7, 2, 0); + var pmd = version(7, 3, 0); scope(compile) .include(dependency("com.uwyn.rife2", "bld", version(1, 9, 1))) .include(dependency("net.sourceforge.pmd", "pmd-java", pmd)); diff --git a/src/main/java/rife/bld/extension/PmdOperation.java b/src/main/java/rife/bld/extension/PmdOperation.java index f374349..8aaea0d 100644 --- a/src/main/java/rife/bld/extension/PmdOperation.java +++ b/src/main/java/rife/bld/extension/PmdOperation.java @@ -69,6 +69,10 @@ public class PmdOperation extends AbstractOperation { * The encoding. */ private Charset encoding_ = StandardCharsets.UTF_8; + /** + * The fail on error toggle. + */ + private boolean failOnError_ = true; /** * The fail on violation toggle. */ @@ -296,7 +300,28 @@ public class PmdOperation extends AbstractOperation { } /** - * Sets whether the build will continue on warnings. + * Sets whether the build will exit on recoverable errors. + *

+ * Default is: {@code true} + *

+ * Note: If only violations are found, see {@link #failOnViolation(boolean) failOnViolation} + * + * @param failOnError whether to exit and fail the build if recoverable errors occurred + * @return this operation + * @see #failOnViolation(boolean) + */ + public PmdOperation failOnError(boolean failOnError) { + failOnError_ = failOnError; + return this; + } + + /** + * Sets whether the build will continue on violations. + *

+ * Note: If additionally recoverable errors occurred, see {@link #failOnError(boolean) failOnError} + * + * @param failOnViolation whether to exit and fail the build if violations are found + * @return this operation */ public PmdOperation failOnViolation(boolean failOnViolation) { failOnViolation_ = failOnViolation; @@ -411,6 +436,7 @@ public class PmdOperation extends AbstractOperation { config.setAnalysisCacheLocation(cache_.toFile().getAbsolutePath()); } + config.setFailOnError(failOnError_); config.setFailOnViolation(failOnViolation_); if (languageVersions_ != null) { @@ -574,8 +600,8 @@ public class PmdOperation extends AbstractOperation { * * @param commandName the command name * @param config the configuration - * @return the number of errors - * @throws RuntimeException if an error occurs + * @return the number of violations + * @throws ExitStatusException if an error occurs */ @SuppressWarnings({"PMD.CloseResource", "PMD.AvoidInstantiatingObjectsInLoops"}) public int performPmdAnalysis(String commandName, PMDConfiguration config) throws ExitStatusException { @@ -585,8 +611,9 @@ public class PmdOperation extends AbstractOperation { LOGGER.log(Level.INFO, "[{0}] inputPaths{1}", new Object[]{commandName, inputPaths_}); LOGGER.log(Level.INFO, "[{0}] ruleSets{1}", new Object[]{commandName, ruleSets_}); } - var numErrors = report.getViolations().size(); - if (numErrors > 0) { + + var numViolations = report.getViolations().size(); + if (numViolations > 0) { for (var v : report.getViolations()) { if (LOGGER.isLoggable(Level.WARNING) && !silent()) { final String msg; @@ -608,7 +635,7 @@ public class PmdOperation extends AbstractOperation { } var violations = String.format( - "[%s] %d rule violations were found. See the report at: %s", commandName, numErrors, + "[%s] %d rule violations were found. See the report at: %s", commandName, numViolations, config.getReportFilePath().toUri()); if (config.isFailOnViolation()) { if (LOGGER.isLoggable(Level.SEVERE) && !silent()) { @@ -616,8 +643,10 @@ public class PmdOperation extends AbstractOperation { } throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); } else if (LOGGER.isLoggable(Level.WARNING) && !silent()) { - LOGGER.warning(violations); + LOGGER.warning(violations); } + } else if (pmd.getReporter().numErrors() > 0 && failOnError_) { + throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); } else { var rules = pmd.getRulesets(); if (!rules.isEmpty()) { @@ -630,7 +659,7 @@ public class PmdOperation extends AbstractOperation { } } } - return numErrors; + return numViolations; } /** diff --git a/src/test/java/rife/bld/extension/PmdOperationTest.java b/src/test/java/rife/bld/extension/PmdOperationTest.java index ad387ac..6d042a7 100644 --- a/src/test/java/rife/bld/extension/PmdOperationTest.java +++ b/src/test/java/rife/bld/extension/PmdOperationTest.java @@ -142,12 +142,6 @@ class PmdOperationTest { assertThat(config.getSourceEncoding()).as("ISO_8859").isEqualTo(StandardCharsets.ISO_8859_1); } - @Test - void testExecuteNoProject() { - var pmd = new PmdOperation(); - assertThatCode(pmd::execute).isInstanceOf(ExitStatusException.class); - } - @Test void testExecute() throws ExitStatusException { var pmd = new PmdOperation().fromProject(new BaseProject()); @@ -163,12 +157,30 @@ class PmdOperationTest { assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); } + @Test + void testExecuteNoProject() { + var pmd = new PmdOperation(); + assertThatCode(pmd::execute).isInstanceOf(ExitStatusException.class); + } + + @Test + void testFailOnError() { + var pmd = newPmdOperation().ruleSets("src/test/resources/xml/old.xml") + .inputPaths(Path.of("src/test/resources/java/Documentation.java")); + assertThatCode(() -> pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .isInstanceOf(ExitStatusException.class); + assertThatCode(() -> pmd.failOnError(false).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .doesNotThrowAnyException(); + } + @Test void testFailOnValidation() { var pmd = newPmdOperation().ruleSets(DOCUMENTATION_XML) .inputPaths(Path.of("src/test/resources/java/Documentation.java")); assertThatCode(() -> pmd.failOnViolation(true).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) .isInstanceOf(ExitStatusException.class); + assertThatCode(() -> pmd.failOnViolation(false).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .doesNotThrowAnyException(); } @Test @@ -369,7 +381,7 @@ class PmdOperationTest { @Test void testRuleSetsEmpty() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(""); + var pmd = newPmdOperation().ruleSets("").failOnError(false); assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); } diff --git a/src/test/resources/pmd.xml b/src/test/resources/pmd.xml index c4c6617..18cc49b 100644 --- a/src/test/resources/pmd.xml +++ b/src/test/resources/pmd.xml @@ -1,7 +1,7 @@ - Erik's Ruleset diff --git a/src/test/resources/xml/basic.xml b/src/test/resources/xml/basic.xml index c261dc7..4043fba 100644 --- a/src/test/resources/xml/basic.xml +++ b/src/test/resources/xml/basic.xml @@ -1,8 +1,8 @@ - The Basic ruleset contains a collection of good practices which should be followed. diff --git a/src/test/resources/xml/old.xml b/src/test/resources/xml/old.xml new file mode 100644 index 0000000..fa71516 --- /dev/null +++ b/src/test/resources/xml/old.xml @@ -0,0 +1,8 @@ + + + Deprecated (old) rule + + \ No newline at end of file