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 3992711c29..1de515a616 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -162,25 +162,30 @@ public class RuleSetFactory { * @throws RuleSetNotFoundException if unable to find a resource. */ public synchronized RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { - return parseRuleSetNode(ruleSetReferenceId, ruleSetReferenceId.getInputStream(this.classLoader)); + return createRuleSet(ruleSetReferenceId, false); } + private synchronized RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId, boolean withDeprecatedRuleReferences) throws RuleSetNotFoundException { + return parseRuleSetNode(ruleSetReferenceId, ruleSetReferenceId.getInputStream(this.classLoader), withDeprecatedRuleReferences); + } /** * Create a Rule from a RuleSet created from a file name resource. * The currently configured ClassLoader is used. *

* Any Rules in the RuleSet other than the one being created, are _not_ created. + * Deprecated rules are _not_ ignored, so that they can be referenced. * * @param ruleSetReferenceId The RuleSetReferenceId of the RuleSet with the Rule to create. + * @param withDeprecatedRuleReferences Whether RuleReferences that are deprecated should be ignored or not * @return A new Rule. * @throws RuleSetNotFoundException if unable to find a resource. */ - private Rule createRule(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException { + 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 + ">."); } - RuleSet ruleSet = createRuleSet(ruleSetReferenceId); + RuleSet ruleSet = createRuleSet(ruleSetReferenceId, withDeprecatedRuleReferences); return ruleSet.getRuleByName(ruleSetReferenceId.getRuleName()); } @@ -189,9 +194,10 @@ public class RuleSetFactory { * * @param ruleSetReferenceId The RuleSetReferenceId of the RuleSet being parsed. * @param inputStream InputStream containing the RuleSet XML configuration. + * @param withDeprecatedRuleReferences whether rule references that are deprecated should be ignored or not * @return The new RuleSet. */ - private RuleSet parseRuleSetNode(RuleSetReferenceId ruleSetReferenceId, InputStream inputStream) { + private RuleSet parseRuleSetNode(RuleSetReferenceId ruleSetReferenceId, InputStream inputStream, boolean withDeprecatedRuleReferences) { if (!ruleSetReferenceId.isExternal()) { throw new IllegalArgumentException("Cannot parse a RuleSet from a non-external reference: <" + ruleSetReferenceId + ">."); @@ -217,7 +223,7 @@ public class RuleSetFactory { } else if ("exclude-pattern".equals(nodeName)) { ruleSet.addExcludePattern(parseTextNode(node)); } else if ("rule".equals(nodeName)) { - parseRuleNode(ruleSetReferenceId, ruleSet, node); + parseRuleNode(ruleSetReferenceId, ruleSet, node, withDeprecatedRuleReferences); } else { throw new IllegalArgumentException("Unexpected element <" + node.getNodeName() + "> encountered as child of element."); @@ -254,8 +260,9 @@ public class RuleSetFactory { * @param ruleSetReferenceId The RuleSetReferenceId of the RuleSet being parsed. * @param ruleSet The RuleSet being constructed. * @param ruleNode Must be a rule element node. + * @param withDeprecatedRuleReferences whether rule references that are deprecated should be ignored or not */ - private void parseRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode) + private void parseRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode, boolean withDeprecatedRuleReferences) throws ClassNotFoundException, InstantiationException, IllegalAccessException, RuleSetNotFoundException { Element ruleElement = (Element) ruleNode; String ref = ruleElement.getAttribute("ref"); @@ -264,7 +271,7 @@ public class RuleSetFactory { } else if (StringUtil.isEmpty(ref)) { parseSingleRuleNode(ruleSetReferenceId, ruleSet, ruleNode); } else { - parseRuleReferenceNode(ruleSetReferenceId, ruleSet, ruleNode, ref); + parseRuleReferenceNode(ruleSetReferenceId, ruleSet, ruleNode, ref, withDeprecatedRuleReferences); } } @@ -450,9 +457,12 @@ public class RuleSetFactory { * @param ruleSet The RuleSet being constructed. * @param ruleNode Must be a rule element node. * @param ref A reference to a Rule. + * @param withDeprecatedRuleReferences whether rule references that are deprecated should be ignored or not */ - private void parseRuleReferenceNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode, String ref) throws RuleSetNotFoundException { + private void parseRuleReferenceNode(RuleSetReferenceId ruleSetReferenceId, RuleSet ruleSet, Node ruleNode, + String ref, boolean withDeprecatedRuleReferences) throws RuleSetNotFoundException { Element ruleElement = (Element) ruleNode; + boolean isSameRuleSet = false; // Stop if we're looking for a particular Rule, and this element is not it. if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName()) @@ -466,8 +476,9 @@ public class RuleSetFactory { RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0); if (!otherRuleSetReferenceId.isExternal() && containsRule(ruleSetReferenceId, otherRuleSetReferenceId.getRuleName())) { otherRuleSetReferenceId = new RuleSetReferenceId(ref, ruleSetReferenceId); + isSameRuleSet = true; } - Rule referencedRule = ruleSetFactory.createRule(otherRuleSetReferenceId); + Rule referencedRule = ruleSetFactory.createRule(otherRuleSetReferenceId, true); // do not ignore deprecated rule references if (referencedRule == null) { throw new IllegalArgumentException("Unable to find referenced rule " + otherRuleSetReferenceId.getRuleName() + "; perhaps the rule name is mispelled?"); @@ -478,7 +489,7 @@ public class RuleSetFactory { RuleReference ruleReference = (RuleReference) referencedRule; if (LOG.isLoggable(Level.WARNING)) { LOG.warning("Use Rule name " + ruleReference.getRuleSetReference().getRuleSetFileName() + "/" - + ruleReference.getName() + " instead of the deprecated Rule name " + otherRuleSetReferenceId + + ruleReference.getOriginalName() + " instead of the deprecated Rule name " + otherRuleSetReferenceId + ". Future versions of PMD will remove support for this deprecated Rule name usage."); } } else if (referencedRule instanceof MockRule) { @@ -534,10 +545,12 @@ public class RuleSetFactory { } } - if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName()) - || referencedRule.getPriority().compareTo(minimumPriority) <= 0) { - ruleSet.addRuleReplaceIfExists(ruleReference); - } + if (StringUtil.isNotEmpty(ruleSetReferenceId.getRuleName()) || referencedRule.getPriority().compareTo( + minimumPriority) <= 0) { + if (withDeprecatedRuleReferences || !isSameRuleSet || !ruleReference.isDeprecated()) { + ruleSet.addRuleReplaceIfExists(ruleReference); + } + } } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java index 9f0d994201..92608ff099 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java @@ -110,6 +110,10 @@ public class RuleReference extends AbstractDelegateRule { return name; } + public String getOriginalName() { + return super.getName(); + } + @Override public void setName(String name) { // Only override if different than current value, or if already overridden. 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 4f31f239ee..eb0fc98403 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -20,7 +20,6 @@ import net.sourceforge.pmd.lang.DummyLanguageModule; 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.properties.StringMultiProperty; import net.sourceforge.pmd.util.ResourceLoader; import org.junit.Assert; @@ -208,6 +207,44 @@ public class RuleSetFactoryTest { Assert.assertArrayEquals(new String[]{"com.aptsssss", "com.abc"}, values); } + @Test + public void testRuleSetWithDeprecatedRule() throws Exception { + RuleSet rs = loadRuleSet("\n" + + "\n" + + " " + + ""); + Assert.assertEquals(1, rs.getRules().size()); + Rule rule = rs.getRuleByName("DummyBasicMockRule"); + Assert.assertNotNull(rule); + } + + @Test + public void testRuleSetWithDeprecatedButRenamedRule() throws Exception { + RuleSet rs = loadRuleSet("\n" + + "\n" + + " " + + " " + + " d\n" + + " 2\n" + + " " + + ""); + Assert.assertEquals(1, rs.getRules().size()); + Rule rule = rs.getRuleByName("NewName"); + Assert.assertNotNull(rule); + Assert.assertNull(rs.getRuleByName("OldName")); + } + + @Test + public void testRuleSetReferencesADeprecatedRenamedRule() throws Exception { + RuleSet rs = loadRuleSet("\n" + + "\n" + + " " + + ""); + Assert.assertEquals(1, rs.getRules().size()); + Rule rule = rs.getRuleByName("OldNameOfDummyBasicMockRule"); + Assert.assertNotNull(rule); + } + @Test @SuppressWarnings("unchecked") public void testXPath() throws RuleSetNotFoundException { diff --git a/pmd-core/src/test/resources/rulesets/dummy/basic.xml b/pmd-core/src/test/resources/rulesets/dummy/basic.xml index 2b415d5222..30273be6d8 100644 --- a/pmd-core/src/test/resources/rulesets/dummy/basic.xml +++ b/pmd-core/src/test/resources/rulesets/dummy/basic.xml @@ -17,4 +17,6 @@ Just for test ]]> + + \ No newline at end of file