2 * Copyright 2000-2014 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.java.decompiler.modules.decompiler.stats;
18 import org.jetbrains.java.decompiler.code.CodeConstants;
19 import org.jetbrains.java.decompiler.main.DecompilerContext;
20 import org.jetbrains.java.decompiler.main.TextBuffer;
21 import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
22 import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
23 import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
24 import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
25 import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
26 import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
27 import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
28 import org.jetbrains.java.decompiler.struct.gen.VarType;
29 import org.jetbrains.java.decompiler.util.InterpreterUtil;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.HashSet;
34 import java.util.List;
36 public class CatchAllStatement extends Statement {
38 private Statement handler;
40 private boolean isFinally;
42 private VarExprent monitor;
44 private List<VarExprent> vars = new ArrayList<VarExprent>();
46 // *****************************************************************************
48 // *****************************************************************************
50 private CatchAllStatement() {
51 type = Statement.TYPE_CATCHALL;
54 private CatchAllStatement(Statement head, Statement handler) {
59 stats.addWithKey(head, head.id);
61 this.handler = handler;
62 stats.addWithKey(handler, handler.id);
64 List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
65 if (!lstSuccs.isEmpty()) {
66 StatEdge edge = lstSuccs.get(0);
67 if (edge.getType() == StatEdge.TYPE_REGULAR) {
68 post = edge.getDestination();
72 vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
73 new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
74 (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
78 // *****************************************************************************
80 // *****************************************************************************
82 public static Statement isHead(Statement head) {
84 if (head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
88 HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
90 if (setHandlers.size() != 1) {
94 for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
95 Statement exc = edge.getDestination();
97 if (edge.getExceptions() == null && setHandlers.contains(exc) && exc.getLastBasicType() == LASTBASICTYPE_GENERAL) {
98 List<StatEdge> lstSuccs = exc.getSuccessorEdges(STATEDGE_DIRECT_ALL);
99 if (lstSuccs.isEmpty() || lstSuccs.get(0).getType() != StatEdge.TYPE_REGULAR) {
101 if (head.isMonitorEnter() || exc.isMonitorEnter()) {
105 if (DecHelper.checkStatementExceptions(Arrays.asList(head, exc))) {
106 return new CatchAllStatement(head, exc);
115 public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
116 String indstr = InterpreterUtil.getIndentString(indent);
117 String indstr1 = null;
119 String new_line_separator = DecompilerContext.getNewLineSeparator();
121 TextBuffer buf = new TextBuffer();
123 buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
125 boolean labeled = isLabeled();
127 buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator);
128 tracer.incrementCurrentSourceLine();
131 List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
132 if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally &&
133 !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) {
134 TextBuffer content = ExprProcessor.jmpWrapper(first, indent, true, tracer);
135 content.setLength(content.length() - new_line_separator.length());
139 buf.append(indstr).append("try {").append(new_line_separator);
140 tracer.incrementCurrentSourceLine();
141 buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
142 buf.append(indstr).append("}");
145 buf.append(isFinally ? " finally" :
146 " catch (" + vars.get(0).toJava(indent, tracer) + ")").append(" {").append(new_line_separator);
147 tracer.incrementCurrentSourceLine();
149 if (monitor != null) {
150 indstr1 = InterpreterUtil.getIndentString(indent + 1);
151 buf.append(indstr1).append("if(").append(monitor.toJava(indent, tracer)).append(") {").append(new_line_separator);
152 tracer.incrementCurrentSourceLine();
155 buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true, tracer));
157 if (monitor != null) {
158 buf.append(indstr1).append("}").append(new_line_separator);
159 tracer.incrementCurrentSourceLine();
162 buf.append(indstr).append("}").append(new_line_separator);
163 tracer.incrementCurrentSourceLine();
168 public void replaceStatement(Statement oldstat, Statement newstat) {
170 if (handler == oldstat) {
174 super.replaceStatement(oldstat, newstat);
177 public Statement getSimpleCopy() {
179 CatchAllStatement cas = new CatchAllStatement();
181 cas.isFinally = this.isFinally;
183 if (this.monitor != null) {
184 cas.monitor = new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
186 (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR));
189 if (!this.vars.isEmpty()) {
190 // FIXME: WTF??? vars?!
191 vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
192 new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
193 (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
199 public void initSimpleCopy() {
200 first = stats.get(0);
201 handler = stats.get(1);
204 // *****************************************************************************
205 // getter and setter methods
206 // *****************************************************************************
208 public Statement getHandler() {
213 public void setHandler(Statement handler) {
214 this.handler = handler;
218 public boolean isFinally() {
223 public void setFinally(boolean isFinally) {
224 this.isFinally = isFinally;
228 public VarExprent getMonitor() {
233 public void setMonitor(VarExprent monitor) {
234 this.monitor = monitor;
237 public List<VarExprent> getVars() {