diff --git a/docs/pages/pmd/userdocs/extending/defining_properties.md b/docs/pages/pmd/userdocs/extending/defining_properties.md index 3551accd42..dfda872abc 100644 --- a/docs/pages/pmd/userdocs/extending/defining_properties.md +++ b/docs/pages/pmd/userdocs/extending/defining_properties.md @@ -165,7 +165,6 @@ with a backslash when needed. ```xml - diff --git a/docs/pages/pmd/userdocs/extending/writing_rules_intro.md b/docs/pages/pmd/userdocs/extending/writing_rules_intro.md index 74c3978b70..49184bbe00 100644 --- a/docs/pages/pmd/userdocs/extending/writing_rules_intro.md +++ b/docs/pages/pmd/userdocs/extending/writing_rules_intro.md @@ -104,7 +104,7 @@ instead of mentioning the `ref` attribute, it mentions the `class` attribute, with the implementation class of your rule. * **For Java rules:** this is the concrete class extending AbstractRule (transitively) -* **For XPath rules:** this is `net.sourceforge.pmd.lang.rule.XPathRule`. +* **For XPath rules:** this is `net.sourceforge.pmd.lang.rule.xpath.XPathRule`. * **For XPath rules analyzing XML-based languages:** this is `net.sourceforge.pmd.lang.xml.rule.DomXPathRule`. See [XPath rules in XML](pmd_languages_xml.html#xpath-rules-in-xml) for more info. @@ -128,7 +128,7 @@ Example for XPath rule: + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> Description diff --git a/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md b/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md index a0bc692c6c..a374d5abd6 100644 --- a/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md +++ b/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md @@ -27,7 +27,8 @@ with opt-in support for XPath 2.0. See [the Saxonica documentation](https://www.saxonica.com/html/documentation/expressions/xpath31new.html) for an introduction to new features in XPath 3.1. -The property `version` of {% jdoc core::lang.rule.XPathRule %} is deprecated and will be removed. +The property `version` of {% jdoc core::lang.rule.XPathRule %} is deprecated and +has been removed with PMD 7. ## DOM representation of ASTs diff --git a/docs/pages/pmd/userdocs/extending/your_first_rule.md b/docs/pages/pmd/userdocs/extending/your_first_rule.md index 873324db0c..30c2f98e13 100644 --- a/docs/pages/pmd/userdocs/extending/your_first_rule.md +++ b/docs/pages/pmd/userdocs/extending/your_first_rule.md @@ -127,7 +127,7 @@ copy-paste into your ruleset XML. The resulting element looks like so: + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> TODO diff --git a/docs/pages/pmd/userdocs/migrating_to_pmd7.md b/docs/pages/pmd/userdocs/migrating_to_pmd7.md index 1565dadef9..501f40c49e 100644 --- a/docs/pages/pmd/userdocs/migrating_to_pmd7.md +++ b/docs/pages/pmd/userdocs/migrating_to_pmd7.md @@ -109,9 +109,11 @@ XPath 2.0 is available in PMD 6 already and can be used right away. PMD 7 will u won't support XPath 1.0 anymore. The difference between XPath 2.0 and XPath 3.1 is not big, so your XPath 2.0 can be expected to work in PMD 7 without any further changes. So the migration path is to simply migrate to XPath 2.0. -After you have migrated your XPath rules to XPath 2.0, remove the "version" property, since that will be removed -with PMD 7. PMD 7 by default uses XPath 3.1. -See below [XPath](#xpath-migrating-from-10-to-20) for details. +After you have migrated your XPath rules to XPath 2.0, remove the "version" property, since that has been removed +with PMD 7. PMD 7 by default uses XPath 3.1. See below [XPath](#xpath-migrating-from-10-to-20) for details. + +Then change the `class` attribute of your rule to `net.sourceforge.pmd.lang.rule.xpath.XPathRule` - because the +class {%jdoc core::lang.rule.xpath.XPathRule %} has been moved into subpackage {% jdoc_package core::lang.rule.xpath %}. There are some general changes for AST nodes regarding the `@Image` attribute. See below [General AST Changes to avoid @Image](#general-ast-changes-to-avoid-image). diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 269154ee56..b75f263abc 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -175,6 +175,7 @@ The rules have been moved into categories with PMD 6. * [#3903](https://github.com/pmd/pmd/issues/3903): \[core] Consolidate `n.s.pmd.reporting` package * [#3917](https://github.com/pmd/pmd/issues/3917): \[core] Consolidate `n.s.pmd.lang.rule` package * [#4065](https://github.com/pmd/pmd/issues/4065): \[core] Rename TokenMgrError to LexException, Tokenizer to CpdLexer + * [#4309](https://github.com/pmd/pmd/issues/4309): \[core] Cleanups in XPath area * [#4312](https://github.com/pmd/pmd/issues/4312): \[core] Remove unnecessary property `color` and system property `pmd.color` in `TextColorRenderer` * [#4313](https://github.com/pmd/pmd/issues/4313): \[core] Remove support for <lang>-<ruleset> hyphen notation for ruleset references * [#4314](https://github.com/pmd/pmd/issues/4314): \[core] Remove ruleset compatibility filter (RuleSetFactoryCompatibility) and CLI option `--no-ruleset-compatibility` @@ -235,6 +236,11 @@ The rules have been moved into categories with PMD 6. See [General AST Changes to avoid @Image]({{ baseurl }}pmd_userdocs_migrating_to_pmd7.html#general-ast-changes-to-avoid-image) in the migration guide for details. +**XPath Rules** +* The property `version` was already deprecated and has finally been removed. Please don't define the version + property anymore in your custom XPath rules. By default, the latest XPath version will be used, which + is XPath 3.1. + **Moved classes/consolidated packages** * pmd-core @@ -252,6 +258,7 @@ in the migration guide for details. * {%jdoc core::reporting.RuleViolation %} * {%jdoc core::reporting.ViolationSuppressor %} * {%jdoc core::reporting.ParametricRuleViolation %} (moved from `net.sourcceforge.pmd.lang.rule`) + * {%jdoc core::lang.rule.xpath.XPathRule %} has been moved into subpackage {% jdoc_package core::lang.rule.xpath %}. **Internalized classes** @@ -746,6 +753,7 @@ See also [Detailed Release Notes for PMD 7]({{ baseurl }}pmd_release_notes_pmd7. * [#4204](https://github.com/pmd/pmd/issues/4204): \[core] Provide a CpdAnalysis class as a programmatic entry point into CPD * [#4301](https://github.com/pmd/pmd/issues/4301): \[core] Remove deprecated property concrete classes * [#4302](https://github.com/pmd/pmd/issues/4302): \[core] Migrate Property Framework API to Java 8 + * [#4309](https://github.com/pmd/pmd/issues/4309): \[core] Cleanups in XPath area * [#4312](https://github.com/pmd/pmd/issues/4312): \[core] Remove unnecessary property `color` and system property `pmd.color` in `TextColorRenderer` * [#4313](https://github.com/pmd/pmd/issues/4313): \[core] Remove support for <lang>-<ruleset> hyphen notation for ruleset references * [#4314](https://github.com/pmd/pmd/issues/4314): \[core] Remove ruleset compatibility filter (RuleSetFactoryCompatibility) and CLI option `--no-ruleset-compatibility` diff --git a/pmd-apex/src/main/resources/category/apex/bestpractices.xml b/pmd-apex/src/main/resources/category/apex/bestpractices.xml index 178f94e82e..f2d723cb8c 100644 --- a/pmd-apex/src/main/resources/category/apex/bestpractices.xml +++ b/pmd-apex/src/main/resources/category/apex/bestpractices.xml @@ -106,7 +106,7 @@ private class TestRunAs { since="6.13.0" language="apex" message="Apex test methods should have @isTest annotation." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation"> Apex test methods should have `@isTest` annotation instead of the `testMethod` keyword, @@ -116,7 +116,6 @@ annotation for test classes and methods. 3 - The first parameter of System.debug, when using the signature with two parameters, is a LoggingLevel enum. diff --git a/pmd-apex/src/main/resources/category/apex/codestyle.xml b/pmd-apex/src/main/resources/category/apex/codestyle.xml index c2028bfd3c..448d8e9a00 100644 --- a/pmd-apex/src/main/resources/category/apex/codestyle.xml +++ b/pmd-apex/src/main/resources/category/apex/codestyle.xml @@ -37,7 +37,7 @@ public class fooClass { } // This will be reported unless you change the regex language="apex" since="5.6.0" message="Avoid using 'if...else' statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_codestyle.html#ifelsestmtsmustusebraces"> Avoid using if..else statements without using surrounding braces. If the code formatting @@ -74,7 +74,7 @@ else language="apex" since="5.6.0" message="Avoid using if statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_codestyle.html#ifstmtsmustusebraces"> Avoid using if statements without using braces to surround the code block. If the code @@ -156,7 +156,7 @@ public class Foo { language="apex" since="5.6.0" message="Avoid using 'for' statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_codestyle.html#forloopsmustusebraces"> Avoid using 'for' statements without using surrounding braces. If the code formatting or @@ -270,7 +270,7 @@ public class Foo { language="apex" since="6.7.0" message="Use one statement for each line, it enhances code readability." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_codestyle.html#onedeclarationperline"> Apex allows the use of several variables declaration of the same type on one line. However, it @@ -338,7 +338,7 @@ public class Foo { language="apex" since="5.6.0" message="Avoid using 'while' statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_codestyle.html#whileloopsmustusebraces"> Avoid using 'while' statements without using braces to surround the code block. If the code diff --git a/pmd-apex/src/main/resources/category/apex/errorprone.xml b/pmd-apex/src/main/resources/category/apex/errorprone.xml index 2a4f16618b..4bfe137c50 100644 --- a/pmd-apex/src/main/resources/category/apex/errorprone.xml +++ b/pmd-apex/src/main/resources/category/apex/errorprone.xml @@ -54,7 +54,7 @@ public class Foo { language="apex" since="6.0.0" message="Avoid directly accessing Trigger.old and Trigger.new" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#avoiddirectaccesstriggermap"> Avoid directly accessing Trigger.old and Trigger.new as it can lead to a bug. Triggers should be bulkified and iterate through the map to handle the actions for each item separately. @@ -138,7 +138,7 @@ public without sharing class Foo { language="apex" since="6.0.0" message="Avoid empty catch blocks" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#emptycatchblock"> Empty Catch Block finds instances where an exception is caught, but nothing is done. @@ -177,7 +177,7 @@ public void doSomething() { language="apex" since="6.0.0" message="Avoid empty 'if' statements" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#emptyifstmt"> Empty If Statement finds instances where a condition is checked but nothing is done about it. @@ -210,7 +210,7 @@ public class Foo { language="apex" since="6.0.0" message="Avoid empty block statements." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#emptystatementblock"> Empty block statements serve no purpose and should be removed. @@ -247,7 +247,7 @@ public class Foo { language="apex" since="6.0.0" message="Avoid empty try or finally blocks" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#emptytryorfinallyblock"> Avoid empty try or finally blocks - what's the point? @@ -291,7 +291,7 @@ public class Foo { language="apex" since="6.0.0" message="Avoid empty 'while' statements" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#emptywhilestmt"> Empty While Statement finds all instances where a while statement does nothing. @@ -445,7 +445,7 @@ public class Foo { // perfect, both methods provided language="apex" since="6.22.0" message="Test methods must be in test classes" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_errorprone.html#testmethodsmustbeintestclasses"> Test methods marked as a testMethod or annotated with @IsTest, diff --git a/pmd-apex/src/main/resources/category/apex/performance.xml b/pmd-apex/src/main/resources/category/apex/performance.xml index 8f4e17523b..874e0b7268 100644 --- a/pmd-apex/src/main/resources/category/apex/performance.xml +++ b/pmd-apex/src/main/resources/category/apex/performance.xml @@ -13,7 +13,7 @@ Rules that flag suboptimal code. language="apex" since="6.36.0" message="Avoid debug statements since they impact on performance" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_performance.html#avoiddebugstatements"> Debug statements contribute to longer transactions and consume Apex CPU time even when debug logs are not being captured. @@ -24,7 +24,6 @@ For other valid use cases that the statement is in fact valid make use of the `@ 3 - This rule finds `DescribeSObjectResult`s which could have been loaded eagerly via `SObjectType.getDescribe()`. @@ -172,7 +171,6 @@ Properties: 3 - Just for test 3 diff --git a/pmd-compat6/src/it/pmd-for-java/exception_ruleset.xml b/pmd-compat6/src/it/pmd-for-java/exception_ruleset.xml index 7f9604ffa3..bd7427e5a8 100644 --- a/pmd-compat6/src/it/pmd-for-java/exception_ruleset.xml +++ b/pmd-compat6/src/it/pmd-for-java/exception_ruleset.xml @@ -2,7 +2,7 @@ + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> Use this rule to produce a processing error. 3 diff --git a/pmd-compat6/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java b/pmd-compat6/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java new file mode 100644 index 0000000000..eb11ac7e77 --- /dev/null +++ b/pmd-compat6/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java @@ -0,0 +1,8 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule; + +public class XPathRule extends net.sourceforge.pmd.lang.rule.xpath.XPathRule { +} diff --git a/pmd-compat6/src/main/java/net/sourceforge/pmd/lang/rule/xpath/XPathRule.java b/pmd-compat6/src/main/java/net/sourceforge/pmd/lang/rule/xpath/XPathRule.java new file mode 100644 index 0000000000..f8ddce578b --- /dev/null +++ b/pmd-compat6/src/main/java/net/sourceforge/pmd/lang/rule/xpath/XPathRule.java @@ -0,0 +1,172 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +// This class has been taken from 7.0.0-SNAPSHOT +// Changes: not final anymore to allow a subclass in the old package + +package net.sourceforge.pmd.lang.rule.xpath; + +import java.util.List; +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ContextedRuntimeException; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.LanguageProcessor; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.AbstractRule; +import net.sourceforge.pmd.lang.rule.RuleTargetSelector; +import net.sourceforge.pmd.lang.rule.xpath.internal.DeprecatedAttrLogger; +import net.sourceforge.pmd.lang.rule.xpath.internal.SaxonXPathRuleQuery; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + + +/** + * Rule that tries to match an XPath expression against a DOM view of an AST. + */ +public /*final*/ class XPathRule extends AbstractRule { + + private static final Logger LOG = LoggerFactory.getLogger(XPathRule.class); + + /** + * @deprecated Use {@link #XPathRule(XPathVersion, String)} + */ + @Deprecated + public static final PropertyDescriptor XPATH_DESCRIPTOR = + PropertyFactory.stringProperty("xpath") + .desc("XPath expression") + .defaultValue("") + .build(); + + /** + * This is initialized only once when calling {@link #apply(Node, RuleContext)} or {@link #getTargetSelector()}. + */ + private SaxonXPathRuleQuery xpathRuleQuery; + + + // this is shared with rules forked by deepCopy, used by the XPathRuleQuery + private DeprecatedAttrLogger attrLogger = DeprecatedAttrLogger.create(this); + + + /** + * @deprecated This is now only used by the ruleset loader. When + * we have syntactic sugar for XPath rules in the XML, we won't + * need this anymore. + */ + @Deprecated + public XPathRule() { + definePropertyDescriptor(XPATH_DESCRIPTOR); + } + + /** + * Make a new XPath rule with the given version + expression + * + * @param version Version of the XPath language + * @param expression XPath expression + * + * @throws NullPointerException If any of the arguments is null + */ + public XPathRule(XPathVersion version, String expression) { + this(); + + Objects.requireNonNull(version, "XPath version is null"); + Objects.requireNonNull(expression, "XPath expression is null"); + + setProperty(XPathRule.XPATH_DESCRIPTOR, expression); + } + + + @Override + public Rule deepCopy() { + XPathRule rule = (XPathRule) super.deepCopy(); + rule.attrLogger = this.attrLogger; + return rule; + } + + /** + * Returns the XPath expression that implements this rule. + */ + public String getXPathExpression() { + return getProperty(XPATH_DESCRIPTOR); + } + + + @Override + public void apply(Node target, RuleContext ctx) { + SaxonXPathRuleQuery query = getQueryMaybeInitialize(); + + List nodesWithViolation; + try { + nodesWithViolation = query.evaluate(target); + } catch (PmdXPathException e) { + throw addExceptionContext(e); + } + + for (Node nodeWithViolation : nodesWithViolation) { + addViolation(ctx, nodeWithViolation, nodeWithViolation.getImage()); + } + } + + private ContextedRuntimeException addExceptionContext(PmdXPathException e) { + return e.addRuleName(getName()); + } + + @Override + public void initialize(LanguageProcessor languageProcessor) { + String xpath = getXPathExpression(); + XPathVersion version = XPathVersion.DEFAULT; + + try { + xpathRuleQuery = new SaxonXPathRuleQuery(xpath, + version, + getPropertiesByPropertyDescriptor(), + languageProcessor.services().getXPathHandler(), + attrLogger); + } catch (PmdXPathException e) { + throw addExceptionContext(e); + } + } + + private SaxonXPathRuleQuery getQueryMaybeInitialize() throws PmdXPathException { + if (xpathRuleQuery == null) { + throw new IllegalStateException("Not initialized"); + } + return xpathRuleQuery; + } + + + @Override + protected @NonNull RuleTargetSelector buildTargetSelector() { + + List visits = getQueryMaybeInitialize().getRuleChainVisits(); + + logXPathRuleChainUsage(!visits.isEmpty()); + + return visits.isEmpty() ? RuleTargetSelector.forRootOnly() + : RuleTargetSelector.forXPathNames(visits); + } + + + private void logXPathRuleChainUsage(boolean usesRuleChain) { + LOG.debug("{} rule chain for XPath rule: {} ({})", + usesRuleChain ? "Using" : "no", + getName(), + getRuleSetName()); + } + + + @Override + public String dysfunctionReason() { + if (StringUtils.isBlank(getXPathExpression())) { + return "Missing XPath expression"; + } + return null; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleSet.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleSet.java index 095e207224..264275deea 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleSet.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleSet.java @@ -27,6 +27,7 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.document.FileId; import net.sourceforge.pmd.lang.document.TextFile; import net.sourceforge.pmd.lang.rule.internal.RuleSetReference; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; /** * This class represents a collection of rules along with some optional filter diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/XPathRule.java similarity index 72% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/XPathRule.java index b074496f4a..d9b021501b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/XPathRule.java @@ -2,12 +2,9 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule; +package net.sourceforge.pmd.lang.rule.xpath; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import org.apache.commons.lang3.StringUtils; @@ -16,11 +13,11 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.LanguageProcessor; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException; -import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; +import net.sourceforge.pmd.lang.rule.AbstractRule; +import net.sourceforge.pmd.lang.rule.Rule; +import net.sourceforge.pmd.lang.rule.RuleTargetSelector; import net.sourceforge.pmd.lang.rule.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.rule.xpath.internal.SaxonXPathRuleQuery; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -35,8 +32,6 @@ public final class XPathRule extends AbstractRule { private static final Logger LOG = LoggerFactory.getLogger(XPathRule.class); - // TODO move to XPath subpackage - /** * @deprecated Use {@link #XPathRule(XPathVersion, String)} */ @@ -47,17 +42,6 @@ public final class XPathRule extends AbstractRule { .defaultValue("") .build(); - /** - * @deprecated Use {@link #XPathRule(XPathVersion, String)} - */ - @Deprecated - @DeprecatedUntil700 - public static final PropertyDescriptor VERSION_DESCRIPTOR = - PropertyFactory.enumProperty("version", getXPathVersions()) - .desc("XPath specification version") - .defaultValue(XPathVersion.DEFAULT) - .build(); - /** * This is initialized only once when calling {@link #apply(Node, RuleContext)} or {@link #getTargetSelector()}. */ @@ -76,7 +60,6 @@ public final class XPathRule extends AbstractRule { @Deprecated public XPathRule() { definePropertyDescriptor(XPATH_DESCRIPTOR); - definePropertyDescriptor(VERSION_DESCRIPTOR); } /** @@ -94,7 +77,6 @@ public final class XPathRule extends AbstractRule { Objects.requireNonNull(expression, "XPath expression is null"); setProperty(XPathRule.XPATH_DESCRIPTOR, expression); - setProperty(XPathRule.VERSION_DESCRIPTOR, XPathVersion.ofId(version.getXmlName())); } @@ -105,14 +87,6 @@ public final class XPathRule extends AbstractRule { return rule; } - /** - * Returns the version for this rule. Returns null if this is not - * set or invalid. - */ - public XPathVersion getVersion() { - return getProperty(VERSION_DESCRIPTOR); - } - /** * Returns the XPath expression that implements this rule. */ @@ -144,11 +118,7 @@ public final class XPathRule extends AbstractRule { @Override public void initialize(LanguageProcessor languageProcessor) { String xpath = getXPathExpression(); - XPathVersion version = getVersion(); - - if (version == null) { - throw new IllegalStateException("Invalid XPath version, should have been caught by Rule::dysfunctionReason"); - } + XPathVersion version = XPathVersion.DEFAULT; try { xpathRuleQuery = new SaxonXPathRuleQuery(xpath, @@ -182,9 +152,8 @@ public final class XPathRule extends AbstractRule { private void logXPathRuleChainUsage(boolean usesRuleChain) { - LOG.debug("{} rule chain for XPath {} rule: {} ({})", + LOG.debug("{} rule chain for XPath rule: {} ({})", usesRuleChain ? "Using" : "no", - getProperty(XPathRule.VERSION_DESCRIPTOR), getName(), getRuleSetName()); } @@ -192,19 +161,9 @@ public final class XPathRule extends AbstractRule { @Override public String dysfunctionReason() { - if (getVersion() == null) { - return "Invalid XPath version '" + getProperty(VERSION_DESCRIPTOR) + "'"; - } else if (StringUtils.isBlank(getXPathExpression())) { + if (StringUtils.isBlank(getXPathExpression())) { return "Missing XPath expression"; } return null; } - - private static Map getXPathVersions() { - Map tmp = new HashMap<>(); - for (XPathVersion v : XPathVersion.values()) { - tmp.put(v.getXmlName(), v); - } - return Collections.unmodifiableMap(tmp); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/AbstractXPathFunctionDef.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/AbstractXPathFunctionDef.java deleted file mode 100644 index 8963a9071b..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/AbstractXPathFunctionDef.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.xpath.impl; - -import net.sourceforge.pmd.lang.Language; - -import net.sf.saxon.lib.ExtensionFunctionDefinition; -import net.sf.saxon.om.StructuredQName; - - -/** - * Base impl for an XPath function definition. - * This uses Saxon API. - * - * @since 7.0.0 - */ -public abstract class AbstractXPathFunctionDef extends ExtensionFunctionDefinition { - - private static final String PMD_URI_PREFIX = "http://pmd.sourceforge.net/"; - private final StructuredQName qname; - - private AbstractXPathFunctionDef(String localName, String namespacePrefix, String uri) { - this.qname = new StructuredQName(namespacePrefix, uri, localName); - } - - protected AbstractXPathFunctionDef(String localName) { - this(localName, "pmd", PMD_URI_PREFIX + "pmd-core"); - } - - protected AbstractXPathFunctionDef(String localName, Language language) { - this(localName, "pmd-" + language.getId(), PMD_URI_PREFIX + "pmd-" + language.getId()); - } - - @Override - public final StructuredQName getFunctionQName() { - return qname; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathFunctionDefinition.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathFunctionDefinition.java new file mode 100644 index 0000000000..a684f835bc --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathFunctionDefinition.java @@ -0,0 +1,126 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.xpath.impl; + +import javax.xml.namespace.QName; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.ast.Node; + +/** + * Base impl for an XPath function definition. + * + * @since 7.0.0 + */ +public abstract class XPathFunctionDefinition { + + private static final String PMD_URI_PREFIX = "http://pmd.sourceforge.net/"; + private final QName qname; + + private XPathFunctionDefinition(String localName, String namespacePrefix, String uri) { + this.qname = new QName(uri, localName, namespacePrefix); + } + + protected XPathFunctionDefinition(String localName) { + this(localName, "pmd", PMD_URI_PREFIX + "pmd-core"); + } + + protected XPathFunctionDefinition(String localName, Language language) { + this(localName, "pmd-" + language.getId(), PMD_URI_PREFIX + "pmd-" + language.getId()); + } + + public final QName getQName() { + return qname; + } + + /** + * Defines the types of the function arguments. By default, an empty array is returned, indicating + * that the function takes no arguments. + */ + public Type[] getArgumentTypes() { + return new Type[0]; + } + + /** + * Defines the return type of the function. + */ + public abstract Type getResultType(); + + /** + * If the function depends on the context item, then + * this method should return {@code true}. + * + *

Note: Only if this is true, the contextNode parameter will be present in the + * {@link FunctionCall#call(Node, Object[])} method. + */ + public boolean dependsOnContext() { + return false; + } + + /** + * Create a call on this function. This method is called, when a function call + * is found in the XPath expression. + */ + public abstract FunctionCall makeCallExpression(); + + /** + * Supported types of a custom XPath function. These can be used as {@link #getResultType() result types} + * or {@link #getArgumentTypes() argument types}. + */ + public enum Type { + /** Represents {@link String}. */ + SINGLE_STRING, + /** Represents {@link Boolean}. */ + SINGLE_BOOLEAN, + /** Represents {@link Integer}. */ + SINGLE_INTEGER, + /** Represents any node. Usually used as an argument type. */ + SINGLE_ELEMENT, + /** Represents a {@link java.util.List} of {@link String}, potentially empty. */ + STRING_SEQUENCE, + /** Represents a {@link java.util.Optional} {@link String}. */ + OPTIONAL_STRING, + /** Represents a {@link java.util.Optional} {@link Double}. */ + OPTIONAL_DECIMAL, + } + + /** + * Provides the actual implementation of a custom XPath function. + */ + public interface FunctionCall { + /** + * This method is called at runtime to evaluate the XPath function expression. + * + * @param contextNode the context node or {@code null}, if this function doesn't depend on the context. + * See {@link XPathFunctionDefinition#dependsOnContext()}. + * @param arguments The arguments converted as the corresponding java types. + * See {@link XPathFunctionDefinition#getArgumentTypes()}. + * @return The result of the function. This should be the corresponding java type of + * {@link XPathFunctionDefinition#getResultType()}. + * @throws XPathFunctionException when any problem during evaluation occurs, like invalid arguments. + */ + Object call(@Nullable Node contextNode, Object[] arguments) throws XPathFunctionException; + + /** + * This is called once before the function is evaluated. It can be used to optimize the + * implementation by doing expensive operations only once and cache the result. + * This is useful, if the argument of the function is of type {@link String} and is provided + * as a String literal in the XPath expression. + * + *

This is an optional step. The default implementation does nothing. + * + * @param arguments The arguments converted as the corresponding java types. + * See {@link XPathFunctionDefinition#getArgumentTypes()}. + * Note: This array might contain {@code null} elements, if the values are + * not known yet because they are dynamic. Only literal values are available. + * @throws XPathFunctionException when any problem during initialization occurs, like invalid arguments. + */ + default void staticInit(Object[] arguments) throws XPathFunctionException { + // default implementation does nothing + } + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathFunctionException.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathFunctionException.java new file mode 100644 index 0000000000..11704594af --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathFunctionException.java @@ -0,0 +1,19 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.xpath.impl; + +/** + * Indicates a problem during the execution of a custom + * XPath function. + */ +public class XPathFunctionException extends Exception { + public XPathFunctionException(String message) { + super(message); + } + + public XPathFunctionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java index 0ef25b7884..73af54e17d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java @@ -11,8 +11,6 @@ import java.util.Set; import net.sourceforge.pmd.lang.rule.xpath.internal.DefaultXPathFunctions; import net.sourceforge.pmd.util.CollectionUtil; -import net.sf.saxon.lib.ExtensionFunctionDefinition; - /** * Interface for performing Language specific XPath handling, such as @@ -24,7 +22,7 @@ public interface XPathHandler { * Returns the set of extension functions for this language module. * These are the additional functions available in XPath queries. */ - Set getRegisteredExtensionFunctions(); + Set getRegisteredExtensionFunctions(); static XPathHandler noFunctionDefinitions() { @@ -34,8 +32,8 @@ public interface XPathHandler { /** * Returns a default XPath handler. */ - static XPathHandler getHandlerForFunctionDefs(ExtensionFunctionDefinition first, ExtensionFunctionDefinition... defs) { - Set set = new HashSet<>(CollectionUtil.setOf(first, defs)); + static XPathHandler getHandlerForFunctionDefs(XPathFunctionDefinition first, XPathFunctionDefinition... defs) { + Set set = new HashSet<>(CollectionUtil.setOf(first, defs)); set.addAll(DefaultXPathFunctions.getDefaultFunctions()); return () -> Collections.unmodifiableSet(set); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java index 31d41783e2..59a4e83b8e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java @@ -7,23 +7,15 @@ package net.sourceforge.pmd.lang.rule.xpath.internal; import java.util.function.ToIntFunction; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.rule.xpath.impl.AbstractXPathFunctionDef; - -import net.sf.saxon.expr.XPathContext; -import net.sf.saxon.lib.ExtensionFunctionCall; -import net.sf.saxon.om.Sequence; -import net.sf.saxon.pattern.NodeKindTest; -import net.sf.saxon.trans.XPathException; -import net.sf.saxon.type.Type; -import net.sf.saxon.value.Int64Value; -import net.sf.saxon.value.SequenceType; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException; /** * A function that returns the current file name. * * @author Clément Fournier */ -public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { +public final class CoordinateXPathFunction extends XPathFunctionDefinition { public static final CoordinateXPathFunction START_LINE = new CoordinateXPathFunction("startLine", Node::getBeginLine); @@ -34,9 +26,7 @@ public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { public static final CoordinateXPathFunction END_COLUMN = new CoordinateXPathFunction("endColumn", Node::getEndColumn); - private static final SequenceType[] A_SINGLE_ELEMENT = { - NodeKindTest.makeNodeKindTest(Type.ELEMENT).one(), - }; + private static final Type[] A_SINGLE_ELEMENT = { Type.SINGLE_ELEMENT }; public static final String PMD_NODE_USER_DATA = "pmd.node"; private final ToIntFunction getter; @@ -46,32 +36,26 @@ public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { } @Override - public SequenceType[] getArgumentTypes() { + public Type[] getArgumentTypes() { return A_SINGLE_ELEMENT; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.SINGLE_INTEGER; + public Type getResultType() { + return Type.SINGLE_INTEGER; } @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { - - @Override - public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node node = XPathElementToNodeHelper.itemToNode(arguments[0]); - if (node == null) { - throw new XPathException( - "Cannot call function '" + getFunctionQName().getLocalPart() - + "' on argument " + arguments[0] - ); - } - return Int64Value.makeIntegerValue(getter.applyAsInt(node)); + public FunctionCall makeCallExpression() { + return (contextNode, arguments) -> { + Node node = XPathElementToNodeHelper.itemToNode(arguments[0]); + if (node == null) { + throw new XPathFunctionException( + "Cannot call function '" + getQName().getLocalPart() + + "' on argument " + arguments[0] + ); } + return getter.applyAsInt(node); }; } - - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java index bfd58f98fa..fddc9bc8e6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java @@ -7,16 +7,15 @@ package net.sourceforge.pmd.lang.rule.xpath.internal; import java.util.Set; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; import net.sourceforge.pmd.util.CollectionUtil; -import net.sf.saxon.lib.ExtensionFunctionDefinition; - /** * Default XPath functions provided by pmd-core. */ public final class DefaultXPathFunctions { - private static final Set DEFAULTS = + private static final Set DEFAULTS = CollectionUtil.immutableSetOf( FileNameXPathFunction.INSTANCE, CoordinateXPathFunction.START_LINE, @@ -29,7 +28,7 @@ public final class DefaultXPathFunctions { // utility class } - public static Set getDefaultFunctions() { + public static Set getDefaultFunctions() { return DEFAULTS; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DeprecatedAttrLogger.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DeprecatedAttrLogger.java index 268684c2b8..1190e0235e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DeprecatedAttrLogger.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DeprecatedAttrLogger.java @@ -11,8 +11,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sourceforge.pmd.lang.rule.Rule; -import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.Attribute; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; /** * Records usages of deprecated attributes in XPath rules. This needs diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java index 97131458e1..1f170aee12 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java @@ -6,23 +6,16 @@ package net.sourceforge.pmd.lang.rule.xpath.internal; import java.util.Objects; -import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.RootNode; -import net.sourceforge.pmd.lang.rule.xpath.impl.AbstractXPathFunctionDef; - -import net.sf.saxon.expr.XPathContext; -import net.sf.saxon.lib.ExtensionFunctionCall; -import net.sf.saxon.om.Sequence; -import net.sf.saxon.trans.XPathException; -import net.sf.saxon.value.SequenceType; -import net.sf.saxon.value.StringValue; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException; /** * A function that returns the current file name. * * @author Clément Fournier */ -public final class FileNameXPathFunction extends AbstractXPathFunctionDef { +public final class FileNameXPathFunction extends XPathFunctionDefinition { public static final FileNameXPathFunction INSTANCE = new FileNameXPathFunction(); @@ -31,36 +24,31 @@ public final class FileNameXPathFunction extends AbstractXPathFunctionDef { } @Override - public SequenceType[] getArgumentTypes() { - return new SequenceType[0]; + public Type getResultType() { + return Type.SINGLE_STRING; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.STRING_SEQUENCE; + public boolean dependsOnContext() { + return true; } @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { - - @Override - public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node node = XPathElementToNodeHelper.itemToNode(context.getContextItem()); - if (node == null) { - throw new XPathException( - "Cannot call function '" + getFunctionQName().getLocalPart() - + "' with context item " + context.getContextItem() - ); - } - RootNode root = node.getRoot(); - Objects.requireNonNull(root, "No root node in tree?"); - - String fileName = root.getTextDocument().getFileId().getFileName(); - Objects.requireNonNull(fileName, "File name was not set"); - - return new StringValue(fileName); + public FunctionCall makeCallExpression() { + return (node, arguments) -> { + if (node == null) { + throw new XPathFunctionException( + "Cannot call function '" + getQName().getLocalPart() + + "' without context item" + ); } + RootNode root = node.getRoot(); + Objects.requireNonNull(root, "No root node in tree?"); + + String fileName = root.getTextDocument().getFileId().getFileName(); + Objects.requireNonNull(fileName, "File name was not set"); + + return fileName; }; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonExtensionFunctionDefinitionAdapter.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonExtensionFunctionDefinitionAdapter.java new file mode 100644 index 0000000000..31808f9fab --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonExtensionFunctionDefinitionAdapter.java @@ -0,0 +1,172 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.xpath.internal; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.xml.namespace.QName; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException; + +import net.sf.saxon.expr.Expression; +import net.sf.saxon.expr.StaticContext; +import net.sf.saxon.expr.StringLiteral; +import net.sf.saxon.expr.XPathContext; +import net.sf.saxon.lib.ExtensionFunctionCall; +import net.sf.saxon.lib.ExtensionFunctionDefinition; +import net.sf.saxon.om.EmptyAtomicSequence; +import net.sf.saxon.om.Sequence; +import net.sf.saxon.om.StructuredQName; +import net.sf.saxon.pattern.NodeKindTest; +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.value.BigDecimalValue; +import net.sf.saxon.value.BooleanValue; +import net.sf.saxon.value.EmptySequence; +import net.sf.saxon.value.Int64Value; +import net.sf.saxon.value.SequenceExtent; +import net.sf.saxon.value.SequenceType; +import net.sf.saxon.value.StringValue; + +/** + * Converts PMD's {@link XPathFunctionDefinition} into Saxon's {@link ExtensionFunctionDefinition}. + */ +public class SaxonExtensionFunctionDefinitionAdapter extends ExtensionFunctionDefinition { + private static final SequenceType SINGLE_ELEMENT_SEQUENCE_TYPE = NodeKindTest.ELEMENT.one(); + + private final XPathFunctionDefinition definition; + + public SaxonExtensionFunctionDefinitionAdapter(XPathFunctionDefinition definition) { + this.definition = definition; + } + + private SequenceType convertToSequenceType(XPathFunctionDefinition.Type type) { + switch (type) { + case SINGLE_STRING: return SequenceType.SINGLE_STRING; + case SINGLE_BOOLEAN: return SequenceType.SINGLE_BOOLEAN; + case SINGLE_ELEMENT: return SINGLE_ELEMENT_SEQUENCE_TYPE; + case SINGLE_INTEGER: return SequenceType.SINGLE_INTEGER; + case STRING_SEQUENCE: return SequenceType.STRING_SEQUENCE; + case OPTIONAL_STRING: return SequenceType.OPTIONAL_STRING; + case OPTIONAL_DECIMAL: return SequenceType.OPTIONAL_DECIMAL; + default: + throw new UnsupportedOperationException("Type " + type + " is not supported"); + } + } + + private SequenceType[] convertToSequenceTypes(XPathFunctionDefinition.Type[] types) { + SequenceType[] result = new SequenceType[types.length]; + for (int i = 0; i < types.length; i++) { + result[i] = convertToSequenceType(types[i]); + } + return result; + } + + @Override + public StructuredQName getFunctionQName() { + QName qName = definition.getQName(); + return new StructuredQName(qName.getPrefix(), qName.getNamespaceURI(), qName.getLocalPart()); + } + + @Override + public SequenceType[] getArgumentTypes() { + return convertToSequenceTypes(definition.getArgumentTypes()); + } + + @Override + public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { + return convertToSequenceType(definition.getResultType()); + } + + @Override + public boolean dependsOnFocus() { + return definition.dependsOnContext(); + } + + @Override + public ExtensionFunctionCall makeCallExpression() { + XPathFunctionDefinition.FunctionCall call = definition.makeCallExpression(); + return new ExtensionFunctionCall() { + @Override + public Expression rewrite(StaticContext context, Expression[] arguments) throws XPathException { + Object[] convertedArguments = new Object[definition.getArgumentTypes().length]; + for (int i = 0; i < convertedArguments.length; i++) { + if (arguments[i] instanceof StringLiteral) { + convertedArguments[i] = ((StringLiteral) arguments[i]).getStringValue(); + } + } + try { + call.staticInit(convertedArguments); + } catch (XPathFunctionException e) { + XPathException xPathException = new XPathException(e); + xPathException.setIsStaticError(true); + throw xPathException; + } + return null; + } + + @Override + public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { + Node contextNode = null; + if (definition.dependsOnContext()) { + contextNode = XPathElementToNodeHelper.itemToNode(context.getContextItem()); + } + Object[] convertedArguments = new Object[definition.getArgumentTypes().length]; + for (int i = 0; i < convertedArguments.length; i++) { + switch (definition.getArgumentTypes()[i]) { + case SINGLE_STRING: + convertedArguments[i] = arguments[i].head().getStringValue(); + break; + case SINGLE_ELEMENT: + convertedArguments[i] = arguments[i].head(); + break; + default: + throw new UnsupportedOperationException("Don't know how to convert argument type " + definition.getArgumentTypes()[i]); + } + } + + + Object result = null; + try { + result = call.call(contextNode, convertedArguments); + } catch (XPathFunctionException e) { + throw new XPathException(e); + } + Sequence convertedResult = null; + switch (definition.getResultType()) { + case SINGLE_BOOLEAN: + convertedResult = BooleanValue.get((Boolean) result); + break; + case SINGLE_INTEGER: + convertedResult = Int64Value.makeIntegerValue((Integer) result); + break; + case SINGLE_STRING: + convertedResult = new StringValue((String) result); + break; + case OPTIONAL_STRING: + convertedResult = result instanceof Optional && ((Optional) result).isPresent() + ? new StringValue(((Optional) result).get()) + : EmptyAtomicSequence.INSTANCE; + break; + case STRING_SEQUENCE: + convertedResult = result instanceof List + ? new SequenceExtent(((List) result).stream().map(StringValue::new).collect(Collectors.toList())) + : EmptySequence.getInstance(); + break; + case OPTIONAL_DECIMAL: + convertedResult = result instanceof Optional && ((Optional) result).isPresent() + ? new BigDecimalValue(((Optional) result).get()) + : EmptySequence.getInstance(); + break; + default: + throw new UnsupportedOperationException("Don't know how to convert result type " + definition.getResultType()); + } + return convertedResult; + } + }; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java index 70ec7b7e59..60945da303 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java @@ -17,10 +17,10 @@ import org.slf4j.LoggerFactory; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.RootNode; -import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException; import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException.Phase; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.util.DataMap; @@ -194,12 +194,13 @@ public class SaxonXPathRuleQuery { for (final PropertyDescriptor propertyDescriptor : properties.keySet()) { final String name = propertyDescriptor.name(); - if (!"xpath".equals(name) && !XPathRule.VERSION_DESCRIPTOR.name().equals(name)) { + if (!"xpath".equals(name)) { staticCtx.declareProperty(propertyDescriptor); } } - for (ExtensionFunctionDefinition fun : xPathHandler.getRegisteredExtensionFunctions()) { + for (XPathFunctionDefinition xpathFun : xPathHandler.getRegisteredExtensionFunctions()) { + ExtensionFunctionDefinition fun = new SaxonExtensionFunctionDefinitionAdapter(xpathFun); StructuredQName qname = fun.getFunctionQName(); staticCtx.declareNamespace(qname.getPrefix(), qname.getURI()); this.configuration.registerExtensionFunction(fun); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetFactoryTest.java index bcda455453..e9f8e2c1b5 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetFactoryTest.java @@ -241,7 +241,7 @@ class RuleSetFactoryTest extends RulesetFactoryTestBase { "\n" + "\n" + " ruleset desc\n" + " " - + " " + + " " + " d\n" + " 2\n" + " " + ""); assertEquals(1, rs.getRules().size()); @@ -269,7 +269,7 @@ class RuleSetFactoryTest extends RulesetFactoryTestBase { "\n" + "\n" + " ruleset desc\n" + " " - + " " + + " " + " d\n" + " 2\n" + " " diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetWriterTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetWriterTest.java index 916cf559b4..0fd6bf6e49 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetWriterTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/RuleSetWriterTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test; import net.sourceforge.pmd.lang.rule.RuleSet.RuleSetBuilder; import net.sourceforge.pmd.lang.rule.internal.RuleSetReference; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.util.internal.xml.SchemaConstants; /** diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java index 29f4142ad9..abc6d27135 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java @@ -19,6 +19,7 @@ import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.DummyNode.DummyRootNode; import net.sourceforge.pmd.lang.ast.DummyNodeWithDeprecatedAttribute; import net.sourceforge.pmd.lang.document.TextRegion; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.reporting.Report; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java index d24b7e9869..99de993087 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.checkerframework.checker.nullness.qual.NonNull; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.Test; @@ -31,18 +32,12 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; -import net.sourceforge.pmd.lang.rule.xpath.impl.AbstractXPathFunctionDef; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; import net.sf.saxon.expr.Expression; -import net.sf.saxon.expr.XPathContext; -import net.sf.saxon.lib.ExtensionFunctionCall; -import net.sf.saxon.om.Sequence; -import net.sf.saxon.trans.XPathException; -import net.sf.saxon.value.BooleanValue; -import net.sf.saxon.value.SequenceType; class SaxonXPathRuleQueryTest { @@ -422,27 +417,21 @@ class SaxonXPathRuleQueryTest { } @NonNull - private static AbstractXPathFunctionDef imageIsFunction() { - return new AbstractXPathFunctionDef("imageIs", DummyLanguageModule.getInstance()) { + private static XPathFunctionDefinition imageIsFunction() { + return new XPathFunctionDefinition("imageIs", DummyLanguageModule.getInstance()) { @Override - public SequenceType[] getArgumentTypes() { - return new SequenceType[] {SequenceType.SINGLE_STRING}; + public Type[] getArgumentTypes() { + return new Type[] {Type.SINGLE_STRING}; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.SINGLE_BOOLEAN; + public Type getResultType() { + return Type.SINGLE_BOOLEAN; } @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { - @Override - public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node contextNode = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); - return BooleanValue.get(arguments[0].head().getStringValue().equals(contextNode.getImage())); - } - }; + public FunctionCall makeCallExpression() { + return (contextNode, arguments) -> StringUtils.equals(arguments[0].toString(), contextNode.getImage()); } }; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java index 501e222df9..bc3d7ab4bf 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java @@ -9,7 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import net.sourceforge.pmd.lang.document.FileLocation; -import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.reporting.ParametricRuleViolation; diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/lang/rule/TestRuleset1.xml b/pmd-core/src/test/resources/net/sourceforge/pmd/lang/rule/TestRuleset1.xml index b5090aaa8a..f82952a473 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/lang/rule/TestRuleset1.xml +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/lang/rule/TestRuleset1.xml @@ -33,7 +33,7 @@ Just for test Just for test diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml b/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml index 17443c62ab..40af25174a 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml @@ -13,14 +13,13 @@ language="java" since="3.7" message="In J2EE, getClassLoader() might not work as expected. Use Thread.currentThread().getContextClassLoader() instead." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/rules/j2ee.html#UseProperClassLoader"> In J2EE getClassLoader() might not work as expected. Use Thread.currentThread().getContextClassLoader() instead. 3 - @@ -50,7 +49,6 @@ public class Foo { 4 - @@ -95,7 +93,6 @@ public class Foo { 4 - @@ -140,7 +137,6 @@ public class Foo { 4 - @@ -185,7 +181,6 @@ public class Foo { 4 - @@ -230,7 +225,6 @@ public class Foo { 4 - 3 - According to the J2EE specification (p.494), an EJB should not have any static fields @@ -315,7 +308,6 @@ behavior especially when instances are distributed by the container on several J 3 - @@ -363,7 +355,6 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { 3 - - Test 3 - - + - Test Deprecated rule 3 - - + 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 4fea52673a..425037f749 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 @@ -40,7 +40,7 @@ import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.RuleSet; import net.sourceforge.pmd.lang.rule.RuleSetLoadException; import net.sourceforge.pmd.lang.rule.RuleSetLoader; -import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.properties.PropertyDescriptor; public class RuleDocGenerator { @@ -437,7 +437,6 @@ public class RuleDocGenerator { properties.remove(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR); properties.remove(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR); properties.remove(XPathRule.XPATH_DESCRIPTOR); - properties.remove(XPathRule.VERSION_DESCRIPTOR); if (!properties.isEmpty()) { lines.add("**This rule has the following properties:**"); diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index c6c78e76a8..119a865b0d 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -16,7 +16,7 @@ Here might be <script>alert('XSS');</script> as well. And "quotes". language="java" since="0.1" message="Tests that <script>alert('XSS');</script> is properly escaped" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#xssindocumentation"> <script>alert('XSS at the beginning');</script> HTML tags might appear at various places. @@ -57,7 +57,6 @@ Here might be <script>alert('XSS');</script> as well. And "quotes". 3 - Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. 3 - @@ -206,7 +204,6 @@ RuleTag with full category and without quotes: Use {% rule java/sample/RenamedRu 3 - Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. 3 - Don't mix content and style. Use separate CSS-files for the style and introduce classes. @@ -21,7 +21,6 @@ This helps to reuse common styles. 3 - extends BaseJavaXPathFunction { - static final SequenceType[] SINGLE_STRING_SEQ = {SequenceType.SINGLE_STRING}; + static final Type[] SINGLE_STRING_SEQ = {Type.SINGLE_STRING}; private final Class klass; private final BiPredicate checker; @@ -45,31 +36,25 @@ public class BaseContextNodeTestFun extends BaseJavaXPathFun } @Override - public SequenceType[] getArgumentTypes() { + public Type[] getArgumentTypes() { return SINGLE_STRING_SEQ; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.SINGLE_BOOLEAN; + public Type getResultType() { + return Type.SINGLE_BOOLEAN; } @Override - public boolean dependsOnFocus() { + public boolean dependsOnContext() { return true; } @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { - @Override - public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node contextNode = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); - String fullTypeName = arguments[0].head().getStringValue(); - - - return BooleanValue.get(klass.isInstance(contextNode) && checker.test(fullTypeName, (T) contextNode)); - } + public FunctionCall makeCallExpression() { + return (contextNode, arguments) -> { + String fullTypeName = arguments[0].toString(); + return klass.isInstance(contextNode) && checker.test(fullTypeName, (T) contextNode); }; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseJavaXPathFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseJavaXPathFunction.java index 450a33013e..e8927bde54 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseJavaXPathFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseJavaXPathFunction.java @@ -5,9 +5,9 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; import net.sourceforge.pmd.lang.java.JavaLanguageModule; -import net.sourceforge.pmd.lang.rule.xpath.impl.AbstractXPathFunctionDef; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; -abstract class BaseJavaXPathFunction extends AbstractXPathFunctionDef { +abstract class BaseJavaXPathFunction extends XPathFunctionDefinition { protected BaseJavaXPathFunction(String localName) { super(localName, JavaLanguageModule.getInstance()); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseRewrittenFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseRewrittenFunction.java index f2f1e4c768..0f81232666 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseRewrittenFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseRewrittenFunction.java @@ -7,17 +7,7 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; import static net.sourceforge.pmd.lang.java.rule.xpath.internal.BaseContextNodeTestFun.SINGLE_STRING_SEQ; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.rule.xpath.internal.AstElementNode; - -import net.sf.saxon.expr.Expression; -import net.sf.saxon.expr.StaticContext; -import net.sf.saxon.expr.StringLiteral; -import net.sf.saxon.expr.XPathContext; -import net.sf.saxon.lib.ExtensionFunctionCall; -import net.sf.saxon.om.Sequence; -import net.sf.saxon.trans.XPathException; -import net.sf.saxon.value.BooleanValue; -import net.sf.saxon.value.SequenceType; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException; /** @@ -39,17 +29,17 @@ abstract class BaseRewrittenFunction extends BaseJavaXPathFun } @Override - public SequenceType[] getArgumentTypes() { + public Type[] getArgumentTypes() { return SINGLE_STRING_SEQ; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.SINGLE_BOOLEAN; + public Type getResultType() { + return Type.SINGLE_BOOLEAN; } @Override - public boolean dependsOnFocus() { + public boolean dependsOnContext() { return true; } @@ -59,7 +49,7 @@ abstract class BaseRewrittenFunction extends BaseJavaXPathFun * if the arg is constant, otherwise it's anyway called before {@link #matches(Node, String, Object, boolean)} * is called. */ - protected abstract S parseArgument(String arg) throws XPathException; + protected abstract S parseArgument(String arg) throws XPathFunctionException; /** * Compute the result of the function. @@ -71,48 +61,40 @@ abstract class BaseRewrittenFunction extends BaseJavaXPathFun * * @return Whether the function matches */ - protected abstract boolean matches(N contextNode, String arg, S parsedArg, boolean isConstant) throws XPathException; + protected abstract boolean matches(N contextNode, String arg, S parsedArg, boolean isConstant) throws XPathFunctionException; @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { + public FunctionCall makeCallExpression() { + return new FunctionCall() { private S constantState; private boolean isConstant; @Override - public Expression rewrite(StaticContext context, Expression[] arguments) throws XPathException { - // If the argument is a string literal then we can preload - // the class, and check that it's valid at expression build time + public void staticInit(Object[] arguments) throws XPathFunctionException { + if (arguments[0] instanceof String) { + // If the argument was a string literal then we can preload + // the class, and check that it's valid at expression build time - Expression firstArg = arguments[0]; // this expression has been type checked so there is an argument - if (firstArg instanceof StringLiteral) { - String name = ((StringLiteral) firstArg).getStringValue(); - try { - constantState = parseArgument(name); - } catch (XPathException e) { - e.setIsStaticError(true); - throw e; - } + String name = (String) arguments[0]; // this expression has been type checked so there is an argument + constantState = parseArgument(name); isConstant = true; } - return null; } @Override - public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node node = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); + public Boolean call(Node node, Object[] arguments) throws XPathFunctionException { if (!contextNodeType.isInstance(node)) { // we could report that as an error - return BooleanValue.FALSE; + return false; } - String arg = arguments[0].head().getStringValue(); + String arg = arguments[0].toString(); S parsedArg = isConstant ? constantState : parseArgument(arg); - return BooleanValue.get(matches((N) node, arg, parsedArg, isConstant)); + return matches((N) node, arg, parsedArg, isConstant); } }; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetCommentOnFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetCommentOnFunction.java index 6a3169fae8..6a45b987ba 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetCommentOnFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetCommentOnFunction.java @@ -5,19 +5,11 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; import java.util.List; +import java.util.Optional; -import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.document.FileLocation; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.JavaComment; -import net.sourceforge.pmd.lang.rule.xpath.internal.AstElementNode; - -import net.sf.saxon.expr.XPathContext; -import net.sf.saxon.lib.ExtensionFunctionCall; -import net.sf.saxon.om.EmptyAtomicSequence; -import net.sf.saxon.om.Sequence; -import net.sf.saxon.value.SequenceType; -import net.sf.saxon.value.StringValue; /** @@ -37,43 +29,31 @@ public class GetCommentOnFunction extends BaseJavaXPathFunction { } @Override - public SequenceType[] getArgumentTypes() { - return new SequenceType[0]; + public Type getResultType() { + return Type.OPTIONAL_STRING; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.OPTIONAL_STRING; - } - - - @Override - public boolean dependsOnFocus() { + public boolean dependsOnContext() { return true; } @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { - @Override - public Sequence call(XPathContext context, Sequence[] arguments) { - Node contextNode = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); + public FunctionCall makeCallExpression() { + return (contextNode, arguments) -> { + int codeBeginLine = contextNode.getBeginLine(); + int codeEndLine = contextNode.getEndLine(); - int codeBeginLine = contextNode.getBeginLine(); - int codeEndLine = contextNode.getEndLine(); - - List commentList = contextNode.ancestorsOrSelf().filterIs(ASTCompilationUnit.class).first().getComments(); - for (JavaComment comment : commentList) { - FileLocation location = comment.getReportLocation(); - if (location.getStartLine() == codeBeginLine || location.getEndLine() == codeEndLine) { - return new StringValue(comment.getText()); - } + List commentList = contextNode.ancestorsOrSelf().filterIs(ASTCompilationUnit.class).first().getComments(); + for (JavaComment comment : commentList) { + FileLocation location = comment.getReportLocation(); + if (location.getStartLine() == codeBeginLine || location.getEndLine() == codeEndLine) { + return Optional.of(comment.getText().toString()); } - return EmptyAtomicSequence.INSTANCE; } - + return Optional.empty(); }; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetModifiersFun.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetModifiersFun.java index 501427045b..52c32bc3ad 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetModifiersFun.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/GetModifiersFun.java @@ -4,29 +4,19 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; +import java.util.Collections; import java.util.Set; -import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTModifierList; import net.sourceforge.pmd.lang.java.ast.JModifier; import net.sourceforge.pmd.lang.java.ast.ModifierOwner; -import net.sourceforge.pmd.lang.rule.xpath.internal.AstElementNode; import net.sourceforge.pmd.util.CollectionUtil; -import net.sf.saxon.expr.XPathContext; -import net.sf.saxon.lib.ExtensionFunctionCall; -import net.sf.saxon.om.Sequence; -import net.sf.saxon.value.EmptySequence; -import net.sf.saxon.value.SequenceExtent; -import net.sf.saxon.value.SequenceType; -import net.sf.saxon.value.StringValue; - /** * The two functions {@code modifiers} and {@code explicitModifiers}. */ public final class GetModifiersFun extends BaseJavaXPathFunction { - private static final SequenceType[] ARGTYPES = {}; private final boolean explicit; public static final GetModifiersFun GET_EFFECTIVE = new GetModifiersFun("modifiers", false); @@ -38,36 +28,25 @@ public final class GetModifiersFun extends BaseJavaXPathFunction { } @Override - public SequenceType[] getArgumentTypes() { - return ARGTYPES; + public Type getResultType() { + return Type.STRING_SEQUENCE; } @Override - public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.STRING_SEQUENCE; - } - - @Override - public boolean dependsOnFocus() { + public boolean dependsOnContext() { return true; } @Override - public ExtensionFunctionCall makeCallExpression() { - return new ExtensionFunctionCall() { - @Override - public Sequence call(XPathContext context, Sequence[] arguments) { - Node contextNode = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); - - if (contextNode instanceof ModifierOwner) { - ASTModifierList modList = ((ModifierOwner) contextNode).getModifiers(); - Set mods = explicit ? modList.getExplicitModifiers() - : modList.getEffectiveModifiers(); - return new SequenceExtent(CollectionUtil.map(mods, mod -> new StringValue(mod.getToken()))); - } else { - return EmptySequence.getInstance(); - } + public FunctionCall makeCallExpression() { + return (contextNode, arguments) -> { + if (contextNode instanceof ModifierOwner) { + ASTModifierList modList = ((ModifierOwner) contextNode).getModifiers(); + Set mods = explicit ? modList.getExplicitModifiers() + : modList.getEffectiveModifiers(); + return CollectionUtil.map(mods, JModifier::getToken); } + return Collections.emptyList(); }; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MatchesSignatureFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MatchesSignatureFunction.java index 187d100612..7e74e78026 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MatchesSignatureFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MatchesSignatureFunction.java @@ -6,8 +6,7 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; import net.sourceforge.pmd.lang.java.ast.InvocationNode; import net.sourceforge.pmd.lang.java.types.InvocationMatcher; - -import net.sf.saxon.trans.XPathException; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException; public final class MatchesSignatureFunction extends BaseRewrittenFunction { @@ -18,16 +17,16 @@ public final class MatchesSignatureFunction extends BaseRewrittenFunction { + String metricKey = arguments[0].toString(); + return getMetric(contextNode, metricKey); }; } @@ -78,16 +63,16 @@ public final class MetricFunction extends BaseJavaXPathFunction { } - private static double getMetric(Node n, String metricKeyName) throws XPathException { + private static Optional getMetric(Node n, String metricKeyName) throws XPathFunctionException { LanguageMetricsProvider provider = n.getAstInfo().getLanguageProcessor().services().getLanguageMetricsProvider(); Metric metric = provider.getMetricWithName(metricKeyName); if (metric == null) { - throw new XPathException(badMetricKeyMessage(metricKeyName)); + throw new XPathFunctionException(badMetricKeyMessage(metricKeyName)); } Number computed = Metric.compute(metric, n, MetricOptions.emptyOptions()); - return computed == null ? Double.NaN : computed.doubleValue(); + return computed == null ? Optional.empty() : Optional.of(computed.doubleValue()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/NodeIsFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/NodeIsFunction.java index 0b30a1f0f1..98dce04f8f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/NodeIsFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/NodeIsFunction.java @@ -5,8 +5,7 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; import net.sourceforge.pmd.lang.java.ast.JavaNode; - -import net.sf.saxon.trans.XPathException; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException; public final class NodeIsFunction extends BaseRewrittenFunction, JavaNode> { @@ -17,16 +16,16 @@ public final class NodeIsFunction extends BaseRewrittenFunction, JavaNo } @Override - protected Class parseArgument(String arg) throws XPathException { + protected Class parseArgument(String arg) throws XPathFunctionException { try { return Class.forName("net.sourceforge.pmd.lang.java.ast.AST" + arg); } catch (ClassNotFoundException e) { - throw new XPathException("No class named AST" + arg); + throw new XPathFunctionException("No class named AST" + arg, e); } } @Override - protected boolean matches(JavaNode contextNode, String arg, Class parsedArg, boolean isConstant) throws XPathException { + protected boolean matches(JavaNode contextNode, String arg, Class parsedArg, boolean isConstant) { return parsedArg.isInstance(contextNode); } diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 3da6e337ca..03ed6fd517 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -133,7 +133,7 @@ public class Foo { language="java" since="6.18.0" message="You shouldn't declare field of MessageDigest type, because unsynchronized access could cause problems" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#avoidmessagedigestfield"> Declaring a MessageDigest instance as a field make this instance directly available to multiple threads. @@ -183,7 +183,7 @@ public class AvoidMessageDigestFieldExample { language="java" since="3.2" message="Avoid printStackTrace(); use a logger call instead." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#avoidprintstacktrace"> Avoid printStackTrace(); use a logger call instead. @@ -336,7 +336,7 @@ public class Hello { language="java" since="4.2" message="StringBuffers can grow quite a lot, and so may become a source of memory leak (if the owning class has a long life time)." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#avoidstringbufferfield"> StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks @@ -414,7 +414,7 @@ if (rst.next()) { // result is properly examined and used language="java" since="5.5" message="Using constants in interfaces is a bad practice." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#constantsininterface"> Using constants in interfaces is a bad practice. Interfaces define types, constants are implementation details better placed in classes or enums. If the constants are best viewed as members of an enumerated type, you should export them with an enum type. @@ -461,7 +461,7 @@ public interface YetAnotherConstantInterface { language="java" since="1.5" message="The default label should be the last label in a switch statement" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#defaultlabelnotlastinswitchstmt"> By convention, the default label should be the last label in a switch statement. @@ -498,7 +498,7 @@ public class Foo { language="java" since="6.16.0" message="Double-brace initialization should be avoided" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#doublebraceinitialization"> Double brace initialisation is a pattern to initialise eg collections concisely. But it implicitly @@ -572,7 +572,7 @@ public class MyClass { language="java" since="6.11.0" message="Too many control variables in the 'for' statement" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#forloopvariablecount"> Having a lot of control variables in a 'for' loop makes it harder to see what range of values @@ -632,7 +632,7 @@ log.debug("log something expensive: {}", () -> calculateExpensiveLoggingText()); language="java" since="4.0" message="JUnit 4 indicates test suites via annotations, not the suite method." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4suitesshouldusesuiteannotation"> In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated @@ -670,7 +670,7 @@ public class GoodTest { language="java" since="4.0" message="JUnit 4 tests that clean up tests should use the @After annotation, JUnit5 tests should use @AfterEach or @AfterAll" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4testshoulduseafterannotation"> In JUnit 3, the tearDown method was used to clean up all data entities required in running tests. @@ -714,7 +714,7 @@ public class MyTest2 { language="java" since="4.0" message="JUnit 4 tests that set up tests should use the @Before annotation, JUnit5 tests should use @BeforeEach or @BeforeAll" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4testshouldusebeforeannotation"> In JUnit 3, the setUp method was used to set up all data entities required in running tests. @@ -759,7 +759,7 @@ public class MyTest2 { language="java" since="4.0" message="Unit tests that execute tests should use the @Test annotation. In case of JUnit 5, test methods might use @RepeatedTest, @TestFactory, @TestTemplate or @ParameterizedTest annotations instead." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit4testshouldusetestannotation"> In JUnit 3, the framework executed all methods which started with the word test as a unit test. @@ -813,7 +813,7 @@ public class MyTest { language="java" since="6.35.0" message="JUnit 5 tests should be package-private." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit5testshouldbepackageprivate"> 3 - @@ -1242,7 +1241,7 @@ public class Foo { language="java" since="3.4" message="Consider replacing this Enumeration with the newer java.util.Iterator" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#replaceenumerationwithiterator"> Consider replacing Enumeration usages with the newer java.util.Iterator @@ -1276,7 +1275,7 @@ public class Foo implements Enumeration { language="java" since="3.4" message="Consider replacing this Hashtable with the newer java.util.Map" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#replacehashtablewithmap"> Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. @@ -1304,7 +1303,7 @@ public class Foo { language="java" since="3.4" message="Consider replacing this Vector with the newer java.util.List" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#replacevectorwithlist"> Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required. @@ -1370,7 +1369,7 @@ class SomeTestClass { language="java" since="1.0" message="Switch statements should be exhaustive, add a default case (or missing enum branches)" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#switchstmtsshouldhavedefault"> Switch statements should be exhaustive, to make their control flow @@ -1404,7 +1403,7 @@ class Foo {{ language="java" since="2.1" message="Usage of System.out/err" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#systemprintln"> References to System.(out|err).print are usually intended for debugging purposes and can remain in @@ -1697,7 +1696,7 @@ public class Foo { since="6.34.0" minimumLanguageVersion="1.7" message="Please use StandardCharsets constants" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#usestandardcharsets"> Starting with Java 7, StandardCharsets provides constants for common Charset objects, such as UTF-8. @@ -1786,7 +1785,7 @@ public class TryWithResources { minimumLanguageVersion="1.5" since="5.0" message="Consider using varargs for methods or constructors which take an array the last parameter." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#usevarargs"> Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic @@ -1825,7 +1824,7 @@ public class Foo { - Avoid using dollar signs in variable/method/class/interface names. @@ -70,7 +70,7 @@ public class Fo$o { // not a recommended name language="java" since="2.1" message="Avoid protected fields in a final class. Change to private or package access." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#avoidprotectedfieldinfinalclass"> Do not use protected fields in final classes since they cannot be subclassed. @@ -103,7 +103,7 @@ public final class Bar { language="java" since="5.1" message="Avoid protected methods in a final class that doesn't extend anything other than Object. Change to private or package access." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#avoidprotectedmethodinfinalclassnotextending"> Do not use protected methods in most final classes since they cannot be subclassed. This should @@ -136,7 +136,7 @@ public final class Foo { language="java" since="4.1" message="The use of native code is not recommended." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#avoidusingnativecode"> Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability @@ -173,7 +173,7 @@ public class SomeJNIClass { language="java" since="4.0" message="A 'getX()' method which returns a boolean should be named 'isX()'" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#booleangetmethodname"> Methods that return boolean results should be named as predicate statements to denote this. @@ -207,7 +207,7 @@ public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true language="java" since="3.0" message="It is a good practice to call super() in a constructor" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#callsuperinconstructor"> It is a good practice to call super() in a constructor. If super() is not called but @@ -357,7 +357,7 @@ boolean bar(int x, int y) { language="java" since="6.2.0" message="This statement should have braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#controlstatementbraces"> Enforce a policy for braces on control statements. It is recommended to use braces on 'if ... else' @@ -419,7 +419,7 @@ while (true) { // preferred approach @@ -509,7 +509,7 @@ class Foo { language="java" since="5.0" message="No need to explicitly extend Object." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#extendsobject"> No need to explicitly extend Object. 4 @@ -600,7 +600,7 @@ public class HelloWorldBean { language="java" since="6.42.0" message="Final parameter in abstract method" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" typeResolution="true" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#finalparameterinabstractmethod"> @@ -608,7 +608,6 @@ public class HelloWorldBean { 1 - Some for loops can be simplified to while loops, this makes them more concise. @@ -702,7 +701,7 @@ public class Foo { language="java" since="4.2.6" message="Generics names should be a one letter long and upper case." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#genericsnaming"> Names for references to generic values should be limited to a single uppercase letter. @@ -841,7 +840,7 @@ public class LinguisticNaming { @@ -873,7 +872,7 @@ public interface MissingProperSuffix extends javax.ejb.EJBLocalHome {} // non-s @@ -964,7 +963,7 @@ public class Bar { language="java" since="0.3" message="Avoid excessively long variable names like {0}" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#longvariable"> Fields, formal arguments, or local variable names that are too long can make the code difficult to follow. @@ -998,7 +997,7 @@ public class Something { @@ -1080,7 +1079,7 @@ public class Foo { language="java" since="3.3" message="All classes, interfaces, enums and annotations must belong to a named package" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#nopackage"> Detects when a class, interface, enum or annotation does not have a package definition. @@ -1105,7 +1104,7 @@ public class ClassInDefaultPackage { since="6.10.0" minimumLanguageVersion="1.7" message="Number {0} should separate every third digit with an underscore" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#useunderscoresinnumericliterals"> Since Java 1.7, numeric literals can use underscores to separate digits. This rule enforces that @@ -1180,7 +1179,7 @@ public class OneReturnOnly1 { language="java" since="3.3" message="Package name contains upper case characters" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#packagecase"> Detects when a package definition contains uppercase characters. @@ -1261,7 +1260,7 @@ public int getLength(String[] strings) { @@ -1298,7 +1297,7 @@ public interface BadSuffixBean extends javax.ejb.EJBObject {} @@ -1331,7 +1330,7 @@ public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-stand language="java" since="5.0" message="Avoid short class names like {0}" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#shortclassname"> Short Classnames with fewer than e.g. five characters are not recommended. @@ -1359,7 +1358,7 @@ public class Foo { language="java" since="0.3" message="Avoid using short method names" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#shortmethodname"> Method names that are very short are not helpful to the reader. @@ -1389,7 +1388,7 @@ public class ShortMethod { language="java" since="0.3" message="Avoid variables with short names like {0}" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#shortvariable"> Fields, local variables, enum constant names or parameter names that are very short are not helpful to the reader. @@ -1434,7 +1433,7 @@ public class Something { @@ -1471,7 +1470,7 @@ import static Yoko; // Too much ! language="java" since="6.2.0" message="Avoid the use of value in annotations when it's the only element" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#unnecessaryannotationvalueelement"> Avoid the use of value in annotations when it's the only element. @@ -1798,7 +1797,7 @@ public class Foo { language="java" since="6.46.0" message="Unnecessary semicolon" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#unnecessarysemicolon"> Reports unnecessary semicolons (so called "empty statements" and "empty declarations"). @@ -1812,7 +1811,6 @@ public class Foo { 3 - Java 10 introduced the `var` keyword. This reduces the amount of code written because java can infer the type @@ -1905,7 +1903,6 @@ See also [Local Variable Type Inference Style Guidelines](https://openjdk.org/pr - Reports qualified this usages in the same class. @@ -2018,7 +2015,7 @@ public class Foo { language="java" since="6.15.0" message="Array initialization can be written shorter" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#useshortarrayinitializer"> @@ -51,7 +51,7 @@ public abstract class Example { since="4.2.6" language="java" message="Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#avoidcatchinggenericexception"> Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block. @@ -122,7 +122,7 @@ public class Foo { language="java" since="3.8" message="A catch statement that catches an exception only to rethrow it should be avoided." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#avoidrethrowingexception"> Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. @@ -156,7 +156,7 @@ public void bar() { since="4.2.5" language="java" message="A catch statement that catches an exception only to wrap it in a new instance of the same type of exception and throw it should be avoided" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#avoidthrowingnewinstanceofsameexception"> Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to @@ -243,7 +243,7 @@ public class Foo { language="java" since="1.8" message="Avoid throwing raw exception types." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#avoidthrowingrawexceptiontypes"> Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable, @@ -283,7 +283,7 @@ public class Foo { since="6.13.0" language="java" message="A method or constructor should not explicitly declare unchecked exceptions in its ''throws'' clause" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#avoiduncheckedexceptionsinsignatures"> Reports unchecked exceptions in the `throws` clause of a method or constructor. @@ -334,7 +334,7 @@ public class Foo { //Should be final language="java" since="3.1" message="This if statement could be combined with its parent" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#collapsibleifstatements"> Errors are system exceptions. Do not extend them. @@ -796,7 +796,7 @@ public class Foo { language="java" since="1.1" message="This final field could be made static" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#finalfieldcouldbestatic"> If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead @@ -1013,7 +1013,7 @@ public class Foo { @@ -1197,7 +1197,7 @@ public void foo() throws Exception { language="java" since="5.4.0" message="This conditional expression can be simplified with || or &&" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#simplifiedternary"> Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. @@ -1401,7 +1401,7 @@ public class Foo { language="java" since="3.0" message="Too many fields" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#toomanyfields"> Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, @@ -1444,7 +1444,7 @@ public class Person { // this is more manageable @@ -1505,7 +1505,7 @@ public Long getId() { language="java" since="4.2.6" message="Rather than using a lot of String arguments, consider using a container object for those values." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#useobjectforclearerapi"> When you write a public method, you should be thinking in terms of an API. If your method is public, it means other class @@ -1573,7 +1573,7 @@ public class MaybeAUtility { language="java" since="6.35.0" message="Do not use non-final non-private static fields" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#mutablestaticstate"> Non-private static fields should be made constants (or immutable references) by @@ -1590,7 +1590,6 @@ rule {% rule java/errorprone/AssignmentToNonFinalStatic %}. 3 - Uncommented Empty Constructor finds instances where a constructor does not @@ -123,7 +123,7 @@ public Foo() { language="java" since="3.4" message="Document empty method body" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_documentation.html#uncommentedemptymethodbody"> Uncommented Empty Method Body finds instances where a method body does not contain diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index ecd6966822..9bf0ad3cb6 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -57,7 +57,7 @@ public class StaticField { language="java" since="4.1" message="You should not modify visibility of constructors, methods or fields using setAccessible()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidaccessibilityalteration"> Methods such as `getDeclaredConstructors()`, `getDeclaredMethods()`, and `getDeclaredFields()` also @@ -135,7 +135,7 @@ public class Violation { maximumLanguageVersion="1.3" since="3.4" message="Avoid using assert as an identifier; it became a reserved word in JDK 1.4" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidassertasidentifier"> Use of the term `assert` will conflict with newer versions of Java since it is a reserved word. @@ -196,7 +196,7 @@ for (int i = 0; i < 10; i++) { language="java" since="3.0" message="Avoid calling finalize() explicitly" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcallingfinalize"> The method Object.finalize() is called by the garbage collector on an object when garbage collection determines @@ -230,7 +230,7 @@ void foo() { language="java" since="1.8" message="Avoid catching NullPointerException; consider removing the cause of the NPE." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingnpe"> Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the @@ -264,7 +264,7 @@ public class Foo { language="java" since="1.2" message="A catch statement should never catch throwable since it includes errors." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingthrowable"> Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as @@ -295,7 +295,7 @@ public void bar() { language="java" since="3.4" message="Avoid creating BigDecimal with a decimal (float/double) literal. Use a String literal" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoiddecimalliteralsinbigdecimalconstructor"> One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actually @@ -357,7 +357,7 @@ private void buz(String x) {} maximumLanguageVersion="1.4" since="3.4" message="Avoid using enum as an identifier; it's a reserved word in JDK 1.5" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidenumasidentifier"> Use of the term `enum` will conflict with newer versions of Java since it is a reserved word. @@ -387,7 +387,7 @@ public class A { language="java" since="3.0" message="Field {0} has the same name as a method" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidfieldnamematchingmethodname"> It can be confusing to have a field name with the same name as a method. While this is permitted, @@ -422,7 +422,7 @@ public class Foo { language="java" since="3.0" message="It is somewhat confusing to have a field name matching the declaring class name" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidfieldnamematchingtypename"> It is somewhat confusing to have a field name matching the declaring type name. @@ -455,7 +455,7 @@ public interface Operation { language="java" since="3.0" message="An instanceof check is being performed on the caught exception. Create a separate catch clause for this exception type." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidinstanceofchecksincatchclause"> Each caught exception type should be handled in its own catch clause. @@ -495,7 +495,7 @@ try { // Prefer this: language="java" since="4.2.6" message="Avoid using literals in if statements" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidliteralsinifcondition"> Avoid using hard-coded literals in conditional statements. By declaring them as static variables @@ -576,7 +576,7 @@ public void checkRequests() { since="4.2.6" language="java" message="Avoid statements in a catch block that invoke accessors on the exception without using the information" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidlosingexceptioninformation"> Statements in a catch block that invoke accessors on the exception without using the information @@ -614,7 +614,7 @@ public void bar() { @@ -704,7 +704,7 @@ public String bar(String string) { since="4.2.5" language="java" message="super should be called at the start of the method" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#callsuperfirst"> Super should be called at the start of the method 3 @@ -747,7 +747,7 @@ public class DummyActivity extends Activity { since="4.2.5" language="java" message="super should be called at the end of the method" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#callsuperlast"> Super should be called at the end of the method @@ -822,7 +822,7 @@ public class Foo { language="java" since="3.4" message="This usage of the Collection.toArray() method will throw a ClassCastException." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#classcastexceptionwithtoarray"> When deriving an array of a specific class from your Collection, one should provide an array of @@ -859,7 +859,7 @@ Integer[] b = (Integer [])c.toArray(new Integer[0]); language="java" since="5.4.0" message="clone() method must be public if the class implements Cloneable" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#clonemethodmustbepublic"> The java manual says "By convention, classes that implement this interface should override @@ -928,7 +928,7 @@ public class MyClass { minimumLanguageVersion="1.5" since="5.4.0" message="The return type of the clone() method must be the class name when implements Cloneable" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#clonemethodreturntypemustmatchclassname"> If a class implements `Cloneable` the return type of the method `clone()` must be the class name. That way, the caller @@ -1020,7 +1020,7 @@ public class Bar { language="java" since="3.2" message="Use equals() to compare object references." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#compareobjectswithequals"> Use `equals()` to compare object references; avoid comparing them with `==`. @@ -1035,7 +1035,6 @@ in the `typesThatCompareByReference` property. 3 - java.lang.Enum,java.lang.Class @@ -1074,7 +1073,7 @@ class Foo { language="java" since="6.36.0" message="Comparisons with NaN always return false" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#comparisonwithnan"> 3 - Calls to `System.gc()`, `Runtime.getRuntime().gc()`, and `System.runFinalization()` are not advised. @@ -1240,7 +1238,7 @@ public class GCCall { language="java" since="6.0.0" message="Exceptions should not extend java.lang.Throwable" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotextendjavalangthrowable"> Extend Exception or RuntimeException instead of Throwable. @@ -1267,7 +1265,7 @@ public class Foo extends Throwable { } since="4.2.6" language="java" message="Do not hardcode /sdcard." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donothardcodesdcard"> Use Environment.getExternalStorageDirectory() instead of "/sdcard" @@ -1295,7 +1293,7 @@ public class MyActivity extends Activity { language="java" since="4.1" message="System.exit() should not be used in J2EE/JEE apps" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotterminatevm"> Web applications should not call `System.exit()`, since only the web container or the @@ -1336,7 +1334,7 @@ public void foo() { language="java" since="4.2" message="A throw statement in a finally block makes the control flow hard to understand." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotthrowexceptioninfinally"> Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions @@ -1371,7 +1369,7 @@ public class Foo { language="java" since="1.5" message="Avoid importing anything from the 'sun.*' packages" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#dontimportsun"> Avoid importing anything from the 'sun.*' packages. These packages are not portable @@ -1404,7 +1402,7 @@ public class Foo {} language="java" since="4.3" message="Don't use floating point for loop indices. If you must use floating point, use double." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#dontusefloattypeforloopindices"> Don't use floating point for loop indices. If you must use floating point, use double @@ -1442,7 +1440,7 @@ public class Count { language="java" since="0.1" message="Avoid empty catch blocks" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptycatchblock"> Empty Catch Block finds instances where an exception is caught, but nothing is done. @@ -1484,7 +1482,7 @@ public void doSomething() { language="java" since="1.5" message="Avoid empty finalize methods" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyfinalizer"> Empty finalize methods serve no purpose and should be removed. Note that Oracle has declared Object.finalize() as deprecated since JDK 9. @@ -1514,7 +1512,7 @@ public class Foo { language="java" since="0.4" message="Avoid empty finally blocks" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyfinallyblock"> Empty finally blocks serve no purpose and should be removed. @@ -1552,7 +1550,7 @@ public class Foo { language="java" since="0.1" message="Avoid empty 'if' statements" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyifstmt"> Empty If Statement finds instances where a condition is checked but nothing is done about it. @@ -1588,7 +1586,7 @@ public class Foo { language="java" since="5.0" message="Empty initializer was found" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyinitializer"> Empty initializers serve no purpose and should be removed. @@ -1620,7 +1618,7 @@ public class Foo { language="java" since="5.0" message="Avoid empty block statements." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptystatementblock"> Empty block statements serve no purpose and should be removed. @@ -1655,7 +1653,7 @@ public class Foo { since="1.5" deprecated="true" message="An empty statement (semicolon) not part of a loop" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptystatementnotinloop"> An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' @@ -1699,7 +1697,7 @@ public void doit() { language="java" since="1.0" message="Avoid empty switch statements" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyswitchstatements"> Empty switch statements serve no purpose and should be removed.# @@ -1731,7 +1729,7 @@ public void bar() { language="java" since="1.3" message="Avoid empty synchronized blocks" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptysynchronizedblock"> Empty synchronized blocks serve no purpose and should be removed. @@ -1763,7 +1761,7 @@ public class Foo { language="java" since="0.4" message="Avoid empty try blocks" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptytryblock"> Avoid empty try blocks - what's the point? @@ -1800,7 +1798,7 @@ public class Foo { language="java" since="0.2" message="Avoid empty 'while' statements" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptywhilestmt"> Empty While Statement finds all instances where a while statement does nothing. @@ -1835,7 +1833,7 @@ void bar(int a, int b) { language="java" since="1.9" message="Avoid using equals() to compare against null" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#equalsnull"> Tests for null should not use the equals() method. The '==' operator should be used instead. @@ -1869,7 +1867,7 @@ if (x == null) { // preferred language="java" since="1.5" message="Last statement in finalize method should be a call to super.finalize()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizedoesnotcallsuperfinalize"> If the finalize() is implemented, its last action should be to call super.finalize. Note that Oracle has declared Object.finalize() as deprecated since JDK 9. @@ -1904,7 +1902,7 @@ protected void finalize() { language="java" since="1.5" message="Finalize should do something besides just calling super.finalize()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeonlycallssuperfinalize"> If the finalize() is implemented, it should do something besides just calling super.finalize(). Note that Oracle has declared Object.finalize() as deprecated since JDK 9. @@ -1933,7 +1931,7 @@ protected void finalize() { language="java" since="1.5" message="Finalize methods should not be overloaded" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeoverloaded"> Methods named finalize() should not have parameters. It is confusing and most likely an attempt to @@ -1966,7 +1964,7 @@ public class Foo { language="java" since="1.1" message="If you override finalize(), make it protected" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeshouldbeprotected"> When overriding the finalize(), the new method should be set as protected. If made public, @@ -2060,7 +2058,7 @@ public void bar(int status) { language="java" since="2.0" message="Avoid instantiating an object just to call getClass() on it; use the .class public member instead" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#instantiationtogetclass"> Avoid instantiating an object just to call getClass() on it; use the .class public member instead. @@ -2117,7 +2115,7 @@ LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The except language="java" since="1.0" message="Avoid modifying an outer loop incrementer in an inner loop for update expression" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#jumbledincrementer"> Avoid jumbled loop incrementers - it's usually a mistake, and is confusing even if intentional. @@ -2202,7 +2200,7 @@ public class Foo extends TestCase { language="java" since="1.5" message="A method should not have the same name as its containing class" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#methodwithsamenameasenclosingclass"> A method should not have the same name as its containing class. @@ -2234,7 +2232,7 @@ public class MyClass { language="java" since="3.5" message="The null check here is misplaced; if the variable ''{0}'' is null there will be a NullPointerException" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#misplacednullcheck"> The null check here is misplaced. If the variable is null a `NullPointerException` will be thrown. @@ -2304,7 +2302,7 @@ public class Foo { language="java" since="3.0" message="Classes implementing Serializable should set a serialVersionUID" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#missingserialversionuid"> Serializable classes should provide a serialVersionUID field. @@ -2339,7 +2337,7 @@ public class Foo implements java.io.Serializable { language="java" since="3.0" message="Class cannot be instantiated and does not provide any static methods or fields" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#missingstaticmethodinnoninstantiatableclass"> A class that has private constructors and does not have any static methods or fields cannot be used. @@ -2415,7 +2413,7 @@ public class Foo { language="java" since="2.0" message="Class contains more than one logger." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#morethanonelogger"> Normally only one logger is used in each class. This rule supports slf4j, log4j, Java Util Logging and @@ -2423,7 +2421,6 @@ log4j2 (since 6.19.0). 2 - A non-case label (e.g. a named break/continue label) was present in a switch statement. @@ -2531,7 +2528,7 @@ class Buzz implements java.io.Serializable { language="java" since="1.5" message="Non-static initializers are confusing" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#nonstaticinitializer"> A non-static initializer block will be called any time a constructor is invoked (just prior to @@ -2540,7 +2537,6 @@ confusing. 3 - A logger should normally be defined private static final and be associated with the correct class. @@ -2703,7 +2699,7 @@ public class Foo { @@ -2715,7 +2711,6 @@ See Effective Java, 3rd Edition, Item 54: Return empty collections or arrays ins 1 - Avoid returning from a finally block, this can discard exceptions. @@ -2785,7 +2780,7 @@ public class Bar { language="java" since="2.0" message="When instantiating a SimpleDateFormat object, specify a Locale" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#simpledateformatneedslocale"> Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate @@ -2876,7 +2871,7 @@ class Singleton { language="java" since="4.1" message="EJB's shouldn't have non-final static fields" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#staticejbfieldshouldbefinal"> According to the J2EE specification, an EJB should not have any static fields @@ -2918,7 +2913,7 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { language="java" since="3.9" message="Do not instantiate a StringBuffer or StringBuilder with a char" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#stringbufferinstantiationwithchar"> Individual character values provided as initialization arguments will be converted into integers. @@ -2967,7 +2962,7 @@ StringBuilder sb4 = new StringBuilder("c"); language="java" since="2.0" message="The method name and parameter number are suspiciously close to equals(Object)" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#suspiciousequalsmethodname"> The method name and parameter number are suspiciously close to `Object.equals`, which can denote an @@ -3022,7 +3017,7 @@ public class Foo { language="java" since="1.5" message="The method name and return type are suspiciously close to hashCode()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#suspicioushashcodemethodname"> The method name and return type are suspiciously close to hashCode(), which may denote an intention @@ -3115,7 +3110,7 @@ public class CarTest { language="java" since="1.5" message="Do not use 'if' statements that are always true or always false" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unconditionalifstatement"> Do not use "if" statements whose conditionals are always true or always false. @@ -3147,7 +3142,7 @@ public class Foo { language="java" since="3.0" message="assertTrue(true) or similar statements are unnecessary" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unnecessarybooleanassertion"> A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing. @@ -3215,7 +3210,7 @@ boolean answer2 = buz.toUpperCase().equalsIgnoreCase("BAZ"); // another unnec language="java" since="0.1" message="Avoid unnecessary temporaries when converting primitives to Strings" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unnecessaryconversiontemporary"> Avoid the use temporary objects when converting primitives to Strings. Use the static conversion methods @@ -3256,7 +3251,7 @@ public String convert(int x) { language="java" since="3.5" message="Invoke equals() on the object you''ve already ensured is not null" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unusednullcheckinequals"> After checking an object reference for null, you should invoke equals() on that object rather than passing @@ -3321,7 +3316,7 @@ public class Test { language="java" since="3.2" message="Use the correct logging statement for logging exceptions" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#usecorrectexceptionlogging"> To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable. @@ -3361,7 +3356,7 @@ public class Main { language="java" since="4.1" message="Use equals() to compare strings instead of ''=='' or ''!=''" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useequalstocomparestrings"> Using '==' or '!=' to compare strings is only reliable if the interned string (`String#intern()`) @@ -3424,7 +3419,7 @@ class Test { language="java" since="2.0" message="When doing a String.toLowerCase()/toUpperCase() call, use a Locale" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#uselocalewithcaseconversions"> When doing `String::toLowerCase()/toUpperCase()` conversions, use an explicit locale argument to specify the case @@ -3478,7 +3473,7 @@ String z2 = a.toLowerCase(Locale.getDefault()); language="java" since="3.7" message="In J2EE, getClassLoader() might not work as expected. Use Thread.currentThread().getContextClassLoader() instead." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useproperclassloader"> In J2EE, the getClassLoader() method might not work as expected. Use diff --git a/pmd-java/src/main/resources/category/java/multithreading.xml b/pmd-java/src/main/resources/category/java/multithreading.xml index 405d884406..88750e9ab0 100644 --- a/pmd-java/src/main/resources/category/java/multithreading.xml +++ b/pmd-java/src/main/resources/category/java/multithreading.xml @@ -13,7 +13,7 @@ Rules that flag issues when dealing with multiple threads of execution. language="java" since="3.0" message="Use block level rather than method level synchronization" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#avoidsynchronizedatmethodlevel"> Method-level synchronization can cause problems when new code is added to the method. @@ -76,7 +76,7 @@ public class Foo { language="java" since="3.6" message="Avoid using java.lang.ThreadGroup; it is not thread safe" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#avoidthreadgroup"> Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment @@ -110,7 +110,7 @@ public class Bar { @@ -137,7 +137,7 @@ public class ThrDeux { @@ -209,7 +209,7 @@ public class UsingExecutors { language="java" since="4.3" message="Don't call Thread.run() explicitly, use Thread.start()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#dontcallthreadrun"> Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, call Thread.start() for the intended behavior. @@ -339,7 +339,7 @@ public class Foo { minimumLanguageVersion="1.5" since="4.2.6" message="If you run in Java5 or newer and have concurrent access, you should use the ConcurrentHashMap implementation" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#useconcurrenthashmap"> Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can @@ -374,7 +374,7 @@ public class ConcurrentApp { language="java" since="3.0" message="Call Thread.notifyAll() rather than Thread.notify()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_multithreading.html#usenotifyallinsteadofnotify"> Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 8d8aca244b..e8a4cfcb80 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -53,7 +53,7 @@ sb.append('a'); // use this instead language="java" since="3.5" message="Arrays.copyOf or System.arraycopy are more efficient" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidarrayloops"> Instead of manually copying data between two arrays, use the more efficient `Arrays.copyOf` @@ -157,7 +157,7 @@ class Scratch { since="6.25.0" language="java" message="A Calendar is used to get the current time, this is expensive." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" typeResolution="true" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidcalendardatecreation"> @@ -231,7 +231,7 @@ public class DateStuff { message="Avoid instantiating FileInputStream, FileOutputStream, FileReader, or FileWriter" language="java" minimumLanguageVersion="1.7" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#avoidfilestream"> The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbage @@ -487,7 +487,7 @@ good.append("This is a long string, which is pre-sized"); since="1.8" minimumLanguageVersion="1.6" message="This call to Collection.toArray() may be optimizable" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#optimizabletoarraycall"> Calls to a collection's `toArray(E[])` method should specify a target array of zero size. This allows the JVM @@ -584,7 +584,7 @@ private String bar = new String("bar"); // just do a String bar = "bar"; language="java" since="1.0" message="Avoid calling toString() on String objects; this is unnecessary." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#stringtostring"> Avoid calling toString() on objects already known to be string instances; this is unnecessary. @@ -610,7 +610,7 @@ private String baz() { @@ -651,7 +651,7 @@ public class Foo { language="java" since="3.0" message="Use ArrayList instead of Vector" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#usearraylistinsteadofvector"> ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required. @@ -683,7 +683,7 @@ public class SimpleTest extends TestCase { language="java" since="3.5" message="Use asList instead of tight loops" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#usearraysaslist"> @@ -786,7 +786,6 @@ and buffering. 3 - Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") 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 9468660883..6f3c838dec 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 @@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.java.JavaParsingHelper; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.rule.Rule; -import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; import net.sourceforge.pmd.lang.rule.xpath.internal.DeprecatedAttrLogger; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java index c880098785..d59517e7c3 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java @@ -19,9 +19,9 @@ import net.sourceforge.pmd.lang.ast.test.TestUtilsKt; import net.sourceforge.pmd.lang.java.BaseParserTest; import net.sourceforge.pmd.lang.java.JavaLanguageModule; import net.sourceforge.pmd.lang.rule.Rule; -import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException; import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException.Phase; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.reporting.Report; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml index bf5fdf9c0c..78e2212101 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml @@ -12,14 +12,13 @@ The Basic ruleset contains a collection of good practices which should be follow language="java" since="1.0" message="Avoid modifying an outer loop incrementer in an inner loop for update expression" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/rules/java/basic.html#JumbledIncrementer"> Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. 3 - Avoid using with - it's bad news 1 @@ -72,7 +72,7 @@ function bar() { message="Avoid using global variables" language="ecmascript" since="5.0" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_bestpractices.html#globalvariable"> This rule helps to avoid using accidently global variables by simply missing the "var" declaration. @@ -105,7 +105,7 @@ function(arg) { language="ecmascript" since="5.0" message="The for-in loop variable ''{0}'' should be explicitly scoped with 'var' to avoid pollution." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_bestpractices.html#scopeforinvariable"> A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the 'var' keyword can @@ -161,7 +161,7 @@ function bar() { message="Always provide a base when using parseInt() functions" language="ecmascript" since="5.0.1" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_bestpractices.html#usebasewithparseint"> This rule checks for usages of parseInt. While the second parameter is optional and usually defaults diff --git a/pmd-javascript/src/main/resources/category/ecmascript/codestyle.xml b/pmd-javascript/src/main/resources/category/ecmascript/codestyle.xml index 42bdcb2d57..82b38cbf08 100644 --- a/pmd-javascript/src/main/resources/category/ecmascript/codestyle.xml +++ b/pmd-javascript/src/main/resources/category/ecmascript/codestyle.xml @@ -14,7 +14,7 @@ Rules which enforce a specific coding style. language="ecmascript" since="5.0" message="Avoid assignments in operands" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#assignmentinoperand"> Avoid assignments in operands; this can make code more complicated and harder to read. This is sometime @@ -65,7 +65,7 @@ function getX() { language="ecmascript" since="5.0" message="Avoid using 'for' statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#forloopsmustusebraces"> Avoid using 'for' statements without using curly braces. @@ -100,7 +100,7 @@ for (var i = 0; i < 42; i++) language="ecmascript" since="5.0" message="Avoid using 'if...else' statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#ifelsestmtsmustusebraces"> Avoid using if..else statements without using curly braces. @@ -139,7 +139,7 @@ else language="ecmascript" since="5.0" message="Avoid using if statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#ifstmtsmustusebraces"> Avoid using if statements without using curly braces. @@ -172,7 +172,7 @@ if (foo) language="ecmascript" since="5.5.0" message="The else block is unnecessary" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#noelsereturn"> The else block in a if-else-construct is unnecessary if the `if` block contains a return. @@ -212,7 +212,7 @@ return z; language="ecmascript" since="5.0" message="Unnecessary block." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#unnecessaryblock"> An unnecessary Block is present. Such Blocks are often used in other languages to @@ -251,7 +251,7 @@ if (bar) { language="ecmascript" since="5.0" message="Unnecessary parentheses." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#unnecessaryparentheses"> Unnecessary parentheses should be removed. 4 @@ -277,7 +277,7 @@ var z = ((1 + 1)); // Bad language="ecmascript" since="5.0" message="A ''return'', ''break'', ''continue'', or ''throw'' statement should be the last in a block." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#unreachablecode"> A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements after these @@ -319,7 +319,7 @@ function bar() { language="ecmascript" since="5.0" message="Avoid using 'while' statements without curly braces" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#whileloopsmustusebraces"> Avoid using 'while' statements without using curly braces. diff --git a/pmd-javascript/src/main/resources/category/ecmascript/errorprone.xml b/pmd-javascript/src/main/resources/category/ecmascript/errorprone.xml index 4a8132e859..efe71468b7 100644 --- a/pmd-javascript/src/main/resources/category/ecmascript/errorprone.xml +++ b/pmd-javascript/src/main/resources/category/ecmascript/errorprone.xml @@ -13,7 +13,7 @@ Rules to detect constructs that are either broken, extremely confusing or prone message="Avoid trailing commas in object or array literals" language="ecmascript" since="5.1" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_errorprone.html#avoidtrailingcomma"> This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals. @@ -49,7 +49,7 @@ function(arg) { language="ecmascript" since="5.0" message="Use '==='/'!==' to compare with true/false or Numbers" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_errorprone.html#equalcomparison"> Using == in condition may lead to unexpected results, as the variables are automatically casted to be of the @@ -95,7 +95,7 @@ if (someVar != 3) { language="ecmascript" since="5.0" message="The numeric literal ''{0}'' will have at different value at runtime." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_errorprone.html#innaccuratenumericliteral"> The numeric literal will have a different value at runtime, which can happen if you provide too much diff --git a/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml b/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml index 986833ca55..bac992c27f 100644 --- a/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml +++ b/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml @@ -13,7 +13,7 @@ Rules which enforce generally accepted best practices. language="jsp" since="3.6" message="Do not nest JSF component custom actions inside a custom action that iterates over its body." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_bestpractices.html#dontnestjsfinjstliteration"> Do not nest JSF component custom actions inside a custom action that iterates over its body. @@ -47,7 +47,7 @@ Do not nest JSF component custom actions inside a custom action that iterates ov language="jsp" since="3.6" message="Do not use an attribute called 'class'." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_bestpractices.html#noclassattribute"> Do not use an attribute called 'class'. Use "styleclass" for CSS styles. @@ -75,7 +75,7 @@ Do not use an attribute called 'class'. Use "styleclass" for CSS styles. language="jsp" since="3.6" message="Use JSP comments instead of HTML comments" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_bestpractices.html#nohtmlcomments"> In a production system, HTML comments increase the payload @@ -109,7 +109,7 @@ little other purpose. Consider switching to JSP comments. language="jsp" since="3.6" message="Do not do a forward from within a JSP file." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_bestpractices.html#nojspforward"> Do not do a forward from within a JSP file. diff --git a/pmd-jsp/src/main/resources/category/jsp/design.xml b/pmd-jsp/src/main/resources/category/jsp/design.xml index 5082a0f959..f8d9fe1565 100644 --- a/pmd-jsp/src/main/resources/category/jsp/design.xml +++ b/pmd-jsp/src/main/resources/category/jsp/design.xml @@ -12,7 +12,7 @@ Rules that help you discover design issues. @@ -53,7 +53,7 @@ tags, or attributes like "align='center'". language="jsp" since="3.6" message="Avoid having long scripts (e.g. Javascript) inside a JSP file." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_design.html#nolongscripts"> Scripts should be part of Tag Libraries, rather than part of JSP pages. @@ -99,7 +99,7 @@ onload=calcDays; language="jsp" since="3.6" message="Avoid having scriptlets inside a JSP file." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_design.html#noscriptlets"> Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages. diff --git a/pmd-jsp/src/main/resources/category/jsp/errorprone.xml b/pmd-jsp/src/main/resources/category/jsp/errorprone.xml index b254f17769..c87d432562 100644 --- a/pmd-jsp/src/main/resources/category/jsp/errorprone.xml +++ b/pmd-jsp/src/main/resources/category/jsp/errorprone.xml @@ -12,7 +12,7 @@ Rules to detect constructs that are either broken, extremely confusing or prone diff --git a/pmd-jsp/src/main/resources/category/jsp/security.xml b/pmd-jsp/src/main/resources/category/jsp/security.xml index 4a29b0fba4..c335fe7f93 100644 --- a/pmd-jsp/src/main/resources/category/jsp/security.xml +++ b/pmd-jsp/src/main/resources/category/jsp/security.xml @@ -13,7 +13,7 @@ Rules that flag potential security flaws. language="jsp" since="3.6" message="IFrames must have a src attribute." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_jsp_security.html#iframemissingsrcattribute"> IFrames which are missing a src element can cause security information popups in IE if you are accessing the page diff --git a/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/rule/xpath/internal/BaseKotlinXPathFunction.java b/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/rule/xpath/internal/BaseKotlinXPathFunction.java index e74c632ec2..96459af335 100644 --- a/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/rule/xpath/internal/BaseKotlinXPathFunction.java +++ b/pmd-kotlin/src/main/java/net/sourceforge/pmd/lang/kotlin/rule/xpath/internal/BaseKotlinXPathFunction.java @@ -5,9 +5,9 @@ package net.sourceforge.pmd.lang.kotlin.rule.xpath.internal; import net.sourceforge.pmd.lang.kotlin.KotlinLanguageModule; -import net.sourceforge.pmd.lang.rule.xpath.impl.AbstractXPathFunctionDef; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; -abstract class BaseKotlinXPathFunction extends AbstractXPathFunctionDef { +abstract class BaseKotlinXPathFunction extends XPathFunctionDefinition { protected BaseKotlinXPathFunction(String localName) { super(localName, KotlinLanguageModule.getInstance()); diff --git a/pmd-kotlin/src/main/resources/category/kotlin/bestpractices.xml b/pmd-kotlin/src/main/resources/category/kotlin/bestpractices.xml index a28c34e39a..2ee1dd66ab 100644 --- a/pmd-kotlin/src/main/resources/category/kotlin/bestpractices.xml +++ b/pmd-kotlin/src/main/resources/category/kotlin/bestpractices.xml @@ -13,14 +13,13 @@ Rules which enforce generally accepted best practices. since="7.0.0" language="kotlin" message="Function names should have non-cryptic and clear names." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_kotlin_bestpractices.html#functionnametooshort"> Function names should be easy to understand and describe the intention. Makes developers happy. 3 - + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> Having a class starting with some name and some *different* name in its end clause is an error. diff --git a/pmd-plsql/src/main/resources/category/plsql/bestpractices.xml b/pmd-plsql/src/main/resources/category/plsql/bestpractices.xml index 1af8bcde7b..d859856eac 100644 --- a/pmd-plsql/src/main/resources/category/plsql/bestpractices.xml +++ b/pmd-plsql/src/main/resources/category/plsql/bestpractices.xml @@ -14,7 +14,7 @@ Rules which enforce generally accepted best practices. language="plsql" since="5.1" message="WHEN OTHERS THEN NULL - when you do this, Tom Kyte cries" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_plsql_bestpractices.html#tomkytesdespair"> "WHEN OTHERS THEN NULL" hides all errors - (Re)RAISE an exception or call RAISE_APPLICATION_ERROR diff --git a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml index 113f0c71e7..386f4cdf4f 100644 --- a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml +++ b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml @@ -96,7 +96,7 @@ END; language="plsql" since="5.5.2" message="Pragma should be used only inside the declaration block before 'BEGIN'." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_plsql_codestyle.html#misplacedpragma"> Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block, @@ -139,7 +139,7 @@ end inline_pragma_error; language="plsql" since="6.7.0" message="Use meaningful names for loop variables" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_plsql_codestyle.html#forloopnaming"> In case you have loops please name the loop variables more meaningful. diff --git a/pmd-plsql/src/main/resources/category/plsql/design.xml b/pmd-plsql/src/main/resources/category/plsql/design.xml index 2e27b89f79..f11ccc7fbf 100644 --- a/pmd-plsql/src/main/resources/category/plsql/design.xml +++ b/pmd-plsql/src/main/resources/category/plsql/design.xml @@ -489,7 +489,7 @@ END pkg_too_many_fields; diff --git a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml index 72f00e6bb8..af87467a67 100644 --- a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml +++ b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml @@ -13,7 +13,7 @@ Rules to detect constructs that are either broken, extremely confusing or prone language="plsql" since="5.1" message="TO_DATE(TO_CHAR(variable)) instead of TRUNC(variable)" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_plsql_errorprone.html#to_date_to_char"> TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-variable) @@ -53,7 +53,7 @@ END date_utilities; language="plsql" since="5.1" message="TO_DATE without date format" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_plsql_errorprone.html#to_datewithoutdateformat"> TO_DATE without date format- use TO_DATE(expression, date-format) @@ -104,7 +104,7 @@ END date_utilities; diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLXPathRuleTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLXPathRuleTest.java index 5919fa8e55..a4536102ff 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLXPathRuleTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/PLSQLXPathRuleTest.java @@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.reporting.Report; diff --git a/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/rule/XPathRuleTest.java b/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/rule/XPathRuleTest.java index a1faaa0969..f5b978b9ef 100644 --- a/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/rule/XPathRuleTest.java +++ b/pmd-scala-modules/pmd-scala-common/src/test/java/net/sourceforge/pmd/lang/scala/rule/XPathRuleTest.java @@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.scala.ast.BaseScalaTest; import net.sourceforge.pmd.reporting.Report; import net.sourceforge.pmd.reporting.RuleViolation; diff --git a/pmd-swift/src/main/resources/category/swift/bestpractices.xml b/pmd-swift/src/main/resources/category/swift/bestpractices.xml index e1d9ad423e..b34f346cbe 100644 --- a/pmd-swift/src/main/resources/category/swift/bestpractices.xml +++ b/pmd-swift/src/main/resources/category/swift/bestpractices.xml @@ -13,7 +13,7 @@ Rules which enforce generally accepted best practices. since="7.0.0" language="swift" message="Creating views using Interface Builder should be avoided." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_swift_bestpractices.html#prohibitedinterfacebuilder"> Creating views using Interface Builder should be avoided. diff --git a/pmd-swift/src/main/resources/category/swift/errorprone.xml b/pmd-swift/src/main/resources/category/swift/errorprone.xml index 7bf277656b..b771ba9838 100644 --- a/pmd-swift/src/main/resources/category/swift/errorprone.xml +++ b/pmd-swift/src/main/resources/category/swift/errorprone.xml @@ -13,7 +13,7 @@ language="swift" since="7.0.0" message="Force casts should be avoided." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_swift_errorprone.html#forcecast"> Force casts should be avoided. This may lead to a crash if it's not used carefully. @@ -43,7 +43,7 @@ NSNumber() as? Int // no violation language="swift" since="7.0.0" message="Force tries should be avoided." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_swift_errorprone.html#forcetry"> Force tries should be avoided. If the code being wrapped happens to raise and exception, our application will crash. diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleSetFactoryTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleSetFactoryTest.java index 5cf75dbf3e..68a379c719 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleSetFactoryTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRuleSetFactoryTest.java @@ -45,6 +45,7 @@ import org.xml.sax.helpers.DefaultHandler; import net.sourceforge.pmd.internal.util.IOUtil; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.util.log.internal.MessageReporterBase; diff --git a/pmd-test/src/main/resources/rulesets/dummy/basic.xml b/pmd-test/src/main/resources/rulesets/dummy/basic.xml index ba7589bf21..95c5a8a97e 100644 --- a/pmd-test/src/main/resources/rulesets/dummy/basic.xml +++ b/pmd-test/src/main/resources/rulesets/dummy/basic.xml @@ -20,13 +20,12 @@ Just for test - Test 3 - Avoid inline styles. Use css classes instead. diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index aac7c7d0ca..d6e5b82829 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -9,7 +9,7 @@ import java.util.Objects; import net.sourceforge.pmd.lang.LanguageProcessor; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.AbstractRule; -import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathRule; import net.sourceforge.pmd.lang.xml.ast.internal.XmlParserImpl.RootXmlNode; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -128,8 +128,6 @@ public class DomXPathRule extends AbstractRule { public DomXPathRule() { definePropertyDescriptor(XPATH_EXPR); definePropertyDescriptor(DEFAULT_NS_URI); - // for compatibility, but is ignored. - definePropertyDescriptor(XPathRule.VERSION_DESCRIPTOR); } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java index 74f70fa3a3..68771d2381 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -16,8 +16,10 @@ import org.apache.commons.lang3.exception.ContextedRuntimeException; import org.w3c.dom.Document; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; import net.sourceforge.pmd.lang.rule.xpath.internal.DomainConversion; +import net.sourceforge.pmd.lang.rule.xpath.internal.SaxonExtensionFunctionDefinitionAdapter; import net.sourceforge.pmd.lang.xml.ast.XmlNode; import net.sourceforge.pmd.lang.xml.ast.internal.XmlParserImpl.RootXmlNode; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -78,7 +80,8 @@ final class SaxonDomXPathQuery { - for (ExtensionFunctionDefinition fun : xpathHandler.getRegisteredExtensionFunctions()) { + for (XPathFunctionDefinition xpathFun : xpathHandler.getRegisteredExtensionFunctions()) { + ExtensionFunctionDefinition fun = new SaxonExtensionFunctionDefinitionAdapter(xpathFun); StructuredQName qname = fun.getFunctionQName(); xpathStaticContext.declareNamespace(qname.getPrefix(), qname.getURI()); this.configuration.registerExtensionFunction(fun); diff --git a/pmd-xml/src/main/resources/category/pom/errorprone.xml b/pmd-xml/src/main/resources/category/pom/errorprone.xml index 6e09df3d62..a9c5fb113e 100644 --- a/pmd-xml/src/main/resources/category/pom/errorprone.xml +++ b/pmd-xml/src/main/resources/category/pom/errorprone.xml @@ -13,7 +13,7 @@ Rules to detect constructs that are either broken, extremely confusing or prone language="pom" since="5.4" message="By default, Maven only recognizes the following types: pom, jar, maven-plugin, ejb, war, ear, rar, par." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_pom_errorprone.html#invaliddependencytypes"> If you use an invalid dependency type in the dependency management section, Maven doesn't fail. Instead, @@ -59,7 +59,7 @@ The following types are considered valid: pom, jar, maven-plugin, ejb, war, ear, language="pom" since="5.4" message="Do not use project.version to express a dependency version." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_pom_errorprone.html#projectversionasdependencyversion"> Using that expression in dependency declarations seems like a shortcut, but it can go wrong. diff --git a/pmd-xml/src/main/resources/category/xml/bestpractices.xml b/pmd-xml/src/main/resources/category/xml/bestpractices.xml index dd25bea6e8..f8147217f1 100644 --- a/pmd-xml/src/main/resources/category/xml/bestpractices.xml +++ b/pmd-xml/src/main/resources/category/xml/bestpractices.xml @@ -13,7 +13,7 @@ Rules which enforce generally accepted best practices. language="xml" since="7.0.0" message="Set an explicit XML encoding in the XML declaration to ensure proper parsing" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_xml_bestpractices.html#missingencoding"> When the character encoding is missing from the XML declaration, @@ -27,7 +27,6 @@ parsing. 3 - An XML CDATA section begins with a <![CDATA[ marker, which has only one [, and ends with a ]]> marker, which has two ]. diff --git a/pmd-xml/src/main/resources/category/xsl/codestyle.xml b/pmd-xml/src/main/resources/category/xsl/codestyle.xml index 6363dfbf23..d6d09bc5b0 100644 --- a/pmd-xml/src/main/resources/category/xsl/codestyle.xml +++ b/pmd-xml/src/main/resources/category/xsl/codestyle.xml @@ -13,7 +13,7 @@ Rules which enforce a specific coding style. language="xsl" since="5.0" message="The xpath concat() function accepts as many arguments as required, you may be able to factorize this expression" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_xsl_codestyle.html#useconcatonce"> The XPath concat() functions accepts as many arguments as required so you can have diff --git a/pmd-xml/src/main/resources/category/xsl/performance.xml b/pmd-xml/src/main/resources/category/xsl/performance.xml index 0e5201d43d..223b7f8de5 100644 --- a/pmd-xml/src/main/resources/category/xsl/performance.xml +++ b/pmd-xml/src/main/resources/category/xsl/performance.xml @@ -13,7 +13,7 @@ Rules that flag suboptimal code. language="xsl" since="5.0" message="Axis navigation has the largest impact when writing an XPath query." - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_xsl_performance.html#avoidaxisnavigation"> Avoid using the 'following' or 'preceding' axes whenever possible, as these can cut