Enable methods to declare generics

git-svn-id: https://svn.code.sf.net/p/jode/code/branches/generics@1409 379699f6-c40d-0410-875b-85095c16579e
generics
hoenicke 17 years ago
parent ec94bc4489
commit c2bcab17c3
  1. 1
      jode/src/net/sf/jode/bytecode/Block.java
  2. 2
      jode/src/net/sf/jode/decompiler/MethodAnalyzer.java
  3. 7
      jode/src/net/sf/jode/expr/InvokeOperator.java
  4. 3
      jode/src/net/sf/jode/type/ClassInfoType.java
  5. 16
      jode/src/net/sf/jode/type/ClassType.java
  6. 5
      jode/src/net/sf/jode/type/GenericDeclarer.java
  7. 42
      jode/src/net/sf/jode/type/MethodType.java
  8. 9
      jode/src/net/sf/jode/type/Type.java

@ -280,6 +280,7 @@ public final class Block {
if (succs[succs.length-1] == null) if (succs[succs.length-1] == null)
output.println("\treturn"); output.println("\treturn");
else else
output.println("\tgoto "+succs[succs.length-1]); output.println("\tgoto "+succs[succs.length-1]);
} }
} }

@ -247,7 +247,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
} }
} }
this.methodType = Type.tMethod(cla.getClassPath(), cla.getType(), signature); this.methodType = Type.tMethod(cla.getClassPath(), cla.getType(), signature, genericTypes);
this.isConstructor = this.isConstructor =
methodName.equals("<init>") || methodName.equals("<clinit>"); methodName.equals("<init>") || methodName.equals("<clinit>");

@ -155,8 +155,9 @@ public final class InvokeOperator extends Operator
super(Type.tUnknown, 0); super(Type.tUnknown, 0);
this.classPath = methodAnalyzer.getClassAnalyzer().getClassPath(); this.classPath = methodAnalyzer.getClassAnalyzer().getClassPath();
this.ref = reference; this.ref = reference;
//TODO: generics
this.methodType = Type.tMethod(methodAnalyzer.getClassPath(), this.methodType = Type.tMethod(methodAnalyzer.getClassPath(),
null, reference.getType()); null, reference.getType(), null);
this.methodName = reference.getName(); this.methodName = reference.getName();
this.classType = (ClassType) this.classType = (ClassType)
Type.tType(methodAnalyzer.getClassPath(), null, reference.getClazz()); Type.tType(methodAnalyzer.getClassPath(), null, reference.getClazz());
@ -774,8 +775,10 @@ public final class InvokeOperator extends Operator
/* method name doesn't match*/ /* method name doesn't match*/
continue next_method; continue next_method;
// TODO Generics
Type[] otherParamTypes Type[] otherParamTypes
= Type.tMethod(methodAnalyzer.getClassPath(), null, methods[i].getSignature()) = Type.tMethod(methodAnalyzer.getClassPath(), null,
methods[i].getSignature(), null)
.getParameterTypes(); .getParameterTypes();
if (otherParamTypes.length != myParamTypes.length) { if (otherParamTypes.length != myParamTypes.length) {
/* parameter count doesn't match*/ /* parameter count doesn't match*/

@ -44,7 +44,7 @@ public class ClassInfoType extends ClassType {
} }
public ClassInfoType(ClassInfo clazz, Type[] generics, public ClassInfoType(ClassInfo clazz, Type[] generics,
ClassType outerClass) { GenericDeclarer outerClass) {
super(TC_CLASS, clazz.getName(), outerClass); super(TC_CLASS, clazz.getName(), outerClass);
this.clazz = clazz; this.clazz = clazz;
@ -68,7 +68,6 @@ public class ClassInfoType extends ClassType {
} }
genericInstances = generics; genericInstances = generics;
Map genericMap = new SimpleMap();
if (generics != null) { if (generics != null) {
/* parse generic names */ /* parse generic names */
genericNames = TypeSignature.getGenericNames(signature); genericNames = TypeSignature.getGenericNames(signature);

@ -26,14 +26,14 @@ import java.util.Stack;
* *
* @author Jochen Hoenicke * @author Jochen Hoenicke
*/ */
public abstract class ClassType extends ReferenceType { public abstract class ClassType extends ReferenceType implements GenericDeclarer {
/** /**
* The full qualified class name in java syntax. * The full qualified class name in java syntax.
*/ */
protected String className; protected String className;
protected String[] genericNames; protected String[] genericNames;
protected Type[] genericInstances; protected Type[] genericInstances;
protected ClassType outerClass; protected GenericDeclarer outerClass;
/* /*
* @invariant (genericNames == null) == (genericInstances == null) * @invariant (genericNames == null) == (genericInstances == null)
@ -41,6 +41,12 @@ public abstract class ClassType extends ReferenceType {
* (genericNames.length == genericInstances.length) * (genericNames.length == genericInstances.length)
*/ */
public ClassType(int typecode, String clazzName, GenericDeclarer outerClass) {
super(typecode);
className = clazzName;
this.outerClass = outerClass;
}
public String getClassName() { public String getClassName() {
return className; return className;
} }
@ -56,12 +62,6 @@ public abstract class ClassType extends ReferenceType {
return null; return null;
} }
public ClassType(int typecode, String clazzName, ClassType outerClass) {
super(typecode);
className = clazzName;
this.outerClass = outerClass;
}
public ClassType(int typecode, String clazzName, public ClassType(int typecode, String clazzName,
String[] genNames, Type[] genTypes) { String[] genNames, Type[] genTypes) {
super(typecode); super(typecode);

@ -0,0 +1,5 @@
package net.sf.jode.type;
public interface GenericDeclarer {
public Type getGeneric(String name);
}

@ -18,26 +18,32 @@
*/ */
package net.sf.jode.type; package net.sf.jode.type;
import java.util.Map;
import net.sf.jode.bytecode.ClassPath; import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.TypeSignature; import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.decompiler.ClassDeclarer; import net.sf.jode.decompiler.ClassDeclarer;
import net.sf.jode.util.SimpleMap;
/** /**
* This type represents an method type. * This type represents an method type.
* *
* @author Jochen Hoenicke * @author Jochen Hoenicke
*/ */
public class MethodType extends Type { public class MethodType extends Type implements GenericDeclarer {
final String signature; final String signature;
final Type[] parameterTypes; final Type[] parameterTypes;
final Type returnType; final Type returnType;
final String[] genericNames;
final Type[] genericInstances;
final GenericDeclarer declarer;
final ClassPath cp; final ClassPath cp;
public MethodType(ClassPath cp, ClassType declarer, String signature) { public MethodType(ClassPath cp, GenericDeclarer declarer, String signature, Type[] generics) {
/* TODO: /* TODO:
* We need TypeVariable: e.g. iff we have * We need TypeVariable: e.g. iff we have
* E getElm<E>(Vector<E> v); * E getElm<E>(Vector<E> v);
* then E is a TypeVariable and if we now, that input type is a * then E is a TypeVariable and if we know, that input type is a
* vector of Integer, then return value is Integer... * vector of Integer, then return value is Integer...
* *
* A problem is that casts of v omit the value for E. * A problem is that casts of v omit the value for E.
@ -45,19 +51,39 @@ public class MethodType extends Type {
super(TC_METHOD); super(TC_METHOD);
this.cp = cp; this.cp = cp;
this.signature = signature; this.signature = signature;
if (signature.charAt(0) == '<') { this.declarer = declarer;
/* handled by MethodAnalyzer */ genericInstances = generics;
signature = signature.substring(signature.indexOf('(')); genericNames = TypeSignature.getGenericNames(signature);
if (generics != null) {
/* parse generic names */
if (generics.length != genericNames.length)
throw new IllegalArgumentException
("Wrong number of generic parameters");
} }
if (signature.charAt(0) == '<')
signature = signature.substring(signature.indexOf('('));
String[] params = TypeSignature.getParameterTypes(signature); String[] params = TypeSignature.getParameterTypes(signature);
parameterTypes = new Type[params.length]; parameterTypes = new Type[params.length];
for (int i = 0; i < params.length; i++) { for (int i = 0; i < params.length; i++) {
parameterTypes[i] = Type.tType(cp, declarer, params[i]); parameterTypes[i] = Type.tType(cp, this, params[i]);
} }
returnType = Type.tType(cp, declarer, returnType = Type.tType(cp, this,
TypeSignature.getReturnType(signature)); TypeSignature.getReturnType(signature));
} }
public Type getGeneric(String name) {
if (genericInstances != null && /*TODO */ genericNames != null) {
for (int i = 0; i < genericNames.length; i++)
if (genericNames[i].equals(name))
return genericInstances[i];
}
if (declarer != null)
return declarer.getGeneric(name);
return null;
}
public final int stackSize() { public final int stackSize() {
int size = returnType.stackSize(); int size = returnType.stackSize();
for (int i=0; i<parameterTypes.length; i++) for (int i=0; i<parameterTypes.length; i++)

@ -211,7 +211,7 @@ public class Type {
return tType(declarer.getClassPath(), null, signature); return tType(declarer.getClassPath(), null, signature);
} }
public static final ClassInfoType tClassSig(ClassPath cp, ClassType declarer, public static final ClassInfoType tClassSig(ClassPath cp, GenericDeclarer declarer,
String signature) String signature)
{ {
Type[] generics = null; Type[] generics = null;
@ -266,7 +266,7 @@ public class Type {
* @param type the type signature (or method signature). * @param type the type signature (or method signature).
* @return a singleton set containing the given type. * @return a singleton set containing the given type.
*/ */
public static final Type tType(ClassPath cp, ClassType declarer, public static final Type tType(ClassPath cp, GenericDeclarer declarer,
String signature) { String signature) {
if (signature == null || signature.length() == 0) if (signature == null || signature.length() == 0)
return tError; return tError;
@ -429,8 +429,9 @@ public class Type {
* @param signature the method descriptor. * @param signature the method descriptor.
* @return a method type (a singleton set). * @return a method type (a singleton set).
*/ */
public static MethodType tMethod(ClassPath cp, ClassType declarer, String signature) { public static MethodType tMethod(ClassPath cp, GenericDeclarer declarer,
return new MethodType(cp, declarer, signature); String signature, Type[] generics) {
return new MethodType(cp, declarer, signature, generics);
} }
/** /**

Loading…
Cancel
Save