From 7572a49d3506e298a885c268710da748fb6a16fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Thu, 24 May 2018 11:23:03 -0300 Subject: [PATCH] [java] Deprecate the old typeof function - Have new functions typeIs() and typeIsExactly() with simpler syntaxes - Nag about the deprecated usage of the old method - Replace all internal usages with the new one - Have the functions use the TypeHelper to avoid multiple separate implementations of the same behavior - Tidy up a little the TypeHelper --- .../pmd/lang/java/AbstractJavaHandler.java | 4 + .../ForLoopCanBeForeachRule.java | 2 +- .../performance/StringInstantiationRule.java | 2 +- .../rule/performance/StringToStringRule.java | 4 +- .../lang/java/typeresolution/TypeHelper.java | 77 ++++++++++++++++--- .../pmd/lang/java/xpath/JavaFunctions.java | 17 +++- .../java/xpath/TypeIsExactlyFunction.java | 54 +++++++++++++ .../pmd/lang/java/xpath/TypeIsFunction.java | 54 +++++++++++++ .../pmd/lang/java/xpath/TypeOfFunction.java | 19 ++++- .../resources/category/java/bestpractices.xml | 10 +-- .../main/resources/category/java/design.xml | 14 ++-- .../resources/category/java/documentation.xml | 2 +- .../resources/category/java/errorprone.xml | 18 ++--- .../category/java/multithreading.xml | 6 +- .../resources/category/java/performance.xml | 20 ++--- .../MultithreadingRulesTest.java | 5 ++ .../testdata/ArrayVariableDeclaration.java | 4 +- .../xml/UnusedFormalParameter.xml | 2 +- .../multithreading/xml/AvoidThreadGroup.xml | 3 +- .../fxdesigner/NodeInfoPanelController.java | 2 +- 20 files changed, 259 insertions(+), 60 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsExactlyFunction.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsFunction.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java index 70bcbb1ea5..68ad02f403 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java @@ -27,6 +27,8 @@ import net.sourceforge.pmd.lang.java.typeresolution.TypeResolutionFacade; import net.sourceforge.pmd.lang.java.xpath.GetCommentOnFunction; import net.sourceforge.pmd.lang.java.xpath.JavaFunctions; import net.sourceforge.pmd.lang.java.xpath.MetricFunction; +import net.sourceforge.pmd.lang.java.xpath.TypeIsExactlyFunction; +import net.sourceforge.pmd.lang.java.xpath.TypeIsFunction; import net.sourceforge.pmd.lang.java.xpath.TypeOfFunction; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; @@ -53,6 +55,8 @@ public abstract class AbstractJavaHandler extends AbstractLanguageVersionHandler TypeOfFunction.registerSelfInSimpleContext(); GetCommentOnFunction.registerSelfInSimpleContext(); MetricFunction.registerSelfInSimpleContext(); + TypeIsFunction.registerSelfInSimpleContext(); + TypeIsExactlyFunction.registerSelfInSimpleContext(); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java index 13306de827..3ce05ca9ac 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java @@ -63,7 +63,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { List occurrences = indexDecl.getValue(); VariableNameDeclaration index = indexDecl.getKey(); - if (TypeHelper.isA(index, Iterator.class)) { + if (TypeHelper.isExactlyAny(index, Iterator.class)) { Entry> iterableInfo = getIterableDeclOfIteratorLoop(index, node.getScope()); if (iterableInfo != null && isReplaceableIteratorLoop(indexDecl, guardCondition, iterableInfo, node)) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringInstantiationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringInstantiationRule.java index 2b0c5e3c62..8f17a26fca 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringInstantiationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringInstantiationRule.java @@ -50,7 +50,7 @@ public class StringInstantiationRule extends AbstractJavaRule { return data; } - if (nd instanceof TypedNameDeclaration && TypeHelper.isA((TypedNameDeclaration) nd, String.class)) { + if (nd instanceof TypedNameDeclaration && TypeHelper.isExactlyAny((TypedNameDeclaration) nd, String.class)) { addViolation(data, node); } return data; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringToStringRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringToStringRule.java index 1e739dccc3..4ea00326aa 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringToStringRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/StringToStringRule.java @@ -17,8 +17,8 @@ import net.sourceforge.pmd.lang.symboltable.ScopedNode; public class StringToStringRule extends AbstractJavaRule { public Object visit(ASTVariableDeclaratorId node, Object data) { - if (!TypeHelper.isA(node.getNameDeclaration(), String.class) - && !TypeHelper.isA(node.getNameDeclaration(), String[].class)) { + if (!TypeHelper.isExactlyAny(node.getNameDeclaration(), String.class) + && !TypeHelper.isExactlyAny(node.getNameDeclaration(), String[].class)) { return data; } boolean isArray = node.isArray(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/TypeHelper.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/TypeHelper.java index 640ba90ea8..f8b1e097f7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/TypeHelper.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/TypeHelper.java @@ -24,6 +24,34 @@ public final class TypeHelper { * @return true if type node n is of type clazzName or a subtype of clazzName */ public static boolean isA(final TypeNode n, final String clazzName) { + final Class clazz = loadClassWithNodeClassloader(n, clazzName); + + if (clazz != null) { + return isA(n, clazz); + } + + return clazzName.equals(n.getImage()) || clazzName.endsWith("." + n.getImage()); + } + + /** + * Checks whether the resolved type of the given {@link TypeNode} n is exactly of the type + * given by the clazzName. + * + * @param n the type node to check + * @param clazzName the class name to compare to + * @return true if type node n is exactly of type clazzName. + */ + public static boolean isExactlyA(final TypeNode n, final String clazzName) { + final Class clazz = loadClassWithNodeClassloader(n, clazzName); + + if (clazz != null) { + return n.getType() == clazz; + } + + return clazzName.equals(n.getImage()) || clazzName.endsWith("." + n.getImage()); + } + + private static Class loadClassWithNodeClassloader(final TypeNode n, final String clazzName) { if (n.getType() != null) { try { ClassLoader classLoader = n.getType().getClassLoader(); @@ -31,21 +59,20 @@ public final class TypeHelper { // Using the system classloader then classLoader = ClassLoader.getSystemClassLoader(); } - + // If the requested type is in the classpath, using the same classloader should work - final Class clazz = classLoader.loadClass(clazzName); - - if (clazz != null) { - return isA(n, clazz); - } + return classLoader.loadClass(clazzName); } catch (final ClassNotFoundException ignored) { // The requested type is not on the auxclasspath. This might happen, if the type node // is probed for a specific type (e.g. is is a JUnit5 Test Annotation class). // Failing to resolve clazzName does not necessarily indicate an incomplete auxclasspath. + } catch (final LinkageError expected) { + // We found the class but it's invalid / incomplete. This may be an incomplete auxclasspath + // if it was a NoClassDefFoundError. TODO : Report it? } } - - return clazzName.equals(n.getImage()) || clazzName.endsWith("." + n.getImage()); + + return null; } public static boolean isA(TypeNode n, Class clazz) { @@ -56,16 +83,42 @@ public final class TypeHelper { return subclasses(n, class1) || subclasses(n, class2); } - public static boolean isA(TypedNameDeclaration vnd, Class clazz) { + public static boolean isExactlyAny(TypedNameDeclaration vnd, Class... clazzes) { Class type = vnd.getType(); - return type != null && type.equals(clazz) || type == null - && (clazz.getSimpleName().equals(vnd.getTypeImage()) || clazz.getName().equals(vnd.getTypeImage())); + for (final Class clazz : clazzes) { + if (type != null && type.equals(clazz) || type == null + && (clazz.getSimpleName().equals(vnd.getTypeImage()) || clazz.getName().equals(vnd.getTypeImage()))) { + return true; + } + } + + return false; + } + + public static boolean isExactlyNone(TypedNameDeclaration vnd, Class... clazzes) { + return !isExactlyAny(vnd, clazzes); + } + + /** + * @deprecated use {@link #isExactlyAny(TypedNameDeclaration, Class...)} + */ + @Deprecated + public static boolean isA(TypedNameDeclaration vnd, Class clazz) { + return isExactlyAny(vnd, clazz); } + /** + * @deprecated use {@link #isExactlyAny(TypedNameDeclaration, Class...)} + */ + @Deprecated public static boolean isEither(TypedNameDeclaration vnd, Class class1, Class class2) { - return isA(vnd, class1) || isA(vnd, class2); + return isExactlyAny(vnd, class1, class2); } + /** + * @deprecated use {@link #isExactlyNone(TypedNameDeclaration, Class...)} + */ + @Deprecated public static boolean isNeither(TypedNameDeclaration vnd, Class class1, Class class2) { return !isA(vnd, class1) && !isA(vnd, class2); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/JavaFunctions.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/JavaFunctions.java index 20b20a21c1..35f43e830b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/JavaFunctions.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/JavaFunctions.java @@ -18,16 +18,27 @@ public final class JavaFunctions { // utility class } - public static boolean typeof(XPathContext context, String nodeTypeName, String fullTypeName) { + @Deprecated + public static boolean typeof(final XPathContext context, final String nodeTypeName, final String fullTypeName) { return typeof(context, nodeTypeName, fullTypeName, null); } - public static boolean typeof(XPathContext context, String nodeTypeName, String fullTypeName, String shortTypeName) { + @Deprecated + public static boolean typeof(final XPathContext context, final String nodeTypeName, + final String fullTypeName, final String shortTypeName) { return TypeOfFunction.typeof((Node) ((ElementNode) context.getContextItem()).getUnderlyingNode(), nodeTypeName, fullTypeName, shortTypeName); } - public static double metric(XPathContext context, String metricKeyName) { + public static double metric(final XPathContext context, final String metricKeyName) { return MetricFunction.getMetric((Node) ((ElementNode) context.getContextItem()).getUnderlyingNode(), metricKeyName); } + + public static boolean typeIs(final XPathContext context, final String fullTypeName) { + return TypeIsFunction.typeIs((Node) ((ElementNode) context.getContextItem()).getUnderlyingNode(), fullTypeName); + } + + public static boolean typeIsExactly(final XPathContext context, final String fullTypeName) { + return TypeIsExactlyFunction.typeIsExactly((Node) ((ElementNode) context.getContextItem()).getUnderlyingNode(), fullTypeName); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsExactlyFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsExactlyFunction.java new file mode 100644 index 0000000000..e6437fcce3 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsExactlyFunction.java @@ -0,0 +1,54 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.xpath; + +import java.util.List; + +import org.jaxen.Context; +import org.jaxen.Function; +import org.jaxen.FunctionCallException; +import org.jaxen.SimpleFunctionContext; +import org.jaxen.XPathFunctionContext; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.TypeNode; +import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; + +public class TypeIsExactlyFunction implements Function { + + public static void registerSelfInSimpleContext() { + ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "typeIsExactly", + new TypeIsExactlyFunction()); + } + + @Override + public Object call(final Context context, final List args) throws FunctionCallException { + if (args.size() != 1) { + throw new IllegalArgumentException( + "typeIsExactly function takes a single String argument with the fully qualified type name to check against."); + } + final String fullTypeName = (String) args.get(0); + final Node n = (Node) context.getNodeSet().get(0); + + return typeIsExactly(n, fullTypeName); + } + + /** + * Example XPath 1.0: {@code //ClassOrInterfaceType[typeIsExactly('java.lang.String')]} + *

+ * Example XPath 2.0: {@code //ClassOrInterfaceType[pmd-java:typeIsExactly('java.lang.String')]} + * + * @param n The node on which to check for types + * @param fullTypeName The fully qualified name of the class or any supertype + * @return True if the type of the node matches, false otherwise. + */ + public static boolean typeIsExactly(final Node n, final String fullTypeName) { + if (n instanceof TypeNode) { + return TypeHelper.isExactlyA((TypeNode) n, fullTypeName); + } else { + throw new IllegalArgumentException("typeIsExactly function may only be called on a TypeNode."); + } + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsFunction.java new file mode 100644 index 0000000000..0c5ecb3c3f --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeIsFunction.java @@ -0,0 +1,54 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.xpath; + +import java.util.List; + +import org.jaxen.Context; +import org.jaxen.Function; +import org.jaxen.FunctionCallException; +import org.jaxen.SimpleFunctionContext; +import org.jaxen.XPathFunctionContext; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.TypeNode; +import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper; + +public class TypeIsFunction implements Function { + + public static void registerSelfInSimpleContext() { + ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "typeIs", + new TypeIsFunction()); + } + + @Override + public Object call(final Context context, final List args) throws FunctionCallException { + if (args.size() != 1) { + throw new IllegalArgumentException( + "typeIs function takes a single String argument with the fully qualified type name to check against."); + } + final String fullTypeName = (String) args.get(0); + final Node n = (Node) context.getNodeSet().get(0); + + return typeIs(n, fullTypeName); + } + + /** + * Example XPath 1.0: {@code //ClassOrInterfaceType[typeIs('java.lang.String')]} + *

+ * Example XPath 2.0: {@code //ClassOrInterfaceType[pmd-java:typeIs('java.lang.String')]} + * + * @param n The node on which to check for types + * @param fullTypeName The fully qualified name of the class or any supertype + * @return True if the type of the node matches, false otherwise. + */ + public static boolean typeIs(final Node n, final String fullTypeName) { + if (n instanceof TypeNode) { + return TypeHelper.isA((TypeNode) n, fullTypeName); + } else { + throw new IllegalArgumentException("typeIs function may only be called on a TypeNode."); + } + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeOfFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeOfFunction.java index 52d6c25841..b313674ba5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeOfFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/TypeOfFunction.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.xpath; import java.util.Arrays; import java.util.List; +import java.util.logging.Logger; import org.jaxen.Context; import org.jaxen.Function; @@ -13,19 +14,25 @@ import org.jaxen.FunctionCallException; import org.jaxen.SimpleFunctionContext; import org.jaxen.XPathFunctionContext; +import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.xpath.Attribute; import net.sourceforge.pmd.lang.java.ast.TypeNode; +@Deprecated public class TypeOfFunction implements Function { + private static final Logger LOG = Logger.getLogger(TypeOfFunction.class.getName()); + private static boolean deprecationWarned = false; + public static void registerSelfInSimpleContext() { ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "typeof", new TypeOfFunction()); } public Object call(Context context, List args) throws FunctionCallException { - + nagDeprecatedFunction(); + String nodeTypeName = null; String fullTypeName = null; String shortTypeName = null; @@ -57,6 +64,14 @@ public class TypeOfFunction implements Function { return typeof(n, nodeTypeName, fullTypeName, shortTypeName); } + private static void nagDeprecatedFunction() { + if (!deprecationWarned) { + deprecationWarned = true; + LOG.warning("The XPath function typeof() is deprecated and will be removed in " + + PMDVersion.getNextMajorRelease() + ". Use typeIs() instead."); + } + } + /** * Example XPath 1.0: {@code //ClassOrInterfaceType[typeof(@Image, 'java.lang.String', 'String')]} *

@@ -69,6 +84,8 @@ public class TypeOfFunction implements Function { * @return */ public static boolean typeof(Node n, String nodeTypeName, String fullTypeName, String shortTypeName) { + nagDeprecatedFunction(); + if (n instanceof TypeNode) { Class type = ((TypeNode) n).getType(); if (type == null) { diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 551797d13e..1572dddbfe 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -536,10 +536,10 @@ In JUnit 4, only methods annotated with the @Test annotation are executed. @@ -1207,7 +1207,7 @@ This rule detects JUnit assertions in object equality. These assertions should b PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name [ends-with(@Image, '.equals')] ] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> @@ -1247,7 +1247,7 @@ more specific methods, like assertNull, assertNotNull. Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral ] ] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> @@ -1289,7 +1289,7 @@ by more specific methods, like assertSame, assertNotSame. [PrimarySuffix/Arguments /ArgumentList/Expression /EqualityExpression[count(.//NullLiteral) = 0]] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index a14cad558a..37f530ac04 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -29,7 +29,7 @@ protected constructor in order to prevent instantiation than make the class misl //ClassOrInterfaceDeclaration [@Abstract = 'true'] [count(//MethodDeclaration) + count(//ConstructorDeclaration) = 0] - [not(../Annotation/MarkerAnnotation/Name[typeof(@Image, 'com.google.auto.value.AutoValue', 'AutoValue')])] + [not(../Annotation/MarkerAnnotation/Name[typeIs('com.google.auto.value.AutoValue')])] ]]> @@ -267,13 +267,13 @@ Exception, or Error, use a subclassed exception or error instead. @@ -503,7 +503,7 @@ Errors are system exceptions. Do not extend them. @@ -1213,7 +1213,7 @@ PrimaryExpression/PrimarySuffix/Arguments/ArgumentList /Expression/UnaryExpressionNotPlusMinus[@Image='!'] /PrimaryExpression/PrimaryPrefix ] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> diff --git a/pmd-java/src/main/resources/category/java/documentation.xml b/pmd-java/src/main/resources/category/java/documentation.xml index 1af9383159..6e1d7e8e61 100644 --- a/pmd-java/src/main/resources/category/java/documentation.xml +++ b/pmd-java/src/main/resources/category/java/documentation.xml @@ -96,7 +96,7 @@ and unintentional empty constructors. diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index f701cc4fef..5c322a7351 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -707,9 +707,9 @@ public String bar(String string) { /Block[not( (BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image]))] [ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[ - typeof(@Image, 'android.app.Activity', 'Activity') or - typeof(@Image, 'android.app.Application', 'Application') or - typeof(@Image, 'android.app.Service', 'Service') + typeIs('android.app.Activity') or + typeIs('android.app.Application') or + typeIs('android.app.Service') ]]] ]]> @@ -752,9 +752,9 @@ Super should be called at the end of the method /Block/BlockStatement[last()] [not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])] [ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[ - typeof(@Image, 'android.app.Activity', 'Activity') or - typeof(@Image, 'android.app.Application', 'Application') or - typeof(@Image, 'android.app.Service', 'Service') + typeIs('android.app.Activity') or + typeIs('android.app.Application') or + typeIs('android.app.Service') ]]] ]]> @@ -2058,7 +2058,7 @@ Some JUnit framework methods are easy to misspell. or (not(@Image = 'tearDown') and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')] [FormalParameters[count(*) = 0]] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> @@ -2092,7 +2092,7 @@ The suite() method in a JUnit test needs to be both public and static. //MethodDeclaration[not(@Static='true') or not(@Public='true')] [MethodDeclarator/@Image='suite'] [MethodDeclarator/FormalParameters/@ParameterCount=0] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> @@ -3059,7 +3059,7 @@ or UnaryExpressionNotPlusMinus[@Image='!'] /PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]] ] -[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')] or //MarkerAnnotation/Name[pmd-java:typeIs('org.junit.Test')]]] ]]> diff --git a/pmd-java/src/main/resources/category/java/multithreading.xml b/pmd-java/src/main/resources/category/java/multithreading.xml index f6a2086ca1..fcede3d979 100644 --- a/pmd-java/src/main/resources/category/java/multithreading.xml +++ b/pmd-java/src/main/resources/category/java/multithreading.xml @@ -68,7 +68,7 @@ it contains methods that are not thread-safe. @@ -169,8 +169,8 @@ Explicitly calling Thread.run() method will execute in the caller's thread of co [ ./Name[ends-with(@Image, '.run') or @Image = 'run'] and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image - [../../../Type/ReferenceType/ClassOrInterfaceType[typeof(@Image, 'java.lang.Thread', 'Thread')]] - or (./AllocationExpression/ClassOrInterfaceType[typeof(@Image, 'java.lang.Thread', 'Thread')] + [../../../Type/ReferenceType/ClassOrInterfaceType[typeIs('java.lang.Thread')]] + or (./AllocationExpression/ClassOrInterfaceType[typeIs('java.lang.Thread')] and ../PrimarySuffix[@Image = 'run']) ] ] diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 0d265f88d2..8ea388733b 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -135,10 +135,10 @@ The FileReader and FileWriter constructors instantiate FileInputStream and FileO @@ -209,10 +209,10 @@ adverse impacts on performance. @@ -467,7 +467,7 @@ Note that new Integer() is deprecated since JDK 9 for that reason. @@ -500,7 +500,7 @@ Note that new Long() is deprecated since JDK 9 for that reason. @@ -664,7 +664,7 @@ Note that new Short() is deprecated since JDK 9 for that reason. diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/multithreading/MultithreadingRulesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/multithreading/MultithreadingRulesTest.java index 1bc4397544..d6f43996b3 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/multithreading/MultithreadingRulesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/multithreading/MultithreadingRulesTest.java @@ -34,4 +34,9 @@ public class MultithreadingRulesTest extends SimpleAggregatorTst { System.out.println("test"); } } + + // Used by AvoidThreadGroup test cases + public static class ThreadGroup { + + } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ArrayVariableDeclaration.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ArrayVariableDeclaration.java index 104a5d4a2b..05a99d2238 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ArrayVariableDeclaration.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/ArrayVariableDeclaration.java @@ -24,10 +24,10 @@ public class ArrayVariableDeclaration { | + PrimitiveType | |+ VariableDeclarator - | + VariableDeclaratorId[@Image="a" and @Array=false() and ArrayDims=0 and typeof(.)='int[].class'] + | + VariableDeclaratorId[@Image="a" and @Array=false() and ArrayDims=0 and typeIs(.)='int[].class'] | |+ VariableDeclarator - | + VariableDeclaratorId[@Image="b" and @Array=true() and ArrayDims=1 and typeof(.)='int[][].class'] + | + VariableDeclaratorId[@Image="b" and @Array=true() and ArrayDims=1 and typeIs(.)='int[][].class'] */ public int[] a, b[]; // SUPPRESS CHECKSTYLE now public String[] c, d[]; // SUPPRESS CHECKSTYLE now diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml index 01632cabe9..ba281bbf8a 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml @@ -236,7 +236,7 @@ class Foo { violation suppression xpath works, by type ]]> - .[typeof('java.lang.String')] + .[typeIs('java.lang.String')] 0 0