From eb6b4142b82de67ced2ea1e0d10e2d4f77f99aa0 Mon Sep 17 00:00:00 2001 From: Oleksii Dykov Date: Sun, 23 Jan 2022 00:43:18 +0200 Subject: [PATCH 1/3] New template rule: AvoidProhibitedMethodInvocation --- pom.xml | 2 +- .../pmd/AvoidProhibitedMethodInvocation.java | 148 ++++++++++++++++++ .../arch4u/pmd/arch4u-template-ruleset.xml | 32 +++- .../AvoidProhibitedMethodInvocationTest.java | 44 ++++++ .../xml/AvoidProhibitedMethodInvocation.xml | 106 +++++++++++++ 5 files changed, 330 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java create mode 100644 src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java create mode 100644 src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodInvocation.xml diff --git a/pom.xml b/pom.xml index ac7752d..af5bb70 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ arch4u-pmd - 0.3.0 + 0.4.0 jar ${project.artifactId} diff --git a/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java b/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java new file mode 100644 index 0000000..6a01626 --- /dev/null +++ b/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java @@ -0,0 +1,148 @@ +/* + * MIT License + * + * Copyright (c) 2019-2022 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.arch4u.pmd; + +import java.util.List; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.rule.AbstractPoorMethodCall; +import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence; +import net.sourceforge.pmd.lang.java.xpath.TypeIsExactlyFunction; +import net.sourceforge.pmd.lang.java.xpath.TypeIsFunction; +import net.sourceforge.pmd.lang.symboltable.NameOccurrence; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; +import org.apache.commons.lang3.StringUtils; + +/** + * A rule that prohibits the using methods of a particular class. + * + * @see + * https://github.com/dgroup/arch4u-pmd/issues/22 + * @since 0.4.0 + */ +@SuppressWarnings("PMD.StaticAccessToStaticFields") +public final class AvoidProhibitedMethodInvocation extends AbstractPoorMethodCall { + + /** + * Property descriptor with test class suffix. + */ + private static final PropertyDescriptor CLASS = + PropertyFactory.stringProperty("class") + .desc("The fully qualified name of the class") + .defaultValue(StringUtils.EMPTY) + .build(); + + /** + * Property descriptor with the list of the prohibited methods. + */ + private static final PropertyDescriptor> METHODS = + PropertyFactory.stringListProperty("methods") + .desc("List of prohibited methods") + .emptyDefaultValue() + .build(); + + /** + * A property descriptor with the property that is responsible for + * whether subtypes should be checked. + */ + private static final PropertyDescriptor CHECK_SUBTYPES = + PropertyFactory.booleanProperty("checkSubtypes") + .desc("The property matches whether the subtypes should be checked") + .defaultValue(false) + .build(); + + /** + * Constructor for defining property descriptor. + */ + @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") + public AvoidProhibitedMethodInvocation() { + this.definePropertyDescriptor(CLASS); + this.definePropertyDescriptor(METHODS); + this.definePropertyDescriptor(CHECK_SUBTYPES); + } + + @Override + public Object visit(final ASTVariableDeclaratorId node, final Object data) { + if (node.getNameDeclaration() != null && this.hasNotedClass(node)) { + for (final NameOccurrence usage : node.getUsages()) { + final JavaNameOccurrence occurrence = (JavaNameOccurrence) usage; + if (this.isNotedMethod(occurrence.getNameForWhichThisIsAQualifier())) { + this.addViolation( + data, occurrence.getLocation(), new String[]{ + this.targetTypename(), + occurrence.getNameForWhichThisIsAQualifier().getImage(), + } + ); + } + } + } + return data; + } + + @Override + public String targetTypename() { + return this.getProperty(CLASS); + } + + @Override + public String[] methodNames() { + return this.getProperty(METHODS).toArray(new String[0]); + } + + @Override + public boolean isViolationArgument(final Node node) { + throw new UnsupportedOperationException(); + } + + /** + * Checks if the class of the variable is specified in the rule properties. + * @param node Variable declarator node. + * @return True if the node class is specified. + */ + private boolean hasNotedClass(final ASTVariableDeclaratorId node) { + final boolean noted; + if (this.getProperty(CHECK_SUBTYPES)) { + noted = TypeIsFunction.typeIs(node.getTypeNode(), this.targetTypename()); + } else { + noted = TypeIsExactlyFunction.typeIsExactly(node.getTypeNode(), this.targetTypename()); + } + return noted; + } + + /** + * Checks if the variable occurrence contains prohibited method. + * @param occurrence Variable occurrence. + * @return True if the occurrence contains prohibited method. + */ + private boolean isNotedMethod(final NameOccurrence occurrence) { + boolean noted = false; + if (occurrence != null) { + final String invocation = occurrence.getImage(); + noted = this.getProperty(METHODS).contains(invocation); + } + return noted; + } +} diff --git a/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml b/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml index 8184fae..74da8aa 100644 --- a/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml +++ b/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml @@ -15,7 +15,8 @@ class="net.sourceforge.pmd.lang.rule.XPathRule"> Avoid to use prohibited classes. - See discussion about tips/tricks implementation on Github: https://github.com/pmd/pmd/discussions/3705 + See discussion about tips/tricks implementation on Github: + https://github.com/pmd/pmd/discussions/3705 3 @@ -77,4 +78,33 @@ ]]> + + + + Avoid to use prohibited method invocation. + See discussion about tips/tricks implementation on Github: + https://github.com/pmd/pmd/discussions/TBD + + 3 + + + + + + + + + diff --git a/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java b/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java new file mode 100644 index 0000000..0dfff1e --- /dev/null +++ b/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (c) 2019-2022 Yurii Dubinka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package io.github.dgroup.arch4u.pmd; + +import net.sourceforge.pmd.testframework.SimpleAggregatorTst; + +/** + * Test case for {@link AvoidProhibitedMethodInvocation} rule. + * + * @since 0.4.0 + */ +@SuppressWarnings({"PMD.TestClassWithoutTestCases", "PMD.JUnit4TestShouldUseBeforeAnnotation"}) +public final class AvoidProhibitedMethodInvocationTest extends SimpleAggregatorTst { + + @Override + public void setUp() { + addRule( + "io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml", + "AvoidProhibitedMethodInvocation" + ); + } +} diff --git a/src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodInvocation.xml b/src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodInvocation.xml new file mode 100644 index 0000000..ffcf788 --- /dev/null +++ b/src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodInvocation.xml @@ -0,0 +1,106 @@ + + + + + + + [BAD]: prohibited method invocation + java.lang.Object + toString + false + 1 + 3 + + The java.lang.Object#toString invocation is prohibited to use. + + + + + + [BAD]: prohibited method invocation, check subtypes + java.lang.Object + toString + true + 1 + 3 + + The java.lang.Object#toString invocation is prohibited to use. + + + + + + [BAD]: prohibited method invocation on field + java.lang.Object + toString + true + 1 + 6 + + + + + [OK]: prohibited method invocation on unchecked subclass instance + java.lang.Object + toString + false + 0 + + + + From e86190907207944af6e8671356e6a27163e47e5f Mon Sep 17 00:00:00 2001 From: Oleksii Dykov Date: Mon, 24 Jan 2022 21:27:00 +0200 Subject: [PATCH 2/3] Rename to AvoidProhibitedMethodsUsage --- pom.xml | 2 +- ...thodInvocation.java => AvoidProhibitedMethodsUsage.java} | 4 ++-- .../io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml | 4 ++-- ...cationTest.java => AvoidProhibitedMethodsUsageTest.java} | 6 +++--- ...MethodInvocation.xml => AvoidProhibitedMethodsUsage.xml} | 0 5 files changed, 8 insertions(+), 8 deletions(-) rename src/main/java/io/github/dgroup/arch4u/pmd/{AvoidProhibitedMethodInvocation.java => AvoidProhibitedMethodsUsage.java} (97%) rename src/test/java/io/github/dgroup/arch4u/pmd/{AvoidProhibitedMethodInvocationTest.java => AvoidProhibitedMethodsUsageTest.java} (88%) rename src/test/resources/io/github/dgroup/arch4u/pmd/xml/{AvoidProhibitedMethodInvocation.xml => AvoidProhibitedMethodsUsage.xml} (100%) diff --git a/pom.xml b/pom.xml index af5bb70..66e4abe 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ arch4u-pmd - 0.4.0 + 0.0.0 jar ${project.artifactId} diff --git a/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java b/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodsUsage.java similarity index 97% rename from src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java rename to src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodsUsage.java index 6a01626..9f95f8a 100644 --- a/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocation.java +++ b/src/main/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodsUsage.java @@ -44,7 +44,7 @@ * @since 0.4.0 */ @SuppressWarnings("PMD.StaticAccessToStaticFields") -public final class AvoidProhibitedMethodInvocation extends AbstractPoorMethodCall { +public final class AvoidProhibitedMethodsUsage extends AbstractPoorMethodCall { /** * Property descriptor with test class suffix. @@ -78,7 +78,7 @@ public final class AvoidProhibitedMethodInvocation extends AbstractPoorMethodCal * Constructor for defining property descriptor. */ @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") - public AvoidProhibitedMethodInvocation() { + public AvoidProhibitedMethodsUsage() { this.definePropertyDescriptor(CLASS); this.definePropertyDescriptor(METHODS); this.definePropertyDescriptor(CHECK_SUBTYPES); diff --git a/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml b/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml index 74da8aa..d60e18d 100644 --- a/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml +++ b/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml @@ -79,11 +79,11 @@ - + class="io.github.dgroup.arch4u.pmd.AvoidProhibitedMethodsUsage"> Avoid to use prohibited method invocation. See discussion about tips/tricks implementation on Github: diff --git a/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java b/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodsUsageTest.java similarity index 88% rename from src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java rename to src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodsUsageTest.java index 0dfff1e..c51ffdb 100644 --- a/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodInvocationTest.java +++ b/src/test/java/io/github/dgroup/arch4u/pmd/AvoidProhibitedMethodsUsageTest.java @@ -27,18 +27,18 @@ import net.sourceforge.pmd.testframework.SimpleAggregatorTst; /** - * Test case for {@link AvoidProhibitedMethodInvocation} rule. + * Test case for {@link AvoidProhibitedMethodsUsage} rule. * * @since 0.4.0 */ @SuppressWarnings({"PMD.TestClassWithoutTestCases", "PMD.JUnit4TestShouldUseBeforeAnnotation"}) -public final class AvoidProhibitedMethodInvocationTest extends SimpleAggregatorTst { +public final class AvoidProhibitedMethodsUsageTest extends SimpleAggregatorTst { @Override public void setUp() { addRule( "io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml", - "AvoidProhibitedMethodInvocation" + "AvoidProhibitedMethodsUsage" ); } } diff --git a/src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodInvocation.xml b/src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodsUsage.xml similarity index 100% rename from src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodInvocation.xml rename to src/test/resources/io/github/dgroup/arch4u/pmd/xml/AvoidProhibitedMethodsUsage.xml From d43689ee577570c2fb58eecc227feafa13302890 Mon Sep 17 00:00:00 2001 From: Oleksii Dykov Date: Mon, 24 Jan 2022 21:30:33 +0200 Subject: [PATCH 3/3] Update description in the ruleset --- .../io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml b/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml index d60e18d..b6d4452 100644 --- a/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml +++ b/src/main/resources/io/github/dgroup/arch4u/pmd/arch4u-template-ruleset.xml @@ -85,9 +85,8 @@ message="The {0}#{1} invocation is prohibited to use." class="io.github.dgroup.arch4u.pmd.AvoidProhibitedMethodsUsage"> - Avoid to use prohibited method invocation. - See discussion about tips/tricks implementation on Github: - https://github.com/pmd/pmd/discussions/TBD + Avoid using the prohibited method(s). + See the discussion about implementation tips/tricks on Github: https://github.com/dgroup/arch4u-pmd/discussions/40 3