False Negative: LambdaParameterName silently passes lambdas in switch rule
I have read check documentation: https://checkstyle.org/checks/naming/lambdaparametername.html I have downloaded the latest checkstyle from: https://checkstyle.org/cmdline.html#Download_and_Run I have executed the cli and showed it below, as cli describes the problem better than 1,000 words
/var/tmp $ javac RuleValueLambda.java
/var/tmp $ cat config.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="TreeWalker">
<module name="LambdaParameterName"/>
</module>
</module>
/var/tmp $ cat RuleValueLambda.java
import java.util.function.Function;
public class RuleValueLambda {
Function<String, String> atRuleValue(int x) {
return switch (x) {
case 1 -> Word -> Word.trim(); // should be flagged, but is NOT
default -> w -> w.trim();
};
}
Function<String, String> outsideSwitchRule = Word -> Word.trim(); // flagged
}
/var/tmp $ RUN_LOCALE="-Duser.language=en -Duser.country=US"
/var/tmp $ java $RUN_LOCALE -jar checkstyle-14.1.0-all.jar -c config.xml RuleValueLambda.java
Starting audit..
[ERROR] /var/tmp/RuleValueLambda.java:11:50: Name 'Word' must match pattern '^([a-z][a-zA-Z0-9]*|_)$'. [LambdaParameterName]
Audit done.
Checkstyle ends with 1 errors.Describe what you expect in detail.
Lambdas as the branch value of switch rules should be checked but are not.
There are two types of LAMBDA nodes in AST:
- 'real'
->that defines a lambda, e.g.(a, b) -> a + b - 'fake'
->in a switch rule, e.g.switch(a) { case 1 -> b;}
Checks targeting lambdas should filter out the second type when checking LAMBDA nodes. However, the most obvious filtering logic is erroneous:
Wrong
final boolean isRealLambda = lambda.getParent().getType() != TokenTypes.SWITCH_RULE;This mistakenly filters out real lambdas, as in the given breaking example above, both real and fake arrows are direct children of SWITCH_RULE:
|--SWITCH_RULE -> SWITCH_RULE [8:13]
| | `--EXPR -> EXPR [8:18]
| |--LAMBDA -> -> [8:20] // fake switch-rule arrow, should be filtered
| |--LAMBDA -> -> [8:28] // real lambda arrow, should not be filtered
| | |--IDENT -> Word [8:23]
| | `--EXPR -> EXPR [8:40]
...The correct filtering implementation is to simply check the presence of children, because it has been empirically proven that a LAMBDA is a real lambda arrow if and only if it has at least one child. (see https://github.com/checkstyle/checkstyle/pull/21540#pullrequestreview-5166211027)
Correct
final boolean isRealLambda= lambda.hasChildren();I've identified four checks that fall for this trap:
- ExpressionOverBlockLambda (#21515)
- NeedBraces (#21579)
- LambdaParameterName (this issue)
- LambdaBodyLengthCheck
Considering the fact that filtering real lambdas is prone to mistakes, should we implement a single source of truth somewhere in the util files?
Source: checkstyle/checkstyle