Merge branch 'analysis-listener' into text-utils-simple

This commit is contained in:
Clément Fournier
2020-11-15 21:19:15 +01:00
21 changed files with 107 additions and 81 deletions

View File

@ -76,7 +76,10 @@ public final class PMD {
// Load the RuleSets
final RuleSetLoader ruleSetFactory = RuleSetLoader.fromPmdConfig(configuration);
final List<RuleSet> ruleSets;
try (TimedOperation ignored = TimeTracker.startOperation(TimedOperationCategory.LOAD_RULES)) {
ruleSets;
try (TimedOperation ignored = TimeTracker.startOperation(TimedOperationCategory.LOAD_RULES)) {
ruleSets = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), ruleSetFactory);
}

View File

@ -69,7 +69,7 @@ public final class RuleContext {
Objects.requireNonNull(message, "Message was null");
Objects.requireNonNull(formatArgs, "Format arguments were null, use an empty array");
RuleViolationFactory fact = node.getLanguageVersion().getLanguageVersionHandler().getRuleViolationFactory();
RuleViolationFactory fact = node.getAstInfo().getLanguageVersion().getLanguageVersionHandler().getRuleViolationFactory();
FileLocation location = node.getReportLocation();

View File

@ -185,7 +185,7 @@ public final class RuleSetLoader {
public List<RuleSet> getStandardRuleSets() throws RuleSetNotFoundException {
String rulesetsProperties;
List<RuleSetReferenceId> ruleSetReferenceIds = new ArrayList<>();
for (Language language : LanguageRegistry.findWithRuleSupport()) {
for (Language language : LanguageRegistry.getLanguages()) {
Properties props = new Properties();
rulesetsProperties = "category/" + language.getTerseName() + "/categories.properties";
try (InputStream inputStream = resourceLoader.loadClassPathResourceAsStreamOrThrow(rulesetsProperties)) {
@ -202,6 +202,6 @@ public final class RuleSetLoader {
+ System.getProperty("java.class.path"), ioe);
}
}
return toFactory().createRuleSets(ruleSetReferenceIds).getRuleSetsInternal();
return toFactory().createRuleSets(ruleSetReferenceIds);
}
}

View File

@ -4,6 +4,8 @@
package net.sourceforge.pmd.ant.internal;
import static java.util.Arrays.asList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -23,11 +25,8 @@ import net.sourceforge.pmd.PMDConfiguration;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RulePriority;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.RuleSetLoader;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.RulesetsFactoryUtils;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.ant.Formatter;
import net.sourceforge.pmd.ant.PMDTask;
import net.sourceforge.pmd.ant.SourceLanguage;
@ -40,7 +39,6 @@ import net.sourceforge.pmd.reporting.GlobalAnalysisListener.ViolationCounterList
import net.sourceforge.pmd.util.ClasspathClassLoader;
import net.sourceforge.pmd.util.FileUtil;
import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.ResourceLoader;
import net.sourceforge.pmd.util.document.TextFile;
import net.sourceforge.pmd.util.log.AntLogHandler;
import net.sourceforge.pmd.util.log.ScopedLogHandlersManager;
@ -112,7 +110,8 @@ public class PMDTaskImpl {
// Substitute env variables/properties
configuration.setRuleSets(project.replaceProperties(ruleSets));
}
rules = ruleSetFactory.createRuleSets(configuration.getRuleSets());
List<String> paths = asList(configuration.getRuleSets().split(","));
rules = rulesetLoader.loadFromResources(paths);
logRulesUsed(rules);
} catch (RuleSetNotFoundException e) {
throw new BuildException(e.getMessage(), e);
@ -201,7 +200,7 @@ public class PMDTaskImpl {
};
}
private ResourceLoader setupResourceLoader() {
private ClassLoader setupResourceLoader() {
if (classpath == null) {
classpath = new Path(project);
}
@ -218,8 +217,8 @@ public class PMDTaskImpl {
// are loaded twice
// and exist in multiple class loaders
final boolean parentFirst = true;
return new ResourceLoader(new AntClassLoader(Thread.currentThread().getContextClassLoader(),
project, classpath, parentFirst));
return new AntClassLoader(Thread.currentThread().getContextClassLoader(),
project, classpath, parentFirst);
}
private void setupClassLoader() {

View File

@ -54,7 +54,7 @@ public class RuleApplicator {
Iterator<? extends Node> targets = rule.getTargetSelector().getVisitedNodes(idx);
while (targets.hasNext()) {
Node node = targets.next();
if (!RuleSet.applies(rule, node.getLanguageVersion())) {
if (!RuleSet.applies(rule, node.getTextDocument().getLanguageVersion())) {
continue;
}
@ -62,7 +62,7 @@ public class RuleApplicator {
rule.apply(node, ctx);
rcto.close(1);
} catch (RuntimeException | StackOverflowError | AssertionError e) {
if (e instanceof Error && !SystemProps.isErrorRecoveryMode()) {
if (e instanceof Error && !SystemProps.isErrorRecoveryMode()) { // NOPMD
throw e;
}
// The listener handles logging if needed,

View File

@ -25,12 +25,7 @@ final class MonoThreadProcessor extends AbstractPMDProcessor {
@SuppressWarnings("PMD.CloseResource") // closed by the PMDRunnable
public void processFiles(RuleSets rulesets, List<TextFile> files, GlobalAnalysisListener listener) {
for (TextFile file : files) {
new PmdRunnable(file, listener, configuration) {
@Override
protected RuleSets getRulesets() {
return rulesets;
}
}.run();
new MonothreadRunnable(rulesets, file, listener, configuration).run();
}
}
@ -38,4 +33,19 @@ final class MonoThreadProcessor extends AbstractPMDProcessor {
public void close() {
// nothing to do
}
static final class MonothreadRunnable extends PmdRunnable {
private final RuleSets ruleSets;
MonothreadRunnable(RuleSets ruleSets, DataSource dataSource, GlobalAnalysisListener ruleContext, PMDConfiguration configuration) {
super(dataSource, ruleContext, configuration);
this.ruleSets = ruleSets;
}
@Override
protected RuleSets getRulesets() {
return ruleSets;
}
}
}

View File

@ -14,10 +14,9 @@ import net.sourceforge.pmd.benchmark.TimedOperationCategory;
import net.sourceforge.pmd.cache.AnalysisCache;
import net.sourceforge.pmd.internal.RulesetStageDependencyHelper;
import net.sourceforge.pmd.internal.SystemProps;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.Parser;
import net.sourceforge.pmd.lang.Parser.ParserTask;
import net.sourceforge.pmd.lang.ast.FileAnalysisException;
import net.sourceforge.pmd.lang.ast.Parser;
import net.sourceforge.pmd.lang.ast.Parser.ParserTask;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.ast.SemanticErrorReporter;
import net.sourceforge.pmd.reporting.FileAnalysisListener;
@ -75,7 +74,7 @@ abstract class PmdRunnable implements Runnable {
try {
processSource(listener, textDocument, ruleSets);
} catch (Exception | StackOverflowError | AssertionError e) {
if (e instanceof Error && !SystemProps.isErrorRecoveryMode()) {
if (e instanceof Error && !SystemProps.isErrorRecoveryMode()) { // NOPMD:
throw e;
}
analysisCache.analysisFailed(textDocument);
@ -90,7 +89,7 @@ abstract class PmdRunnable implements Runnable {
} catch (FileAnalysisException e) {
throw e; // bubble managed exceptions, they were already reported
} catch (Exception e) {
throw FileAnalysisException.wrap(textFile.getDisplayName(), "Exception while closing listener", e);
throw FileAnalysisException.wrap(textFile.getDisplayName(), "An unknown exception occurred", e);
}
TimeTracker.finishThread();

View File

@ -0,0 +1,12 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
/**
* Logic about reporting: violations, suppression etc.
*
* <p>TODO move {@link net.sourceforge.pmd.Report}, {@link net.sourceforge.pmd.RuleViolation},
* {@link net.sourceforge.pmd.RuleContext}, {@link net.sourceforge.pmd.ViolationSuppressor},
* {@link net.sourceforge.pmd.lang.rule.RuleViolationFactory} into this package
*/
package net.sourceforge.pmd.reporting;

View File

@ -70,7 +70,7 @@ public class AbstractRuleTest {
public void testCreateRV() {
MyRule r = new MyRule();
r.setRuleSetName("foo");
DummyNode s = new DummyNode().withFileName("filename");
DummyNode s = new DummyRoot().withFileName("filename");
s.setCoords(5, 5, 5, 10);
RuleViolation rv = new ParametricRuleViolation(r, s, r.getMessage());
assertEquals("Line number mismatch!", 5, rv.getBeginLine());
@ -83,7 +83,7 @@ public class AbstractRuleTest {
@Test
public void testCreateRV2() {
MyRule r = new MyRule();
DummyNode s = new DummyNode().withFileName("filename");
DummyNode s = new DummyRoot().withFileName("filename");
s.setCoords(5, 5, 5, 10);
RuleViolation rv = new ParametricRuleViolation(r, s, "specificdescription");
assertEquals("Line number mismatch!", 5, rv.getBeginLine());

View File

@ -65,8 +65,8 @@ public class ReportTest {
}
private static DummyNode getNode(int line, int column) {
DummyNode s = new DummyRoot();
DummyNode parent = new DummyNode();
DummyNode parent = new DummyRoot();
DummyNode s = new DummyNode();
parent.setCoords(line, column, line, column + 1);
parent.addChild(s, 0);
s.setCoords(line, column, line, column + 1);

View File

@ -16,6 +16,7 @@ import java.util.Random;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyRoot;
import net.sourceforge.pmd.lang.rule.MockRule;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
@ -69,7 +70,7 @@ public class RuleViolationComparatorTest {
private RuleViolation createJavaRuleViolation(Rule rule, String fileName, int beginLine, String description,
int beginColumn, int endLine, int endColumn) {
DummyNode simpleNode = new DummyNode().withFileName(fileName);
DummyNode simpleNode = new DummyRoot().withFileName(fileName);
simpleNode.setCoords(beginLine, beginColumn, endLine, endColumn);
return new ParametricRuleViolation(rule, simpleNode, description);
}

View File

@ -13,6 +13,7 @@ import org.junit.Ignore;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyRoot;
import net.sourceforge.pmd.lang.rule.MockRule;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
@ -23,7 +24,7 @@ public class RuleViolationTest {
@Test
public void testConstructor1() {
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
DummyNode s = new DummyNode().withFileName("filename");
DummyNode s = new DummyRoot().withFileName("filename");
s.setCoords(2, 1, 2, 3);
RuleViolation r = new ParametricRuleViolation(rule, s, rule.getMessage());
assertEquals("object mismatch", rule, r.getRule());
@ -34,7 +35,7 @@ public class RuleViolationTest {
@Test
public void testConstructor2() {
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
DummyNode s = new DummyNode().withFileName("filename");
DummyNode s = new DummyRoot().withFileName("filename");
s.setCoords(2, 1, 2, 3);
RuleViolation r = new ParametricRuleViolation(rule, s, "description");
assertEquals("object mismatch", rule, r.getRule());
@ -47,10 +48,10 @@ public class RuleViolationTest {
public void testComparatorWithDifferentFilenames() {
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
Comparator<RuleViolation> comp = RuleViolation.DEFAULT_COMPARATOR;
DummyNode s = new DummyNode().withFileName("filename1");
DummyNode s = new DummyRoot().withFileName("filename1");
s.setCoords(10, 1, 11, 3);
RuleViolation r1 = new ParametricRuleViolation(rule, s, "description");
DummyNode s1 = new DummyNode().withFileName("filename2");
DummyNode s1 = new DummyRoot().withFileName("filename2");
s1.setCoords(10, 1, 11, 3);
RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description");
assertEquals(-1, comp.compare(r1, r2));
@ -61,9 +62,9 @@ public class RuleViolationTest {
public void testComparatorWithSameFileDifferentLines() {
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
Comparator<RuleViolation> comp = RuleViolation.DEFAULT_COMPARATOR;
DummyNode s = new DummyNode().withFileName("filename1");
DummyNode s = new DummyRoot().withFileName("filename1");
s.setCoords(10, 1, 15, 10);
DummyNode s1 = new DummyNode().withFileName("filename1");
DummyNode s1 = new DummyRoot().withFileName("filename1");
s1.setCoords(20, 1, 25, 10);
RuleViolation r1 = new ParametricRuleViolation(rule, s, "description");
RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description");

View File

@ -59,7 +59,7 @@ public class DummyLanguageModule extends BaseLanguageModule {
public static class HandlerWithParserThatThrows extends Handler {
@Override
public Parser getParser(ParserOptions parserOptions) {
return task -> {
return task -> {
throw new AssertionError("test error while parsing");
};
}

View File

@ -95,7 +95,7 @@ public class DummyNode extends AbstractNode<DummyNode, DummyNode> implements Gen
public DummyNode withFileName(String filename) {
((DummyRoot) getRoot()).withFileName(filename);
return null;
return this;
}
public static class DummyNodeTypeB extends DummyNode {

View File

@ -2,11 +2,7 @@
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
package net.sourceforge.pmd.processor;
import org.junit.Assert;
import org.junit.Before;
@ -14,6 +10,13 @@ import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.rules.TestRule;
import net.sourceforge.pmd.PMDConfiguration;
import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Report.GlobalReportBuilderListener;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSets;
import net.sourceforge.pmd.internal.SystemProps;
import net.sourceforge.pmd.lang.DummyLanguageModule;
import net.sourceforge.pmd.lang.Language;
@ -21,72 +24,73 @@ import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.AbstractRule;
import net.sourceforge.pmd.processor.MonoThreadProcessor.MonothreadRunnable;
import net.sourceforge.pmd.util.datasource.DataSource;
public class SourceCodeProcessorTest {
public class PmdRunnableTest {
@org.junit.Rule
public TestRule restoreSystemProperties = new RestoreSystemProperties();
private SourceCodeProcessor processor;
private StringReader sourceCode;
private RuleContext ctx;
private List<RuleSet> rulesets;
private LanguageVersion dummyThrows;
private LanguageVersion dummyDefault;
private PMDConfiguration configuration;
private PmdRunnable pmdRunnable;
private GlobalReportBuilderListener reportBuilder;
@Before
public void prepare() {
Language dummyLanguage = LanguageRegistry.findLanguageByTerseName(DummyLanguageModule.TERSE_NAME);
dummyDefault = dummyLanguage.getDefaultVersion();
dummyThrows = dummyLanguage.getVersion("1.9-throws");
DataSource dataSource = DataSource.forString("test", "test.dummy");
processor = new SourceCodeProcessor(new PMDConfiguration());
sourceCode = new StringReader("test");
Rule rule = new RuleThatThrows();
rulesets = Arrays.asList(RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule));
configuration = new PMDConfiguration();
reportBuilder = new GlobalReportBuilderListener();
pmdRunnable = new MonothreadRunnable(new RuleSets(RuleSet.forSingleRule(rule)),
dataSource,
reportBuilder,
configuration);
ctx = new RuleContext();
}
@Test
public void inErrorRecoveryModeErrorsShouldBeLoggedByParser() {
System.setProperty(SystemProps.PMD_ERROR_RECOVERY, "");
ctx.setLanguageVersion(dummyThrows);
configuration.setDefaultLanguageVersion(dummyThrows);
Assert.assertThrows(PMDException.class, () -> {
processor.processSourceCode(sourceCode, new RuleSets(rulesets), ctx);
});
// the error is actually logged by PmdRunnable
pmdRunnable.run();
reportBuilder.close();
Assert.assertEquals(1, reportBuilder.getResult().getProcessingErrors().size());
}
@Test
public void inErrorRecoveryModeErrorsShouldBeLoggedByRule() throws Exception {
public void inErrorRecoveryModeErrorsShouldBeLoggedByRule() {
System.setProperty(SystemProps.PMD_ERROR_RECOVERY, "");
ctx.setLanguageVersion(dummyDefault);
configuration.setDefaultLanguageVersion(dummyDefault);
processor.processSourceCode(sourceCode, new RuleSets(rulesets), ctx);
Assert.assertEquals(1, ctx.getReport().getProcessingErrors().size());
Assert.assertSame(AssertionError.class, ctx.getReport().getProcessingErrors().get(0).getError().getClass());
pmdRunnable.run();
reportBuilder.close();
Report report = reportBuilder.getResult();
Assert.assertEquals(1, report.getProcessingErrors().size());
Assert.assertSame(AssertionError.class, report.getProcessingErrors().get(0).getError().getClass());
}
@Test
public void withoutErrorRecoveryModeProcessingShouldBeAbortedByParser() {
Assert.assertNull(System.getProperty(SystemProps.PMD_ERROR_RECOVERY));
ctx.setLanguageVersion(dummyThrows);
configuration.setDefaultLanguageVersion(dummyThrows);
Assert.assertThrows(AssertionError.class, () -> {
processor.processSourceCode(sourceCode, new RuleSets(rulesets), ctx);
});
Assert.assertThrows(AssertionError.class, pmdRunnable::run);
}
@Test
public void withoutErrorRecoveryModeProcessingShouldBeAbortedByRule() {
Assert.assertNull(System.getProperty(SystemProps.PMD_ERROR_RECOVERY));
ctx.setLanguageVersion(dummyDefault);
configuration.setDefaultLanguageVersion(dummyDefault);
Assert.assertThrows(AssertionError.class, () -> {
processor.processSourceCode(sourceCode, new RuleSets(rulesets), ctx);
});
Assert.assertThrows(AssertionError.class, pmdRunnable::run);
}
private static class RuleThatThrows extends AbstractRule {

View File

@ -16,6 +16,7 @@ import net.sourceforge.pmd.ReportTest;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.RuleWithProperties;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyRoot;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
public abstract class AbstractRendererTest {
@ -76,7 +77,7 @@ public abstract class AbstractRendererTest {
}
protected DummyNode createNode(int endColumn) {
DummyNode node = new DummyNode().withFileName(getSourceCodeFilename());
DummyNode node = new DummyRoot().withFileName(getSourceCodeFilename());
node.setCoords(1, 1, 1, endColumn);
return node;
}

View File

@ -30,6 +30,7 @@ import net.sourceforge.pmd.Report.ConfigurationError;
import net.sourceforge.pmd.Report.ProcessingError;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyRoot;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
public class XMLRendererTest extends AbstractRendererTest {
@ -89,7 +90,7 @@ public class XMLRendererTest extends AbstractRendererTest {
}
private RuleViolation createRuleViolation(String description) {
DummyNode node = new DummyNode().withFileName(getSourceCodeFilename());
DummyNode node = new DummyRoot().withFileName(getSourceCodeFilename());
node.setCoords(1, 1, 1, 1);
return new ParametricRuleViolation(new FooRule(), node, description);
}

View File

@ -12,6 +12,7 @@ import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.ReportTest;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyRoot;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
public class XSLTRendererTest {
@ -20,7 +21,7 @@ public class XSLTRendererTest {
public void testDefaultStylesheet() throws Exception {
XSLTRenderer renderer = new XSLTRenderer();
Report report = new Report();
DummyNode node = new DummyNode().withFileName("file");
DummyNode node = new DummyRoot().withFileName("file");
node.setCoords(1, 1, 1, 2);
RuleViolation rv = new ParametricRuleViolation(new FooRule(), node, "violation message");
report.addRuleViolation(rv);

View File

@ -23,8 +23,8 @@ import java.util.regex.Pattern;
import org.apache.commons.io.FilenameUtils;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.RuleSetLoader;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;

View File

@ -19,9 +19,7 @@ public final class PmdSwiftParser extends AntlrBaseParser<SwiftNode, SwTopLevel>
@Override
protected SwTopLevel parse(final Lexer lexer, ParserTask task) {
SwiftParser parser = new SwiftParser(new CommonTokenStream(lexer));
SwTopLevel swTopLevel = parser.topLevel().makeAstInfo(task);
swTopLevel.addTaskInfo(task);
return swTopLevel;
return parser.topLevel().makeAstInfo(task);
}
@Override

View File

@ -16,10 +16,6 @@ abstract class SwiftRootNode extends SwiftInnerNode implements RootNode {
private AstInfo<SwTopLevel> astInfo;
SwiftRootNode() {
super();
}
SwiftRootNode(ParserRuleContext parent, int invokingStateNumber) {
super(parent, invokingStateNumber);
}