From 412d39f51384468810e08ffe11ac218138fb2395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 7 Jul 2020 16:09:14 +0200 Subject: [PATCH 01/34] Replace createFactory methods with a builder Deprecate compatibility filter Deprecate methods in RulesetsFactUtils --- .../pmd/lang/apex/DefaultRulesetTest.java | 5 +- .../main/java/net/sourceforge/pmd/PMD.java | 6 +- .../net/sourceforge/pmd/RuleSetFactory.java | 131 +++++++++++++++--- .../pmd/RuleSetFactoryCompatibility.java | 8 ++ .../sourceforge/pmd/RulesetsFactoryUtils.java | 18 ++- .../pmd/ant/internal/PMDTaskImpl.java | 14 +- .../sourceforge/pmd/RuleSetFactoryTest.java | 30 ++-- .../pmd/lang/java/PMD5RulesetTest.java | 5 +- .../pmd/lang/java/QuickstartRulesetTest.java | 5 +- 9 files changed, 167 insertions(+), 55 deletions(-) diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java index 11ef33e0d1..7cf90ce8f6 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java @@ -14,16 +14,15 @@ import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.SystemErrRule; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RulesetsFactoryUtils; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; public class DefaultRulesetTest { @Rule public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests(); - private RuleSetFactory factory = RulesetsFactoryUtils.createFactory(RulePriority.LOW, true, false); + private RuleSetFactory factory = new RuleSetFactoryConfig().enableCompatibility(false).createFactory(); @Test public void loadDefaultRuleset() throws Exception { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 066d2fc935..5a4b864375 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -21,6 +21,7 @@ import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.benchmark.TextTimingReportRenderer; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; @@ -45,7 +46,6 @@ import net.sourceforge.pmd.stat.Metric; 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.database.DBMSMetadata; import net.sourceforge.pmd.util.database.DBURI; import net.sourceforge.pmd.util.database.SourceObject; @@ -203,7 +203,7 @@ public class PMD { public static int doPMD(PMDConfiguration configuration) { // Load the RuleSets - final RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration, new ResourceLoader()); + final RuleSetFactory ruleSetFactory = RuleSetFactoryConfig.fromPmdConfig(configuration).createFactory(); final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory); if (ruleSets == null) { return PMDCommandLineInterface.NO_ERRORS_STATUS; @@ -305,7 +305,7 @@ public class PMD { // Make sure the cache is listening for analysis results ctx.getReport().addListener(configuration.getAnalysisCache()); - final RuleSetFactory silentFactory = new RuleSetFactory(ruleSetFactory, false); + final RuleSetFactory silentFactory = ruleSetFactory.toConfig().warnDeprecated(false).createFactory(); newFileProcessor(configuration).processFiles(silentFactory, files, ctx, renderers); configuration.getAnalysisCache().persist(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 3fef741d9a..e248c3ee86 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -44,11 +44,9 @@ import net.sourceforge.pmd.util.ResourceLoader; /** * RuleSetFactory is responsible for creating RuleSet instances from XML - * content. By default Rules will be loaded using the {@link RulePriority#LOW} priority, - * with Rule deprecation warnings off; - * the ruleset compatibility filter is active, too (see {@link RuleSetFactoryCompatibility}); - * if the ruleset contains rule references (e.g. for renamed or moved rules), these - * are ignored by default. + * content. See {@link RuleSetFactoryConfig} for configuration options and + * their defaults. The constructors of this class are deprecated and their + * usages should be replaced by use of {@link RuleSetFactoryConfig#createFactory()}. */ public class RuleSetFactory { @@ -67,7 +65,7 @@ public class RuleSetFactory { private final Map parsedRulesets = new HashMap<>(); /** - * @deprecated Use {@link RulesetsFactoryUtils#defaultFactory()} + * @deprecated Use a {@link RuleSetFactoryConfig} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory() { @@ -75,8 +73,7 @@ public class RuleSetFactory { } /** - * @deprecated Use {@link RulesetsFactoryUtils#createFactory(ClassLoader, RulePriority, boolean, boolean)} - * or {@link RulesetsFactoryUtils#createFactory(RulePriority, boolean, boolean)} + * @deprecated Use a {@link RuleSetFactoryConfig} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory(final ClassLoader classLoader, final RulePriority minimumPriority, @@ -85,8 +82,7 @@ public class RuleSetFactory { } /** - * @deprecated Use {@link RulesetsFactoryUtils#createFactory(ClassLoader, RulePriority, boolean, boolean)} - * or {@link RulesetsFactoryUtils#createFactory(RulePriority, boolean, boolean)} + * @deprecated Use a {@link RuleSetFactoryConfig} to build a new factory */ @Deprecated // to be hidden with PMD 7.0.0. public RuleSetFactory(final ResourceLoader resourceLoader, final RulePriority minimumPriority, @@ -115,12 +111,20 @@ public class RuleSetFactory { * The factory whose configuration to copy. * @param warnDeprecated * Whether deprecation warnings are to be produced by this - * factory. + * factory + * + * @deprecated Use {@link #toConfig()} to rebuild a factory from a configuration */ + @Deprecated public RuleSetFactory(final RuleSetFactory factory, final boolean warnDeprecated) { this(factory.resourceLoader, factory.minimumPriority, warnDeprecated, factory.compatibilityFilter != null); } + + RuleSetFactory(RuleSetFactoryConfig config) { + this(config.resourceLoader, config.minimumPriority, config.warnDeprecated, config.enableCompatibility, config.includeDeprecatedRuleReferences); + } + /** * Gets the compatibility filter in order to adjust it, e.g. add additional * filters. @@ -154,10 +158,9 @@ public class RuleSetFactory { } catch (RuleSetNotFoundException e) { LOG.warning("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); } catch (IOException ioe) { - throw new RuntimeException("Couldn't find " + rulesetsProperties - + "; please ensure that the directory is on the classpath. The current classpath is: " - + System.getProperty("java.class.path")); - } + throw new RuntimeException("Couldn't find " + rulesetsProperties + + "; please ensure that the directory is on the classpath. The current classpath is: " + + System.getProperty("java.class.path"));} } return createRuleSets(ruleSetReferenceIds).getRuleSetsIterator(); } @@ -348,7 +351,8 @@ public class RuleSetFactory { private Rule createRule(RuleSetReferenceId ruleSetReferenceId, boolean withDeprecatedRuleReferences) throws RuleSetNotFoundException { if (ruleSetReferenceId.isAllRules()) { - throw new IllegalArgumentException("Cannot parse a single Rule from an all Rule RuleSet reference: <" + ruleSetReferenceId + ">."); + throw new IllegalArgumentException( + "Cannot parse a single Rule from an all Rule RuleSet reference: <" + ruleSetReferenceId + ">."); } RuleSet ruleSet; // java8: computeIfAbsent @@ -557,7 +561,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = new RuleSetFactory(resourceLoader, RulePriority.LOW, false, this.compatibilityFilter != null); + RuleSetFactory ruleSetFactory = toConfig().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).createFactory(); RuleSet otherRuleSet = ruleSetFactory.createRuleSet(RuleSetReferenceId.parse(ref).get(0)); List potentialRules = new ArrayList<>(); int countDeprecated = 0; @@ -672,7 +676,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = new RuleSetFactory(resourceLoader, RulePriority.LOW, false, this.compatibilityFilter != null); + RuleSetFactory ruleSetFactory = toConfig().warnDeprecated(false).createFactory(); boolean isSameRuleSet = false; RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0); @@ -832,4 +836,95 @@ public class RuleSetFactory { return false; } } + + + public RuleSetFactoryConfig toConfig() { + return new RuleSetFactoryConfig().loadResourcesWith(resourceLoader) + .filterAbovePriority(minimumPriority) + .warnDeprecated(warnDeprecated) + .enableCompatibility(compatibilityFilter != null); + } + + + /** + * Configuration of a {@link RuleSetFactory}. This is a fluent builder + * pattern. Use this instead of the constructors of RuleSetFactory. + */ + public static final class RuleSetFactoryConfig { + + ResourceLoader resourceLoader = new ResourceLoader(RuleSetFactoryConfig.class.getClassLoader()); + RulePriority minimumPriority = RulePriority.LOW; + boolean warnDeprecated = true; + boolean enableCompatibility = true; + boolean includeDeprecatedRuleReferences = false; + + /** + * Specify that the given classloader should be used to resolve + * paths to external ruleset references. The default uses PMD's + * own classpath. + */ + public RuleSetFactoryConfig loadResourcesWith(ClassLoader classLoader) { + this.resourceLoader = new ResourceLoader(classLoader); + return this; + } + + // internal + RuleSetFactoryConfig loadResourcesWith(ResourceLoader loader) { + this.resourceLoader = loader; + return this; + } + + /** + * Filter loaded rules to only those that match or are above + * the given priority. The default is {@link RulePriority#LOW}, + * ie, no filtering occurs. + */ + public RuleSetFactoryConfig filterAbovePriority(RulePriority minimumPriority) { + this.minimumPriority = minimumPriority; + return this; + } + + /** + * Log a warning when referencing a deprecated rule. + * This is enabled by default. + */ + public RuleSetFactoryConfig warnDeprecated(boolean warn) { + this.warnDeprecated = warn; + return this; + } + + /** + * Enable translating old rule references to newer ones, if they have + * been moved or renamed. This is enabled by default, if disabled, + * unresolved references will not be translated and will produce an + * error. + */ + public RuleSetFactoryConfig enableCompatibility(boolean enable) { + this.enableCompatibility = enable; + return this; + } + + /** + * Follow deprecated rule references. By default this is off, + * and those references will be ignored (with a warning depending + * on {@link #enableCompatibility(boolean)}). + */ + public RuleSetFactoryConfig includeDeprecatedRuleReferences(boolean enable) { + this.includeDeprecatedRuleReferences = enable; + return this; + } + + public RuleSetFactory createFactory() { + return new RuleSetFactory(this); + } + + /** + * Configure a new ruleset factory builder according to the parameters + * of the given PMD configuration. + */ + public static RuleSetFactoryConfig fromPmdConfig(PMDConfiguration configuration) { + return new RuleSetFactoryConfig().filterAbovePriority(configuration.getMinimumPriority()) + .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java index cd933218fd..a0008ab3b4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java @@ -18,13 +18,21 @@ import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; +import net.sourceforge.pmd.annotation.InternalApi; + /** * Provides a simple filter mechanism to avoid failing to parse an old ruleset, * which references rules, that have either been removed from PMD already or * renamed or moved to another ruleset. * * @see issue 1360 + * + * @deprecated Use {@link RuleSetFactoryConfig#enableCompatibility(boolean)} to enable this feature. + * This implementation is internal API. */ +@InternalApi +@Deprecated public class RuleSetFactoryCompatibility { private static final Logger LOG = Logger.getLogger(RuleSetFactoryCompatibility.class.getName()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java index 69a1ff066c..609c7b6549 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd; import java.util.logging.Level; import java.util.logging.Logger; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; @@ -76,7 +77,7 @@ public final class RulesetsFactoryUtils { } /** - * @deprecated Use {@link #createFactory(PMDConfiguration)} or {@link #createFactory(PMDConfiguration, ClassLoader)} + * @deprecated Use a {@link RuleSetFactoryConfig} */ @InternalApi @Deprecated @@ -96,7 +97,10 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration, ClassLoader) + * + * @deprecated Use {@link RuleSetFactoryConfig#fromPmdConfig(PMDConfiguration)} */ + @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration) { return createFactory(configuration, RulesetsFactoryUtils.class.getClassLoader()); } @@ -107,7 +111,7 @@ public final class RulesetsFactoryUtils { * * @return A ruleset factory * - * @see #createFactory(PMDConfiguration, ClassLoader) + * @see RuleSetFactoryConfig */ public static RuleSetFactory defaultFactory() { return new RuleSetFactory(); @@ -124,7 +128,10 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * + * @deprecated Use a {@link RuleSetFactoryConfig} */ + @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration, ClassLoader classLoader) { return createFactory(classLoader, configuration.getMinimumPriority(), @@ -145,7 +152,10 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * + * @deprecated Use a {@link RuleSetFactoryConfig} */ + @Deprecated public static RuleSetFactory createFactory(ClassLoader classLoader, RulePriority minimumPriority, boolean warnDeprecated, @@ -166,11 +176,13 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * + * @deprecated Use a {@link RuleSetFactoryConfig} */ + @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, boolean warnDeprecated, boolean enableCompatibility) { - return new RuleSetFactory(new ResourceLoader(), minimumPriority, warnDeprecated, enableCompatibility); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index f78d78b8b9..0abe673de8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -29,9 +29,9 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RuleSets; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.ant.Formatter; import net.sourceforge.pmd.ant.PMDTask; import net.sourceforge.pmd.ant.SourceLanguage; @@ -41,7 +41,6 @@ import net.sourceforge.pmd.renderers.AbstractRenderer; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.util.ClasspathClassLoader; import net.sourceforge.pmd.util.IOUtil; -import net.sourceforge.pmd.util.ResourceLoader; import net.sourceforge.pmd.util.datasource.DataSource; import net.sourceforge.pmd.util.datasource.FileDataSource; import net.sourceforge.pmd.util.log.AntLogHandler; @@ -103,8 +102,9 @@ public class PMDTaskImpl { setupClassLoader(); // Setup RuleSetFactory and validate RuleSets - final ResourceLoader rl = setupResourceLoader(); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration, rl); + RuleSetFactory ruleSetFactory = RuleSetFactoryConfig.fromPmdConfig(configuration) + .loadResourcesWith(setupResourceLoader()) + .createFactory(); try { // This is just used to validate and display rules. Each thread will create its own ruleset @@ -216,7 +216,7 @@ public class PMDTaskImpl { } } - private ResourceLoader setupResourceLoader() { + private ClassLoader setupResourceLoader() { if (classpath == null) { classpath = new Path(project); } @@ -233,8 +233,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 handleError(RuleContext ctx, Report errorReport, RuntimeException pmde) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 1732c1f732..840def81e1 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils; import org.junit.Test; import org.junit.rules.ExpectedException; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.junit.JavaUtilLoggingRule; import net.sourceforge.pmd.junit.LocaleRule; import net.sourceforge.pmd.lang.DummyLanguageModule; @@ -505,40 +506,40 @@ public class RuleSetFactoryTest { @Test public void testReferencePriority() throws RuleSetNotFoundException { - ResourceLoader rl = new ResourceLoader(); - RuleSetFactory rsf = new RuleSetFactory(rl, RulePriority.LOW, false, true); + RuleSetFactoryConfig config = new RuleSetFactoryConfig().warnDeprecated(false).enableCompatibility(true); + RuleSetFactory rsf = config.filterAbovePriority(RulePriority.LOW).createFactory(); RuleSet ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); assertEquals("Number of Rules", 3, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("MockRuleName")); assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_HIGH, false, true); + rsf = config.filterAbovePriority(RulePriority.MEDIUM_HIGH).createFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); assertEquals("Number of Rules", 2, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.HIGH, false, true); + rsf = config.filterAbovePriority(RulePriority.HIGH).createFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); assertEquals("Number of Rules", 1, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.LOW, false, true); + rsf = config.filterAbovePriority(RulePriority.LOW).createFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); assertEquals("Number of Rules", 3, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleName")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_HIGH, false, true); + rsf = config.filterAbovePriority(RulePriority.MEDIUM_HIGH).createFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); assertEquals("Number of Rules", 2, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.HIGH, false, true); + rsf = config.filterAbovePriority(RulePriority.HIGH).createFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); assertEquals("Number of Rules", 1, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); @@ -546,7 +547,7 @@ public class RuleSetFactoryTest { @Test public void testOverridePriorityLoadWithMinimum() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetFactory(new ResourceLoader(), RulePriority.MEDIUM_LOW, true, true); + RuleSetFactory rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); // only one rule should remain, since we filter out the other rule by minimum priority assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -567,13 +568,13 @@ public class RuleSetFactoryTest { @Test public void testExcludeWithMinimumPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = RulesetsFactoryUtils.createFactory(RulePriority.HIGH, true, true); + RuleSetFactory rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.HIGH).createFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // no rules should be loaded assertEquals("Number of Rules", 0, ruleset.getRules().size()); // now, load with default minimum priority - rsf = RulesetsFactoryUtils.defaultFactory(); + rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.LOW).createFactory(); ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // only one rule, we have excluded one... assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -602,10 +603,9 @@ public class RuleSetFactoryTest { @Test public void testSetPriority() throws RuleSetNotFoundException { - ResourceLoader rl = new ResourceLoader(); - RuleSetFactory rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_HIGH, false, true); + RuleSetFactory rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).createFactory(); assertEquals(0, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); - rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_LOW, false, true); + rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).createFactory(); assertEquals(1, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); } @@ -780,7 +780,7 @@ public class RuleSetFactoryTest { + " Ruleset which references a empty ruleset\n" + "\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, true); + RuleSetFactory ruleSetFactory = new RuleSetFactoryConfig().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref); assertEquals(0, ruleset.getRules().size()); @@ -1285,7 +1285,7 @@ public class RuleSetFactoryTest { } private RuleSet loadRuleSetWithDeprecationWarnings(String ruleSetXml) throws RuleSetNotFoundException { - RuleSetFactory rsf = RulesetsFactoryUtils.createFactory(RulePriority.LOW, true, false); + RuleSetFactory rsf = new RuleSetFactoryConfig().warnDeprecated(true).enableCompatibility(false).createFactory(); return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml)); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java index 3401199005..135294a762 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java @@ -7,16 +7,15 @@ package net.sourceforge.pmd.lang.java; import org.junit.Assert; import org.junit.Test; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.util.ResourceLoader; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; public class PMD5RulesetTest { @Test public void loadRuleset() throws Exception { - RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, true); + RuleSetFactory ruleSetFactory = new RuleSetFactoryConfig().createFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet("net/sourceforge/pmd/lang/java/pmd5ruleset.xml"); Assert.assertNotNull(ruleset); Assert.assertNull(ruleset.getRuleByName("GuardLogStatementJavaUtil")); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index 816c98b918..fa3bb3f027 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -14,11 +14,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.SystemErrRule; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.RuleSetNotFoundException; -import net.sourceforge.pmd.util.ResourceLoader; public class QuickstartRulesetTest { @@ -50,7 +49,7 @@ public class QuickstartRulesetTest { } }); - RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, false); + RuleSetFactory ruleSetFactory = new RuleSetFactoryConfig().enableCompatibility(false).createFactory(); RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); Assert.assertFalse(quickstart.getRules().isEmpty()); } From ac864aa5294a9caa72827fd8400c8db1337c3897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 19:29:19 +0100 Subject: [PATCH 02/34] Rename --- .../pmd/lang/apex/DefaultRulesetTest.java | 4 +- .../main/java/net/sourceforge/pmd/PMD.java | 3 +- .../net/sourceforge/pmd/RuleSetFactory.java | 103 ++---------------- .../pmd/RuleSetFactoryCompatibility.java | 3 +- .../sourceforge/pmd/RuleSetParserConfig.java | 96 ++++++++++++++++ .../sourceforge/pmd/RulesetsFactoryUtils.java | 13 +-- .../pmd/ant/internal/PMDTaskImpl.java | 8 +- .../sourceforge/pmd/RuleSetFactoryTest.java | 17 ++- .../pmd/lang/java/PMD5RulesetTest.java | 4 +- .../pmd/lang/java/QuickstartRulesetTest.java | 4 +- .../lang/scala/ast/ScalaParsingHelper.java | 4 +- 11 files changed, 135 insertions(+), 124 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java index 7cf90ce8f6..c2d76f7d1f 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java @@ -16,13 +16,13 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; +import net.sourceforge.pmd.RuleSetParserConfig; public class DefaultRulesetTest { @Rule public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests(); - private RuleSetFactory factory = new RuleSetFactoryConfig().enableCompatibility(false).createFactory(); + private RuleSetFactory factory = new RuleSetParserConfig().enableCompatibility(false).createFactory(); @Test public void loadDefaultRuleset() throws Exception { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 5a4b864375..c7aaf5877e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -21,7 +21,6 @@ import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.benchmark.TextTimingReportRenderer; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; @@ -203,7 +202,7 @@ public class PMD { public static int doPMD(PMDConfiguration configuration) { // Load the RuleSets - final RuleSetFactory ruleSetFactory = RuleSetFactoryConfig.fromPmdConfig(configuration).createFactory(); + final RuleSetFactory ruleSetFactory = RuleSetParserConfig.fromPmdConfig(configuration).createFactory(); final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory); if (ruleSets == null) { return PMDCommandLineInterface.NO_ERRORS_STATUS; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index e248c3ee86..6163e96c89 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -44,9 +44,9 @@ import net.sourceforge.pmd.util.ResourceLoader; /** * RuleSetFactory is responsible for creating RuleSet instances from XML - * content. See {@link RuleSetFactoryConfig} for configuration options and + * content. See {@link RuleSetParserConfig} for configuration options and * their defaults. The constructors of this class are deprecated and their - * usages should be replaced by use of {@link RuleSetFactoryConfig#createFactory()}. + * usages should be replaced by use of {@link RuleSetParserConfig#createFactory()}. */ public class RuleSetFactory { @@ -65,7 +65,7 @@ public class RuleSetFactory { private final Map parsedRulesets = new HashMap<>(); /** - * @deprecated Use a {@link RuleSetFactoryConfig} to build a new factory + * @deprecated Use a {@link RuleSetParserConfig} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory() { @@ -73,7 +73,7 @@ public class RuleSetFactory { } /** - * @deprecated Use a {@link RuleSetFactoryConfig} to build a new factory + * @deprecated Use a {@link RuleSetParserConfig} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory(final ClassLoader classLoader, final RulePriority minimumPriority, @@ -82,7 +82,7 @@ public class RuleSetFactory { } /** - * @deprecated Use a {@link RuleSetFactoryConfig} to build a new factory + * @deprecated Use a {@link RuleSetParserConfig} to build a new factory */ @Deprecated // to be hidden with PMD 7.0.0. public RuleSetFactory(final ResourceLoader resourceLoader, final RulePriority minimumPriority, @@ -121,7 +121,7 @@ public class RuleSetFactory { } - RuleSetFactory(RuleSetFactoryConfig config) { + RuleSetFactory(RuleSetParserConfig config) { this(config.resourceLoader, config.minimumPriority, config.warnDeprecated, config.enableCompatibility, config.includeDeprecatedRuleReferences); } @@ -838,93 +838,12 @@ public class RuleSetFactory { } - public RuleSetFactoryConfig toConfig() { - return new RuleSetFactoryConfig().loadResourcesWith(resourceLoader) - .filterAbovePriority(minimumPriority) - .warnDeprecated(warnDeprecated) - .enableCompatibility(compatibilityFilter != null); + public RuleSetParserConfig toConfig() { + return new RuleSetParserConfig().loadResourcesWith(resourceLoader) + .filterAbovePriority(minimumPriority) + .warnDeprecated(warnDeprecated) + .enableCompatibility(compatibilityFilter != null); } - /** - * Configuration of a {@link RuleSetFactory}. This is a fluent builder - * pattern. Use this instead of the constructors of RuleSetFactory. - */ - public static final class RuleSetFactoryConfig { - - ResourceLoader resourceLoader = new ResourceLoader(RuleSetFactoryConfig.class.getClassLoader()); - RulePriority minimumPriority = RulePriority.LOW; - boolean warnDeprecated = true; - boolean enableCompatibility = true; - boolean includeDeprecatedRuleReferences = false; - - /** - * Specify that the given classloader should be used to resolve - * paths to external ruleset references. The default uses PMD's - * own classpath. - */ - public RuleSetFactoryConfig loadResourcesWith(ClassLoader classLoader) { - this.resourceLoader = new ResourceLoader(classLoader); - return this; - } - - // internal - RuleSetFactoryConfig loadResourcesWith(ResourceLoader loader) { - this.resourceLoader = loader; - return this; - } - - /** - * Filter loaded rules to only those that match or are above - * the given priority. The default is {@link RulePriority#LOW}, - * ie, no filtering occurs. - */ - public RuleSetFactoryConfig filterAbovePriority(RulePriority minimumPriority) { - this.minimumPriority = minimumPriority; - return this; - } - - /** - * Log a warning when referencing a deprecated rule. - * This is enabled by default. - */ - public RuleSetFactoryConfig warnDeprecated(boolean warn) { - this.warnDeprecated = warn; - return this; - } - - /** - * Enable translating old rule references to newer ones, if they have - * been moved or renamed. This is enabled by default, if disabled, - * unresolved references will not be translated and will produce an - * error. - */ - public RuleSetFactoryConfig enableCompatibility(boolean enable) { - this.enableCompatibility = enable; - return this; - } - - /** - * Follow deprecated rule references. By default this is off, - * and those references will be ignored (with a warning depending - * on {@link #enableCompatibility(boolean)}). - */ - public RuleSetFactoryConfig includeDeprecatedRuleReferences(boolean enable) { - this.includeDeprecatedRuleReferences = enable; - return this; - } - - public RuleSetFactory createFactory() { - return new RuleSetFactory(this); - } - - /** - * Configure a new ruleset factory builder according to the parameters - * of the given PMD configuration. - */ - public static RuleSetFactoryConfig fromPmdConfig(PMDConfiguration configuration) { - return new RuleSetFactoryConfig().filterAbovePriority(configuration.getMinimumPriority()) - .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); - } - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java index a0008ab3b4..26393af8ea 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java @@ -18,7 +18,6 @@ import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.annotation.InternalApi; /** @@ -28,7 +27,7 @@ import net.sourceforge.pmd.annotation.InternalApi; * * @see issue 1360 * - * @deprecated Use {@link RuleSetFactoryConfig#enableCompatibility(boolean)} to enable this feature. + * @deprecated Use {@link RuleSetParserConfig#enableCompatibility(boolean)} to enable this feature. * This implementation is internal API. */ @InternalApi diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java new file mode 100644 index 0000000000..c1b1f6fe15 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java @@ -0,0 +1,96 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +import net.sourceforge.pmd.util.ResourceLoader; + +/** + * Configuration of a {@link RuleSetFactory}. This is a fluent builder + * pattern. Use this instead of the constructors of RuleSetFactory. + */ +public final class RuleSetParserConfig { + + ResourceLoader resourceLoader = new ResourceLoader(RuleSetParserConfig.class.getClassLoader()); + RulePriority minimumPriority = RulePriority.LOW; + boolean warnDeprecated = true; + boolean enableCompatibility = true; + boolean includeDeprecatedRuleReferences = false; + + /** + * Create a new config with the default values. + */ + public RuleSetParserConfig() { + + } + + /** + * Specify that the given classloader should be used to resolve + * paths to external ruleset references. The default uses PMD's + * own classpath. + */ + public RuleSetParserConfig loadResourcesWith(ClassLoader classLoader) { + this.resourceLoader = new ResourceLoader(classLoader); + return this; + } + + // internal + RuleSetParserConfig loadResourcesWith(ResourceLoader loader) { + this.resourceLoader = loader; + return this; + } + + /** + * Filter loaded rules to only those that match or are above + * the given priority. The default is {@link RulePriority#LOW}, + * ie, no filtering occurs. + */ + public RuleSetParserConfig filterAbovePriority(RulePriority minimumPriority) { + this.minimumPriority = minimumPriority; + return this; + } + + /** + * Log a warning when referencing a deprecated rule. + * This is enabled by default. + */ + public RuleSetParserConfig warnDeprecated(boolean warn) { + this.warnDeprecated = warn; + return this; + } + + /** + * Enable translating old rule references to newer ones, if they have + * been moved or renamed. This is enabled by default, if disabled, + * unresolved references will not be translated and will produce an + * error. + */ + public RuleSetParserConfig enableCompatibility(boolean enable) { + this.enableCompatibility = enable; + return this; + } + + /** + * Follow deprecated rule references. By default this is off, + * and those references will be ignored (with a warning depending + * on {@link #enableCompatibility(boolean)}). + */ + public RuleSetParserConfig includeDeprecatedRuleReferences(boolean enable) { + this.includeDeprecatedRuleReferences = enable; + return this; + } + + public RuleSetFactory createFactory() { + return new RuleSetFactory(this); + } + + /** + * Configure a new ruleset factory builder according to the parameters + * of the given PMD configuration. + */ + public static RuleSetParserConfig fromPmdConfig(PMDConfiguration configuration) { + return new RuleSetParserConfig().filterAbovePriority(configuration.getMinimumPriority()) + .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java index 609c7b6549..bba3ef5f55 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd; import java.util.logging.Level; import java.util.logging.Logger; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; @@ -77,7 +76,7 @@ public final class RulesetsFactoryUtils { } /** - * @deprecated Use a {@link RuleSetFactoryConfig} + * @deprecated Use a {@link RuleSetParserConfig} */ @InternalApi @Deprecated @@ -98,7 +97,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration, ClassLoader) * - * @deprecated Use {@link RuleSetFactoryConfig#fromPmdConfig(PMDConfiguration)} + * @deprecated Use {@link RuleSetParserConfig#fromPmdConfig(PMDConfiguration)} */ @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration) { @@ -111,7 +110,7 @@ public final class RulesetsFactoryUtils { * * @return A ruleset factory * - * @see RuleSetFactoryConfig + * @see RuleSetParserConfig */ public static RuleSetFactory defaultFactory() { return new RuleSetFactory(); @@ -129,7 +128,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetFactoryConfig} + * @deprecated Use a {@link RuleSetParserConfig} */ @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration, ClassLoader classLoader) { @@ -153,7 +152,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetFactoryConfig} + * @deprecated Use a {@link RuleSetParserConfig} */ @Deprecated public static RuleSetFactory createFactory(ClassLoader classLoader, @@ -177,7 +176,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetFactoryConfig} + * @deprecated Use a {@link RuleSetParserConfig} */ @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index 0abe673de8..6a8b4750de 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -29,7 +29,7 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; +import net.sourceforge.pmd.RuleSetParserConfig; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.ant.Formatter; @@ -102,9 +102,9 @@ public class PMDTaskImpl { setupClassLoader(); // Setup RuleSetFactory and validate RuleSets - RuleSetFactory ruleSetFactory = RuleSetFactoryConfig.fromPmdConfig(configuration) - .loadResourcesWith(setupResourceLoader()) - .createFactory(); + RuleSetFactory ruleSetFactory = RuleSetParserConfig.fromPmdConfig(configuration) + .loadResourcesWith(setupResourceLoader()) + .createFactory(); try { // This is just used to validate and display rules. Each thread will create its own ruleset diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 840def81e1..75de7f2189 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -23,7 +23,6 @@ import org.apache.commons.lang3.StringUtils; import org.junit.Test; import org.junit.rules.ExpectedException; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; import net.sourceforge.pmd.junit.JavaUtilLoggingRule; import net.sourceforge.pmd.junit.LocaleRule; import net.sourceforge.pmd.lang.DummyLanguageModule; @@ -506,7 +505,7 @@ public class RuleSetFactoryTest { @Test public void testReferencePriority() throws RuleSetNotFoundException { - RuleSetFactoryConfig config = new RuleSetFactoryConfig().warnDeprecated(false).enableCompatibility(true); + RuleSetParserConfig config = new RuleSetParserConfig().warnDeprecated(false).enableCompatibility(true); RuleSetFactory rsf = config.filterAbovePriority(RulePriority.LOW).createFactory(); RuleSet ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); @@ -547,7 +546,7 @@ public class RuleSetFactoryTest { @Test public void testOverridePriorityLoadWithMinimum() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); + RuleSetFactory rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); // only one rule should remain, since we filter out the other rule by minimum priority assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -568,13 +567,13 @@ public class RuleSetFactoryTest { @Test public void testExcludeWithMinimumPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.HIGH).createFactory(); + RuleSetFactory rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.HIGH).createFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // no rules should be loaded assertEquals("Number of Rules", 0, ruleset.getRules().size()); // now, load with default minimum priority - rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.LOW).createFactory(); + rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.LOW).createFactory(); ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // only one rule, we have excluded one... assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -603,9 +602,9 @@ public class RuleSetFactoryTest { @Test public void testSetPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).createFactory(); + RuleSetFactory rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).createFactory(); assertEquals(0, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); - rsf = new RuleSetFactoryConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).createFactory(); + rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).createFactory(); assertEquals(1, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); } @@ -780,7 +779,7 @@ public class RuleSetFactoryTest { + " Ruleset which references a empty ruleset\n" + "\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = new RuleSetFactoryConfig().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParserConfig().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref); assertEquals(0, ruleset.getRules().size()); @@ -1285,7 +1284,7 @@ public class RuleSetFactoryTest { } private RuleSet loadRuleSetWithDeprecationWarnings(String ruleSetXml) throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetFactoryConfig().warnDeprecated(true).enableCompatibility(false).createFactory(); + RuleSetFactory rsf = new RuleSetParserConfig().warnDeprecated(true).enableCompatibility(false).createFactory(); return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml)); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java index 135294a762..7954efdc88 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java @@ -9,13 +9,13 @@ import org.junit.Test; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; +import net.sourceforge.pmd.RuleSetParserConfig; public class PMD5RulesetTest { @Test public void loadRuleset() throws Exception { - RuleSetFactory ruleSetFactory = new RuleSetFactoryConfig().createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParserConfig().createFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet("net/sourceforge/pmd/lang/java/pmd5ruleset.xml"); Assert.assertNotNull(ruleset); Assert.assertNull(ruleset.getRuleByName("GuardLogStatementJavaUtil")); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index fa3bb3f027..2daa2c1c39 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -16,7 +16,7 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetFactory.RuleSetFactoryConfig; +import net.sourceforge.pmd.RuleSetParserConfig; import net.sourceforge.pmd.RuleSetNotFoundException; public class QuickstartRulesetTest { @@ -49,7 +49,7 @@ public class QuickstartRulesetTest { } }); - RuleSetFactory ruleSetFactory = new RuleSetFactoryConfig().enableCompatibility(false).createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParserConfig().enableCompatibility(false).createFactory(); RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); Assert.assertFalse(quickstart.getRules().isEmpty()); } diff --git a/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java b/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java index 1f37f484c7..6c7ac28b46 100644 --- a/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java +++ b/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java @@ -13,8 +13,8 @@ import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSets; +import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; import net.sourceforge.pmd.lang.scala.ScalaLanguageModule; @@ -38,7 +38,7 @@ public final class ScalaParsingHelper extends BaseParsingHelper Date: Mon, 26 Oct 2020 19:31:48 +0100 Subject: [PATCH 03/34] Isolate single rule pattern --- .../java/net/sourceforge/pmd/RuleSet.java | 24 +++++++++++++++++++ .../net/sourceforge/pmd/RuleSetFactory.java | 23 ------------------ .../pmd/benchmark/Benchmarker.java | 2 +- .../pmd/util/designer/Designer.java | 5 ++-- .../java/net/sourceforge/pmd/RuleSetTest.java | 10 ++++---- .../sourceforge/pmd/RuleSetWriterTest.java | 2 +- .../properties/PropertyDescriptorTest.java | 5 ++-- .../net/sourceforge/pmd/ExcludeLinesTest.java | 2 +- .../xpath/XPathMetricFunctionTest.java | 3 +-- .../pmd/lang/java/rule/XPathRuleTest.java | 3 +-- .../pmd/lang/jsp/ast/XPathJspRuleTest.java | 3 +-- .../lang/scala/ast/ScalaParsingHelper.java | 3 +-- .../pmd/testframework/RuleTst.java | 2 +- 13 files changed, 41 insertions(+), 46 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java index c22906166a..3c88301211 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java @@ -28,6 +28,7 @@ import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.RuleReference; +import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.util.filter.Filter; import net.sourceforge.pmd.util.filter.Filters; @@ -100,6 +101,29 @@ public class RuleSet implements ChecksumAware { filter = rs.filter; // filters are immutable, can be shared } + /** + * Creates a new RuleSet containing a single rule. + * + * @param rule The rule being created + * + * @return The newly created RuleSet + */ + public static RuleSet forSingleRule(final Rule rule) { + final long checksum; + if (rule instanceof XPathRule) { + checksum = ((XPathRule) rule).getXPathExpression().hashCode(); + } else { + // TODO : Is this good enough? all properties' values + rule name + checksum = rule.getPropertiesByPropertyDescriptor().values().hashCode() * 31 + rule.getName().hashCode(); + } + + final RuleSetBuilder builder = new RuleSetBuilder(checksum) + .withName(rule.getName()) + .withDescription("RuleSet for " + rule.getName()); + builder.addRule(rule); + return builder.build(); + } + /* package */ static class RuleSetBuilder { public String description; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 6163e96c89..da00e5c7f7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -308,29 +308,6 @@ public class RuleSetFactory { return result; } - /** - * Creates a new RuleSet containing a single rule. - * - * @param rule - * The rule being created - * @return The newly created RuleSet - */ - public RuleSet createSingleRuleRuleSet(final Rule rule) { // TODO make static? - final long checksum; - if (rule instanceof XPathRule) { - checksum = ((XPathRule) rule).getXPathExpression().hashCode(); - } else { - // TODO : Is this good enough? all properties' values + rule name - checksum = rule.getPropertiesByPropertyDescriptor().values().hashCode() * 31 + rule.getName().hashCode(); - } - - final RuleSetBuilder builder = new RuleSetBuilder(checksum) - .withName(rule.getName()) - .withDescription("RuleSet for " + rule.getName()); - builder.addRule(rule); - return builder.build(); - } - /** * Create a Rule from a RuleSet created from a file name resource. The * currently configured ResourceLoader is used. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java index 42baa667b6..89a81b28e0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java @@ -181,7 +181,7 @@ public final class Benchmarker { System.out.println("Starting " + rule.getName()); } - final RuleSet working = factory.createSingleRuleRuleSet(rule); + final RuleSet working = RuleSet.forSingleRule(rule); RuleSets ruleSets = new RuleSets(working); PMDConfiguration config = new PMDConfiguration(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java index 1ece0350ac..588ff6f7ff 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java @@ -103,7 +103,6 @@ import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.lang.LanguageRegistry; @@ -564,7 +563,7 @@ public class Designer implements ClipboardOwner { LanguageVersion languageVersion = getLanguageVersion(); DFAGraphRule dfaGraphRule = languageVersion.getLanguageVersionHandler().getDFAGraphRule(); if (dfaGraphRule != null) { - final RuleSet rs = new RuleSetFactory().createSingleRuleRuleSet(dfaGraphRule); + final RuleSet rs = RuleSet.forSingleRule(dfaGraphRule); RuleContext ctx = new RuleContext(); ctx.setSourceCodeFile(new File("[no filename]." + languageVersion.getLanguage().getExtensions().get(0))); PMDConfiguration config = new PMDConfiguration(); @@ -610,7 +609,7 @@ public class Designer implements ClipboardOwner { xpathRule.setXPath(xpathQueryArea.getText()); xpathRule.setVersion(xpathVersionButtonGroup.getSelection().getActionCommand()); - final RuleSet ruleSet = new RuleSetFactory().createSingleRuleRuleSet(xpathRule); + final RuleSet ruleSet = RuleSet.forSingleRule(xpathRule); RuleSets ruleSets = new RuleSets(ruleSet); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java index 7a275bc011..7c0f5c8813 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java @@ -60,7 +60,7 @@ public class RuleSetTest { public void testNoDFA() { MockRule mock = new MockRule("name", "desc", "msg", "rulesetname"); mock.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)); - RuleSet rs = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(mock); + RuleSet rs = RuleSet.forSingleRule(mock); assertFalse(rs.usesDFA(LanguageRegistry.getLanguage(DummyLanguageModule.NAME))); } @@ -69,7 +69,7 @@ public class RuleSetTest { MockRule mock = new MockRule("name", "desc", "msg", "rulesetname"); mock.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)); mock.setDfa(true); - RuleSet rs = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(mock); + RuleSet rs = RuleSet.forSingleRule(mock); assertTrue(rs.usesDFA(LanguageRegistry.getLanguage(DummyLanguageModule.NAME))); } @@ -88,21 +88,21 @@ public class RuleSetTest { @Test public void testGetRuleByName() { MockRule mock = new MockRule("name", "desc", "msg", "rulesetname"); - RuleSet rs = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(mock); + RuleSet rs = RuleSet.forSingleRule(mock); assertEquals("unable to fetch rule by name", mock, rs.getRuleByName("name")); } @Test public void testGetRuleByName2() { MockRule mock = new MockRule("name", "desc", "msg", "rulesetname"); - RuleSet rs = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(mock); + RuleSet rs = RuleSet.forSingleRule(mock); assertNull("the rule FooRule must not be found!", rs.getRuleByName("FooRule")); } @Test public void testRuleList() { MockRule rule = new MockRule("name", "desc", "msg", "rulesetname"); - RuleSet ruleset = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet ruleset = RuleSet.forSingleRule(rule); assertEquals("Size of RuleSet isn't one.", 1, ruleset.size()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java index d488f30fcc..6f6e1643dc 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java @@ -81,7 +81,7 @@ public class RuleSetWriterTest { ruleRef.setRuleSetReference(ruleSetReference); ruleRef.setName("Foo"); // override the name - RuleSet ruleSet = ruleSetFactory.createSingleRuleRuleSet(ruleRef); + RuleSet ruleSet = RuleSet.forSingleRule(ruleRef); writer.write(ruleSet); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java index bba31ae3dc..7c82a7fa3e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java @@ -30,7 +30,6 @@ import org.junit.rules.ExpectedException; import net.sourceforge.pmd.FooRule; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.properties.constraints.PropertyConstraint; @@ -57,7 +56,7 @@ public class PropertyDescriptorTest { FooRule rule = new FooRule(); rule.definePropertyDescriptor(intProperty); rule.setProperty(intProperty, 1000); - RuleSet ruleSet = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet ruleSet = RuleSet.forSingleRule(rule); List dysfunctional = new ArrayList<>(); ruleSet.removeDysfunctionalRules(dysfunctional); @@ -78,7 +77,7 @@ public class PropertyDescriptorTest { FooRule rule = new FooRule(); rule.definePropertyDescriptor(descriptor); rule.setProperty(descriptor, Collections.singletonList(1000d)); // not in range - RuleSet ruleSet = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet ruleSet = RuleSet.forSingleRule(rule); List dysfunctional = new ArrayList<>(); ruleSet.removeDysfunctionalRules(dysfunctional); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java index 5704ef0951..2d68f04ba7 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java @@ -41,7 +41,7 @@ public class ExcludeLinesTest extends RuleTst { ctx.setReport(r); ctx.setSourceCodeFile(new File("n/a")); ctx.setLanguageVersion(LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getDefaultVersion()); - RuleSet rules = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet rules = RuleSet.forSingleRule(rule); p.getSourceCodeProcessor().processSourceCode(new StringReader(TEST3), new RuleSets(rules), ctx); assertTrue(r.isEmpty()); assertEquals(r.getSuppressedRuleViolations().size(), 1); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java index 2dc75f74cc..1114a434ee 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java @@ -21,7 +21,6 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RuleViolation; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.java.JavaLanguageModule; import net.sourceforge.pmd.lang.java.xpath.MetricFunction; @@ -57,7 +56,7 @@ public class XPathMetricFunctionTest { ctx.setReport(report); ctx.setSourceCodeFile(new File("n/a")); ctx.setIgnoreExceptions(false); // for test, we want immediate exceptions thrown and not collect them - RuleSet rules = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet rules = RuleSet.forSingleRule(rule); p.getSourceCodeProcessor().processSourceCode(new StringReader(code), new RuleSets(rules), ctx); return report.iterator(); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java index 90e01fabe5..e563974933 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java @@ -22,7 +22,6 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RuleViolation; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.Parser; @@ -206,7 +205,7 @@ public class XPathRuleTest extends RuleTst { Report report = new Report(); ctx.setReport(report); ctx.setSourceCodeFile(new File("n/a")); - RuleSet rules = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(r); + RuleSet rules = RuleSet.forSingleRule(r); p.getSourceCodeProcessor().processSourceCode(new StringReader(test), new RuleSets(rules), ctx); return report; } diff --git a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/ast/XPathJspRuleTest.java b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/ast/XPathJspRuleTest.java index 3597fa8496..9f551f3a11 100644 --- a/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/ast/XPathJspRuleTest.java +++ b/pmd-jsp/src/test/java/net/sourceforge/pmd/lang/jsp/ast/XPathJspRuleTest.java @@ -18,7 +18,6 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RuleViolation; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.jsp.JspLanguageModule; import net.sourceforge.pmd.lang.rule.XPathRule; @@ -35,7 +34,7 @@ public class XPathJspRuleTest extends RuleTst { Rule rule = new XPathRule(XPATH_EXPRESSION); rule.setMessage("Test"); rule.setLanguage(LanguageRegistry.getLanguage(JspLanguageModule.NAME)); - RuleSet rules = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet rules = RuleSet.forSingleRule(rule); RuleContext ctx = new RuleContext(); Report report = new Report(); diff --git a/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java b/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java index 6c7ac28b46..984277dd0a 100644 --- a/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java +++ b/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/ast/ScalaParsingHelper.java @@ -14,7 +14,6 @@ import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSets; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; import net.sourceforge.pmd.lang.scala.ScalaLanguageModule; @@ -38,7 +37,7 @@ public final class ScalaParsingHelper extends BaseParsingHelper Date: Mon, 26 Oct 2020 19:47:42 +0100 Subject: [PATCH 04/34] Deprecate other APIs --- .../pmd/lang/apex/DefaultRulesetTest.java | 4 +- .../main/java/net/sourceforge/pmd/PMD.java | 2 +- .../java/net/sourceforge/pmd/RuleSet.java | 64 ++++++++- .../net/sourceforge/pmd/RuleSetFactory.java | 74 +++++++--- .../pmd/RuleSetFactoryCompatibility.java | 2 +- .../net/sourceforge/pmd/RuleSetParser.java | 131 ++++++++++++++++++ .../sourceforge/pmd/RuleSetParserConfig.java | 96 ------------- .../sourceforge/pmd/RuleSetReferenceId.java | 5 + .../java/net/sourceforge/pmd/RuleSets.java | 18 ++- .../sourceforge/pmd/RulesetsFactoryUtils.java | 20 ++- .../pmd/ant/internal/PMDTaskImpl.java | 14 +- .../sourceforge/pmd/RuleSetFactoryTest.java | 16 +-- .../pmd/lang/java/PMD5RulesetTest.java | 4 +- .../pmd/lang/java/QuickstartRulesetTest.java | 4 +- 14 files changed, 298 insertions(+), 156 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java index c2d76f7d1f..ca06fce388 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java @@ -16,13 +16,13 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParserConfig; +import net.sourceforge.pmd.RuleSetParser; public class DefaultRulesetTest { @Rule public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests(); - private RuleSetFactory factory = new RuleSetParserConfig().enableCompatibility(false).createFactory(); + private RuleSetFactory factory = new RuleSetParser().enableCompatibility(false).createFactory(); @Test public void loadDefaultRuleset() throws Exception { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index c7aaf5877e..cd956bb64c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -202,7 +202,7 @@ public class PMD { public static int doPMD(PMDConfiguration configuration) { // Load the RuleSets - final RuleSetFactory ruleSetFactory = RuleSetParserConfig.fromPmdConfig(configuration).createFactory(); + final RuleSetFactory ruleSetFactory = RuleSetParser.fromPmdConfig(configuration).createFactory(); final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory); if (ruleSets == null) { return PMDCommandLineInterface.NO_ERRORS_STATUS; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java index 3c88301211..f53033e5dc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java @@ -102,7 +102,8 @@ public class RuleSet implements ChecksumAware { } /** - * Creates a new RuleSet containing a single rule. + * Creates a new ruleset containing a single rule. The ruleset will + * have default description, name, and null file name. * * @param rule The rule being created * @@ -117,13 +118,72 @@ public class RuleSet implements ChecksumAware { checksum = rule.getPropertiesByPropertyDescriptor().values().hashCode() * 31 + rule.getName().hashCode(); } - final RuleSetBuilder builder = new RuleSetBuilder(checksum) + final RuleSetBuilder builder = + new RuleSetBuilder(checksum) .withName(rule.getName()) .withDescription("RuleSet for " + rule.getName()); builder.addRule(rule); return builder.build(); } + + /** + * Creates a new ruleset with the given metadata such as name, description, + * fileName, exclude/include patterns are used. The rules are taken from the given + * collection. + * + *

Note: The rule instances are shared between the collection + * and the new ruleset (copy-by-reference). This might lead to concurrency issues, + * if the rules of the collection are also referenced by other rulesets and used + * in different threads. + *

+ * + * @param name the name of the ruleset + * @param description the description + * @param fileName the filename + * @param excludePatterns list of exclude patterns + * @param includePatterns list of include patterns, that override the exclude patterns + * @param rules the collection with the rules to add to the new ruleset + * + * @return the new ruleset + * + * @throws NullPointerException If any parameter is null, or the collections contain null elements + */ + public static RuleSet create(String name, + String description, + String fileName, + Collection excludePatterns, + Collection includePatterns, + Iterable rules) { + RuleSetBuilder builder = new RuleSetBuilder(0L); // TODO: checksum missing + builder.withName(name) + .withDescription(description) + .withFileName(fileName) + .replaceFileExclusions(excludePatterns) + .replaceFileInclusions(includePatterns); + for (Rule rule : rules) { + builder.addRule(rule); + } + return builder.build(); + } + + /** + * Creates a copy of the given ruleset. All properties like name, description, fileName + * and exclude/include patterns are copied. + * + *

Note: The rule instances are shared between the original + * and the new ruleset (copy-by-reference). This might lead to concurrency issues, + * if the original ruleset and the new ruleset are used in different threads. + *

+ * + * @param original the original rule set to copy from + * + * @return the copy + */ + public static RuleSet copy(RuleSet original) { + return new RuleSet(original); + } + /* package */ static class RuleSetBuilder { public String description; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index da00e5c7f7..8200c6d525 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -38,16 +38,18 @@ import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; -import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.rules.RuleFactory; import net.sourceforge.pmd.util.ResourceLoader; /** * RuleSetFactory is responsible for creating RuleSet instances from XML - * content. See {@link RuleSetParserConfig} for configuration options and - * their defaults. The constructors of this class are deprecated and their - * usages should be replaced by use of {@link RuleSetParserConfig#createFactory()}. + * content. See {@link RuleSetParser} for configuration options and + * their defaults. + * + * @deprecated Use a {@link RuleSetParser} instead. This will be hidden in PMD 7 + * (it's the implementation, while {@link RuleSetParser} is the API). */ +@Deprecated public class RuleSetFactory { private static final Logger LOG = Logger.getLogger(RuleSetFactory.class.getName()); @@ -65,7 +67,7 @@ public class RuleSetFactory { private final Map parsedRulesets = new HashMap<>(); /** - * @deprecated Use a {@link RuleSetParserConfig} to build a new factory + * @deprecated Use a {@link RuleSetParser} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory() { @@ -73,7 +75,7 @@ public class RuleSetFactory { } /** - * @deprecated Use a {@link RuleSetParserConfig} to build a new factory + * @deprecated Use a {@link RuleSetParser} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory(final ClassLoader classLoader, final RulePriority minimumPriority, @@ -82,7 +84,7 @@ public class RuleSetFactory { } /** - * @deprecated Use a {@link RuleSetParserConfig} to build a new factory + * @deprecated Use a {@link RuleSetParser} to build a new factory */ @Deprecated // to be hidden with PMD 7.0.0. public RuleSetFactory(final ResourceLoader resourceLoader, final RulePriority minimumPriority, @@ -121,7 +123,7 @@ public class RuleSetFactory { } - RuleSetFactory(RuleSetParserConfig config) { + RuleSetFactory(RuleSetParser config) { this(config.resourceLoader, config.minimumPriority, config.warnDeprecated, config.enableCompatibility, config.includeDeprecatedRuleReferences); } @@ -142,7 +144,10 @@ public class RuleSetFactory { * @return An Iterator of RuleSet objects. * * @throws RuleSetNotFoundException if the ruleset file could not be found + * + * @deprecated This is apparently only used in code deprecated for removal */ + @Deprecated public Iterator getRegisteredRuleSets() throws RuleSetNotFoundException { String rulesetsProperties = null; List ruleSetReferenceIds = new ArrayList<>(); @@ -177,7 +182,10 @@ public class RuleSetFactory { * @return The new RuleSets. * @throws RuleSetNotFoundException * if unable to find a resource. + * + * @deprecated Use {@link RuleSetParser#parseFromResourceReference(String)} */ + @Deprecated public RuleSets createRuleSets(String referenceString) throws RuleSetNotFoundException { return createRuleSets(RuleSetReferenceId.parse(referenceString)); } @@ -191,7 +199,10 @@ public class RuleSetFactory { * @return The new RuleSets. * @throws RuleSetNotFoundException * if unable to find a resource. + * + * @deprecated Will not be replaced */ + @Deprecated public RuleSets createRuleSets(List ruleSetReferenceIds) throws RuleSetNotFoundException { RuleSets ruleSets = new RuleSets(); for (RuleSetReferenceId ruleSetReferenceId : ruleSetReferenceIds) { @@ -213,7 +224,10 @@ public class RuleSetFactory { * @return A new RuleSet. * @throws RuleSetNotFoundException * if unable to find a resource. + * + * @deprecated Use {@link RuleSetParser#parseFromResourceReference(String)} and discard the rest of the list. */ + @Deprecated public RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException { List references = RuleSetReferenceId.parse(referenceString); if (references.isEmpty()) { @@ -232,7 +246,10 @@ public class RuleSetFactory { * @return A new RuleSet. * @throws RuleSetNotFoundException * if unable to find a resource. + * + * @deprecated Will not be replaced */ + @Deprecated public RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { return createRuleSet(ruleSetReferenceId, includeDeprecatedRuleReferences); } @@ -253,7 +270,10 @@ public class RuleSetFactory { * * @param original the original rule set to copy from * @return the copy + * + * @deprecated Use {@link RuleSet#copy(RuleSet)} */ + @Deprecated public RuleSet createRuleSetCopy(RuleSet original) { RuleSetBuilder builder = new RuleSetBuilder(original); return builder.build(); @@ -277,23 +297,17 @@ public class RuleSetFactory { * @param includePatterns list of include patterns, if any is not a valid regular expression, it will be ignored * @param rules the collection with the rules to add to the new ruleset * @return the new ruleset + * + * @deprecated Use {@link RuleSet#create(String, String, String, Collection, Collection, Iterable)} */ + @Deprecated public RuleSet createNewRuleSet(String name, String description, String fileName, Collection excludePatterns, Collection includePatterns, Collection rules) { - RuleSetBuilder builder = new RuleSetBuilder(0L); // TODO: checksum missing - builder.withName(name) - .withDescription(description) - .withFileName(fileName) - .replaceFileExclusions(toPatterns(excludePatterns)) - .replaceFileInclusions(toPatterns(includePatterns)); - for (Rule rule : rules) { - builder.addRule(rule); - } - return builder.build(); + return RuleSet.create(name, description, fileName, toPatterns(excludePatterns), toPatterns(includePatterns), rules); } private Collection toPatterns(Collection sources) { @@ -308,6 +322,20 @@ public class RuleSetFactory { return result; } + /** + * Creates a new RuleSet containing a single rule. + * + * @param rule The rule being created + * + * @return The newly created RuleSet + * + * @deprecated Use {@link RuleSet#forSingleRule(Rule)} + */ + @Deprecated + public RuleSet createSingleRuleRuleSet(final Rule rule) { + return RuleSet.forSingleRule(rule); + } + /** * Create a Rule from a RuleSet created from a file name resource. The * currently configured ResourceLoader is used. @@ -815,11 +843,11 @@ public class RuleSetFactory { } - public RuleSetParserConfig toConfig() { - return new RuleSetParserConfig().loadResourcesWith(resourceLoader) - .filterAbovePriority(minimumPriority) - .warnDeprecated(warnDeprecated) - .enableCompatibility(compatibilityFilter != null); + public RuleSetParser toConfig() { + return new RuleSetParser().loadResourcesWith(resourceLoader) + .filterAbovePriority(minimumPriority) + .warnDeprecated(warnDeprecated) + .enableCompatibility(compatibilityFilter != null); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java index 26393af8ea..b3d5d51a7b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java @@ -27,7 +27,7 @@ import net.sourceforge.pmd.annotation.InternalApi; * * @see issue 1360 * - * @deprecated Use {@link RuleSetParserConfig#enableCompatibility(boolean)} to enable this feature. + * @deprecated Use {@link RuleSetParser#enableCompatibility(boolean)} to enable this feature. * This implementation is internal API. */ @InternalApi diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java new file mode 100644 index 0000000000..f972e541fb --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java @@ -0,0 +1,131 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +import java.util.ArrayList; +import java.util.List; + +import net.sourceforge.pmd.util.ResourceLoader; + +/** + * Configurable ruleset parser. Note that this replaces the API of {@link RulesetsFactoryUtils} + * and {@link RuleSetFactory}. + */ +public final class RuleSetParser { + + ResourceLoader resourceLoader = new ResourceLoader(RuleSetParser.class.getClassLoader()); + RulePriority minimumPriority = RulePriority.LOW; + boolean warnDeprecated = true; + boolean enableCompatibility = true; + boolean includeDeprecatedRuleReferences = false; + + /** + * Create a new config with the default values. + */ + public RuleSetParser() { + + } + + /** + * Specify that the given classloader should be used to resolve + * paths to external ruleset references. The default uses PMD's + * own classpath. + */ + public RuleSetParser loadResourcesWith(ClassLoader classLoader) { + this.resourceLoader = new ResourceLoader(classLoader); + return this; + } + + // internal + RuleSetParser loadResourcesWith(ResourceLoader loader) { + this.resourceLoader = loader; + return this; + } + + /** + * Filter loaded rules to only those that match or are above + * the given priority. The default is {@link RulePriority#LOW}, + * ie, no filtering occurs. + */ + public RuleSetParser filterAbovePriority(RulePriority minimumPriority) { + this.minimumPriority = minimumPriority; + return this; + } + + /** + * Log a warning when referencing a deprecated rule. + * This is enabled by default. + */ + public RuleSetParser warnDeprecated(boolean warn) { + this.warnDeprecated = warn; + return this; + } + + /** + * Enable translating old rule references to newer ones, if they have + * been moved or renamed. This is enabled by default, if disabled, + * unresolved references will not be translated and will produce an + * error. + */ + public RuleSetParser enableCompatibility(boolean enable) { + this.enableCompatibility = enable; + return this; + } + + /** + * Follow deprecated rule references. By default this is off, + * and those references will be ignored (with a warning depending + * on {@link #enableCompatibility(boolean)}). + */ + public RuleSetParser includeDeprecatedRuleReferences(boolean enable) { + this.includeDeprecatedRuleReferences = enable; + return this; + } + + public RuleSetFactory createFactory() { + return new RuleSetFactory(this); + } + + + /** + * Create a RuleSets from a comma separated list of RuleSet reference IDs. + * This is a convenience method which calls + * {@link RuleSetReferenceId#parse(String)}, and then calls + * {@link #createRuleSets(List)}. The currently configured ResourceLoader is + * used. + * + * @param rulesetResourcePaths A comma separated list of RuleSet reference IDs. + * + * @return The new RuleSets. + */ + public List parseFromResourceReference(String rulesetResourcePaths) throws RuleSetNotFoundException { + return createRuleSets(RuleSetReferenceId.parse(rulesetResourcePaths)); + } + + private List createRuleSets(List ruleSetReferenceIds) throws RuleSetNotFoundException { + List ruleSets = new ArrayList<>(); + for (RuleSetReferenceId ruleSetReferenceId : ruleSetReferenceIds) { + RuleSet ruleSet = createRuleSet(ruleSetReferenceId); + ruleSets.add(ruleSet); + } + return ruleSets; + } + + + // package private + RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { + return new RuleSetFactory(this).createRuleSet(ruleSetReferenceId); + } + + + /** + * Configure a new ruleset factory builder according to the parameters + * of the given PMD configuration. + */ + public static RuleSetParser fromPmdConfig(PMDConfiguration configuration) { + return new RuleSetParser().filterAbovePriority(configuration.getMinimumPriority()) + .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java deleted file mode 100644 index c1b1f6fe15..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParserConfig.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import net.sourceforge.pmd.util.ResourceLoader; - -/** - * Configuration of a {@link RuleSetFactory}. This is a fluent builder - * pattern. Use this instead of the constructors of RuleSetFactory. - */ -public final class RuleSetParserConfig { - - ResourceLoader resourceLoader = new ResourceLoader(RuleSetParserConfig.class.getClassLoader()); - RulePriority minimumPriority = RulePriority.LOW; - boolean warnDeprecated = true; - boolean enableCompatibility = true; - boolean includeDeprecatedRuleReferences = false; - - /** - * Create a new config with the default values. - */ - public RuleSetParserConfig() { - - } - - /** - * Specify that the given classloader should be used to resolve - * paths to external ruleset references. The default uses PMD's - * own classpath. - */ - public RuleSetParserConfig loadResourcesWith(ClassLoader classLoader) { - this.resourceLoader = new ResourceLoader(classLoader); - return this; - } - - // internal - RuleSetParserConfig loadResourcesWith(ResourceLoader loader) { - this.resourceLoader = loader; - return this; - } - - /** - * Filter loaded rules to only those that match or are above - * the given priority. The default is {@link RulePriority#LOW}, - * ie, no filtering occurs. - */ - public RuleSetParserConfig filterAbovePriority(RulePriority minimumPriority) { - this.minimumPriority = minimumPriority; - return this; - } - - /** - * Log a warning when referencing a deprecated rule. - * This is enabled by default. - */ - public RuleSetParserConfig warnDeprecated(boolean warn) { - this.warnDeprecated = warn; - return this; - } - - /** - * Enable translating old rule references to newer ones, if they have - * been moved or renamed. This is enabled by default, if disabled, - * unresolved references will not be translated and will produce an - * error. - */ - public RuleSetParserConfig enableCompatibility(boolean enable) { - this.enableCompatibility = enable; - return this; - } - - /** - * Follow deprecated rule references. By default this is off, - * and those references will be ignored (with a warning depending - * on {@link #enableCompatibility(boolean)}). - */ - public RuleSetParserConfig includeDeprecatedRuleReferences(boolean enable) { - this.includeDeprecatedRuleReferences = enable; - return this; - } - - public RuleSetFactory createFactory() { - return new RuleSetFactory(this); - } - - /** - * Configure a new ruleset factory builder according to the parameters - * of the given PMD configuration. - */ - public static RuleSetParserConfig fromPmdConfig(PMDConfiguration configuration) { - return new RuleSetParserConfig().filterAbovePriority(configuration.getMinimumPriority()) - .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java index e5ee6c47cc..bac49f5f86 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java @@ -14,6 +14,7 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.util.ResourceLoader; /** @@ -78,7 +79,11 @@ import net.sourceforge.pmd.util.ResourceLoader; * * * + * + * @deprecated This is part of the internals of the {@link RuleSetParser}. */ +@Deprecated +@InternalApi public class RuleSetReferenceId { private final boolean external; private final String ruleSetFileName; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java index bbeaba74fe..c0e43ddb10 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java @@ -56,21 +56,31 @@ public class RuleSets { /** * Public constructor. Add the given rule set. * - * @param ruleSet - * the RuleSet + * @param ruleSet the RuleSet */ public RuleSets(RuleSet ruleSet) { addRuleSet(ruleSet); } + /** + * Aggregate the given rulesets. + */ + public RuleSets(List ruleSet) { + for (RuleSet set : ruleSet) { + addRuleSet(set); + } + } + /** * Add a ruleset for a language. Only one ruleset can be added for a * specific language. If ruleSet.getLanguage() is null, it is assumed to be * a RuleSet of java rules. * - * @param ruleSet - * the RuleSet + * @param ruleSet the RuleSet + * + * @deprecated Use {@link #RuleSets(List)} and don't mutate RuleSets after creation */ + @Deprecated public void addRuleSet(RuleSet ruleSet) { ruleSets.add(ruleSet); ruleChain.add(ruleSet); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java index bba3ef5f55..c835b9ac9e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java @@ -13,6 +13,10 @@ import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; import net.sourceforge.pmd.util.ResourceLoader; +/** + * @deprecated Use a {@link RuleSetParser} instead + */ +@Deprecated public final class RulesetsFactoryUtils { private static final Logger LOG = Logger.getLogger(RulesetsFactoryUtils.class.getName()); @@ -76,7 +80,7 @@ public final class RulesetsFactoryUtils { } /** - * @deprecated Use a {@link RuleSetParserConfig} + * @deprecated Use a {@link RuleSetParser} */ @InternalApi @Deprecated @@ -97,7 +101,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration, ClassLoader) * - * @deprecated Use {@link RuleSetParserConfig#fromPmdConfig(PMDConfiguration)} + * @deprecated Use {@link RuleSetParser#fromPmdConfig(PMDConfiguration)} */ @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration) { @@ -110,7 +114,7 @@ public final class RulesetsFactoryUtils { * * @return A ruleset factory * - * @see RuleSetParserConfig + * @see RuleSetParser */ public static RuleSetFactory defaultFactory() { return new RuleSetFactory(); @@ -128,7 +132,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetParserConfig} + * @deprecated Use a {@link RuleSetParser} */ @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration, ClassLoader classLoader) { @@ -152,7 +156,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetParserConfig} + * @deprecated Use a {@link RuleSetParser} */ @Deprecated public static RuleSetFactory createFactory(ClassLoader classLoader, @@ -176,7 +180,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetParserConfig} + * @deprecated Use a {@link RuleSetParser} */ @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, @@ -201,14 +205,16 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * @deprecated Use a {@link RuleSetParser} */ + @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, boolean warnDeprecated, boolean enableCompatibility, boolean includeDeprecatedRuleReferences) { return new RuleSetFactory(new ResourceLoader(), minimumPriority, warnDeprecated, enableCompatibility, - includeDeprecatedRuleReferences); + includeDeprecatedRuleReferences); } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index 6a8b4750de..f495cdfd34 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -28,9 +28,8 @@ import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParserConfig; import net.sourceforge.pmd.RuleSetNotFoundException; +import net.sourceforge.pmd.RuleSetParser; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.ant.Formatter; import net.sourceforge.pmd.ant.PMDTask; @@ -102,9 +101,8 @@ public class PMDTaskImpl { setupClassLoader(); // Setup RuleSetFactory and validate RuleSets - RuleSetFactory ruleSetFactory = RuleSetParserConfig.fromPmdConfig(configuration) - .loadResourcesWith(setupResourceLoader()) - .createFactory(); + RuleSetParser rulesetParser = RuleSetParser.fromPmdConfig(configuration) + .loadResourcesWith(setupResourceLoader()); try { // This is just used to validate and display rules. Each thread will create its own ruleset @@ -113,8 +111,8 @@ public class PMDTaskImpl { // Substitute env variables/properties configuration.setRuleSets(project.replaceProperties(ruleSets)); } - RuleSets rules = ruleSetFactory.createRuleSets(configuration.getRuleSets()); - logRulesUsed(rules); + List rules = rulesetParser.parseFromResourceReference(configuration.getRuleSets()); + logRulesUsed(new RuleSets(rules)); } catch (RuleSetNotFoundException e) { throw new BuildException(e.getMessage(), e); } @@ -193,7 +191,7 @@ public class PMDTaskImpl { renderers.add(renderer); } try { - PMD.processFiles(configuration, ruleSetFactory, files, ctx, renderers); + PMD.processFiles(configuration, rulesetParser.createFactory(), files, ctx, renderers); } catch (RuntimeException pmde) { handleError(ctx, errorReport, pmde); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 75de7f2189..60e2c8ea63 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -505,7 +505,7 @@ public class RuleSetFactoryTest { @Test public void testReferencePriority() throws RuleSetNotFoundException { - RuleSetParserConfig config = new RuleSetParserConfig().warnDeprecated(false).enableCompatibility(true); + RuleSetParser config = new RuleSetParser().warnDeprecated(false).enableCompatibility(true); RuleSetFactory rsf = config.filterAbovePriority(RulePriority.LOW).createFactory(); RuleSet ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); @@ -546,7 +546,7 @@ public class RuleSetFactoryTest { @Test public void testOverridePriorityLoadWithMinimum() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); + RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); // only one rule should remain, since we filter out the other rule by minimum priority assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -567,13 +567,13 @@ public class RuleSetFactoryTest { @Test public void testExcludeWithMinimumPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.HIGH).createFactory(); + RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.HIGH).createFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // no rules should be loaded assertEquals("Number of Rules", 0, ruleset.getRules().size()); // now, load with default minimum priority - rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.LOW).createFactory(); + rsf = new RuleSetParser().filterAbovePriority(RulePriority.LOW).createFactory(); ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // only one rule, we have excluded one... assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -602,9 +602,9 @@ public class RuleSetFactoryTest { @Test public void testSetPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).createFactory(); + RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).createFactory(); assertEquals(0, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); - rsf = new RuleSetParserConfig().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).createFactory(); + rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).createFactory(); assertEquals(1, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); } @@ -779,7 +779,7 @@ public class RuleSetFactoryTest { + " Ruleset which references a empty ruleset\n" + "\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = new RuleSetParserConfig().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParser().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref); assertEquals(0, ruleset.getRules().size()); @@ -1284,7 +1284,7 @@ public class RuleSetFactoryTest { } private RuleSet loadRuleSetWithDeprecationWarnings(String ruleSetXml) throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParserConfig().warnDeprecated(true).enableCompatibility(false).createFactory(); + RuleSetFactory rsf = new RuleSetParser().warnDeprecated(true).enableCompatibility(false).createFactory(); return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml)); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java index 7954efdc88..4f8bd58215 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java @@ -9,13 +9,13 @@ import org.junit.Test; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParserConfig; +import net.sourceforge.pmd.RuleSetParser; public class PMD5RulesetTest { @Test public void loadRuleset() throws Exception { - RuleSetFactory ruleSetFactory = new RuleSetParserConfig().createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParser().createFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet("net/sourceforge/pmd/lang/java/pmd5ruleset.xml"); Assert.assertNotNull(ruleset); Assert.assertNull(ruleset.getRuleByName("GuardLogStatementJavaUtil")); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index 2daa2c1c39..9de80e56c1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -16,7 +16,7 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParserConfig; +import net.sourceforge.pmd.RuleSetParser; import net.sourceforge.pmd.RuleSetNotFoundException; public class QuickstartRulesetTest { @@ -49,7 +49,7 @@ public class QuickstartRulesetTest { } }); - RuleSetFactory ruleSetFactory = new RuleSetParserConfig().enableCompatibility(false).createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParser().enableCompatibility(false).createFactory(); RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); Assert.assertFalse(quickstart.getRules().isEmpty()); } From efb133c74e9d3c60ed4ff012da0000c8d43aa152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 20:19:45 +0100 Subject: [PATCH 05/34] Cleanup API around processors --- .../main/java/net/sourceforge/pmd/PMD.java | 45 +++++++++++++++++-- .../pmd/ant/internal/PMDTaskImpl.java | 30 ++++++++----- .../pmd/processor/AbstractPMDProcessor.java | 25 ++++++++++- .../pmd/processor/MonoThreadProcessor.java | 5 ++- .../pmd/processor/MultiThreadProcessor.java | 4 ++ .../pmd/processor/PmdRunnable.java | 7 +++ .../pmd/processor/PmdThreadFactory.java | 8 ++++ 7 files changed, 107 insertions(+), 17 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index cd956bb64c..516194e935 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -11,6 +11,8 @@ import java.io.Writer; import java.net.URISyntaxException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -220,9 +222,9 @@ public class PMD { renderer.start(); } - RuleContext ctx = new RuleContext(); final AtomicInteger violations = new AtomicInteger(0); - ctx.getReport().addListener(new ThreadSafeReportListener() { + Report report = new Report(); + report.addListener(new ThreadSafeReportListener() { @Override public void ruleViolationAdded(RuleViolation ruleViolation) { violations.getAndIncrement(); @@ -235,7 +237,7 @@ public class PMD { }); try (TimedOperation to = TimeTracker.startOperation(TimedOperationCategory.FILE_PROCESSING)) { - processFiles(configuration, ruleSetFactory, files, ctx, renderers); + processFiles(configuration, Arrays.asList(ruleSets.getAllRuleSets()), files, report, renderers); } try (TimedOperation rto = TimeTracker.startOperation(TimedOperationCategory.REPORTING)) { @@ -296,9 +298,14 @@ public class PMD { * RuleContext * @param renderers * List of {@link Renderer}s + * + * @deprecated Use {@link #processFiles(PMDConfiguration, List, Collection, Report, List)} + * so as not to depend on {@link RuleSetFactory}. Note that this sorts the list of data sources in-place, + * which won't be fixed */ + @Deprecated public static void processFiles(final PMDConfiguration configuration, final RuleSetFactory ruleSetFactory, - final List files, final RuleContext ctx, final List renderers) { + final List files, final RuleContext ctx, final List renderers) { encourageToUseIncrementalAnalysis(configuration); sortFiles(configuration, files); // Make sure the cache is listening for analysis results @@ -309,6 +316,36 @@ public class PMD { configuration.getAnalysisCache().persist(); } + /** + * Run PMD using the given configuration. This replaces the other overload. + * + * @param configuration Configuration for the run. Note that the files, and rulesets, are ignored, as they are + * supplied as parameter + * @param rulesets Parsed rulesets + * @param files Files to process + * @param report Report in which violations are accumulated + * @param renderers Renderers that render the report + * + * + * @throws RuntimeException If processing fails + */ + public static void processFiles(final PMDConfiguration configuration, + final List rulesets, + final Collection files, + final Report report, + final List renderers) { + encourageToUseIncrementalAnalysis(configuration); + report.addListener(configuration.getAnalysisCache()); + + List sortedFiles = new ArrayList<>(files); + sortFiles(configuration, sortedFiles); + + RuleContext ctx = new RuleContext(); + ctx.setReport(report); + newFileProcessor(configuration).processFiles(new RuleSets(rulesets), sortedFiles, ctx, renderers); + configuration.getAnalysisCache().persist(); + } + private static void sortFiles(final PMDConfiguration configuration, final List files) { if (configuration.isStressTest()) { // randomize processing order diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index f495cdfd34..7756e5eace 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ContextedRuntimeException; import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; @@ -25,7 +26,6 @@ import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetNotFoundException; @@ -104,15 +104,17 @@ public class PMDTaskImpl { RuleSetParser rulesetParser = RuleSetParser.fromPmdConfig(configuration) .loadResourcesWith(setupResourceLoader()); + List ruleSets; + try { // This is just used to validate and display rules. Each thread will create its own ruleset - String ruleSets = configuration.getRuleSets(); - if (StringUtils.isNotBlank(ruleSets)) { + String ruleSetString = configuration.getRuleSets(); + if (StringUtils.isNotBlank(ruleSetString)) { // Substitute env variables/properties - configuration.setRuleSets(project.replaceProperties(ruleSets)); + configuration.setRuleSets(project.replaceProperties(ruleSetString)); } - List rules = rulesetParser.parseFromResourceReference(configuration.getRuleSets()); - logRulesUsed(new RuleSets(rules)); + ruleSets = rulesetParser.parseFromResourceReference(configuration.getRuleSets()); + logRulesUsed(new RuleSets(ruleSets)); } catch (RuleSetNotFoundException e) { throw new BuildException(e.getMessage(), e); } @@ -132,7 +134,7 @@ public class PMDTaskImpl { // TODO Do we really need all this in a loop over each FileSet? Seems // like a lot of redundancy - RuleContext ctx = new RuleContext(); + Report report = new Report(); Report errorReport = new Report(); final AtomicInteger reportSize = new AtomicInteger(); final String separator = System.getProperty("file.separator"); @@ -191,9 +193,15 @@ public class PMDTaskImpl { renderers.add(renderer); } try { - PMD.processFiles(configuration, rulesetParser.createFactory(), files, ctx, renderers); + PMD.processFiles(configuration, ruleSets, files, report, renderers); + } catch (ContextedRuntimeException e) { + if (e.getFirstContextValue("filename") instanceof String) { + handleError((String) e.getFirstContextValue("filename"), errorReport, e); + } else { + handleError("(unknown file)", errorReport, e); + } } catch (RuntimeException pmde) { - handleError(ctx, errorReport, pmde); + handleError("(unknown file)", errorReport, pmde); } } @@ -235,7 +243,7 @@ public class PMDTaskImpl { project, classpath, parentFirst); } - private void handleError(RuleContext ctx, Report errorReport, RuntimeException pmde) { + private void handleError(String filename, Report errorReport, RuntimeException pmde) { pmde.printStackTrace(); project.log(pmde.toString(), Project.MSG_VERBOSE); @@ -258,7 +266,7 @@ public class PMDTaskImpl { if (failOnError) { throw new BuildException(pmde); } - errorReport.addError(new Report.ProcessingError(pmde, String.valueOf(ctx.getSourceCodeFile()))); + errorReport.addError(new Report.ProcessingError(pmde, filename)); } private void setupClassLoader() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index 07552dd3e8..ff192c2bb6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -12,6 +12,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.exception.ContextedRuntimeException; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; @@ -21,6 +22,7 @@ import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.SourceCodeProcessor; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; @@ -30,7 +32,10 @@ import net.sourceforge.pmd.util.datasource.DataSource; /** * @author Romain Pelisse <belaran@gmail.com> * + * @deprecated Is internal API */ +@Deprecated +@InternalApi public abstract class AbstractPMDProcessor { private static final Logger LOG = Logger.getLogger(AbstractPMDProcessor.class.getName()); @@ -108,10 +113,26 @@ public abstract class AbstractPMDProcessor { @SuppressWarnings("PMD.CloseResource") // the data sources must only be closed after the threads are finished // this is done manually without a try-with-resources + @Deprecated public void processFiles(RuleSetFactory ruleSetFactory, List files, RuleContext ctx, - List renderers) { + List renderers) { try { final RuleSets rs = createRuleSets(ruleSetFactory, ctx.getReport()); + processFiles(rs, files, ctx, renderers); + } finally { + // in case we analyzed files within Zip Files/Jars, we need to close them after + // the analysis is finished + for (DataSource dataSource : files) { + IOUtils.closeQuietly(dataSource); + } + } + } + + @SuppressWarnings("PMD.CloseResource") + // the data sources must only be closed after the threads are finished + // this is done manually without a try-with-resources + public void processFiles(RuleSets rs, List files, RuleContext ctx, List renderers) { + try { configuration.getAnalysisCache().checkValidity(rs, configuration.getClassLoader()); final SourceCodeProcessor processor = new SourceCodeProcessor(configuration); @@ -127,6 +148,8 @@ public abstract class AbstractPMDProcessor { // then add analysis results per file collectReports(renderers); + } catch (RuntimeException e) { + throw new ContextedRuntimeException(e).addContextValue("filename", String.valueOf(ctx.getSourceCodeFile())); } finally { // in case we analyzed files within Zip Files/Jars, we need to close them after // the analysis is finished diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java index 6acf61a32c..f2776574e4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MonoThreadProcessor.java @@ -9,12 +9,15 @@ import java.util.List; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.renderers.Renderer; /** * @author Romain Pelisse <belaran@gmail.com> - * + * @deprecated Is internal API */ +@Deprecated +@InternalApi public final class MonoThreadProcessor extends AbstractPMDProcessor { private final List reports = new ArrayList<>(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java index f398a90db8..8745f99bf0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/MultiThreadProcessor.java @@ -13,12 +13,16 @@ import java.util.concurrent.Executors; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.renderers.Renderer; /** * @author Romain Pelisse <belaran@gmail.com> + * @deprecated Is internal API */ +@Deprecated +@InternalApi public class MultiThreadProcessor extends AbstractPMDProcessor { private final ExecutorService executor; private final CompletionService completionService; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java index d3ddeb6230..4c290a61b6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java @@ -17,10 +17,17 @@ import net.sourceforge.pmd.Report; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.SourceCodeProcessor; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.util.datasource.DataSource; +/** + * + * @deprecated Is internal API + */ +@Deprecated +@InternalApi public class PmdRunnable implements Callable { private static final Logger LOG = Logger.getLogger(PmdRunnable.class.getName()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java index 51c84b3063..e767b8e79b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdThreadFactory.java @@ -7,6 +7,14 @@ package net.sourceforge.pmd.processor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; +import net.sourceforge.pmd.annotation.InternalApi; + +/** + * + * @deprecated Is internal API + */ +@Deprecated +@InternalApi public class PmdThreadFactory implements ThreadFactory { private final AtomicInteger counter = new AtomicInteger(); From 8295dad86caa23a7718a8ee863c8cfd8f9e8247e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 20:27:38 +0100 Subject: [PATCH 06/34] Deprecate some methods of PMD --- .../main/java/net/sourceforge/pmd/PMD.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 516194e935..13d4d8e2d7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -90,7 +90,10 @@ public class PMD { /** * Create a PMD instance using a default Configuration. Changes to the * configuration may be required. + * + * @deprecated Just use the static methods, and maintain your {@link PMDConfiguration} separately. */ + @Deprecated public PMD() { this(new PMDConfiguration()); } @@ -98,9 +101,11 @@ public class PMD { /** * Create a PMD instance using the specified Configuration. * - * @param configuration - * The runtime Configuration of PMD to use. + * @param configuration The runtime Configuration of PMD to use. + * + * @deprecated Just use the static methods, and maintain your {@link PMDConfiguration} separately. */ + @Deprecated public PMD(PMDConfiguration configuration) { this.configuration = configuration; this.rulesetsFileProcessor = new SourceCodeProcessor(configuration); @@ -189,7 +194,9 @@ public class PMD { * Gets the source code processor. * * @return SourceCodeProcessor + * @deprecated Source code processor is internal */ + @Deprecated public SourceCodeProcessor getSourceCodeProcessor() { return rulesetsFileProcessor; } @@ -275,7 +282,10 @@ public class PMD { * @param sourceCodeFile * the source code file * @return the rule context + * + * @deprecated Not useful */ + @Deprecated public static RuleContext newRuleContext(String sourceCodeFilename, File sourceCodeFile) { RuleContext context = new RuleContext(); @@ -319,14 +329,14 @@ public class PMD { /** * Run PMD using the given configuration. This replaces the other overload. * - * @param configuration Configuration for the run. Note that the files, and rulesets, are ignored, as they are - * supplied as parameter + * @param configuration Configuration for the run. Note that the files, + * and rulesets, are ignored, as they are supplied + * as parameters * @param rulesets Parsed rulesets * @param files Files to process * @param report Report in which violations are accumulated * @param renderers Renderers that render the report * - * * @throws RuntimeException If processing fails */ public static void processFiles(final PMDConfiguration configuration, From 125b0200ed189d8ef8f74e33e45b2ff65e69884d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 20:30:29 +0100 Subject: [PATCH 07/34] Deprecate configuration objects --- pmd-core/src/main/java/net/sourceforge/pmd/PMD.java | 13 +++++++++++-- .../main/java/net/sourceforge/pmd/PMDException.java | 1 + .../net/sourceforge/pmd/SourceCodeProcessor.java | 6 ++++++ .../pmd/cli/PMDCommandLineInterface.java | 4 ++++ .../java/net/sourceforge/pmd/cli/PMDParameters.java | 7 +++++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 13d4d8e2d7..867343372f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -23,6 +23,7 @@ import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TextTimingReportRenderer; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; @@ -121,7 +122,10 @@ public class PMD { * @throws PMDException * if the URI couldn't be parsed * @see DBURI + * + * @deprecated Will be hidden as part of the parsing of {@link PMD#getApplicableFiles(PMDConfiguration, Set)} */ + @Deprecated public static List getURIDataSources(String uriString) throws PMDException { List dataSources = new ArrayList<>(); @@ -167,7 +171,11 @@ public class PMD { * @param configuration * the given configuration * @return the pre-configured parser + * + * @deprecated This is internal */ + @Deprecated + @InternalApi public static Parser parserFor(LanguageVersion languageVersion, PMDConfiguration configuration) { // TODO Handle Rules having different parser options. @@ -488,7 +496,7 @@ public class PMD { } /** - * Entry to invoke PMD as command line tool + * Entry to invoke PMD as command line tool. Note that this will invoke {@link System#exit(int)}. * * @param args * command line arguments @@ -498,7 +506,8 @@ public class PMD { } /** - * Parses the command line arguments and executes PMD. + * Parses the command line arguments and executes PMD. Returns the + * exit code without exiting the VM. * * @param args * command line arguments diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMDException.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMDException.java index 4cadd9728d..d2ab5fc2b3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMDException.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMDException.java @@ -13,6 +13,7 @@ package net.sourceforge.pmd; * @version $Revision$, $Date$ * @since August 30, 2002 */ +@Deprecated public class PMDException extends Exception { private static final long serialVersionUID = 6938647389367956874L; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java index 4722c89ec0..235e8faa9d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java @@ -11,6 +11,7 @@ import java.io.Reader; import java.util.Collections; import java.util.List; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; @@ -23,6 +24,11 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.ParseException; import net.sourceforge.pmd.lang.xpath.Initializer; +/** + * Source code processor is internal. + */ +@Deprecated +@InternalApi public class SourceCodeProcessor { private final PMDConfiguration configuration; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java index 04daf8b5dc..f3ec3345bf 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java @@ -8,6 +8,7 @@ import java.util.Properties; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDVersion; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.renderers.Renderer; @@ -19,7 +20,10 @@ import com.beust.jcommander.ParameterException; /** * @author Romain Pelisse <belaran@gmail.com> * + * @deprecated Internal API. Use {@link PMD#run(String[])} or {@link PMD#run(String[])}. */ +@Deprecated +@InternalApi public final class PMDCommandLineInterface { public static final String PROG_NAME = "pmd"; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index b68cb336a3..e64637fc68 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -9,8 +9,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.RulePriority; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; @@ -20,6 +22,11 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.validators.PositiveInteger; +/** + * @deprecated Internal API. Use {@link PMD#main(String[])}. + */ +@Deprecated +@InternalApi public class PMDParameters { @Parameter(names = { "-rulesets", "-R" }, description = "Comma separated list of ruleset names to use.", From 7d66d7cbca6f88f80d4468f412f93950ca121014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 20:41:36 +0100 Subject: [PATCH 08/34] Doc --- docs/pages/release_notes.md | 17 +++++++++++++++++ .../src/main/java/net/sourceforge/pmd/PMD.java | 7 +++++++ .../java/net/sourceforge/pmd/RuleSetParser.java | 13 ++++++++++++- .../net/sourceforge/pmd/RuleSetReference.java | 6 ++++++ .../pmd/cli/PMDCommandLineInterface.java | 2 +- .../net/sourceforge/pmd/cli/PMDParameters.java | 2 +- 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..710428b79d 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -18,6 +18,23 @@ This is a {{ site.pmd.release_type }} release. ### API Changes +#### Deprecated API + +##### Around RuleSet parsing + +* {% jdoc core::RuleSetFactory %} and {% jdoc core::RuleSetFactoryUtils %} have been deprecated in favor of {% jdoc core::RuleSetParser %}. This is easier to configure, and more maintainable than the multiple overloads of `RuleSetFactoryUtils`. +* Some static creation methods have been added to {% jdoc core::RuleSet %} for simple cases, eg {% jdoc core::RuleSet#forSingleRule(core::Rule) %}. These replace some counterparts in {% jdoc core::RuleSetFactory %} +* Since {% jdoc core::RuleSets %} is also deprecated, many APIs that require a RuleSets instance now are deprecated, and have a counterpart that expects a `List`. +* {% jdoc core::RuleSetReferenceId %}, {% jdoc core::RuleSetReference %}, {% jdoc core::RuleSetFactoryCompatibility %} are deprecated. They are most likely not relevant outside of the implementation of pmd-core. + +##### Around the `PMD` class + +Many APIs around PMD's entry point ({% jdoc core::PMD %}) have been deprecated, including: +* The contents of the packages {% jdoc_package core::cli %}, {% jdoc_package core::processor %} +* {% jdoc core::SourceCodeProcessor %} +* The constructors of {% jdoc core::PMD %} (the class will be made a utility class) + + ### External Contributions {% endtocmaker %} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 867343372f..161dc9d48a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -193,7 +193,10 @@ public class PMD { * * @return The configuration. * @see PMDConfiguration + * + * @deprecated Don't create a PMD instance just to create a {@link PMDConfiguration} */ + @Deprecated public PMDConfiguration getConfiguration() { return configuration; } @@ -324,6 +327,10 @@ public class PMD { @Deprecated public static void processFiles(final PMDConfiguration configuration, final RuleSetFactory ruleSetFactory, final List files, final RuleContext ctx, final List renderers) { + // Note that this duplicates the other routine, because the old behavior was + // that we parsed rulesets (a second time) inside the processor execution. + // To not mess up error handling, we keep this behavior. + encourageToUseIncrementalAnalysis(configuration); sortFiles(configuration, files); // Make sure the cache is listening for analysis results diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java index f972e541fb..9d9173b318 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java @@ -11,7 +11,9 @@ import net.sourceforge.pmd.util.ResourceLoader; /** * Configurable ruleset parser. Note that this replaces the API of {@link RulesetsFactoryUtils} - * and {@link RuleSetFactory}. + * and {@link RuleSetFactory}. This can be configured using a fluent + * API, see eg {@link #warnDeprecated(boolean)}. To create a list of + * rulesets, use {@link #parseFromResourceReference(String)}. */ public final class RuleSetParser { @@ -48,6 +50,7 @@ public final class RuleSetParser { * Filter loaded rules to only those that match or are above * the given priority. The default is {@link RulePriority#LOW}, * ie, no filtering occurs. + * @return This instance, modified */ public RuleSetParser filterAbovePriority(RulePriority minimumPriority) { this.minimumPriority = minimumPriority; @@ -57,6 +60,7 @@ public final class RuleSetParser { /** * Log a warning when referencing a deprecated rule. * This is enabled by default. + * @return This instance, modified */ public RuleSetParser warnDeprecated(boolean warn) { this.warnDeprecated = warn; @@ -68,6 +72,7 @@ public final class RuleSetParser { * been moved or renamed. This is enabled by default, if disabled, * unresolved references will not be translated and will produce an * error. + * @return This instance, modified */ public RuleSetParser enableCompatibility(boolean enable) { this.enableCompatibility = enable; @@ -78,12 +83,18 @@ public final class RuleSetParser { * Follow deprecated rule references. By default this is off, * and those references will be ignored (with a warning depending * on {@link #enableCompatibility(boolean)}). + * + * @return This instance, modified */ public RuleSetParser includeDeprecatedRuleReferences(boolean enable) { this.includeDeprecatedRuleReferences = enable; return this; } + /** + * Create a new rule set factory, if you have to (that class is deprecated). + * That factory will use the configuration that was set using the setters of this. + */ public RuleSetFactory createFactory() { return new RuleSetFactory(this); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java index e7098568e1..32e2eeedb7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java @@ -8,9 +8,15 @@ import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import net.sourceforge.pmd.annotation.InternalApi; + /** * This class represents a reference to RuleSet. + * + * @deprecated This is part of the internals of the {@link RuleSetParser}. */ +@Deprecated +@InternalApi public class RuleSetReference { private final String ruleSetFileName; private final boolean allRules; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java index f3ec3345bf..a8ad35ed4a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java @@ -20,7 +20,7 @@ import com.beust.jcommander.ParameterException; /** * @author Romain Pelisse <belaran@gmail.com> * - * @deprecated Internal API. Use {@link PMD#run(String[])} or {@link PMD#run(String[])}. + * @deprecated Internal API. Use {@link PMD#run(String[])} or {@link PMD#main(String[])} */ @Deprecated @InternalApi diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index e64637fc68..94cd430553 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -23,7 +23,7 @@ import com.beust.jcommander.ParameterException; import com.beust.jcommander.validators.PositiveInteger; /** - * @deprecated Internal API. Use {@link PMD#main(String[])}. + * @deprecated Internal API. Use {@link PMD#run(String[])} or {@link PMD#main(String[])} */ @Deprecated @InternalApi From 8f8af7780e092f3eb371e9bf34e15168bc139d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 21:10:58 +0100 Subject: [PATCH 09/34] Rename stuff --- .../pmd/lang/apex/DefaultRulesetTest.java | 2 +- .../main/java/net/sourceforge/pmd/PMD.java | 4 +-- .../net/sourceforge/pmd/RuleSetFactory.java | 15 +++++++---- .../net/sourceforge/pmd/RuleSetParser.java | 3 ++- .../sourceforge/pmd/RuleSetFactoryTest.java | 26 +++++++++---------- .../pmd/lang/java/PMD5RulesetTest.java | 2 +- .../pmd/lang/java/QuickstartRulesetTest.java | 2 +- 7 files changed, 30 insertions(+), 24 deletions(-) diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java index ca06fce388..8a1c2db3c1 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java @@ -22,7 +22,7 @@ public class DefaultRulesetTest { @Rule public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests(); - private RuleSetFactory factory = new RuleSetParser().enableCompatibility(false).createFactory(); + private RuleSetFactory factory = new RuleSetParser().enableCompatibility(false).toFactory(); @Test public void loadDefaultRuleset() throws Exception { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 161dc9d48a..370c0ad672 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -222,7 +222,7 @@ public class PMD { public static int doPMD(PMDConfiguration configuration) { // Load the RuleSets - final RuleSetFactory ruleSetFactory = RuleSetParser.fromPmdConfig(configuration).createFactory(); + final RuleSetFactory ruleSetFactory = RuleSetParser.fromPmdConfig(configuration).toFactory(); final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory); if (ruleSets == null) { return PMDCommandLineInterface.NO_ERRORS_STATUS; @@ -336,7 +336,7 @@ public class PMD { // Make sure the cache is listening for analysis results ctx.getReport().addListener(configuration.getAnalysisCache()); - final RuleSetFactory silentFactory = ruleSetFactory.toConfig().warnDeprecated(false).createFactory(); + final RuleSetFactory silentFactory = ruleSetFactory.toParser().warnDeprecated(false).toFactory(); newFileProcessor(configuration).processFiles(silentFactory, files, ctx, renderers); configuration.getAnalysisCache().persist(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 8200c6d525..ef578dab76 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -115,7 +115,7 @@ public class RuleSetFactory { * Whether deprecation warnings are to be produced by this * factory * - * @deprecated Use {@link #toConfig()} to rebuild a factory from a configuration + * @deprecated Use {@link #toParser()} to rebuild a factory from a configuration */ @Deprecated public RuleSetFactory(final RuleSetFactory factory, final boolean warnDeprecated) { @@ -566,7 +566,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = toConfig().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).createFactory(); + RuleSetFactory ruleSetFactory = toParser().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory(); RuleSet otherRuleSet = ruleSetFactory.createRuleSet(RuleSetReferenceId.parse(ref).get(0)); List potentialRules = new ArrayList<>(); int countDeprecated = 0; @@ -681,7 +681,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = toConfig().warnDeprecated(false).createFactory(); + RuleSetFactory ruleSetFactory = toParser().warnDeprecated(false).toFactory(); boolean isSameRuleSet = false; RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0); @@ -843,11 +843,16 @@ public class RuleSetFactory { } - public RuleSetParser toConfig() { + /** + * Create a new {@link RuleSetParser} with the same config as this + * factory. This is a transitional API. + */ + public RuleSetParser toParser() { return new RuleSetParser().loadResourcesWith(resourceLoader) .filterAbovePriority(minimumPriority) .warnDeprecated(warnDeprecated) - .enableCompatibility(compatibilityFilter != null); + .enableCompatibility(compatibilityFilter != null) + .includeDeprecatedRuleReferences(includeDeprecatedRuleReferences); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java index 9d9173b318..326c5b0914 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java @@ -95,7 +95,8 @@ public final class RuleSetParser { * Create a new rule set factory, if you have to (that class is deprecated). * That factory will use the configuration that was set using the setters of this. */ - public RuleSetFactory createFactory() { + @Deprecated + public RuleSetFactory toFactory() { return new RuleSetFactory(this); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 60e2c8ea63..455d0287b9 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -507,38 +507,38 @@ public class RuleSetFactoryTest { public void testReferencePriority() throws RuleSetNotFoundException { RuleSetParser config = new RuleSetParser().warnDeprecated(false).enableCompatibility(true); - RuleSetFactory rsf = config.filterAbovePriority(RulePriority.LOW).createFactory(); + RuleSetFactory rsf = config.filterAbovePriority(RulePriority.LOW).toFactory(); RuleSet ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); assertEquals("Number of Rules", 3, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("MockRuleName")); assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = config.filterAbovePriority(RulePriority.MEDIUM_HIGH).createFactory(); + rsf = config.filterAbovePriority(RulePriority.MEDIUM_HIGH).toFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); assertEquals("Number of Rules", 2, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = config.filterAbovePriority(RulePriority.HIGH).createFactory(); + rsf = config.filterAbovePriority(RulePriority.HIGH).toFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); assertEquals("Number of Rules", 1, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = config.filterAbovePriority(RulePriority.LOW).createFactory(); + rsf = config.filterAbovePriority(RulePriority.LOW).toFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); assertEquals("Number of Rules", 3, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleName")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); - rsf = config.filterAbovePriority(RulePriority.MEDIUM_HIGH).createFactory(); + rsf = config.filterAbovePriority(RulePriority.MEDIUM_HIGH).toFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); assertEquals("Number of Rules", 2, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); - rsf = config.filterAbovePriority(RulePriority.HIGH).createFactory(); + rsf = config.filterAbovePriority(RulePriority.HIGH).toFactory(); ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); assertEquals("Number of Rules", 1, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); @@ -546,7 +546,7 @@ public class RuleSetFactoryTest { @Test public void testOverridePriorityLoadWithMinimum() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); + RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); // only one rule should remain, since we filter out the other rule by minimum priority assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -567,13 +567,13 @@ public class RuleSetFactoryTest { @Test public void testExcludeWithMinimumPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.HIGH).createFactory(); + RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.HIGH).toFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // no rules should be loaded assertEquals("Number of Rules", 0, ruleset.getRules().size()); // now, load with default minimum priority - rsf = new RuleSetParser().filterAbovePriority(RulePriority.LOW).createFactory(); + rsf = new RuleSetParser().filterAbovePriority(RulePriority.LOW).toFactory(); ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // only one rule, we have excluded one... assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -602,9 +602,9 @@ public class RuleSetFactoryTest { @Test public void testSetPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).createFactory(); + RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).toFactory(); assertEquals(0, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); - rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).createFactory(); + rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).toFactory(); assertEquals(1, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); } @@ -779,7 +779,7 @@ public class RuleSetFactoryTest { + " Ruleset which references a empty ruleset\n" + "\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = new RuleSetParser().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParser().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref); assertEquals(0, ruleset.getRules().size()); @@ -1284,7 +1284,7 @@ public class RuleSetFactoryTest { } private RuleSet loadRuleSetWithDeprecationWarnings(String ruleSetXml) throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().warnDeprecated(true).enableCompatibility(false).createFactory(); + RuleSetFactory rsf = new RuleSetParser().warnDeprecated(true).enableCompatibility(false).toFactory(); return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml)); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java index 4f8bd58215..d4406a6ed0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java @@ -15,7 +15,7 @@ public class PMD5RulesetTest { @Test public void loadRuleset() throws Exception { - RuleSetFactory ruleSetFactory = new RuleSetParser().createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParser().toFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet("net/sourceforge/pmd/lang/java/pmd5ruleset.xml"); Assert.assertNotNull(ruleset); Assert.assertNull(ruleset.getRuleByName("GuardLogStatementJavaUtil")); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index 9de80e56c1..9b356fe03c 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -49,7 +49,7 @@ public class QuickstartRulesetTest { } }); - RuleSetFactory ruleSetFactory = new RuleSetParser().enableCompatibility(false).createFactory(); + RuleSetFactory ruleSetFactory = new RuleSetParser().enableCompatibility(false).toFactory(); RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); Assert.assertFalse(quickstart.getRules().isEmpty()); } From 9c56fb629a5330858c36c561bf9b6bd1553db051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 21:21:29 +0100 Subject: [PATCH 10/34] Fix bug --- pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index ef578dab76..99eef0b567 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -681,7 +681,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = toParser().warnDeprecated(false).toFactory(); + RuleSetFactory ruleSetFactory = toParser().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory(); boolean isSameRuleSet = false; RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0); From 38a0934feef8900fafe04c19ef7437ed4106832b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 21:32:26 +0100 Subject: [PATCH 11/34] PMD warnings --- .../src/main/java/net/sourceforge/pmd/RuleSetFactory.java | 7 ++++--- .../src/main/java/net/sourceforge/pmd/RuleSetParser.java | 7 ------- .../java/net/sourceforge/pmd/benchmark/Benchmarker.java | 1 - 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 99eef0b567..c8ad55f0c7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -163,9 +163,10 @@ public class RuleSetFactory { } catch (RuleSetNotFoundException e) { LOG.warning("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); } catch (IOException ioe) { - throw new RuntimeException("Couldn't find " + rulesetsProperties - + "; please ensure that the directory is on the classpath. The current classpath is: " - + System.getProperty("java.class.path"));} + throw new RuntimeException("Couldn't find " + rulesetsProperties + + "; please ensure that the directory is on the classpath. The current classpath is: " + + System.getProperty("java.class.path")); + } } return createRuleSets(ruleSetReferenceIds).getRuleSetsIterator(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java index 326c5b0914..815b58056a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java @@ -23,13 +23,6 @@ public final class RuleSetParser { boolean enableCompatibility = true; boolean includeDeprecatedRuleReferences = false; - /** - * Create a new config with the default values. - */ - public RuleSetParser() { - - } - /** * Specify that the given classloader should be used to resolve * paths to external ruleset references. The default uses PMD's diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java index 89a81b28e0..af56e1d1e0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java @@ -175,7 +175,6 @@ public final class Benchmarker { private static void stress(LanguageVersion languageVersion, RuleSet ruleSet, List dataSources, Set results, boolean debug) throws PMDException, IOException { - final RuleSetFactory factory = RulesetsFactoryUtils.defaultFactory(); for (Rule rule: ruleSet.getRules()) { if (debug) { System.out.println("Starting " + rule.getName()); From 050ec4464e56405946674dad2f979cb6eeb21f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 23:30:03 +0100 Subject: [PATCH 12/34] Stop parsing comma-separated paths by default --- .../net/sourceforge/pmd/RuleSetFactory.java | 5 +- .../net/sourceforge/pmd/RuleSetParser.java | 52 +++++++++++++------ .../pmd/ant/internal/PMDTaskImpl.java | 31 +++++------ 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index c8ad55f0c7..0778035fc3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -184,7 +184,8 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException * if unable to find a resource. * - * @deprecated Use {@link RuleSetParser#parseFromResourceReference(String)} + * @deprecated Use {@link RuleSetParser#parseFromResource(String)}, + * but note that that method does not split on commas */ @Deprecated public RuleSets createRuleSets(String referenceString) throws RuleSetNotFoundException { @@ -226,7 +227,7 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException * if unable to find a resource. * - * @deprecated Use {@link RuleSetParser#parseFromResourceReference(String)} and discard the rest of the list. + * @deprecated Use {@link RuleSetParser#parseFromResource(String)} and discard the rest of the list. */ @Deprecated public RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java index 815b58056a..72b3dc60b7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import net.sourceforge.pmd.util.ResourceLoader; @@ -13,7 +15,7 @@ import net.sourceforge.pmd.util.ResourceLoader; * Configurable ruleset parser. Note that this replaces the API of {@link RulesetsFactoryUtils} * and {@link RuleSetFactory}. This can be configured using a fluent * API, see eg {@link #warnDeprecated(boolean)}. To create a list of - * rulesets, use {@link #parseFromResourceReference(String)}. + * rulesets, use {@link #parseFromResource(String)}. */ public final class RuleSetParser { @@ -95,32 +97,50 @@ public final class RuleSetParser { /** - * Create a RuleSets from a comma separated list of RuleSet reference IDs. - * This is a convenience method which calls - * {@link RuleSetReferenceId#parse(String)}, and then calls - * {@link #createRuleSets(List)}. The currently configured ResourceLoader is - * used. + * Parses and returns a ruleset from its location. The location may + * be a file system path, or a resource path (see {@link #loadResourcesWith(ClassLoader)}). * - * @param rulesetResourcePaths A comma separated list of RuleSet reference IDs. + *

This replaces {@link RuleSetFactory#createRuleSet(String)}, + * but does not split commas. * - * @return The new RuleSets. + * @param rulesetPath A reference to a single ruleset + * + * @throws RuleSetNotFoundException If the path does not correspond to a resource */ - public List parseFromResourceReference(String rulesetResourcePaths) throws RuleSetNotFoundException { - return createRuleSets(RuleSetReferenceId.parse(rulesetResourcePaths)); + public RuleSet parseFromResource(String rulesetPath) throws RuleSetNotFoundException { + return parseFromResource(new RuleSetReferenceId(rulesetPath)); } - private List createRuleSets(List ruleSetReferenceIds) throws RuleSetNotFoundException { - List ruleSets = new ArrayList<>(); - for (RuleSetReferenceId ruleSetReferenceId : ruleSetReferenceIds) { - RuleSet ruleSet = createRuleSet(ruleSetReferenceId); - ruleSets.add(ruleSet); + /** + * Parses several resources into a list of rulesets. + * + * @param paths Paths + * + * @throws RuleSetNotFoundException If any resource throws + * @throws NullPointerException If the parameter, or any component is null + */ + public List parseFromResources(Collection paths) throws RuleSetNotFoundException { + List ruleSets = new ArrayList<>(paths.size()); + for (String path : paths) { + ruleSets.add(parseFromResource(path)); } return ruleSets; } + /** + * Parses several resources into a list of rulesets. + * + * @param paths Paths + * + * @throws RuleSetNotFoundException If any resource throws + * @throws NullPointerException If the parameter, or any component is null + */ + public List parseFromResources(String... paths) throws RuleSetNotFoundException { + return parseFromResources(Arrays.asList(paths)); + } // package private - RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { + RuleSet parseFromResource(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { return new RuleSetFactory(this).createRuleSet(ruleSetReferenceId); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index 7756e5eace..101bd4d8ec 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -9,6 +9,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -28,9 +29,9 @@ import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RuleSetParser; import net.sourceforge.pmd.RuleSets; +import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.ant.Formatter; import net.sourceforge.pmd.ant.PMDTask; import net.sourceforge.pmd.ant.SourceLanguage; @@ -104,21 +105,17 @@ public class PMDTaskImpl { RuleSetParser rulesetParser = RuleSetParser.fromPmdConfig(configuration) .loadResourcesWith(setupResourceLoader()); - List ruleSets; - - try { - // This is just used to validate and display rules. Each thread will create its own ruleset - String ruleSetString = configuration.getRuleSets(); - if (StringUtils.isNotBlank(ruleSetString)) { - // Substitute env variables/properties - configuration.setRuleSets(project.replaceProperties(ruleSetString)); - } - ruleSets = rulesetParser.parseFromResourceReference(configuration.getRuleSets()); - logRulesUsed(new RuleSets(ruleSets)); - } catch (RuleSetNotFoundException e) { - throw new BuildException(e.getMessage(), e); + // This is just used to validate and display rules. Each thread will create its own ruleset + String ruleSetString = configuration.getRuleSets(); + if (StringUtils.isNotBlank(ruleSetString)) { + // Substitute env variables/properties + configuration.setRuleSets(project.replaceProperties(ruleSetString)); } + final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), rulesetParser.toFactory()); + List rulesetList = Arrays.asList(ruleSets.getAllRuleSets()); + logRulesUsed(ruleSets); + if (configuration.getSuppressMarker() != null) { project.log("Setting suppress marker to be " + configuration.getSuppressMarker(), Project.MSG_VERBOSE); } @@ -193,7 +190,7 @@ public class PMDTaskImpl { renderers.add(renderer); } try { - PMD.processFiles(configuration, ruleSets, files, report, renderers); + PMD.processFiles(configuration, rulesetList, files, report, renderers); } catch (ContextedRuntimeException e) { if (e.getFirstContextValue("filename") instanceof String) { handleError((String) e.getFirstContextValue("filename"), errorReport, e); @@ -285,6 +282,10 @@ public class PMDTaskImpl { final ScopedLogHandlersManager logManager = new ScopedLogHandlersManager(antLogHandler.getAntLogLevel(), antLogHandler); try { doTask(); + } catch (BuildException e) { + throw e; + } catch (Exception other) { + throw new BuildException(other); } finally { logManager.close(); // only close the classloader, if it is ours. Otherwise we end up with class not found From cc7bb35e72ed6fa016e49dd663b0170ba5951537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 27 Oct 2020 00:30:31 +0100 Subject: [PATCH 13/34] Checkstyle --- .../net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index 9b356fe03c..270238f2a8 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -16,8 +16,8 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParser; import net.sourceforge.pmd.RuleSetNotFoundException; +import net.sourceforge.pmd.RuleSetParser; public class QuickstartRulesetTest { From 36e55bc2c1d4ea0a41d39fed0b9178d876b3447f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 27 Oct 2020 09:15:16 +0100 Subject: [PATCH 14/34] Fix broken rule reporting --- .../pmd/processor/AbstractPMDProcessor.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index ff192c2bb6..d0ad3ae1ef 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -80,13 +80,15 @@ public abstract class AbstractPMDProcessor { */ protected RuleSets createRuleSets(RuleSetFactory factory, Report report) { final RuleSets rs = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), factory); + reportBrokenRules(report, rs); + return rs; + } + public static void reportBrokenRules(Report report, RuleSets rs) { final Set brokenRules = removeBrokenRules(rs); for (final Rule rule : brokenRules) { report.addConfigError(new Report.ConfigurationError(rule, rule.dysfunctionReason())); } - - return rs; } /** @@ -96,7 +98,7 @@ public abstract class AbstractPMDProcessor { * @param ruleSets RuleSets to prune of broken rules. * @return Set */ - private Set removeBrokenRules(final RuleSets ruleSets) { + private static Set removeBrokenRules(final RuleSets ruleSets) { final Set brokenRules = new HashSet<>(); ruleSets.removeDysfunctionalRules(brokenRules); @@ -131,16 +133,17 @@ public abstract class AbstractPMDProcessor { @SuppressWarnings("PMD.CloseResource") // the data sources must only be closed after the threads are finished // this is done manually without a try-with-resources - public void processFiles(RuleSets rs, List files, RuleContext ctx, List renderers) { + public void processFiles(RuleSets rulesets, List files, RuleContext ctx, List renderers) { try { - configuration.getAnalysisCache().checkValidity(rs, configuration.getClassLoader()); + reportBrokenRules(ctx.getReport(), rulesets); + configuration.getAnalysisCache().checkValidity(rulesets, configuration.getClassLoader()); final SourceCodeProcessor processor = new SourceCodeProcessor(configuration); for (final DataSource dataSource : files) { // this is the real, canonical and absolute filename (not shortened) String realFileName = dataSource.getNiceFileName(false, null); - runAnalysis(new PmdRunnable(dataSource, realFileName, renderers, ctx, rs, processor)); + runAnalysis(new PmdRunnable(dataSource, realFileName, renderers, ctx, rulesets, processor)); } // render base report first - general errors From 1ff1e07c4dd10d61141a54138f932ab129b495f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 14:43:38 +0100 Subject: [PATCH 15/34] Return a report instead of side-effecting on it I think this will be more compatible with pmd 7. --- .../main/java/net/sourceforge/pmd/PMD.java | 37 ++++++------------- .../pmd/ant/internal/PMDTaskImpl.java | 3 +- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 370c0ad672..660148eea4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -18,7 +18,6 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; @@ -44,7 +43,6 @@ import net.sourceforge.pmd.processor.AbstractPMDProcessor; 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.ClasspathClassLoader; import net.sourceforge.pmd.util.FileUtil; import net.sourceforge.pmd.util.IOUtil; @@ -240,28 +238,15 @@ public class PMD { renderer.start(); } - final AtomicInteger violations = new AtomicInteger(0); - Report report = new Report(); - report.addListener(new ThreadSafeReportListener() { - @Override - public void ruleViolationAdded(RuleViolation ruleViolation) { - violations.getAndIncrement(); - } - - @Override - public void metricAdded(Metric metric) { - // ignored - not needed for counting violations - } - }); - + Report report; try (TimedOperation to = TimeTracker.startOperation(TimedOperationCategory.FILE_PROCESSING)) { - processFiles(configuration, Arrays.asList(ruleSets.getAllRuleSets()), files, report, renderers); + report = processFiles(configuration, Arrays.asList(ruleSets.getAllRuleSets()), files, renderers); } try (TimedOperation rto = TimeTracker.startOperation(TimedOperationCategory.REPORTING)) { renderer.end(); renderer.flush(); - return violations.get(); + return report.getViolations().size(); } } catch (Exception e) { String message = e.getMessage(); @@ -320,7 +305,7 @@ public class PMD { * @param renderers * List of {@link Renderer}s * - * @deprecated Use {@link #processFiles(PMDConfiguration, List, Collection, Report, List)} + * @deprecated Use {@link #processFiles(PMDConfiguration, List, Collection, List)} * so as not to depend on {@link RuleSetFactory}. Note that this sorts the list of data sources in-place, * which won't be fixed */ @@ -349,16 +334,17 @@ public class PMD { * as parameters * @param rulesets Parsed rulesets * @param files Files to process - * @param report Report in which violations are accumulated * @param renderers Renderers that render the report * + * @return Report in which violations are accumulated + * * @throws RuntimeException If processing fails */ - public static void processFiles(final PMDConfiguration configuration, - final List rulesets, - final Collection files, - final Report report, - final List renderers) { + public static Report processFiles(final PMDConfiguration configuration, + final List rulesets, + final Collection files, + final List renderers) { + Report report = new Report(); encourageToUseIncrementalAnalysis(configuration); report.addListener(configuration.getAnalysisCache()); @@ -369,6 +355,7 @@ public class PMD { ctx.setReport(report); newFileProcessor(configuration).processFiles(new RuleSets(rulesets), sortedFiles, ctx, renderers); configuration.getAnalysisCache().persist(); + return report; } private static void sortFiles(final PMDConfiguration configuration, final List files) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index 101bd4d8ec..c804f5700f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -131,7 +131,6 @@ public class PMDTaskImpl { // TODO Do we really need all this in a loop over each FileSet? Seems // like a lot of redundancy - Report report = new Report(); Report errorReport = new Report(); final AtomicInteger reportSize = new AtomicInteger(); final String separator = System.getProperty("file.separator"); @@ -190,7 +189,7 @@ public class PMDTaskImpl { renderers.add(renderer); } try { - PMD.processFiles(configuration, rulesetList, files, report, renderers); + PMD.processFiles(configuration, rulesetList, files, renderers); } catch (ContextedRuntimeException e) { if (e.getFirstContextValue("filename") instanceof String) { handleError((String) e.getFirstContextValue("filename"), errorReport, e); From 08fca9367e3722fc65b7c7911fe4ade978158c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 14:44:54 +0100 Subject: [PATCH 16/34] Rename RuleSetParser to RuleSetLoader --- .../pmd/lang/apex/DefaultRulesetTest.java | 4 ++-- .../main/java/net/sourceforge/pmd/PMD.java | 2 +- .../net/sourceforge/pmd/RuleSetFactory.java | 24 +++++++++---------- .../pmd/RuleSetFactoryCompatibility.java | 2 +- ...{RuleSetParser.java => RuleSetLoader.java} | 20 ++++++++-------- .../net/sourceforge/pmd/RuleSetReference.java | 2 +- .../sourceforge/pmd/RuleSetReferenceId.java | 2 +- .../sourceforge/pmd/RulesetsFactoryUtils.java | 16 ++++++------- .../pmd/ant/internal/PMDTaskImpl.java | 6 ++--- .../sourceforge/pmd/RuleSetFactoryTest.java | 16 ++++++------- .../pmd/lang/java/PMD5RulesetTest.java | 4 ++-- .../pmd/lang/java/QuickstartRulesetTest.java | 4 ++-- 12 files changed, 51 insertions(+), 51 deletions(-) rename pmd-core/src/main/java/net/sourceforge/pmd/{RuleSetParser.java => RuleSetLoader.java} (88%) diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java index 8a1c2db3c1..e8f53a6d68 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java @@ -16,13 +16,13 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParser; +import net.sourceforge.pmd.RuleSetLoader; public class DefaultRulesetTest { @Rule public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests(); - private RuleSetFactory factory = new RuleSetParser().enableCompatibility(false).toFactory(); + private RuleSetFactory factory = new RuleSetLoader().enableCompatibility(false).toFactory(); @Test public void loadDefaultRuleset() throws Exception { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 660148eea4..118904dbcc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -220,7 +220,7 @@ public class PMD { public static int doPMD(PMDConfiguration configuration) { // Load the RuleSets - final RuleSetFactory ruleSetFactory = RuleSetParser.fromPmdConfig(configuration).toFactory(); + final RuleSetFactory ruleSetFactory = RuleSetLoader.fromPmdConfig(configuration).toFactory(); final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory); if (ruleSets == null) { return PMDCommandLineInterface.NO_ERRORS_STATUS; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 0778035fc3..093a5c12d9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -43,11 +43,11 @@ import net.sourceforge.pmd.util.ResourceLoader; /** * RuleSetFactory is responsible for creating RuleSet instances from XML - * content. See {@link RuleSetParser} for configuration options and + * content. See {@link RuleSetLoader} for configuration options and * their defaults. * - * @deprecated Use a {@link RuleSetParser} instead. This will be hidden in PMD 7 - * (it's the implementation, while {@link RuleSetParser} is the API). + * @deprecated Use a {@link RuleSetLoader} instead. This will be hidden in PMD 7 + * (it's the implementation, while {@link RuleSetLoader} is the API). */ @Deprecated public class RuleSetFactory { @@ -67,7 +67,7 @@ public class RuleSetFactory { private final Map parsedRulesets = new HashMap<>(); /** - * @deprecated Use a {@link RuleSetParser} to build a new factory + * @deprecated Use a {@link RuleSetLoader} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory() { @@ -75,7 +75,7 @@ public class RuleSetFactory { } /** - * @deprecated Use a {@link RuleSetParser} to build a new factory + * @deprecated Use a {@link RuleSetLoader} to build a new factory */ @Deprecated // to be removed with PMD 7.0.0. public RuleSetFactory(final ClassLoader classLoader, final RulePriority minimumPriority, @@ -84,7 +84,7 @@ public class RuleSetFactory { } /** - * @deprecated Use a {@link RuleSetParser} to build a new factory + * @deprecated Use a {@link RuleSetLoader} to build a new factory */ @Deprecated // to be hidden with PMD 7.0.0. public RuleSetFactory(final ResourceLoader resourceLoader, final RulePriority minimumPriority, @@ -123,7 +123,7 @@ public class RuleSetFactory { } - RuleSetFactory(RuleSetParser config) { + RuleSetFactory(RuleSetLoader config) { this(config.resourceLoader, config.minimumPriority, config.warnDeprecated, config.enableCompatibility, config.includeDeprecatedRuleReferences); } @@ -184,7 +184,7 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException * if unable to find a resource. * - * @deprecated Use {@link RuleSetParser#parseFromResource(String)}, + * @deprecated Use {@link RuleSetLoader#parseFromResource(String)}, * but note that that method does not split on commas */ @Deprecated @@ -227,7 +227,7 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException * if unable to find a resource. * - * @deprecated Use {@link RuleSetParser#parseFromResource(String)} and discard the rest of the list. + * @deprecated Use {@link RuleSetLoader#parseFromResource(String)} and discard the rest of the list. */ @Deprecated public RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException { @@ -846,11 +846,11 @@ public class RuleSetFactory { /** - * Create a new {@link RuleSetParser} with the same config as this + * Create a new {@link RuleSetLoader} with the same config as this * factory. This is a transitional API. */ - public RuleSetParser toParser() { - return new RuleSetParser().loadResourcesWith(resourceLoader) + public RuleSetLoader toParser() { + return new RuleSetLoader().loadResourcesWith(resourceLoader) .filterAbovePriority(minimumPriority) .warnDeprecated(warnDeprecated) .enableCompatibility(compatibilityFilter != null) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java index b3d5d51a7b..6ed1d189a4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java @@ -27,7 +27,7 @@ import net.sourceforge.pmd.annotation.InternalApi; * * @see issue 1360 * - * @deprecated Use {@link RuleSetParser#enableCompatibility(boolean)} to enable this feature. + * @deprecated Use {@link RuleSetLoader#enableCompatibility(boolean)} to enable this feature. * This implementation is internal API. */ @InternalApi diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java similarity index 88% rename from pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java rename to pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index 72b3dc60b7..cb6cb1cdc5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -17,9 +17,9 @@ import net.sourceforge.pmd.util.ResourceLoader; * API, see eg {@link #warnDeprecated(boolean)}. To create a list of * rulesets, use {@link #parseFromResource(String)}. */ -public final class RuleSetParser { +public final class RuleSetLoader { - ResourceLoader resourceLoader = new ResourceLoader(RuleSetParser.class.getClassLoader()); + ResourceLoader resourceLoader = new ResourceLoader(RuleSetLoader.class.getClassLoader()); RulePriority minimumPriority = RulePriority.LOW; boolean warnDeprecated = true; boolean enableCompatibility = true; @@ -30,13 +30,13 @@ public final class RuleSetParser { * paths to external ruleset references. The default uses PMD's * own classpath. */ - public RuleSetParser loadResourcesWith(ClassLoader classLoader) { + public RuleSetLoader loadResourcesWith(ClassLoader classLoader) { this.resourceLoader = new ResourceLoader(classLoader); return this; } // internal - RuleSetParser loadResourcesWith(ResourceLoader loader) { + RuleSetLoader loadResourcesWith(ResourceLoader loader) { this.resourceLoader = loader; return this; } @@ -47,7 +47,7 @@ public final class RuleSetParser { * ie, no filtering occurs. * @return This instance, modified */ - public RuleSetParser filterAbovePriority(RulePriority minimumPriority) { + public RuleSetLoader filterAbovePriority(RulePriority minimumPriority) { this.minimumPriority = minimumPriority; return this; } @@ -57,7 +57,7 @@ public final class RuleSetParser { * This is enabled by default. * @return This instance, modified */ - public RuleSetParser warnDeprecated(boolean warn) { + public RuleSetLoader warnDeprecated(boolean warn) { this.warnDeprecated = warn; return this; } @@ -69,7 +69,7 @@ public final class RuleSetParser { * error. * @return This instance, modified */ - public RuleSetParser enableCompatibility(boolean enable) { + public RuleSetLoader enableCompatibility(boolean enable) { this.enableCompatibility = enable; return this; } @@ -81,7 +81,7 @@ public final class RuleSetParser { * * @return This instance, modified */ - public RuleSetParser includeDeprecatedRuleReferences(boolean enable) { + public RuleSetLoader includeDeprecatedRuleReferences(boolean enable) { this.includeDeprecatedRuleReferences = enable; return this; } @@ -149,8 +149,8 @@ public final class RuleSetParser { * Configure a new ruleset factory builder according to the parameters * of the given PMD configuration. */ - public static RuleSetParser fromPmdConfig(PMDConfiguration configuration) { - return new RuleSetParser().filterAbovePriority(configuration.getMinimumPriority()) + public static RuleSetLoader fromPmdConfig(PMDConfiguration configuration) { + return new RuleSetLoader().filterAbovePriority(configuration.getMinimumPriority()) .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java index 32e2eeedb7..cdc6e5f77c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReference.java @@ -13,7 +13,7 @@ import net.sourceforge.pmd.annotation.InternalApi; /** * This class represents a reference to RuleSet. * - * @deprecated This is part of the internals of the {@link RuleSetParser}. + * @deprecated This is part of the internals of the {@link RuleSetLoader}. */ @Deprecated @InternalApi diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java index bac49f5f86..66dd5e47c9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java @@ -80,7 +80,7 @@ import net.sourceforge.pmd.util.ResourceLoader; * * * - * @deprecated This is part of the internals of the {@link RuleSetParser}. + * @deprecated This is part of the internals of the {@link RuleSetLoader}. */ @Deprecated @InternalApi diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java index c835b9ac9e..135736f8a6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java @@ -14,7 +14,7 @@ import net.sourceforge.pmd.benchmark.TimedOperationCategory; import net.sourceforge.pmd.util.ResourceLoader; /** - * @deprecated Use a {@link RuleSetParser} instead + * @deprecated Use a {@link RuleSetLoader} instead */ @Deprecated public final class RulesetsFactoryUtils { @@ -80,7 +80,7 @@ public final class RulesetsFactoryUtils { } /** - * @deprecated Use a {@link RuleSetParser} + * @deprecated Use a {@link RuleSetLoader} */ @InternalApi @Deprecated @@ -101,7 +101,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration, ClassLoader) * - * @deprecated Use {@link RuleSetParser#fromPmdConfig(PMDConfiguration)} + * @deprecated Use {@link RuleSetLoader#fromPmdConfig(PMDConfiguration)} */ @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration) { @@ -114,7 +114,7 @@ public final class RulesetsFactoryUtils { * * @return A ruleset factory * - * @see RuleSetParser + * @see RuleSetLoader */ public static RuleSetFactory defaultFactory() { return new RuleSetFactory(); @@ -132,7 +132,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetParser} + * @deprecated Use a {@link RuleSetLoader} */ @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration, ClassLoader classLoader) { @@ -156,7 +156,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetParser} + * @deprecated Use a {@link RuleSetLoader} */ @Deprecated public static RuleSetFactory createFactory(ClassLoader classLoader, @@ -180,7 +180,7 @@ public final class RulesetsFactoryUtils { * * @see #createFactory(PMDConfiguration) * - * @deprecated Use a {@link RuleSetParser} + * @deprecated Use a {@link RuleSetLoader} */ @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, @@ -205,7 +205,7 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) - * @deprecated Use a {@link RuleSetParser} + * @deprecated Use a {@link RuleSetLoader} */ @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index c804f5700f..685c459bd9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -29,7 +29,7 @@ import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetParser; +import net.sourceforge.pmd.RuleSetLoader; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.ant.Formatter; @@ -102,7 +102,7 @@ public class PMDTaskImpl { setupClassLoader(); // Setup RuleSetFactory and validate RuleSets - RuleSetParser rulesetParser = RuleSetParser.fromPmdConfig(configuration) + RuleSetLoader rulesetLoader = RuleSetLoader.fromPmdConfig(configuration) .loadResourcesWith(setupResourceLoader()); // This is just used to validate and display rules. Each thread will create its own ruleset @@ -112,7 +112,7 @@ public class PMDTaskImpl { configuration.setRuleSets(project.replaceProperties(ruleSetString)); } - final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), rulesetParser.toFactory()); + final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), rulesetLoader.toFactory()); List rulesetList = Arrays.asList(ruleSets.getAllRuleSets()); logRulesUsed(ruleSets); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 455d0287b9..bfbc7ce547 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -505,7 +505,7 @@ public class RuleSetFactoryTest { @Test public void testReferencePriority() throws RuleSetNotFoundException { - RuleSetParser config = new RuleSetParser().warnDeprecated(false).enableCompatibility(true); + RuleSetLoader config = new RuleSetLoader().warnDeprecated(false).enableCompatibility(true); RuleSetFactory rsf = config.filterAbovePriority(RulePriority.LOW).toFactory(); RuleSet ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); @@ -546,7 +546,7 @@ public class RuleSetFactoryTest { @Test public void testOverridePriorityLoadWithMinimum() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); + RuleSetFactory rsf = new RuleSetLoader().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); // only one rule should remain, since we filter out the other rule by minimum priority assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -567,13 +567,13 @@ public class RuleSetFactoryTest { @Test public void testExcludeWithMinimumPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.HIGH).toFactory(); + RuleSetFactory rsf = new RuleSetLoader().filterAbovePriority(RulePriority.HIGH).toFactory(); RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // no rules should be loaded assertEquals("Number of Rules", 0, ruleset.getRules().size()); // now, load with default minimum priority - rsf = new RuleSetParser().filterAbovePriority(RulePriority.LOW).toFactory(); + rsf = new RuleSetLoader().filterAbovePriority(RulePriority.LOW).toFactory(); ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // only one rule, we have excluded one... assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -602,9 +602,9 @@ public class RuleSetFactoryTest { @Test public void testSetPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).toFactory(); + RuleSetFactory rsf = new RuleSetLoader().filterAbovePriority(RulePriority.MEDIUM_HIGH).warnDeprecated(false).toFactory(); assertEquals(0, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); - rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).toFactory(); + rsf = new RuleSetLoader().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(false).toFactory(); assertEquals(1, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); } @@ -779,7 +779,7 @@ public class RuleSetFactoryTest { + " Ruleset which references a empty ruleset\n" + "\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = new RuleSetParser().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); + RuleSetFactory ruleSetFactory = new RuleSetLoader().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref); assertEquals(0, ruleset.getRules().size()); @@ -1284,7 +1284,7 @@ public class RuleSetFactoryTest { } private RuleSet loadRuleSetWithDeprecationWarnings(String ruleSetXml) throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetParser().warnDeprecated(true).enableCompatibility(false).toFactory(); + RuleSetFactory rsf = new RuleSetLoader().warnDeprecated(true).enableCompatibility(false).toFactory(); return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml)); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java index d4406a6ed0..23de5ce3de 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java @@ -9,13 +9,13 @@ import org.junit.Test; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetParser; +import net.sourceforge.pmd.RuleSetLoader; public class PMD5RulesetTest { @Test public void loadRuleset() throws Exception { - RuleSetFactory ruleSetFactory = new RuleSetParser().toFactory(); + RuleSetFactory ruleSetFactory = new RuleSetLoader().toFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet("net/sourceforge/pmd/lang/java/pmd5ruleset.xml"); Assert.assertNotNull(ruleset); Assert.assertNull(ruleset.getRuleByName("GuardLogStatementJavaUtil")); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index 270238f2a8..16c3142ab9 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -16,8 +16,8 @@ import org.junit.contrib.java.lang.system.SystemErrRule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetLoader; import net.sourceforge.pmd.RuleSetNotFoundException; -import net.sourceforge.pmd.RuleSetParser; public class QuickstartRulesetTest { @@ -49,7 +49,7 @@ public class QuickstartRulesetTest { } }); - RuleSetFactory ruleSetFactory = new RuleSetParser().enableCompatibility(false).toFactory(); + RuleSetFactory ruleSetFactory = new RuleSetLoader().enableCompatibility(false).toFactory(); RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); Assert.assertFalse(quickstart.getRules().isEmpty()); } From 4f175a1c4fca8a88d9a688f68b149ec2fbcb6142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 14:48:29 +0100 Subject: [PATCH 17/34] Hide RuleSetLoader fields --- .../net/sourceforge/pmd/RuleSetFactory.java | 4 ---- .../net/sourceforge/pmd/RuleSetLoader.java | 23 +++++++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 093a5c12d9..aa490e4dea 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -123,10 +123,6 @@ public class RuleSetFactory { } - RuleSetFactory(RuleSetLoader config) { - this(config.resourceLoader, config.minimumPriority, config.warnDeprecated, config.enableCompatibility, config.includeDeprecatedRuleReferences); - } - /** * Gets the compatibility filter in order to adjust it, e.g. add additional * filters. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index cb6cb1cdc5..27910274cd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -19,11 +19,11 @@ import net.sourceforge.pmd.util.ResourceLoader; */ public final class RuleSetLoader { - ResourceLoader resourceLoader = new ResourceLoader(RuleSetLoader.class.getClassLoader()); - RulePriority minimumPriority = RulePriority.LOW; - boolean warnDeprecated = true; - boolean enableCompatibility = true; - boolean includeDeprecatedRuleReferences = false; + private ResourceLoader resourceLoader = new ResourceLoader(RuleSetLoader.class.getClassLoader()); + private RulePriority minimumPriority = RulePriority.LOW; + private boolean warnDeprecated = true; + private boolean enableCompatibility = true; + private boolean includeDeprecatedRuleReferences = false; /** * Specify that the given classloader should be used to resolve @@ -89,10 +89,19 @@ public final class RuleSetLoader { /** * Create a new rule set factory, if you have to (that class is deprecated). * That factory will use the configuration that was set using the setters of this. + * + * @deprecated {@link RuleSetFactory} is deprecated, replace its usages with usages of this class, + * or of static factory methods of {@link RuleSet} */ @Deprecated public RuleSetFactory toFactory() { - return new RuleSetFactory(this); + return new RuleSetFactory( + this.resourceLoader, + this.minimumPriority, + this.warnDeprecated, + this.enableCompatibility, + this.includeDeprecatedRuleReferences + ); } @@ -141,7 +150,7 @@ public final class RuleSetLoader { // package private RuleSet parseFromResource(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { - return new RuleSetFactory(this).createRuleSet(ruleSetReferenceId); + return toFactory().createRuleSet(ruleSetReferenceId); } From 8f7801c2e71b62e9520f097aec7ed69648cda64a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 14:51:23 +0100 Subject: [PATCH 18/34] Remove try with resources --- pmd-core/src/main/java/net/sourceforge/pmd/PMD.java | 2 +- .../pmd/processor/AbstractPMDProcessor.java | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 118904dbcc..8985dfa8a7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -344,8 +344,8 @@ public class PMD { final List rulesets, final Collection files, final List renderers) { - Report report = new Report(); encourageToUseIncrementalAnalysis(configuration); + Report report = new Report(); report.addListener(configuration.getAnalysisCache()); List sortedFiles = new ArrayList<>(files); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index d0ad3ae1ef..a77181b2e3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -118,16 +118,8 @@ public abstract class AbstractPMDProcessor { @Deprecated public void processFiles(RuleSetFactory ruleSetFactory, List files, RuleContext ctx, List renderers) { - try { - final RuleSets rs = createRuleSets(ruleSetFactory, ctx.getReport()); - processFiles(rs, files, ctx, renderers); - } finally { - // in case we analyzed files within Zip Files/Jars, we need to close them after - // the analysis is finished - for (DataSource dataSource : files) { - IOUtils.closeQuietly(dataSource); - } - } + RuleSets rs = createRuleSets(ruleSetFactory, ctx.getReport()); + processFiles(rs, files, ctx, renderers); } @SuppressWarnings("PMD.CloseResource") From e30fcaf31dffa9fa3c2e15df4f901bce1e212460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 14:52:45 +0100 Subject: [PATCH 19/34] Rename to loadFromResources --- .../java/net/sourceforge/pmd/RuleSetFactory.java | 4 ++-- .../java/net/sourceforge/pmd/RuleSetLoader.java | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index aa490e4dea..199e36a25d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -180,7 +180,7 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException * if unable to find a resource. * - * @deprecated Use {@link RuleSetLoader#parseFromResource(String)}, + * @deprecated Use {@link RuleSetLoader#loadFromResource(String)}, * but note that that method does not split on commas */ @Deprecated @@ -223,7 +223,7 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException * if unable to find a resource. * - * @deprecated Use {@link RuleSetLoader#parseFromResource(String)} and discard the rest of the list. + * @deprecated Use {@link RuleSetLoader#loadFromResource(String)} and discard the rest of the list. */ @Deprecated public RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index 27910274cd..34a876717b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -15,7 +15,7 @@ import net.sourceforge.pmd.util.ResourceLoader; * Configurable ruleset parser. Note that this replaces the API of {@link RulesetsFactoryUtils} * and {@link RuleSetFactory}. This can be configured using a fluent * API, see eg {@link #warnDeprecated(boolean)}. To create a list of - * rulesets, use {@link #parseFromResource(String)}. + * rulesets, use {@link #loadFromResource(String)}. */ public final class RuleSetLoader { @@ -116,8 +116,8 @@ public final class RuleSetLoader { * * @throws RuleSetNotFoundException If the path does not correspond to a resource */ - public RuleSet parseFromResource(String rulesetPath) throws RuleSetNotFoundException { - return parseFromResource(new RuleSetReferenceId(rulesetPath)); + public RuleSet loadFromResource(String rulesetPath) throws RuleSetNotFoundException { + return loadFromResource(new RuleSetReferenceId(rulesetPath)); } /** @@ -128,10 +128,10 @@ public final class RuleSetLoader { * @throws RuleSetNotFoundException If any resource throws * @throws NullPointerException If the parameter, or any component is null */ - public List parseFromResources(Collection paths) throws RuleSetNotFoundException { + public List loadFromResources(Collection paths) throws RuleSetNotFoundException { List ruleSets = new ArrayList<>(paths.size()); for (String path : paths) { - ruleSets.add(parseFromResource(path)); + ruleSets.add(loadFromResource(path)); } return ruleSets; } @@ -144,12 +144,12 @@ public final class RuleSetLoader { * @throws RuleSetNotFoundException If any resource throws * @throws NullPointerException If the parameter, or any component is null */ - public List parseFromResources(String... paths) throws RuleSetNotFoundException { - return parseFromResources(Arrays.asList(paths)); + public List loadFromResources(String... paths) throws RuleSetNotFoundException { + return loadFromResources(Arrays.asList(paths)); } // package private - RuleSet parseFromResource(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { + RuleSet loadFromResource(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { return toFactory().createRuleSet(ruleSetReferenceId); } From ccaf57e8d650f4564ff65f9f4ec55ee800a1b273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 14:54:54 +0100 Subject: [PATCH 20/34] Update release notes --- docs/pages/release_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 710428b79d..4487ee4bf5 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -22,14 +22,14 @@ This is a {{ site.pmd.release_type }} release. ##### Around RuleSet parsing -* {% jdoc core::RuleSetFactory %} and {% jdoc core::RuleSetFactoryUtils %} have been deprecated in favor of {% jdoc core::RuleSetParser %}. This is easier to configure, and more maintainable than the multiple overloads of `RuleSetFactoryUtils`. +* {% jdoc core::RuleSetFactory %} and {% jdoc core::RuleSetFactoryUtils %} have been deprecated in favor of {% jdoc core::RuleSetLoader %}. This is easier to configure, and more maintainable than the multiple overloads of `RuleSetFactoryUtils`. * Some static creation methods have been added to {% jdoc core::RuleSet %} for simple cases, eg {% jdoc core::RuleSet#forSingleRule(core::Rule) %}. These replace some counterparts in {% jdoc core::RuleSetFactory %} * Since {% jdoc core::RuleSets %} is also deprecated, many APIs that require a RuleSets instance now are deprecated, and have a counterpart that expects a `List`. * {% jdoc core::RuleSetReferenceId %}, {% jdoc core::RuleSetReference %}, {% jdoc core::RuleSetFactoryCompatibility %} are deprecated. They are most likely not relevant outside of the implementation of pmd-core. ##### Around the `PMD` class -Many APIs around PMD's entry point ({% jdoc core::PMD %}) have been deprecated, including: +Many classes around PMD's entry point ({% jdoc core::PMD %}) have been deprecated as internal, including: * The contents of the packages {% jdoc_package core::cli %}, {% jdoc_package core::processor %} * {% jdoc core::SourceCodeProcessor %} * The constructors of {% jdoc core::PMD %} (the class will be made a utility class) From 6eee3d037f4af2b6c591f361d0e91e337fcd7742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 3 Nov 2020 15:05:58 +0100 Subject: [PATCH 21/34] Provide replacement api for getRegisteredRuleSets --- .../main/java/net/sourceforge/pmd/PMD.java | 2 +- .../net/sourceforge/pmd/RuleSetFactory.java | 42 ++++--------------- .../net/sourceforge/pmd/RuleSetLoader.java | 42 +++++++++++++++++++ .../pmd/RuleSetNotFoundException.java | 4 ++ .../java/net/sourceforge/pmd/RuleSets.java | 5 +++ 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 8985dfa8a7..47619f4844 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -321,7 +321,7 @@ public class PMD { // Make sure the cache is listening for analysis results ctx.getReport().addListener(configuration.getAnalysisCache()); - final RuleSetFactory silentFactory = ruleSetFactory.toParser().warnDeprecated(false).toFactory(); + final RuleSetFactory silentFactory = ruleSetFactory.toLoader().warnDeprecated(false).toFactory(); newFileProcessor(configuration).processFiles(silentFactory, files, ctx, renderers); configuration.getAnalysisCache().persist(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 199e36a25d..8cf19d28d5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -13,7 +13,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -34,8 +33,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import net.sourceforge.pmd.RuleSet.RuleSetBuilder; -import net.sourceforge.pmd.lang.Language; -import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.rules.RuleFactory; @@ -109,13 +106,11 @@ public class RuleSetFactory { /** * Constructor copying all configuration from another factory. * - * @param factory - * The factory whose configuration to copy. - * @param warnDeprecated - * Whether deprecation warnings are to be produced by this - * factory + * @param factory The factory whose configuration to copy. + * @param warnDeprecated Whether deprecation warnings are to be produced by this + * factory * - * @deprecated Use {@link #toParser()} to rebuild a factory from a configuration + * @deprecated Use {@link #toLoader()} to rebuild a factory from a configuration */ @Deprecated public RuleSetFactory(final RuleSetFactory factory, final boolean warnDeprecated) { @@ -141,30 +136,11 @@ public class RuleSetFactory { * * @throws RuleSetNotFoundException if the ruleset file could not be found * - * @deprecated This is apparently only used in code deprecated for removal + * @deprecated Use {@link RuleSetLoader#getStandardRuleSets()} */ @Deprecated public Iterator getRegisteredRuleSets() throws RuleSetNotFoundException { - String rulesetsProperties = null; - List ruleSetReferenceIds = new ArrayList<>(); - for (Language language : LanguageRegistry.findWithRuleSupport()) { - Properties props = new Properties(); - rulesetsProperties = "category/" + language.getTerseName() + "/categories.properties"; - try (InputStream inputStream = resourceLoader.loadClassPathResourceAsStreamOrThrow(rulesetsProperties)) { - props.load(inputStream); - String rulesetFilenames = props.getProperty("rulesets.filenames"); - if (rulesetFilenames != null) { - ruleSetReferenceIds.addAll(RuleSetReferenceId.parse(rulesetFilenames)); - } - } catch (RuleSetNotFoundException e) { - LOG.warning("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); - } catch (IOException ioe) { - throw new RuntimeException("Couldn't find " + rulesetsProperties - + "; please ensure that the directory is on the classpath. The current classpath is: " - + System.getProperty("java.class.path")); - } - } - return createRuleSets(ruleSetReferenceIds).getRuleSetsIterator(); + return toLoader().getStandardRuleSets().iterator(); } /** @@ -564,7 +540,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = toParser().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory(); + RuleSetFactory ruleSetFactory = toLoader().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory(); RuleSet otherRuleSet = ruleSetFactory.createRuleSet(RuleSetReferenceId.parse(ref).get(0)); List potentialRules = new ArrayList<>(); int countDeprecated = 0; @@ -679,7 +655,7 @@ public class RuleSetFactory { // load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule // minimum priority will be applied again, before constructing the final ruleset - RuleSetFactory ruleSetFactory = toParser().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory(); + RuleSetFactory ruleSetFactory = toLoader().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory(); boolean isSameRuleSet = false; RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0); @@ -845,7 +821,7 @@ public class RuleSetFactory { * Create a new {@link RuleSetLoader} with the same config as this * factory. This is a transitional API. */ - public RuleSetLoader toParser() { + public RuleSetLoader toLoader() { return new RuleSetLoader().loadResourcesWith(resourceLoader) .filterAbovePriority(minimumPriority) .warnDeprecated(warnDeprecated) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index 34a876717b..032372ae7c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -4,11 +4,17 @@ package net.sourceforge.pmd; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Properties; +import java.util.logging.Logger; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.util.ResourceLoader; /** @@ -19,6 +25,8 @@ import net.sourceforge.pmd.util.ResourceLoader; */ public final class RuleSetLoader { + private static final Logger LOG = Logger.getLogger(RuleSetLoader.class.getName()); + private ResourceLoader resourceLoader = new ResourceLoader(RuleSetLoader.class.getClassLoader()); private RulePriority minimumPriority = RulePriority.LOW; private boolean warnDeprecated = true; @@ -162,4 +170,38 @@ public final class RuleSetLoader { return new RuleSetLoader().filterAbovePriority(configuration.getMinimumPriority()) .enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled()); } + + + /** + * Returns an Iterator of RuleSet objects loaded from descriptions from the + * "categories.properties" resource for each Language with Rule support. This + * uses the classpath of the resource loader ({@link #loadResourcesWith(ClassLoader)}). + * + * @return A list of all category rulesets + * + * @throws RuleSetNotFoundException if some ruleset file could not be parsed + * TODO shouldn't our API forbid this case? + */ + public List getStandardRuleSets() throws RuleSetNotFoundException { + String rulesetsProperties; + List ruleSetReferenceIds = new ArrayList<>(); + for (Language language : LanguageRegistry.findWithRuleSupport()) { + Properties props = new Properties(); + rulesetsProperties = "category/" + language.getTerseName() + "/categories.properties"; + try (InputStream inputStream = resourceLoader.loadClassPathResourceAsStreamOrThrow(rulesetsProperties)) { + props.load(inputStream); + String rulesetFilenames = props.getProperty("rulesets.filenames"); + if (rulesetFilenames != null) { + ruleSetReferenceIds.addAll(RuleSetReferenceId.parse(rulesetFilenames)); + } + } catch (RuleSetNotFoundException e) { + LOG.fine("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); + } catch (IOException ioe) { + throw new RuleSetNotFoundException("Couldn't read " + rulesetsProperties + + "; please ensure that the directory is on the classpath. The current classpath is: " + + System.getProperty("java.class.path"), ioe); + } + } + return toFactory().createRuleSets(ruleSetReferenceIds).getRuleSetsInternal(); + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java index 0ad22f4c68..5c86702518 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java @@ -10,4 +10,8 @@ public class RuleSetNotFoundException extends Exception { public RuleSetNotFoundException(String msg) { super(msg); } + + public RuleSetNotFoundException(String msg, Throwable cause) { + super(msg, cause); + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java index c0e43ddb10..c107765f0a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSets.java @@ -95,6 +95,11 @@ public class RuleSets { return ruleSets.toArray(new RuleSet[0]); } + // internal + List getRuleSetsInternal() { + return ruleSets; + } + public Iterator getRuleSetsIterator() { return ruleSets.iterator(); } From 87892adefe4b6dfe9055ea9f04a5ef98ff6b30d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 13 Nov 2020 17:23:43 +0100 Subject: [PATCH 22/34] Fix unnecessary throws clause --- .../src/main/java/net/sourceforge/pmd/RuleSetFactory.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 8cf19d28d5..efd2b0ab31 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -421,9 +421,6 @@ public class RuleSetFactory { ruleSetBuilder.filterRulesByPriority(minimumPriority); return ruleSetBuilder.build(); - } catch (ReflectiveOperationException ex) { - ex.printStackTrace(); - throw new RuntimeException("Couldn't find the class " + ex.getMessage(), ex); } catch (ParserConfigurationException | IOException | SAXException ex) { ex.printStackTrace(); throw new RuntimeException("Couldn't read the ruleset " + ruleSetReferenceId + ": " + ex.getMessage(), ex); @@ -495,7 +492,7 @@ public class RuleSetFactory { */ private void parseRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetBuilder ruleSetBuilder, Node ruleNode, boolean withDeprecatedRuleReferences, Set rulesetReferences) - throws ClassNotFoundException, InstantiationException, IllegalAccessException, RuleSetNotFoundException { + throws RuleSetNotFoundException { Element ruleElement = (Element) ruleNode; String ref = ruleElement.getAttribute("ref"); if (ref.endsWith("xml")) { @@ -603,7 +600,7 @@ public class RuleSetFactory { * Must be a rule element node. */ private void parseSingleRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetBuilder ruleSetBuilder, - Node ruleNode) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + Node ruleNode) { Element ruleElement = (Element) ruleNode; // Stop if we're looking for a particular Rule, and this element is not From 87e2a9c99b2b546c99ad776ddf3754053adb3be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 24 Nov 2020 13:05:21 +0100 Subject: [PATCH 23/34] Replace checked exception with wrapper --- .../net/sourceforge/pmd/RuleSetLoader.java | 68 ++++++++++++------- .../pmd/RuleSetNotFoundException.java | 6 ++ .../sourceforge/pmd/RulesetLoadException.java | 32 +++++++++ 3 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index 032372ae7c..53e65a8cba 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -7,21 +7,22 @@ package net.sourceforge.pmd; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Properties; +import java.util.logging.Level; import java.util.logging.Logger; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.ResourceLoader; /** - * Configurable ruleset parser. Note that this replaces the API of {@link RulesetsFactoryUtils} - * and {@link RuleSetFactory}. This can be configured using a fluent - * API, see eg {@link #warnDeprecated(boolean)}. To create a list of - * rulesets, use {@link #loadFromResource(String)}. + * Configurable object to load rulesets from XML resources. + * This can be configured using a fluent API, see eg {@link #warnDeprecated(boolean)}. + * To create a new ruleset, use {@link #loadFromResource(String)} + * or some such overload. */ public final class RuleSetLoader { @@ -98,8 +99,8 @@ public final class RuleSetLoader { * Create a new rule set factory, if you have to (that class is deprecated). * That factory will use the configuration that was set using the setters of this. * - * @deprecated {@link RuleSetFactory} is deprecated, replace its usages with usages of this class, - * or of static factory methods of {@link RuleSet} + * @deprecated {@link RuleSetFactory} is deprecated, replace its usages + * with usages of this class, or of static factory methods of {@link RuleSet} */ @Deprecated public RuleSetFactory toFactory() { @@ -122,9 +123,9 @@ public final class RuleSetLoader { * * @param rulesetPath A reference to a single ruleset * - * @throws RuleSetNotFoundException If the path does not correspond to a resource + * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found) */ - public RuleSet loadFromResource(String rulesetPath) throws RuleSetNotFoundException { + public RuleSet loadFromResource(String rulesetPath) { return loadFromResource(new RuleSetReferenceId(rulesetPath)); } @@ -133,10 +134,11 @@ public final class RuleSetLoader { * * @param paths Paths * - * @throws RuleSetNotFoundException If any resource throws - * @throws NullPointerException If the parameter, or any component is null + * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found), + * for any of the parameters + * @throws NullPointerException If the parameter, or any component is null */ - public List loadFromResources(Collection paths) throws RuleSetNotFoundException { + public List loadFromResources(Collection paths) { List ruleSets = new ArrayList<>(paths.size()); for (String path : paths) { ruleSets.add(loadFromResource(path)); @@ -147,18 +149,24 @@ public final class RuleSetLoader { /** * Parses several resources into a list of rulesets. * - * @param paths Paths + * @param first First path + * @param rest Paths * - * @throws RuleSetNotFoundException If any resource throws - * @throws NullPointerException If the parameter, or any component is null + * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found), + * for any of the parameters + * @throws NullPointerException If the parameter, or any component is null */ - public List loadFromResources(String... paths) throws RuleSetNotFoundException { - return loadFromResources(Arrays.asList(paths)); + public List loadFromResources(String first, String... rest) { + return loadFromResources(CollectionUtil.listOf(first, rest)); } // package private - RuleSet loadFromResource(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { - return toFactory().createRuleSet(ruleSetReferenceId); + RuleSet loadFromResource(RuleSetReferenceId ruleSetReferenceId) { + try { + return toFactory().createRuleSet(ruleSetReferenceId); + } catch (Exception e) { + throw new RulesetLoadException("Cannot parse " + ruleSetReferenceId, e); + } } @@ -182,7 +190,7 @@ public final class RuleSetLoader { * @throws RuleSetNotFoundException if some ruleset file could not be parsed * TODO shouldn't our API forbid this case? */ - public List getStandardRuleSets() throws RuleSetNotFoundException { + public List getStandardRuleSets() { String rulesetsProperties; List ruleSetReferenceIds = new ArrayList<>(); for (Language language : LanguageRegistry.findWithRuleSupport()) { @@ -195,13 +203,23 @@ public final class RuleSetLoader { ruleSetReferenceIds.addAll(RuleSetReferenceId.parse(rulesetFilenames)); } } catch (RuleSetNotFoundException e) { - LOG.fine("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); + } } catch (IOException ioe) { - throw new RuleSetNotFoundException("Couldn't read " + rulesetsProperties - + "; please ensure that the directory is on the classpath. The current classpath is: " - + System.getProperty("java.class.path"), ioe); + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("Couldn't read " + rulesetsProperties + + "; please ensure that the directory is on the classpath. The current classpath is: " + + System.getProperty("java.class.path")); + LOG.fine(ioe.toString()); + } } } - return toFactory().createRuleSets(ruleSetReferenceIds).getRuleSetsInternal(); + + List ruleSets = new ArrayList<>(); + for (RuleSetReferenceId id : ruleSetReferenceIds) { + ruleSets.add(loadFromResource(id)); // may throw + } + return ruleSets; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java index 5c86702518..05dd3d4be2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java @@ -4,7 +4,13 @@ package net.sourceforge.pmd; +/** + * @deprecated This is now only thrown by deprecated apis. {@link RuleSetLoader} + * throws {@link RulesetLoadException} instead + */ +@Deprecated public class RuleSetNotFoundException extends Exception { + private static final long serialVersionUID = -4617033110919250810L; public RuleSetNotFoundException(String msg) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java new file mode 100644 index 0000000000..7979971118 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java @@ -0,0 +1,32 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +import net.sourceforge.pmd.annotation.InternalApi; + +/** + * An exception that is thrown when something wrong occurs while + * {@linkplain RuleSetLoader loading rulesets}. This may be because the + * XML is not well-formed, does not respect the ruleset schema, is + * not a valid ruleset or is otherwise unparsable. + * + *

In the new {@link RuleSetLoader} API, this is thrown instead of + * {@link RuleSetNotFoundException}. + */ +public final class RulesetLoadException extends RuntimeException { + + /** Constructors are internal. */ + @InternalApi + public RulesetLoadException(String message, Throwable cause) { + super(message, cause); + } + + /** Constructors are internal. */ + @InternalApi + public RulesetLoadException(String message) { + super(message); + } + +} From b0df6a82480a91c28902420befed86d9db237b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 24 Nov 2020 13:18:30 +0100 Subject: [PATCH 24/34] Update pmd-doc module to use newer apis --- .../pmd/docs/GenerateRuleDocsCmd.java | 11 +--- .../pmd/docs/RuleDocGenerator.java | 61 +++++++------------ 2 files changed, 24 insertions(+), 48 deletions(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java index 2256a21d18..1658262fb3 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java @@ -13,24 +13,20 @@ import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import org.apache.commons.io.FilenameUtils; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetNotFoundException; -import net.sourceforge.pmd.RulesetsFactoryUtils; +import net.sourceforge.pmd.RuleSetLoader; public final class GenerateRuleDocsCmd { private GenerateRuleDocsCmd() { // Utility class } - public static void main(String[] args) throws RuleSetNotFoundException { + public static void main(String[] args) throws IOException { if (args.length != 1) { System.err.println("One argument is required: The base directory of the module pmd-doc."); System.exit(1); @@ -41,8 +37,7 @@ public final class GenerateRuleDocsCmd { System.out.println("Generating docs into " + output); // important: use a RuleSetFactory that includes all rules, e.g. deprecated rule references - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(RulePriority.LOW, false, false, true); - Iterator registeredRuleSets = ruleSetFactory.getRegisteredRuleSets(); + List registeredRuleSets = new RuleSetLoader().getStandardRuleSets(); List additionalRulesets = findAdditionalRulesets(output); RuleDocGenerator generator = new RuleDocGenerator(new DefaultFileWriter(), output); diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index f62400b1a9..2b5d83c0cc 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -17,7 +17,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -29,6 +28,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; @@ -36,9 +36,8 @@ import org.apache.commons.text.StringEscapeUtils; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.RuleSetNotFoundException; -import net.sourceforge.pmd.RulesetsFactoryUtils; +import net.sourceforge.pmd.RuleSetLoader; +import net.sourceforge.pmd.RulesetLoadException; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; @@ -91,21 +90,16 @@ public class RuleDocGenerator { } } - public void generate(Iterator registeredRulesets, List additionalRulesets) { + public void generate(List registeredRulesets, List additionalRulesets) throws IOException { Map> sortedRulesets; Map> sortedAdditionalRulesets; - try { - sortedRulesets = sortRulesets(registeredRulesets); - sortedAdditionalRulesets = sortRulesets(resolveAdditionalRulesets(additionalRulesets)); - determineRuleClassSourceFiles(sortedRulesets); - generateLanguageIndex(sortedRulesets, sortedAdditionalRulesets); - generateRuleSetIndex(sortedRulesets); + sortedRulesets = sortRulesets(registeredRulesets); + sortedAdditionalRulesets = sortRulesets(resolveAdditionalRulesets(additionalRulesets)); + determineRuleClassSourceFiles(sortedRulesets); + generateLanguageIndex(sortedRulesets, sortedAdditionalRulesets); + generateRuleSetIndex(sortedRulesets); - generateSidebar(sortedRulesets); - - } catch (RuleSetNotFoundException | IOException e) { - throw new RuntimeException(e); - } + generateSidebar(sortedRulesets); } private void generateSidebar(Map> sortedRulesets) throws IOException { @@ -113,53 +107,40 @@ public class RuleDocGenerator { generator.generateSidebar(sortedRulesets); } - private Iterator resolveAdditionalRulesets(List additionalRulesets) throws RuleSetNotFoundException { + private List resolveAdditionalRulesets(List additionalRulesets) { if (additionalRulesets == null) { - return Collections.emptyIterator(); + return Collections.emptyList(); } List rulesets = new ArrayList<>(); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); + RuleSetLoader ruleSetLoader = new RuleSetLoader(); for (String filename : additionalRulesets) { try { // do not take rulesets from pmd-test or pmd-core if (!filename.contains("pmd-test") && !filename.contains("pmd-core")) { - rulesets.add(ruleSetFactory.createRuleSet(filename)); + rulesets.add(ruleSetLoader.loadFromResource(filename)); } else { LOG.fine("Ignoring ruleset " + filename); } - } catch (IllegalArgumentException e) { + } catch (RulesetLoadException e) { // ignore rulesets, we can't read LOG.log(Level.WARNING, "ruleset file " + filename + " ignored (" + e.getMessage() + ")", e); } } - return rulesets.iterator(); + return rulesets; } private Path getAbsoluteOutputPath(String filename) { return root.resolve(FilenameUtils.normalize(filename)); } - private Map> sortRulesets(Iterator rulesets) throws RuleSetNotFoundException { - SortedMap> rulesetsByLanguage = new TreeMap<>(); - - while (rulesets.hasNext()) { - RuleSet ruleset = rulesets.next(); - Language language = getRuleSetLanguage(ruleset); - - if (!rulesetsByLanguage.containsKey(language)) { - rulesetsByLanguage.put(language, new ArrayList()); - } - rulesetsByLanguage.get(language).add(ruleset); - } + private Map> sortRulesets(List rulesets) { + SortedMap> rulesetsByLanguage = rulesets.stream().collect(Collectors.groupingBy(RuleDocGenerator::getRuleSetLanguage, + TreeMap::new, + Collectors.toCollection(ArrayList::new))); for (List rulesetsOfOneLanguage : rulesetsByLanguage.values()) { - Collections.sort(rulesetsOfOneLanguage, new Comparator() { - @Override - public int compare(RuleSet o1, RuleSet o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }); + rulesetsOfOneLanguage.sort((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName())); } return rulesetsByLanguage; } From 1a2a897b3f37f2263fd44acaea52d8990560bd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 24 Nov 2020 13:55:26 +0100 Subject: [PATCH 25/34] Fix bug with sub-report not being merged into global report --- .../main/java/net/sourceforge/pmd/Report.java | 26 ++++++++++++------- .../pmd/processor/PmdRunnable.java | 3 +++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/Report.java b/pmd-core/src/main/java/net/sourceforge/pmd/Report.java index f0a75a7028..8bafa2ccc5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/Report.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/Report.java @@ -47,6 +47,7 @@ public class Report implements Iterable { private final List listeners = new ArrayList<>(); private final List errors = new ArrayList<>(); private final List configErrors = new ArrayList<>(); + private final Object lock = new Object(); private Map linesToSuppress = new HashMap<>(); private long start; private long end; @@ -394,20 +395,25 @@ public class Report implements Iterable { * summary over all violations is needed as PMD creates one report per file * by default. * - * @param r - * the report to be merged into this. + *

This is synchronized on an internal lock (note that other mutation + * operations are not synchronized, todo for pmd 7). + * + * @param r the report to be merged into this. + * * @see AbstractAccumulatingRenderer */ public void merge(Report r) { - errors.addAll(r.errors); - configErrors.addAll(r.configErrors); - metrics.addAll(r.metrics); - suppressedRuleViolations.addAll(r.suppressedRuleViolations); + synchronized (lock) { + errors.addAll(r.errors); + configErrors.addAll(r.configErrors); + metrics.addAll(r.metrics); + suppressedRuleViolations.addAll(r.suppressedRuleViolations); - for (RuleViolation violation : r.getViolations()) { - int index = Collections.binarySearch(violations, violation, RuleViolation.DEFAULT_COMPARATOR); - violations.add(index < 0 ? -index - 1 : index, violation); - violationTree.addRuleViolation(violation); + for (RuleViolation violation : r.getViolations()) { + int index = Collections.binarySearch(violations, violation, RuleViolation.DEFAULT_COMPARATOR); + violations.add(index < 0 ? -index - 1 : index, violation); + violationTree.addRuleViolation(violation); + } } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java index 4c290a61b6..da91fbd95a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java @@ -93,6 +93,9 @@ public class PmdRunnable implements Callable { TimeTracker.finishThread(); + // merge the sub-report into the global report (thread-safe) + ruleContext.getReport().merge(report); + return report; } From 141c51b0ab903fe079a21a76ac193c8b0f8ebd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 24 Nov 2020 14:34:35 +0100 Subject: [PATCH 26/34] Fix ant tests Report was being rendered mutliple times --- pmd-core/src/main/java/net/sourceforge/pmd/PMD.java | 2 +- .../sourceforge/pmd/ant/internal/PMDTaskImpl.java | 12 ++++-------- .../pmd/processor/AbstractPMDProcessor.java | 7 ++++--- .../java/net/sourceforge/pmd/ant/PMDTaskTest.java | 3 +-- .../sourceforge/pmd/docs/RuleDocGeneratorTest.java | 2 +- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 47619f4844..88e66e2d53 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -333,7 +333,7 @@ public class PMD { * and rulesets, are ignored, as they are supplied * as parameters * @param rulesets Parsed rulesets - * @param files Files to process + * @param files Files to process, will be closed by this method. * @param renderers Renderers that render the report * * @return Report in which violations are accumulated diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index 685c459bd9..6fe78b9856 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ContextedRuntimeException; @@ -132,7 +131,7 @@ public class PMDTaskImpl { // TODO Do we really need all this in a loop over each FileSet? Seems // like a lot of redundancy Report errorReport = new Report(); - final AtomicInteger reportSize = new AtomicInteger(); + int problemCount = 0; final String separator = System.getProperty("file.separator"); for (FileSet fs : filesets) { @@ -165,10 +164,7 @@ public class PMDTaskImpl { @Override public void renderFileReport(Report r) { - int size = r.size(); - if (size > 0) { - reportSize.addAndGet(size); - } + // Nothing to do } @Override @@ -189,7 +185,8 @@ public class PMDTaskImpl { renderers.add(renderer); } try { - PMD.processFiles(configuration, rulesetList, files, renderers); + Report report = PMD.processFiles(configuration, rulesetList, files, renderers); + problemCount += report.getViolations().size(); } catch (ContextedRuntimeException e) { if (e.getFirstContextValue("filename") instanceof String) { handleError((String) e.getFirstContextValue("filename"), errorReport, e); @@ -201,7 +198,6 @@ public class PMDTaskImpl { } } - int problemCount = reportSize.get(); project.log(problemCount + " problems found", Project.MSG_VERBOSE); for (Formatter formatter : formatters) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index a77181b2e3..dd5b9081fb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -128,6 +128,10 @@ public abstract class AbstractPMDProcessor { public void processFiles(RuleSets rulesets, List files, RuleContext ctx, List renderers) { try { reportBrokenRules(ctx.getReport(), rulesets); + + // render base report first - general errors + renderReports(renderers, ctx.getReport()); + configuration.getAnalysisCache().checkValidity(rulesets, configuration.getClassLoader()); final SourceCodeProcessor processor = new SourceCodeProcessor(configuration); @@ -138,9 +142,6 @@ public abstract class AbstractPMDProcessor { runAnalysis(new PmdRunnable(dataSource, realFileName, renderers, ctx, rulesets, processor)); } - // render base report first - general errors - renderReports(renderers, ctx.getReport()); - // then add analysis results per file collectReports(renderers); } catch (RuntimeException e) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java index 0bdf85b5ad..cad90eac45 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.ant; import static org.junit.Assert.fail; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; @@ -71,7 +70,7 @@ public class PMDTaskTest { } @Test - public void testWithShortFilenames() throws FileNotFoundException, IOException { + public void testWithShortFilenames() throws IOException { buildRule.executeTarget("testWithShortFilenames"); try (InputStream in = new FileInputStream("target/pmd-ant-test.txt")) { diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java index 5e7561cdf3..23d91a043d 100644 --- a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java @@ -65,7 +65,7 @@ public class RuleDocGeneratorTest { RuleSetFactory rsf = RulesetsFactoryUtils.createFactory(RulePriority.LOW, false, false, true); RuleSet ruleset = rsf.createRuleSet("rulesets/ruledoctest/sample.xml"); - generator.generate(Arrays.asList(ruleset).iterator(), + generator.generate(Arrays.asList(ruleset), Arrays.asList( "rulesets/ruledoctest/sample-deprecated.xml", "rulesets/ruledoctest/other-ruleset.xml")); From 0244ebf6e39a35ae9ede97feee0ad7acf7374109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Wed, 25 Nov 2020 11:51:54 +0100 Subject: [PATCH 27/34] Fix javadoc --- .../net/sourceforge/pmd/RuleSetLoader.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index 53e65a8cba..6bde6e0dbb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -54,6 +54,7 @@ public final class RuleSetLoader { * Filter loaded rules to only those that match or are above * the given priority. The default is {@link RulePriority#LOW}, * ie, no filtering occurs. + * * @return This instance, modified */ public RuleSetLoader filterAbovePriority(RulePriority minimumPriority) { @@ -64,6 +65,7 @@ public final class RuleSetLoader { /** * Log a warning when referencing a deprecated rule. * This is enabled by default. + * * @return This instance, modified */ public RuleSetLoader warnDeprecated(boolean warn) { @@ -76,6 +78,7 @@ public final class RuleSetLoader { * been moved or renamed. This is enabled by default, if disabled, * unresolved references will not be translated and will produce an * error. + * * @return This instance, modified */ public RuleSetLoader enableCompatibility(boolean enable) { @@ -135,8 +138,8 @@ public final class RuleSetLoader { * @param paths Paths * * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found), - * for any of the parameters - * @throws NullPointerException If the parameter, or any component is null + * for any of the parameters + * @throws NullPointerException If the parameter, or any component is null */ public List loadFromResources(Collection paths) { List ruleSets = new ArrayList<>(paths.size()); @@ -153,8 +156,8 @@ public final class RuleSetLoader { * @param rest Paths * * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found), - * for any of the parameters - * @throws NullPointerException If the parameter, or any component is null + * for any of the parameters + * @throws NullPointerException If the parameter, or any component is null */ public List loadFromResources(String first, String... rest) { return loadFromResources(CollectionUtil.listOf(first, rest)); @@ -182,13 +185,15 @@ public final class RuleSetLoader { /** * Returns an Iterator of RuleSet objects loaded from descriptions from the - * "categories.properties" resource for each Language with Rule support. This + * "categories.properties" resource for each language. This * uses the classpath of the resource loader ({@link #loadResourcesWith(ClassLoader)}). * * @return A list of all category rulesets * - * @throws RuleSetNotFoundException if some ruleset file could not be parsed - * TODO shouldn't our API forbid this case? + * @throws RulesetLoadException If a standard ruleset cannot be loaded. + * This is a corner case, that probably should not be caught by clients. + * The standard rulesets are well-formed, at least in stock PMD distributions. + * */ public List getStandardRuleSets() { String rulesetsProperties; From 26728348f69ec6ee58ccbbe4443af68e3f0cf80f Mon Sep 17 00:00:00 2001 From: Maikel Steneker Date: Wed, 9 Dec 2020 16:08:04 +0100 Subject: [PATCH 28/34] Add support for C++14 binary literals --- pmd-cpp/etc/grammar/cpp.jj | 4 +++- .../pmd/lang/cpp/cpd/testdata/literals.cpp | 3 +++ .../pmd/lang/cpp/cpd/testdata/literals.txt | 14 +++++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/pmd-cpp/etc/grammar/cpp.jj b/pmd-cpp/etc/grammar/cpp.jj index 4c10ad9d66..5790cf4062 100644 --- a/pmd-cpp/etc/grammar/cpp.jj +++ b/pmd-cpp/etc/grammar/cpp.jj @@ -284,12 +284,14 @@ TOKEN : TOKEN: { - < #DECIMALDIGIT: ["0"-"9"] > + < #BINARYDIGIT: ["0"-"1"] > | < #OCTALDIGIT: ["0"-"7"] > +| < #DECIMALDIGIT: ["0"-"9"] > | < #HEXDIGIT: ["a"-"f", "A"-"F", "0"-"9"] > | < #INT_SUFFIX: ["u", "U", "l", "L"] | "uL" | "Ul" | "UL" | "ul" | "lu" | "Lu" | "lU" | "LU" > | < ZERO: "0" > +| < BINARY_INT_LITERAL: "0" ["b", "B"] ("'" | )+ ()? > | < OCTAL_INT_LITERAL: "0" ("'" | )+ ()? > | < DECIMAL_INT_LITERAL: ["1"-"9"] ("'" | )* ()? > | < HEXADECIMAL_INT_LITERAL: "0" ["x", "X"] ("'" | )+ ()? > diff --git a/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.cpp b/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.cpp index 9f0d38b06f..cbae7336ba 100644 --- a/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.cpp +++ b/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.cpp @@ -37,4 +37,7 @@ auto hex_literal = 0x0F00'abcd'6f3d; auto silly_example = 1'0'0'000'00; + // boolean literals + int b1 = 0B001101; // C++ 14 binary literal + int b2 = 0b000001; // C++ 14 binary literal } \ No newline at end of file diff --git a/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.txt b/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.txt index 1e792e7302..174e6325c4 100644 --- a/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.txt +++ b/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/literals.txt @@ -118,6 +118,18 @@ L38 [=] 24 24 [1'0'0'000'00] 26 37 [;] 38 38 -L40 +L41 + [int] 5 7 + [b1] 9 10 + [=] 12 12 + [0B001101] 14 21 + [;] 22 22 +L42 + [int] 5 7 + [b2] 9 10 + [=] 12 12 + [0b000001] 14 21 + [;] 22 22 +L43 [}] 1 1 EOF From da3943bf171d669223111d60dcf36f16256c0026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 11 Dec 2020 11:34:50 +0100 Subject: [PATCH 29/34] Update release notes, refs #2962 --- docs/pages/release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 68e200ae2c..d46528bf77 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -84,5 +84,6 @@ You can identify them with the `@InternalApi` annotation. You'll also get a depr * [#2936](https://github.com/pmd/pmd/pull/2936): \[java] (doc) Fix typo: "an accessor" not "a" - [Igor Moreno](https://github.com/igormoreno) * [#2938](https://github.com/pmd/pmd/pull/2938): \[cs] CPD: fix issue where ignoring using directives could not be disabled - [Maikel Steneker](https://github.com/maikelsteneker) * [#2945](https://github.com/pmd/pmd/pull/2945): \[cs] Add option to ignore sequences of literals - [Maikel Steneker](https://github.com/maikelsteneker) +* [#2962](https://github.com/pmd/pmd/pull/2962): \[cpp] Add support for C++ 14 binary literals - [Maikel Steneker](https://github.com/maikelsteneker) {% endtocmaker %} From 85ed4f3303b0ded7a5a2068d8b850052e0ab9288 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Dec 2020 16:12:00 +0100 Subject: [PATCH 30/34] [ci] Fix build badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d07be46f1f..ca8a2941b8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PMD [![Join the chat at https://gitter.im/pmd/pmd](https://badges.gitter.im/pmd/pmd.svg)](https://gitter.im/pmd/pmd?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://github.com/pmd/pmd/workflows/.github/workflows/pushes.yml/badge.svg?branch=master)](https://github.com/pmd/pmd/actions) +[![Build Status](https://github.com/pmd/pmd/workflows/Pushes/badge.svg?branch=master)](https://github.com/pmd/pmd/actions) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd) [![Reproducible Builds](https://img.shields.io/badge/Reproducible_Builds-ok-green?labelColor=blue)](https://github.com/jvm-repo-rebuild/reproducible-central#net.sourceforge.pmd:pmd) [![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd) From feccab274e4209eea1ee661042682dff29ed65ec Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Dec 2020 16:50:49 +0100 Subject: [PATCH 31/34] Bump org.codehaus.groovy:groovy from 2.4.7 to 2.4.21 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b47efa1f31..ba793f9856 100644 --- a/pom.xml +++ b/pom.xml @@ -724,7 +724,7 @@ org.codehaus.groovy groovy - 2.4.7 + 2.4.21 From 422934317314efdb93adc708c1fb9b6c171ee01e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Dec 2020 16:52:17 +0100 Subject: [PATCH 32/34] Use Github Discussions for Q&A --- .github/ISSUE_TEMPLATE/config.yml | 3 +++ .github/ISSUE_TEMPLATE/question.md | 14 -------------- 2 files changed, 3 insertions(+), 14 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 56a5a13ccb..738f691819 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: + - name: Question + url: https://github.com/pmd/pmd/discussions?discussions_q=category%3AQ%26A + about: Feel free to ask any question about PMD and its usage - name: PMD Designer Issues url: https://github.com/pmd/pmd-designer/issues about: Issues about the rule designer diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 5af12acfa1..0000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Question -about: Feel free to ask any question about PMD and its usage -title: '' -labels: 'a:question' -assignees: '' - ---- - - - -**Description:** - From bcbf588bba76c16e5d26121b16d4d7d0a85c174e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Dec 2020 18:35:41 +0100 Subject: [PATCH 33/34] Rename RuleSetLoadException --- ...setLoadException.java => RuleSetLoadException.java} | 6 +++--- .../main/java/net/sourceforge/pmd/RuleSetLoader.java | 10 +++++----- .../net/sourceforge/pmd/RuleSetNotFoundException.java | 2 +- .../net/sourceforge/pmd/docs/RuleDocGenerator.java | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) rename pmd-core/src/main/java/net/sourceforge/pmd/{RulesetLoadException.java => RuleSetLoadException.java} (80%) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoadException.java similarity index 80% rename from pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java rename to pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoadException.java index 7979971118..a59321e146 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetLoadException.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoadException.java @@ -15,17 +15,17 @@ import net.sourceforge.pmd.annotation.InternalApi; *

In the new {@link RuleSetLoader} API, this is thrown instead of * {@link RuleSetNotFoundException}. */ -public final class RulesetLoadException extends RuntimeException { +public final class RuleSetLoadException extends RuntimeException { /** Constructors are internal. */ @InternalApi - public RulesetLoadException(String message, Throwable cause) { + public RuleSetLoadException(String message, Throwable cause) { super(message, cause); } /** Constructors are internal. */ @InternalApi - public RulesetLoadException(String message) { + public RuleSetLoadException(String message) { super(message); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java index 6bde6e0dbb..61f441db7e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetLoader.java @@ -126,7 +126,7 @@ public final class RuleSetLoader { * * @param rulesetPath A reference to a single ruleset * - * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found) + * @throws RuleSetLoadException If any error occurs (eg, invalid syntax, or resource not found) */ public RuleSet loadFromResource(String rulesetPath) { return loadFromResource(new RuleSetReferenceId(rulesetPath)); @@ -137,7 +137,7 @@ public final class RuleSetLoader { * * @param paths Paths * - * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found), + * @throws RuleSetLoadException If any error occurs (eg, invalid syntax, or resource not found), * for any of the parameters * @throws NullPointerException If the parameter, or any component is null */ @@ -155,7 +155,7 @@ public final class RuleSetLoader { * @param first First path * @param rest Paths * - * @throws RulesetLoadException If any error occurs (eg, invalid syntax, or resource not found), + * @throws RuleSetLoadException If any error occurs (eg, invalid syntax, or resource not found), * for any of the parameters * @throws NullPointerException If the parameter, or any component is null */ @@ -168,7 +168,7 @@ public final class RuleSetLoader { try { return toFactory().createRuleSet(ruleSetReferenceId); } catch (Exception e) { - throw new RulesetLoadException("Cannot parse " + ruleSetReferenceId, e); + throw new RuleSetLoadException("Cannot parse " + ruleSetReferenceId, e); } } @@ -190,7 +190,7 @@ public final class RuleSetLoader { * * @return A list of all category rulesets * - * @throws RulesetLoadException If a standard ruleset cannot be loaded. + * @throws RuleSetLoadException If a standard ruleset cannot be loaded. * This is a corner case, that probably should not be caught by clients. * The standard rulesets are well-formed, at least in stock PMD distributions. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java index 05dd3d4be2..4e3acad5d4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetNotFoundException.java @@ -6,7 +6,7 @@ package net.sourceforge.pmd; /** * @deprecated This is now only thrown by deprecated apis. {@link RuleSetLoader} - * throws {@link RulesetLoadException} instead + * throws {@link RuleSetLoadException} instead */ @Deprecated public class RuleSetNotFoundException extends Exception { diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 2b5d83c0cc..6f7c7e60ce 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -36,8 +36,8 @@ import org.apache.commons.text.StringEscapeUtils; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleSetLoadException; import net.sourceforge.pmd.RuleSetLoader; -import net.sourceforge.pmd.RulesetLoadException; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; @@ -122,7 +122,7 @@ public class RuleDocGenerator { } else { LOG.fine("Ignoring ruleset " + filename); } - } catch (RulesetLoadException e) { + } catch (RuleSetLoadException e) { // ignore rulesets, we can't read LOG.log(Level.WARNING, "ruleset file " + filename + " ignored (" + e.getMessage() + ")", e); } From afcb45ea89fec1820fb0513962149cb43beece9f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Dec 2020 18:47:19 +0100 Subject: [PATCH 34/34] Remove unneeded suppresswarnings in AbstractPMDProcessor --- .../net/sourceforge/pmd/processor/AbstractPMDProcessor.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index dd5b9081fb..5bcf538f21 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -112,9 +112,6 @@ public abstract class AbstractPMDProcessor { return brokenRules; } - @SuppressWarnings("PMD.CloseResource") - // the data sources must only be closed after the threads are finished - // this is done manually without a try-with-resources @Deprecated public void processFiles(RuleSetFactory ruleSetFactory, List files, RuleContext ctx, List renderers) {