diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md
index efbb83fb66..fe5d6673bd 100644
--- a/docs/pages/pmd/rules/java.md
+++ b/docs/pages/pmd/rules/java.md
@@ -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.
diff --git a/docs/pages/pmd/rules/java/errorprone.md b/docs/pages/pmd/rules/java/errorprone.md
index 4af46319b9..09b3874264 100644
--- a/docs/pages/pmd/rules/java/errorprone.md
+++ b/docs/pages/pmd/rules/java/errorprone.md
@@ -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)
diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml
index 2479508fbc..81a2ed49d2 100644
--- a/pmd-java/pom.xml
+++ b/pmd-java/pom.xml
@@ -4,6 +4,10 @@
pmd-java
PMD Java
+
+ 1.3.50
+
+
net.sourceforge.pmd
pmd
@@ -41,6 +45,32 @@
kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
org.jetbrains.kotlin
@@ -92,6 +122,20 @@
pmd-java-checkstyle-suppressions.xml
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+
@@ -143,6 +187,18 @@
slf4j-api
test
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.12.1
+ test
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.12.1
+ test
+
junit
junit
@@ -169,5 +225,16 @@
assertj-core
test
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin.version}
+ test
+
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java
index 6534669cba..9b08a58431 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidSlf4jMessageFormatRule.java
@@ -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 LOGGER_LEVELS;
- private static final String LOGGER_CLASS = "org.slf4j.Logger";
+ private static final Map> LOGGERS;
static {
- LOGGER_LEVELS = Collections
- .unmodifiableSet(new HashSet(Arrays.asList("trace", "debug", "info", "warn", "error")));
+ Map> loggersMap = new HashMap<>();
+
+ loggersMap.put("org.slf4j.Logger", Collections
+ .unmodifiableSet(new HashSet(Arrays.asList("trace", "debug", "info", "warn", "error"))));
+ loggersMap.put("org.apache.logging.log4j.Logger", Collections
+ .unmodifiableSet(new HashSet(Arrays.asList("trace", "debug", "info", "warn", "error", "fatal", "all"))));
+
+ LOGGERS = Collections
+ .unmodifiableMap(new HashMap>(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;
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/MoreThanOneLoggerRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/MoreThanOneLoggerRule.java
index 30e201509d..59cfc83362 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/MoreThanOneLoggerRule.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/MoreThanOneLoggerRule.java
@@ -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;
diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml
index 74e40ae08e..5dc4f6127b 100644
--- a/pmd-java/src/main/resources/category/java/errorprone.xml
+++ b/pmd-java/src/main/resources/category/java/errorprone.xml
@@ -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">
-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.
5
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml
index 486a1351fc..0c5162f38a 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidSlf4jMessageFormat.xml
@@ -375,6 +375,383 @@ public final class Main {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(LoggerHelper.class);
+ logger.info(pattern, 1, 2);
+ }
+ }
+ ]]>
+
+
+
+ 1
+ 9
+
+
+
+
+ 1
+ 9
+
+
+
+
+ 0
+
+
+
+
+ 0
+
+
+
+
+ Class cast exception with Method calls
+ 0
+
+
+
+
+ Null pointer with VariableNameDeclaration / VariableDeclaratorId
+ 0
+
+
+
+
+ Log4j2 NPE
+ 0
+
+
+
+
+ Log4j2: doesn't ignore exception param
+ 0
+
+
+
+
+ Log4j2: False positive with placeholder and exception
+ 0
+
+
+
+
+ Log4j2: fails with NPE
+ 0
+
+
+
+
+ Log4j2: false positive with pre-incremented variable
+ 0
+
+
+
+
+ NPE in PMD 5.8.1 Log4j2
+ 0
+
+
+
+
+ Log4j2 false positive: too many arguments with string concatenation operator
+ 0
+
+
+
+
+ NPE in static block (see #1512)
+ 0
+
+
+
+
+ missing argument in static block
+ 1
+ 8
+
+
+
+
+ NPE in lambda call (see #1512)
+ 0
+ list = someMethod(message -> logger.info(message));
+ }
+ ]]>
+
+
+
+ missing argument in lambda call
+ 1
+ 9
+ list = someMethod(message -> {
+ final String pattern = "log: {}";
+
+ logger.info(pattern, 1, 2);
+ });
+ }
+ ]]>
+
+
+
+ NPE in enums (see #1549)
+ 0
+
+
+
+
+ missing argument in enum
+ 1
+ 12
+
-
+
+ Add log4j2 Logger type
+ 0
+
+
+
+ Logger type log4j2: Two Loggers
+ 1
+
+
+
\ No newline at end of file