diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 4c44122915..b6e947ad79 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -36,6 +36,7 @@ the suppressions with a `NOPMD` comment. See [Suppressing warnings](pmd_userdocs * [#2277](https://github.com/pmd/pmd/issues/2277): \[java] FP in UnusedImports for ambiguous static on-demand imports * java-errorprone * [#2250](https://github.com/pmd/pmd/issues/2250): \[java] InvalidLogMessageFormat flags logging calls using a slf4j-Marker + * [#2255](https://github.com/pmd/pmd/issues/2255): \[java] InvalidLogMessageFormat false-positive for a lambda argument * java-performance * [#2275](https://github.com/pmd/pmd/issues/2275): \[java] AppendCharacterWithChar flags literals in an expression diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java index 46101bdff2..ad45ebb133 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java @@ -158,11 +158,32 @@ public class InvalidLogMessageFormatRule extends AbstractJavaRule { int lastIndex = params.size() - 1; ASTPrimaryExpression last = params.get(lastIndex).getFirstDescendantOfType(ASTPrimaryExpression.class); - if (isNewThrowable(last) || hasTypeThrowable(last) || isReferencingThrowable(last)) { + if (isNewThrowable(last) || hasTypeThrowable(last) || isReferencingThrowable(last) || isLambdaParameter(last)) { params.remove(lastIndex); } } + private boolean isLambdaParameter(ASTPrimaryExpression last) { + String varName = null; + ASTPrimaryPrefix prefix = last.getFirstChildOfType(ASTPrimaryPrefix.class); + if (prefix != null) { + ASTName name = prefix.getFirstChildOfType(ASTName.class); + if (name != null) { + varName = name.getImage(); + } + } + for (NameDeclaration decl : prefix.getScope().getDeclarations().keySet()) { + if (decl.getName().equals(varName)) { + if (decl.getNode().getParent() instanceof ASTLambdaExpression) { + // If the last parameter is a lambda parameter, then we also ignore it - regardless of the type. + // This is actually a workaround, since type resolution doesn't resolve the types of lambda parameters. + return true; + } + } + } + return false; + } + private String getExpectedMessage(final List params, final int expectedArguments) { return " expected " + expectedArguments + (expectedArguments > 1 ? " arguments " : " argument ") + "but have " + params.size(); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidLogMessageFormat.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidLogMessageFormat.xml index 8f0db82778..dd0b03c1b9 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidLogMessageFormat.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/InvalidLogMessageFormat.xml @@ -785,7 +785,7 @@ public class InvalidLogMessageFormatTest { - ignore slf4j-Markers when detecting the number of arguments + ignore slf4j-Markers when detecting the number of arguments #2250 2 11,17 + + + + [java] InvalidLogMessageFormat false-positive for a lambda argument #2255 + 0 + LOGGER.error("Foo", exception)); + } + + private static void foo(Consumer consumer) { + consumer.accept(new IllegalArgumentException()); + } +} + ]]> + + + + [java] InvalidLogMessageFormat false-negative for a lambda argument #2255 + 3 + 11,13,16 + LOGGER.error("Foo", arg)); // missing violation: extra argument, that is not a exception + // explicit cast helps type resolution + foo((String arg) -> LOGGER.error("Foo", arg)); // violation: extra argument, that is not a exception + foo((String arg) -> LOGGER.error("Foo {}", arg)); // no violation: correct number of arguments + foo(arg -> LOGGER.error("Foo {}", arg)); // no violation: correct number of arguments + foo(arg -> LOGGER.error("Foo {} {}", arg)); // violation: missing argument + } + + private static void foo(Consumer consumer) { + consumer.accept("bar"); + } } ]]>