summaryrefslogtreecommitdiff
path: root/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java
diff options
context:
space:
mode:
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.java416
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;
+ }
+}