You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3384 lines
116 KiB
XML
3384 lines
116 KiB
XML
6 years ago
|
<?xml version="1.0"?>
|
||
|
|
||
|
<ruleset name="Error Prone"
|
||
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
|
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
||
|
|
||
|
<description>
|
||
|
Rules to detect constructs that are either broken, extremely confusing or prone to runtime errors.
|
||
|
</description>
|
||
|
|
||
|
<rule name="AssignmentInOperand"
|
||
|
since="1.03"
|
||
|
message="Avoid assignments in operands"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AssignmentInOperandRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#assignmentinoperand">
|
||
|
<description>
|
||
|
Avoid assignments in operands; this can make code more complicated and harder to read.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar() {
|
||
|
int x = 2;
|
||
|
if ((x = getX()) == 3) {
|
||
|
System.out.println("3!");
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AssignmentToNonFinalStatic"
|
||
|
since="2.2"
|
||
|
message="Possible unsafe assignment to a non-final static field in a constructor."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AssignmentToNonFinalStaticRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#assignmenttononfinalstatic">
|
||
|
<description>
|
||
|
Identifies a possible unsafe usage of a static field.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class StaticField {
|
||
|
static int x;
|
||
|
public FinalFields(int y) {
|
||
|
x = y; // unsafe
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidAccessibilityAlteration"
|
||
|
language="java"
|
||
|
since="4.1"
|
||
|
message="You should not modify visibility of class or methods using getDeclaredConstructors(), getDeclaredConstructor(Class[]), setAccessible() or PrivilegedAction."
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidaccessibilityalteration">
|
||
|
<description>
|
||
|
Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(),
|
||
|
as the interface PrivilegedAction, allow for the runtime alteration of variable, class, or
|
||
|
method visibility, even if they are private. This violates the principle of encapsulation.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//PrimaryExpression[
|
||
|
(
|
||
|
(PrimarySuffix[
|
||
|
ends-with(@Image,'getDeclaredConstructors')
|
||
|
or
|
||
|
ends-with(@Image,'getDeclaredConstructor')
|
||
|
or
|
||
|
ends-with(@Image,'setAccessible')
|
||
|
])
|
||
|
or
|
||
|
(PrimaryPrefix/Name[
|
||
|
ends-with(@Image,'getDeclaredConstructor')
|
||
|
or
|
||
|
ends-with(@Image,'getDeclaredConstructors')
|
||
|
or
|
||
|
starts-with(@Image,'AccessibleObject.setAccessible')
|
||
|
])
|
||
|
)
|
||
|
and
|
||
|
(//ImportDeclaration/Name[
|
||
|
contains(@Image,'java.security.PrivilegedAction')])
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
import java.lang.reflect.AccessibleObject;
|
||
|
import java.lang.reflect.Method;
|
||
|
import java.security.PrivilegedAction;
|
||
|
|
||
|
public class Violation {
|
||
|
public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException {
|
||
|
// Possible call to forbidden getDeclaredConstructors
|
||
|
Class[] arrayOfClass = new Class[1];
|
||
|
this.getClass().getDeclaredConstructors();
|
||
|
this.getClass().getDeclaredConstructor(arrayOfClass);
|
||
|
Class clazz = this.getClass();
|
||
|
clazz.getDeclaredConstructor(arrayOfClass);
|
||
|
clazz.getDeclaredConstructors();
|
||
|
// Possible call to forbidden setAccessible
|
||
|
clazz.getMethod("", arrayOfClass).setAccessible(false);
|
||
|
AccessibleObject.setAccessible(null, false);
|
||
|
Method.setAccessible(null, false);
|
||
|
Method[] methodsArray = clazz.getMethods();
|
||
|
int nbMethod;
|
||
|
for ( nbMethod = 0; nbMethod < methodsArray.length; nbMethod++ ) {
|
||
|
methodsArray[nbMethod].setAccessible(false);
|
||
|
}
|
||
|
|
||
|
// Possible call to forbidden PrivilegedAction
|
||
|
PrivilegedAction priv = (PrivilegedAction) new Object(); priv.run();
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidAssertAsIdentifier"
|
||
|
language="java"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidassertasidentifier">
|
||
|
<description>
|
||
|
Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//VariableDeclaratorId[@Image='assert']</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class A {
|
||
|
public class Foo {
|
||
|
String assert = "foo";
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidBranchingStatementAsLastInLoop"
|
||
|
since="5.0"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidBranchingStatementAsLastInLoopRule"
|
||
|
message="Avoid using a branching statement as the last in a loop."
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidbranchingstatementaslastinloop">
|
||
|
<description>
|
||
|
Using a branching statement as the last part of a loop may be a bug, and/or is confusing.
|
||
|
Ensure that the usage is not a bug, or consider using another approach.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
// unusual use of branching statement in a loop
|
||
|
for (int i = 0; i < 10; i++) {
|
||
|
if (i*i <= 25) {
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// this makes more sense...
|
||
|
for (int i = 0; i < 10; i++) {
|
||
|
if (i*i > 25) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidCallingFinalize"
|
||
|
since="3.0"
|
||
|
message="Avoid calling finalize() explicitly"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCallingFinalizeRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcallingfinalize">
|
||
|
<description>
|
||
|
The method Object.finalize() is called by the garbage collector on an object when garbage collection determines
|
||
|
that there are no more references to the object. It should not be invoked by application logic.
|
||
|
|
||
|
Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
void foo() {
|
||
|
Bar b = new Bar();
|
||
|
b.finalize();
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidCatchingNPE"
|
||
|
language="java"
|
||
|
since="1.8"
|
||
|
message="Avoid catching NullPointerException; consider removing the cause of the NPE."
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingnpe">
|
||
|
<description>
|
||
|
Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the
|
||
|
original error, causing other, more subtle problems later on.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//CatchStatement/FormalParameter/Type
|
||
|
/ReferenceType/ClassOrInterfaceType[@Image='NullPointerException']
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
void bar() {
|
||
|
try {
|
||
|
// do something
|
||
|
} catch (NullPointerException npe) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidCatchingThrowable"
|
||
|
since="1.2"
|
||
|
message="A catch statement should never catch throwable since it includes errors."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCatchingThrowableRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingthrowable">
|
||
|
<description>
|
||
|
Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as
|
||
|
OutOfMemoryError that should be exposed and managed separately.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar() {
|
||
|
try {
|
||
|
// do something
|
||
|
} catch (Throwable th) { // should not catch Throwable
|
||
|
th.printStackTrace();
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidDecimalLiteralsInBigDecimalConstructor"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoiddecimalliteralsinbigdecimalconstructor">
|
||
|
<description>
|
||
|
One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actually
|
||
|
equal to .1000000000000000055511151231257827021181583404541015625.
|
||
|
This is because 0.1 cannot be represented exactly as a double (or as a binary fraction of any finite
|
||
|
length). Thus, the long value that is being passed in to the constructor is not exactly equal to 0.1,
|
||
|
appearances notwithstanding.
|
||
|
|
||
|
The (String) constructor, on the other hand, is perfectly predictable: 'new BigDecimal("0.1")' is
|
||
|
exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the
|
||
|
(String) constructor be used in preference to this one.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//AllocationExpression
|
||
|
[ClassOrInterfaceType[@Image="BigDecimal"]]
|
||
|
[Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix
|
||
|
[
|
||
|
Literal[(not(ends-with(@Image,'"'))) and contains(@Image,".")]
|
||
|
or
|
||
|
Name[ancestor::Block/BlockStatement/LocalVariableDeclaration
|
||
|
[Type[PrimitiveType[@Image='double' or @Image='float']
|
||
|
or ReferenceType/ClassOrInterfaceType[@Image='Double' or @Image='Float']]]
|
||
|
/VariableDeclarator/VariableDeclaratorId/@Image = @Image
|
||
|
]
|
||
|
or
|
||
|
Name[ancestor::MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter
|
||
|
[Type[PrimitiveType[@Image='double' or @Image='float']
|
||
|
or ReferenceType/ClassOrInterfaceType[@Image='Double' or @Image='Float']]]
|
||
|
/VariableDeclaratorId/@Image = @Image
|
||
|
]
|
||
|
]
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
BigDecimal bd = new BigDecimal(1.123); // loss of precision, this would trigger the rule
|
||
|
|
||
|
BigDecimal bd = new BigDecimal("1.123"); // preferred approach
|
||
|
|
||
|
BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer values
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidDuplicateLiterals"
|
||
|
since="1.0"
|
||
|
message="The String literal {0} appears {1} times in this file; the first occurrence is on line {2}"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidDuplicateLiteralsRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidduplicateliterals">
|
||
|
<description>
|
||
|
Code containing duplicate String literals can usually be improved by declaring the String as a constant field.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
private void bar() {
|
||
|
buz("Howdy");
|
||
|
buz("Howdy");
|
||
|
buz("Howdy");
|
||
|
buz("Howdy");
|
||
|
}
|
||
|
private void buz(String x) {}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidEnumAsIdentifier"
|
||
|
language="java"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidenumasidentifier">
|
||
|
<description>
|
||
|
Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//VariableDeclaratorId[@Image='enum']</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class A {
|
||
|
public class Foo {
|
||
|
String enum = "foo";
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidFieldNameMatchingMethodName"
|
||
|
since="3.0"
|
||
|
message="Field {0} has the same name as a method"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingMethodNameRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidfieldnamematchingmethodname">
|
||
|
<description>
|
||
|
It can be confusing to have a field name with the same name as a method. While this is permitted,
|
||
|
having information (field) and actions (method) is not clear naming. Developers versed in
|
||
|
Smalltalk often prefer this approach as the methods denote accessor methods.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
Object bar;
|
||
|
// bar is data or an action or both?
|
||
|
void bar() {
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidFieldNameMatchingTypeName"
|
||
|
since="3.0"
|
||
|
message="It is somewhat confusing to have a field name matching the declaring class name"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingTypeNameRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidfieldnamematchingtypename">
|
||
|
<description>
|
||
|
It is somewhat confusing to have a field name matching the declaring class name.
|
||
|
This probably means that type and/or field names should be chosen more carefully.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo extends Bar {
|
||
|
int foo; // There is probably a better name that can be used
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidInstanceofChecksInCatchClause"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidinstanceofchecksincatchclause">
|
||
|
<description>
|
||
|
Each caught exception type should be handled in its own catch clause.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//CatchStatement/FormalParameter
|
||
|
/following-sibling::Block//InstanceOfExpression/PrimaryExpression/PrimaryPrefix
|
||
|
/Name[
|
||
|
@Image = ./ancestor::Block/preceding-sibling::FormalParameter
|
||
|
/VariableDeclaratorId/@Image
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
try { // Avoid this
|
||
|
// do something
|
||
|
} catch (Exception ee) {
|
||
|
if (ee instanceof IOException) {
|
||
|
cleanup();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
try { // Prefer this:
|
||
|
// do something
|
||
|
} catch (IOException ee) {
|
||
|
cleanup();
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidLiteralsInIfCondition"
|
||
|
language="java"
|
||
|
since="4.2.6"
|
||
|
message="Avoid using Literals in Conditional Statements"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidliteralsinifcondition">
|
||
|
<description>
|
||
|
Avoid using hard-coded literals in conditional statements. By declaring them as static variables
|
||
|
or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored.
|
||
|
More exceptions can be defined with the property "ignoreMagicNumbers".
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="ignoreMagicNumbers"
|
||
|
description="Comma-separated list of magic numbers, that should be ignored"
|
||
|
type="String" value="-1,0"/>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//IfStatement/Expression/*/PrimaryExpression/PrimaryPrefix/Literal
|
||
|
[not(NullLiteral)]
|
||
|
[not(BooleanLiteral)]
|
||
|
[empty(index-of(tokenize($ignoreMagicNumbers, '\s*,\s*'), @Image))]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
<property name="version" value="2.0"/>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
private static final int MAX_NUMBER_OF_REQUESTS = 10;
|
||
|
|
||
|
public void checkRequests() {
|
||
|
|
||
|
if (i == 10) { // magic number, buried in a method
|
||
|
doSomething();
|
||
|
}
|
||
|
|
||
|
if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach
|
||
|
doSomething();
|
||
|
}
|
||
|
|
||
|
if (aString.indexOf('.') != -1) {} // magic number -1, by default ignored
|
||
|
if (aString.indexOf('.') >= 0) { } // alternative approach
|
||
|
|
||
|
if (aDouble > 0.0) {} // magic number 0.0
|
||
|
if (aDouble >= Double.MIN_VALUE) {} // preferred approach
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidLosingExceptionInformation"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidlosingexceptioninformation">
|
||
|
<description>
|
||
|
Statements in a catch block that invoke accessors on the exception without using the information
|
||
|
only add to code size. Either remove the invocation, or use the return result.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//CatchStatement/Block/BlockStatement/Statement/StatementExpression/PrimaryExpression/PrimaryPrefix/Name
|
||
|
[
|
||
|
@Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getMessage')
|
||
|
or
|
||
|
@Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getLocalizedMessage')
|
||
|
or
|
||
|
@Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getCause')
|
||
|
or
|
||
|
@Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getStackTrace')
|
||
|
or
|
||
|
@Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.toString')
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar() {
|
||
|
try {
|
||
|
// do something
|
||
|
} catch (SomeException se) {
|
||
|
se.getMessage();
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidMultipleUnaryOperators"
|
||
|
since="4.2"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidMultipleUnaryOperatorsRule"
|
||
|
message="Using multiple unary operators may be a bug, and/or is confusing."
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidmultipleunaryoperators">
|
||
|
<description>
|
||
|
The use of multiple unary operators may be problematic, and/or confusing.
|
||
|
Ensure that the intended usage is not a bug, or consider simplifying the expression.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
// These are typo bugs, or at best needlessly complex and confusing:
|
||
|
int i = - -1;
|
||
|
int j = + - +1;
|
||
|
int z = ~~2;
|
||
|
boolean b = !!true;
|
||
|
boolean c = !!!true;
|
||
|
|
||
|
// These are better:
|
||
|
int i = 1;
|
||
|
int j = -1;
|
||
|
int z = 2;
|
||
|
boolean b = true;
|
||
|
boolean c = false;
|
||
|
|
||
|
// And these just make your brain hurt:
|
||
|
int i = ~-2;
|
||
|
int j = -~7;
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="AvoidUsingOctalValues"
|
||
|
since="3.9"
|
||
|
message="Do not start a literal by 0 unless it's an octal value"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidUsingOctalValuesRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidusingoctalvalues">
|
||
|
<description>
|
||
|
Integer literals should not start with zero since this denotes that the rest of literal will be
|
||
|
interpreted as an octal value.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
int i = 012; // set i with 10 not 12
|
||
|
int j = 010; // set j with 8 not 10
|
||
|
k = i * j; // set k with 80 not 120
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="BadComparison"
|
||
|
language="java"
|
||
|
since="1.8"
|
||
|
message="Avoid equality comparisons with Double.NaN"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#badcomparison">
|
||
|
<description>
|
||
|
Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation
|
||
|
precision when comparing floating point numbers these are likely to cause logic errors.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//EqualityExpression[@Image='==']
|
||
|
/PrimaryExpression/PrimaryPrefix
|
||
|
/Name[@Image='Double.NaN' or @Image='Float.NaN']
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
boolean x = (y == Double.NaN);
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="BeanMembersShouldSerialize"
|
||
|
since="1.1"
|
||
|
message="Found non-transient, non-static member. Please mark as transient or provide accessors."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.BeanMembersShouldSerializeRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#beanmembersshouldserialize">
|
||
|
<description>
|
||
|
If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializable.
|
||
|
Member variables need to be marked as transient, static, or have accessor methods in the class. Marking
|
||
|
variables as transient is the safest and easiest modification. Accessor methods should follow the Java
|
||
|
naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
private transient int someFoo; // good, it's transient
|
||
|
private static int otherFoo; // also OK
|
||
|
private int moreFoo; // OK, has proper accessors, see below
|
||
|
private int badFoo; // bad, should be marked transient
|
||
|
|
||
|
private void setMoreFoo(int moreFoo){
|
||
|
this.moreFoo = moreFoo;
|
||
|
}
|
||
|
|
||
|
private int getMoreFoo(){
|
||
|
return this.moreFoo;
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="BrokenNullCheck"
|
||
|
since="3.8"
|
||
|
message="Method call on object which may be null"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.BrokenNullCheckRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#brokennullcheck">
|
||
|
<description>
|
||
|
The null check is broken since it will throw a NullPointerException itself.
|
||
|
It is likely that you used || instead of && or vice versa.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public String bar(String string) {
|
||
|
// should be &&
|
||
|
if (string!=null || !string.equals(""))
|
||
|
return string;
|
||
|
// should be ||
|
||
|
if (string==null && string.equals(""))
|
||
|
return string;
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CallSuperFirst"
|
||
|
since="4.2.5"
|
||
|
language="java"
|
||
|
message="super should be called at the start of the method"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#callsuperfirst">
|
||
|
<description>Super should be called at the start of the method</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[MethodDeclarator[
|
||
|
@Image='onCreate' or
|
||
|
@Image='onConfigurationChanged' or
|
||
|
@Image='onPostCreate' or
|
||
|
@Image='onPostResume' or
|
||
|
@Image='onRestart' or
|
||
|
@Image='onRestoreInstanceState' or
|
||
|
@Image='onResume' or
|
||
|
@Image='onStart'
|
||
|
]]
|
||
|
/Block[not(
|
||
|
(BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image]))]
|
||
|
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
|
||
|
pmd-java:typeIs('android.app.Activity') or
|
||
|
pmd-java:typeIs('android.app.Application') or
|
||
|
pmd-java:typeIs('android.app.Service')
|
||
|
]]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class DummyActivity extends Activity {
|
||
|
public void onCreate(Bundle bundle) {
|
||
|
// missing call to super.onCreate(bundle)
|
||
|
foo();
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CallSuperLast"
|
||
|
since="4.2.5"
|
||
|
language="java"
|
||
|
message="super should be called at the end of the method"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#callsuperlast">
|
||
|
<description>
|
||
|
Super should be called at the end of the method
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[MethodDeclarator[
|
||
|
@Image='finish' or
|
||
|
@Image='onDestroy' or
|
||
|
@Image='onPause' or
|
||
|
@Image='onSaveInstanceState' or
|
||
|
@Image='onStop' or
|
||
|
@Image='onTerminate'
|
||
|
]]
|
||
|
/Block/BlockStatement[last()]
|
||
|
[not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])]
|
||
|
[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[
|
||
|
pmd-java:typeIs('android.app.Activity') or
|
||
|
pmd-java:typeIs('android.app.Application') or
|
||
|
pmd-java:typeIs('android.app.Service')
|
||
|
]]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class DummyActivity extends Activity {
|
||
|
public void onPause() {
|
||
|
foo();
|
||
|
// missing call to super.onPause()
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CheckSkipResult"
|
||
|
language="java"
|
||
|
since="5.0"
|
||
|
message="Check the value returned by the skip() method of an InputStream to see if the requested number of bytes has been skipped."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.CheckSkipResultRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#checkskipresult">
|
||
|
<description>
|
||
|
The skip() method may skip a smaller number of bytes than requested. Check the returned value to find out if it was the case or not.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
|
||
|
private FileInputStream _s = new FileInputStream("file");
|
||
|
|
||
|
public void skip(int n) throws IOException {
|
||
|
_s.skip(n); // You are not sure that exactly n bytes are skipped
|
||
|
}
|
||
|
|
||
|
public void skipExactly(int n) throws IOException {
|
||
|
while (n != 0) {
|
||
|
long skipped = _s.skip(n);
|
||
|
if (skipped == 0)
|
||
|
throw new EOFException();
|
||
|
n -= skipped;
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ClassCastExceptionWithToArray"
|
||
|
language="java"
|
||
|
since="3.4"
|
||
|
message="This usage of the Collection.toArray() method will throw a ClassCastException."
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#classcastexceptionwithtoarray">
|
||
|
<description>
|
||
|
When deriving an array of a specific class from your Collection, one should provide an array of
|
||
|
the same class as the parameter of the toArray() method. Doing otherwise you will will result
|
||
|
in a ClassCastException.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//CastExpression[Type/ReferenceType/ClassOrInterfaceType[@Image !=
|
||
|
"Object"]]/PrimaryExpression
|
||
|
[
|
||
|
PrimaryPrefix/Name[ends-with(@Image, '.toArray')]
|
||
|
and
|
||
|
PrimarySuffix/Arguments[count(*) = 0]
|
||
|
and
|
||
|
count(PrimarySuffix) = 1
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
Collection c = new ArrayList();
|
||
|
Integer obj = new Integer(1);
|
||
|
c.add(obj);
|
||
|
|
||
|
// this would trigger the rule (and throw a ClassCastException if executed)
|
||
|
Integer[] a = (Integer [])c.toArray();
|
||
|
|
||
|
// this is fine and will not trigger the rule
|
||
|
Integer[] b = (Integer [])c.toArray(new Integer[c.size()]);
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CloneMethodMustBePublic"
|
||
|
language="java"
|
||
|
since="5.4.0"
|
||
|
message="clone() method must be public if the class implements Cloneable"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#clonemethodmustbepublic">
|
||
|
<description>
|
||
|
The java Manual says "By convention, classes that implement this interface should override
|
||
|
Object.clone (which is protected) with a public method."
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[@Public='false']
|
||
|
[MethodDeclarator/@Image = 'clone']
|
||
|
[MethodDeclarator/FormalParameters/@ParameterCount = 0]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo implements Cloneable {
|
||
|
@Override
|
||
|
protected Object clone() throws CloneNotSupportedException { // Violation, must be public
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Foo implements Cloneable {
|
||
|
@Override
|
||
|
protected Foo clone() { // Violation, must be public
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Foo implements Cloneable {
|
||
|
@Override
|
||
|
public Object clone() // Ok
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CloneMethodMustImplementCloneable"
|
||
|
language="java"
|
||
|
since="1.9"
|
||
|
message="clone() method should be implemented only if implementing Cloneable interface"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.CloneMethodMustImplementCloneableRule"
|
||
|
typeResolution="true"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#clonemethodmustimplementcloneable">
|
||
|
<description>
|
||
|
The method clone() should only be implemented if the class implements the Cloneable interface with the exception of
|
||
|
a final method that only throws CloneNotSupportedException.
|
||
|
|
||
|
The rule can also detect, if the class implements or extends a Cloneable class.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class MyClass {
|
||
|
public Object clone() throws CloneNotSupportedException {
|
||
|
return foo;
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CloneMethodReturnTypeMustMatchClassName"
|
||
|
language="java"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#clonemethodreturntypemustmatchclassname">
|
||
|
<description>
|
||
|
If a class implements cloneable the return type of the method clone() must be the class name. That way, the caller
|
||
|
of the clone method doesn't need to cast the returned clone to the correct type.
|
||
|
|
||
|
Note: This is only possible with Java 1.5 or higher.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration
|
||
|
[
|
||
|
MethodDeclarator/@Image = 'clone'
|
||
|
and MethodDeclarator/FormalParameters/@ParameterCount = 0
|
||
|
and not (ResultType//ClassOrInterfaceType/@Image = ancestor::ClassOrInterfaceDeclaration[1]/@Image)
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo implements Cloneable {
|
||
|
@Override
|
||
|
protected Object clone() { // Violation, Object must be Foo
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Foo implements Cloneable {
|
||
|
@Override
|
||
|
public Foo clone() { //Ok
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CloneThrowsCloneNotSupportedException"
|
||
|
language="java"
|
||
|
since="1.9"
|
||
|
message="clone() method should throw CloneNotSupportedException"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#clonethrowsclonenotsupportedexception">
|
||
|
<description>
|
||
|
The method clone() should throw a CloneNotSupportedException.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration
|
||
|
[
|
||
|
MethodDeclarator/@Image = 'clone'
|
||
|
and count(MethodDeclarator/FormalParameters/*) = 0
|
||
|
and count(NameList/Name[contains
|
||
|
(@Image,'CloneNotSupportedException')]) = 0
|
||
|
]
|
||
|
[
|
||
|
../../../../ClassOrInterfaceDeclaration[@Final = 'false']
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class MyClass implements Cloneable{
|
||
|
public Object clone() { // will cause an error
|
||
|
MyClass clone = (MyClass)super.clone();
|
||
|
return clone;
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CloseResource"
|
||
|
since="1.2.2"
|
||
|
message="Ensure that resources like this {0} object are closed after use"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.CloseResourceRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#closeresource">
|
||
|
<description>
|
||
|
Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after use.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Bar {
|
||
|
public void foo() {
|
||
|
Connection c = pool.getConnection();
|
||
|
try {
|
||
|
// do stuff
|
||
|
} catch (SQLException ex) {
|
||
|
// handle exception
|
||
|
} finally {
|
||
|
// oops, should close the connection using 'close'!
|
||
|
// c.close();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="CompareObjectsWithEquals"
|
||
|
since="3.2"
|
||
|
message="Use equals() to compare object references."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.CompareObjectsWithEqualsRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#compareobjectswithequals">
|
||
|
<description>
|
||
|
Use equals() to compare object references; avoid comparing them with ==.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
class Foo {
|
||
|
boolean bar(String a, String b) {
|
||
|
return a == b;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ConstructorCallsOverridableMethod"
|
||
|
since="1.04"
|
||
|
message="Overridable {0} called during object construction"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.ConstructorCallsOverridableMethodRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#constructorcallsoverridablemethod">
|
||
|
<description>
|
||
|
Calling overridable methods during construction poses a risk of invoking methods on an incompletely
|
||
|
constructed object and can be difficult to debug.
|
||
|
It may leave the sub-class unable to construct its superclass or forced to replicate the construction
|
||
|
process completely within itself, losing the ability to call super(). If the default constructor
|
||
|
contains a call to an overridable method, the subclass may be completely uninstantiable. Note that
|
||
|
this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a
|
||
|
private method bar() that calls a public method buz(), this denotes a problem.
|
||
|
</description>
|
||
|
<priority>1</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class SeniorClass {
|
||
|
public SeniorClass(){
|
||
|
toString(); //may throw NullPointerException if overridden
|
||
|
}
|
||
|
public String toString(){
|
||
|
return "IAmSeniorClass";
|
||
|
}
|
||
|
}
|
||
|
public class JuniorClass extends SeniorClass {
|
||
|
private String name;
|
||
|
public JuniorClass(){
|
||
|
super(); //Automatic call leads to NullPointerException
|
||
|
name = "JuniorClass";
|
||
|
}
|
||
|
public String toString(){
|
||
|
return name.toUpperCase();
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DataflowAnomalyAnalysis"
|
||
|
since="3.9"
|
||
|
message="Found ''{0}''-anomaly for variable ''{1}'' (lines ''{2}''-''{3}'')."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.DataflowAnomalyAnalysisRule"
|
||
|
dfa="true"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#dataflowanomalyanalysis">
|
||
|
<description>The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow.
|
||
|
From those informations there can be found various problems.
|
||
|
|
||
|
1. UR - Anomaly: There is a reference to a variable that was not defined before. This is a bug and leads to an error.
|
||
|
2. DU - Anomaly: A recently defined variable is undefined. These anomalies may appear in normal source text.
|
||
|
3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug.
|
||
|
</description>
|
||
|
<priority>5</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void foo() {
|
||
|
int buz = 5;
|
||
|
buz = 6; // redefinition of buz -> dd-anomaly
|
||
|
foo(buz);
|
||
|
buz = 2;
|
||
|
} // buz is undefined when leaving scope -> du-anomaly
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DoNotCallGarbageCollectionExplicitly"
|
||
|
language="java"
|
||
|
since="4.2"
|
||
|
message="Do not explicitly trigger a garbage collection."
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotcallgarbagecollectionexplicitly">
|
||
|
<description>
|
||
|
Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Code should have the
|
||
|
same behavior whether the garbage collection is disabled using the option -Xdisableexplicitgc or not.
|
||
|
Moreover, "modern" jvms do a very good job handling garbage collections. If memory usage issues unrelated to memory
|
||
|
leaks develop within an application, it should be dealt with JVM options rather than within the code itself.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//Name[
|
||
|
(starts-with(@Image, 'System.') and
|
||
|
(starts-with(@Image, 'System.gc') or
|
||
|
starts-with(@Image, 'System.runFinalization'))) or
|
||
|
(
|
||
|
starts-with(@Image,'Runtime.getRuntime') and
|
||
|
../../PrimarySuffix[ends-with(@Image,'gc')]
|
||
|
)
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class GCCall {
|
||
|
public GCCall() {
|
||
|
// Explicit gc call !
|
||
|
System.gc();
|
||
|
}
|
||
|
|
||
|
public void doSomething() {
|
||
|
// Explicit gc call !
|
||
|
Runtime.getRuntime().gc();
|
||
|
}
|
||
|
|
||
|
public explicitGCcall() {
|
||
|
// Explicit gc call !
|
||
|
System.gc();
|
||
|
}
|
||
|
|
||
|
public void doSomething() {
|
||
|
// Explicit gc call !
|
||
|
Runtime.getRuntime().gc();
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DoNotCallSystemExit"
|
||
|
language="java"
|
||
|
since="4.1"
|
||
|
message="System.exit() should not be used in J2EE/JEE apps"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotcallsystemexit">
|
||
|
<description>
|
||
|
Web applications should not call System.exit(), since only the web container or the
|
||
|
application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit().
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//Name[
|
||
|
starts-with(@Image,'System.exit')
|
||
|
or
|
||
|
(starts-with(@Image,'Runtime.getRuntime') and ../../PrimarySuffix[ends-with(@Image,'exit')])
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar() {
|
||
|
System.exit(0); // never call this when running in an application server!
|
||
|
}
|
||
|
public void foo() {
|
||
|
Runtime.getRuntime().exit(0); // never stop the JVM manually, the container will do this.
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DoNotExtendJavaLangThrowable"
|
||
|
language="java"
|
||
|
since="6.0.0"
|
||
|
message="Exceptions should not extend java.lang.Throwable"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotextendjavalangthrowable">
|
||
|
<description>
|
||
|
Extend Exception or RuntimeException instead of Throwable.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//ClassOrInterfaceDeclaration/ExtendsList/ClassOrInterfaceType
|
||
|
[@Image="Throwable" or @Image="java.lang.Throwable"]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo extends Throwable { }
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DoNotHardCodeSDCard"
|
||
|
since="4.2.6"
|
||
|
language="java"
|
||
|
message="Do not hardcode /sdcard."
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donothardcodesdcard">
|
||
|
<description>
|
||
|
Use Environment.getExternalStorageDirectory() instead of "/sdcard"
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//Literal[starts-with(@Image,'"/sdcard')]</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class MyActivity extends Activity {
|
||
|
protected void foo() {
|
||
|
String storageLocation = "/sdcard/mypackage"; // hard-coded, poor approach
|
||
|
|
||
|
storageLocation = Environment.getExternalStorageDirectory() + "/mypackage"; // preferred approach
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DoNotThrowExceptionInFinally"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotthrowexceptioninfinally">
|
||
|
<description>
|
||
|
Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions
|
||
|
or code defects.
|
||
|
Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block"
|
||
|
</description>
|
||
|
<priority>4</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//FinallyStatement[descendant::ThrowStatement]</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public void bar() {
|
||
|
try {
|
||
|
// Here do some stuff
|
||
|
} catch( Exception e) {
|
||
|
// Handling the issue
|
||
|
} finally {
|
||
|
// is this really a good idea ?
|
||
|
throw new Exception();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DontImportSun"
|
||
|
since="1.5"
|
||
|
message="Avoid importing anything from the 'sun.*' packages"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.DontImportSunRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#dontimportsun">
|
||
|
<description>
|
||
|
Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change.
|
||
|
</description>
|
||
|
<priority>4</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
import sun.misc.foo;
|
||
|
public class Foo {}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="DontUseFloatTypeForLoopIndices"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#dontusefloattypeforloopindices">
|
||
|
<description>
|
||
|
Don't use floating point for loop indices. If you must use floating point, use double
|
||
|
unless you're certain that float provides enough precision and you have a compelling
|
||
|
performance need (space or time).
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//ForStatement/ForInit/LocalVariableDeclaration
|
||
|
/Type/PrimitiveType[@Image="float"]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Count {
|
||
|
public static void main(String[] args) {
|
||
|
final int START = 2000000000;
|
||
|
int count = 0;
|
||
|
for (float f = START; f < START + 50; f++)
|
||
|
count++;
|
||
|
//Prints 0 because (float) START == (float) (START + 50).
|
||
|
System.out.println(count);
|
||
|
//The termination test misbehaves due to floating point granularity.
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyCatchBlock"
|
||
|
language="java"
|
||
|
since="0.1"
|
||
|
message="Avoid empty catch blocks"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptycatchblock">
|
||
|
<description>
|
||
|
Empty Catch Block finds instances where an exception is caught, but nothing is done.
|
||
|
In most circumstances, this swallows an exception which should either be acted on
|
||
|
or reported.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//CatchStatement
|
||
|
[count(Block/BlockStatement) = 0 and ($allowCommentedBlocks != 'true' or Block/@containsComment = 'false')]
|
||
|
[FormalParameter/Type/ReferenceType
|
||
|
/ClassOrInterfaceType[@Image != 'InterruptedException' and @Image != 'CloneNotSupportedException']
|
||
|
]
|
||
|
[FormalParameter/VariableDeclaratorId[not(matches(@Image, $allowExceptionNameRegex))]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
<property name="allowCommentedBlocks" type="Boolean" description="Empty blocks containing comments will be skipped" value="false"/>
|
||
|
<property name="allowExceptionNameRegex" type="String" description="Empty blocks catching exceptions with names matching this regular expression will be skipped" value="^(ignored|expected)$"/>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void doSomething() {
|
||
|
try {
|
||
|
FileInputStream fis = new FileInputStream("/tmp/bugger");
|
||
|
} catch (IOException ioe) {
|
||
|
// not good
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyFinalizer"
|
||
|
language="java"
|
||
|
since="1.5"
|
||
|
message="Avoid empty finalize methods"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyfinalizer">
|
||
|
<description>
|
||
|
Empty finalize methods serve no purpose and should be removed. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]]
|
||
|
/Block[count(*)=0]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
protected void finalize() {}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyFinallyBlock"
|
||
|
language="java"
|
||
|
since="0.4"
|
||
|
message="Avoid empty finally blocks"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyfinallyblock">
|
||
|
<description>
|
||
|
Empty finally blocks serve no purpose and should be removed.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//FinallyStatement[count(Block/BlockStatement) = 0]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public void bar() {
|
||
|
try {
|
||
|
int x=2;
|
||
|
} finally {
|
||
|
// empty!
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyIfStmt"
|
||
|
language="java"
|
||
|
since="0.1"
|
||
|
message="Avoid empty 'if' statements"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyifstmt">
|
||
|
<description>
|
||
|
Empty If Statement finds instances where a condition is checked but nothing is done about it.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//IfStatement/Statement
|
||
|
[EmptyStatement or Block[count(*) = 0]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
void bar(int x) {
|
||
|
if (x == 0) {
|
||
|
// empty!
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyInitializer"
|
||
|
language="java"
|
||
|
since="5.0"
|
||
|
message="Empty initializer was found"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyinitializer">
|
||
|
<description>
|
||
|
Empty initializers serve no purpose and should be removed.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//Initializer/Block[count(*)=0]</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
|
||
|
static {} // Why ?
|
||
|
|
||
|
{} // Again, why ?
|
||
|
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyStatementBlock"
|
||
|
language="java"
|
||
|
since="5.0"
|
||
|
message="Avoid empty block statements."
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptystatementblock">
|
||
|
<description>
|
||
|
Empty block statements serve no purpose and should be removed.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//BlockStatement/Statement/Block[count(*) = 0]</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
|
||
|
private int _bar;
|
||
|
|
||
|
public void setBar(int bar) {
|
||
|
{ _bar = bar; } // Why not?
|
||
|
{} // But remove this.
|
||
|
}
|
||
|
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyStatementNotInLoop"
|
||
|
language="java"
|
||
|
since="1.5"
|
||
|
message="An empty statement (semicolon) not part of a loop"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptystatementnotinloop">
|
||
|
<description>
|
||
|
An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for'
|
||
|
or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose
|
||
|
and should be removed.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//EmptyStatement
|
||
|
[not(
|
||
|
../../../ForStatement
|
||
|
or ../../../WhileStatement
|
||
|
or ../../../BlockStatement/ClassOrInterfaceDeclaration
|
||
|
or ../../../../../../ForStatement/Statement[1]
|
||
|
/Block[1]/BlockStatement[1]/Statement/EmptyStatement
|
||
|
or ../../../../../../WhileStatement/Statement[1]
|
||
|
/Block[1]/BlockStatement[1]/Statement/EmptyStatement)
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void doit() {
|
||
|
// this is probably not what you meant to do
|
||
|
;
|
||
|
// the extra semicolon here this is not necessary
|
||
|
System.out.println("look at the extra semicolon");;
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptySwitchStatements"
|
||
|
language="java"
|
||
|
since="1.0"
|
||
|
message="Avoid empty switch statements"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptyswitchstatements">
|
||
|
<description>
|
||
|
Empty switch statements serve no purpose and should be removed.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//SwitchStatement[count(*) = 1]</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar() {
|
||
|
int x = 2;
|
||
|
switch (x) {
|
||
|
// once there was code here
|
||
|
// but it's been commented out or something
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptySynchronizedBlock"
|
||
|
language="java"
|
||
|
since="1.3"
|
||
|
message="Avoid empty synchronized blocks"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptysynchronizedblock">
|
||
|
<description>
|
||
|
Empty synchronized blocks serve no purpose and should be removed.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//SynchronizedStatement/Block[1][count(*) = 0]</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public void bar() {
|
||
|
synchronized (this) {
|
||
|
// empty!
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyTryBlock"
|
||
|
language="java"
|
||
|
since="0.4"
|
||
|
message="Avoid empty try blocks"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptytryblock">
|
||
|
<description>
|
||
|
Avoid empty try blocks - what's the point?
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//TryStatement[not(ResourceSpecification)]/Block[1][count(*) = 0]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public void bar() {
|
||
|
try {
|
||
|
} catch (Exception e) {
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EmptyWhileStmt"
|
||
|
language="java"
|
||
|
since="0.2"
|
||
|
message="Avoid empty 'while' statements"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptywhilestmt">
|
||
|
<description>
|
||
|
Empty While Statement finds all instances where a while statement does nothing.
|
||
|
If it is a timing loop, then you should use Thread.sleep() for it; if it is
|
||
|
a while loop that does a lot in the exit expression, rewrite it to make it clearer.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//WhileStatement/Statement[./Block[count(*) = 0] or ./EmptyStatement]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
void bar(int a, int b) {
|
||
|
while (a == b) {
|
||
|
// empty!
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="EqualsNull"
|
||
|
language="java"
|
||
|
since="1.9"
|
||
|
message="Avoid using equals() to compare against null"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#equalsnull">
|
||
|
<description>
|
||
|
Tests for null should not use the equals() method. The '==' operator should be used instead.
|
||
|
</description>
|
||
|
<priority>1</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//PrimaryExpression
|
||
|
[
|
||
|
PrimaryPrefix[Name[ends-with(@Image, 'equals')]]
|
||
|
[following-sibling::node()/Arguments/ArgumentList[count(Expression)=1]
|
||
|
/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
|
||
|
|
||
|
or
|
||
|
|
||
|
PrimarySuffix[ends-with(@Image, 'equals')]
|
||
|
[following-sibling::node()/Arguments/ArgumentList[count(Expression)=1]
|
||
|
/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
|
||
|
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
String x = "foo";
|
||
|
|
||
|
if (x.equals(null)) { // bad form
|
||
|
doSomething();
|
||
|
}
|
||
|
|
||
|
if (x == null) { // preferred
|
||
|
doSomething();
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="FinalizeDoesNotCallSuperFinalize"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizedoesnotcallsuperfinalize">
|
||
|
<description>
|
||
|
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.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<!-- in English: a method declaration of finalize(), with no arguments, containing
|
||
|
a block whose last statement is NOT a call to super.finalize -->
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]]
|
||
|
/Block
|
||
|
/BlockStatement[last()]
|
||
|
[not(Statement/StatementExpression/PrimaryExpression
|
||
|
[./PrimaryPrefix[@SuperModifier='true']]
|
||
|
[./PrimarySuffix[@Image='finalize']]
|
||
|
)
|
||
|
]
|
||
|
[not(Statement/TryStatement/FinallyStatement
|
||
|
/Block/BlockStatement/Statement/StatementExpression/PrimaryExpression
|
||
|
[./PrimaryPrefix[@SuperModifier='true']]
|
||
|
[./PrimarySuffix[@Image='finalize']]
|
||
|
)
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
protected void finalize() {
|
||
|
something();
|
||
|
// neglected to call super.finalize()
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="FinalizeOnlyCallsSuperFinalize"
|
||
|
language="java"
|
||
|
since="1.5"
|
||
|
message="Finalize should do something besides just calling super.finalize()"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeonlycallssuperfinalize">
|
||
|
<description>
|
||
|
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.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[MethodDeclarator[@Image="finalize"][not(FormalParameters/*)]]
|
||
|
/Block[count(BlockStatement)=1]
|
||
|
/BlockStatement[
|
||
|
Statement/StatementExpression/PrimaryExpression
|
||
|
[./PrimaryPrefix[@SuperModifier='true']]
|
||
|
[./PrimarySuffix[@Image='finalize']]
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
protected void finalize() {
|
||
|
super.finalize();
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="FinalizeOverloaded"
|
||
|
language="java"
|
||
|
since="1.5"
|
||
|
message="Finalize methods should not be overloaded"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeoverloaded">
|
||
|
<description>
|
||
|
Methods named finalize() should not have parameters. It is confusing and most likely an attempt to
|
||
|
overload Object.finalize(). It will not be called by the VM.
|
||
|
|
||
|
Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration
|
||
|
/MethodDeclarator[@Image='finalize'][FormalParameters[count(*)>0]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
// this is confusing and probably a bug
|
||
|
protected void finalize(int a) {
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="FinalizeShouldBeProtected"
|
||
|
language="java"
|
||
|
since="1.1"
|
||
|
message="If you override finalize(), make it protected"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeshouldbeprotected">
|
||
|
<description>
|
||
|
When overriding the finalize(), the new method should be set as protected. If made public,
|
||
|
other classes may invoke it at inappropriate times.
|
||
|
|
||
|
Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[@Protected="false"]
|
||
|
/MethodDeclarator[@Image="finalize"]
|
||
|
[not(FormalParameters/*)]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void finalize() {
|
||
|
// do something
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="IdempotentOperations"
|
||
|
since="2.0"
|
||
|
message="Avoid idempotent operations (like assigning a variable to itself)."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.IdempotentOperationsRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#idempotentoperations">
|
||
|
<description>
|
||
|
Avoid idempotent operations - they have no effect.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public void bar() {
|
||
|
int x = 2;
|
||
|
x = x;
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ImportFromSamePackage"
|
||
|
since="1.02"
|
||
|
message="No need to import a type that lives in the same package"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.ImportFromSamePackageRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#importfromsamepackage">
|
||
|
<description>
|
||
|
There is no need to import a type that lives in the same package.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
package foo;
|
||
|
|
||
|
import foo.Buz; // no need for this
|
||
|
import foo.*; // or this
|
||
|
|
||
|
public class Bar{}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="InstantiationToGetClass"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#instantiationtogetclass">
|
||
|
<description>
|
||
|
Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
|
||
|
</description>
|
||
|
<priority>4</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//PrimarySuffix
|
||
|
[@Image='getClass']
|
||
|
[parent::PrimaryExpression
|
||
|
[PrimaryPrefix/AllocationExpression]
|
||
|
[count(PrimarySuffix) = 2]
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
// replace this
|
||
|
Class c = new String().getClass();
|
||
|
|
||
|
// with this:
|
||
|
Class c = String.class;
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="InvalidSlf4jMessageFormat"
|
||
|
language="java"
|
||
|
since="5.5.0"
|
||
|
message="Invalid message format"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.InvalidSlf4jMessageFormatRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#invalidslf4jmessageformat">
|
||
|
<description>
|
||
|
Check for messages in slf4j loggers with non matching number of arguments and placeholders.
|
||
|
</description>
|
||
|
<priority>5</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
LOGGER.error("forget the arg {}");
|
||
|
LOGGER.error("too many args {}", "arg1", "arg2");
|
||
|
LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The exception is shown separately, so is correct.
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="JumbledIncrementer"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#jumbledincrementer">
|
||
|
<description>
|
||
|
Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value><![CDATA[
|
||
|
//ForStatement
|
||
|
[
|
||
|
ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image
|
||
|
=
|
||
|
ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class JumbledIncrementerRule1 {
|
||
|
public void foo() {
|
||
|
for (int i = 0; i < 10; i++) { // only references 'i'
|
||
|
for (int k = 0; k < 20; i++) { // references both 'i' and 'k'
|
||
|
System.out.println("Hello");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="JUnitSpelling"
|
||
|
language="java"
|
||
|
since="1.0"
|
||
|
message="You may have misspelled a JUnit framework method (setUp or tearDown)"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#junitspelling">
|
||
|
<description>
|
||
|
Some JUnit framework methods are easy to misspell.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclarator[(not(@Image = 'setUp')
|
||
|
and translate(@Image, 'SETuP', 'setUp') = 'setUp')
|
||
|
or (not(@Image = 'tearDown')
|
||
|
and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')]
|
||
|
[FormalParameters[count(*) = 0]]
|
||
|
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||
|
or //MarkerAnnotation/Name[
|
||
|
pmd-java:typeIs('org.junit.Test')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||
|
]
|
||
|
]]]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
import junit.framework.*;
|
||
|
|
||
|
public class Foo extends TestCase {
|
||
|
public void setup() {} // oops, should be setUp
|
||
|
public void TearDown() {} // oops, should be tearDown
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="JUnitStaticSuite"
|
||
|
language="java"
|
||
|
since="1.0"
|
||
|
message="You have a suite() method that is not both public and static, so JUnit won't call it to get your TestSuite. Is that what you wanted to do?"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
typeResolution="true"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#junitstaticsuite">
|
||
|
<description>
|
||
|
The suite() method in a JUnit test needs to be both public and static.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration[not(@Static='true') or not(@Public='true')]
|
||
|
[MethodDeclarator/@Image='suite']
|
||
|
[MethodDeclarator/FormalParameters/@ParameterCount=0]
|
||
|
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||
|
or //MarkerAnnotation/Name[
|
||
|
pmd-java:typeIs('org.junit.Test')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||
|
]
|
||
|
]]]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
import junit.framework.*;
|
||
|
|
||
|
public class Foo extends TestCase {
|
||
|
public void suite() {} // oops, should be static
|
||
|
private static void suite() {} // oops, should be public
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="LoggerIsNotStaticFinal"
|
||
|
language="java"
|
||
|
since="2.0"
|
||
|
message="The Logger variable declaration does not contain the static and final modifiers"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#loggerisnotstaticfinal">
|
||
|
<description>
|
||
|
In most cases, the Logger reference can be declared as static and final.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//VariableDeclarator
|
||
|
[parent::FieldDeclaration]
|
||
|
[../Type/ReferenceType
|
||
|
/ClassOrInterfaceType[@Image='Logger']
|
||
|
and
|
||
|
(..[@Final='false'] or ..[@Static = 'false'] ) ]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo{
|
||
|
Logger log = Logger.getLogger(Foo.class.getName()); // not recommended
|
||
|
|
||
|
static final Logger log = Logger.getLogger(Foo.class.getName()); // preferred approach
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="MethodWithSameNameAsEnclosingClass"
|
||
|
since="1.5"
|
||
|
message="Classes should not have non-constructor methods with the same name as the class"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.MethodWithSameNameAsEnclosingClassRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#methodwithsamenameasenclosingclass">
|
||
|
<description>
|
||
|
Non-constructor methods should not have the same name as the enclosing class.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class MyClass {
|
||
|
|
||
|
public MyClass() {} // this is OK because it is a constructor
|
||
|
|
||
|
public void MyClass() {} // this is bad because it is a method
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="MisplacedNullCheck"
|
||
|
language="java"
|
||
|
since="3.5"
|
||
|
message="The null check here is misplaced; if the variable is null there will be a NullPointerException"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#misplacednullcheck">
|
||
|
<description>
|
||
|
The null check here is misplaced. If the variable is null a NullPointerException will be thrown.
|
||
|
Either the check is useless (the variable will never be "null") or it is incorrect.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//Expression
|
||
|
/*[self::ConditionalOrExpression or self::ConditionalAndExpression]
|
||
|
/descendant::PrimaryExpression/PrimaryPrefix
|
||
|
/Name[starts-with(@Image,
|
||
|
concat(ancestor::PrimaryExpression/following-sibling::EqualityExpression
|
||
|
[./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
|
||
|
/PrimaryExpression/PrimaryPrefix
|
||
|
/Name[count(../../PrimarySuffix)=0]/@Image,".")
|
||
|
)
|
||
|
]
|
||
|
[count(ancestor::ConditionalAndExpression/EqualityExpression
|
||
|
[@Image='!=']
|
||
|
[./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
|
||
|
[starts-with(following-sibling::*/PrimaryExpression/PrimaryPrefix/Name/@Image,
|
||
|
concat(./PrimaryExpression/PrimaryPrefix/Name/@Image, '.'))]
|
||
|
) = 0
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
void bar() {
|
||
|
if (a.equals(baz) && a != null) {}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
void bar() {
|
||
|
if (a.equals(baz) || a == null) {}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="MissingBreakInSwitch"
|
||
|
language="java"
|
||
|
since="3.0"
|
||
|
message="A switch statement does not contain a break"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#missingbreakinswitch">
|
||
|
<description>
|
||
|
Switch statements without break or return statements for each case option
|
||
|
may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//SwitchStatement
|
||
|
[(count(.//BreakStatement)
|
||
|
+ count(BlockStatement//Statement/ReturnStatement)
|
||
|
+ count(BlockStatement//Statement/ContinueStatement)
|
||
|
+ count(BlockStatement//Statement/ThrowStatement)
|
||
|
+ count(BlockStatement//Statement/IfStatement[@Else='true' and Statement[2][ReturnStatement|ContinueStatement|ThrowStatement]]/Statement[1][ReturnStatement|ContinueStatement|ThrowStatement])
|
||
|
+ count(SwitchLabel[name(following-sibling::node()) = 'SwitchLabel'])
|
||
|
+ count(SwitchLabel[count(following-sibling::node()) = 0])
|
||
|
< count (SwitchLabel))]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar(int status) {
|
||
|
switch(status) {
|
||
|
case CANCELLED:
|
||
|
doCancelled();
|
||
|
// break; hm, should this be commented out?
|
||
|
case NEW:
|
||
|
doNew();
|
||
|
// is this really a fall-through?
|
||
|
case REMOVED:
|
||
|
doRemoved();
|
||
|
// what happens if you add another case after this one?
|
||
|
case OTHER: // empty case - this is interpreted as an intentional fall-through
|
||
|
case ERROR:
|
||
|
doErrorHandling();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="MissingSerialVersionUID"
|
||
|
language="java"
|
||
|
since="3.0"
|
||
|
message="Classes implementing Serializable should set a serialVersionUID"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
typeResolution="true"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#missingserialversionuid">
|
||
|
<description>
|
||
|
Serializable classes should provide a serialVersionUID field.
|
||
|
The serialVersionUID field is also needed for abstract base classes. Each individual class in the inheritance
|
||
|
chain needs an own serialVersionUID field. See also [Should an abstract class have a serialVersionUID](https://stackoverflow.com/questions/893259/should-an-abstract-class-have-a-serialversionuid).
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//ClassOrInterfaceDeclaration
|
||
|
[@Interface = 'false']
|
||
|
[count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
|
||
|
/FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0]
|
||
|
[(ImplementsList | ExtendsList)/ClassOrInterfaceType[pmd-java:typeIs('java.io.Serializable')]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo implements java.io.Serializable {
|
||
|
String name;
|
||
|
// Define serialization id to avoid serialization related bugs
|
||
|
// i.e., public static final long serialVersionUID = 4328743;
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="MissingStaticMethodInNonInstantiatableClass"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#missingstaticmethodinnoninstantiatableclass">
|
||
|
<description>
|
||
|
A class that has private constructors and does not have any static methods or fields cannot be used.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//ClassOrInterfaceDeclaration[@Nested='false']
|
||
|
[
|
||
|
(
|
||
|
./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration
|
||
|
and
|
||
|
count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) = count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private='true'])
|
||
|
)
|
||
|
and
|
||
|
not(.//MethodDeclaration[@Static='true'])
|
||
|
and
|
||
|
not(.//FieldDeclaration[@Private='false'][@Static='true'])
|
||
|
and
|
||
|
not(.//ClassOrInterfaceDeclaration[@Nested='true']
|
||
|
[@Public='true']
|
||
|
[@Static='true']
|
||
|
[not(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) or ./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Public='true']]
|
||
|
[./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration
|
||
|
[@Public='true']
|
||
|
[./ResultType/Type/ReferenceType/ClassOrInterfaceType
|
||
|
[@Image = //ClassOrInterfaceDeclaration[@Nested='false']/@Image]
|
||
|
]
|
||
|
]
|
||
|
)
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
// This class is unusable, since it cannot be
|
||
|
// instantiated (private constructor),
|
||
|
// and no static method can be called.
|
||
|
|
||
|
public class Foo {
|
||
|
private Foo() {}
|
||
|
void foo() {}
|
||
|
}
|
||
|
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="MoreThanOneLogger"
|
||
|
since="2.0"
|
||
|
message="Class contains more than one logger."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.MoreThanOneLoggerRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#morethanonelogger">
|
||
|
<description>
|
||
|
Normally only one logger is used in each class.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
Logger log = Logger.getLogger(Foo.class.getName());
|
||
|
// It is very rare to see two loggers on a class, normally
|
||
|
// log information is multiplexed by levels
|
||
|
Logger log2= Logger.getLogger(Foo.class.getName());
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="NonCaseLabelInSwitchStatement"
|
||
|
language="java"
|
||
|
since="1.5"
|
||
|
message="A non-case label was present in a switch statement"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#noncaselabelinswitchstatement">
|
||
|
<description>
|
||
|
A non-case label (e.g. a named break/continue label) was present in a switch statement.
|
||
|
This legal, but confusing. It is easy to mix up the case labels and the non-case labels.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//SwitchStatement//BlockStatement/Statement/LabeledStatement</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
void bar(int a) {
|
||
|
switch (a) {
|
||
|
case 1:
|
||
|
// do something
|
||
|
break;
|
||
|
mylabel: // this is legal, but confusing!
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="NonStaticInitializer"
|
||
|
language="java"
|
||
|
since="1.5"
|
||
|
message="Non-static initializers are confusing"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#nonstaticinitializer">
|
||
|
<description>
|
||
|
A non-static initializer block will be called any time a constructor is invoked (just prior to
|
||
|
invoking the constructor). While this is a valid language construct, it is rarely used and is
|
||
|
confusing.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//Initializer[@Static='false']
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class MyClass {
|
||
|
// this block gets run before any call to a constructor
|
||
|
{
|
||
|
System.out.println("I am about to construct myself");
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="NullAssignment"
|
||
|
since="1.02"
|
||
|
message="Assigning an Object to null is a code smell. Consider refactoring."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.NullAssignmentRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#nullassignment">
|
||
|
<description>
|
||
|
Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type
|
||
|
of assignment is an indication that the programmer doesn't completely understand what is going on in the code.
|
||
|
|
||
|
NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void bar() {
|
||
|
Object x = null; // this is OK
|
||
|
x = new Object();
|
||
|
// big, complex piece of code here
|
||
|
x = null; // this is not required
|
||
|
// big, complex piece of code here
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="OverrideBothEqualsAndHashcode"
|
||
|
language="java"
|
||
|
since="0.4"
|
||
|
message="Ensure you override both equals() and hashCode()"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.OverrideBothEqualsAndHashcodeRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#overridebothequalsandhashcode">
|
||
|
<description>
|
||
|
Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Bar { // poor, missing a hashcode() method
|
||
|
public boolean equals(Object o) {
|
||
|
// do some comparison
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Baz { // poor, missing an equals() method
|
||
|
public int hashCode() {
|
||
|
// return some hash value
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Foo { // perfect, both methods provided
|
||
|
public boolean equals(Object other) {
|
||
|
// do some comparison
|
||
|
}
|
||
|
public int hashCode() {
|
||
|
// return some hash value
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ProperCloneImplementation"
|
||
|
language="java"
|
||
|
since="1.4"
|
||
|
message="Object clone() should be implemented with super.clone()"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#propercloneimplementation">
|
||
|
<description>
|
||
|
Object clone() should be implemented with super.clone().
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclarator
|
||
|
[@Image = 'clone']
|
||
|
[count(FormalParameters/*) = 0]
|
||
|
[count(../Block//*[
|
||
|
(self::AllocationExpression) and
|
||
|
(./ClassOrInterfaceType/@Image = ancestor::
|
||
|
ClassOrInterfaceDeclaration[1]/@Image)
|
||
|
])> 0
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
class Foo{
|
||
|
public Object clone(){
|
||
|
return new Foo(); // This is bad
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ProperLogger"
|
||
|
language="java"
|
||
|
since="3.3"
|
||
|
message="Logger should be defined private static final and have the correct class"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#properlogger">
|
||
|
<description>
|
||
|
A logger should normally be defined private static final and be associated with the correct class.
|
||
|
Private final Log log; is also allowed for rare cases where loggers need to be passed around,
|
||
|
with the restriction that the logger needs to be passed into the constructor.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//ClassOrInterfaceBodyDeclaration[FieldDeclaration//ClassOrInterfaceType[@Image='Log']
|
||
|
and
|
||
|
not(FieldDeclaration[@Final='true'][@Static='true'][@Private='true'][.//VariableDeclaratorId[@Image=$staticLoggerName]]
|
||
|
and
|
||
|
//ArgumentList//ClassOrInterfaceType[@Image = ancestor::ClassOrInterfaceDeclaration/@Image or @Image = ancestor::EnumDeclaration/@Image])
|
||
|
and
|
||
|
not(FieldDeclaration[@Final='true'][@Private='true'][.//VariableDeclaratorId[@Image='log']]
|
||
|
[count(.//VariableInitializer)=0]
|
||
|
[ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image='log']][count(.//AllocationExpression)=0]]
|
||
|
)]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
<property name="staticLoggerName" type="String" description="Name of the static Logger variable" value="LOG"/>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
|
||
|
private static final Log LOG = LogFactory.getLog(Foo.class); // proper way
|
||
|
|
||
|
protected Log LOG = LogFactory.getLog(Testclass.class); // wrong approach
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ReturnEmptyArrayRatherThanNull"
|
||
|
language="java"
|
||
|
since="4.2"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
message="Return an empty array rather than 'null'."
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#returnemptyarrayratherthannull">
|
||
|
<description>
|
||
|
For any method that returns an array, it is a better to return an empty array rather than a
|
||
|
null reference. This removes the need for null checking all results and avoids inadvertent
|
||
|
NullPointerExceptions.
|
||
|
</description>
|
||
|
<priority>1</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclaration
|
||
|
[
|
||
|
(./ResultType/Type[@ArrayType='true'])
|
||
|
and
|
||
|
(./Block/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral)
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Example {
|
||
|
// Not a good idea...
|
||
|
public int[] badBehavior() {
|
||
|
// ...
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// Good behavior
|
||
|
public String[] bonnePratique() {
|
||
|
//...
|
||
|
return new String[0];
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="ReturnFromFinallyBlock"
|
||
|
language="java"
|
||
|
since="1.05"
|
||
|
message="Avoid returning from a finally block"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#returnfromfinallyblock">
|
||
|
<description>
|
||
|
Avoid returning from a finally block, this can discard exceptions.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="version" value="2.0"/>
|
||
|
<property name="xpath">
|
||
|
<value>//FinallyStatement//ReturnStatement except //FinallyStatement//(MethodDeclaration|LambdaExpression)//ReturnStatement</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Bar {
|
||
|
public String foo() {
|
||
|
try {
|
||
|
throw new Exception( "My Exception" );
|
||
|
} catch (Exception e) {
|
||
|
throw e;
|
||
|
} finally {
|
||
|
return "A. O. K."; // return not recommended here
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="SimpleDateFormatNeedsLocale"
|
||
|
language="java"
|
||
|
since="2.0"
|
||
|
message="When instantiating a SimpleDateFormat object, specify a Locale"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#simpledateformatneedslocale">
|
||
|
<description>
|
||
|
Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate
|
||
|
formatting is used.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//AllocationExpression
|
||
|
[ClassOrInterfaceType[@Image='SimpleDateFormat']]
|
||
|
[Arguments[@ArgumentCount=1]]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
// Should specify Locale.US (or whatever)
|
||
|
private SimpleDateFormat sdf = new SimpleDateFormat("pattern");
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="SingleMethodSingleton"
|
||
|
since="5.4"
|
||
|
message="Class contains multiple getInstance methods. Please review."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.SingleMethodSingletonRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#singlemethodsingleton">
|
||
|
<description>
|
||
|
Some classes contain overloaded getInstance. The problem with overloaded getInstance methods
|
||
|
is that the instance created using the overloaded method is not cached and so,
|
||
|
for each call and new objects will be created for every invocation.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Singleton {
|
||
|
|
||
|
private static Singleton singleton = new Singleton( );
|
||
|
|
||
|
private Singleton(){ }
|
||
|
|
||
|
public static Singleton getInstance( ) {
|
||
|
return singleton;
|
||
|
}
|
||
|
|
||
|
public static Singleton getInstance(Object obj){
|
||
|
Singleton singleton = (Singleton) obj;
|
||
|
return singleton; //violation
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="SingletonClassReturningNewInstance"
|
||
|
since="5.4"
|
||
|
message="getInstance method always creates a new object and hence does not comply to Singleton Design Pattern behaviour. Please review"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.SingletonClassReturningNewInstanceRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#singletonclassreturningnewinstance">
|
||
|
<description>
|
||
|
Some classes contain overloaded getInstance. The problem with overloaded getInstance methods
|
||
|
is that the instance created using the overloaded method is not cached and so,
|
||
|
for each call and new objects will be created for every invocation.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
class Singleton {
|
||
|
private static Singleton instance = null;
|
||
|
public static Singleton getInstance() {
|
||
|
synchronized(Singleton.class) {
|
||
|
return new Singleton();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="StaticEJBFieldShouldBeFinal"
|
||
|
language="java"
|
||
|
since="4.1"
|
||
|
message="EJB's shouldn't have non-final static fields"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#staticejbfieldshouldbefinal">
|
||
|
<description>
|
||
|
According to the J2EE specification, an EJB should not have any static fields
|
||
|
with write access. However, static read-only fields are allowed. This ensures proper
|
||
|
behavior especially when instances are distributed by the container on several JREs.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//ClassOrInterfaceDeclaration[
|
||
|
(
|
||
|
(./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'SessionBean')])
|
||
|
or
|
||
|
(./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBHome')])
|
||
|
or
|
||
|
(./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalObject')])
|
||
|
or
|
||
|
(./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalHome')])
|
||
|
or
|
||
|
(./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBObject')])
|
||
|
)
|
||
|
and
|
||
|
(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[
|
||
|
(./FieldDeclaration[@Static = 'true'])
|
||
|
and
|
||
|
(./FieldDeclaration[@Final = 'false'])
|
||
|
])
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class SomeEJB extends EJBObject implements EJBLocalHome {
|
||
|
|
||
|
private static int CountA; // poor, field can be edited
|
||
|
|
||
|
private static final int CountB; // preferred, read-only access
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="StringBufferInstantiationWithChar"
|
||
|
language="java"
|
||
|
since="3.9"
|
||
|
message="Do not instantiate a StringBuffer or StringBuilder with a char"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#stringbufferinstantiationwithchar">
|
||
|
<description>
|
||
|
Individual character values provided as initialization arguments will be converted into integers.
|
||
|
This can lead to internal buffer sizes that are larger than expected. Some examples:
|
||
|
|
||
|
```
|
||
|
new StringBuffer() // 16
|
||
|
new StringBuffer(6) // 6
|
||
|
new StringBuffer("hello world") // 11 + 16 = 27
|
||
|
new StringBuffer('A') // chr(A) = 65
|
||
|
new StringBuffer("A") // 1 + 16 = 17
|
||
|
|
||
|
new StringBuilder() // 16
|
||
|
new StringBuilder(6) // 6
|
||
|
new StringBuilder("hello world") // 11 + 16 = 27
|
||
|
new StringBuilder('C') // chr(C) = 67
|
||
|
new StringBuilder("A") // 1 + 16 = 17
|
||
|
```
|
||
|
</description>
|
||
|
<priority>4</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//AllocationExpression/ClassOrInterfaceType
|
||
|
[@Image='StringBuffer' or @Image='StringBuilder']
|
||
|
/../Arguments/ArgumentList/Expression/PrimaryExpression
|
||
|
/PrimaryPrefix/
|
||
|
Literal
|
||
|
[starts-with(@Image, "'")]
|
||
|
[ends-with(@Image, "'")]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
// misleading instantiation, these buffers
|
||
|
// are actually sized to 99 characters long
|
||
|
StringBuffer sb1 = new StringBuffer('c');
|
||
|
StringBuilder sb2 = new StringBuilder('c');
|
||
|
|
||
|
// in these forms, just single characters are allocated
|
||
|
StringBuffer sb3 = new StringBuffer("c");
|
||
|
StringBuilder sb4 = new StringBuilder("c");
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="SuspiciousEqualsMethodName"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#suspiciousequalsmethodname">
|
||
|
<description>
|
||
|
The method name and parameter number are suspiciously close to equals(Object), which can denote an
|
||
|
intention to override the equals(Object) method.
|
||
|
</description>
|
||
|
<priority>2</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//MethodDeclarator[@Image = 'equals']
|
||
|
[
|
||
|
(count(FormalParameters/*) = 1
|
||
|
and not (FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType
|
||
|
[@Image = 'Object' or @Image = 'java.lang.Object'])
|
||
|
or not (../ResultType/Type/PrimitiveType[@Image = 'boolean'])
|
||
|
) or (
|
||
|
count(FormalParameters/*) = 2
|
||
|
and ../ResultType/Type/PrimitiveType[@Image = 'boolean']
|
||
|
and FormalParameters//ClassOrInterfaceType[@Image = 'Object' or @Image = 'java.lang.Object']
|
||
|
and not(../../Annotation/MarkerAnnotation/Name[@Image='Override'])
|
||
|
)
|
||
|
]
|
||
|
| //MethodDeclarator[@Image = 'equal']
|
||
|
[
|
||
|
count(FormalParameters/*) = 1
|
||
|
and FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType
|
||
|
[@Image = 'Object' or @Image = 'java.lang.Object']
|
||
|
]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public int equals(Object o) {
|
||
|
// oops, this probably was supposed to be boolean equals
|
||
|
}
|
||
|
public boolean equals(String s) {
|
||
|
// oops, this probably was supposed to be equals(Object)
|
||
|
}
|
||
|
public boolean equals(Object o1, Object o2) {
|
||
|
// oops, this probably was supposed to be equals(Object)
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="SuspiciousHashcodeMethodName"
|
||
|
since="1.5"
|
||
|
message="The method name and return type are suspiciously close to hashCode()"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.SuspiciousHashcodeMethodNameRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#suspicioushashcodemethodname">
|
||
|
<description>
|
||
|
The method name and return type are suspiciously close to hashCode(), which may denote an intention
|
||
|
to override the hashCode() method.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public int hashcode() { // oops, this probably was supposed to be 'hashCode'
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="SuspiciousOctalEscape"
|
||
|
since="1.5"
|
||
|
message="Suspicious decimal characters following octal escape in string literal"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.SuspiciousOctalEscapeRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#suspiciousoctalescape">
|
||
|
<description>
|
||
|
A suspicious octal escape sequence was found inside a String literal.
|
||
|
The Java language specification (section 3.10.6) says an octal
|
||
|
escape sequence inside a literal String shall consist of a backslash
|
||
|
followed by:
|
||
|
|
||
|
OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit
|
||
|
|
||
|
Any octal escape sequence followed by non-octal digits can be confusing,
|
||
|
e.g. "\038" is interpreted as the octal escape sequence "\03" followed by
|
||
|
the literal character "8".
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public void foo() {
|
||
|
// interpreted as octal 12, followed by character '8'
|
||
|
System.out.println("suspicious: \128");
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="TestClassWithoutTestCases"
|
||
|
since="3.0"
|
||
|
message="This class name ends with 'Test' but contains no test cases"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.TestClassWithoutTestCasesRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#testclasswithouttestcases">
|
||
|
<description>
|
||
|
Test classes end with the suffix Test. Having a non-test class with that name is not a good practice,
|
||
|
since most people will assume it is a test case. Test classes have test methods named testXXX.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
//Consider changing the name of the class if it is not a test
|
||
|
//Consider adding test methods if it is a test
|
||
|
public class CarTest {
|
||
|
public static void main(String[] args) {
|
||
|
// do something
|
||
|
}
|
||
|
// code
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UnconditionalIfStatement"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unconditionalifstatement">
|
||
|
<description>
|
||
|
Do not use "if" statements whose conditionals are always true or always false.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//IfStatement/Expression
|
||
|
[count(PrimaryExpression)=1]
|
||
|
/PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
public void close() {
|
||
|
if (true) { // fixed conditional, not recommended
|
||
|
// ...
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UnnecessaryBooleanAssertion"
|
||
|
language="java"
|
||
|
since="3.0"
|
||
|
message="assertTrue(true) or similar statements are unnecessary"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
typeResolution="true"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unnecessarybooleanassertion">
|
||
|
<description>
|
||
|
A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing.
|
||
|
Consider using flow control (in case of assertTrue(false) or similar) or simply removing
|
||
|
statements like assertTrue(true) and assertFalse(false). If you just want a test to halt after finding
|
||
|
an error, use the fail() method and provide an indication message of why it did.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//StatementExpression
|
||
|
[
|
||
|
PrimaryExpression/PrimaryPrefix/Name[@Image='assertTrue' or @Image='assertFalse']
|
||
|
and
|
||
|
PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression
|
||
|
[PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
|
||
|
or
|
||
|
UnaryExpressionNotPlusMinus[@Image='!']
|
||
|
/PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]]
|
||
|
]
|
||
|
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeIs('junit.framework.TestCase')]
|
||
|
or //MarkerAnnotation/Name[
|
||
|
pmd-java:typeIs('org.junit.Test')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.api.Test') or pmd-java:typeIs('org.junit.jupiter.api.RepeatedTest')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.api.TestFactory') or pmd-java:typeIs('org.junit.jupiter.api.TestTemplate')
|
||
|
or pmd-java:typeIs('org.junit.jupiter.params.ParameterizedTest')
|
||
|
]
|
||
|
]]]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class SimpleTest extends TestCase {
|
||
|
public void testX() {
|
||
|
assertTrue(true); // serves no real purpose
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UnnecessaryCaseChange"
|
||
|
since="3.3"
|
||
|
message="Using equalsIgnoreCase() is cleaner than using toUpperCase/toLowerCase().equals()."
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.UnnecessaryCaseChangeRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unnecessarycasechange">
|
||
|
<description>
|
||
|
Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals()
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz.equalsIgnoreCase("baz")
|
||
|
|
||
|
boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unnecessary toUpperCase()
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UnnecessaryConversionTemporary"
|
||
|
since="0.1"
|
||
|
message="Avoid unnecessary temporaries when converting primitives to Strings"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.UnnecessaryConversionTemporaryRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unnecessaryconversiontemporary">
|
||
|
<description>
|
||
|
Avoid the use temporary objects when converting primitives to Strings. Use the static conversion methods
|
||
|
on the wrapper classes instead.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public String convert(int x) {
|
||
|
String foo = new Integer(x).toString(); // this wastes an object
|
||
|
|
||
|
return Integer.toString(x); // preferred approach
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UnusedNullCheckInEquals"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#unusednullcheckinequals">
|
||
|
<description>
|
||
|
After checking an object reference for null, you should invoke equals() on that object rather than passing it to another object's equals() method.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
(//PrimaryPrefix[ends-with(Name/@Image, '.equals') and Name/@Image != 'Arrays.equals'] | //PrimarySuffix[@Image='equals' and not(../PrimaryPrefix/Literal)])
|
||
|
/following-sibling::PrimarySuffix/Arguments/ArgumentList/Expression
|
||
|
/PrimaryExpression[count(PrimarySuffix)=0]/PrimaryPrefix
|
||
|
/Name[@Image = ./../../../../../../../../../../Expression/ConditionalAndExpression
|
||
|
/EqualityExpression[@Image="!=" and count(./preceding-sibling::*)=0 and
|
||
|
./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral]
|
||
|
/PrimaryExpression/PrimaryPrefix/Name/@Image]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Test {
|
||
|
|
||
|
public String method1() { return "ok";}
|
||
|
public String method2() { return null;}
|
||
|
|
||
|
public void method(String a) {
|
||
|
String b;
|
||
|
// I don't know it method1() can be "null"
|
||
|
// but I know "a" is not null..
|
||
|
// I'd better write a.equals(method1())
|
||
|
|
||
|
if (a!=null && method1().equals(a)) { // will trigger the rule
|
||
|
//whatever
|
||
|
}
|
||
|
|
||
|
if (method1().equals(a) && a != null) { // won't trigger the rule
|
||
|
//whatever
|
||
|
}
|
||
|
|
||
|
if (a!=null && method1().equals(b)) { // won't trigger the rule
|
||
|
//whatever
|
||
|
}
|
||
|
|
||
|
if (a!=null && "LITERAL".equals(a)) { // won't trigger the rule
|
||
|
//whatever
|
||
|
}
|
||
|
|
||
|
if (a!=null && !a.equals("go")) { // won't trigger the rule
|
||
|
a=method2();
|
||
|
if (method1().equals(a)) {
|
||
|
//whatever
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UseCorrectExceptionLogging"
|
||
|
language="java"
|
||
|
since="3.2"
|
||
|
message="Use the correct logging statement for logging exceptions"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#usecorrectexceptionlogging">
|
||
|
<description>
|
||
|
To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//CatchStatement/Block/BlockStatement/Statement/StatementExpression
|
||
|
/PrimaryExpression[PrimaryPrefix/Name[starts-with(@Image,
|
||
|
concat(ancestor::ClassOrInterfaceDeclaration/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration
|
||
|
[Type//ClassOrInterfaceType[@Image='Log']]
|
||
|
/VariableDeclarator/VariableDeclaratorId/@Image, '.'))]]
|
||
|
[PrimarySuffix/Arguments[@ArgumentCount='1']]
|
||
|
[PrimarySuffix/Arguments//Name/@Image = ancestor::CatchStatement/FormalParameter/VariableDeclaratorId/@Image]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Main {
|
||
|
private static final Log _LOG = LogFactory.getLog( Main.class );
|
||
|
void bar() {
|
||
|
try {
|
||
|
} catch( Exception e ) {
|
||
|
_LOG.error( e ); //Wrong!
|
||
|
} catch( OtherException oe ) {
|
||
|
_LOG.error( oe.getMessage(), oe ); //Correct
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UseEqualsToCompareStrings"
|
||
|
language="java"
|
||
|
since="4.1"
|
||
|
message="Use equals() to compare strings instead of ''=='' or ''!=''"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useequalstocomparestrings">
|
||
|
<description>
|
||
|
Using '==' or '!=' to compare strings only works if intern version is used on both sides.
|
||
|
Use the equals() method instead.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//EqualityExpression/PrimaryExpression
|
||
|
[(PrimaryPrefix/Literal
|
||
|
[starts-with(@Image, '"')]
|
||
|
[ends-with(@Image, '"')]
|
||
|
and count(PrimarySuffix) = 0)]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public boolean test(String s) {
|
||
|
if (s == "one") return true; // unreliable
|
||
|
if ("two".equals(s)) return true; // better
|
||
|
return false;
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UselessOperationOnImmutable"
|
||
|
since="3.5"
|
||
|
message="An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself"
|
||
|
class="net.sourceforge.pmd.lang.java.rule.errorprone.UselessOperationOnImmutableRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#uselessoperationonimmutable">
|
||
|
<description>
|
||
|
An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself
|
||
|
since the result of the operation is a new object. Therefore, ignoring the operation result is an error.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
import java.math.*;
|
||
|
|
||
|
class Test {
|
||
|
void method1() {
|
||
|
BigDecimal bd=new BigDecimal(10);
|
||
|
bd.add(new BigDecimal(5)); // this will trigger the rule
|
||
|
}
|
||
|
void method2() {
|
||
|
BigDecimal bd=new BigDecimal(10);
|
||
|
bd = bd.add(new BigDecimal(5)); // this won't trigger the rule
|
||
|
}
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UseLocaleWithCaseConversions"
|
||
|
language="java"
|
||
|
since="2.0"
|
||
|
message="When doing a String.toLowerCase()/toUpperCase() call, use a Locale"
|
||
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#uselocalewithcaseconversions">
|
||
|
<description>
|
||
|
When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that
|
||
|
have unusual conventions, i.e. Turkish.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>
|
||
|
<![CDATA[
|
||
|
//PrimaryExpression
|
||
|
[
|
||
|
PrimaryPrefix
|
||
|
[Name[ends-with(@Image, 'toLowerCase') or ends-with(@Image, 'toUpperCase')]]
|
||
|
[following-sibling::PrimarySuffix[position() = 1]/Arguments[@ArgumentCount=0]]
|
||
|
|
||
|
or
|
||
|
|
||
|
PrimarySuffix
|
||
|
[ends-with(@Image, 'toLowerCase') or ends-with(@Image, 'toUpperCase')]
|
||
|
[following-sibling::PrimarySuffix[position() = 1]/Arguments[@ArgumentCount=0]]
|
||
|
]
|
||
|
[not(PrimaryPrefix/Name[ends-with(@Image, 'toHexString')])]
|
||
|
]]>
|
||
|
</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
class Foo {
|
||
|
// BAD
|
||
|
if (x.toLowerCase().equals("list")) { }
|
||
|
|
||
|
/*
|
||
|
* This will not match "LIST" when in Turkish locale
|
||
|
* The above could be
|
||
|
* if (x.toLowerCase(Locale.US).equals("list")) { }
|
||
|
* or simply
|
||
|
* if (x.equalsIgnoreCase("list")) { }
|
||
|
*/
|
||
|
// GOOD
|
||
|
String z = a.toLowerCase(Locale.EN);
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
<rule name="UseProperClassLoader"
|
||
|
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"
|
||
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useproperclassloader">
|
||
|
<description>
|
||
|
In J2EE, the getClassLoader() method might not work as expected. Use
|
||
|
Thread.currentThread().getContextClassLoader() instead.
|
||
|
</description>
|
||
|
<priority>3</priority>
|
||
|
<properties>
|
||
|
<property name="xpath">
|
||
|
<value>//PrimarySuffix[@Image='getClassLoader']</value>
|
||
|
</property>
|
||
|
</properties>
|
||
|
<example>
|
||
|
<![CDATA[
|
||
|
public class Foo {
|
||
|
ClassLoader cl = Bar.class.getClassLoader();
|
||
|
}
|
||
|
]]>
|
||
|
</example>
|
||
|
</rule>
|
||
|
|
||
|
</ruleset>
|