Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public J visitTry(J.Try tryable, ExecutionContext ctx) {

if (!semanticallyEqualCatchesMap.isEmpty()) {
// Collect the identifiers of caught exceptions that are subtypes or implementations of an exception that is caught later in a different catch.
Map<J.Try.Catch, Map<J.Try.Catch, Set<J.Identifier>>> parentChildClassRelationship = new HashMap<>();
Map<J.Try.Catch, Map<J.Try.Catch, Set<NameTree>>> parentChildClassRelationship = new HashMap<>();
for (int i = 0; i < catches.size(); i++) {
J.Try.Catch from = catches.get(i);
for (int j = i + 1; j < catches.size(); j++) {
Expand All @@ -86,10 +86,10 @@ public J visitTry(J.Try tryable, ExecutionContext ctx) {
JavaType fromType = TypeUtils.asFullyQualified(fromException.getType());
JavaType toType = TypeUtils.asFullyQualified(toException.getType());
if (fromType != null && toType != null && TypeUtils.isAssignableTo(toType, fromType)) {
Map<J.Try.Catch, Set<J.Identifier>> subTypesMap = parentChildClassRelationship.computeIfAbsent(from, key -> new HashMap<>());
Set<J.Identifier> childClassIdentifiers = subTypesMap.computeIfAbsent(to, key -> new HashSet<>());
if (fromException instanceof J.Identifier) {
childClassIdentifiers.add((J.Identifier) fromException);
Map<J.Try.Catch, Set<NameTree>> subTypesMap = parentChildClassRelationship.computeIfAbsent(from, key -> new HashMap<>());
Set<NameTree> childClassIdentifiers = subTypesMap.computeIfAbsent(to, key -> new HashSet<>());
if (fromException instanceof J.Identifier || fromException instanceof J.FieldAccess) {
childClassIdentifiers.add(fromException);
}
}
}
Expand Down Expand Up @@ -171,11 +171,11 @@ static class RemoveCatches extends JavaVisitor<ExecutionContext> {
private static class CombineCatches extends JavaVisitor<ExecutionContext> {
private final J.Try.Catch scope;
private final List<J.Try.Catch> equivalentCatches;
private final Map<J.Try.Catch, Set<J.Identifier>> childClassesToExclude;
private final Map<J.Try.Catch, Set<NameTree>> childClassesToExclude;

CombineCatches(J.Try.Catch scope,
List<J.Try.Catch> equivalentCatches,
Map<J.Try.Catch, Set<J.Identifier>> childClassesToExclude) {
Map<J.Try.Catch, Set<NameTree>> childClassesToExclude) {
this.scope = scope;
this.equivalentCatches = equivalentCatches;
this.childClassesToExclude = childClassesToExclude;
Expand Down Expand Up @@ -211,24 +211,24 @@ public J visitCatch(J.Try.Catch _catch, ExecutionContext ctx) {
}

private List<JRightPadded<NameTree>> combineEquivalentCatches() {
Set<J.Identifier> removeIdentifiers = new HashSet<>();
Set<NameTree> removeExceptions = new HashSet<>();
List<JRightPadded<NameTree>> combinedCatches = new ArrayList<>();

for (J.Try.Catch equivalentCatch : equivalentCatches) {
Set<J.Identifier> childClasses = childClassesToExclude.get(equivalentCatch);
Set<NameTree> childClasses = childClassesToExclude.get(equivalentCatch);
if (childClasses != null) {
// Remove child classes that will be unnecessary since the parent exists in the new multi-catch.
removeIdentifiers.addAll(childClasses);
removeExceptions.addAll(childClasses);
}

TypeTree typeExpr = equivalentCatch.getParameter().getTree().getTypeExpression();
if (typeExpr instanceof J.MultiCatch) {
for (JRightPadded<NameTree> alternative : ((J.MultiCatch) typeExpr).getPadding().getAlternatives()) {
NameTree name = alternative.getElement();
if (removeExceptions.contains(name)) {
continue; // Skip redundant subtype
}
if (name instanceof J.Identifier) {
if (removeIdentifiers.contains((J.Identifier) name)) {
continue; // Skip redundant subtype
}
combinedCatches.add(alternative.withElement(((J.Identifier) name).withPrefix(EMPTY)));
} else if (name instanceof J.FieldAccess) {
combinedCatches.add(alternative.withElement(((J.FieldAccess) name).withPrefix(EMPTY)));
Expand All @@ -238,11 +238,14 @@ private List<JRightPadded<NameTree>> combineEquivalentCatches() {
}
} else if (typeExpr instanceof J.Identifier) {
J.Identifier identifier = (J.Identifier) typeExpr;
if (!removeIdentifiers.contains(identifier)) {
if (!removeExceptions.contains(identifier)) {
combinedCatches.add(JRightPadded.build(identifier.withPrefix(EMPTY)));
}
} else if (typeExpr instanceof J.FieldAccess) {
combinedCatches.add(JRightPadded.build(((J.FieldAccess) typeExpr).withPrefix(EMPTY)));
J.FieldAccess fieldAccess = (J.FieldAccess) typeExpr;
if (!removeExceptions.contains(fieldAccess)) {
combinedCatches.add(JRightPadded.build(fieldAccess.withPrefix(EMPTY)));
}
}
}

Expand All @@ -251,17 +254,21 @@ private List<JRightPadded<NameTree>> combineEquivalentCatches() {
List<JRightPadded<NameTree>> alternatives = ((J.MultiCatch) scopeExpr).getPadding().getAlternatives();
for (int i = alternatives.size() - 1; i >= 0; i--) {
NameTree name = alternatives.get(i).getElement();
if (name instanceof J.Identifier && !removeIdentifiers.contains(name)) {
combinedCatches.add(0, alternatives.get(i).withElement(((J.Identifier) name).withPrefix(EMPTY)));
} else if (!(name instanceof J.Identifier)) {
combinedCatches.add(0, alternatives.get(i));
if (!removeExceptions.contains(name)) {
if (name instanceof J.Identifier) {
combinedCatches.add(0, alternatives.get(i).withElement(((J.Identifier) name).withPrefix(EMPTY)));
} else {
combinedCatches.add(0, alternatives.get(i));
}
}
}
} else {
if (scopeExpr instanceof J.Identifier && !removeIdentifiers.contains(scopeExpr)) {
combinedCatches.add(0, JRightPadded.build(((J.Identifier) scopeExpr).withPrefix(EMPTY)));
} else if (scopeExpr instanceof J.FieldAccess) {
combinedCatches.add(0, JRightPadded.build(((J.FieldAccess) scopeExpr).withPrefix(EMPTY)));
if (!removeExceptions.contains(scopeExpr)) {
if (scopeExpr instanceof J.Identifier) {
combinedCatches.add(0, JRightPadded.build(((J.Identifier) scopeExpr).withPrefix(EMPTY)));
} else if (scopeExpr instanceof J.FieldAccess) {
combinedCatches.add(0, JRightPadded.build(((J.FieldAccess) scopeExpr).withPrefix(EMPTY)));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,4 +528,41 @@ void method() {
)
);
}

@Issue("https://github.com/openrewrite/rewrite-static-analysis/issues/771")
@Test
void removeRedundantInnerExceptionWhenParentIsCaught() {
rewriteRun(
//language=java
java(
"""
class Outer {
public static class InnerException extends Exception {}
}
"""
),
//language=java
java(
"""
class Test {
void method() {
try {
} catch (Outer.InnerException e) {
} catch (Exception e) {
}
}
}
""",
"""
class Test {
void method() {
try {
} catch (Exception e) {
}
}
}
"""
)
);
}
}