Revision: 5803 Author: j...@google.com Date: Mon Jul 27 09:35:29 2009 Log: Fix handling of enclosing classes.
http://code.google.com/p/google-web-toolkit/source/detail?r=5803 Modified: /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JAnnotationType.java /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JEnumType.java /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java /changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java /changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java /changes/jat/ihm/dev/core/test/com/google/gwt/dev/javac/asm/ResolveGenericsTest.java ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JAnnotationType.java Tue Jun 16 14:33:06 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JAnnotationType.java Mon Jul 27 09:35:29 2009 @@ -23,9 +23,9 @@ public class JAnnotationType extends JRealClassType { public JAnnotationType(TypeOracle oracle, JPackage declaringPackage, - JClassType enclosingType, boolean isLocalType, String name, + String enclosingTypeName, boolean isLocalType, String name, boolean isInterface) { - super(oracle, declaringPackage, enclosingType, isLocalType, name, + super(oracle, declaringPackage, enclosingTypeName, isLocalType, name, isInterface); } ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java Fri May 8 17:38:40 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java Mon Jul 27 09:35:29 2009 @@ -43,6 +43,23 @@ } return flattened; } + + protected static final String makeCompoundBinaryName(JClassType type) { + String prefix = ""; + if (type.getEnclosingType() != null) { + prefix = makeCompoundBinaryName(type.getEnclosingType()) + "$"; + } + return prefix + type.getSimpleSourceName(); + } + + protected static final String makeCompoundName(JClassType type) { + if (type.getEnclosingType() == null) { + return type.getSimpleSourceName(); + } else { + return makeCompoundName(type.getEnclosingType()) + "." + + type.getSimpleSourceName(); + } + } /** * Returns <code>true</code> if the rhs array type can be assigned to the @@ -557,23 +574,6 @@ protected JMaybeParameterizedType isMaybeParameterizedType() { return null; } - - protected final String makeCompoundBinaryName(JClassType type) { - String prefix = ""; - if (type.getEnclosingType() != null) { - prefix = makeCompoundBinaryName(type.getEnclosingType()) + "$"; - } - return prefix + type.getSimpleSourceName(); - } - - protected final String makeCompoundName(JClassType type) { - if (type.getEnclosingType() == null) { - return type.getSimpleSourceName(); - } else { - return makeCompoundName(type.getEnclosingType()) + "." - + type.getSimpleSourceName(); - } - } /** * Tells this type's superclasses and superinterfaces about it. ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JEnumType.java Tue Jun 16 14:33:06 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JEnumType.java Mon Jul 27 09:35:29 2009 @@ -25,9 +25,9 @@ private JEnumConstant[] lazyEnumConstants; public JEnumType(TypeOracle oracle, JPackage declaringPackage, - JClassType enclosingType, boolean isLocalType, String name, + String enclosingTypeName, boolean isLocalType, String name, boolean isInterface) { - super(oracle, declaringPackage, enclosingType, isLocalType, name, + super(oracle, declaringPackage, enclosingTypeName, isLocalType, name, isInterface); } ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java Wed Apr 1 12:12:47 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java Mon Jul 27 09:35:29 2009 @@ -30,9 +30,9 @@ private List<JTypeParameter> typeParams = Lists.create(); public JGenericType(TypeOracle oracle, JPackage declaringPackage, - JClassType enclosingType, boolean isLocalType, String name, + String enclosingTypeName, boolean isLocalType, String name, boolean isInterface, JTypeParameter[] jtypeParameters) { - super(oracle, declaringPackage, enclosingType, isLocalType, name, + super(oracle, declaringPackage, enclosingTypeName, isLocalType, name, isInterface); if (jtypeParameters != null) { ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java Tue Jun 16 14:33:06 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java Mon Jul 27 09:35:29 2009 @@ -34,7 +34,8 @@ private final JPackage declaringPackage; - private final JClassType enclosingType; + // Set when this class is resolved, then never modified. + private JRealClassType enclosingType; private List<JClassType> interfaces = Lists.create(); @@ -62,16 +63,27 @@ private JClassType superclass; + /** + * Create a class type that reflects an actual type. + * + * @param oracle + * @param declaringPackage + * @param enclosingTypeName the fully qualified source name of the enclosing + * class or null if a top-level class - setEnclosingType must be called + * later with the proper enclosing type if this is non-null + * @param isLocalType + * @param name + * @param isInterface + */ public JRealClassType(TypeOracle oracle, JPackage declaringPackage, - JClassType enclosingType, boolean isLocalType, String name, + String enclosingTypeName, boolean isLocalType, String name, boolean isInterface) { this.oracle = oracle; this.declaringPackage = declaringPackage; - this.enclosingType = enclosingType; this.isLocalType = isLocalType; this.name = name; this.isInterface = isInterface; - if (enclosingType == null) { + if (enclosingTypeName == null) { // Add myself to my package. // declaringPackage.addType(this); @@ -79,18 +91,12 @@ // nestedName = name; } else { - // Add myself to my enclosing type. - // - enclosingType.addNestedType(this); // Compute my "nested name". // - JClassType enclosing = enclosingType; - String nn = name; - do { - nn = enclosing.getSimpleSourceName() + "." + nn; - enclosing = enclosing.getEnclosingType(); - } while (enclosing != null); - nestedName = nn; + nestedName = enclosingTypeName + "." + name; + + // We will add ourselves to the enclosing class when it is set in + // setEnclosingType(). } oracle.addNewType(this); } @@ -241,7 +247,7 @@ if (!pkg.isDefault()) { lazyQualifiedBinaryName = pkg.getName() + "."; } - lazyQualifiedBinaryName += makeCompoundBinaryName(this); + lazyQualifiedBinaryName += nestedName.replace('.', '$'); } return lazyQualifiedBinaryName; } @@ -251,9 +257,9 @@ if (lazyQualifiedName == null) { JPackage pkg = getPackage(); if (!pkg.isDefault()) { - lazyQualifiedName = pkg.getName() + "." + makeCompoundName(this); + lazyQualifiedName = pkg.getName() + "." + nestedName; } else { - lazyQualifiedName = makeCompoundName(this); + lazyQualifiedName = nestedName; } } return lazyQualifiedName; @@ -430,6 +436,23 @@ public void resurrect() { oracle.resurrect(this); } + + /** + * INTERNAL METHOD -- this should only be called by TypeOracleMediator. + * + * TODO: reduce visibility. + * + * @param enclosingType + */ + public void setEnclosingType(JRealClassType enclosingType) { + assert this.enclosingType == null; + assert enclosingType != null; + + this.enclosingType = enclosingType; + + // Add myself to my enclosing type. + enclosingType.addNestedType(this); + } public void setResolved() { resolved = true; ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java Tue Jul 14 16:09:16 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java Mon Jul 27 09:35:29 2009 @@ -56,6 +56,7 @@ import com.google.gwt.dev.javac.impl.Shared; import com.google.gwt.dev.util.Name; import com.google.gwt.dev.util.Name.BinaryName; +import com.google.gwt.dev.util.Name.InternalName; import java.io.PrintWriter; import java.lang.annotation.Annotation; @@ -89,6 +90,8 @@ Opcodes.ACC_TRANSIENT, Shared.MOD_TRANSIENT, }; + private static final JTypeParameter[] NO_TYPE_PARAMETERS = new JTypeParameter[0]; + /** * Returns the binary name of a type. This is the same name that would be * returned by {...@link Class#getName()} for this type. @@ -134,7 +137,7 @@ reader.accept(new CollectTypeParams(params)); return params.toArray(new JTypeParameter[params.size()]); } - return new JTypeParameter[0]; + return NO_TYPE_PARAMETERS; } private static <T> Class<? extends T> getClassLiteral(TreeLogger logger, @@ -238,6 +241,17 @@ getDescriptor(buf, returnType); return buf.toString(); } + + private static JTypeParameter[] getTypeParametersForClass( + CollectClassData classData) { + JTypeParameter[] typeParams = null; + if (classData.getSignature() != null) { + // TODO(jat): do we need to consider generic types w/ method type + // params for local classes? + typeParams = collectTypeParams(classData.getSignature()); + } + return typeParams; + } private static Class<?> getWrapperClass(Class<?> primitiveClass) { assert primitiveClass.isPrimitive(); @@ -271,13 +285,22 @@ return "package-info".equals(qname); } + /** + * Returns true if this class is a non-static class inside a generic class. + * + * TODO(jat): do we need to consider the entire hierarchy? + * + * @param classData + * @param enclosingClassData + * @return + */ private static boolean nonStaticInsideGeneric(CollectClassData classData, - JRealClassType enclosingType) { - if (enclosingType == null + CollectClassData enclosingClassData) { + if (enclosingClassData == null || (classData.getAccess() & Opcodes.ACC_STATIC) != 0) { return false; } - return enclosingType.isGenericType() != null; + return getTypeParametersForClass(enclosingClassData) != null; } /** @@ -304,10 +327,10 @@ // map of internal names to class visitors // transient since it is not retained across calls to addnewUnits private transient Map<String, CollectClassData> classMap; - + // transient since it is not retained across calls to addnewUnits private transient HashMap<JRealClassType, CollectClassData> classMapType; - + public TypeOracleMediator() { this(null); } @@ -443,7 +466,7 @@ } private JRealClassType createType(CompiledClass compiledClass, - CollectClassData classData, JRealClassType enclosingType) { + CollectClassData classData, CollectClassData enclosingClassData) { int access = classData.getAccess(); String qname = compiledClass.getSourceName(); String className = Shared.getShortName(qname); @@ -452,25 +475,28 @@ JPackage pkg = typeOracle.getOrCreatePackage(jpkgName); boolean isIntf = (access & Opcodes.ACC_INTERFACE) != 0; boolean isLocalType = classData.isLocal(); + String enclosingTypeName = null; + if (enclosingClassData != null) { + enclosingTypeName = enclosingClassData.getName(); + int idx = enclosingTypeName.lastIndexOf('/'); + if (idx > 0) { + enclosingTypeName = enclosingTypeName.substring(idx + 1); + } + } if ((access & Opcodes.ACC_ANNOTATION) != 0) { - resultType = new JAnnotationType(typeOracle, pkg, enclosingType, false, + resultType = new JAnnotationType(typeOracle, pkg, enclosingTypeName , false, className, true); } else if ((access & Opcodes.ACC_ENUM) != 0) { - resultType = new JEnumType(typeOracle, pkg, enclosingType, isLocalType, + resultType = new JEnumType(typeOracle, pkg, enclosingTypeName, isLocalType, className, isIntf); } else { - JTypeParameter[] typeParams = null; - if (classData.getSignature() != null) { - // TODO(jat): do we need to consider generic types w/ method type - // params for local classes? - typeParams = collectTypeParams(classData.getSignature()); - } + JTypeParameter[] typeParams = getTypeParametersForClass(classData); if ((typeParams != null && typeParams.length > 0) - || nonStaticInsideGeneric(classData, enclosingType)) { - resultType = new JGenericType(typeOracle, pkg, enclosingType, + || nonStaticInsideGeneric(classData, enclosingClassData)) { + resultType = new JGenericType(typeOracle, pkg, enclosingTypeName, isLocalType, className, isIntf, typeParams); } else { - resultType = new JRealClassType(typeOracle, pkg, enclosingType, + resultType = new JRealClassType(typeOracle, pkg, enclosingTypeName, isLocalType, className, isIntf); } } @@ -502,16 +528,9 @@ JRealClassType realClassType = compiledClass.getRealClassType(); if (realClassType == null) { CollectClassData classData = classMap.get(compiledClass.getInternalName()); - JRealClassType enclosingType = null; - // TODO(jat): need to get enclosing classes from ClassData instead - CompiledClass enclosingClass = compiledClass.getEnclosingClass(); - if (enclosingClass != null) { - enclosingType = enclosingClass.getRealClassType(); - if (enclosingType == null) { - enclosingType = createType(enclosingClass, unresolvedTypes); - } - } - realClassType = createType(compiledClass, classData, enclosingType); + String outerClassName = classData.getOuterClass(); + CollectClassData enclosingClassData = classMap.get(outerClassName); + realClassType = createType(compiledClass, classData, enclosingClassData); unresolvedTypes.add(realClassType); compiledClass.setRealClassType(realClassType); } @@ -772,9 +791,19 @@ boolean stopHere = true; } + // Find our enclosing class and set it + CollectClassData classData = classMapType.get(type); + assert classData != null; + String outerClass = classData.getOuterClass(); + JRealClassType enclosingType = null; + if (outerClass != null) { + enclosingType = binaryMapper.get(outerClass); + type.setEnclosingType(enclosingType); + } + // Ensure enclosing classes are resolved - if (type.getEnclosingType() != null) { - if (!resolveClass(logger, type.getEnclosingType())) { + if (enclosingType != null) { + if (!resolveClass(logger, enclosingType)) { return false; } } @@ -784,8 +813,6 @@ TypeParameterLookup typeParamLookup = new TypeParameterLookup(); typeParamLookup.pushEnclosingScopes(type); - CollectClassData classData = classMapType.get(type); - assert classData != null; int access = classData.getAccess(); if (classData.getOuterClass() != null) { ======================================= --- /changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java Wed Jul 15 07:37:51 2009 +++ /changes/jat/ihm/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java Mon Jul 27 09:35:29 2009 @@ -349,6 +349,9 @@ // If this inner class is ourselves, merge the access flags, since // static, for example, only appears in the InnerClass attribute. if (this.name.equals(name)) { + if (outerName != null) { + outerClass = outerName; + } // TODO(jat): should we only pull in a subset of these flags? Use only // these flags, or what? For now, just grab ACC_STATIC and ACC_PRIVATE int copyFlags = access & (Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE); ======================================= --- /changes/jat/ihm/dev/core/test/com/google/gwt/dev/javac/asm/ResolveGenericsTest.java Wed Jul 15 07:37:51 2009 +++ /changes/jat/ihm/dev/core/test/com/google/gwt/dev/javac/asm/ResolveGenericsTest.java Mon Jul 27 09:35:29 2009 @@ -223,12 +223,16 @@ TypeVariable<?>[] typeParams = clazz.getTypeParameters(); JRealClassType type; int n = typeParams.length; + String enclosingTypeName = null; + if (enclosingType != null) { + enclosingTypeName = enclosingType.getName(); + } if (n == 0) { - type = new JRealClassType(oracle, pkg, enclosingType, + type = new JRealClassType(oracle, pkg, enclosingTypeName, false, clazz.getSimpleName(), clazz.isInterface()); } else { JTypeParameter[] params = createTypeParams(typeParams); - type = new JGenericType(oracle, pkg, enclosingType, false, + type = new JGenericType(oracle, pkg, enclosingTypeName, false, clazz.getSimpleName(), clazz.isInterface(), params); } return type; --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---