Fix for issue #336, introduce log4j 2 support as it can use the same rules as slf4j.

Note, one of the rules remains InvalidSlf4jMessageFormatRule, to make the rule more generic it would require a documentation change on sourceforge site.
This commit is contained in:
markhall82
2019-09-11 20:36:34 +01:00
parent 36d63429b4
commit a660f2cfcb
8 changed files with 490 additions and 13 deletions

View File

@ -254,7 +254,7 @@ folder: pmd/rules
* [IdempotentOperations](pmd_rules_java_errorprone.html#idempotentoperations): Avoid idempotent operations - they have no effect.
* [ImportFromSamePackage](pmd_rules_java_errorprone.html#importfromsamepackage): There is no need to import a type that lives in the same package.
* [InstantiationToGetClass](pmd_rules_java_errorprone.html#instantiationtogetclass): Avoid instantiating an object just to call getClass() on it; use the .class public member instead.
* [InvalidSlf4jMessageFormat](pmd_rules_java_errorprone.html#invalidslf4jmessageformat): Check for messages in slf4j loggers with non matching number of arguments and placeholders.
* [InvalidSlf4jMessageFormat](pmd_rules_java_errorprone.html#invalidslf4jmessageformat): Check for messages in slf4j and log4j2 loggers with non matching number of arguments and placehol...
* [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.
* [JUnitStaticSuite](pmd_rules_java_errorprone.html#junitstaticsuite): The suite() method in a JUnit test needs to be both public and static.

View File

@ -2278,7 +2278,7 @@ Class c = String.class;{%endraw%}
**Priority:** Low (5)
Check for messages in slf4j loggers with non matching number of arguments and placeholders.
Check for messages in slf4j and log4j2 loggers with non matching number of arguments and placeholders.
**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.errorprone.InvalidSlf4jMessageFormatRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java)

View File

@ -4,6 +4,10 @@
<artifactId>pmd-java</artifactId>
<name>PMD Java</name>
<properties>
<kotlin.version>1.3.50</kotlin.version>
</properties>
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
@ -41,6 +45,32 @@
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<source>src/test/java</source>
<source>src/test/kotlin</source>
</sourceDirs>
</configuration>
</execution>
</executions>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
<groupId>org.jetbrains.kotlin</groupId>
</plugin>
@ -92,6 +122,20 @@
<suppressionsLocation>pmd-java-checkstyle-suppressions.xml</suppressionsLocation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
@ -143,6 +187,18 @@
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.12.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@ -169,5 +225,16 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -7,8 +7,10 @@ package net.sourceforge.pmd.lang.java.rule.errorprone;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -43,12 +45,18 @@ import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule {
private static final Logger LOG = Logger.getLogger(InvalidSlf4jMessageFormatRule.class.getName());
private static final Set<String> LOGGER_LEVELS;
private static final String LOGGER_CLASS = "org.slf4j.Logger";
private static final Map<String, Set<String>> LOGGERS;
static {
LOGGER_LEVELS = Collections
.unmodifiableSet(new HashSet<String>(Arrays.asList("trace", "debug", "info", "warn", "error")));
Map<String, Set<String>> loggersMap = new HashMap<>();
loggersMap.put("org.slf4j.Logger", Collections
.unmodifiableSet(new HashSet<String>(Arrays.asList("trace", "debug", "info", "warn", "error"))));
loggersMap.put("org.apache.logging.log4j.Logger", Collections
.unmodifiableSet(new HashSet<String>(Arrays.asList("trace", "debug", "info", "warn", "error", "fatal", "all"))));
LOGGERS = Collections
.unmodifiableMap(new HashMap<String, Set<String>>(loggersMap));
}
public InvalidSlf4jMessageFormatRule() {
@ -62,11 +70,13 @@ public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule {
if (!(nameDeclaration instanceof VariableNameDeclaration)) {
return data;
}
// ignore non slf4j logger
final String loggingClass;
// ignore unsupported logger
Class<?> type = ((VariableNameDeclaration) nameDeclaration).getType();
if (type == null || !type.getName().equals(LOGGER_CLASS)) {
if (type == null || !LOGGERS.containsKey(type.getName())) {
return data;
} else {
loggingClass = type.getName();
}
// get the node that contains the logger
@ -77,7 +87,7 @@ public class InvalidSlf4jMessageFormatRule extends AbstractJavaRule {
.getImage().replace(nameDeclaration.getImage() + ".", "");
// ignore if not a log level
if (!LOGGER_LEVELS.contains(method)) {
if (!LOGGERS.get(loggingClass).contains(method)) {
return data;
}

View File

@ -22,6 +22,7 @@ import net.sourceforge.pmd.util.NumericConstants;
public class MoreThanOneLoggerRule extends AbstractJavaRule {
private static final String LOG4J_LOGGER_NAME = "org.apache.log4j.Logger";
private static final String LOG4J2_LOGGER_NAME = "org.apache.logging.log4j.Logger";
private static final String JAVA_LOGGER_NAME = "java.util.logging.Logger";
private static final String SLF4J_LOGGER_NAME = "org.slf4j.Logger";
@ -72,7 +73,8 @@ public class MoreThanOneLoggerRule extends AbstractJavaRule {
Class<?> clazzType = ((ASTClassOrInterfaceType) classOrIntType).getType();
if (clazzType != null
&& (TypeHelper.isA((ASTClassOrInterfaceType) classOrIntType, LOG4J_LOGGER_NAME)
|| TypeHelper.isA((ASTClassOrInterfaceType) classOrIntType, JAVA_LOGGER_NAME)
|| TypeHelper.isA((ASTClassOrInterfaceType) classOrIntType, LOG4J2_LOGGER_NAME)
|| TypeHelper.isA((ASTClassOrInterfaceType) classOrIntType, JAVA_LOGGER_NAME)
|| TypeHelper.isA((ASTClassOrInterfaceType) classOrIntType, SLF4J_LOGGER_NAME))
|| clazzType == null && "Logger".equals(classOrIntType.getImage())) {
++count;

View File

@ -2063,7 +2063,7 @@ Class c = String.class;
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.
Check for messages in slf4j and log4j2 loggers with non matching number of arguments and placeholders.
</description>
<priority>5</priority>
<example>

View File

@ -75,4 +75,25 @@ public class Foo {
}
]]></code>
</test-code>
</test-data>
<test-code>
<description>Add log4j2 Logger type</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.apache.logging.log4j.Logger;
public class Foo {
Logger log;
}
]]></code>
</test-code>
<test-code>
<description>Logger type log4j2: Two Loggers</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
import org.apache.logging.log4j.Logger;
public class Foo {
Logger log;
Logger log2;
}
]]></code>
</test-code>
</test-data>