From 5e46c058cd6d0f61db59e6b8319e9cc30b947015 Mon Sep 17 00:00:00 2001 From: Graham Date: Thu, 29 Aug 2019 12:06:12 +0100 Subject: [PATCH] Improve structuring of if/else chains ending in a throw or return --- .../deob/ast/transform/IfElseTransformer.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.java b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.java index 440e722f..58b999db 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.java +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.java @@ -36,6 +36,22 @@ public final class IfElseTransformer extends Transformer { throw new IllegalArgumentException(); } + private static boolean isTailThrowOrReturn(Statement stmt) { + if (stmt.isThrowStmt() || stmt.isReturnStmt()) { + return true; + } else if (stmt.isBlockStmt()) { + var stmts = stmt.asBlockStmt().getStatements(); + if (stmts.isEmpty()) { + return false; + } + + var tail = stmts.get(stmts.size() - 1); + return tail.isThrowStmt() || tail.isReturnStmt(); + } else { + return false; + } + } + @Override public void transform(CompilationUnit unit) { NodeUtils.walk(unit, Node.TreeTraversal.POSTORDER, IfStmt.class, stmt -> { @@ -78,5 +94,65 @@ public final class IfElseTransformer extends Transformer { } }); }); + + /* + * Rewrite: + * + * ... + * } else { + * if (x != 123) { + * ... + * throw ...; + * } + * ... + * } + * + * to: + * + * ... + * } else if (x == 123) { + * ... + * } else { + * ... + * throw ...; + * } + */ + NodeUtils.walk(unit, Node.TreeTraversal.POSTORDER, IfStmt.class, stmt -> { + stmt.getElseStmt().ifPresent(elseStmt -> { + /* match */ + if (!elseStmt.isBlockStmt()) { + return; + } + + var blockStmt = elseStmt.asBlockStmt(); + var statements = blockStmt.getStatements(); + if (statements.isEmpty()) { + return; + } + + var head = statements.get(0); + if (!head.isIfStmt()) { + return; + } + + var ifStmt = head.asIfStmt(); + if (ifStmt.getElseStmt().isPresent()) { + return; + } + + var thenStmt = ifStmt.getThenStmt(); + if (!isTailThrowOrReturn(thenStmt)) { + return; + } + + /* rewrite */ + var condition = ExprUtils.not(ifStmt.getCondition()); + + var tail = blockStmt.clone(); + tail.getStatements().remove(0); + + elseStmt.replace(new IfStmt(condition, tail, thenStmt.clone())); + }); + }); } }