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. 42
      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. 152
      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 excluding="src/|innerclasses/" kind="src" path="test"/>
<classpathentry kind="src" path="test/innerclasses"/> <classpathentry kind="src" path="test/innerclasses"/>
<classpathentry kind="src" path="test/src"/> <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/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="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"/> <classpathentry kind="output" path="build"/>
</classpath> </classpath>

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

@ -19,6 +19,7 @@
package net.sf.jode.bytecode; package net.sf.jode.bytecode;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.ArrayList;
import java.util.Map; import java.util.Map;
///#enddef ///#enddef
@ -429,6 +430,65 @@ public class TypeSignature {
return params; 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, private static int mapGenericsInType(String typeSig, Map generics,
StringBuffer mapped, int spos) { StringBuffer mapped, int spos) {
int pos = spos; int pos = spos;
@ -551,34 +611,36 @@ public class TypeSignature {
private static int checkClassName(String clName, int i) private static int checkClassName(String clName, int i)
throws IllegalArgumentException, StringIndexOutOfBoundsException throws IllegalArgumentException, StringIndexOutOfBoundsException
{ {
while (true) { char c = clName.charAt(i++);
char c = clName.charAt(i++); while (c != ';' && c != '.' && c != '<') {
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;
if (c != '/' && !Character.isJavaIdentifierPart(c)) if (c != '/' && !Character.isJavaIdentifierPart(c))
throw new IllegalArgumentException("Illegal java class name: " throw new IllegalArgumentException("Illegal java class name: "
+ clName); + 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 if ((Options.options & Options.OPTION_INNER) != 0
&& parent instanceof ClassAnalyzer && !isStatic()) && parent instanceof ClassAnalyzer && !isStatic())
outerInstance = new ThisOperator(((ClassAnalyzer) parent).clazz); outerInstance = new ThisOperator((ClassAnalyzer) parent);
if (outerValues != null) if (outerValues != null)
this.outerValues = new OuterValues(this, outerValues); this.outerValues = new OuterValues(this, outerValues);
} }
@ -569,7 +569,7 @@ public class ClassAnalyzer
} }
String signature = clazz.getSignature(); String signature = clazz.getSignature();
System.err.println("Class Signature: "+signature+ " (class "+name+")"); System.err.println("Class Signature: "+signature+ " (class "+name+")");
writer.printExtendsImplements(Type.tClass(clazz)); writer.printExtendsImplements(myType);
writer.println(); writer.println();
writer.openBraceClass(); writer.openBraceClass();
@ -799,6 +799,18 @@ public class ClassAnalyzer
return getParent().getClassAnalyzer(cinfo); 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. * Get the class analyzer for the given inner class.
* @param name the short name of the inner class * @param name the short name of the inner class

@ -19,6 +19,8 @@
package net.sf.jode.decompiler; package net.sf.jode.decompiler;
import net.sf.jode.bytecode.ClassInfo; 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 * This is the interface for objects, that a method can declare
@ -30,6 +32,12 @@ public interface ClassDeclarer {
*/ */
public ClassDeclarer getParent(); 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 * Get the class analyzer for the given anonymous class info. It
* will search it in the classes we declare and in the parent * will search it in the classes we declare and in the parent
@ -38,5 +46,13 @@ public interface ClassDeclarer {
*/ */
public ClassAnalyzer getClassAnalyzer(ClassInfo ci); 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); public void addClassAnalyzer(ClassAnalyzer classAna);
} }

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

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

@ -22,10 +22,12 @@ import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.BasicBlocks; import net.sf.jode.bytecode.BasicBlocks;
import net.sf.jode.bytecode.Block; import net.sf.jode.bytecode.Block;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.Handler; import net.sf.jode.bytecode.Handler;
import net.sf.jode.bytecode.Instruction; import net.sf.jode.bytecode.Instruction;
import net.sf.jode.bytecode.LocalVariableInfo; import net.sf.jode.bytecode.LocalVariableInfo;
import net.sf.jode.bytecode.MethodInfo; import net.sf.jode.bytecode.MethodInfo;
import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.jvm.SyntheticAnalyzer; import net.sf.jode.jvm.SyntheticAnalyzer;
import net.sf.jode.type.*; import net.sf.jode.type.*;
import net.sf.jode.expr.Expression; import net.sf.jode.expr.Expression;
@ -53,6 +55,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Collection; import java.util.Collection;
import java.util.ArrayList; import java.util.ArrayList;
@ -186,6 +189,11 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
* classes that are used in this method. * classes that are used in this method.
*/ */
Collection usedAnalyzers; Collection usedAnalyzers;
/**
* This array contains the generic types this method declares if
* it is generic.
*/
GenericParameterType[] genericTypes;
/** /**
* This is the default constructor. * This is the default constructor.
@ -199,7 +207,47 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
this.imports = imports; this.imports = imports;
this.minfo = minfo; this.minfo = minfo;
this.methodName = minfo.getName(); 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 = this.isConstructor =
methodName.equals("<init>") || methodName.equals("<clinit>"); methodName.equals("<init>") || methodName.equals("<clinit>");
@ -423,8 +471,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
LocalInfo li = new LocalInfo(this, lvi.getSlot()); LocalInfo li = new LocalInfo(this, lvi.getSlot());
if ((Options.options & Options.OPTION_LVT) != 0 if ((Options.options & Options.OPTION_LVT) != 0
&& lvi.getName() != null) && lvi.getName() != null)
li.addHint(lvi.getName(), Type.tType(classAnalyzer.getClassPath(), li.addHint(lvi.getName(),
lvi.getType())); Type.tType(classAnalyzer.getClassPath(),
classAnalyzer.getType(),
lvi.getType()));
allLocals.addElement(li); allLocals.addElement(li);
return li; return li;
} }
@ -582,11 +632,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
int offset = 0; int offset = 0;
int slot = 0; int slot = 0;
if (!isStatic()) { if (!isStatic()) {
ClassInfo classInfo = classAnalyzer.getClazz();
param[offset] = getLocalInfo(bb != null param[offset] = getLocalInfo(bb != null
? bb.getParamInfo(slot) ? bb.getParamInfo(slot)
: LocalVariableInfo.getInfo(slot)); : LocalVariableInfo.getInfo(slot));
param[offset].setExpression(new ThisOperator(classInfo, true)); param[offset].setExpression(new ThisOperator(classAnalyzer, true));
slot++; slot++;
offset++; offset++;
} }
@ -1011,7 +1060,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
expr).getSubExpressions()[0]; expr).getSubExpressions()[0];
if (expr instanceof ThisOperator) { if (expr instanceof ThisOperator) {
outerValueArray[j] = outerValueArray[j] =
new ThisOperator(((ThisOperator) expr).getClassInfo()); new ThisOperator(((ThisOperator) expr).getClassAnalyzer());
continue; continue;
} }
LocalInfo li = null; LocalInfo li = null;
@ -1109,6 +1158,23 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
return getParent().getClassAnalyzer(cinfo); 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) { public void addClassAnalyzer(ClassAnalyzer clazzAna) {
if (innerAnalyzers == null) if (innerAnalyzers == null)
innerAnalyzers = new Vector(); innerAnalyzers = new Vector();

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

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

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

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

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

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

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

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

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

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

@ -18,16 +18,13 @@
*/ */
package net.sf.jode.type; 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 * This class represents the singleton set containing one parameter type. For
* from package java.lang, that need special handling, like * example in the context of the class <code>Enum&lt;E extends
* Object, String, StringBuffer, etc. * 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 * @author Jochen Hoenicke
*/ */
@ -41,7 +38,7 @@ public class GenericParameterType extends ClassType {
public GenericParameterType(String className, public GenericParameterType(String className,
ClassType superType, ClassType superType,
ClassType[] ifacesTypes) { ClassType[] ifacesTypes) {
super(TC_SYSCLASS, className); super(TC_SYSCLASS, className, null);
this.superType = superType; this.superType = superType;
this.ifacesTypes = ifacesTypes; this.ifacesTypes = ifacesTypes;
} }

@ -20,6 +20,7 @@
package net.sf.jode.type; package net.sf.jode.type;
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;
/** /**
* This type represents an method type. * This type represents an method type.
@ -32,21 +33,29 @@ public class MethodType extends Type {
final Type returnType; final Type returnType;
final ClassPath cp; 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); super(TC_METHOD);
this.cp = cp; this.cp = cp;
this.signature = signature; this.signature = signature;
if (signature.charAt(0) == '<') { if (signature.charAt(0) == '<') {
/*FIXME */ /* handled by MethodAnalyzer */
signature = signature.substring(signature.indexOf('(')); 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, params[i]); parameterTypes[i] = Type.tType(cp, declarer, params[i]);
} }
returnType = Type.tType(cp, returnType = Type.tType(cp, declarer,
signature.substring(signature.indexOf(')')+1)); TypeSignature.getReturnType(signature));
} }
public final int stackSize() { 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 superType,
ClassType[] ifacesTypes, ClassType[] ifacesTypes,
boolean isFinal, boolean isInterface) { boolean isFinal, boolean isInterface) {
super(TC_SYSCLASS, className); super(TC_SYSCLASS, className, null);
this.superType = superType; this.superType = superType;
this.ifacesTypes = ifacesTypes; this.ifacesTypes = ifacesTypes;
this.isFinal = isFinal; this.isFinal = isFinal;

@ -22,11 +22,10 @@ import net.sf.jode.GlobalOptions;
import net.sf.jode.bytecode.ClassPath; import net.sf.jode.bytecode.ClassPath;
import net.sf.jode.bytecode.ClassInfo; import net.sf.jode.bytecode.ClassInfo;
import net.sf.jode.bytecode.TypeSignature; import net.sf.jode.bytecode.TypeSignature;
import net.sf.jode.decompiler.ClassDeclarer;
import net.sf.jode.util.UnifyHash; import net.sf.jode.util.UnifyHash;
///#def COLLECTIONS java.util ///#def COLLECTIONS java.util
import java.util.Collections;
import java.util.Map;
import java.util.Iterator; import java.util.Iterator;
import java.util.Arrays; import java.util.Arrays;
///#enddef ///#enddef
@ -64,7 +63,6 @@ public class Type {
private static final UnifyHash classHash = new UnifyHash(); private static final UnifyHash classHash = new UnifyHash();
private static final UnifyHash arrayHash = 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. * This type represents the singleton set containing the boolean type.
@ -194,22 +192,82 @@ public class Type {
* string. * string.
* @param classpath the current classpath. * @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. * @return a singleton set containing the given type.
*/ */
public static final Type tType(ClassPath cp, String 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 * Generate the singleton set of the type represented by the given
* string. * string.
* @param classpath the current classpath. * @param declarer a class declarer for the current context.
* @param signature the type signature (or method signature). * @param type the type signature (or method signature).
* @param parameterMap the map from type variables to real types.
* @return a singleton set containing the given type. * @return a singleton set containing the given type.
*/ */
public static final Type tType(ClassPath cp, String signature, public static final Type tType(ClassDeclarer declarer,
Map parameterMap) { 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, ClassType declarer,
String signature) {
if (signature == null || signature.length() == 0) if (signature == null || signature.length() == 0)
return tError; return tError;
switch(signature.charAt(0)) { switch(signature.charAt(0)) {
@ -232,41 +290,24 @@ public class Type {
case 'V': case 'V':
return tVoid; return tVoid;
case '[': case '[':
return tArray(tType(cp, signature.substring(1))); return tArray(tType(cp, declarer, signature.substring(1)));
case 'L': { case 'L': {
int endIndex = signature.length()-1; int endIndex = signature.length()-1;
Type[] generics = null;
if (signature.charAt(endIndex) != ';') if (signature.charAt(endIndex) != ';')
return tError; return tError;
if (signature.charAt(endIndex-1) == '>') { Type type = tClassSig(cp, declarer,
/* parse parameter types */ signature.substring(1, endIndex));
int index = signature.indexOf('<'); if (type == null)
String[] genericNames = TypeSignature return tError;
.getArgumentTypes(signature.substring(index, endIndex)); return type;
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);
} }
case 'T': { case 'T': {
int index = signature.indexOf(';'); int index = signature.indexOf(';');
if (index != signature.length()-1) if (index != signature.length()-1)
return tError; 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) if (type == null)
return tError; return tError;
return type; return type;
@ -282,7 +323,7 @@ public class Type {
* The packages may be separated by `.' or `/'. * The packages may be separated by `.' or `/'.
* @return a singleton set containing the given type. * @return a singleton set containing the given type.
*/ */
public static final ClassType tClass(ClassPath classPath, public static final ClassInfoType tClass(ClassPath classPath,
String className, String className,
Type[] generics) { Type[] generics) {
return tClass(classPath.getClassInfo(className.replace('/','.')), return tClass(classPath.getClassInfo(className.replace('/','.')),
@ -316,9 +357,12 @@ public class Type {
* @param clazzinfo the net.sf.jode.bytecode.ClassInfo. * @param clazzinfo the net.sf.jode.bytecode.ClassInfo.
* @return a singleton set containing the given type. * @return a singleton set containing the given type.
*/ */
public static final ClassType tClass(ClassInfo clazzinfo, public static final ClassInfoType tClass(ClassInfo clazzinfo,
Type[] generics) { Type[] generics,
ClassInfoType outer) {
int hash = clazzinfo.hashCode(); int hash = clazzinfo.hashCode();
if (outer != null)
hash = hash * 11 + outer.hashCode();
if (generics != null) { if (generics != null) {
for (int i = 0; i < generics.length; i++) for (int i = 0; i < generics.length; i++)
hash = hash * 11 + generics[i].hashCode(); hash = hash * 11 + generics[i].hashCode();
@ -327,14 +371,26 @@ public class Type {
while (iter.hasNext()) { while (iter.hasNext()) {
ClassInfoType type = (ClassInfoType) iter.next(); ClassInfoType type = (ClassInfoType) iter.next();
if (type.getClassInfo() == clazzinfo if (type.getClassInfo() == clazzinfo
&& type.outerClass == outer
&& Arrays.equals(generics, type.genericInstances)) && Arrays.equals(generics, type.genericInstances))
return type; return type;
} }
ClassInfoType type = new ClassInfoType(clazzinfo, generics); ClassInfoType type = new ClassInfoType(clazzinfo, generics, outer);
classHash.put(hash, type); classHash.put(hash, type);
return 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 * Generate the singleton set of the type represented by the given
* class info. * class info.
@ -342,7 +398,7 @@ public class Type {
* @return a singleton set containing the given type. * @return a singleton set containing the given type.
* deprecated This should be removed if generics work. * 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); return tClass(clazzinfo, null);
} }
@ -370,21 +426,11 @@ public class Type {
/** /**
* Generate/look up the method type for the given signature * 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). * @return a method type (a singleton set).
*/ */
public static MethodType tMethod(ClassPath cp, String signature) { public static MethodType tMethod(ClassPath cp, ClassType declarer, String signature) {
int hash = signature.hashCode() + cp.hashCode(); return new MethodType(cp, declarer, signature);
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;
} }
/** /**

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

Loading…
Cancel
Save