Skip to content

[java] New rules about labeled statements #2928

@linusjf

Description

@linusjf

Proposing several rules:

Rule 1: UnusedLabel

Proposed Rule Name: UnusedLabel

Proposed Category: Best Practices + Quickstart

Description:
Finds labeled statements (https://docs.oracle.com/javase/specs/jls/se25/html/jls-14.html#jls-14.7) whose label is not used.

Code Sample:

class Example {
    void main() {
        lbl1: {                     // violation: Label "lbl1" is not nused
            int x = 1;
            System.out.println(x);
        }
    }
}

UnusedLabel is really uncontroversial and could be included in the quickstart ruleset. Nobody
wants unused code constructs in their code.
#6042 (comment)


If a label is declared but not used in the program, it can be considered as dead code and
should therefore be removed.

This will improve maintainability as developers will not wonder what this label is used for.

https://rules.sonarsource.com/java/RSPEC-1065

Possible Properties:
None.

Rule 2: LabeledStatement

Proposed Rule Name: LabeledStatement

Proposed Category: Best Practices

Description:
Labeled statements (https://docs.oracle.com/javase/specs/jls/se25/html/jls-14.html#jls-14.7) break the flow of a program and is difficult to trace the control flow. It is reminiscent of the goto statement. Code can be rewritten to avoid labeled statements.

Quotes:

It's difficult to read code containing breaks to a label. Also, a label can be accidentally
moved, or code inserted at an incorrect location with respect to a label. The compiler is not
able to warn you of these effects since the code remains syntactically valid.

Code that's difficult to read is difficult to maintain. Bugs will inevitably creep in.

Other control structures (break, continue, while, for, etc.) don't suffer from this.

Note that a switch to a label doesn't suffer from these effects either: the structure of a
switch block is well-defined.

The most sensible alternative to breaking out of a nested loop is to recast the code to a
function and use return. You also get the added benefit of being able (potentially) to return
a value back to the caller.

https://stackoverflow.com/questions/33689466/labels-in-java-bad-practice


Labels should not be used
Labels are not commonly used in Java, and many developers do not understand how they work.
Moreover, their usage makes the control flow harder to follow, which reduces the code’s
readability.

https://rules.sonarsource.com/java/tag/confusing/RSPEC-1119


A break with a label is always tricky, because you'll have to hunt for the label to find out
which statement/block the break escapes from (i.e. the break will continue after the labeled
block/statement).

The worst kind (the one you almost always want to avoid) is a nested loop where you break
somewhere in the middle."

https://softwareengineering.stackexchange.com/questions/185944/java-labels-to-be-or-not-to-be/185945#185945


Also I think labels on loops are actually the only legit use case for labels, even though
they can be applied to any statement. I think it would be better to have a rule
LabeledStatement that by default flags all labels except those applied to loops, and that
has a property to also flag labels of loops.

#6042 (comment)

Code Sample:

class Scratch {
    public static void main(String[] args) {
        int x = 1;
        lbl1: while (true) {          // violation: labeled statement on loop (when property allowLoops=false)
            lbl2: if (x == 3) {       // violation: labeled statement
                x++;
                break lbl2;
            }
            lbl3: if (x == 4) {
                break lbl1;
            }
            System.out.println(x);
            x++;
        }
    }
}

Possible Properties:

  • allowLoops: boolean. default is true. whether to allow or not labels before loop statements (do, while, for)

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:new-ruleProposal to add a new built-in rule

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions