in src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java [388:543]
private static Statement findGeneralStatement(Statement stat, boolean forceall, HashMap<Integer, Set<Integer>> mapExtPost) {
VBStyleCollection<Statement, Integer> stats = stat.getStats();
VBStyleCollection<List<Integer>, Integer> vbPost;
if (mapExtPost.isEmpty()) {
FastExtendedPostdominanceHelper extpost = new FastExtendedPostdominanceHelper();
mapExtPost.putAll(extpost.getExtendedPostdominators(stat));
}
if (forceall) {
vbPost = new VBStyleCollection<>();
List<Statement> lstAll = stat.getPostReversePostOrderList();
for (Statement st : lstAll) {
Set<Integer> set = mapExtPost.get(st.id);
if (set != null) {
vbPost.addWithKey(new ArrayList<>(set), st.id); // FIXME: sort order!!
}
}
// tail statements
Set<Integer> setFirst = mapExtPost.get(stat.getFirst().id);
if (setFirst != null) {
for (Integer id : setFirst) {
List<Integer> lst = vbPost.getWithKey(id);
if (lst == null) {
vbPost.addWithKey(lst = new ArrayList<>(), id);
}
lst.add(id);
}
}
}
else {
vbPost = calcPostDominators(stat);
}
for (int k = 0; k < vbPost.size(); k++) {
Integer headid = vbPost.getKey(k);
List<Integer> posts = vbPost.get(k);
if (!mapExtPost.containsKey(headid) &&
!(posts.size() == 1 && posts.get(0).equals(headid))) {
continue;
}
Statement head = stats.getWithKey(headid);
Set<Integer> setExtPosts = mapExtPost.get(headid);
for (Integer postId : posts) {
if (!postId.equals(headid) && !setExtPosts.contains(postId)) {
continue;
}
Statement post = stats.getWithKey(postId);
if (post == null) { // possible in case of an inherited postdominance set
continue;
}
boolean same = (post == head);
HashSet<Statement> setNodes = new LinkedHashSet<>();
HashSet<Statement> setPreds = new HashSet<>();
// collect statement nodes
HashSet<Statement> setHandlers = new LinkedHashSet<>();
setHandlers.add(head);
while (true) {
boolean hdfound = false;
for (Statement handler : setHandlers) {
if (setNodes.contains(handler)) {
continue;
}
boolean addhd = (setNodes.isEmpty()); // first handler == head
if (!addhd) {
List<Statement> hdsupp = handler.getNeighbours(EdgeType.EXCEPTION, EdgeDirection.BACKWARD);
addhd = (setNodes.containsAll(hdsupp) && (setNodes.size() > hdsupp.size()
|| setNodes.size() == 1)); // strict subset
}
if (addhd) {
List<Statement> lstStack = new ArrayList<>();
lstStack.add(handler);
while (!lstStack.isEmpty()) {
Statement st = lstStack.remove(0);
if (!(setNodes.contains(st) || (!same && st == post))) {
setNodes.add(st);
if (st != head) {
// record predeccessors except for the head
setPreds.addAll(st.getNeighbours(EdgeType.REGULAR, EdgeDirection.BACKWARD));
}
// put successors on the stack
lstStack.addAll(st.getNeighbours(EdgeType.REGULAR, EdgeDirection.FORWARD));
// exception edges
setHandlers.addAll(st.getNeighbours(EdgeType.EXCEPTION, EdgeDirection.FORWARD));
}
}
hdfound = true;
setHandlers.remove(handler);
break;
}
}
if (!hdfound) {
break;
}
}
// check exception handlers
setHandlers.clear();
for (Statement st : setNodes) {
setHandlers.addAll(st.getNeighbours(EdgeType.EXCEPTION, EdgeDirection.FORWARD));
}
setHandlers.removeAll(setNodes);
boolean excok = true;
for (Statement handler : setHandlers) {
if (!handler.getNeighbours(EdgeType.EXCEPTION, EdgeDirection.BACKWARD).containsAll(setNodes)) {
excok = false;
break;
}
}
// build statement and return
if (excok) {
Statement res;
setPreds.removeAll(setNodes);
if (setPreds.isEmpty()) {
if ((setNodes.size() > 1 ||
head.getNeighbours(EdgeType.REGULAR, EdgeDirection.BACKWARD).contains(head))
&& setNodes.size() < stats.size()) {
if (checkSynchronizedCompleteness(setNodes)) {
res = new GeneralStatement(head, setNodes, same ? null : post);
stat.collapseNodesToStatement(res);
return res;
}
}
}
}
}
}
return null;
}