Issue #19717: Add input files for FinalLocalVariableCheck about initialization in adjacent catches#19728
Conversation
a5e4bb5 to
9351b67
Compare
|
Github, generate report for FinalLocalVariableCheck/all-examples-in-one |
|
Report for SimplifyBooleanExpression/all-examples-in-one: |
9351b67 to
7f85265
Compare
| <module name="LambdaBodyLength"/> | ||
| <module name="MethodCount"> | ||
| <property name="maxTotal" value="34"/> | ||
| <property name="maxTotal" value="35"/> |
There was a problem hiding this comment.
The value 34 was chosen exactly because this check had 34 methods and was the largest of all checks: (#4539 (comment))
I think it is reasonable to increase it as the updated version now has 35 methods.
There was a problem hiding this comment.
you can put permanent suppression on this Check + File to our suppression xml, there are already bunch like this.
We do not know how to design classes to be less big and same time easy to read and keep logic very close.
There was a problem hiding this comment.
done. I restored to 34 and added suppression
|
@romani PR ready for review. |
| public class InputFinalLocalVariableMultiCatch { | ||
| public void demo() throws Throwable { | ||
| // violation below, "Variable 'a' should be declared final" | ||
| int a; // assigned in adjacent catches |
There was a problem hiding this comment.
assigned in adjacent catches
assigned in nested catches
very hard to read such Inputs, yes, it is very comprehensive and compact, but it will not make it good in long run.
lets make them compact in formatting, but keep single variable to validate and right under correct form:
int u; // violation
try { } catch (IndexOutOfBoundsException e) { u = 9; }
final int u;
try { } catch (IndexOutOfBoundsException e) { u = 9; }
There was a problem hiding this comment.
That's true. I've completely separated each case into different try-catch blocks and added the correct version right under each violation.
|
Github, generate report for FinalLocalVariableCheck/all-examples-in-one |
|
Failed to download or process the specified configuration(s).
|
|
Github, generate report for FinalLocalVariable/all-examples-in-one |
|
Report for FinalLocalVariable/all-examples-in-one: |
|
@lithops-zty , small update please and we will merge |
7d6ce09 to
9eb5120
Compare
romani
left a comment
There was a problem hiding this comment.
Not clear why some violations are missed
|
|
||
| byte b; | ||
| try { | ||
| b = -1; |
There was a problem hiding this comment.
In this case b is assigned in both try and catch.
It is very hard to say whether assignment will happen only once in try, as we cannot determine syntactically if exceptions will be thrown.
In fact, java disallow final in this case:
(base) zty@zty:/mnt/d/IntellijProjects/checkstyle-playground/inputs/final-local-variable$ cat Test.java
public class Test {
public void test() {
final byte b;
try {
b = -1;
} catch (final NumberFormatException e) {
b = 0;
} catch (IllegalStateException | NullPointerException e) {
b = 0;
}
}
}(base) zty@zty:/mnt/d/IntellijProjects/checkstyle-playground/inputs/final-local-variable$ javac Test.java
Test.java:7: error: variable b might already have been assigned
b = 0;
^
Test.java:9: error: variable b might already have been assigned
b = 0;
^
2 errors
There was a problem hiding this comment.
ok, but why this violation:
int a; // violation, "Variable 'a' should be declared final"
try {
} catch (final NumberFormatException e) {
a = 0;
} catch (IllegalStateException | NullPointerException e) {
a = 1;
} catch (final IllegalArgumentException e) {
a = 2;
}
as if no exception happens, a is not initialized.
if this is defect of compiler, we should not put violation on this, as eventually it will be fixed in compiler.
Can you looks in jdk for defect on this? if not present you can create :)
There was a problem hiding this comment.
I am not sure if this is a defect, but Java allows uninitialized final variable declaration. However, such variables cannot be read later on and will lead to a compiling error:
(base) zty@zty:/mnt/d/IntellijProjects/checkstyle-playground/inputs/final-local-variable$ cat Test.java
public class Test {
public void test() {
final int a;
try {
} catch (final NumberFormatException e) {
a = 0;
} catch (IllegalStateException | NullPointerException e) {
a = 1;
} catch (final IllegalArgumentException e) {
a = 2;
}
int b = a;
}
}(base) zty@zty:/mnt/d/IntellijProjects/checkstyle-playground/inputs/final-local-variable$ javac Test.java
Test.java:12: error: variable a might not have been initialized
int b = a;
^
1 error
There was a problem hiding this comment.
Something tells me that we should not try to validate this at all, to much uncertainty, even compiler is not consistent.
9eb5120 to
1b50d59
Compare
|
I more and inclined to not do violations in such code. We would rather do less violations, to not produce false positives. False positives blocks builds and annoy a lot user. Missed violations are ok. Missed violations on crazy edges are ok. I recommend to remove functional changes and keep all test extension to make it clear we considered it but decided to not do. If we in agreement, I will change issue title |
|
Sorry for replying late. |
|
I don't see value. Let's in this PR remove all changes in check, and simply merge Inputs, and we can add some comment over variables that until compiler becomes strict, we should not place violation. And we can merge PR. Can you create issue over java compiler? In worse case they close it with explanation of reason, that is also good to know. |
|
No problem, I will remove all functional changes. However, I don't see a problem with the compiler, could you elaborate on the exact bug you mentioned? To me, the compiler works as I would expect in terms of allowing and disallowing
final byte b; // compile error
try {
b = -1;
} catch (final NumberFormatException e) {
b = 0;
}
final int a;
try {
} catch (final NumberFormatException e) {
a = 0;
} catch (IllegalStateException | NullPointerException e) {
a = 1;
}
|
Yes, we should not make violation on such code.
If exception is not happening, what value will have a variable? |
|
@romani Thanks for the insights. Now I see there is no value checking case 2 since such variable cannot be used at all despite successful compilation. I have pushed a new commit with only input files. |
1b50d59 to
d90977d
Compare
…bout initialization in adjacent catches
d90977d to
371009c
Compare
fixes: #19717
Fix false negative in
FinalLocalVariableCheckfor multi-catch blocks.Problem
When multiple
catchblocks each assign the same uninitialized variable, the variable should be reported as a candidate forfinalbecause only onecatchbranch can execute, so the variable is effectively assigned exactly once on every path. Currently, the check silently misses this case.Root Cause
Two methods in FinalLocalVariableCheck lack awareness of LITERAL_CATCH as a mutually-exclusive branch (analogous to LITERAL_ELSE for if-else and SWITCH_RULE for arrow-switch):
Fix