Lots of improvements to generic branch. Still many type errors and missing code.

git-svn-id: https://svn.code.sf.net/p/jode/code/branches/generics@1406 379699f6-c40d-0410-875b-85095c16579e
generics
hoenicke 18 years ago
parent b3b29c076a
commit ec94bc4489
  1. 8
      jode/.classpath
  2. 5
      jode/src/net/sf/jode/bytecode/ClassInfo.java
  3. 110
      jode/src/net/sf/jode/bytecode/TypeSignature.java
  4. 16
      jode/src/net/sf/jode/decompiler/ClassAnalyzer.java
  5. 16
      jode/src/net/sf/jode/decompiler/ClassDeclarer.java
  6. 2
      jode/src/net/sf/jode/decompiler/FieldAnalyzer.java
  7. 3
      jode/src/net/sf/jode/decompiler/ImportHandler.java
  8. 78
      jode/src/net/sf/jode/decompiler/MethodAnalyzer.java
  9. 4
      jode/src/net/sf/jode/decompiler/Opcodes.java
  10. 8
      jode/src/net/sf/jode/expr/FieldOperator.java
  11. 2
      jode/src/net/sf/jode/expr/IfThenElseOperator.java
  12. 11
      jode/src/net/sf/jode/expr/InvokeOperator.java
  13. 25
      jode/src/net/sf/jode/expr/ThisOperator.java
  14. 2
      jode/src/net/sf/jode/flow/CreateClassField.java
  15. 13
      jode/src/net/sf/jode/jvm/SyntheticAnalyzer.java
  16. 2
      jode/src/net/sf/jode/type/ArrayType.java
  17. 44
      jode/src/net/sf/jode/type/ClassInfoType.java
  18. 6
      jode/src/net/sf/jode/type/ClassType.java
  19. 15
      jode/src/net/sf/jode/type/GenericParameterType.java
  20. 19
      jode/src/net/sf/jode/type/MethodType.java
  21. 88
      jode/src/net/sf/jode/type/ParameterType.java
  22. 2
      jode/src/net/sf/jode/type/SystemClassType.java
  23. 154
      jode/src/net/sf/jode/type/Type.java
  24. 3
      jode/test/TryCatch.java

@ -4,13 +4,9 @@
<classpathentry excluding="src/|innerclasses/" kind="src" path="test"/>
<classpathentry kind="src" path="test/innerclasses"/>
<classpathentry kind="src" path="test/src"/>
<classpathentry kind="lib" path="lib/ant-junit.jar"/>
<classpathentry kind="lib" path="lib/collections.jar"/>
<classpathentry kind="lib" path="lib/jakarta-ant-1.3-optional.jar"/>
<classpathentry kind="lib" path="lib/java-getopt-1.0.8.jar"/>
<classpathentry kind="lib" path="lib/junit.jar"/>
<classpathentry kind="lib" path="release/jode-1.90-CVS.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path="props"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/>
<classpathentry kind="output" path="build"/>
</classpath>

@ -1210,8 +1210,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
public String getSignature() {
if (status < HIERARCHY)
throw new IllegalStateException("status is "+status);
if (signature != null)
if (signature != null) {
System.err.println("Sig(attrib) of "+this+": "+signature);/*XXX REMOVE*/
return signature;
}
if (superclass == null)
return "";
StringBuffer sb = new StringBuffer();
@ -1221,6 +1223,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
sb.append('L').append(interfaces[i].getName().replace('.','/'))
.append(";");
}
System.err.println("Sig of "+this+": "+sb.toString());/*XXX REMOVE*/
return sb.toString();
}

@ -19,6 +19,7 @@
package net.sf.jode.bytecode;
///#def COLLECTIONS java.util
import java.util.ArrayList;
import java.util.Map;
///#enddef
@ -429,6 +430,65 @@ public class TypeSignature {
return params;
}
/**
* Gets the signature of the super class from a class signature.
* @param typeSig the class's signature.
* @return the signature of the super class.
*/
public static String getSuperSignature(String typeSig) {
int pos = 0;
if (typeSig.charAt(0) == '<') {
/* Skip generic info */
pos++;
while (typeSig.charAt(pos) != '>') {
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
}
pos++;
}
return typeSig.substring(pos, skipType(typeSig, pos));
}
/**
* Gets the signatures of the super interfaces from a class signature.
* @param typeSig the class's signature.
* @return an array containing the signatures of the interfaces.
*/
public static String[] getIfaceSignatures(String typeSig) {
int pos = 0;
if (typeSig.charAt(0) == '<') {
/* Skip generic info */
pos++;
while (typeSig.charAt(pos) != '>') {
while (typeSig.charAt(pos) != ':')
pos++;
/* check for empty entry */
if (typeSig.charAt(pos+1) == ':')
pos++;
while (typeSig.charAt(pos) == ':') {
/* skip colon and type */
pos = skipType(typeSig, pos + 1);
}
}
pos++;
}
pos = skipType(typeSig, pos);
ArrayList list = new ArrayList();
while (pos < typeSig.length()) {
int epos = skipType(typeSig, pos);
list.add(typeSig.substring(pos, epos));
pos = epos;
}
return (String[]) list.toArray(new String[list.size()]);
}
private static int mapGenericsInType(String typeSig, Map generics,
StringBuffer mapped, int spos) {
int pos = spos;
@ -551,34 +611,36 @@ public class TypeSignature {
private static int checkClassName(String clName, int i)
throws IllegalArgumentException, StringIndexOutOfBoundsException
{
while (true) {
char c = clName.charAt(i++);
if (c == '<') {
c = clName.charAt(i++);
do {
if (c == '*')
i++;
else {
if (c == '+' || c == '-')
c = clName.charAt(i++);
if (c != 'L' && c != 'T' && c != '[')
throw new IllegalArgumentException
("Wrong class instantiation: "+clName);
i = checkTypeSig(clName, i - 1);
}
c = clName.charAt(i++);
} while (c != '>');
c = clName.charAt(i++);
if (c != ';')
throw new IllegalArgumentException
("no ; after > in "+clName);
}
if (c == ';')
return i;
char c = clName.charAt(i++);
while (c != ';' && c != '.' && c != '<') {
if (c != '/' && !Character.isJavaIdentifierPart(c))
throw new IllegalArgumentException("Illegal java class name: "
+ clName);
c = clName.charAt(i++);
}
if (c == '<') {
c = clName.charAt(i++);
do {
if (c == '*')
i++;
else {
if (c == '+' || c == '-')
c = clName.charAt(i++);
if (c != 'L' && c != 'T' && c != '[')
throw new IllegalArgumentException
("Wrong class instantiation: "+clName);
i = checkTypeSig(clName, i - 1);
}
c = clName.charAt(i++);
} while (c != '>');
c = clName.charAt(i++);
}
if (c == '.')
return checkClassName(clName, i);
if (c != ';')
throw new IllegalArgumentException
("no ; after > in "+clName);
return i;
}
/**

@ -178,7 +178,7 @@ public class ClassAnalyzer
*/
if ((Options.options & Options.OPTION_INNER) != 0
&& parent instanceof ClassAnalyzer && !isStatic())
outerInstance = new ThisOperator(((ClassAnalyzer) parent).clazz);
outerInstance = new ThisOperator((ClassAnalyzer) parent);
if (outerValues != null)
this.outerValues = new OuterValues(this, outerValues);
}
@ -569,7 +569,7 @@ public class ClassAnalyzer
}
String signature = clazz.getSignature();
System.err.println("Class Signature: "+signature+ " (class "+name+")");
writer.printExtendsImplements(Type.tClass(clazz));
writer.printExtendsImplements(myType);
writer.println();
writer.openBraceClass();
@ -799,6 +799,18 @@ public class ClassAnalyzer
return getParent().getClassAnalyzer(cinfo);
}
public GenericParameterType getGenericType(String name) {
if (genericTypes != null) {
for (int i = 0; i < genericTypes.length; i++) {
if (genericTypes[i].getClassName().equals(name))
return genericTypes[i];
}
}
if (parent != null)
return parent.getGenericType(name);
return null;
}
/**
* Get the class analyzer for the given inner class.
* @param name the short name of the inner class

@ -19,6 +19,8 @@
package net.sf.jode.decompiler;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.type.GenericParameterType;
/**
* This is the interface for objects, that a method can declare
@ -29,6 +31,12 @@ public interface ClassDeclarer {
* @return null if this is the outermost instance.
*/
public ClassDeclarer getParent();
/**
* Get the current class path.
* @return the current class path.
*/
public ClassPath getClassPath();
/**
* Get the class analyzer for the given anonymous class info. It
@ -38,5 +46,13 @@ public interface ClassDeclarer {
*/
public ClassAnalyzer getClassAnalyzer(ClassInfo ci);
/**
* Gets the generic type for the given named generic.
* @param name the name of the generic, e.g. K.
* @return the generic type for the named generic.
*/
public GenericParameterType getGenericType(String name);
public void addClassAnalyzer(ClassAnalyzer classAna);
}

@ -51,7 +51,7 @@ public class FieldAnalyzer implements Analyzer {
imports = i;
modifiers = fd.getModifiers();
type = Type.tType(cla.getClassPath(), fd.getType());
type = Type.tType(cla.getClassPath(), cla.getType(), fd.getSignature());
fieldName = fd.getName();
constant = null;
this.isSynthetic = fd.isSynthetic();

@ -21,6 +21,7 @@ package net.sf.jode.decompiler;
import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.type.SystemClassType;
import net.sf.jode.type.Type;
import net.sf.jode.type.ArrayType;
import net.sf.jode.type.ClassInfoType;
@ -321,7 +322,7 @@ public class ImportHandler {
useType(((ArrayType) type).getElementType());
else if (type instanceof ClassInfoType)
useClass(((ClassInfoType) type).getClassInfo());
else if (type instanceof ClassType)
else if (type instanceof SystemClassType)
useClass(((ClassType) type).getClassName());
}

@ -22,10 +22,12 @@ import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.BasicBlocks;
import net.sf.jode.bytecode.Block;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.Handler;
import net.sf.jode.bytecode.Instruction;
import net.sf.jode.bytecode.LocalVariableInfo;
import net.sf.jode.bytecode.MethodInfo;
import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.jvm.SyntheticAnalyzer;
import net.sf.jode.type.*;
import net.sf.jode.expr.Expression;
@ -53,6 +55,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
///#def COLLECTIONS java.util
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.ArrayList;
@ -186,6 +189,11 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
* classes that are used in this method.
*/
Collection usedAnalyzers;
/**
* This array contains the generic types this method declares if
* it is generic.
*/
GenericParameterType[] genericTypes;
/**
* This is the default constructor.
@ -199,7 +207,47 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
this.imports = imports;
this.minfo = minfo;
this.methodName = minfo.getName();
this.methodType = Type.tMethod(cla.getClassPath(), minfo.getSignature());
String signature = minfo.getSignature();
if (signature.charAt(0) == '<') {
String[] genericSignatures =
TypeSignature.getGenericSignatures(signature);
genericTypes = new GenericParameterType[genericSignatures.length];
for (int i = 0; i < genericTypes.length; i++) {
int colon = genericSignatures[i].indexOf(':');
String genName;
if (colon == -1) {
genericTypes[i] =
new GenericParameterType(genericSignatures[i],
Type.tObject,
new ClassType[0]);
} else {
String genname = genericSignatures[i].substring(0, colon);
String remainder = genericSignatures[i].substring(colon+1);
int nextIndex = TypeSignature.skipType(remainder, 0);
List superClazzes = new ArrayList();
for (;;) {
String clazzSig = remainder.substring(0, nextIndex);
superClazzes.add(Type.tType(classAnalyzer.getClassPath(),
classAnalyzer.getType(), clazzSig));
if (nextIndex >= remainder.length())
break;
remainder = remainder.substring(nextIndex+1);
}
ClassType genSupClass = (ClassType) superClazzes.get(0);
if (!genSupClass.isInterface())
superClazzes.remove(0);
else
genSupClass = Type.tObject;
ClassType[] genSupIfaces = (ClassType[])
superClazzes.toArray(new ClassType[0]);
genericTypes[i] = new GenericParameterType(genname,
genSupClass,
genSupIfaces);
}
}
}
this.methodType = Type.tMethod(cla.getClassPath(), cla.getType(), signature);
this.isConstructor =
methodName.equals("<init>") || methodName.equals("<clinit>");
@ -423,8 +471,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
LocalInfo li = new LocalInfo(this, lvi.getSlot());
if ((Options.options & Options.OPTION_LVT) != 0
&& lvi.getName() != null)
li.addHint(lvi.getName(), Type.tType(classAnalyzer.getClassPath(),
lvi.getType()));
li.addHint(lvi.getName(),
Type.tType(classAnalyzer.getClassPath(),
classAnalyzer.getType(),
lvi.getType()));
allLocals.addElement(li);
return li;
}
@ -582,11 +632,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
int offset = 0;
int slot = 0;
if (!isStatic()) {
ClassInfo classInfo = classAnalyzer.getClazz();
param[offset] = getLocalInfo(bb != null
? bb.getParamInfo(slot)
: LocalVariableInfo.getInfo(slot));
param[offset].setExpression(new ThisOperator(classInfo, true));
param[offset].setExpression(new ThisOperator(classAnalyzer, true));
slot++;
offset++;
}
@ -1011,7 +1060,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
expr).getSubExpressions()[0];
if (expr instanceof ThisOperator) {
outerValueArray[j] =
new ThisOperator(((ThisOperator) expr).getClassInfo());
new ThisOperator(((ThisOperator) expr).getClassAnalyzer());
continue;
}
LocalInfo li = null;
@ -1109,6 +1158,23 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
return getParent().getClassAnalyzer(cinfo);
}
public GenericParameterType getGenericType(String name) {
if (genericTypes != null) {
for (int i = 0; i < genericTypes.length; i++) {
if (genericTypes[i].getClassName().equals(name))
return genericTypes[i];
}
}
return getParent().getGenericType(name);
}
/**
* Gets the current class path.
*/
public ClassPath getClassPath() {
return classAnalyzer.getClassPath();
}
public void addClassAnalyzer(ClassAnalyzer clazzAna) {
if (innerAnalyzers == null)
innerAnalyzers = new Vector();

@ -152,8 +152,8 @@ public abstract class Opcodes implements net.sf.jode.bytecode.Opcodes {
if (instr.getConstant() instanceof Reference) {
Reference ref = (Reference) instr.getConstant();
expr = new ClassFieldOperator
(Type.tType(cp, ref.getType()),
Type.tType(cp, ref.getClazz()));
(Type.tType(ma.getClassPath(), null, ref.getType()),
Type.tType(ma.getClassPath(), null, ref.getClazz()));
} else if (instr.getConstant() instanceof String) {
expr = new ConstOperator(cp, (String) instr.getConstant());
} else {

@ -62,8 +62,8 @@ public abstract class FieldOperator extends Operator {
this.methodAnalyzer = methodAnalyzer;
this.staticFlag = staticFlag;
this.type = Type.tType(classPath, ref.getType());
this.classType = Type.tType(classPath, ref.getClazz());
this.type = Type.tType(methodAnalyzer, ref.getType());
this.classType = Type.tType(methodAnalyzer, ref.getClazz());
this.ref = ref;
if (staticFlag)
methodAnalyzer.useType(classType);
@ -119,7 +119,7 @@ public abstract class FieldOperator extends Operator {
while (true) {
if (clazz == ana.getClazz()) {
int field = ana.getFieldIndex
(ref.getName(), Type.tType(classPath, ref.getType()));
(ref.getName(), Type.tType(methodAnalyzer, ref.getType()));
if (field >= 0)
return ana.getField(field);
return null;
@ -143,7 +143,7 @@ public abstract class FieldOperator extends Operator {
}
public Type getFieldType() {
return Type.tType(classPath, ref.getType());
return Type.tType(methodAnalyzer, ref.getType());
}
private void loadFields(ClassInfo clazz) {

@ -100,7 +100,7 @@ public class IfThenElseOperator extends Operator {
return new ClassFieldOperator
(invoke.getType(),
clazz.charAt(0) == '['
? Type.tType(cp, clazz)
? Type.tType(field.getClassAnalyzer(), clazz)
: Type.tClass(cp, clazz));
}
}

@ -155,10 +155,11 @@ public final class InvokeOperator extends Operator
super(Type.tUnknown, 0);
this.classPath = methodAnalyzer.getClassAnalyzer().getClassPath();
this.ref = reference;
this.methodType = Type.tMethod(classPath, reference.getType());
this.methodType = Type.tMethod(methodAnalyzer.getClassPath(),
null, reference.getType());
this.methodName = reference.getName();
this.classType = (ClassType)
Type.tType(classPath, reference.getClazz());
Type.tType(methodAnalyzer.getClassPath(), null, reference.getClazz());
this.hints = null;
Map allHints = (Map) hintTypes.get(methodName+"."+methodType);
if (allHints != null) {
@ -774,7 +775,7 @@ public final class InvokeOperator extends Operator
continue next_method;
Type[] otherParamTypes
= Type.tMethod(classPath, methods[i].getType())
= Type.tMethod(methodAnalyzer.getClassPath(), null, methods[i].getSignature())
.getParameterTypes();
if (otherParamTypes.length != myParamTypes.length) {
/* parameter count doesn't match*/
@ -1120,7 +1121,7 @@ public final class InvokeOperator extends Operator
/* XXX check if this is a private method. */
if (needsCast(0, paramTypes)){
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 1);
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 1);
writer.print("(");
writer.printType(classType);
writer.print(") ");
@ -1135,7 +1136,7 @@ public final class InvokeOperator extends Operator
writer.print(".");
} else {
writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0);
writer.startOp(TabbedPrintWriter.EXPL_PAREN, 0);
writer.print("(NON VIRTUAL ");
writer.printType(classType);
writer.print(") ");

@ -20,25 +20,30 @@
package net.sf.jode.expr;
import net.sf.jode.type.Type;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.decompiler.ClassAnalyzer;
import net.sf.jode.decompiler.Scope;
import net.sf.jode.decompiler.TabbedPrintWriter;
public class ThisOperator extends NoArgOperator {
boolean isInnerMost;
ClassInfo classInfo;
ClassAnalyzer classAna;
public ThisOperator(ClassInfo classInfo, boolean isInnerMost) {
super(Type.tClass(classInfo));
this.classInfo = classInfo;
public ThisOperator(ClassAnalyzer classAna, boolean isInnerMost) {
super(classAna.getType());
this.classAna = classAna;
this.isInnerMost = isInnerMost;
}
public ThisOperator(ClassInfo classInfo) {
this(classInfo, false);
public ThisOperator(ClassAnalyzer classAna) {
this(classAna, false);
}
public ClassInfo getClassInfo() {
return classInfo;
return classAna.getClazz();
}
public ClassAnalyzer getClassAnalyzer() {
return classAna;
}
public int getPriority() {
@ -46,18 +51,18 @@ public class ThisOperator extends NoArgOperator {
}
public String toString() {
return classInfo+".this";
return classAna+".this";
}
public boolean opEquals(Operator o) {
return (o instanceof ThisOperator &&
((ThisOperator) o).classInfo.equals(classInfo));
((ThisOperator) o).classAna == classAna);
}
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
if (!isInnerMost) {
writer.print(writer.getClassString(classInfo,
writer.print(writer.getClassString(getClassInfo(),
Scope.AMBIGUOUSNAME));
writer.print(".");
}

@ -76,7 +76,7 @@ public class CreateClassField {
cmp.setSubExpressions
(0, new ClassFieldOperator(put.getType(),
clazz.charAt(0) == '['
? Type.tType(cp, clazz)
? Type.tType(invoke.getClassAnalyzer(), clazz)
: Type.tClass(cp, clazz)));
EmptyBlock empty = new EmptyBlock();
empty.moveJump(ifBlock.thenBlock.jump);

@ -311,12 +311,12 @@ public class SyntheticAnalyzer implements Opcodes {
}
MethodInfo refMethod
= refClazz.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(classInfo.getClassPath(),
ref.getType());
String[] refParams = TypeSignature.getParameterTypes(ref.getType());
String retType = TypeSignature.getReturnType(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != 0
|| refType.getParameterTypes().length != params)
|| refParams.length != params)
return false;
if (refType.getReturnType() == Type.tVoid) {
if (retType.equals("V")) {
if (iter.hasNext())
return false;
} else {
@ -390,12 +390,11 @@ public class SyntheticAnalyzer implements Opcodes {
return false;
MethodInfo refMethod
= refClazz.findMethod(ref.getName(), ref.getType());
MethodType refType = Type.tMethod(classInfo.getClassPath(),
ref.getType());
String[] refParams = TypeSignature.getParameterTypes(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != 0
|| !refMethod.getName().equals("<init>")
|| unifyParam == -1
|| refType.getParameterTypes().length != params - 2)
|| refParams.length != params - 2)
return false;
if (iter.hasNext())
return false;

@ -31,7 +31,7 @@ public class ArrayType extends ClassType {
Type elementType;
ArrayType(Type elementType) {
super(TC_ARRAY, elementType + "[]");
super(TC_ARRAY, elementType + "[]", null);
this.elementType = elementType;
}

@ -43,8 +43,9 @@ public class ClassInfoType extends ClassType {
return clazz;
}
public ClassInfoType(ClassInfo clazz, Type[] generics) {
super(TC_CLASS, clazz.getName());
public ClassInfoType(ClassInfo clazz, Type[] generics,
ClassType outerClass) {
super(TC_CLASS, clazz.getName(), outerClass);
this.clazz = clazz;
try {
@ -70,20 +71,15 @@ public class ClassInfoType extends ClassType {
Map genericMap = new SimpleMap();
if (generics != null) {
/* parse generic names */
String[] genNames;
if (signature.charAt(0) != '<')
throw new IllegalArgumentException
("Generic parameters for non-generic class");
genNames = TypeSignature.getGenericNames(signature);
if (generics.length != genNames.length)
genericNames = TypeSignature.getGenericNames(signature);
if (generics.length != genericNames.length)
throw new IllegalArgumentException
("Wrong number of generic parameters");
for (int i = 0; i < generics.length; i++)
genericMap.put(genNames[i], generics[i].getTypeSignature());
}
signature = TypeSignature.mapGenerics(signature, genericMap);
}
public ClassInfoType(ClassInfo clazz, Type[] generics) {
this(clazz, generics, null);
}
public boolean isUnknown() {
@ -99,26 +95,30 @@ public class ClassInfoType extends ClassType {
}
public ClassType getSuperClass() {
if (clazz.isInterface())
String signature = clazz.getSignature();
if (clazz.isInterface() || signature.length() == 0)
return null;
if (superClass == null) {
ClassInfo superInfo = clazz.getSuperclass();
if (superInfo == null)
return null;
superClass = Type.tClass(superInfo);
String superSig = TypeSignature.getSuperSignature(signature);
superClass = (ClassType) tType(clazz.getClassPath(), this, superSig);
}
return superClass;
}
public ClassType[] getInterfaces() {
if (interfaces == null) {
ClassInfo[] ifaceInfos = clazz.getInterfaces();
if (ifaceInfos.length == 0)
String sig = clazz.getSignature();
if (sig.length() == 0)
return EMPTY_IFACES;
String[] ifaceSigs =
TypeSignature.getIfaceSignatures(sig);
if (ifaceSigs.length == 0)
interfaces = EMPTY_IFACES;
else {
interfaces = new ClassType[ifaceInfos.length];
interfaces = new ClassType[ifaceSigs.length];
for (int i=0; i < interfaces.length; i++)
interfaces[i] = Type.tClass(ifaceInfos[i]);
interfaces[i] = (ClassType)
Type.tType(clazz.getClassPath(), this, ifaceSigs[i]);
}
}
return interfaces;

@ -33,6 +33,7 @@ public abstract class ClassType extends ReferenceType {
protected String className;
protected String[] genericNames;
protected Type[] genericInstances;
protected ClassType outerClass;
/*
* @invariant (genericNames == null) == (genericInstances == null)
@ -50,12 +51,15 @@ public abstract class ClassType extends ReferenceType {
if (genericNames[i].equals(name))
return genericInstances[i];
}
if (outerClass != null)
return outerClass.getGeneric(name);
return null;
}
public ClassType(int typecode, String clazzName) {
public ClassType(int typecode, String clazzName, ClassType outerClass) {
super(typecode);
className = clazzName;
this.outerClass = outerClass;
}
public ClassType(int typecode, String clazzName,

@ -18,16 +18,13 @@
*/
package net.sf.jode.type;
import net.sf.jode.bytecode.ClassInfo;
import java.util.Vector;
import java.util.Stack;
import java.util.Hashtable;
import java.io.IOException;
/**
* This class represents the type of a system class, i.e. the classes
* from package java.lang, that need special handling, like
* Object, String, StringBuffer, etc.
* This class represents the singleton set containing one parameter type. For
* example in the context of the class <code>Enum&lt;E extends
* Enum&lt;E&gt;&gt;</code> the identifier <code>E</code> denotes such a
* parameter type. It has the super class <code>Enum&lt;E&gt;</code> and
* implements no interfaces.
*
* @author Jochen Hoenicke
*/
@ -41,7 +38,7 @@ public class GenericParameterType extends ClassType {
public GenericParameterType(String className,
ClassType superType,
ClassType[] ifacesTypes) {
super(TC_SYSCLASS, className);
super(TC_SYSCLASS, className, null);
this.superType = superType;
this.ifacesTypes = ifacesTypes;
}

@ -20,6 +20,7 @@
package net.sf.jode.type;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.decompiler.ClassDeclarer;
/**
* This type represents an method type.
@ -32,21 +33,29 @@ public class MethodType extends Type {
final Type returnType;
final ClassPath cp;
public MethodType(ClassPath cp, String signature) {
public MethodType(ClassPath cp, ClassType declarer, String signature) {
/* TODO:
* We need TypeVariable: e.g. iff we have
* E getElm<E>(Vector<E> v);
* then E is a TypeVariable and if we now, that input type is a
* vector of Integer, then return value is Integer...
*
* A problem is that casts of v omit the value for E.
*/
super(TC_METHOD);
this.cp = cp;
this.signature = signature;
if (signature.charAt(0) == '<') {
/*FIXME */
/* handled by MethodAnalyzer */
signature = signature.substring(signature.indexOf('('));
}
String[] params = TypeSignature.getParameterTypes(signature);
parameterTypes = new Type[params.length];
for (int i = 0; i < params.length; i++) {
parameterTypes[i] = Type.tType(cp, params[i]);
parameterTypes[i] = Type.tType(cp, declarer, params[i]);
}
returnType = Type.tType(cp,
signature.substring(signature.indexOf(')')+1));
returnType = Type.tType(cp, declarer,
TypeSignature.getReturnType(signature));
}
public final int stackSize() {

@ -1,88 +0,0 @@
/* ParameterType Copyright (C) 2005 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: ParameterType.java,v 1.3 2004/06/01 08:46:10 hoenicke Exp $
*/
package net.sf.jode.type;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.GlobalOptions;
import java.lang.reflect.Modifier;
import java.io.IOException;
import java.util.Vector;
import java.util.Stack;
import java.util.Hashtable;
///#def COLLECTIONS java.util
import java.util.Map;
///#enddef
/**
* This class represents the singleton set containing one parameter type. For
* example in the context of the class <code>Enum&lt;E extends
* Enum&lt;E&gt;&gt;</code> the identifier <code>E</code> denotes such a
* parameter type. It has the super class <code>Enum&lt;E&gt;</code> and
* implements no interfaces.
*
* @author Jochen Hoenicke
*/
public class ParameterType extends ClassType {
ClassType superClass;
ClassType[] interfaces;
public ParameterType(String name,
ClassInfo superInfo, ClassInfo[] ifaceInfos) {
super(TC_PARAMETER, name);
superClass = Type.tClass(superInfo);
if (ifaceInfos.length == 0) {
interfaces = EMPTY_IFACES;
} else {
interfaces = new ClassType[ifaceInfos.length];
for (int i=0; i < interfaces.length; i++)
interfaces[i] = Type.tClass(ifaceInfos[i]);
}
}
public boolean isUnknown() {
return false;
}
public boolean isFinal() {
return false;
}
public boolean isInterface() {
return false;
}
public ClassType getSuperClass() {
return superClass;
}
public ClassType[] getInterfaces() {
return interfaces;
}
public boolean equals(Object o) {
if (o instanceof ParameterType)
return ((ParameterType) o).className == className;
return false;
}
}

@ -43,7 +43,7 @@ public class SystemClassType extends ClassType {
ClassType superType,
ClassType[] ifacesTypes,
boolean isFinal, boolean isInterface) {
super(TC_SYSCLASS, className);
super(TC_SYSCLASS, className, null);
this.superType = superType;
this.ifacesTypes = ifacesTypes;
this.isFinal = isFinal;

@ -22,11 +22,10 @@ import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.decompiler.ClassDeclarer;
import net.sf.jode.util.UnifyHash;
///#def COLLECTIONS java.util
import java.util.Collections;
import java.util.Map;
import java.util.Iterator;
import java.util.Arrays;
///#enddef
@ -64,7 +63,6 @@ public class Type {
private static final UnifyHash classHash = new UnifyHash();
private static final UnifyHash arrayHash = new UnifyHash();
private static final UnifyHash methodHash = new UnifyHash();
/**
* This type represents the singleton set containing the boolean type.
@ -193,23 +191,83 @@ public class Type {
* Generate the singleton set of the type represented by the given
* string.
* @param classpath the current classpath.
* @param type the type signature (or method signature).
* @param type the type signature (or method signature).
* @deprecated give a classdeclarer instead.
* @return a singleton set containing the given type.
*/
public static final Type tType(ClassPath cp, String type) {
return tType(cp, type, Collections.EMPTY_MAP);
return tType(cp, null, type);
}
/**
* Generate the singleton set of the type represented by the given
* string.
* @param classpath the current classpath.
* @param signature the type signature (or method signature).
* @param parameterMap the map from type variables to real types.
* @param declarer a class declarer for the current context.
* @param type the type signature (or method signature).
* @return a singleton set containing the given type.
*/
public static final Type tType(ClassDeclarer declarer,
String signature) {
return tType(declarer.getClassPath(), null, signature);
}
public static final ClassInfoType tClassSig(ClassPath cp, ClassType declarer,
String signature)
{
Type[] generics = null;
ClassInfoType outer = null;
int index = signature.indexOf('.');
if (index >= 0) {
outer = tClassSig(cp, declarer, signature.substring(0, index));
signature = signature.substring(index+1);
if (outer == null)
return null;
}
index = signature.indexOf('<');
if (index >= 0) {
/* parse parameter types */
String[] genericNames = TypeSignature
.getArgumentTypes(signature.substring(index));
signature = signature.substring(0, index);
generics = new Type[genericNames.length];
for (int i = 0; i < generics.length; i++) {
String name = genericNames[i];
char c = name.charAt(0);
if (c == '*')
generics[i] = Type.tUObject;
else if (c == '+')
generics[i] = Type.tType(cp, declarer, name.substring(1))
.getSubType();
else if (c == '-')
generics[i] = Type.tType(cp, declarer, name.substring(1))
.getSuperType();
else
generics[i] = Type.tType(cp, declarer, name);
}
}
if (outer != null) {
ClassInfo[] inner = outer.getClassInfo().getClasses();
for (int i = 0; i < inner.length; i++) {
if (inner[i].getClassName().equals(signature))
return tClass(inner[i], generics, outer);
}
System.err.println("Inner class "+signature+" in class "+outer
+" not found.");
return null;
}
return tClass(cp, signature, generics);
}
/**
* Generate the singleton set of the type represented by the given
* string.
* @param cp current classpath.
* @param genericType the class containing generics of current context.
* @param type the type signature (or method signature).
* @return a singleton set containing the given type.
*/
public static final Type tType(ClassPath cp, String signature,
Map parameterMap) {
public static final Type tType(ClassPath cp, ClassType declarer,
String signature) {
if (signature == null || signature.length() == 0)
return tError;
switch(signature.charAt(0)) {
@ -232,41 +290,24 @@ public class Type {
case 'V':
return tVoid;
case '[':
return tArray(tType(cp, signature.substring(1)));
return tArray(tType(cp, declarer, signature.substring(1)));
case 'L': {
int endIndex = signature.length()-1;
Type[] generics = null;
if (signature.charAt(endIndex) != ';')
return tError;
if (signature.charAt(endIndex-1) == '>') {
/* parse parameter types */
int index = signature.indexOf('<');
String[] genericNames = TypeSignature
.getArgumentTypes(signature.substring(index, endIndex));
endIndex = index;
generics = new Type[genericNames.length];
for (int i = 0; i < generics.length; i++) {
String name = genericNames[i];
char c = name.charAt(0);
if (c == '*')
generics[i] = Type.tUObject;
else if (c == '+')
generics[i] = Type.tType(cp, name.substring(1))
.getSubType();
else if (c == '-')
generics[i] = Type.tType(cp, name.substring(1))
.getSuperType();
else
generics[i] = Type.tType(cp, name);
}
}
return tClass(cp, signature.substring(1, endIndex), generics);
Type type = tClassSig(cp, declarer,
signature.substring(1, endIndex));
if (type == null)
return tError;
return type;
}
case 'T': {
int index = signature.indexOf(';');
if (index != signature.length()-1)
return tError;
Type type = (Type) parameterMap.get(signature.substring(1, index));
if (declarer == null)
return tUnknown; /* XXX: Should be a type variable */
Type type = declarer.getGeneric(signature.substring(1, index));
if (type == null)
return tError;
return type;
@ -282,7 +323,7 @@ public class Type {
* The packages may be separated by `.' or `/'.
* @return a singleton set containing the given type.
*/
public static final ClassType tClass(ClassPath classPath,
public static final ClassInfoType tClass(ClassPath classPath,
String className,
Type[] generics) {
return tClass(classPath.getClassInfo(className.replace('/','.')),
@ -316,9 +357,12 @@ public class Type {
* @param clazzinfo the net.sf.jode.bytecode.ClassInfo.
* @return a singleton set containing the given type.
*/
public static final ClassType tClass(ClassInfo clazzinfo,
Type[] generics) {
public static final ClassInfoType tClass(ClassInfo clazzinfo,
Type[] generics,
ClassInfoType outer) {
int hash = clazzinfo.hashCode();
if (outer != null)
hash = hash * 11 + outer.hashCode();
if (generics != null) {
for (int i = 0; i < generics.length; i++)
hash = hash * 11 + generics[i].hashCode();
@ -327,14 +371,26 @@ public class Type {
while (iter.hasNext()) {
ClassInfoType type = (ClassInfoType) iter.next();
if (type.getClassInfo() == clazzinfo
&& type.outerClass == outer
&& Arrays.equals(generics, type.genericInstances))
return type;
}
ClassInfoType type = new ClassInfoType(clazzinfo, generics);
ClassInfoType type = new ClassInfoType(clazzinfo, generics, outer);
classHash.put(hash, type);
return type;
}
/**
* Generate the singleton set of the type represented by the given
* class info.
* @param clazzinfo the net.sf.jode.bytecode.ClassInfo.
* @return a singleton set containing the given type.
*/
public static final ClassInfoType tClass(ClassInfo clazzinfo,
Type[] generics) {
return tClass(clazzinfo, generics, null);
}
/**
* Generate the singleton set of the type represented by the given
* class info.
@ -342,7 +398,7 @@ public class Type {
* @return a singleton set containing the given type.
* deprecated This should be removed if generics work.
*/
public static final ClassType tClass(ClassInfo clazzinfo) {
public static final ClassInfoType tClass(ClassInfo clazzinfo) {
return tClass(clazzinfo, null);
}
@ -370,21 +426,11 @@ public class Type {
/**
* Generate/look up the method type for the given signature
* @param signature the method decriptor.
* @param signature the method descriptor.
* @return a method type (a singleton set).
*/
public static MethodType tMethod(ClassPath cp, String signature) {
int hash = signature.hashCode() + cp.hashCode();
Iterator iter = methodHash.iterateHashCode(hash);
while (iter.hasNext()) {
MethodType methodType = (MethodType) iter.next();
if (methodType.getTypeSignature().equals(signature)
&& methodType.getClassPath().equals(cp))
return methodType;
}
MethodType methodType = new MethodType(cp, signature);
methodHash.put(hash, methodType);
return methodType;
public static MethodType tMethod(ClassPath cp, ClassType declarer, String signature) {
return new MethodType(cp, declarer, signature);
}
/**

@ -63,6 +63,7 @@ class TryCatch {
}
}
@SuppressWarnings("finally")
int finallyBreaks() {
try {
simple();
@ -75,6 +76,7 @@ class TryCatch {
}
}
@SuppressWarnings("finally")
int whileInTry() {
int a=1;
try {
@ -95,6 +97,7 @@ class TryCatch {
}
}
@SuppressWarnings("finally")
void foo() {
TryCatch local = null;
while (true) {

Loading…
Cancel
Save