New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[java] UnusedPrivateMethod - fix false positive with lambdas #4841
Conversation
.../src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateMethodRule.java
Outdated
Show resolved
Hide resolved
Generated by 🚫 Danger |
Ok, I've spent my whole Saturday juggling between the JLS and the code, but I think I'm starting to understand what the underlaying issue is… Running this in verbose mode, we get some clues. The code runs in loop through the different stages, but takes care to understand which are invocation runs and which are not… mostly! As it starts analyzing on the first STRICT phase looking for applicability of methods, it goes:
Effectively, an implicitly typed lambda expression isn't pertitent to applicability as per jls-15.12.2.2. Therefore, applicability is decided by simply checking wether the And so, the code performs a
So the inference moves, and it's now on invocation phase:
It set's the lambda's inferred type to a still partial type pmd/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java Lines 477 to 482 in 8cc2d29
Here is were things go south… as that inference bubbles up, we eventually get back to context 3 (the one being used in a
But in context 7 we actually set listeners for the resolution of And so, as the algorithm moves forward…
It sees the lambda actually expects a I'm not 100% sure yet, but I believe we need to split how This seems to be in compliance with the jls-18.5.2 where it reads:
I'll keep tinkering, but maybe this is enough for @oowekyala to know better… |
I did a very dirty test, and it seems to work… now I get this beautiful log without failures, and the FP is gone without changing the rule 🎉
I'll clean it up, check a full build, and hopefully update this PR with it. Interestingly, it is ~42% smaller, which hopefully also means this is actually faster, by avoiding several phases / runs by being more accurate… at least on this scenario. |
- This should fix some inference errors
- The inference now works for this case
pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/Infer.java
Outdated
Show resolved
Hide resolved
@jsotuyod Awesome! Thanks for digging into this! |
I had a look at the regression report now:
We could also declare these false positives as a separate issue. Maybe we should - they all seem to be static methods... I'll try to retest my test case for #4817 with the changes from here, to make sure, the original issue is indeed fixed (and the rule test case really works). |
@adangel good catch! I had completely missed that. And yes, there seems to be some issues with static methods, definitely worth having a separate issue to track and fix it regardless of wether we change the rule here or not. The case for #4817 is still part of this PR, the additional test cases for the rule are in here and they pass. Or did you have an additional scenario? |
A very preliminar look into the FP on openjdk shows that the node is null not because inference failed, but because, as those classes (ie: 3 possible ways around this would be:
|
I've tested it now (6.55.0 vs. 7.0.0-rc4 vs 7.0.0-SNAPSHOT) - and #4817 is still fixed. So we are good (just wanted to double check, as the regression tester didn't show any changes anymore). I'll create a separate issue for these static methods false positives now.... |
I'm going to merge this now. The original bug is fixed and there are no obvious side effects on other rules. In case we find a better/more correct solution, we can ship this improved code with the next version. |
Yeah fwiw I fiddled around with the code and I also think this is a good solution. I think there might still problems with how we type resolve lambdas but well... For now it's the best thing we have. Thanks Juan for implementing this and Andreas for taking care it is merged! |
Ready?
./mvnw clean verify
passes (checked automatically by github actions)