child of #14942
Check doc: https://checkstyle.org/checks/coding/unusedlocalvariable.html#UnusedLocalVariable
From Check Description :
Checks that a local variable is declared and/or assigned, but not used. Doesn't support pattern variables yet
We should extend UnusedLocalVariable to support pattern variables. The unused pattern variables should be unnamed patterns or unnamed pattern variables. This Improves the readability of record patterns by eliding unnecessary nested type patterns. The main goal is to ensure that unused pattern variables are detected and violated, prompting developers to either use them or declare them as unnamed variables.
To be clear a pattern is a local variable.
Reference: https://docs.oracle.com/javase/specs/jls/se17/html/jls-14.html#jls-14.30:~:text=A%20local%20variable%20declaration%20can%20appear%20in%20the%20following%20locations%3A
A local variable declaration can appear in the following locations:
- a local variable declaration statement in a block (§14.4.2)
- the resource specification of a try-with-resources statement (§14.20.3)
Examples of expected behaviour when we add support for pattern variables
- Switch and case labels
sealed abstract class Ball permits RedBall, GreenBall { }
final class RedBall extends Ball { }
final class GreenBall extends Ball { }
record Box<T extends Ball>(T content) { }
public class Test {
public void PatternVariableInCaseLabels(Ball ball) {
switch (ball) {
case RedBall redBall -> process(ball); // expected violation, unused variable 'redBall'
case GreenBall greenBall -> stopProcessing(ball); // expected violation, unused variable 'greenBall'
}
// after fix
switch (ball) {
case RedBall _ -> process(ball);
case GreenBall _ -> stopProcessing(ball);
}
}
public void PatternVariableRecordPatternCaseLabels(Box<? extends Ball> box) {
switch (box) {
case Box(RedBall redBall) -> process(box); // expected violation, unused variable 'redBall'
case Box(GreenBall greenBall) -> stopProcessing(box); // expected violation, unused variable 'greenBall'
}
switch (box) {
case Box(RedBall _) -> process(box);
case Box(GreenBall _) -> stopProcessing(box);
}
}
void process(Object obj) {}
void stopProcessing(Object obj) {}
}
<!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="UnusedLocalVariable"/>
</module>
</module>
PS D:\CS\test> java -jar checkstyle-10.17.0-all.jar -c config.xml src/Test.java
Starting audit...
Audit done.
PS D:\CS\test>
- Contitional Statments
sealed abstract class Ball permits RedBall, GreenBall { }
final class RedBall extends Ball { }
final class GreenBall extends Ball { }
record Box<T extends Ball>(T content) { }
record ColoredPoint(int x, int y, String color) { }
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) { }
public class Test {
public void PatternVariableConditionalStatements(Ball ball) {
if (ball instanceof RedBall redBall) { // expected violation, unused variable 'redBall'
process(ball);
} else if (ball instanceof GreenBall greenBall) { // expected violation, unused variable 'greenBall'
stopProcessing(ball);
}
// fix
if (ball instanceof RedBall _) {
process(ball);
} else if (ball instanceof GreenBall _) {
stopProcessing(ball);
}
}
public void PatternVariableConditionalStatements2(Ball ball) {
if (!(ball instanceof RedBall redBall)) {
process(ball); // red ball is not in this scope
} else {
process(redBall); // ok red ball is used
}
}
public void PatternVariableInRecordPatternInConditionalStatements(Box<? extends Ball> box) {
if (box instanceof Box(RedBall redBall)) { // expected violation, unused variable 'redBall'
process(box);
} else if (box instanceof Box(GreenBall greenBall)) { // expected violation, unused variable 'greenBall'
stopProcessing(box);
}
// fix
if (box instanceof Box(RedBall _)) {
process(box);
} else if (box instanceof Box(GreenBall _)) {
stopProcessing(box);
}
public void PatternVariableNestedRecordPatterns(Object o) {
if (o instanceof Rectangle(ColoredPoint(int p, int x, String c), ColoredPoint lr)) {
System.out.println(p + "" + x + c);
}
// fix
if (o instanceof Rectangle(ColoredPoint(int p, int x, String c), ColoredPoint _)) {
System.out.println(p + "" + x + c);
}
// another fix
if (o instanceof Rectangle(ColoredPoint(int p, int x, String c), _)) {
System.out.println(p + "" + x + c);
}
}
}
}
PS D:\CS\test> 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="UnusedLocalVariable"/>
</module>
</module>
PS D:\CS\test> java -jar checkstyle-10.17.0-all.jar -c config.xml src/Test.java
Starting audit...
Audit done.
pattern variables within conditional statements are subject to flow sensitivity. This means that the scope of these variables depend on the control flow of the program.
Reference for the pattern variable scope:
child of #14942
Check doc: https://checkstyle.org/checks/coding/unusedlocalvariable.html#UnusedLocalVariable
From Check Description :
We should extend
UnusedLocalVariableto support pattern variables. The unused pattern variables should be unnamed patterns or unnamed pattern variables. This Improves the readability of record patterns by eliding unnecessary nested type patterns. The main goal is to ensure that unused pattern variables are detected and violated, prompting developers to either use them or declare them as unnamed variables.To be clear a pattern is a local variable.
Reference: https://docs.oracle.com/javase/specs/jls/se17/html/jls-14.html#jls-14.30:~:text=A%20local%20variable%20declaration%20can%20appear%20in%20the%20following%20locations%3A
Examples of expected behaviour when we add support for pattern variables
pattern variables within conditional statements are subject to flow sensitivity. This means that the scope of these variables depend on the control flow of the program.
Reference for the pattern variable scope: