ProperLogger - make class-name configurable and requirement of static-final logger (deprecate LoggerIsNotStaticFinal)

This commit is contained in:
Ivo Smid
2019-04-22 14:55:15 +02:00
parent 601a6be306
commit ccf99a4dc3
4 changed files with 199 additions and 67 deletions

View File

@ -255,7 +255,7 @@ folder: pmd/rules
* [JumbledIncrementer](pmd_rules_java_errorprone.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. * [JumbledIncrementer](pmd_rules_java_errorprone.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional.
* [JUnitSpelling](pmd_rules_java_errorprone.html#junitspelling): Some JUnit framework methods are easy to misspell. * [JUnitSpelling](pmd_rules_java_errorprone.html#junitspelling): Some JUnit framework methods are easy to misspell.
* [JUnitStaticSuite](pmd_rules_java_errorprone.html#junitstaticsuite): The suite() method in a JUnit test needs to be both public and static. * [JUnitStaticSuite](pmd_rules_java_errorprone.html#junitstaticsuite): The suite() method in a JUnit test needs to be both public and static.
* [LoggerIsNotStaticFinal](pmd_rules_java_errorprone.html#loggerisnotstaticfinal): In most cases, the Logger reference can be declared as static and final. * [LoggerIsNotStaticFinal](pmd_rules_java_errorprone.html#loggerisnotstaticfinal): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> In most cases, the Logger reference can be declared as static and final. This rule is deprecated. ...
* [MethodWithSameNameAsEnclosingClass](pmd_rules_java_errorprone.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class. * [MethodWithSameNameAsEnclosingClass](pmd_rules_java_errorprone.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class.
* [MisplacedNullCheck](pmd_rules_java_errorprone.html#misplacednullcheck): The null check here is misplaced. If the variable is null a NullPointerException will be thrown.E... * [MisplacedNullCheck](pmd_rules_java_errorprone.html#misplacednullcheck): The null check here is misplaced. If the variable is null a NullPointerException will be thrown.E...
* [MissingBreakInSwitch](pmd_rules_java_errorprone.html#missingbreakinswitch): Switch statements without break or return statements for each case optionmay indicate problematic... * [MissingBreakInSwitch](pmd_rules_java_errorprone.html#missingbreakinswitch): Switch statements without break or return statements for each case optionmay indicate problematic...

View File

@ -245,7 +245,7 @@ for (int i = 0; i < 10; i++) {
The method Object.finalize() is called by the garbage collector on an object when garbage collection determines 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. 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. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCallingFinalizeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidCallingFinalizeRule.java) **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCallingFinalizeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidCallingFinalizeRule.java)
@ -270,7 +270,7 @@ void foo() {
**Priority:** Medium (3) **Priority:** Medium (3)
Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the
original error, causing other, more subtle problems later on. original error, causing other, more subtle problems later on.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**
@ -303,7 +303,7 @@ public class Foo {
**Priority:** Medium (3) **Priority:** Medium (3)
Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as 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. OutOfMemoryError that should be exposed and managed separately.
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCatchingThrowableRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidCatchingThrowableRule.java) **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCatchingThrowableRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidCatchingThrowableRule.java)
@ -464,8 +464,8 @@ public class A {
**Priority:** Medium (3) **Priority:** Medium (3)
It can be confusing to have a field name with the same name as a method. While this is permitted, 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 having information (field) and actions (method) is not clear naming. Developers versed in
Smalltalk often prefer this approach as the methods denote accessor methods. Smalltalk often prefer this approach as the methods denote accessor methods.
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingMethodNameRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidFieldNameMatchingMethodNameRule.java) **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingMethodNameRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidFieldNameMatchingMethodNameRule.java)
@ -764,9 +764,9 @@ boolean x = (y == Double.NaN);
**Priority:** Medium (3) **Priority:** Medium (3)
If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializable. 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 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 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. naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided.
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.BeanMembersShouldSerializeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BeanMembersShouldSerializeRule.java) **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.BeanMembersShouldSerializeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BeanMembersShouldSerializeRule.java)
@ -1527,7 +1527,7 @@ public class MyActivity extends Activity {
**Priority:** Medium Low (4) **Priority:** Medium Low (4)
Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions
or code defects. or code defects.
Note: This is a PMD implementation of the Lint4j rule &quot;A throw in a finally block&quot; Note: This is a PMD implementation of the Lint4j rule &quot;A throw in a finally block&quot;
@ -1623,8 +1623,8 @@ public class Count {
**Priority:** Medium (3) **Priority:** Medium (3)
Empty Catch Block finds instances where an exception is caught, but nothing is done. 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 In most circumstances, this swallows an exception which should either be acted on
or reported. or reported.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**
@ -1830,7 +1830,7 @@ public class Foo {
**Priority:** Medium (3) **Priority:** Medium (3)
An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' 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 or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose
and should be removed. and should be removed.
@ -1961,7 +1961,7 @@ public class Foo {
**Priority:** Medium (3) **Priority:** Medium (3)
Empty While Statement finds all instances where a while statement does nothing. 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 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. a while loop that does a lot in the exit expression, rewrite it to make it clearer.
@ -2109,7 +2109,7 @@ protected void finalize() {
Methods named finalize() should not have parameters. It is confusing and most likely an attempt to 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. overload Object.finalize(). It will not be called by the VM.
Note that Oracle has declared Object.finalize() as deprecated since JDK 9. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**
@ -2139,9 +2139,9 @@ public class Foo {
**Priority:** Medium (3) **Priority:** Medium (3)
When overriding the finalize(), the new method should be set as protected. If made public, When overriding the finalize(), the new method should be set as protected. If made public,
other classes may invoke it at inappropriate times. other classes may invoke it at inappropriate times.
Note that Oracle has declared Object.finalize() as deprecated since JDK 9. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**
@ -2391,12 +2391,16 @@ public class Foo extends TestCase {
## LoggerIsNotStaticFinal ## LoggerIsNotStaticFinal
<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span>
**Since:** PMD 2.0 **Since:** PMD 2.0
**Priority:** Medium High (2) **Priority:** Medium High (2)
In most cases, the Logger reference can be declared as static and final. In most cases, the Logger reference can be declared as static and final.
This rule is deprecated. The rule is replaced by {% rule java/errorprone/ProperLogger %}.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**
``` xpath ``` xpath
//VariableDeclarator //VariableDeclarator
@ -2850,16 +2854,26 @@ with the restriction that the logger needs to be passed into the constructor.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**
``` xpath ``` xpath
//ClassOrInterfaceBodyDeclaration[FieldDeclaration//ClassOrInterfaceType[@Image='Log'] //ClassOrInterfaceBodyDeclaration[
and FieldDeclaration//ClassOrInterfaceType[pmd-java:typeIs($loggerClass)]
not(FieldDeclaration[@Final='true'][@Static='true'][@Private='true'][.//VariableDeclaratorId[@Image=$staticLoggerName]] and not (
and (: check logger name :)
//ArgumentList//ClassOrInterfaceType[@Image = ancestor::ClassOrInterfaceDeclaration/@Image or @Image = ancestor::EnumDeclaration/@Image]) (
and FieldDeclaration[$requireStaticFinalLogger][@Final=true()][@Static=true()][.//VariableDeclaratorId[@Image=$loggerName or @Image=$staticLoggerName]]
not(FieldDeclaration[@Final='true'][@Private='true'][.//VariableDeclaratorId[@Image='log']] |
[count(.//VariableInitializer)=0] FieldDeclaration[$requireStaticFinalLogger = false()][.//VariableDeclaratorId[@Image=$loggerName or @Image=$staticLoggerName]]
[ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image='log']][count(.//AllocationExpression)=0]] )
)] and
(: in place initialization with method argument pointing to current class (even for Enums) :)
.//ArgumentList//ClassOrInterfaceType[@Image = ancestor::ClassOrInterfaceDeclaration/@Image or @Image = ancestor::EnumDeclaration/@Image]
)
and not (
(: final logger initialized inside constructor :)
FieldDeclaration[@Final=true()][@Private=true()][.//VariableDeclaratorId[@Image=$loggerName or @Image=$staticLoggerName]]
[count(.//VariableInitializer)=0]
[ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image=$loggerName or @Image=$staticLoggerName]][count(.//AllocationExpression)=0]]
)
]
``` ```
**Example(s):** **Example(s):**
@ -2877,7 +2891,10 @@ public class Foo {
|Name|Default Value|Description|Multivalued| |Name|Default Value|Description|Multivalued|
|----|-------------|-----------|-----------| |----|-------------|-----------|-----------|
|staticLoggerName|LOG|Name of the static Logger variable|no| |staticLoggerName|LOG|<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> (Use 'loggerName' property) Name of the static Logger variable|no|
|loggerName|LOG|Name of the Logger variable|no|
|loggerClass|Log|Class name of the logger|no|
|requireStaticFinalLogger|false|Static final logger is required|no|
**Use this rule with the default properties by just referencing it:** **Use this rule with the default properties by just referencing it:**
``` xml ``` xml
@ -2888,7 +2905,9 @@ public class Foo {
``` xml ``` xml
<rule ref="category/java/errorprone.xml/ProperLogger"> <rule ref="category/java/errorprone.xml/ProperLogger">
<properties> <properties>
<property name="staticLoggerName" value="LOG" /> <property name="loggerName" value="LOG" />
<property name="loggerClass" value="Log" />
<property name="requireStaticFinalLogger" value="false" />
</properties> </properties>
</rule> </rule>
``` ```
@ -3130,7 +3149,7 @@ new StringBuffer() // 16
new StringBuffer(6) // 6 new StringBuffer(6) // 6
new StringBuffer("hello world") // 11 + 16 = 27 new StringBuffer("hello world") // 11 + 16 = 27
new StringBuffer('A') // chr(A) = 65 new StringBuffer('A') // chr(A) = 65
new StringBuffer("A") // 1 + 16 = 17 new StringBuffer("A") // 1 + 16 = 17
new StringBuilder() // 16 new StringBuilder() // 16
new StringBuilder(6) // 6 new StringBuilder(6) // 6
@ -3285,7 +3304,7 @@ public void foo() {
**Priority:** Medium (3) **Priority:** Medium (3)
Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, 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. since most people will assume it is a test case. Test classes have test methods named testXXX.
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.TestClassWithoutTestCasesRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/TestClassWithoutTestCasesRule.java) **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.TestClassWithoutTestCasesRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/TestClassWithoutTestCasesRule.java)
@ -3663,7 +3682,7 @@ class Foo {
**Priority:** Medium (3) **Priority:** Medium (3)
In J2EE, the getClassLoader() method might not work as expected. Use In J2EE, the getClassLoader() method might not work as expected. Use
Thread.currentThread().getContextClassLoader() instead. Thread.currentThread().getContextClassLoader() instead.
**This rule is defined by the following XPath expression:** **This rule is defined by the following XPath expression:**

View File

@ -190,7 +190,7 @@ for (int i = 0; i < 10; i++) {
<description> <description>
The method Object.finalize() is called by the garbage collector on an object when garbage collection determines 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. 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. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -211,7 +211,7 @@ void foo() {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingnpe"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingnpe">
<description> <description>
Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the
original error, causing other, more subtle problems later on. original error, causing other, more subtle problems later on.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -245,7 +245,7 @@ public class Foo {
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCatchingThrowableRule" class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidCatchingThrowableRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingthrowable"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidcatchingthrowable">
<description> <description>
Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as 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. OutOfMemoryError that should be exposed and managed separately.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -372,8 +372,8 @@ public class A {
class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingMethodNameRule" class="net.sourceforge.pmd.lang.java.rule.errorprone.AvoidFieldNameMatchingMethodNameRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidfieldnamematchingmethodname"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidfieldnamematchingmethodname">
<description> <description>
It can be confusing to have a field name with the same name as a method. While this is permitted, 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 having information (field) and actions (method) is not clear naming. Developers versed in
Smalltalk often prefer this approach as the methods denote accessor methods. Smalltalk often prefer this approach as the methods denote accessor methods.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -634,9 +634,9 @@ boolean x = (y == Double.NaN);
class="net.sourceforge.pmd.lang.java.rule.errorprone.BeanMembersShouldSerializeRule" class="net.sourceforge.pmd.lang.java.rule.errorprone.BeanMembersShouldSerializeRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#beanmembersshouldserialize"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#beanmembersshouldserialize">
<description> <description>
If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializable. 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 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 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. naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -1324,7 +1324,7 @@ public class MyActivity extends Activity {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotthrowexceptioninfinally"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#donotthrowexceptioninfinally">
<description> <description>
Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions
or code defects. or code defects.
Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block" Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block"
</description> </description>
@ -1415,8 +1415,8 @@ public class Count {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptycatchblock"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptycatchblock">
<description> <description>
Empty Catch Block finds instances where an exception is caught, but nothing is done. 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 In most circumstances, this swallows an exception which should either be acted on
or reported. or reported.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -1611,7 +1611,7 @@ public class Foo {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptystatementnotinloop"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptystatementnotinloop">
<description> <description>
An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' 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 or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose
and should be removed. and should be removed.
</description> </description>
@ -1742,7 +1742,7 @@ public class Foo {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptywhilestmt"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#emptywhilestmt">
<description> <description>
Empty While Statement finds all instances where a while statement does nothing. 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 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. a while loop that does a lot in the exit expression, rewrite it to make it clearer.
</description> </description>
@ -1900,7 +1900,7 @@ protected void finalize() {
<description> <description>
Methods named finalize() should not have parameters. It is confusing and most likely an attempt to 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. overload Object.finalize(). It will not be called by the VM.
Note that Oracle has declared Object.finalize() as deprecated since JDK 9. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -1932,9 +1932,9 @@ public class Foo {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeshouldbeprotected"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#finalizeshouldbeprotected">
<description> <description>
When overriding the finalize(), the new method should be set as protected. If made public, When overriding the finalize(), the new method should be set as protected. If made public,
other classes may invoke it at inappropriate times. other classes may invoke it at inappropriate times.
Note that Oracle has declared Object.finalize() as deprecated since JDK 9. Note that Oracle has declared Object.finalize() as deprecated since JDK 9.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -2180,9 +2180,12 @@ public class Foo extends TestCase {
since="2.0" since="2.0"
message="The Logger variable declaration does not contain the static and final modifiers" message="The Logger variable declaration does not contain the static and final modifiers"
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#loggerisnotstaticfinal"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#loggerisnotstaticfinal"
deprecated="true">
<description> <description>
In most cases, the Logger reference can be declared as static and final. In most cases, the Logger reference can be declared as static and final.
This rule is deprecated. The rule is replaced by {% rule java/errorprone/ProperLogger %}.
</description> </description>
<priority>2</priority> <priority>2</priority>
<properties> <properties>
@ -2625,7 +2628,8 @@ class Foo{
since="3.3" since="3.3"
message="Logger should be defined private static final and have the correct class" message="Logger should be defined private static final and have the correct class"
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#properlogger"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#properlogger"
typeResolution="true">
<description> <description>
A logger should normally be defined private static final and be associated with the correct class. 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, Private final Log log; is also allowed for rare cases where loggers need to be passed around,
@ -2633,23 +2637,37 @@ with the restriction that the logger needs to be passed into the constructor.
</description> </description>
<priority>3</priority> <priority>3</priority>
<properties> <properties>
<property name="version" value="2.0"/>
<property name="xpath"> <property name="xpath">
<value> <value>
<![CDATA[ <![CDATA[
//ClassOrInterfaceBodyDeclaration[FieldDeclaration//ClassOrInterfaceType[@Image='Log'] //ClassOrInterfaceBodyDeclaration[
and FieldDeclaration//ClassOrInterfaceType[pmd-java:typeIs($loggerClass)]
not(FieldDeclaration[@Final='true'][@Static='true'][@Private='true'][.//VariableDeclaratorId[@Image=$staticLoggerName]] and not (
and (: check logger name :)
//ArgumentList//ClassOrInterfaceType[@Image = ancestor::ClassOrInterfaceDeclaration/@Image or @Image = ancestor::EnumDeclaration/@Image]) (
and FieldDeclaration[$requireStaticFinalLogger][@Final=true()][@Static=true()][.//VariableDeclaratorId[@Image=$loggerName or @Image=$staticLoggerName]]
not(FieldDeclaration[@Final='true'][@Private='true'][.//VariableDeclaratorId[@Image='log']] |
[count(.//VariableInitializer)=0] FieldDeclaration[$requireStaticFinalLogger = false()][.//VariableDeclaratorId[@Image=$loggerName or @Image=$staticLoggerName]]
[ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image='log']][count(.//AllocationExpression)=0]] )
)] and
(: in place initialization with method argument pointing to current class (even for Enums) :)
.//ArgumentList//ClassOrInterfaceType[@Image = ancestor::ClassOrInterfaceDeclaration/@Image or @Image = ancestor::EnumDeclaration/@Image]
)
and not (
(: final logger initialized inside constructor :)
FieldDeclaration[@Final=true()][@Private=true()][.//VariableDeclaratorId[@Image=$loggerName or @Image=$staticLoggerName]]
[count(.//VariableInitializer)=0]
[ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image=$loggerName or @Image=$staticLoggerName]][count(.//AllocationExpression)=0]]
)
]
]]> ]]>
</value> </value>
</property> </property>
<property name="staticLoggerName" type="String" description="Name of the static Logger variable" value="LOG"/> <property name="staticLoggerName" type="String" description="deprecated!(Use 'loggerName' property) Name of the static Logger variable" value="LOG"/>
<property name="loggerName" type="String" description="Name of the Logger variable" value="LOG"/>
<property name="loggerClass" type="String" description="Class name of the logger" value="Log"/>
<property name="requireStaticFinalLogger" type="Boolean" description="Static final logger is required" value="false"/>
</properties> </properties>
<example> <example>
<![CDATA[ <![CDATA[
@ -2896,7 +2914,7 @@ new StringBuffer() // 16
new StringBuffer(6) // 6 new StringBuffer(6) // 6
new StringBuffer("hello world") // 11 + 16 = 27 new StringBuffer("hello world") // 11 + 16 = 27
new StringBuffer('A') // chr(A) = 65 new StringBuffer('A') // chr(A) = 65
new StringBuffer("A") // 1 + 16 = 17 new StringBuffer("A") // 1 + 16 = 17
new StringBuilder() // 16 new StringBuilder() // 16
new StringBuilder(6) // 6 new StringBuilder(6) // 6
@ -3044,7 +3062,7 @@ public void foo() {
class="net.sourceforge.pmd.lang.java.rule.errorprone.TestClassWithoutTestCasesRule" class="net.sourceforge.pmd.lang.java.rule.errorprone.TestClassWithoutTestCasesRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#testclasswithouttestcases"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#testclasswithouttestcases">
<description> <description>
Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, 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. since most people will assume it is a test case. Test classes have test methods named testXXX.
</description> </description>
<priority>3</priority> <priority>3</priority>
@ -3415,7 +3433,7 @@ class Foo {
class="net.sourceforge.pmd.lang.rule.XPathRule" class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useproperclassloader"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useproperclassloader">
<description> <description>
In J2EE, the getClassLoader() method might not work as expected. Use In J2EE, the getClassLoader() method might not work as expected. Use
Thread.currentThread().getContextClassLoader() instead. Thread.currentThread().getContextClassLoader() instead.
</description> </description>
<priority>3</priority> <priority>3</priority>

View File

@ -29,6 +29,7 @@ public class Foo {
<description><![CDATA[ <description><![CDATA[
Ok, special case Ok, special case
]]></description> ]]></description>
<rule-property name="loggerName">log</rule-property>
<expected-problems>0</expected-problems> <expected-problems>0</expected-problems>
<code><![CDATA[ <code><![CDATA[
public class Foo { public class Foo {
@ -55,18 +56,19 @@ public enum Foo {
<description><![CDATA[ <description><![CDATA[
bug 1626232, a separate variable initialization should not confuse the rule bug 1626232, a separate variable initialization should not confuse the rule
]]></description> ]]></description>
<rule-property name="loggerName">log</rule-property>
<expected-problems>0</expected-problems> <expected-problems>0</expected-problems>
<code><![CDATA[ <code><![CDATA[
public class Foo { public class Foo {
private String bar = ""; private String bar = "";
private final Log log; private final Log log;
Foo(Log log) { Foo(Log log1) {
this.log = log; this.log = log1;
} }
} }
]]> </code> ]]> </code>
</test-code> </test-code>
<test-code> <test-code>
<description><![CDATA[ <description><![CDATA[
Enums shoud be accepted for declaration Enums shoud be accepted for declaration
]]></description> ]]></description>
@ -87,6 +89,99 @@ bug 1626232, extra loggers with different names are not allowed by default (use
public class Foo { public class Foo {
private static final Log LOG = LogFactory.getLog(Foo.class); private static final Log LOG = LogFactory.getLog(Foo.class);
private static final Log LOG2 = LogFactory.getLog(Foo.class + ".foo"); private static final Log LOG2 = LogFactory.getLog(Foo.class + ".foo");
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Custom logger-class with invalid logger variable name
]]></description>
<rule-property name="loggerClass">MyLog</rule-property>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
private static final MyLog INVALID_LOG_NAME = LogFactory.getLog(Foo.class);
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Public logger
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public static final Log LOG = LogFactory.getLog(Foo.class);
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Public logger when static final required
]]></description>
<rule-property name="requireStaticFinalLogger">true</rule-property>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public static final Log LOG = LogFactory.getLog(Foo.class);
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Logger initialized as String constant from class name
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
Log LOG = LogFactory.getLog(Foo.class.getName());
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Package-protected logger when static final is not required
]]></description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
Log LOG = LogFactory.getLog(Foo.class);
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Package-protected logger when static final is required
]]></description>
<rule-property name="requireStaticFinalLogger">true</rule-property>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
Log LOG = LogFactory.getLog(Foo.class);
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Check type resolution of logger
]]></description>
<rule-property name="loggerClass">org.slf4j.Logger</rule-property>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(Foo.class);
}
]]> </code>
</test-code>
<test-code>
<description><![CDATA[
Check type resolution of logger with invalid logger specified
]]></description>
<rule-property name="loggerClass">org.slf4j.Logger</rule-property>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(Bar.class);
} }
]]> </code> ]]> </code>
</test-code> </test-code>