diff options
Diffstat (limited to 'plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java')
-rw-r--r-- | plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java new file mode 100644 index 000000000000..9ad812534c6c --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java @@ -0,0 +1,416 @@ +/* + * 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.stats; + +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; +import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; +import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; +import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.IfExprent; +import org.jetbrains.java.decompiler.util.InterpreterUtil; + +import java.util.ArrayList; +import java.util.List; + + +public class IfStatement extends Statement { + + public static int IFTYPE_IF = 0; + public static int IFTYPE_IFELSE = 1; + + public int iftype; + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private Statement ifstat; + private Statement elsestat; + + private StatEdge ifedge; + private StatEdge elseedge; + + private boolean negated = false; + + private boolean iffflag; + + private List<Exprent> headexprent = new ArrayList<Exprent>(); // contains IfExprent + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + private IfStatement() { + type = TYPE_IF; + + headexprent.add(null); + } + + private IfStatement(Statement head, int regedges, Statement postst) { + + this(); + + first = head; + stats.addWithKey(head, head.id); + + List<StatEdge> lstHeadSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL); + + switch (regedges) { + case 0: + ifstat = null; + elsestat = null; + + break; + case 1: + ifstat = null; + elsestat = null; + + StatEdge edgeif = lstHeadSuccs.get(1); + if (edgeif.getType() != StatEdge.TYPE_REGULAR) { + post = lstHeadSuccs.get(0).getDestination(); + } + else { + post = edgeif.getDestination(); + negated = true; + } + break; + case 2: + elsestat = lstHeadSuccs.get(0).getDestination(); + ifstat = lstHeadSuccs.get(1).getDestination(); + + List<StatEdge> lstSucc = ifstat.getSuccessorEdges(StatEdge.TYPE_REGULAR); + List<StatEdge> lstSucc1 = elsestat.getSuccessorEdges(StatEdge.TYPE_REGULAR); + + if (ifstat.getPredecessorEdges(StatEdge.TYPE_REGULAR).size() > 1 || lstSucc.size() > 1) { + post = ifstat; + } + else if (elsestat.getPredecessorEdges(StatEdge.TYPE_REGULAR).size() > 1 || lstSucc1.size() > 1) { + post = elsestat; + } + else { + if (lstSucc.size() == 0) { + post = elsestat; + } + else if (lstSucc1.size() == 0) { + post = ifstat; + } + } + + if (ifstat == post) { + if (elsestat != post) { + ifstat = elsestat; + negated = true; + } + else { + ifstat = null; + } + elsestat = null; + } + else if (elsestat == post) { + elsestat = null; + } + else { + post = postst; + } + + if (elsestat == null) { + regedges = 1; // if without else + } + } + + ifedge = lstHeadSuccs.get(negated ? 0 : 1); + elseedge = (regedges == 2) ? lstHeadSuccs.get(negated ? 1 : 0) : null; + + iftype = (regedges == 2) ? IFTYPE_IFELSE : IFTYPE_IF; + + if (iftype == IFTYPE_IF) { + if (regedges == 0) { + StatEdge edge = lstHeadSuccs.get(0); + head.removeSuccessor(edge); + edge.setSource(this); + this.addSuccessor(edge); + } + else if (regedges == 1) { + StatEdge edge = lstHeadSuccs.get(negated ? 1 : 0); + head.removeSuccessor(edge); + } + } + + if (ifstat != null) { + stats.addWithKey(ifstat, ifstat.id); + } + + if (elsestat != null) { + stats.addWithKey(elsestat, elsestat.id); + } + + if (post == head) { + post = this; + } + } + + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public static Statement isHead(Statement head) { + + if (head.type == TYPE_BASICBLOCK && head.getLastBasicType() == LASTBASICTYPE_IF) { + int regsize = head.getSuccessorEdges(StatEdge.TYPE_REGULAR).size(); + + Statement p = null; + + boolean ok = (regsize < 2); + if (!ok) { + List<Statement> lst = new ArrayList<Statement>(); + if (DecHelper.isChoiceStatement(head, lst)) { + p = lst.remove(0); + + for (Statement st : lst) { + if (st.isMonitorEnter()) { + return null; + } + } + + ok = DecHelper.checkStatementExceptions(lst); + } + } + + if (ok) { + return new IfStatement(head, regsize, p); + } + } + + return null; + } + + public String toJava(int indent) { + String indstr = InterpreterUtil.getIndentString(indent); + StringBuilder buf = new StringBuilder(); + + String new_line_separator = DecompilerContext.getNewLineSeparator(); + + buf.append(ExprProcessor.listToJava(varDefinitions, indent)); + buf.append(first.toJava(indent)); + + if (isLabeled()) { + buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + } + + buf.append(indstr).append(headexprent.get(0).toJava(indent)).append(" {").append(new_line_separator); + + if (ifstat == null) { + buf.append(InterpreterUtil.getIndentString(indent + 1)); + + if (ifedge.explicit) { + if (ifedge.getType() == StatEdge.TYPE_BREAK) { + // break + buf.append("break"); + } + else { + // continue + buf.append("continue"); + } + + if (ifedge.labeled) { + buf.append(" label").append(ifedge.closure.id); + } + } + buf.append(";").append(new_line_separator); + } + else { + buf.append(ExprProcessor.jmpWrapper(ifstat, indent + 1, true)); + } + + boolean elseif = false; + + if (elsestat != null) { + if (elsestat.type == Statement.TYPE_IF + && elsestat.varDefinitions.isEmpty() && elsestat.getFirst().getExprents().isEmpty() && + !elsestat.isLabeled() && + (elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).isEmpty() + || !elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).get(0).explicit)) { // else if + String content = ExprProcessor.jmpWrapper(elsestat, indent, false); + content = content.substring(indstr.length()); + + buf.append(indstr).append("} else "); + buf.append(content); + + elseif = true; + } + else { + String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false); + + if (content.length() > 0) { + buf.append(indstr).append("} else {").append(new_line_separator); + buf.append(content); + } + } + } + + if (!elseif) { + buf.append(indstr).append("}").append(new_line_separator); + } + + return buf.toString(); + } + + public void initExprents() { + + IfExprent ifexpr = (IfExprent)first.getExprents().remove(first.getExprents().size() - 1); + + if (negated) { + ifexpr = (IfExprent)ifexpr.copy(); + ifexpr.negateIf(); + } + + headexprent.set(0, ifexpr); + } + + public List<Object> getSequentialObjects() { + + List<Object> lst = new ArrayList<Object>(stats); + lst.add(1, headexprent.get(0)); + + return lst; + } + + public void replaceExprent(Exprent oldexpr, Exprent newexpr) { + if (headexprent.get(0) == oldexpr) { + headexprent.set(0, newexpr); + } + } + + public void replaceStatement(Statement oldstat, Statement newstat) { + + super.replaceStatement(oldstat, newstat); + + if (ifstat == oldstat) { + ifstat = newstat; + } + + if (elsestat == oldstat) { + elsestat = newstat; + } + + List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL); + + if (iftype == IFTYPE_IF) { + ifedge = lstSuccs.get(0); + elseedge = null; + } + else { + StatEdge edge0 = lstSuccs.get(0); + StatEdge edge1 = lstSuccs.get(1); + if (edge0.getDestination() == ifstat) { + ifedge = edge0; + elseedge = edge1; + } + else { + ifedge = edge1; + elseedge = edge0; + } + } + } + + public Statement getSimpleCopy() { + + IfStatement is = new IfStatement(); + is.iftype = this.iftype; + is.negated = this.negated; + is.iffflag = this.iffflag; + + return is; + } + + public void initSimpleCopy() { + + first = stats.get(0); + + List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL); + ifedge = lstSuccs.get((iftype == IFTYPE_IF || negated) ? 0 : 1); + if (stats.size() > 1) { + ifstat = stats.get(1); + } + + if (iftype == IFTYPE_IFELSE) { + elseedge = lstSuccs.get(negated ? 1 : 0); + elsestat = stats.get(2); + } + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public Statement getElsestat() { + return elsestat; + } + + public void setElsestat(Statement elsestat) { + this.elsestat = elsestat; + } + + public Statement getIfstat() { + return ifstat; + } + + public void setIfstat(Statement ifstat) { + this.ifstat = ifstat; + } + + public boolean isNegated() { + return negated; + } + + public void setNegated(boolean negated) { + this.negated = negated; + } + + public List<Exprent> getHeadexprentList() { + return headexprent; + } + + public IfExprent getHeadexprent() { + return (IfExprent)headexprent.get(0); + } + + public boolean isIffflag() { + return iffflag; + } + + public void setIffflag(boolean iffflag) { + this.iffflag = iffflag; + } + + public void setElseEdge(StatEdge elseedge) { + this.elseedge = elseedge; + } + + public void setIfEdge(StatEdge ifedge) { + this.ifedge = ifedge; + } + + public StatEdge getIfEdge() { + return ifedge; + } + + public StatEdge getElseEdge() { + return elseedge; + } +} |