Skip to content

RIS-496 Implement S8795: Code after unconditional control flow statements should be removed#5683

Draft
romainbrenguier wants to merge 1 commit into
masterfrom
nigel/S8795-unreachable-code
Draft

RIS-496 Implement S8795: Code after unconditional control flow statements should be removed#5683
romainbrenguier wants to merge 1 commit into
masterfrom
nigel/S8795-unreachable-code

Conversation

@romainbrenguier

Copy link
Copy Markdown
Contributor

Implements detection of unreachable code after unconditional control flow statements (return, throw, break, continue).

Changes

  • Added - Rule implementation
  • Added - Unit tests
  • Added - Test cases
  • Added S8795 metadata (HTML/JSON)

Related

  • Jira: RIS-493
  • RSpec: S8795

Generated using vibe-bot new-rule workflow

…uld be removed

Detects unreachable code after return, throw, break, and continue statements.

Related to RIS-493
@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod Bot changed the title Implement S8795: Code after unconditional control flow statements should be removed RIS-496 Implement S8795: Code after unconditional control flow statements should be removed Jun 19, 2026
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

RIS-496

int codeAfterReturn(int a) {
int i = 10;
return i + a;
i++; // Noncompliant {{Remove this unreachable code.}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 Bug: Test sample file fails javac compilation, breaking the build

In Java, a statement that is unreachable is a compile-time error (JLS §14.21 "Unreachable Statements"), not just a warning. Every // Noncompliant line in UnreachableCodeCheckSample.java places a statement after an unconditional return/throw/break/continue in the same block, which javac rejects.

I verified this by compiling the file directly:

UnreachableCodeCheckSample.java:8: error: unreachable statement
    i++; // Noncompliant {{Remove this unreachable code.}}
UnreachableCodeCheckSample.java:13: error: unreachable statement
...

The java-checks-test-sources/default module is built with maven-compiler-plugin (<release>25</release>, no failOnError=false / maven.main.skip), so this module is compiled during the build. Because the sample does not compile, the module build — and therefore CI — will fail. The UnreachableCodeCheckTest would never even reach a green state.

Unlike most SonarJava sample files, which contain semantically questionable but compilable code, genuine unreachable code cannot be made to compile. The sample must be restructured so the analyzed file compiles (e.g., make the jump conditional via an opaque condition the compiler can't fold, or move the sample out of a javac-compiled module if such a mechanism exists), otherwise the rule cannot be tested via CheckVerifier in this module.

Was this helpful? React with 👍 / 👎

Comment on lines +45 to +59
for (int i = 0; i < statements.size() - 1; i++) {
StatementTree statement = statements.get(i);
if (isUnconditionalJump(statement)) {
StatementTree unreachableStatement = statements.get(i + 1);
reportIssue(unreachableStatement, "Remove this unreachable code.");
break;
}
}
}

private static boolean isUnconditionalJump(StatementTree statement) {
return statement.is(
Tree.Kind.RETURN_STATEMENT,
Tree.Kind.THROW_STATEMENT,
Tree.Kind.BREAK_STATEMENT,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Quality: Rule duplicates a javac compile error and can't fire on valid code

The rule flags statements immediately following return/throw/break/continue within the same BLOCK/CASE_GROUP. In Java this exact situation is already a hard compile-time error (JLS §14.21), so it can never occur in code that compiles. As a result the rule will essentially never raise an issue on real, compilable production code — it only triggers on source that the Java compiler itself already rejects.

This questions the value/scope of the rule as implemented. If the intent (per the RSpec and HTML description) is to catch code that is logically dead due to control flow within branches, the detection likely needs dataflow/CFG-based reachability analysis (e.g. reuse of the existing CFG in sonar-java) rather than a purely syntactic "next sibling statement" check. Recommend confirming with the RSpec whether the syntactic scope is intended, and aligning the implementation (and the test sample) accordingly.

Was this helpful? React with 👍 / 👎

},
"attribute": "LOGICAL"
},
"status": "ready",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: S8795 not added to Sonar_way profile

The rule metadata marks "status": "ready", but S8795 is not present in Sonar_way_profile.json. If the rule is intended to be active by default, it must be added to the ruleKeys list of the Sonar way profile; otherwise it will ship deactivated. Confirm whether default activation is intended and update the profile accordingly (there is typically a profile-completeness test that enforces this).

Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
CI failed: The build is failing due to 'unreachable statement' compilation errors in the newly added 'UnreachableCodeCheckSample.java' file. This occurs because the Java compiler detects the intentionally unreachable code intended for testing as actual errors.

Overview

The build failed because the new test source file UnreachableCodeCheckSample.java contains code specifically written to be unreachable (e.g., following return or throw statements). Since this file is currently in a compilation path, the Java compiler treats these intended test cases as fatal errors.

Failures

Compilation Failure: Unreachable Statements (confidence: high)

  • Type: build
  • Affected jobs: 82361677385, 82361677457
  • Related to change: yes
  • Root cause: The compiler is flagging intentional unreachable code blocks in the new test sample as compilation errors.
  • Suggested fix: Either wrap the unreachable segments in conditional blocks that evaluate to false (e.g., if (false) { ... }) to bypass compiler checks, or ensure the file is placed in a test-only source directory that does not trigger standard javac error validation during the main build phase.

Summary

  • Change-related failures: 1 (Compilation failure caused by new test content).
  • Infrastructure/flaky failures: 0.
  • Recommended action: Modify the test sample file to hide the unreachable code from the compiler or relocate the file to a non-compiled test resource directory.
Code Review 🚫 Blocked 0 resolved / 3 findings

Implements rule S8795 for detecting unreachable code, but currently fails build due to compilation errors in test samples and targets code that javac already rejects. Additionally, the rule is missing from the Sonar way profile.

🚨 Bug: Test sample file fails javac compilation, breaking the build

📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:8 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:13 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:20 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:26 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:32 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:39 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:48 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:57 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:65 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:74 📄 java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:82

In Java, a statement that is unreachable is a compile-time error (JLS §14.21 "Unreachable Statements"), not just a warning. Every // Noncompliant line in UnreachableCodeCheckSample.java places a statement after an unconditional return/throw/break/continue in the same block, which javac rejects.

I verified this by compiling the file directly:

UnreachableCodeCheckSample.java:8: error: unreachable statement
    i++; // Noncompliant {{Remove this unreachable code.}}
UnreachableCodeCheckSample.java:13: error: unreachable statement
...

The java-checks-test-sources/default module is built with maven-compiler-plugin (<release>25</release>, no failOnError=false / maven.main.skip), so this module is compiled during the build. Because the sample does not compile, the module build — and therefore CI — will fail. The UnreachableCodeCheckTest would never even reach a green state.

Unlike most SonarJava sample files, which contain semantically questionable but compilable code, genuine unreachable code cannot be made to compile. The sample must be restructured so the analyzed file compiles (e.g., make the jump conditional via an opaque condition the compiler can't fold, or move the sample out of a javac-compiled module if such a mechanism exists), otherwise the rule cannot be tested via CheckVerifier in this module.

⚠️ Quality: Rule duplicates a javac compile error and can't fire on valid code

📄 java-checks/src/main/java/org/sonar/java/checks/UnreachableCodeCheck.java:45-59

The rule flags statements immediately following return/throw/break/continue within the same BLOCK/CASE_GROUP. In Java this exact situation is already a hard compile-time error (JLS §14.21), so it can never occur in code that compiles. As a result the rule will essentially never raise an issue on real, compilable production code — it only triggers on source that the Java compiler itself already rejects.

This questions the value/scope of the rule as implemented. If the intent (per the RSpec and HTML description) is to catch code that is logically dead due to control flow within branches, the detection likely needs dataflow/CFG-based reachability analysis (e.g. reuse of the existing CFG in sonar-java) rather than a purely syntactic "next sibling statement" check. Recommend confirming with the RSpec whether the syntactic scope is intended, and aligning the implementation (and the test sample) accordingly.

💡 Quality: S8795 not added to Sonar_way profile

📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8795.json:10

The rule metadata marks "status": "ready", but S8795 is not present in Sonar_way_profile.json. If the rule is intended to be active by default, it must be added to the ruleKeys list of the Sonar way profile; otherwise it will ship deactivated. Confirm whether default activation is intended and update the profile accordingly (there is typically a profile-completeness test that enforces this).

🤖 Prompt for agents
Code Review: Implements rule S8795 for detecting unreachable code, but currently fails build due to compilation errors in test samples and targets code that javac already rejects. Additionally, the rule is missing from the Sonar way profile.

1. 🚨 Bug: Test sample file fails javac compilation, breaking the build
   Files: java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:8, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:13, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:20, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:26, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:32, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:39, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:48, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:57, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:65, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:74, java-checks-test-sources/default/src/main/java/checks/UnreachableCodeCheckSample.java:82

   In Java, a statement that is unreachable is a compile-time error (JLS §14.21 "Unreachable Statements"), not just a warning. Every `// Noncompliant` line in `UnreachableCodeCheckSample.java` places a statement after an unconditional `return`/`throw`/`break`/`continue` in the same block, which `javac` rejects.
   
   I verified this by compiling the file directly:
   ```
   UnreachableCodeCheckSample.java:8: error: unreachable statement
       i++; // Noncompliant {{Remove this unreachable code.}}
   UnreachableCodeCheckSample.java:13: error: unreachable statement
   ...
   ```
   The `java-checks-test-sources/default` module is built with `maven-compiler-plugin` (`<release>25</release>`, no `failOnError=false` / `maven.main.skip`), so this module is compiled during the build. Because the sample does not compile, the module build — and therefore CI — will fail. The `UnreachableCodeCheckTest` would never even reach a green state.
   
   Unlike most SonarJava sample files, which contain semantically questionable but compilable code, genuine unreachable code cannot be made to compile. The sample must be restructured so the analyzed file compiles (e.g., make the jump conditional via an opaque condition the compiler can't fold, or move the sample out of a javac-compiled module if such a mechanism exists), otherwise the rule cannot be tested via CheckVerifier in this module.

2. ⚠️ Quality: Rule duplicates a javac compile error and can't fire on valid code
   Files: java-checks/src/main/java/org/sonar/java/checks/UnreachableCodeCheck.java:45-59

   The rule flags statements immediately following `return`/`throw`/`break`/`continue` within the same `BLOCK`/`CASE_GROUP`. In Java this exact situation is already a hard compile-time error (JLS §14.21), so it can never occur in code that compiles. As a result the rule will essentially never raise an issue on real, compilable production code — it only triggers on source that the Java compiler itself already rejects.
   
   This questions the value/scope of the rule as implemented. If the intent (per the RSpec and HTML description) is to catch code that is logically dead due to control flow within branches, the detection likely needs dataflow/CFG-based reachability analysis (e.g. reuse of the existing CFG in sonar-java) rather than a purely syntactic "next sibling statement" check. Recommend confirming with the RSpec whether the syntactic scope is intended, and aligning the implementation (and the test sample) accordingly.

3. 💡 Quality: S8795 not added to Sonar_way profile
   Files: sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8795.json:10

   The rule metadata marks `"status": "ready"`, but `S8795` is not present in `Sonar_way_profile.json`. If the rule is intended to be active by default, it must be added to the `ruleKeys` list of the Sonar way profile; otherwise it will ship deactivated. Confirm whether default activation is intended and update the profile accordingly (there is typically a profile-completeness test that enforces this).

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.
Unblock → Override a blocking verdict and allow merging.

Comment with these commands to change:

Auto-apply Compact Unblock
gitar auto-apply:on         
gitar display:verbose         
gitar unblock         

Was this helpful? React with 👍 / 👎 | Gitar

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ This PR is blocked due to unresolved code review findings.

Comment gitar unblock to override this block and allow merging.

Configure merge blocking · Maintainers can dismiss this review. Gitar never approves changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant