forked from phoedos/pmd
Merge branch '7.0.x' into clem.pmd7-cpd-deprecations
This commit is contained in:
@@ -262,6 +262,10 @@
|
||||
<groupId>info.picocli</groupId>
|
||||
<artifactId>picocli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.tongfei</groupId>
|
||||
<artifactId>progressbar</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
|
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package me.tongfei.progressbar;
|
||||
|
||||
import static me.tongfei.progressbar.TerminalUtils.CARRIAGE_RETURN;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This is a friend class for me.tongfei.progressbar, as TerminalUtils is package-private.
|
||||
*/
|
||||
public final class PmdProgressBarFriend {
|
||||
|
||||
private PmdProgressBarFriend() {
|
||||
throw new AssertionError("Can't instantiate utility classes");
|
||||
}
|
||||
|
||||
public static ConsoleProgressBarConsumer createConsoleConsumer(PrintStream ps) {
|
||||
return TerminalUtils.hasCursorMovementSupport()
|
||||
? new InteractiveConsoleProgressBarConsumer(ps)
|
||||
: new PostCarriageReturnConsoleProgressBarConsumer(ps);
|
||||
}
|
||||
|
||||
private static class PostCarriageReturnConsoleProgressBarConsumer extends ConsoleProgressBarConsumer {
|
||||
|
||||
PostCarriageReturnConsoleProgressBarConsumer(PrintStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(String str) {
|
||||
// Set the carriage return at the end instead of at the beginning
|
||||
out.print(StringDisplayUtils.trimDisplayLength(str, getMaxRenderedLength()) + CARRIAGE_RETURN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
// do nothing (prints an empty line otherwise)
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,8 +14,8 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.PmdAnalysis;
|
||||
@@ -27,6 +27,7 @@ import net.sourceforge.pmd.benchmark.TimingReportRenderer;
|
||||
import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageTypeSupport;
|
||||
import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageVersionTypeSupport;
|
||||
import net.sourceforge.pmd.cli.internal.CliExitCode;
|
||||
import net.sourceforge.pmd.cli.internal.ProgressBarListener;
|
||||
import net.sourceforge.pmd.internal.LogMessages;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.LanguageVersion;
|
||||
@@ -45,6 +46,7 @@ import picocli.CommandLine.ParameterException;
|
||||
@Command(name = "check", showDefaultValues = true,
|
||||
description = "The PMD standard source code analyzer")
|
||||
public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PmdCommand.class);
|
||||
|
||||
static {
|
||||
final Properties emptyProps = new Properties();
|
||||
@@ -279,7 +281,6 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
configuration.setFailOnViolation(failOnViolation);
|
||||
configuration.setAnalysisCacheLocation(cacheLocation != null ? cacheLocation.toString() : null);
|
||||
configuration.setIgnoreIncrementalAnalysis(noCache);
|
||||
configuration.setProgressBar(showProgressBar);
|
||||
|
||||
if (languageVersion != null) {
|
||||
configuration.setDefaultLanguageVersions(languageVersion);
|
||||
@@ -322,7 +323,17 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
return CliExitCode.ERROR;
|
||||
}
|
||||
|
||||
pmdReporter.log(Level.DEBUG, "Current classpath:\n{0}", System.getProperty("java.class.path"));
|
||||
LOG.debug("Current classpath:\n{}", System.getProperty("java.class.path"));
|
||||
|
||||
if (showProgressBar) {
|
||||
if (reportFile == null) {
|
||||
pmdReporter.warn("Progressbar rendering conflicts with reporting to STDOUT. "
|
||||
+ "No progressbar will be shown. Try running with argument '-r <file>' to output the report to a file instead.");
|
||||
} else {
|
||||
pmd.addListener(new ProgressBarListener());
|
||||
}
|
||||
}
|
||||
|
||||
final ReportStats stats = pmd.runAndReturnStats();
|
||||
if (pmdReporter.numErrors() > 0) {
|
||||
// processing errors are ignored
|
||||
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.cli.internal;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.sourceforge.pmd.Report;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
import net.sourceforge.pmd.lang.document.TextFile;
|
||||
import net.sourceforge.pmd.reporting.FileAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.ListenerInitializer;
|
||||
|
||||
import me.tongfei.progressbar.PmdProgressBarFriend;
|
||||
import me.tongfei.progressbar.ProgressBar;
|
||||
import me.tongfei.progressbar.ProgressBarBuilder;
|
||||
import me.tongfei.progressbar.ProgressBarStyle;
|
||||
|
||||
/**
|
||||
* Collects runtime analysis statistics and displays them live on command line output.
|
||||
* Toggled off through --no-progress command line argument.
|
||||
*/
|
||||
public final class ProgressBarListener implements GlobalAnalysisListener {
|
||||
private ProgressBar progressBar;
|
||||
private final AtomicInteger numErrors = new AtomicInteger(0);
|
||||
private final AtomicInteger numViolations = new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public ListenerInitializer initializer() {
|
||||
return new ListenerInitializer() {
|
||||
@Override
|
||||
public void setNumberOfFilesToAnalyze(int totalFiles) {
|
||||
// We need to delay initialization until we know how many files there are to avoid a first bogus render
|
||||
progressBar = new ProgressBarBuilder()
|
||||
.setTaskName("Processing files")
|
||||
.setStyle(ProgressBarStyle.ASCII)
|
||||
.hideEta()
|
||||
.continuousUpdate()
|
||||
.setInitialMax(totalFiles)
|
||||
.setConsumer(PmdProgressBarFriend.createConsoleConsumer(System.out))
|
||||
.clearDisplayOnFinish()
|
||||
.build();
|
||||
progressBar.setExtraMessage(extraMessage());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates progress bar string and forces it to be output regardless of its update interval.
|
||||
*/
|
||||
private void refreshProgressBar() {
|
||||
progressBar.setExtraMessage(extraMessage());
|
||||
progressBar.refresh();
|
||||
}
|
||||
|
||||
private String extraMessage() {
|
||||
return String.format("Violations:%d, Errors:%d", numViolations.get(), numErrors.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileAnalysisListener startFileAnalysis(TextFile file) {
|
||||
return new FileAnalysisListener() {
|
||||
@Override
|
||||
public void onRuleViolation(RuleViolation violation) {
|
||||
ProgressBarListener.this.numViolations.addAndGet(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuppressedRuleViolation(Report.SuppressedViolation violation) {
|
||||
/*Not handled*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Report.ProcessingError error) {
|
||||
ProgressBarListener.this.numErrors.addAndGet(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Refresh progress bar on file analysis end (or file was in cache)
|
||||
progressBar.step();
|
||||
refreshProgressBar();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
progressBar.close();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user