Skip to content

Commit 643008a

Browse files
authored
Stricter type pattern matching rules (#463)
Vineflower's previous implementation of the type casting pattern matching in switch statements was not strict enough, considering any form of cast in the first expression of the case block a result of type pattern matching. This would incorrectly attempt to emit such type pattern matching source code for switches that simply yielded different types. This commit tightens the logic to consider a switch case a type pattern matching one if the first expression is a simple cast of the switch head's variable.
1 parent 04c996e commit 643008a

File tree

3 files changed

+479
-370
lines changed

3 files changed

+479
-370
lines changed

src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ private static boolean processStatement(SwitchStatement stat, Statement root) {
187187
if (assign.getLeft() instanceof VarExprent) {
188188
VarExprent var = (VarExprent) assign.getLeft();
189189

190-
if (assign.getRight() instanceof FunctionExprent && ((FunctionExprent) assign.getRight()).getFuncType() == FunctionExprent.FunctionType.CAST) {
190+
if (isPatternMatchingCastAssignment(head, assign)) {
191191
FunctionExprent cast = (FunctionExprent) assign.getRight();
192192

193193
List<Exprent> operands = new ArrayList<>();
@@ -547,4 +547,19 @@ private static boolean isSwitchPatternMatch(SwitchHeadExprent head) {
547547
public static boolean hasPatternMatch(RootStatement root) {
548548
return root.mt.getBytecodeVersion().hasSwitchPatternMatch() && DecompilerContext.getOption(IFernflowerPreferences.PATTERN_MATCHING);
549549
}
550+
551+
private static boolean isPatternMatchingCastAssignment(final SwitchHeadExprent switchHead, final AssignmentExprent assignment) {
552+
if (!(assignment.getRight() instanceof final FunctionExprent functionExprent)) return false;
553+
if (functionExprent.getFuncType() != FunctionType.CAST) return false;
554+
555+
final List<Exprent> lstOperands = functionExprent.getLstOperands();
556+
// We expect the assignment to be a literal `n = (Type) m`.
557+
// Any other operands are not allowed in simple pattern matching.
558+
if (lstOperands.size() < 2) return false;
559+
if (!(lstOperands.get(0) instanceof final VarExprent switchHeadRef)) return false;
560+
if (!(lstOperands.get(1) instanceof final ConstExprent castTypeRef)) return false;
561+
if (!switchHead.containsVar(switchHeadRef.getVarVersionPair())) return false; // Not the switch head var ref
562+
563+
return true;
564+
}
550565
}

0 commit comments

Comments
 (0)