Skip to content

Add RemoveUnreachableMultiCatchAlternative#926

Merged
timtebeek merged 3 commits into
mainfrom
remove-unreachable-multicatch-alternative
Jun 30, 2026
Merged

Add RemoveUnreachableMultiCatchAlternative#926
timtebeek merged 3 commits into
mainfrom
remove-unreachable-multicatch-alternative

Conversation

@steve-aom-elliott

Copy link
Copy Markdown
Contributor

Summary

Adds RemoveUnreachableMultiCatchAlternative, which removes catch alternatives that are already covered by an earlier catch clause in the same try:

  • catch (X) {} catch (X | Y) {}catch (X) {} catch (Y) {}
  • catch (X) {} catch (Y | X) {}catch (X) {} catch (Y) {}
  • catch (IOException) {} catch (FileNotFoundException | IllegalStateException) {}catch (IOException) {} catch (IllegalStateException) {} (subtype shadowed)
  • catch (IOException) {} catch (FileNotFoundException | EOFException) {}catch (IOException) {} (whole later catch dropped)

When a multi-catch reduces to a single alternative it collapses back to a regular catch; when all alternatives are shadowed the entire catch clause is removed.

Motivation

The pattern shows up after type-substitution migrations that cause two catch clauses to overlap — for example, when a recipe renames an exception so its parent and child end up in adjacent catches. The result is a Java compile error (exception X has already been caught). This recipe cleans that up by dropping the unreachable alternative.

Intended to run before CombineSemanticallyEqualCatchBlocks so collapsed singletons become candidates for combination.

Notes

  • Gated on NoMissingTypes — won't fire when type attribution is incomplete.
  • No RSPEC tag attached: I couldn't find a Sonar rule that specifically targets cross-clause shadowing (Sonar likely treats it as a javac error). Happy to add one if reviewers know of a match.

Test plan

  • dropAlternativeShadowedByEarlierCatchcatch (X) ... catch (X | Y) (@DocumentExample)
  • dropTrailingAlternativeShadowedByEarlierCatchcatch (X) ... catch (Y | X)
  • dropMiddleAlternativeShadowedByEarlierCatchcatch (X) ... catch (Y | X | Z)
  • dropSubtypeAlternativeShadowedByEarlierCatch — alternative is a subtype
  • dropEntireCatchWhenAllAlternativesAreShadowed
  • dropEntireSingleTypeCatchWhenShadowed
  • doNothingWhenOrderingMeansNothingIsShadowed
  • doNothingWhenMultiCatchAlternativesAreAllNeeded

Removes `catch` alternatives that are already covered by an earlier
`catch` clause in the same `try`. When a multi-catch reduces to a
single alternative it collapses to a regular `catch`; when all
alternatives are shadowed the entire `catch` clause is dropped.

This pattern most commonly appears after type-substitution migrations
that cause two `catch` clauses to overlap (for example, renaming an
exception so its parent and child end up in adjacent catches), which
is a Java compile error. Intended to run before
`CombineSemanticallyEqualCatchBlocks` so that collapsed singletons
become candidates for combination.
@knutwannheden

Copy link
Copy Markdown
Contributor

When the recipe drops an entire catch clause (the fully-shadowed multi-catch and the shadowed single-type catch paths), the exception types' imports can be left behind unused. Calling maybeRemoveImport for the removed types would tidy that up. Minor — not a blocker.

@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Jun 30, 2026
Call maybeRemoveImport for shadowed types that are removed, and add a
test covering specific catches retained before a trailing catch-all
Exception block.
@timtebeek timtebeek merged commit be7f594 into main Jun 30, 2026
1 check passed
@timtebeek timtebeek deleted the remove-unreachable-multicatch-alternative branch June 30, 2026 12:07
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants