Merge branch 'pmd6-improve-pmd-analysis' into pmd7-merge-master
This commit is contained in:
commit
e414e2119c
@ -75,6 +75,7 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is
|
||||
{% jdoc core::PMDConfiguration#setRuleSets(java.util.List) %},
|
||||
{% jdoc core::PMDConfiguration#addRuleSet(java.lang.String) %},
|
||||
and {% jdoc core::PMDConfiguration#getRuleSetPaths() %}.
|
||||
* Several members of {% jdoc test::cli.BaseCLITest %} have been deprecated with replacements.
|
||||
|
||||
#### Experimental APIs
|
||||
|
||||
|
@ -20,7 +20,8 @@ import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import net.sourceforge.pmd.Report.GlobalReportBuilderListener;
|
||||
import net.sourceforge.pmd.ReportStatsListener.ReportStats;
|
||||
import net.sourceforge.pmd.reporting.ReportStatsListener;
|
||||
import net.sourceforge.pmd.reporting.ReportStats;
|
||||
import net.sourceforge.pmd.benchmark.TextTimingReportRenderer;
|
||||
import net.sourceforge.pmd.benchmark.TimeTracker;
|
||||
import net.sourceforge.pmd.benchmark.TimingReport;
|
||||
@ -70,7 +71,7 @@ public final class PMD {
|
||||
}
|
||||
|
||||
|
||||
private static ReportStatsListener.ReportStats runAndReturnStats(PmdAnalysis pmd) {
|
||||
private static ReportStats runAndReturnStats(PmdAnalysis pmd) {
|
||||
if (pmd.getRulesets().isEmpty()) {
|
||||
return ReportStats.empty();
|
||||
}
|
||||
|
@ -354,6 +354,9 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
@Deprecated
|
||||
@DeprecatedUntil700
|
||||
public String getRuleSets() {
|
||||
if (ruleSets.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return StringUtils.join(ruleSets, ",");
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,8 @@ public final class PmdAnalysis implements AutoCloseable {
|
||||
private final PmdLogger reporter;
|
||||
|
||||
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* Constructs a new instance. The files paths (input files, filelist,
|
||||
* exclude list, etc) given in the configuration are collected into
|
||||
@ -238,7 +240,8 @@ public final class PmdAnalysis implements AutoCloseable {
|
||||
* All files collected in the {@linkplain #files() file collector} are
|
||||
* processed. This does not return a report, as the analysis results
|
||||
* are consumed by {@link GlobalAnalysisListener} instances (of which
|
||||
* Renderers are a special case).
|
||||
* Renderers are a special case). Note that this does
|
||||
* not throw, errors are instead accumulated into a {@link PmdLogger}.
|
||||
*/
|
||||
public void performAnalysis() {
|
||||
performAnalysisImpl(Collections.emptyList());
|
||||
@ -248,7 +251,8 @@ public final class PmdAnalysis implements AutoCloseable {
|
||||
* Run PMD with the current state of this instance. This will start
|
||||
* and finish the registered renderers. All files collected in the
|
||||
* {@linkplain #files() file collector} are processed. Returns the
|
||||
* output report.
|
||||
* output report. Note that this does not throw, errors are instead
|
||||
* accumulated into a {@link PmdLogger}.
|
||||
*/
|
||||
public Report performAnalysisAndCollectReport() {
|
||||
try (GlobalReportBuilderListener reportBuilder = new GlobalReportBuilderListener()) {
|
||||
@ -364,6 +368,10 @@ public final class PmdAnalysis implements AutoCloseable {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
collector.close();
|
||||
|
||||
/*
|
||||
|
@ -28,7 +28,7 @@ import net.sourceforge.pmd.util.datasource.DataSource;
|
||||
* and configuration errors.
|
||||
*
|
||||
* <p>A report may be created by a {@link GlobalReportBuilderListener} that you
|
||||
* use as the {@link GlobalAnalysisListener} in {@linkplain PMD#processFiles(PMDConfiguration, List, List, GlobalAnalysisListener) PMD's entry point}.
|
||||
* use as the {@linkplain GlobalAnalysisListener} in {@link PmdAnalysis#performAnalysisAndCollectReport() PMD's entry point}.
|
||||
* You can also create one manually with {@link #buildReport(Consumer)}.
|
||||
*/
|
||||
public final class Report {
|
||||
|
@ -19,6 +19,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.util.CollectionUtil;
|
||||
@ -192,8 +193,12 @@ public final class RuleSetLoader {
|
||||
/**
|
||||
* Loads a list of rulesets, if any has an error, report it on the contextual
|
||||
* error reporter instead of aborting, and continue loading the rest.
|
||||
*
|
||||
* <p>Internal API: might be published later, or maybe in PMD 7 this
|
||||
* will be the default behaviour of every method of this class.
|
||||
*/
|
||||
List<RuleSet> loadRuleSetsWithoutException(List<String> rulesetPaths) {
|
||||
@InternalApi
|
||||
public List<RuleSet> loadRuleSetsWithoutException(List<String> rulesetPaths) {
|
||||
List<RuleSet> ruleSets = new ArrayList<>(rulesetPaths.size());
|
||||
boolean anyRules = false;
|
||||
for (String path : rulesetPaths) {
|
||||
@ -203,12 +208,17 @@ public final class RuleSetLoader {
|
||||
printRulesInDebug(path, ruleset);
|
||||
ruleSets.add(ruleset);
|
||||
} catch (RuleSetLoadException e) {
|
||||
reporter.errorEx("Cannot load ruleset {0}", new Object[] { path }, e);
|
||||
if (e.getCause() != null) {
|
||||
// eg RuleSetNotFoundException
|
||||
reporter.errorEx("Cannot load ruleset {0}", new Object[] { path }, e.getCause());
|
||||
} else {
|
||||
reporter.errorEx("Cannot load ruleset {0}", new Object[] { path }, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!anyRules) {
|
||||
reporter.warning("No rules found. Maybe you misspelled a rule name? ({0})",
|
||||
StringUtils.join(rulesetPaths, ','));
|
||||
reporter.warn("No rules found. Maybe you misspelled a rule name? ({0})",
|
||||
StringUtils.join(rulesetPaths, ','));
|
||||
}
|
||||
return ruleSets;
|
||||
}
|
||||
@ -221,7 +231,7 @@ public final class RuleSetLoader {
|
||||
}
|
||||
}
|
||||
if (ruleset.getRules().isEmpty()) {
|
||||
reporter.warning("No rules found in ruleset {0}", path);
|
||||
reporter.warn("No rules found in ruleset {0}", path);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ package net.sourceforge.pmd.ant.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
@ -23,10 +23,7 @@ import org.slf4j.event.Level;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.PmdAnalysis;
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.RulePriority;
|
||||
import net.sourceforge.pmd.RuleSet;
|
||||
import net.sourceforge.pmd.RuleSetLoadException;
|
||||
import net.sourceforge.pmd.RuleSetLoader;
|
||||
import net.sourceforge.pmd.ant.Formatter;
|
||||
import net.sourceforge.pmd.ant.PMDTask;
|
||||
@ -37,7 +34,8 @@ import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.LanguageVersion;
|
||||
import net.sourceforge.pmd.reporting.FileAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.GlobalAnalysisListener.ViolationCounterListener;
|
||||
import net.sourceforge.pmd.reporting.ReportStats;
|
||||
import net.sourceforge.pmd.reporting.ReportStatsListener;
|
||||
import net.sourceforge.pmd.util.ClasspathClassLoader;
|
||||
import net.sourceforge.pmd.util.IOUtil;
|
||||
import net.sourceforge.pmd.util.datasource.DataSource;
|
||||
@ -50,6 +48,7 @@ public class PMDTaskImpl {
|
||||
private final List<FileSet> filesets = new ArrayList<>();
|
||||
private final PMDConfiguration configuration = new PMDConfiguration();
|
||||
private final String rulesetPaths;
|
||||
private boolean failOnError;
|
||||
private boolean failOnRuleViolation;
|
||||
private int maxRuleViolations = 0;
|
||||
private String failuresPropertyName;
|
||||
@ -60,6 +59,7 @@ public class PMDTaskImpl {
|
||||
if (task.getSuppressMarker() != null) {
|
||||
configuration.setSuppressMarker(task.getSuppressMarker());
|
||||
}
|
||||
this.failOnError = task.isFailOnError();
|
||||
this.failOnRuleViolation = task.isFailOnRuleViolation();
|
||||
this.maxRuleViolations = task.getMaxRuleViolations();
|
||||
if (this.maxRuleViolations > 0) {
|
||||
@ -98,26 +98,23 @@ public class PMDTaskImpl {
|
||||
private void doTask() {
|
||||
setupClassLoader();
|
||||
|
||||
// Setup RuleSetFactory and validate RuleSets
|
||||
RuleSetLoader rulesetLoader = RuleSetLoader.fromPmdConfig(configuration)
|
||||
.loadResourcesWith(setupResourceLoader());
|
||||
|
||||
List<RuleSet> rules = loadRulesets(rulesetLoader);
|
||||
|
||||
if (configuration.getSuppressMarker() != null) {
|
||||
project.log("Setting suppress marker to be " + configuration.getSuppressMarker(), Project.MSG_VERBOSE);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("PMD.CloseResource")
|
||||
ViolationCounterListener reportSizeListener = new ViolationCounterListener();
|
||||
final List<String> reportShortNamesPaths = new ArrayList<>();
|
||||
@SuppressWarnings("PMD.CloseResource") final List<String> reportShortNamesPaths = new ArrayList<>();
|
||||
StringJoiner fullInputPath = new StringJoiner(",");
|
||||
|
||||
List<String> ruleSetPaths = expandRuleSetPaths();
|
||||
// don't let PmdAnalysis.create create rulesets itself.
|
||||
configuration.setRuleSets(Collections.emptyList());
|
||||
|
||||
ReportStats stats;
|
||||
try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) {
|
||||
for (RuleSet ruleSet : rules) {
|
||||
pmd.addRuleSet(ruleSet);
|
||||
}
|
||||
RuleSetLoader rulesetLoader =
|
||||
pmd.newRuleSetLoader().loadResourcesWith(setupResourceLoader());
|
||||
pmd.addRuleSets(rulesetLoader.loadRuleSetsWithoutException(ruleSetPaths));
|
||||
|
||||
for (FileSet fileset : filesets) {
|
||||
DirectoryScanner ds = fileset.getDirectoryScanner(project);
|
||||
@ -132,11 +129,17 @@ public class PMDTaskImpl {
|
||||
}
|
||||
}
|
||||
|
||||
pmd.addListener(getListener(reportSizeListener, reportShortNamesPaths, fullInputPath.toString()));
|
||||
ReportStatsListener reportStatsListener = new ReportStatsListener();
|
||||
pmd.addListener(getListener(reportStatsListener, reportShortNamesPaths, fullInputPath.toString()));
|
||||
|
||||
pmd.performAnalysis();
|
||||
stats = reportStatsListener.getResult();
|
||||
if (failOnError && pmd.getLog().numErrors() > 0) {
|
||||
throw new BuildException("Some errors occurred while running PMD");
|
||||
}
|
||||
}
|
||||
|
||||
int problemCount = reportSizeListener.getResult();
|
||||
int problemCount = stats.getNumViolations();
|
||||
project.log(problemCount + " problems found", Project.MSG_VERBOSE);
|
||||
|
||||
if (failuresPropertyName != null && problemCount > 0) {
|
||||
@ -149,25 +152,17 @@ public class PMDTaskImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private List<RuleSet> loadRulesets(RuleSetLoader rulesetLoader) {
|
||||
try {
|
||||
// This is just used to validate and display rules. Each thread will create its own ruleset
|
||||
// Substitute env variables/properties
|
||||
String ruleSetString = project.replaceProperties(rulesetPaths);
|
||||
|
||||
List<String> rulesets = Arrays.asList(ruleSetString.split(","));
|
||||
List<RuleSet> rulesetList = rulesetLoader.loadFromResources(rulesets);
|
||||
if (rulesetList.isEmpty()) {
|
||||
throw new BuildException("No rulesets");
|
||||
}
|
||||
logRulesUsed(rulesetList);
|
||||
return rulesetList;
|
||||
} catch (RuleSetLoadException e) {
|
||||
throw new BuildException(e.getMessage(), e);
|
||||
private List<String> expandRuleSetPaths() {
|
||||
List<String> paths = new ArrayList<>(configuration.getRuleSetPaths());
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
paths.set(i, project.replaceProperties(paths.get(i)));
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
private @NonNull GlobalAnalysisListener getListener(ViolationCounterListener reportSizeListener, List<String> reportShortNamesPaths, String inputPaths) {
|
||||
private @NonNull GlobalAnalysisListener getListener(ReportStatsListener reportSizeListener,
|
||||
List<String> reportShortNamesPaths,
|
||||
String inputPaths) {
|
||||
List<GlobalAnalysisListener> renderers = new ArrayList<>(formatters.size() + 1);
|
||||
try {
|
||||
renderers.add(makeLogListener(inputPaths));
|
||||
@ -254,13 +249,4 @@ public class PMDTaskImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private void logRulesUsed(List<RuleSet> rulesets) {
|
||||
project.log("Using these rulesets: " + rulesetPaths, Project.MSG_VERBOSE);
|
||||
|
||||
for (RuleSet ruleSet : rulesets) {
|
||||
for (Rule rule : ruleSet.getRules()) {
|
||||
project.log("Using rule " + rule.getName(), Project.MSG_VERBOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.PMD.StatusCode;
|
||||
import net.sourceforge.pmd.PMDVersion;
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
@ -28,13 +29,39 @@ import com.beust.jcommander.ParameterException;
|
||||
@InternalApi
|
||||
public final class PMDCommandLineInterface {
|
||||
|
||||
@Deprecated
|
||||
public static final String PROG_NAME = "pmd";
|
||||
|
||||
/**
|
||||
* @deprecated This is used for testing, but support for it will be removed in PMD 7.
|
||||
* Use {@link PMD#runPmd(String...)} or an overload to avoid exiting the VM. In PMD 7,
|
||||
* {@link PMD#main(String[])} will call {@link System#exit(int)} always.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String NO_EXIT_AFTER_RUN = "net.sourceforge.pmd.cli.noExit";
|
||||
|
||||
/**
|
||||
* @deprecated This is used for testing, but support for it will be removed in PMD 7.
|
||||
* Use {@link PMD#runPmd(String...)} or an overload to avoid exiting the VM. In PMD 7,
|
||||
* {@link PMD#main(String[])} will call {@link System#exit(int)} always.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link StatusCode#OK}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int NO_ERRORS_STATUS = 0;
|
||||
/**
|
||||
* @deprecated Use {@link StatusCode#ERROR}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int ERROR_STATUS = 1;
|
||||
/**
|
||||
* @deprecated Use {@link StatusCode#VIOLATIONS_FOUND}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int VIOLATIONS_FOUND = 4;
|
||||
|
||||
private PMDCommandLineInterface() { }
|
||||
@ -126,7 +153,10 @@ public final class PMDCommandLineInterface {
|
||||
* For testing purpose only...
|
||||
*
|
||||
* @param args
|
||||
*
|
||||
* @deprecated Use {@link PMD#runPmd(String...)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void main(String[] args) {
|
||||
System.out.println(PMDCommandLineInterface.buildUsageText());
|
||||
}
|
||||
|
@ -169,9 +169,9 @@ public final class FileCollectionUtil {
|
||||
String source = IOUtils.toString(sourceCode);
|
||||
collector.addSourceFile(source, falseFilePath);
|
||||
} catch (SQLException ex) {
|
||||
collector.getLog().warningEx("Cannot get SourceCode for {} - skipping ...",
|
||||
new Object[] { falseFilePath},
|
||||
ex);
|
||||
collector.getLog().warnEx("Cannot get SourceCode for {} - skipping ...",
|
||||
new Object[] { falseFilePath},
|
||||
ex);
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.reporting;
|
||||
|
||||
/**
|
||||
* Summarized info about a report.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public final class ReportStats {
|
||||
|
||||
private final int numErrors;
|
||||
private final int numViolations;
|
||||
|
||||
ReportStats(int numErrors, int numViolations) {
|
||||
this.numErrors = numErrors;
|
||||
this.numViolations = numViolations;
|
||||
}
|
||||
|
||||
public static ReportStats empty() {
|
||||
return new ReportStats(0, 0);
|
||||
}
|
||||
|
||||
public int getNumErrors() {
|
||||
return numErrors;
|
||||
}
|
||||
|
||||
public int getNumViolations() {
|
||||
return numViolations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReportStats{numErrors=" + numErrors + ", numViolations=" + numViolations + '}';
|
||||
}
|
||||
}
|
@ -2,23 +2,21 @@
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd;
|
||||
package net.sourceforge.pmd.reporting;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.sourceforge.pmd.Report.ProcessingError;
|
||||
import net.sourceforge.pmd.ReportStatsListener.ReportStats;
|
||||
import net.sourceforge.pmd.reporting.FileAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
import net.sourceforge.pmd.util.BaseResultProducingCloseable;
|
||||
import net.sourceforge.pmd.util.datasource.DataSource;
|
||||
|
||||
/**
|
||||
* Counts processing errors.
|
||||
* Collects summarized info about a PMD run.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
final class ReportStatsListener extends BaseResultProducingCloseable<ReportStats> implements GlobalAnalysisListener {
|
||||
public final class ReportStatsListener extends BaseResultProducingCloseable<ReportStats> implements GlobalAnalysisListener {
|
||||
|
||||
private final AtomicInteger numErrors = new AtomicInteger(0);
|
||||
private final AtomicInteger numViolations = new AtomicInteger(0);
|
||||
@ -62,31 +60,4 @@ final class ReportStatsListener extends BaseResultProducingCloseable<ReportStats
|
||||
}
|
||||
|
||||
|
||||
static final class ReportStats {
|
||||
|
||||
private final int numErrors;
|
||||
private final int numViolations;
|
||||
|
||||
ReportStats(int numErrors, int numViolations) {
|
||||
this.numErrors = numErrors;
|
||||
this.numViolations = numViolations;
|
||||
}
|
||||
|
||||
public static ReportStats empty() {
|
||||
return new ReportStats(0, 0);
|
||||
}
|
||||
|
||||
public int getNumErrors() {
|
||||
return numErrors;
|
||||
}
|
||||
|
||||
public int getNumViolations() {
|
||||
return numViolations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReportStats{numErrors=" + numErrors + ", numViolations=" + numViolations + '}';
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,10 @@
|
||||
|
||||
package net.sourceforge.pmd.util;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
@ -513,6 +517,13 @@ public final class StringUtil {
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape the string so that it appears literally when interpreted
|
||||
* by a {@link MessageFormat}.
|
||||
*/
|
||||
public static String quoteMessageFormat(String str) {
|
||||
return str.replaceAll("'", "''");
|
||||
}
|
||||
|
||||
public enum CaseConvention {
|
||||
/** SCREAMING_SNAKE_CASE. */
|
||||
|
@ -36,7 +36,7 @@ public interface PmdLogger {
|
||||
logEx(Level.WARN, message, new Object[0], error);
|
||||
}
|
||||
|
||||
default void warningEx(String message, Object[] formatArgs, Throwable error) {
|
||||
default void warnEx(String message, Object[] formatArgs, Throwable error) {
|
||||
logEx(Level.WARN, message, formatArgs, error);
|
||||
}
|
||||
|
||||
@ -52,6 +52,12 @@ public interface PmdLogger {
|
||||
logEx(Level.ERROR, message, formatArgs, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of errors reported on this instance.
|
||||
* Any call to {@link #log(Level, String, Object...)} or
|
||||
* {@link #logEx(Level, String, Object[], Throwable)} with a level
|
||||
* of {@link Level#ERROR} should increment this number.
|
||||
*/
|
||||
int numErrors();
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import java.text.MessageFormat;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Base implementation.
|
||||
*
|
||||
@ -41,9 +43,15 @@ abstract class PmdLoggerBase implements PmdLogger {
|
||||
public void logEx(Level level, String message, Object[] formatArgs, Throwable error) {
|
||||
if (isLoggable(level)) {
|
||||
message = MessageFormat.format(message, formatArgs);
|
||||
log(level, message + ": " + error.getMessage());
|
||||
String errorMessage = error.getMessage();
|
||||
if (errorMessage == null) {
|
||||
errorMessage = error.getClass().getSimpleName();
|
||||
}
|
||||
errorMessage = StringUtil.quoteMessageFormat(errorMessage);
|
||||
log(level, message + ": " + errorMessage);
|
||||
if (isLoggable(Level.DEBUG)) {
|
||||
log(Level.DEBUG, ExceptionUtils.getStackTrace(error));
|
||||
String stackTrace = StringUtil.quoteMessageFormat(ExceptionUtils.getStackTrace(error));
|
||||
log(Level.DEBUG, stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,13 @@
|
||||
|
||||
package net.sourceforge.pmd;
|
||||
|
||||
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@ -16,6 +20,7 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Assert;
|
||||
@ -111,6 +116,25 @@ public class ConfigurationTest {
|
||||
Assert.assertArrayEquals(expectedUris, uris);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleSetsLegacy() {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
assertNull("Default RuleSets", configuration.getRuleSets());
|
||||
configuration.setRuleSets("/rulesets/basic.xml");
|
||||
assertEquals("Changed RuleSets", "/rulesets/basic.xml", configuration.getRuleSets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleSets() {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
assertThat(configuration.getRuleSetPaths(), empty());
|
||||
configuration.setRuleSets(listOf("/rulesets/basic.xml"));
|
||||
assertEquals(listOf("/rulesets/basic.xml"), configuration.getRuleSetPaths());
|
||||
configuration.addRuleSet("foo.xml");
|
||||
assertEquals(listOf("/rulesets/basic.xml", "foo.xml"), configuration.getRuleSetPaths());
|
||||
configuration.setRuleSets(Collections.<String>emptyList());
|
||||
assertThat(configuration.getRuleSetPaths(), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimumPriority() {
|
||||
|
@ -16,6 +16,8 @@ import org.junit.rules.TestRule;
|
||||
|
||||
import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration;
|
||||
|
||||
import net.sourceforge.pmd.PMD.StatusCode;
|
||||
|
||||
/**
|
||||
* @author Romain Pelisse <belaran@gmail.com>
|
||||
*
|
||||
@ -75,21 +77,21 @@ public class CLITest extends BaseCLITest {
|
||||
@Test
|
||||
public void exitStatusWithViolations() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/errorprone.xml", };
|
||||
String log = runTest(4, args);
|
||||
String log = runTest(StatusCode.VIOLATIONS_FOUND, args);
|
||||
assertThat(log, containsString("Avoid empty if"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitStatusWithViolationsAndWithoutFailOnViolations() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/errorprone.xml", "-failOnViolation", "false", };
|
||||
String log = runTest(0, args);
|
||||
String log = runTest(StatusCode.OK, args);
|
||||
assertThat(log, containsString("Avoid empty if"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exitStatusWithViolationsAndWithoutFailOnViolationsLongOption() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/errorprone.xml", "--fail-on-violation", "false", };
|
||||
String log = runTest(0, args);
|
||||
String log = runTest(StatusCode.OK, args);
|
||||
assertThat(log, containsString("Avoid empty if"));
|
||||
}
|
||||
|
||||
@ -99,7 +101,7 @@ public class CLITest extends BaseCLITest {
|
||||
@Test
|
||||
public void testWrongRuleset() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/designn.xml", };
|
||||
String log = runTest(1, args);
|
||||
String log = runTest(StatusCode.ERROR, args);
|
||||
assertThat(log, containsString("Can't find resource 'category/java/designn.xml' for rule 'null'."
|
||||
+ " Make sure the resource is a valid file"));
|
||||
}
|
||||
@ -110,7 +112,7 @@ public class CLITest extends BaseCLITest {
|
||||
@Test
|
||||
public void testWrongRulesetWithRulename() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/designn.xml/UseCollectionIsEmpty", };
|
||||
String log = runTest(1, args);
|
||||
String log = runTest(StatusCode.ERROR, args);
|
||||
assertThat(log, containsString("Can't find resource 'category/java/designn.xml' for rule "
|
||||
+ "'UseCollectionIsEmpty'."));
|
||||
}
|
||||
@ -121,7 +123,7 @@ public class CLITest extends BaseCLITest {
|
||||
@Test
|
||||
public void testWrongRulename() {
|
||||
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/design.xml/ThisRuleDoesNotExist", };
|
||||
String log = runTest(1, args);
|
||||
String log = runTest(StatusCode.OK, args);
|
||||
assertThat(log, containsString("No rules found. Maybe you misspelled a rule name?"
|
||||
+ " (category/java/design.xml/ThisRuleDoesNotExist)"));
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.junit.BeforeClass;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.PMD.StatusCode;
|
||||
import net.sourceforge.pmd.internal.util.AssertionUtil;
|
||||
|
||||
/**
|
||||
* @author Romain Pelisse <belaran@gmail.com>
|
||||
@ -79,11 +80,19 @@ public abstract class BaseCLITest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #runTest(String...)}, note that
|
||||
* it returns the log while this returns the name of a file containing the log.
|
||||
*/
|
||||
@Deprecated
|
||||
protected String runTest(String[] args, String testname) {
|
||||
return runTest(args);
|
||||
return runTest(args, testname, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #runTest(StatusCode, String...)}, note that
|
||||
* it returns the log while this returns the name of a file containing the log.
|
||||
*/
|
||||
@Deprecated
|
||||
protected String runTest(String[] args, String testname, int expectedExitCode) {
|
||||
String filename = TEST_OUPUT_DIRECTORY + testname + ".txt";
|
||||
@ -100,27 +109,49 @@ public abstract class BaseCLITest {
|
||||
* Returns the log output.
|
||||
*/
|
||||
protected String runTest(String... args) {
|
||||
return runTest(0, args);
|
||||
return runTest(StatusCode.OK, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the log output.
|
||||
*
|
||||
* @deprecated Use {@link #runTest(StatusCode, String...)}
|
||||
*/
|
||||
@Deprecated
|
||||
protected String runTest(int expectedExitCode, String... args) {
|
||||
switch (expectedExitCode) {
|
||||
case 0:
|
||||
return runTest(StatusCode.OK, args);
|
||||
case 1:
|
||||
return runTest(StatusCode.ERROR, args);
|
||||
case 4:
|
||||
return runTest(StatusCode.VIOLATIONS_FOUND, args);
|
||||
default:
|
||||
throw AssertionUtil.shouldNotReachHere("unknown status code " + expectedExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
protected String runTest(StatusCode expectedExitCode, String... args) {
|
||||
ByteArrayOutputStream console = new ByteArrayOutputStream();
|
||||
PrintStream out = new PrintStream(console);
|
||||
System.setOut(out);
|
||||
System.setErr(out);
|
||||
StatusCode statusCode = PMD.runPmd(args);
|
||||
assertEquals(expectedExitCode, statusCode.toInt());
|
||||
assertEquals(expectedExitCode, statusCode);
|
||||
return console.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #runTest(StatusCode, String...)}
|
||||
*/
|
||||
@Deprecated
|
||||
protected void runPMDWith(String[] args) {
|
||||
PMD.main(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #runTest(StatusCode, String...)} instead of checking the return code manually
|
||||
*/
|
||||
@Deprecated
|
||||
protected void checkStatusCode(int expectedExitCode) {
|
||||
int statusCode = getStatusCode();
|
||||
@ -129,6 +160,10 @@ public abstract class BaseCLITest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #runTest(StatusCode, String...)} instead
|
||||
* of checking the return code manually
|
||||
*/
|
||||
@Deprecated
|
||||
protected int getStatusCode() {
|
||||
return Integer.parseInt(System.getProperty(PMDCommandLineInterface.STATUS_CODE_PROPERTY));
|
||||
|
@ -14,6 +14,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.PMD.StatusCode;
|
||||
import net.sourceforge.pmd.cli.BaseCLITest;
|
||||
|
||||
public class XmlCliTest extends BaseCLITest {
|
||||
@ -36,19 +37,19 @@ public class XmlCliTest extends BaseCLITest {
|
||||
|
||||
@Test
|
||||
public void analyzeSingleXmlWithoutForceLanguage() {
|
||||
String log = runTest(0, createArgs("/src/file1.ext"));
|
||||
String log = runTest(StatusCode.OK, createArgs("/src/file1.ext"));
|
||||
assertRuleMessage(0, log);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void analyzeSingleXmlWithForceLanguage() {
|
||||
String log = runTest(4, createArgs("/src/file1.ext", "-force-language", "xml"));
|
||||
String log = runTest(StatusCode.VIOLATIONS_FOUND, createArgs("/src/file1.ext", "-force-language", "xml"));
|
||||
assertRuleMessage(1, log);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void analyzeDirectoryWithForceLanguage() {
|
||||
String log = runTest(4, createArgs("/src/", "-force-language", "xml"));
|
||||
String log = runTest(StatusCode.VIOLATIONS_FOUND, createArgs("/src/", "-force-language", "xml"));
|
||||
assertRuleMessage(3, log);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user