Skip to content

Investigate UnusedLocalVariables Check Updates for Unnamed Variables and Patterns #14960

@nrmancuso

Description

@nrmancuso

from JEP:

The following kinds of declarations can introduce either a named variable (denoted by an identifier) or an unnamed variable (denoted by an underscore):

  • A local variable declaration statement in a block (JLS §14.4.2),
  • The resource specification of a try-with-resources statement (JLS §14.20.3),
  • The header of a basic for loop (JLS §14.14.1),
  • The header of an enhanced for loop (JLS §14.14.2),
  • An exception parameter of a catch block (JLS §14.20), and
  • A formal parameter of a lambda expression (JLS §15.27.1).

before opening an issue, we need to discuss and decide on the possible check updates or new checks due to the presence of unnamed pattern and variables in these constructs

I tried to cover all possible cases in this example.

import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
record Point(int x, int y) {};

class Test {

    void testLocalVariables(){
        int _ = 4;  // violation,  but a false positive
        int x = 4; // violation (expected)
    }

    void testForLoops() {
        Queue<Integer> q = new PriorityQueue<>();
        q.add(1);
        for (Integer a : q) {   // violation  (expected)
            q.poll();
        }
        for (int i = 0, k = Integer.valueOf(1); i < 3; i++) { } // violation (expected)

        for (Integer _ : q) {   // violation, but a false positive
            q.poll();
        }
        for (int i = 0, _ = Integer.valueOf(1); i < 3; i++) { } // violation, but a false positive
    }

    public void testLambdaParameter() {
        List<String> list = List.of("a", "b", "c");
        List<String> _ = list.stream().map(character -> "x").toList(); // ok, but a false negative 'character' is unused
        List<String> _ = list.stream().map(_ -> "x").toList(); // ok (expected)
    }

    public void testTryWithResourceAndCatchParameters() {
        try (AutoCloseable a = new Scanner(System.in)) {  // ok, but a false negative 'a' is unused

        } catch (Exception e) {  // ok, but a false negative 'e' is unused
            System.out.println("error");
        }

        try (AutoCloseable _ = new Scanner(System.in)) { // ok (expected)

        } catch (Exception _) {  // ok  (expected)
            System.out.println("error");
        }
    }

    public void testPatternVariables(Object obj) {
        if (obj instanceof Point(int x, int y)) { // ok, but a false negative 'x' and 'y' is unused

        }
        if (obj instanceof Point(int _, int _)) { // ok (expected) unnamed pattern variables

        }
        if (obj instanceof Point(_,_)){ // ok (expected) unnamed pattern

        }

    }
}
PS D:\CS\test> java  -jar checkstyle-10.14.2-all.jar -c config.xml  src/Test.java
Starting audit...
[ERROR] D:\CS\test\src\Test.java:10:9: Unused local variable '_'. [UnusedLocalVariable]
[ERROR] D:\CS\test\src\Test.java:11:9: Unused local variable 'x'. [UnusedLocalVariable]
[ERROR] D:\CS\test\src\Test.java:17:14: Unused local variable 'a'. [UnusedLocalVariable]
[ERROR] D:\CS\test\src\Test.java:20:14: Unused local variable 'k'. [UnusedLocalVariable]
[ERROR] D:\CS\test\src\Test.java:22:14: Unused local variable '_'. [UnusedLocalVariable]
[ERROR] D:\CS\test\src\Test.java:25:14: Unused local variable '_'. [UnusedLocalVariable]
[ERROR] D:\CS\test\src\Test.java:30:9: Unused local variable '_'. [UnusedLocalVariable]
Audit done.
Checkstyle ends with 7 errors.
PS D:\CS\test> 

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions