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;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashSet;
33 import java.util.List;
35 public class CatchAllStatement extends Statement {
37 private Statement handler;
39 private boolean isFinally;
41 private VarExprent monitor;
43 private List<VarExprent> vars = new ArrayList<VarExprent>();
45 // *****************************************************************************
47 // *****************************************************************************
49 private CatchAllStatement() {
50 type = Statement.TYPE_CATCHALL;
53 private CatchAllStatement(Statement head, Statement handler) {
58 stats.addWithKey(head, head.id);
60 this.handler = handler;
61 stats.addWithKey(handler, handler.id);
63 List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
64 if (!lstSuccs.isEmpty()) {
65 StatEdge edge = lstSuccs.get(0);
66 if (edge.getType() == StatEdge.TYPE_REGULAR) {
67 post = edge.getDestination();
71 vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
72 new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
73 (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
77 // *****************************************************************************
79 // *****************************************************************************
81 public static Statement isHead(Statement head) {
83 if (head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
87 HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
89 if (setHandlers.size() != 1) {
93 for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
94 Statement exc = edge.getDestination();
96 if (edge.getExceptions() == null && setHandlers.contains(exc) && exc.getLastBasicType() == LASTBASICTYPE_GENERAL) {
97 List<StatEdge> lstSuccs = exc.getSuccessorEdges(STATEDGE_DIRECT_ALL);
98 if (lstSuccs.isEmpty() || lstSuccs.get(0).getType() != StatEdge.TYPE_REGULAR) {
100 if (head.isMonitorEnter() || exc.isMonitorEnter()) {
104 if (DecHelper.checkStatementExceptions(Arrays.asList(head, exc))) {
105 return new CatchAllStatement(head, exc);
114 public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
115 String new_line_separator = DecompilerContext.getNewLineSeparator();
117 TextBuffer buf = new TextBuffer();
119 buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer));
121 boolean labeled = isLabeled();
123 buf.appendIndent(indent).append("label").append(this.id.toString()).append(":").appendLineSeparator();
124 tracer.incrementCurrentSourceLine();
127 List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
128 if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally &&
129 !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) {
130 TextBuffer content = ExprProcessor.jmpWrapper(first, indent, true, tracer);
131 content.setLength(content.length() - new_line_separator.length());
132 tracer.incrementCurrentSourceLine(-1);
136 buf.appendIndent(indent).append("try {").appendLineSeparator();
137 tracer.incrementCurrentSourceLine();
138 buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer));
139 buf.appendIndent(indent).append("}");
142 buf.append(isFinally ? " finally" :
143 " catch (" + vars.get(0).toJava(indent, tracer) + ")").append(" {").appendLineSeparator();
144 tracer.incrementCurrentSourceLine();
146 if (monitor != null) {
147 buf.appendIndent(indent+1).append("if(").append(monitor.toJava(indent, tracer)).append(") {").appendLineSeparator();
148 tracer.incrementCurrentSourceLine();
151 buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true, tracer));
153 if (monitor != null) {
154 buf.appendIndent(indent + 1).append("}").appendLineSeparator();
155 tracer.incrementCurrentSourceLine();
158 buf.appendIndent(indent).append("}").appendLineSeparator();
159 tracer.incrementCurrentSourceLine();
164 public void replaceStatement(Statement oldstat, Statement newstat) {
166 if (handler == oldstat) {
170 super.replaceStatement(oldstat, newstat);
173 public Statement getSimpleCopy() {
175 CatchAllStatement cas = new CatchAllStatement();
177 cas.isFinally = this.isFinally;
179 if (this.monitor != null) {
180 cas.monitor = new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
182 (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR));
185 if (!this.vars.isEmpty()) {
186 // FIXME: WTF??? vars?!
187 vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
188 new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
189 (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
195 public void initSimpleCopy() {
196 first = stats.get(0);
197 handler = stats.get(1);
200 // *****************************************************************************
201 // getter and setter methods
202 // *****************************************************************************
204 public Statement getHandler() {
209 public void setHandler(Statement handler) {
210 this.handler = handler;
214 public boolean isFinally() {
219 public void setFinally(boolean isFinally) {
220 this.isFinally = isFinally;
224 public VarExprent getMonitor() {
229 public void setMonitor(VarExprent monitor) {
230 this.monitor = monitor;
233 public List<VarExprent> getVars() {