diff options
Diffstat (limited to 'plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java')
-rw-r--r-- | plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java new file mode 100644 index 000000000000..15af3c604a2e --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java @@ -0,0 +1,233 @@ +/* + * 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.code.CodeConstants; +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.collectors.CounterContainer; +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.VarExprent; +import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; +import org.jetbrains.java.decompiler.struct.gen.VarType; +import org.jetbrains.java.decompiler.util.InterpreterUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +public class CatchAllStatement extends Statement { + + private Statement handler; + + private boolean isFinally; + + private VarExprent monitor; + + private List<VarExprent> vars = new ArrayList<VarExprent>(); + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + private CatchAllStatement() { + type = Statement.TYPE_CATCHALL; + } + + private CatchAllStatement(Statement head, Statement handler) { + + this(); + + first = head; + stats.addWithKey(head, head.id); + + this.handler = handler; + stats.addWithKey(handler, handler.id); + + List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL); + if (!lstSuccs.isEmpty()) { + StatEdge edge = lstSuccs.get(0); + if (edge.getType() == StatEdge.TYPE_REGULAR) { + post = edge.getDestination(); + } + } + + vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), + new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"), + (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); + } + + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public static Statement isHead(Statement head) { + + if (head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) { + return null; + } + + HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head); + + if (setHandlers.size() != 1) { + return null; + } + + for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) { + Statement exc = edge.getDestination(); + + if (edge.getExceptions() == null && setHandlers.contains(exc) && exc.getLastBasicType() == LASTBASICTYPE_GENERAL) { + List<StatEdge> lstSuccs = exc.getSuccessorEdges(STATEDGE_DIRECT_ALL); + if (lstSuccs.isEmpty() || lstSuccs.get(0).getType() != StatEdge.TYPE_REGULAR) { + + if (head.isMonitorEnter() || exc.isMonitorEnter()) { + return null; + } + + if (DecHelper.checkStatementExceptions(Arrays.asList(head, exc))) { + return new CatchAllStatement(head, exc); + } + } + } + } + + return null; + } + + public String toJava(int indent) { + String indstr = InterpreterUtil.getIndentString(indent); + String indstr1 = null; + + String new_line_separator = DecompilerContext.getNewLineSeparator(); + + StringBuilder buf = new StringBuilder(); + + buf.append(ExprProcessor.listToJava(varDefinitions, indent)); + + boolean labeled = isLabeled(); + if (labeled) { + buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + } + + List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL); + if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally && + !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) { + String content = ExprProcessor.jmpWrapper(first, indent, true); + content = content.substring(0, content.length() - new_line_separator.length()); + + buf.append(content); + } + else { + buf.append(indstr).append("try {").append(new_line_separator); + buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); + buf.append(indstr).append("}"); + } + + buf.append(isFinally ? " finally" : + " catch (" + vars.get(0).toJava(indent) + ")").append(" {").append(new_line_separator); + + if (monitor != null) { + indstr1 = InterpreterUtil.getIndentString(indent + 1); + buf.append(indstr1).append("if(").append(monitor.toJava(indent)).append(") {").append(new_line_separator); + } + + buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true)); + + if (monitor != null) { + buf.append(indstr1).append("}").append(new_line_separator); + } + + buf.append(indstr).append("}").append(new_line_separator); + + return buf.toString(); + } + + public void replaceStatement(Statement oldstat, Statement newstat) { + + if (handler == oldstat) { + handler = newstat; + } + + super.replaceStatement(oldstat, newstat); + } + + public Statement getSimpleCopy() { + + CatchAllStatement cas = new CatchAllStatement(); + + cas.isFinally = this.isFinally; + + if (this.monitor != null) { + cas.monitor = new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), + VarType.VARTYPE_INT, + (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)); + } + + if (!this.vars.isEmpty()) { + // FIXME: WTF??? vars?! + vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), + new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"), + (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); + } + + return cas; + } + + public void initSimpleCopy() { + first = stats.get(0); + handler = stats.get(1); + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public Statement getHandler() { + return handler; + } + + + public void setHandler(Statement handler) { + this.handler = handler; + } + + + public boolean isFinally() { + return isFinally; + } + + + public void setFinally(boolean isFinally) { + this.isFinally = isFinally; + } + + + public VarExprent getMonitor() { + return monitor; + } + + + public void setMonitor(VarExprent monitor) { + this.monitor = monitor; + } + + public List<VarExprent> getVars() { + return vars; + } +} |