You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
4.8 KiB
194 lines
4.8 KiB
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
|
package org.jetbrains.java.decompiler.modules.decompiler;
|
|
|
|
import org.jetbrains.java.decompiler.modules.decompiler.stats.IfStatement;
|
|
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
|
|
import org.jetbrains.java.decompiler.modules.decompiler.stats.SynchronizedStatement;
|
|
|
|
import java.util.List;
|
|
|
|
public class LowBreakHelper {
|
|
|
|
public static void lowBreakLabels(Statement root) {
|
|
|
|
lowBreakLabelsRec(root);
|
|
|
|
liftBreakLabels(root);
|
|
}
|
|
|
|
private static void lowBreakLabelsRec(Statement stat) {
|
|
|
|
while (true) {
|
|
|
|
boolean found = false;
|
|
|
|
for (StatEdge edge : stat.getLabelEdges()) {
|
|
if (edge.getType() == StatEdge.TYPE_BREAK) {
|
|
Statement minclosure = getMinClosure(stat, edge.getSource());
|
|
if (minclosure != stat) {
|
|
minclosure.addLabeledEdge(edge);
|
|
edge.labeled = isBreakEdgeLabeled(edge.getSource(), minclosure);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (Statement st : stat.getStats()) {
|
|
lowBreakLabelsRec(st);
|
|
}
|
|
}
|
|
|
|
public static boolean isBreakEdgeLabeled(Statement source, Statement closure) {
|
|
|
|
if (closure.type == Statement.TYPE_DO || closure.type == Statement.TYPE_SWITCH) {
|
|
|
|
Statement parent = source.getParent();
|
|
|
|
if (parent == closure) {
|
|
return false;
|
|
}
|
|
else {
|
|
return isBreakEdgeLabeled(parent, closure) ||
|
|
(parent.type == Statement.TYPE_DO || parent.type == Statement.TYPE_SWITCH);
|
|
}
|
|
}
|
|
else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static Statement getMinClosure(Statement closure, Statement source) {
|
|
|
|
while (true) {
|
|
|
|
Statement newclosure = null;
|
|
|
|
switch (closure.type) {
|
|
case Statement.TYPE_SEQUENCE:
|
|
Statement last = closure.getStats().getLast();
|
|
|
|
if (isOkClosure(closure, source, last)) {
|
|
newclosure = last;
|
|
}
|
|
break;
|
|
case Statement.TYPE_IF:
|
|
IfStatement ifclosure = (IfStatement)closure;
|
|
if (isOkClosure(closure, source, ifclosure.getIfstat())) {
|
|
newclosure = ifclosure.getIfstat();
|
|
}
|
|
else if (isOkClosure(closure, source, ifclosure.getElsestat())) {
|
|
newclosure = ifclosure.getElsestat();
|
|
}
|
|
break;
|
|
case Statement.TYPE_TRYCATCH:
|
|
for (Statement st : closure.getStats()) {
|
|
if (isOkClosure(closure, source, st)) {
|
|
newclosure = st;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case Statement.TYPE_SYNCRONIZED:
|
|
Statement body = ((SynchronizedStatement)closure).getBody();
|
|
|
|
if (isOkClosure(closure, source, body)) {
|
|
newclosure = body;
|
|
}
|
|
}
|
|
|
|
if (newclosure == null) {
|
|
break;
|
|
}
|
|
|
|
closure = newclosure;
|
|
}
|
|
|
|
return closure;
|
|
}
|
|
|
|
private static boolean isOkClosure(Statement closure, Statement source, Statement stat) {
|
|
|
|
boolean ok = false;
|
|
|
|
if (stat != null && stat.containsStatementStrict(source)) {
|
|
|
|
List<StatEdge> lst = stat.getAllSuccessorEdges();
|
|
|
|
ok = lst.isEmpty();
|
|
if (!ok) {
|
|
StatEdge edge = lst.get(0);
|
|
ok = (edge.closure == closure && edge.getType() == StatEdge.TYPE_BREAK);
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
private static void liftBreakLabels(Statement stat) {
|
|
|
|
for (Statement st : stat.getStats()) {
|
|
liftBreakLabels(st);
|
|
}
|
|
|
|
|
|
while (true) {
|
|
|
|
boolean found = false;
|
|
|
|
for (StatEdge edge : stat.getLabelEdges()) {
|
|
if (edge.explicit && edge.labeled && edge.getType() == StatEdge.TYPE_BREAK) {
|
|
|
|
Statement newclosure = getMaxBreakLift(stat, edge);
|
|
|
|
if (newclosure != null) {
|
|
newclosure.addLabeledEdge(edge);
|
|
edge.labeled = isBreakEdgeLabeled(edge.getSource(), newclosure);
|
|
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static Statement getMaxBreakLift(Statement stat, StatEdge edge) {
|
|
|
|
Statement closure = null;
|
|
Statement newclosure = stat;
|
|
|
|
while ((newclosure = getNextBreakLift(newclosure, edge)) != null) {
|
|
closure = newclosure;
|
|
}
|
|
|
|
return closure;
|
|
}
|
|
|
|
private static Statement getNextBreakLift(Statement stat, StatEdge edge) {
|
|
|
|
Statement closure = stat.getParent();
|
|
|
|
while (closure != null && !closure.containsStatementStrict(edge.getDestination())) {
|
|
|
|
boolean labeled = isBreakEdgeLabeled(edge.getSource(), closure);
|
|
if (closure.isLabeled() || !labeled) {
|
|
return closure;
|
|
}
|
|
|
|
closure = closure.getParent();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|