diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java')
-rw-r--r-- | src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java | 375 |
1 files changed, 189 insertions, 186 deletions
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java index 6387d45..17f5636 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java @@ -1,23 +1,20 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * 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 * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * 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 java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; @@ -29,178 +26,184 @@ 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.HashSet; +import java.util.List; + public class CatchStatement extends Statement { - - private List<List<String>> exctstrings = new ArrayList<List<String>>(); - - private List<VarExprent> vars = new ArrayList<VarExprent>(); - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - private CatchStatement() { - type = TYPE_TRYCATCH; - } - - private CatchStatement(Statement head, Statement next, HashSet<Statement> setHandlers) { - - this(); - - first = head; - stats.addWithKey(first, first.id); - - for(StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) { - Statement stat = edge.getDestination(); - - if(setHandlers.contains(stat)) { - stats.addWithKey(stat, stat.id); - exctstrings.add(new ArrayList<String>(edge.getExceptions())); - - vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), - new VarType(CodeConstants.TYPE_OBJECT, 0, edge.getExceptions().get(0)), // FIXME: for now simply the first type. Should get the first common superclass when possible. - (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); - } - } - - if(next != null) { - post = next; - } - - } - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public static Statement isHead(Statement head) { - - if(head.getLastBasicType() != LASTBASICTYPE_GENERAL) { - return null; - } - - HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head); - - if(!setHandlers.isEmpty()) { - - int hnextcount = 0; // either no statements with connection to next, or more than 1 - - Statement next = null; - List<StatEdge> lstHeadSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL); - if(!lstHeadSuccs.isEmpty() && lstHeadSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) { - next = lstHeadSuccs.get(0).getDestination(); - hnextcount = 2; - } - - for(StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) { - Statement stat = edge.getDestination(); - - boolean handlerok = true; - - if(edge.getExceptions() != null && setHandlers.contains(stat)) { - if(stat.getLastBasicType() != LASTBASICTYPE_GENERAL) { - handlerok = false; - } else { - List<StatEdge> lstStatSuccs = stat.getSuccessorEdges(STATEDGE_DIRECT_ALL); - if(!lstStatSuccs.isEmpty() && lstStatSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) { - - Statement statn = lstStatSuccs.get(0).getDestination(); - - if(next == null) { - next = statn; - } else if(next != statn) { - handlerok = false; - } - - if(handlerok) { - hnextcount++; - } - } - } - } else { - handlerok = false; - } - - if(!handlerok) { - setHandlers.remove(stat); - } - } - - if(hnextcount != 1 && !setHandlers.isEmpty()) { - List<Statement> lst = new ArrayList<Statement>(); - lst.add(head); - lst.addAll(setHandlers); - - for(Statement st : lst) { - if(st.isMonitorEnter()) { - return null; - } - } - - if(DecHelper.checkStatementExceptions(lst)) { - return new CatchStatement(head, next, setHandlers); - } - } - } - return null; - } - - public String toJava(int indent) { - String indstr = InterpreterUtil.getIndentString(indent); - StringBuffer buf = new StringBuffer(); - - String new_line_separator = DecompilerContext.getNewLineSeparator(); - - buf.append(ExprProcessor.listToJava(varDefinitions, indent)); - - if(isLabeled()) { - buf.append(indstr+"label"+this.id+":" + new_line_separator); - } - - buf.append(indstr+"try {" + new_line_separator); - buf.append(ExprProcessor.jmpWrapper(first, indent+1, true)); - buf.append(indstr+"}"); - - for(int i=1;i<stats.size();i++) { - List<String> exception_types = exctstrings.get(i - 1); - - buf.append(" catch ("); - if(exception_types.size() > 1) { // multi-catch, Java 7 style - for(int exc_index = 1; exc_index < exception_types.size(); ++exc_index) { - VarType exc_type = new VarType(CodeConstants.TYPE_OBJECT, 0, exception_types.get(exc_index)); - String exc_type_name = ExprProcessor.getCastTypeName(exc_type); - - buf.append(exc_type_name + " | "); - } - } - buf.append(vars.get(i-1).toJava(indent)); - buf.append(") {"+new_line_separator+ExprProcessor.jmpWrapper(stats.get(i), indent+1, true)+indstr+"}"); - } - buf.append(new_line_separator); - - return buf.toString(); - } - - public Statement getSimpleCopy() { - - CatchStatement cs = new CatchStatement(); - - for(List<String> exc : this.exctstrings) { - cs.exctstrings.add(new ArrayList<String>(exc)); - cs.vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), - new VarType(CodeConstants.TYPE_OBJECT, 0, exc.get(0)), - (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); - } - - return cs; - } - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public List<VarExprent> getVars() { - return vars; - } - + + private List<List<String>> exctstrings = new ArrayList<List<String>>(); + + private List<VarExprent> vars = new ArrayList<VarExprent>(); + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + private CatchStatement() { + type = TYPE_TRYCATCH; + } + + private CatchStatement(Statement head, Statement next, HashSet<Statement> setHandlers) { + + this(); + + first = head; + stats.addWithKey(first, first.id); + + for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) { + Statement stat = edge.getDestination(); + + if (setHandlers.contains(stat)) { + stats.addWithKey(stat, stat.id); + exctstrings.add(new ArrayList<String>(edge.getExceptions())); + + vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), + new VarType(CodeConstants.TYPE_OBJECT, 0, edge.getExceptions().get(0)), + // FIXME: for now simply the first type. Should get the first common superclass when possible. + (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); + } + } + + if (next != null) { + post = next; + } + } + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public static Statement isHead(Statement head) { + + if (head.getLastBasicType() != LASTBASICTYPE_GENERAL) { + return null; + } + + HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head); + + if (!setHandlers.isEmpty()) { + + int hnextcount = 0; // either no statements with connection to next, or more than 1 + + Statement next = null; + List<StatEdge> lstHeadSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL); + if (!lstHeadSuccs.isEmpty() && lstHeadSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) { + next = lstHeadSuccs.get(0).getDestination(); + hnextcount = 2; + } + + for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) { + Statement stat = edge.getDestination(); + + boolean handlerok = true; + + if (edge.getExceptions() != null && setHandlers.contains(stat)) { + if (stat.getLastBasicType() != LASTBASICTYPE_GENERAL) { + handlerok = false; + } + else { + List<StatEdge> lstStatSuccs = stat.getSuccessorEdges(STATEDGE_DIRECT_ALL); + if (!lstStatSuccs.isEmpty() && lstStatSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) { + + Statement statn = lstStatSuccs.get(0).getDestination(); + + if (next == null) { + next = statn; + } + else if (next != statn) { + handlerok = false; + } + + if (handlerok) { + hnextcount++; + } + } + } + } + else { + handlerok = false; + } + + if (!handlerok) { + setHandlers.remove(stat); + } + } + + if (hnextcount != 1 && !setHandlers.isEmpty()) { + List<Statement> lst = new ArrayList<Statement>(); + lst.add(head); + lst.addAll(setHandlers); + + for (Statement st : lst) { + if (st.isMonitorEnter()) { + return null; + } + } + + if (DecHelper.checkStatementExceptions(lst)) { + return new CatchStatement(head, next, setHandlers); + } + } + } + return null; + } + + public String toJava(int indent) { + String indstr = InterpreterUtil.getIndentString(indent); + StringBuffer buf = new StringBuffer(); + + String new_line_separator = DecompilerContext.getNewLineSeparator(); + + buf.append(ExprProcessor.listToJava(varDefinitions, indent)); + + if (isLabeled()) { + buf.append(indstr + "label" + this.id + ":" + new_line_separator); + } + + buf.append(indstr + "try {" + new_line_separator); + buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true)); + buf.append(indstr + "}"); + + for (int i = 1; i < stats.size(); i++) { + List<String> exception_types = exctstrings.get(i - 1); + + buf.append(" catch ("); + if (exception_types.size() > 1) { // multi-catch, Java 7 style + for (int exc_index = 1; exc_index < exception_types.size(); ++exc_index) { + VarType exc_type = new VarType(CodeConstants.TYPE_OBJECT, 0, exception_types.get(exc_index)); + String exc_type_name = ExprProcessor.getCastTypeName(exc_type); + + buf.append(exc_type_name + " | "); + } + } + buf.append(vars.get(i - 1).toJava(indent)); + buf.append(") {" + new_line_separator + ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true) + indstr + "}"); + } + buf.append(new_line_separator); + + return buf.toString(); + } + + public Statement getSimpleCopy() { + + CatchStatement cs = new CatchStatement(); + + for (List<String> exc : this.exctstrings) { + cs.exctstrings.add(new ArrayList<String>(exc)); + cs.vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), + new VarType(CodeConstants.TYPE_OBJECT, 0, exc.get(0)), + (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); + } + + return cs; + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public List<VarExprent> getVars() { + return vars; + } } |