| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| 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; |
| } |
| } |