PMD exit with status 4 if violations have been found.
This commit is contained in:
@ -17,6 +17,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@ -30,6 +31,7 @@ import net.sourceforge.pmd.lang.*;
|
||||
import net.sourceforge.pmd.processor.MonoThreadProcessor;
|
||||
import net.sourceforge.pmd.processor.MultiThreadProcessor;
|
||||
import net.sourceforge.pmd.renderers.Renderer;
|
||||
import net.sourceforge.pmd.stat.Metric;
|
||||
import net.sourceforge.pmd.util.FileUtil;
|
||||
import net.sourceforge.pmd.util.IOUtil;
|
||||
import net.sourceforge.pmd.util.SystemUtils;
|
||||
@ -209,14 +211,15 @@ public class PMD {
|
||||
* This method is the main entry point for command line usage.
|
||||
*
|
||||
* @param configuration the configure to use
|
||||
* @return number of violations found.
|
||||
*/
|
||||
public static void doPMD(PMDConfiguration configuration) {
|
||||
public static int doPMD(PMDConfiguration configuration) {
|
||||
|
||||
// Load the RuleSets
|
||||
RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration);
|
||||
RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory);
|
||||
if (ruleSets == null) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Set<Language> languages = getApplicableLanguages(configuration, ruleSets);
|
||||
@ -234,12 +237,23 @@ public class PMD {
|
||||
Benchmarker.mark(Benchmark.Reporting, System.nanoTime() - reportStart, 0);
|
||||
|
||||
RuleContext ctx = new RuleContext();
|
||||
final AtomicInteger violations = new AtomicInteger(0);
|
||||
ctx.getReport().addListener(new ReportListener() {
|
||||
@Override
|
||||
public void ruleViolationAdded(RuleViolation ruleViolation) {
|
||||
violations.incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void metricAdded(Metric metric) {
|
||||
}
|
||||
});
|
||||
|
||||
processFiles(configuration, ruleSetFactory, files, ctx, renderers);
|
||||
|
||||
reportStart = System.nanoTime();
|
||||
renderer.end();
|
||||
renderer.flush();
|
||||
return violations.get();
|
||||
} catch (Exception e) {
|
||||
String message = e.getMessage();
|
||||
if (message != null) {
|
||||
@ -249,6 +263,7 @@ public class PMD {
|
||||
}
|
||||
LOG.log(Level.FINE, "Exception during processing", e);
|
||||
LOG.info(PMDCommandLineInterface.buildUsageText());
|
||||
return 0;
|
||||
} finally {
|
||||
Benchmarker.mark(Benchmark.Reporting, System.nanoTime() - reportStart, 0);
|
||||
}
|
||||
@ -420,7 +435,8 @@ public class PMD {
|
||||
/**
|
||||
* Parses the command line arguments and executes PMD.
|
||||
* @param args command line arguments
|
||||
* @return the exit code, where <code>0</code> means successful execution.
|
||||
* @return the exit code, where <code>0</code> means successful execution, <code>1</code> means error,
|
||||
* <code>4</code> means there have been violations found.
|
||||
*/
|
||||
public static int run(String[] args) {
|
||||
int status = 0;
|
||||
@ -435,7 +451,12 @@ public class PMD {
|
||||
LOG.setLevel(logLevel); // Need to do this, since the static logger has
|
||||
// already been initialized at this point
|
||||
try {
|
||||
PMD.doPMD(configuration);
|
||||
int violations = PMD.doPMD(configuration);
|
||||
if (violations > 0) {
|
||||
status = PMDCommandLineInterface.VIOLATIONS_FOUND;
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(PMDCommandLineInterface.buildUsageText());
|
||||
System.out.println();
|
||||
|
@ -26,6 +26,7 @@ public class PMDCommandLineInterface {
|
||||
public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
|
||||
|
||||
public static final int ERROR_STATUS = 1;
|
||||
public static final int VIOLATIONS_FOUND = 4;
|
||||
|
||||
public static PMDParameters extractParameters(PMDParameters arguments, String[] args, String progName) {
|
||||
JCommander jcommander = new JCommander(arguments);
|
||||
|
@ -20,31 +20,44 @@ import org.junit.Test;
|
||||
public class CLITest extends BaseCLITest {
|
||||
@Test
|
||||
public void minimalArgs() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-basic,java-design" };
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-unnecessary,java-design" };
|
||||
runTest(args, "minimalArgs");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minimumPriority() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-basic,java-design", "-min", "1"};
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-design", "-min", "1"};
|
||||
runTest(args,"minimumPriority");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usingDebug() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-basic,java-design", "-debug" };
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-design", "-debug" };
|
||||
runTest(args, "minimalArgsWithDebug");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeJavaVersion() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-basic,java-design", "-version", "1.5",
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-design", "-version", "1.5",
|
||||
"-language", "java", "-debug" };
|
||||
String resultFilename = runTest(args, "chgJavaVersion");
|
||||
assertTrue("Invalid Java version",
|
||||
FileUtil.findPatternInFile(new File(resultFilename), "Using Java version: Java 1.5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitStatusNoViolations() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-design" };
|
||||
runTest(args, "exitStatusNoViolations");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitStatusWithViolations() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-empty" };
|
||||
String resultFilename = runTest(args, "exitStatusWithViolations", 4);
|
||||
assertTrue(FileUtil.findPatternInFile(new File(resultFilename), "Avoid empty if"));
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://sourceforge.net/p/pmd/bugs/1231/
|
||||
*/
|
||||
|
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Source code file used for
|
||||
* {@link net.sourceforge.pmd.cli.CLITest}
|
||||
*/
|
||||
public class EmptyIfStatement {
|
||||
public void foo() {
|
||||
if (1 == 2) { }
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ public class CLITest extends BaseCLITest {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "xml", "-R", "ecmascript-basic", "-version", "3", "-l",
|
||||
"ecmascript", "-debug" };
|
||||
String resultFilename = runTest(args, "useEcmaScript");
|
||||
assertTrue("Invalid Java version",
|
||||
assertTrue("Invalid JavaScript version",
|
||||
FileUtil.findPatternInFile(new File(resultFilename), "Using Ecmascript version: Ecmascript 3"));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
// just some js file for net.sourceforge.pmd.cli.CLITest
|
@ -25,12 +25,12 @@ public abstract class BaseCLITest {
|
||||
|
||||
protected static final String TEST_OUPUT_DIRECTORY = "target/cli-tests/";
|
||||
|
||||
// Points toward a folder without any source files, to avoid actually PMD
|
||||
// Points toward a folder with not many source files, to avoid actually PMD
|
||||
// and slowing down tests
|
||||
protected static final String SOURCE_FOLDER = "src/main/resources";
|
||||
protected static final String SOURCE_FOLDER = "src/test/resources/net/sourceforge/pmd/cli";
|
||||
|
||||
private PrintStream originalOut;
|
||||
private PrintStream originalErr;
|
||||
protected PrintStream originalOut;
|
||||
protected PrintStream originalErr;
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
@ -68,12 +68,15 @@ public abstract class BaseCLITest {
|
||||
}
|
||||
|
||||
protected String runTest(String[] args, String testname) {
|
||||
return runTest(args, testname, 0);
|
||||
}
|
||||
protected String runTest(String[] args, String testname, int expectedExitCode) {
|
||||
String filename = TEST_OUPUT_DIRECTORY + testname + ".txt";
|
||||
long start = System.currentTimeMillis();
|
||||
createTestOutputFile(filename);
|
||||
System.out.println("Start running test " + testname);
|
||||
runPMDWith(args);
|
||||
checkStatusCode();
|
||||
checkStatusCode(expectedExitCode);
|
||||
System.out.println("Test finished successfully after " + (System.currentTimeMillis() - start) + "ms.");
|
||||
return filename;
|
||||
}
|
||||
@ -82,9 +85,9 @@ public abstract class BaseCLITest {
|
||||
PMD.main(args);
|
||||
}
|
||||
|
||||
protected void checkStatusCode() {
|
||||
protected void checkStatusCode(int expectedExitCode) {
|
||||
int statusCode = getStatusCode();
|
||||
if (statusCode > 0) {
|
||||
if (statusCode != expectedExitCode) {
|
||||
fail("PMD failed with status code:" + statusCode);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
* XML: Line numbers for XML documents are more accurate. This is a further improvement of [#1054](https://sourceforge.net/p/pmd/bugs/1054/).
|
||||
* CPD: New output format 'csv_with_linecount_per_file'
|
||||
* [#1320](https://sourceforge.net/p/pmd/bugs/1320/): Enhance SimplifyBooleanReturns checks
|
||||
* PMD exits with status `4` if any violations have been found. This behavior has been introduced to ease PMD
|
||||
integration into scripts or hooks, such as SVN hooks.
|
||||
|
||||
**New/Modified/Deprecated Rules:**
|
||||
|
||||
|
@ -193,6 +193,13 @@ The tool comes with a rather extensive help text, simply running with `-help`!
|
||||
</table>
|
||||
|
||||
|
||||
Exit Status
|
||||
-----------
|
||||
|
||||
Please note that if PMD detects any violations, it will exit with status 4 (since 5.3).
|
||||
This behavior has been introduced to ease PMD integration into scripts or hooks, such as SVN hooks.
|
||||
|
||||
|
||||
Supported Languages
|
||||
-------------------
|
||||
|
||||
|
Reference in New Issue
Block a user