// 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 lst) { Set all = new HashSet<>(lst); Set handlers = new HashSet<>(); Set intersection = null; for (Statement stat : lst) { Set setNew = stat.getNeighboursSet(StatEdge.TYPE_EXCEPTION, Statement.DIRECTION_FORWARD); if (intersection == null) { intersection = setNew; } else { HashSet 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 lst) { Statement post = null; Set 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 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 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 lstEdges = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL); if (lstEdges.size() > 1) { Set 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 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 getUniquePredExceptions(Statement head) { Set 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 copyExprentList(List lst) { List ret = new ArrayList<>(); for (Exprent expr : lst) { ret.add(expr.copy()); } return ret; } }