Fork of the Fernflower decompiler
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.
fernflower/src/org/jetbrains/java/decompiler/modules/decompiler/DecHelper.java

199 lines
5.4 KiB

// Copyright 2000-2020 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.exps.Exprent;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public final class DecHelper {
public static boolean checkStatementExceptions(List<? extends Statement> lst) {
Set<Statement> all = new HashSet<>(lst);
Set<Statement> handlers = new HashSet<>();
Set<Statement> intersection = null;
for (Statement stat : lst) {
Set<Statement> setNew = stat.getNeighboursSet(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_FORWARD);
if (intersection == null) {
intersection = setNew;
}
else {
HashSet<Statement> interclone = new HashSet<>(intersection);
interclone.removeAll(setNew);
intersection.retainAll(setNew);
setNew.removeAll(intersection);
handlers.addAll(interclone);
handlers.addAll(setNew);
}
}
for (Statement stat : handlers) {
if (!all.contains(stat) || !all.containsAll(stat.getNeighbours(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_BACKWARD))) {
return false;
}
}
// check for other handlers (excluding head)
for (int i = 1; i < lst.size(); i++) {
Statement stat = lst.get(i);
if (!stat.getPredecessorEdges(StatEdge.TYPE_EXCEPTION).isEmpty() && !handlers.contains(stat)) {
return false;
}
}
return true;
}
public static boolean isChoiceStatement(Statement head, List<? super Statement> lst) {
Statement post = null;
Set<Statement> setDest = head.getNeighboursSet(StatEdge.TYPE_REGULAR, Statement.DIRECTION_FORWARD);
if (setDest.contains(head)) {
return false;
}
while (true) {
lst.clear();
boolean repeat = false;
setDest.remove(post);
for (Statement stat : setDest) {
if (stat.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
if (post == null) {
post = stat;
repeat = true;
break;
}
else {
return false;
}
}
// preds
Set<Statement> setPred = stat.getNeighboursSet(StatEdge.TYPE_REGULAR, Statement.DIRECTION_BACKWARD);
setPred.remove(head);
if (setPred.contains(stat)) {
return false;
}
if (!setDest.containsAll(setPred) || setPred.size() > 1) {
if (post == null) {
post = stat;
repeat = true;
break;
}
else {
return false;
}
}
else if (setPred.size() == 1) {
Statement pred = setPred.iterator().next();
while (lst.contains(pred)) {
Set<Statement> setPredTemp = pred.getNeighboursSet(StatEdge.TYPE_REGULAR, Statement.DIRECTION_BACKWARD);
setPredTemp.remove(head);
if (!setPredTemp.isEmpty()) { // at most 1 predecessor
pred = setPredTemp.iterator().next();
if (pred == stat) {
return false; // loop found
}
}
else {
break;
}
}
}
// succs
List<StatEdge> lstEdges = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL);
if (lstEdges.size() > 1) {
Set<Statement> setSucc = stat.getNeighboursSet(Statement.STATEDGE_DIRECT_ALL, Statement.DIRECTION_FORWARD);
setSucc.retainAll(setDest);
if (setSucc.size() > 0) {
return false;
}
else {
if (post == null) {
post = stat;
repeat = true;
break;
}
else {
return false;
}
}
}
else if (lstEdges.size() == 1) {
StatEdge edge = lstEdges.get(0);
if (edge.getType() == StatEdge.TYPE_REGULAR) {
Statement statd = edge.getDestination();
if (head == statd) {
return false;
}
if (post != statd && !setDest.contains(statd)) {
if (post != null) {
return false;
}
else {
Set<Statement> set = statd.getNeighboursSet(StatEdge.TYPE_REGULAR, Statement.DIRECTION_BACKWARD);
if (set.size() > 1) {
post = statd;
repeat = true;
break;
}
else {
return false;
}
}
}
}
}
lst.add(stat);
}
if (!repeat) {
break;
}
}
lst.add(head);
lst.remove(post);
lst.add(0, post);
return true;
}
public static Set<Statement> getUniquePredExceptions(Statement head) {
Set<Statement> setHandlers = new HashSet<>(head.getNeighbours(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_FORWARD));
setHandlers.removeIf(statement -> statement.getPredecessorEdges(StatEdge.TYPE_EXCEPTION).size() > 1);
return setHandlers;
}
public static List<Exprent> copyExprentList(List<? extends Exprent> lst) {
List<Exprent> ret = new ArrayList<>();
for (Exprent expr : lst) {
ret.add(expr.copy());
}
return ret;
}
}