in src/org/jetbrains/java/decompiler/modules/decompiler/IfHelper.java [403:609]
private static boolean reorderIf(IfStatement ifstat) {
if (ifstat.iftype == IfStatement.IFTYPE_IFELSE) {
return false;
}
boolean ifdirect, elsedirect;
boolean noifstat = false, noelsestat;
boolean ifdirectpath = false, elsedirectpath = false;
Statement parent = ifstat.getParent();
Statement from = parent.type == StatementType.SEQUENCE ? parent : ifstat;
Statement next = getNextStatement(from);
if (ifstat.getIfstat() == null) {
noifstat = true;
ifdirect = ifstat.getIfEdge().getType() == EdgeType.FINALLY_EXIT ||
MergeHelper.isDirectPath(from, ifstat.getIfEdge().getDestination());
}
else {
List<StatEdge> lstSuccs = ifstat.getIfstat().getAllSuccessorEdges();
ifdirect = !lstSuccs.isEmpty() && lstSuccs.get(0).getType() == EdgeType.FINALLY_EXIT ||
hasDirectEndEdge(ifstat.getIfstat(), from);
}
Statement last = parent.type == StatementType.SEQUENCE ? parent.getStats().getLast() : ifstat;
noelsestat = (last == ifstat);
elsedirect = !last.getAllSuccessorEdges().isEmpty() && last.getAllSuccessorEdges().get(0).getType() == EdgeType.FINALLY_EXIT ||
hasDirectEndEdge(last, from);
if (!noelsestat && existsPath(ifstat, ifstat.getAllSuccessorEdges().get(0).getDestination())) {
return false;
}
if (!ifdirect && !noifstat) {
ifdirectpath = existsPath(ifstat, next);
}
if (!elsedirect && !noelsestat) {
SequenceStatement sequence = (SequenceStatement)parent;
for (int i = sequence.getStats().size() - 1; i >= 0; i--) {
Statement sttemp = sequence.getStats().get(i);
if (sttemp == ifstat) {
break;
}
else if (existsPath(sttemp, next)) {
elsedirectpath = true;
break;
}
}
}
if ((ifdirect || ifdirectpath) && (elsedirect || elsedirectpath) && !noifstat && !noelsestat) { // if - then - else
SequenceStatement sequence = (SequenceStatement)parent;
// build and cut the new else statement
List<Statement> lst = new ArrayList<>();
for (int i = sequence.getStats().size() - 1; i >= 0; i--) {
Statement sttemp = sequence.getStats().get(i);
if (sttemp == ifstat) {
break;
}
else {
lst.add(0, sttemp);
}
}
Statement stelse;
if (lst.size() == 1) {
stelse = lst.get(0);
}
else {
stelse = new SequenceStatement(lst);
stelse.setAllParent();
}
ifstat.removeSuccessor(ifstat.getAllSuccessorEdges().get(0));
for (Statement st : lst) {
sequence.getStats().removeWithKey(st.id);
}
StatEdge elseedge = new StatEdge(EdgeType.REGULAR, ifstat.getFirst(), stelse);
ifstat.getFirst().addSuccessor(elseedge);
ifstat.setElsestat(stelse);
ifstat.setElseEdge(elseedge);
ifstat.getStats().addWithKey(stelse, stelse.id);
stelse.setParent(ifstat);
// if(next.type != Statement.TYPE_DUMMYEXIT && (ifdirect || elsedirect)) {
// StatEdge breakedge = new StatEdge(StatEdge.TYPE_BREAK, ifstat, next);
// sequence.addLabeledEdge(breakedge);
// ifstat.addSuccessor(breakedge);
// }
ifstat.iftype = IfStatement.IFTYPE_IFELSE;
}
else if (ifdirect && (!elsedirect || (noifstat && !noelsestat))) { // if - then
// negate the if condition
IfExprent statexpr = ifstat.getHeadexprent();
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, statexpr.getCondition(), null));
if (noelsestat) {
StatEdge ifedge = ifstat.getIfEdge();
StatEdge elseedge = ifstat.getAllSuccessorEdges().get(0);
if (noifstat) {
ifstat.getFirst().removeSuccessor(ifedge);
ifstat.removeSuccessor(elseedge);
ifedge.setSource(ifstat);
elseedge.setSource(ifstat.getFirst());
ifstat.addSuccessor(ifedge);
ifstat.getFirst().addSuccessor(elseedge);
ifstat.setIfEdge(elseedge);
}
else {
Statement ifbranch = ifstat.getIfstat();
SequenceStatement newseq = new SequenceStatement(Arrays.asList(ifstat, ifbranch));
ifstat.getFirst().removeSuccessor(ifedge);
ifstat.getStats().removeWithKey(ifbranch.id);
ifstat.setIfstat(null);
ifstat.removeSuccessor(elseedge);
elseedge.setSource(ifstat.getFirst());
ifstat.getFirst().addSuccessor(elseedge);
ifstat.setIfEdge(elseedge);
ifstat.getParent().replaceStatement(ifstat, newseq);
newseq.setAllParent();
ifstat.addSuccessor(new StatEdge(EdgeType.REGULAR, ifstat, ifbranch));
}
}
else {
SequenceStatement sequence = (SequenceStatement)parent;
// build and cut the new else statement
List<Statement> lst = new ArrayList<>();
for (int i = sequence.getStats().size() - 1; i >= 0; i--) {
Statement sttemp = sequence.getStats().get(i);
if (sttemp == ifstat) {
break;
}
else {
lst.add(0, sttemp);
}
}
Statement stelse;
if (lst.size() == 1) {
stelse = lst.get(0);
}
else {
stelse = new SequenceStatement(lst);
stelse.setAllParent();
}
ifstat.removeSuccessor(ifstat.getAllSuccessorEdges().get(0));
for (Statement st : lst) {
sequence.getStats().removeWithKey(st.id);
}
if (noifstat) {
StatEdge ifedge = ifstat.getIfEdge();
ifstat.getFirst().removeSuccessor(ifedge);
ifedge.setSource(ifstat);
ifstat.addSuccessor(ifedge);
}
else {
Statement ifbranch = ifstat.getIfstat();
ifstat.getFirst().removeSuccessor(ifstat.getIfEdge());
ifstat.getStats().removeWithKey(ifbranch.id);
ifstat.addSuccessor(new StatEdge(EdgeType.REGULAR, ifstat, ifbranch));
sequence.getStats().addWithKey(ifbranch, ifbranch.id);
ifbranch.setParent(sequence);
}
StatEdge newifedge = new StatEdge(EdgeType.REGULAR, ifstat.getFirst(), stelse);
ifstat.getFirst().addSuccessor(newifedge);
ifstat.setIfstat(stelse);
ifstat.setIfEdge(newifedge);
ifstat.getStats().addWithKey(stelse, stelse.id);
stelse.setParent(ifstat);
}
}
else {
return false;
}
return true;
}