diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/struct/gen')
9 files changed, 1141 insertions, 1124 deletions
diff --git a/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java b/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java index db6ecd1..53269da 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java @@ -1,98 +1,100 @@ /* - * 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.struct.gen; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.util.ListStack; +import java.util.ArrayList; +import java.util.List; + public class DataPoint { - private List<VarType> localVariables = new ArrayList<VarType>(); - - private ListStack<VarType> stack = new ListStack<VarType>(); - - - public void setVariable(int index, VarType value) { - if(index>=localVariables.size()) { - for(int i=localVariables.size();i<=index;i++) { - localVariables.add(new VarType(CodeConstants.TYPE_NOTINITIALIZED)); - } - } - - localVariables.set(index, value); - } - - public VarType getVariable(int index) { - if(index<localVariables.size()) { - return localVariables.get(index); - } else if(index<0) { - throw new IndexOutOfBoundsException(); - } else { - return new VarType(CodeConstants.TYPE_NOTINITIALIZED); - } - } - - public DataPoint copy() { - DataPoint point = new DataPoint(); - point.setLocalVariables(new ArrayList<VarType>(localVariables)); - point.setStack(stack.clone()); - return point; - } - - public static DataPoint getInitialDataPoint(StructMethod mt) { - - DataPoint point = new DataPoint(); - - MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); - - int k = 0; - if((mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0) { - point.setVariable(k++, new VarType(CodeConstants.TYPE_OBJECT, 0, null)); - } - - for(int i=0;i<md.params.length;i++) { - VarType var = md.params[i]; - - point.setVariable(k++, var); - if(var.stack_size == 2) { - point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY)); - } - } - - return point; - } - - - public List<VarType> getLocalVariables() { - return localVariables; - } - - public void setLocalVariables(List<VarType> localVariables) { - this.localVariables = localVariables; - } - - public ListStack<VarType> getStack() { - return stack; - } - - public void setStack(ListStack<VarType> stack) { - this.stack = stack; - } - + private List<VarType> localVariables = new ArrayList<VarType>(); + + private ListStack<VarType> stack = new ListStack<VarType>(); + + + public void setVariable(int index, VarType value) { + if (index >= localVariables.size()) { + for (int i = localVariables.size(); i <= index; i++) { + localVariables.add(new VarType(CodeConstants.TYPE_NOTINITIALIZED)); + } + } + + localVariables.set(index, value); + } + + public VarType getVariable(int index) { + if (index < localVariables.size()) { + return localVariables.get(index); + } + else if (index < 0) { + throw new IndexOutOfBoundsException(); + } + else { + return new VarType(CodeConstants.TYPE_NOTINITIALIZED); + } + } + + public DataPoint copy() { + DataPoint point = new DataPoint(); + point.setLocalVariables(new ArrayList<VarType>(localVariables)); + point.setStack(stack.clone()); + return point; + } + + public static DataPoint getInitialDataPoint(StructMethod mt) { + + DataPoint point = new DataPoint(); + + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); + + int k = 0; + if ((mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0) { + point.setVariable(k++, new VarType(CodeConstants.TYPE_OBJECT, 0, null)); + } + + for (int i = 0; i < md.params.length; i++) { + VarType var = md.params[i]; + + point.setVariable(k++, var); + if (var.stack_size == 2) { + point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY)); + } + } + + return point; + } + + + public List<VarType> getLocalVariables() { + return localVariables; + } + + public void setLocalVariables(List<VarType> localVariables) { + this.localVariables = localVariables; + } + + public ListStack<VarType> getStack() { + return stack; + } + + public void setStack(ListStack<VarType> stack) { + this.stack = stack; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java index a475937..ff731ae 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java @@ -1,58 +1,59 @@ /* - * 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.struct.gen; public class FieldDescriptor { - - public static final FieldDescriptor INTEGER_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Integer;"); - public static final FieldDescriptor LONG_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Long;"); - public static final FieldDescriptor FLOAT_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Float;"); - public static final FieldDescriptor DOUBLE_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Double;"); - - public VarType type; - - public String descriptorString; - - private FieldDescriptor() {} - - public static FieldDescriptor parseDescriptor(String descr) { - - FieldDescriptor fd = new FieldDescriptor(); - - fd.type = new VarType(descr); - fd.descriptorString = descr; - - return fd; - } - - public String getDescriptor() { - return type.toString(); - } - - @Override - public boolean equals(Object o) { - if(o == this) return true; - if(o == null || !(o instanceof FieldDescriptor)) return false; + + public static final FieldDescriptor INTEGER_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Integer;"); + public static final FieldDescriptor LONG_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Long;"); + public static final FieldDescriptor FLOAT_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Float;"); + public static final FieldDescriptor DOUBLE_DESCRIPTOR = FieldDescriptor.parseDescriptor("Ljava/lang/Double;"); + + public VarType type; + + public String descriptorString; + + private FieldDescriptor() { + } + + public static FieldDescriptor parseDescriptor(String descr) { + + FieldDescriptor fd = new FieldDescriptor(); + + fd.type = new VarType(descr); + fd.descriptorString = descr; + + return fd; + } + + public String getDescriptor() { + return type.toString(); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (o == null || !(o instanceof FieldDescriptor)) return false; FieldDescriptor fd = (FieldDescriptor)o; return type.equals(fd.type); } - @Override - public int hashCode() { - return type.hashCode(); - } - + @Override + public int hashCode() { + return type.hashCode(); + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java index 77a8394..7dbc16c 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java @@ -1,17 +1,18 @@ /* - * 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.struct.gen; import java.util.ArrayList; @@ -20,83 +21,82 @@ import java.util.List; public class MethodDescriptor { - public VarType[] params; - - public VarType ret; - - - public static MethodDescriptor parseDescriptor(String mdescr) { - - MethodDescriptor md = new MethodDescriptor(); - - List<String> lst = new ArrayList<String>(); - String[] pars = mdescr.split("[()]"); - - String par = pars[1]; - - int indexFrom = -1, ind,index = 0; - int len = par.length(); - - for(;index<len;index++) { - - switch(par.charAt(index)){ - case '[': - if(indexFrom<0){ - indexFrom = index; - } - break; - case 'L': - ind = par.indexOf(";", index); - lst.add(par.substring(indexFrom<0?index:indexFrom, ind+1)); - index = ind; - indexFrom = -1; - break; - default: - lst.add(par.substring(indexFrom<0?index:indexFrom, index+1)); - indexFrom = -1; - } - } - - lst.add(pars[2]); - - - md.params = new VarType[lst.size()-1]; - - int i = 0; - for(;i<lst.size()-1;i++) { - md.params[i] = new VarType(lst.get(i)); - } - md.ret = new VarType(lst.get(i)); - - return md; - } - - public String getDescriptor() { - String res = "("; - - for(int j = 0;j<params.length;j++) { - res+=params[j].toString(); - } - - res+=")"+ret.toString(); - - return res; - } - - @Override - public boolean equals(Object o) { - if(o == this) return true; - if(o == null || !(o instanceof MethodDescriptor)) return false; + public VarType[] params; + + public VarType ret; + + + public static MethodDescriptor parseDescriptor(String mdescr) { + + MethodDescriptor md = new MethodDescriptor(); + + List<String> lst = new ArrayList<String>(); + String[] pars = mdescr.split("[()]"); + + String par = pars[1]; + + int indexFrom = -1, ind, index = 0; + int len = par.length(); + + for (; index < len; index++) { + + switch (par.charAt(index)) { + case '[': + if (indexFrom < 0) { + indexFrom = index; + } + break; + case 'L': + ind = par.indexOf(";", index); + lst.add(par.substring(indexFrom < 0 ? index : indexFrom, ind + 1)); + index = ind; + indexFrom = -1; + break; + default: + lst.add(par.substring(indexFrom < 0 ? index : indexFrom, index + 1)); + indexFrom = -1; + } + } + + lst.add(pars[2]); + + + md.params = new VarType[lst.size() - 1]; + + int i = 0; + for (; i < lst.size() - 1; i++) { + md.params[i] = new VarType(lst.get(i)); + } + md.ret = new VarType(lst.get(i)); + + return md; + } + + public String getDescriptor() { + String res = "("; + + for (int j = 0; j < params.length; j++) { + res += params[j].toString(); + } + + res += ")" + ret.toString(); + + return res; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (o == null || !(o instanceof MethodDescriptor)) return false; MethodDescriptor md = (MethodDescriptor)o; return ret.equals(md.ret) && Arrays.equals(params, md.params); } - @Override - public int hashCode() { + @Override + public int hashCode() { int result = ret.hashCode(); result = 31 * result + params.length; return result; - } - + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/VarType.java b/src/org/jetbrains/java/decompiler/struct/gen/VarType.java index 5ee0c4b..79e2cbf 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/VarType.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/VarType.java @@ -1,410 +1,422 @@ /* - * 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.struct.gen; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.util.InterpreterUtil; public class VarType { // TODO: optimize switch - - public static final int FALSEBOOLEAN = 1; - - public static final VarType VARTYPE_UNKNOWN = new VarType(CodeConstants.TYPE_UNKNOWN); - public static final VarType VARTYPE_INT = new VarType(CodeConstants.TYPE_INT); - public static final VarType VARTYPE_FLOAT = new VarType(CodeConstants.TYPE_FLOAT); - public static final VarType VARTYPE_LONG = new VarType(CodeConstants.TYPE_LONG); - public static final VarType VARTYPE_DOUBLE = new VarType(CodeConstants.TYPE_DOUBLE); - public static final VarType VARTYPE_BYTE = new VarType(CodeConstants.TYPE_BYTE); - public static final VarType VARTYPE_CHAR = new VarType(CodeConstants.TYPE_CHAR); - public static final VarType VARTYPE_SHORT = new VarType(CodeConstants.TYPE_SHORT); - public static final VarType VARTYPE_BOOLEAN = new VarType(CodeConstants.TYPE_BOOLEAN); - public static final VarType VARTYPE_BYTECHAR = new VarType(CodeConstants.TYPE_BYTECHAR); - public static final VarType VARTYPE_SHORTCHAR = new VarType(CodeConstants.TYPE_SHORTCHAR); - - public static final VarType VARTYPE_NULL = new VarType(CodeConstants.TYPE_NULL,0,null); - public static final VarType VARTYPE_GROUP2EMPTY = new VarType(CodeConstants.TYPE_GROUP2EMPTY); - public static final VarType VARTYPE_STRING = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String"); - public static final VarType VARTYPE_CLASS = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"); - public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object"); - public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID); - - public int type; - - public int type_family; - - public int arraydim; - - public String value; - - public int stack_size; - - public int convinfo; - - public VarType(int type) { - this.type = type; - this.arraydim = 0; - - value = getChar(type); - setStackSize(type); - setFamily(); - } - - public VarType(int type, int arraydim) { - this(type); - this.arraydim = arraydim; - setFamily(); - } - - public VarType(int type, int arraydim, String value) { - this(type); - this.arraydim = arraydim; - this.value = value; - setFamily(); - } - - public VarType(String strtype) { - this(strtype, false); - } - - public VarType(String strtype, boolean cltype) { - parseTypeString(strtype, cltype); - setStackSize(type); - setFamily(); - } - - public void decArrayDim() { - if(arraydim > 0) { - arraydim--; - setFamily(); - } else { - // throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case - } - } - - public String toString() { - String res = ""; - - for(int i=0;i<arraydim;i++) { - res+="["; - } - - if(type == CodeConstants.TYPE_OBJECT) { - res+="L"+value+";"; - } else { - res+=value; - } - - return res; - } - - public VarType copy() { - VarType v = new VarType(type, arraydim, value); - v.convinfo = convinfo; - return v; - } - - public boolean isFalseBoolean() { - return (convinfo & VarType.FALSEBOOLEAN) != 0; - } - - public boolean isSuperset(VarType val) { - - return this.equals(val) || this.isStrictSuperset(val); - } - - public boolean isStrictSuperset(VarType val) { - - int valtype = val.type; - - if(valtype == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) { - return true; - } - - if(val.arraydim > 0) { - return this.equals(VARTYPE_OBJECT); - } else if(arraydim > 0) { - return (valtype == CodeConstants.TYPE_NULL); - } - - boolean res = false; - - switch(type) { - case CodeConstants.TYPE_INT: - res |= (valtype == CodeConstants.TYPE_SHORT || - valtype == CodeConstants.TYPE_CHAR); - case CodeConstants.TYPE_SHORT: - res |= (valtype == CodeConstants.TYPE_BYTE); - case CodeConstants.TYPE_CHAR: - res |= (valtype == CodeConstants.TYPE_SHORTCHAR); - case CodeConstants.TYPE_BYTE: - case CodeConstants.TYPE_SHORTCHAR: - res |= (valtype == CodeConstants.TYPE_BYTECHAR); - case CodeConstants.TYPE_BYTECHAR: - res |= (valtype == CodeConstants.TYPE_BOOLEAN); - break; - case CodeConstants.TYPE_OBJECT: - if(valtype == CodeConstants.TYPE_NULL) { - return true; - } else if(this.equals(VARTYPE_OBJECT)) { - return valtype == CodeConstants.TYPE_OBJECT && - !val.equals(VARTYPE_OBJECT); - } - } - - return res; - } - - // type1 and type2 must not be null - public static VarType getCommonMinType(VarType type1, VarType type2) { - - if(type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans - return type1.isFalseBoolean() ? type2 : type1; - } - - if(type1.isSuperset(type2)) { - return type2; - } else if(type2.isSuperset(type1)) { - return type1; - } else if(type1.type_family == type2.type_family) { - switch(type1.type_family) { - case CodeConstants.TYPE_FAMILY_INTEGER: - if((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT) - || (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) { - return VarType.VARTYPE_SHORTCHAR; - } else { - return VarType.VARTYPE_BYTECHAR; - } - case CodeConstants.TYPE_FAMILY_OBJECT: - return VarType.VARTYPE_NULL; - } - } - - return null; - } - - // type1 and type2 must not be null - public static VarType getCommonSupertype(VarType type1, VarType type2) { - - if(type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans - return type1.isFalseBoolean() ? type1 : type2; - } - - if(type1.isSuperset(type2)) { - return type1; - } else if(type2.isSuperset(type1)) { - return type2; - } else if(type1.type_family == type2.type_family) { - switch(type1.type_family) { - case CodeConstants.TYPE_FAMILY_INTEGER: - if((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE) - || (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) { - return VarType.VARTYPE_SHORT; - } else { - return VarType.VARTYPE_INT; - } - case CodeConstants.TYPE_FAMILY_OBJECT: - return VarType.VARTYPE_OBJECT; - } - } - - return null; - } - - public static VarType getMinTypeInFamily(int family) { - switch(family) { - case CodeConstants.TYPE_FAMILY_BOOLEAN: - return VarType.VARTYPE_BOOLEAN; - case CodeConstants.TYPE_FAMILY_INTEGER: - return VarType.VARTYPE_BYTECHAR; - case CodeConstants.TYPE_FAMILY_OBJECT: - return VarType.VARTYPE_NULL; - case CodeConstants.TYPE_FAMILY_FLOAT: - return VarType.VARTYPE_FLOAT; - case CodeConstants.TYPE_FAMILY_LONG: - return VarType.VARTYPE_LONG; - case CodeConstants.TYPE_FAMILY_DOUBLE: - return VarType.VARTYPE_DOUBLE; - case CodeConstants.TYPE_FAMILY_UNKNOWN: - return VarType.VARTYPE_UNKNOWN; - default: - throw new RuntimeException("invalid type family!"); - } - } - - public boolean equals(Object o) { - - if(o == this) { - return true; - } - - if(o == null || !(o instanceof VarType)) { - return false; - } - - VarType vt = (VarType) o; - return type == vt.type && arraydim == vt.arraydim && InterpreterUtil.equalObjects(value, vt.value); - } - - private void parseTypeString(String strtype, boolean cltype) { - - for(int i=0;i<strtype.length();i++) { - switch(strtype.charAt(i)){ - case '[': - arraydim++; - break; - case 'L': - if(strtype.charAt(strtype.length()-1) == ';') { - type = CodeConstants.TYPE_OBJECT; - value = strtype.substring(i+1, strtype.length()-1); - return; - } - default: - value = strtype.substring(i, strtype.length()); - if((cltype && i == 0) || value.length()>1) { - type = CodeConstants.TYPE_OBJECT; - } else { - type = getType(value.charAt(0)); - } - return; - } - } - } - - private void setStackSize(int type) { - if(arraydim > 0) { - stack_size = 1; - } else { - stack_size = (type == CodeConstants.TYPE_DOUBLE || - type == CodeConstants.TYPE_LONG)?2: - ((type == CodeConstants.TYPE_VOID || - type == CodeConstants.TYPE_GROUP2EMPTY)?0:1); - } - } - - private int getType(char c) { - switch(c) { - case 'B': - return CodeConstants.TYPE_BYTE; - case 'C': - return CodeConstants.TYPE_CHAR; - case 'D': - return CodeConstants.TYPE_DOUBLE; - case 'F': - return CodeConstants.TYPE_FLOAT; - case 'I': - return CodeConstants.TYPE_INT; - case 'J': - return CodeConstants.TYPE_LONG; - case 'S': - return CodeConstants.TYPE_SHORT; - case 'Z': - return CodeConstants.TYPE_BOOLEAN; - case 'V': - return CodeConstants.TYPE_VOID; - case 'G': - return CodeConstants.TYPE_GROUP2EMPTY; - case 'N': - return CodeConstants.TYPE_NOTINITIALIZED; - case 'A': - return CodeConstants.TYPE_ADDRESS; - case 'X': - return CodeConstants.TYPE_BYTECHAR; - case 'Y': - return CodeConstants.TYPE_SHORTCHAR; - case 'U': - return CodeConstants.TYPE_UNKNOWN; - default: - throw new RuntimeException("Invalid type"); - } - } - - private String getChar(int type) { - switch(type) { - case CodeConstants.TYPE_BYTE: - return "B"; - case CodeConstants.TYPE_CHAR: - return "C"; - case CodeConstants.TYPE_DOUBLE: - return "D"; - case CodeConstants.TYPE_FLOAT: - return "F"; - case CodeConstants.TYPE_INT: - return "I"; - case CodeConstants.TYPE_LONG: - return "J"; - case CodeConstants.TYPE_SHORT: - return "S"; - case CodeConstants.TYPE_BOOLEAN: - return "Z"; - case CodeConstants.TYPE_VOID: - return "V"; - case CodeConstants.TYPE_GROUP2EMPTY: - return "G"; - case CodeConstants.TYPE_NOTINITIALIZED: - return "N"; - case CodeConstants.TYPE_ADDRESS: - return "A"; - case CodeConstants.TYPE_BYTECHAR: - return "X"; - case CodeConstants.TYPE_SHORTCHAR: - return "Y"; - case CodeConstants.TYPE_UNKNOWN: - return "U"; - case CodeConstants.TYPE_NULL: - case CodeConstants.TYPE_OBJECT: - return null; - default: - throw new RuntimeException("Invalid type"); - } - } - - public void setFamily() { - - if(arraydim > 0) { - this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; - return; - } - - switch(type) { - case CodeConstants.TYPE_BYTE: - case CodeConstants.TYPE_BYTECHAR: - case CodeConstants.TYPE_SHORTCHAR: - case CodeConstants.TYPE_CHAR: - case CodeConstants.TYPE_SHORT: - case CodeConstants.TYPE_INT: - this.type_family = CodeConstants.TYPE_FAMILY_INTEGER; - break; - case CodeConstants.TYPE_DOUBLE: - this.type_family = CodeConstants.TYPE_FAMILY_DOUBLE; - break; - case CodeConstants.TYPE_FLOAT: - this.type_family = CodeConstants.TYPE_FAMILY_FLOAT; - break; - case CodeConstants.TYPE_LONG: - this.type_family = CodeConstants.TYPE_FAMILY_LONG; - break; - case CodeConstants.TYPE_BOOLEAN: - this.type_family = CodeConstants.TYPE_FAMILY_BOOLEAN; - break; - case CodeConstants.TYPE_NULL: - case CodeConstants.TYPE_OBJECT: - this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; - break; - default: - this.type_family = CodeConstants.TYPE_FAMILY_UNKNOWN; - } - } - + + public static final int FALSEBOOLEAN = 1; + + public static final VarType VARTYPE_UNKNOWN = new VarType(CodeConstants.TYPE_UNKNOWN); + public static final VarType VARTYPE_INT = new VarType(CodeConstants.TYPE_INT); + public static final VarType VARTYPE_FLOAT = new VarType(CodeConstants.TYPE_FLOAT); + public static final VarType VARTYPE_LONG = new VarType(CodeConstants.TYPE_LONG); + public static final VarType VARTYPE_DOUBLE = new VarType(CodeConstants.TYPE_DOUBLE); + public static final VarType VARTYPE_BYTE = new VarType(CodeConstants.TYPE_BYTE); + public static final VarType VARTYPE_CHAR = new VarType(CodeConstants.TYPE_CHAR); + public static final VarType VARTYPE_SHORT = new VarType(CodeConstants.TYPE_SHORT); + public static final VarType VARTYPE_BOOLEAN = new VarType(CodeConstants.TYPE_BOOLEAN); + public static final VarType VARTYPE_BYTECHAR = new VarType(CodeConstants.TYPE_BYTECHAR); + public static final VarType VARTYPE_SHORTCHAR = new VarType(CodeConstants.TYPE_SHORTCHAR); + + public static final VarType VARTYPE_NULL = new VarType(CodeConstants.TYPE_NULL, 0, null); + public static final VarType VARTYPE_GROUP2EMPTY = new VarType(CodeConstants.TYPE_GROUP2EMPTY); + public static final VarType VARTYPE_STRING = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String"); + public static final VarType VARTYPE_CLASS = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"); + public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object"); + public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID); + + public int type; + + public int type_family; + + public int arraydim; + + public String value; + + public int stack_size; + + public int convinfo; + + public VarType(int type) { + this.type = type; + this.arraydim = 0; + + value = getChar(type); + setStackSize(type); + setFamily(); + } + + public VarType(int type, int arraydim) { + this(type); + this.arraydim = arraydim; + setFamily(); + } + + public VarType(int type, int arraydim, String value) { + this(type); + this.arraydim = arraydim; + this.value = value; + setFamily(); + } + + public VarType(String strtype) { + this(strtype, false); + } + + public VarType(String strtype, boolean cltype) { + parseTypeString(strtype, cltype); + setStackSize(type); + setFamily(); + } + + public void decArrayDim() { + if (arraydim > 0) { + arraydim--; + setFamily(); + } + else { + // throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case + } + } + + public String toString() { + String res = ""; + + for (int i = 0; i < arraydim; i++) { + res += "["; + } + + if (type == CodeConstants.TYPE_OBJECT) { + res += "L" + value + ";"; + } + else { + res += value; + } + + return res; + } + + public VarType copy() { + VarType v = new VarType(type, arraydim, value); + v.convinfo = convinfo; + return v; + } + + public boolean isFalseBoolean() { + return (convinfo & VarType.FALSEBOOLEAN) != 0; + } + + public boolean isSuperset(VarType val) { + + return this.equals(val) || this.isStrictSuperset(val); + } + + public boolean isStrictSuperset(VarType val) { + + int valtype = val.type; + + if (valtype == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) { + return true; + } + + if (val.arraydim > 0) { + return this.equals(VARTYPE_OBJECT); + } + else if (arraydim > 0) { + return (valtype == CodeConstants.TYPE_NULL); + } + + boolean res = false; + + switch (type) { + case CodeConstants.TYPE_INT: + res |= (valtype == CodeConstants.TYPE_SHORT || + valtype == CodeConstants.TYPE_CHAR); + case CodeConstants.TYPE_SHORT: + res |= (valtype == CodeConstants.TYPE_BYTE); + case CodeConstants.TYPE_CHAR: + res |= (valtype == CodeConstants.TYPE_SHORTCHAR); + case CodeConstants.TYPE_BYTE: + case CodeConstants.TYPE_SHORTCHAR: + res |= (valtype == CodeConstants.TYPE_BYTECHAR); + case CodeConstants.TYPE_BYTECHAR: + res |= (valtype == CodeConstants.TYPE_BOOLEAN); + break; + case CodeConstants.TYPE_OBJECT: + if (valtype == CodeConstants.TYPE_NULL) { + return true; + } + else if (this.equals(VARTYPE_OBJECT)) { + return valtype == CodeConstants.TYPE_OBJECT && + !val.equals(VARTYPE_OBJECT); + } + } + + return res; + } + + // type1 and type2 must not be null + public static VarType getCommonMinType(VarType type1, VarType type2) { + + if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans + return type1.isFalseBoolean() ? type2 : type1; + } + + if (type1.isSuperset(type2)) { + return type2; + } + else if (type2.isSuperset(type1)) { + return type1; + } + else if (type1.type_family == type2.type_family) { + switch (type1.type_family) { + case CodeConstants.TYPE_FAMILY_INTEGER: + if ((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT) + || (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) { + return VarType.VARTYPE_SHORTCHAR; + } + else { + return VarType.VARTYPE_BYTECHAR; + } + case CodeConstants.TYPE_FAMILY_OBJECT: + return VarType.VARTYPE_NULL; + } + } + + return null; + } + + // type1 and type2 must not be null + public static VarType getCommonSupertype(VarType type1, VarType type2) { + + if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans + return type1.isFalseBoolean() ? type1 : type2; + } + + if (type1.isSuperset(type2)) { + return type1; + } + else if (type2.isSuperset(type1)) { + return type2; + } + else if (type1.type_family == type2.type_family) { + switch (type1.type_family) { + case CodeConstants.TYPE_FAMILY_INTEGER: + if ((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE) + || (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) { + return VarType.VARTYPE_SHORT; + } + else { + return VarType.VARTYPE_INT; + } + case CodeConstants.TYPE_FAMILY_OBJECT: + return VarType.VARTYPE_OBJECT; + } + } + + return null; + } + + public static VarType getMinTypeInFamily(int family) { + switch (family) { + case CodeConstants.TYPE_FAMILY_BOOLEAN: + return VarType.VARTYPE_BOOLEAN; + case CodeConstants.TYPE_FAMILY_INTEGER: + return VarType.VARTYPE_BYTECHAR; + case CodeConstants.TYPE_FAMILY_OBJECT: + return VarType.VARTYPE_NULL; + case CodeConstants.TYPE_FAMILY_FLOAT: + return VarType.VARTYPE_FLOAT; + case CodeConstants.TYPE_FAMILY_LONG: + return VarType.VARTYPE_LONG; + case CodeConstants.TYPE_FAMILY_DOUBLE: + return VarType.VARTYPE_DOUBLE; + case CodeConstants.TYPE_FAMILY_UNKNOWN: + return VarType.VARTYPE_UNKNOWN; + default: + throw new RuntimeException("invalid type family!"); + } + } + + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (o == null || !(o instanceof VarType)) { + return false; + } + + VarType vt = (VarType)o; + return type == vt.type && arraydim == vt.arraydim && InterpreterUtil.equalObjects(value, vt.value); + } + + private void parseTypeString(String strtype, boolean cltype) { + + for (int i = 0; i < strtype.length(); i++) { + switch (strtype.charAt(i)) { + case '[': + arraydim++; + break; + case 'L': + if (strtype.charAt(strtype.length() - 1) == ';') { + type = CodeConstants.TYPE_OBJECT; + value = strtype.substring(i + 1, strtype.length() - 1); + return; + } + default: + value = strtype.substring(i, strtype.length()); + if ((cltype && i == 0) || value.length() > 1) { + type = CodeConstants.TYPE_OBJECT; + } + else { + type = getType(value.charAt(0)); + } + return; + } + } + } + + private void setStackSize(int type) { + if (arraydim > 0) { + stack_size = 1; + } + else { + stack_size = (type == CodeConstants.TYPE_DOUBLE || + type == CodeConstants.TYPE_LONG) ? 2 : + ((type == CodeConstants.TYPE_VOID || + type == CodeConstants.TYPE_GROUP2EMPTY) ? 0 : 1); + } + } + + private int getType(char c) { + switch (c) { + case 'B': + return CodeConstants.TYPE_BYTE; + case 'C': + return CodeConstants.TYPE_CHAR; + case 'D': + return CodeConstants.TYPE_DOUBLE; + case 'F': + return CodeConstants.TYPE_FLOAT; + case 'I': + return CodeConstants.TYPE_INT; + case 'J': + return CodeConstants.TYPE_LONG; + case 'S': + return CodeConstants.TYPE_SHORT; + case 'Z': + return CodeConstants.TYPE_BOOLEAN; + case 'V': + return CodeConstants.TYPE_VOID; + case 'G': + return CodeConstants.TYPE_GROUP2EMPTY; + case 'N': + return CodeConstants.TYPE_NOTINITIALIZED; + case 'A': + return CodeConstants.TYPE_ADDRESS; + case 'X': + return CodeConstants.TYPE_BYTECHAR; + case 'Y': + return CodeConstants.TYPE_SHORTCHAR; + case 'U': + return CodeConstants.TYPE_UNKNOWN; + default: + throw new RuntimeException("Invalid type"); + } + } + + private String getChar(int type) { + switch (type) { + case CodeConstants.TYPE_BYTE: + return "B"; + case CodeConstants.TYPE_CHAR: + return "C"; + case CodeConstants.TYPE_DOUBLE: + return "D"; + case CodeConstants.TYPE_FLOAT: + return "F"; + case CodeConstants.TYPE_INT: + return "I"; + case CodeConstants.TYPE_LONG: + return "J"; + case CodeConstants.TYPE_SHORT: + return "S"; + case CodeConstants.TYPE_BOOLEAN: + return "Z"; + case CodeConstants.TYPE_VOID: + return "V"; + case CodeConstants.TYPE_GROUP2EMPTY: + return "G"; + case CodeConstants.TYPE_NOTINITIALIZED: + return "N"; + case CodeConstants.TYPE_ADDRESS: + return "A"; + case CodeConstants.TYPE_BYTECHAR: + return "X"; + case CodeConstants.TYPE_SHORTCHAR: + return "Y"; + case CodeConstants.TYPE_UNKNOWN: + return "U"; + case CodeConstants.TYPE_NULL: + case CodeConstants.TYPE_OBJECT: + return null; + default: + throw new RuntimeException("Invalid type"); + } + } + + public void setFamily() { + + if (arraydim > 0) { + this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; + return; + } + + switch (type) { + case CodeConstants.TYPE_BYTE: + case CodeConstants.TYPE_BYTECHAR: + case CodeConstants.TYPE_SHORTCHAR: + case CodeConstants.TYPE_CHAR: + case CodeConstants.TYPE_SHORT: + case CodeConstants.TYPE_INT: + this.type_family = CodeConstants.TYPE_FAMILY_INTEGER; + break; + case CodeConstants.TYPE_DOUBLE: + this.type_family = CodeConstants.TYPE_FAMILY_DOUBLE; + break; + case CodeConstants.TYPE_FLOAT: + this.type_family = CodeConstants.TYPE_FAMILY_FLOAT; + break; + case CodeConstants.TYPE_LONG: + this.type_family = CodeConstants.TYPE_FAMILY_LONG; + break; + case CodeConstants.TYPE_BOOLEAN: + this.type_family = CodeConstants.TYPE_FAMILY_BOOLEAN; + break; + case CodeConstants.TYPE_NULL: + case CodeConstants.TYPE_OBJECT: + this.type_family = CodeConstants.TYPE_FAMILY_OBJECT; + break; + default: + this.type_family = CodeConstants.TYPE_FAMILY_UNKNOWN; + } + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java index d4551ac..66fab96 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java @@ -1,17 +1,18 @@ /* - * 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.struct.gen.generics; import java.util.ArrayList; @@ -19,12 +20,11 @@ import java.util.List; public class GenericClassDescriptor { - public GenericType superclass; - - public List<GenericType> superinterfaces = new ArrayList<GenericType>(); - - public List<String> fparameters = new ArrayList<String>(); + public GenericType superclass; + + public List<GenericType> superinterfaces = new ArrayList<GenericType>(); + + public List<String> fparameters = new ArrayList<String>(); - public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); - + public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java index 4b4114d..598d17b 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java @@ -1,21 +1,21 @@ /* - * 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.struct.gen.generics; public class GenericFieldDescriptor { - public GenericType type; - + public GenericType type; } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java index 50433a9..db7d84b 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java @@ -1,229 +1,233 @@ /* - * 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.struct.gen.generics; -import java.util.ArrayList; -import java.util.List; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.struct.StructClass; +import java.util.ArrayList; +import java.util.List; + public class GenericMain { - - private static final String[] typeNames = new String[] { - "byte", - "char", - "double", - "float", - "int", - "long", - "short", - "boolean", - }; - - public static GenericClassDescriptor parseClassSignature(String signature) { - - GenericClassDescriptor descriptor = new GenericClassDescriptor(); - - signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); - - String supercl = GenericType.getNextType(signature); - descriptor.superclass = new GenericType(supercl); - - signature = signature.substring(supercl.length()); - while(signature.length() > 0) { - String superintr = GenericType.getNextType(signature); - descriptor.superinterfaces.add(new GenericType(superintr)); - signature = signature.substring(superintr.length()); - } - - return descriptor; - } - - public static GenericFieldDescriptor parseFieldSignature(String signature) { - GenericFieldDescriptor descriptor = new GenericFieldDescriptor(); - descriptor.type = new GenericType(signature); - return descriptor; - } - - public static GenericMethodDescriptor parseMethodSignature(String signature) { - - GenericMethodDescriptor descriptor = new GenericMethodDescriptor(); - - signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); - - int to = signature.indexOf(")"); - String pars = signature.substring(1, to); - signature = signature.substring(to+1); - - while(pars.length() > 0) { - String par = GenericType.getNextType(pars); - descriptor.params.add(new GenericType(par)); - pars = pars.substring(par.length()); - } - - String par = GenericType.getNextType(signature); - descriptor.ret = new GenericType(par); - signature = signature.substring(par.length()); - - if(signature.length() > 0) { - String[] excs = signature.split("\\^"); - - for(int i=1;i<excs.length;i++) { - descriptor.exceptions.add(new GenericType(excs[i])); - } - } - - return descriptor; - } - - private static String parseFormalParameters(String signature, List<String> fparameters, List<List<GenericType>> fbounds) { - - if(signature.charAt(0) != '<') { - return signature; - } - - int counter = 1; - int index = 1; - - loop: - while(index < signature.length()) { - switch(signature.charAt(index)) { - case '<': - counter++; - break; - case '>': - counter--; - if(counter == 0) { - break loop; - } - } - - index++; - } - - String value = signature.substring(1, index); - signature = signature.substring(index+1); - - while(value.length() > 0) { - int parto = value.indexOf(":"); - - String param = value.substring(0, parto); - value = value.substring(parto+1); - - List<GenericType> lstBounds = new ArrayList<GenericType>(); - - for(;;) { - if(value.charAt(0) == ':') { - // empty superclass, skip - value = value.substring(1); - } - - String bound = GenericType.getNextType(value); - lstBounds.add(new GenericType(bound)); - value = value.substring(bound.length()); - - - if(value.length() == 0 || value.charAt(0) != ':') { - break; - } else { - value = value.substring(1); - } - } - - fparameters.add(param); - fbounds.add(lstBounds); - } - - return signature; - } - - public static String getGenericCastTypeName(GenericType type) { - String s = getTypeName(type); - int dim = type.arraydim; - while(dim-->0) { - s+="[]"; - } - return s; - } - - public static String getTypeName(GenericType type) { - - int tp = type.type; - if(tp <= CodeConstants.TYPE_BOOLEAN) { - return typeNames[tp]; - } else if(tp == CodeConstants.TYPE_VOID) { - return "void"; - } else if(tp == CodeConstants.TYPE_GENVAR) { - return type.value; - } else if(tp == CodeConstants.TYPE_OBJECT) { - StringBuilder buffer = new StringBuilder(); - buffer.append(DecompilerContext.getImpcollector().getShortName(buildJavaClassName(type))); - - if(!type.getArguments().isEmpty()) { - buffer.append("<"); - for(int i=0;i<type.getArguments().size();i++) { - if(i>0) { - buffer.append(", "); - } - int wildcard = type.getWildcards().get(i); - if(wildcard != GenericType.WILDCARD_NO) { - buffer.append("?"); - - switch(wildcard){ - case GenericType.WILDCARD_EXTENDS: - buffer.append(" extends "); - break; - case GenericType.WILDCARD_SUPER: - buffer.append(" super "); - } - } - - GenericType genpar = type.getArguments().get(i); - if(genpar != null) { - buffer.append(GenericMain.getGenericCastTypeName(genpar)); - } - } - buffer.append(">"); - } - - return buffer.toString(); - } - - throw new RuntimeException("invalid type"); - } - - public static String buildJavaClassName(GenericType type) { - - String name = ""; - for(GenericType tp : type.getEnclosingClasses()) { - name += tp.value+"$"; - } - name+=type.value; - - String res = name.replace('/', '.'); - - if(res.indexOf("$") >=0) { - StructClass cl = DecompilerContext.getStructcontext().getClass(name); - if(cl == null || !cl.isOwn()) { - res = res.replace('$', '.'); - } - } - - return res; - } - + + private static final String[] typeNames = new String[]{ + "byte", + "char", + "double", + "float", + "int", + "long", + "short", + "boolean", + }; + + public static GenericClassDescriptor parseClassSignature(String signature) { + + GenericClassDescriptor descriptor = new GenericClassDescriptor(); + + signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); + + String supercl = GenericType.getNextType(signature); + descriptor.superclass = new GenericType(supercl); + + signature = signature.substring(supercl.length()); + while (signature.length() > 0) { + String superintr = GenericType.getNextType(signature); + descriptor.superinterfaces.add(new GenericType(superintr)); + signature = signature.substring(superintr.length()); + } + + return descriptor; + } + + public static GenericFieldDescriptor parseFieldSignature(String signature) { + GenericFieldDescriptor descriptor = new GenericFieldDescriptor(); + descriptor.type = new GenericType(signature); + return descriptor; + } + + public static GenericMethodDescriptor parseMethodSignature(String signature) { + + GenericMethodDescriptor descriptor = new GenericMethodDescriptor(); + + signature = parseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds); + + int to = signature.indexOf(")"); + String pars = signature.substring(1, to); + signature = signature.substring(to + 1); + + while (pars.length() > 0) { + String par = GenericType.getNextType(pars); + descriptor.params.add(new GenericType(par)); + pars = pars.substring(par.length()); + } + + String par = GenericType.getNextType(signature); + descriptor.ret = new GenericType(par); + signature = signature.substring(par.length()); + + if (signature.length() > 0) { + String[] excs = signature.split("\\^"); + + for (int i = 1; i < excs.length; i++) { + descriptor.exceptions.add(new GenericType(excs[i])); + } + } + + return descriptor; + } + + private static String parseFormalParameters(String signature, List<String> fparameters, List<List<GenericType>> fbounds) { + + if (signature.charAt(0) != '<') { + return signature; + } + + int counter = 1; + int index = 1; + + loop: + while (index < signature.length()) { + switch (signature.charAt(index)) { + case '<': + counter++; + break; + case '>': + counter--; + if (counter == 0) { + break loop; + } + } + + index++; + } + + String value = signature.substring(1, index); + signature = signature.substring(index + 1); + + while (value.length() > 0) { + int parto = value.indexOf(":"); + + String param = value.substring(0, parto); + value = value.substring(parto + 1); + + List<GenericType> lstBounds = new ArrayList<GenericType>(); + + for (; ; ) { + if (value.charAt(0) == ':') { + // empty superclass, skip + value = value.substring(1); + } + + String bound = GenericType.getNextType(value); + lstBounds.add(new GenericType(bound)); + value = value.substring(bound.length()); + + + if (value.length() == 0 || value.charAt(0) != ':') { + break; + } + else { + value = value.substring(1); + } + } + + fparameters.add(param); + fbounds.add(lstBounds); + } + + return signature; + } + + public static String getGenericCastTypeName(GenericType type) { + String s = getTypeName(type); + int dim = type.arraydim; + while (dim-- > 0) { + s += "[]"; + } + return s; + } + + public static String getTypeName(GenericType type) { + + int tp = type.type; + if (tp <= CodeConstants.TYPE_BOOLEAN) { + return typeNames[tp]; + } + else if (tp == CodeConstants.TYPE_VOID) { + return "void"; + } + else if (tp == CodeConstants.TYPE_GENVAR) { + return type.value; + } + else if (tp == CodeConstants.TYPE_OBJECT) { + StringBuilder buffer = new StringBuilder(); + buffer.append(DecompilerContext.getImpcollector().getShortName(buildJavaClassName(type))); + + if (!type.getArguments().isEmpty()) { + buffer.append("<"); + for (int i = 0; i < type.getArguments().size(); i++) { + if (i > 0) { + buffer.append(", "); + } + int wildcard = type.getWildcards().get(i); + if (wildcard != GenericType.WILDCARD_NO) { + buffer.append("?"); + + switch (wildcard) { + case GenericType.WILDCARD_EXTENDS: + buffer.append(" extends "); + break; + case GenericType.WILDCARD_SUPER: + buffer.append(" super "); + } + } + + GenericType genpar = type.getArguments().get(i); + if (genpar != null) { + buffer.append(GenericMain.getGenericCastTypeName(genpar)); + } + } + buffer.append(">"); + } + + return buffer.toString(); + } + + throw new RuntimeException("invalid type"); + } + + public static String buildJavaClassName(GenericType type) { + + String name = ""; + for (GenericType tp : type.getEnclosingClasses()) { + name += tp.value + "$"; + } + name += type.value; + + String res = name.replace('/', '.'); + + if (res.indexOf("$") >= 0) { + StructClass cl = DecompilerContext.getStructcontext().getClass(name); + if (cl == null || !cl.isOwn()) { + res = res.replace('$', '.'); + } + } + + return res; + } } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java index 7a0a4d1..7b4c9dc 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java @@ -1,17 +1,18 @@ /* - * 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.struct.gen.generics; import java.util.ArrayList; @@ -19,14 +20,13 @@ import java.util.List; public class GenericMethodDescriptor { - public List<String> fparameters = new ArrayList<String>(); + public List<String> fparameters = new ArrayList<String>(); + + public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); + + public List<GenericType> params = new ArrayList<GenericType>(); - public List<List<GenericType>> fbounds = new ArrayList<List<GenericType>>(); + public GenericType ret; - public List<GenericType> params = new ArrayList<GenericType>(); - - public GenericType ret; - - public List<GenericType> exceptions = new ArrayList<GenericType>(); - + public List<GenericType> exceptions = new ArrayList<GenericType>(); } diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java index 1f720e6..e2faa4a 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java @@ -1,270 +1,268 @@ /* - * 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.struct.gen.generics; +import org.jetbrains.java.decompiler.code.CodeConstants; + import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.code.CodeConstants; - public class GenericType { - - public static final int WILDCARD_EXTENDS = 1; - public static final int WILDCARD_SUPER = 2; - public static final int WILDCARD_UNBOUND = 3; - public static final int WILDCARD_NO = 4; - - public int type; - - public int arraydim; - - public String value; - - - private List<GenericType> enclosingClasses = new ArrayList<GenericType>(); - - private List<GenericType> arguments = new ArrayList<GenericType>(); - - private List<Integer> wildcards = new ArrayList<Integer>(); - - - public GenericType(int type, int arraydim, String value) { - this.type = type; - this.arraydim = arraydim; - this.value = value; - } - - - public GenericType(String strtype) { - - parseSignature(strtype); - - } - - private void parseSignature(String sig) { - - int index = 0; - while(index < sig.length()) { - - switch(sig.charAt(index)){ - case '[': - arraydim++; - break; - case 'T': - type = CodeConstants.TYPE_GENVAR; - value = sig.substring(index+1, sig.length()-1); - return; - case 'L': - type = CodeConstants.TYPE_OBJECT; - sig = sig.substring(index+1, sig.length()-1); - - for(;;) { - String cl = getNextClassSignature(sig); - - String name = cl; - String args = null; - - int argfrom = cl.indexOf("<"); - if(argfrom >= 0) { - name = cl.substring(0, argfrom); - args = cl.substring(argfrom+1, cl.length()-1); - } - - if(cl.length() < sig.length()) { - sig = sig.substring(cl.length()+1); // skip '.' - GenericType type = new GenericType(CodeConstants.TYPE_OBJECT, 0, name); - parseArgumentsList(args, type); - enclosingClasses.add(type); - } else { - value = name; - parseArgumentsList(args, this); - break; - } - } - - return; - default: - value = sig.substring(index, index+1); - type = getType(value.charAt(0)); - } - - index++; - } - - } - - private String getNextClassSignature(String value) { - - int counter = 0; - int index = 0; - - loop: - while(index < value.length()) { - switch(value.charAt(index)) { - case '<': - counter++; - break; - case '>': - counter--; - break; - case '.': - if(counter == 0) { - break loop; - } - } - - index++; - } - - return value.substring(0, index); - } - - private void parseArgumentsList(String value, GenericType type) { - - if(value == null) { - return; - } - - while(value.length() > 0) { - - String tstr = getNextType(value); - int len = tstr.length(); - int wildcard = WILDCARD_NO; - - switch(tstr.charAt(0)) { - case '*': - wildcard = WILDCARD_UNBOUND; - break; - case '+': - wildcard = WILDCARD_EXTENDS; - break; - case '-': - wildcard = WILDCARD_SUPER; - break; - } - - type.getWildcards().add(wildcard); - - if(wildcard != WILDCARD_NO) { - tstr = tstr.substring(1); - } - - type.getArguments().add(tstr.length() == 0?null:new GenericType(tstr)); - - value = value.substring(len); - } - - } - - public static String getNextType(String value) { - - int counter = 0; - int index = 0; - - boolean contmode = false; - - loop: - while(index < value.length()) { - switch(value.charAt(index)) { - case '*': - if(!contmode) { - break loop; - } - break; - case 'L': - case 'T': - if(!contmode) { - contmode = true; - } - case '[': - case '+': - case '-': - break; - default: - if(!contmode) { - break loop; - } - break; - case '<': - counter++; - break; - case '>': - counter--; - break; - case ';': - if(counter == 0) { - break loop; - } - } - - index++; - } - - return value.substring(0, index+1); - } - - private int getType(char c) { - switch(c) { - case 'B': - return CodeConstants.TYPE_BYTE; - case 'C': - return CodeConstants.TYPE_CHAR; - case 'D': - return CodeConstants.TYPE_DOUBLE; - case 'F': - return CodeConstants.TYPE_FLOAT; - case 'I': - return CodeConstants.TYPE_INT; - case 'J': - return CodeConstants.TYPE_LONG; - case 'S': - return CodeConstants.TYPE_SHORT; - case 'Z': - return CodeConstants.TYPE_BOOLEAN; - case 'V': - return CodeConstants.TYPE_VOID; - case 'G': - return CodeConstants.TYPE_GROUP2EMPTY; - case 'N': - return CodeConstants.TYPE_NOTINITIALIZED; - case 'A': - return CodeConstants.TYPE_ADDRESS; - case 'X': - return CodeConstants.TYPE_BYTECHAR; - case 'Y': - return CodeConstants.TYPE_SHORTCHAR; - case 'U': - return CodeConstants.TYPE_UNKNOWN; - default: - throw new RuntimeException("Invalid type"); - } - } - - - public List<GenericType> getArguments() { - return arguments; - } - - - public List<GenericType> getEnclosingClasses() { - return enclosingClasses; - } - - - public List<Integer> getWildcards() { - return wildcards; - } - + + public static final int WILDCARD_EXTENDS = 1; + public static final int WILDCARD_SUPER = 2; + public static final int WILDCARD_UNBOUND = 3; + public static final int WILDCARD_NO = 4; + + public int type; + + public int arraydim; + + public String value; + + + private List<GenericType> enclosingClasses = new ArrayList<GenericType>(); + + private List<GenericType> arguments = new ArrayList<GenericType>(); + + private List<Integer> wildcards = new ArrayList<Integer>(); + + + public GenericType(int type, int arraydim, String value) { + this.type = type; + this.arraydim = arraydim; + this.value = value; + } + + + public GenericType(String strtype) { + + parseSignature(strtype); + } + + private void parseSignature(String sig) { + + int index = 0; + while (index < sig.length()) { + + switch (sig.charAt(index)) { + case '[': + arraydim++; + break; + case 'T': + type = CodeConstants.TYPE_GENVAR; + value = sig.substring(index + 1, sig.length() - 1); + return; + case 'L': + type = CodeConstants.TYPE_OBJECT; + sig = sig.substring(index + 1, sig.length() - 1); + + for (; ; ) { + String cl = getNextClassSignature(sig); + + String name = cl; + String args = null; + + int argfrom = cl.indexOf("<"); + if (argfrom >= 0) { + name = cl.substring(0, argfrom); + args = cl.substring(argfrom + 1, cl.length() - 1); + } + + if (cl.length() < sig.length()) { + sig = sig.substring(cl.length() + 1); // skip '.' + GenericType type = new GenericType(CodeConstants.TYPE_OBJECT, 0, name); + parseArgumentsList(args, type); + enclosingClasses.add(type); + } + else { + value = name; + parseArgumentsList(args, this); + break; + } + } + + return; + default: + value = sig.substring(index, index + 1); + type = getType(value.charAt(0)); + } + + index++; + } + } + + private String getNextClassSignature(String value) { + + int counter = 0; + int index = 0; + + loop: + while (index < value.length()) { + switch (value.charAt(index)) { + case '<': + counter++; + break; + case '>': + counter--; + break; + case '.': + if (counter == 0) { + break loop; + } + } + + index++; + } + + return value.substring(0, index); + } + + private void parseArgumentsList(String value, GenericType type) { + + if (value == null) { + return; + } + + while (value.length() > 0) { + + String tstr = getNextType(value); + int len = tstr.length(); + int wildcard = WILDCARD_NO; + + switch (tstr.charAt(0)) { + case '*': + wildcard = WILDCARD_UNBOUND; + break; + case '+': + wildcard = WILDCARD_EXTENDS; + break; + case '-': + wildcard = WILDCARD_SUPER; + break; + } + + type.getWildcards().add(wildcard); + + if (wildcard != WILDCARD_NO) { + tstr = tstr.substring(1); + } + + type.getArguments().add(tstr.length() == 0 ? null : new GenericType(tstr)); + + value = value.substring(len); + } + } + + public static String getNextType(String value) { + + int counter = 0; + int index = 0; + + boolean contmode = false; + + loop: + while (index < value.length()) { + switch (value.charAt(index)) { + case '*': + if (!contmode) { + break loop; + } + break; + case 'L': + case 'T': + if (!contmode) { + contmode = true; + } + case '[': + case '+': + case '-': + break; + default: + if (!contmode) { + break loop; + } + break; + case '<': + counter++; + break; + case '>': + counter--; + break; + case ';': + if (counter == 0) { + break loop; + } + } + + index++; + } + + return value.substring(0, index + 1); + } + + private int getType(char c) { + switch (c) { + case 'B': + return CodeConstants.TYPE_BYTE; + case 'C': + return CodeConstants.TYPE_CHAR; + case 'D': + return CodeConstants.TYPE_DOUBLE; + case 'F': + return CodeConstants.TYPE_FLOAT; + case 'I': + return CodeConstants.TYPE_INT; + case 'J': + return CodeConstants.TYPE_LONG; + case 'S': + return CodeConstants.TYPE_SHORT; + case 'Z': + return CodeConstants.TYPE_BOOLEAN; + case 'V': + return CodeConstants.TYPE_VOID; + case 'G': + return CodeConstants.TYPE_GROUP2EMPTY; + case 'N': + return CodeConstants.TYPE_NOTINITIALIZED; + case 'A': + return CodeConstants.TYPE_ADDRESS; + case 'X': + return CodeConstants.TYPE_BYTECHAR; + case 'Y': + return CodeConstants.TYPE_SHORTCHAR; + case 'U': + return CodeConstants.TYPE_UNKNOWN; + default: + throw new RuntimeException("Invalid type"); + } + } + + + public List<GenericType> getArguments() { + return arguments; + } + + + public List<GenericType> getEnclosingClasses() { + return enclosingClasses; + } + + + public List<Integer> getWildcards() { + return wildcards; + } } |