Forgot a few files, whoops.
Patch by: me, jat, mmendez
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1449 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/HasBounds.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/HasBounds.java
new file mode 100644
index 0000000..b5fd866
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/HasBounds.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.typeinfo;
+
+/**
+ * Interface implemented by elements that can have can have have bounds, namely
+ * type parameters and wildcards.
+ */
+public interface HasBounds {
+
+ /**
+ * Returns the bounds on this element.
+ *
+ * @return the bounds of this element; cannot be null
+ */
+ JBound getBounds();
+
+ /**
+ * Returns the first bound of this element.
+ *
+ * @return the first bound of this element; cannot be null
+ */
+ JClassType getFirstBound();
+}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/HasTypeParameters.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/HasTypeParameters.java
new file mode 100644
index 0000000..54108e1
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/HasTypeParameters.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.typeinfo;
+
+/**
+ * Interface implemented by elements that can have can have type parameters,
+ * namely classes and methods.
+ */
+public interface HasTypeParameters {
+
+ /**
+ * Returns the type parameters on this element.
+ *
+ * @return the type parameters on this element, or zero-sized array if this
+ * element is not generic
+ */
+ JTypeParameter[] getTypeParameters();
+}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java
new file mode 100644
index 0000000..0668c13
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.typeinfo;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import java.lang.annotation.Annotation;
+import java.util.Map;
+
+/**
+ * Base class for types that delegate to another type, such as a JTypeParameter
+ * or JParameterizedType.
+ */
+abstract class JDelegatingClassType extends JClassType {
+
+ protected JClassType baseType;
+
+ JDelegatingClassType() {
+ }
+
+ @Override
+ public final void addImplementedInterface(JClassType intf) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ public final void addMetaData(String tagName, String[] values) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ public final void addModifierBits(int bits) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ /**
+ * Delegating types generally cannot be constructed.
+ */
+ @Override
+ public JConstructor findConstructor(JType[] paramTypes) {
+ return null;
+ }
+
+ /**
+ * Subclasses will generally need to echo modified fields.
+ */
+ @Override
+ public abstract JField findField(String name);
+
+ /**
+ * Subclasses will generally need to echo modified methods.
+ */
+ @Override
+ public abstract JMethod findMethod(String name, JType[] paramTypes);
+
+ @Override
+ public JClassType findNestedType(String typeName) {
+ return baseType.findNestedType(typeName);
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return baseType.getAnnotation(annotationClass);
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return baseType.getAnnotations();
+ }
+
+ @Override
+ public int getBodyEnd() {
+ return baseType.getBodyEnd();
+ }
+
+ @Override
+ public int getBodyStart() {
+ return baseType.getBodyStart();
+ }
+
+ @Override
+ public CompilationUnitProvider getCompilationUnit() {
+ return baseType.getCompilationUnit();
+ }
+
+ /**
+ * Delegating types generally cannot be constructed.
+ */
+ @Override
+ public JConstructor getConstructor(JType[] paramTypes)
+ throws NotFoundException {
+ throw new NotFoundException();
+ }
+
+ /**
+ * Delegating types generally cannot be constructed.
+ */
+ @Override
+ public JConstructor[] getConstructors() {
+ return TypeOracle.NO_JCTORS;
+ }
+
+ @Override
+ public Annotation[] getDeclaredAnnotations() {
+ return baseType.getDeclaredAnnotations();
+ }
+
+ @Override
+ public JClassType getEnclosingType() {
+ return baseType.getEnclosingType();
+ }
+
+ public JClassType getErasedType() {
+ return baseType.getErasedType();
+ }
+
+ /**
+ * Subclasses will generally need to echo modified fields.
+ */
+ @Override
+ public abstract JField getField(String name);
+
+ /**
+ * Subclasses will generally need to echo modified fields.
+ */
+ @Override
+ public abstract JField[] getFields();
+
+ @Override
+ public JClassType[] getImplementedInterfaces() {
+ return baseType.getImplementedInterfaces();
+ }
+
+ @Override
+ public String getJNISignature() {
+ return baseType.getJNISignature();
+ }
+
+ @Override
+ public String[][] getMetaData(String tagName) {
+ return baseType.getMetaData(tagName);
+ }
+
+ @Override
+ public String[] getMetaDataTags() {
+ return baseType.getMetaDataTags();
+ }
+
+ /**
+ * Subclasses will generally need to echo modified methods.
+ */
+ @Override
+ public abstract JMethod getMethod(String name, JType[] paramTypes)
+ throws NotFoundException;
+
+ /**
+ * Subclasses will generally need to echo modified methods.
+ */
+ @Override
+ public abstract JMethod[] getMethods();
+
+ @Override
+ public String getName() {
+ return baseType.getName();
+ }
+
+ @Override
+ public JClassType getNestedType(String typeName) throws NotFoundException {
+ return baseType.getNestedType(typeName);
+ }
+
+ @Override
+ public JClassType[] getNestedTypes() {
+ return baseType.getNestedTypes();
+ }
+
+ @Override
+ public TypeOracle getOracle() {
+ return baseType.getOracle();
+ }
+
+ @Override
+ public JMethod[] getOverloads(String name) {
+ return baseType.getOverloads(name);
+ }
+
+ @Override
+ public JMethod[] getOverridableMethods() {
+ return baseType.getOverridableMethods();
+ }
+
+ @Override
+ public JPackage getPackage() {
+ return baseType.getPackage();
+ }
+
+ @Override
+ public JClassType[] getSubtypes() {
+ return baseType.getSubtypes();
+ }
+
+ @Override
+ public JClassType getSuperclass() {
+ return baseType.getSuperclass();
+ }
+
+ /**
+ * TODO: What is this???
+ */
+ @Override
+ public String getTypeHash() throws UnableToCompleteException {
+ return baseType.getTypeHash();
+ }
+
+ @Override
+ public int hashCode() {
+ return baseType.hashCode();
+ }
+
+ @Override
+ public boolean isAbstract() {
+ return baseType.isAbstract();
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+ return baseType.isAnnotationPresent(annotationClass);
+ }
+
+ @Override
+ public final JArrayType isArray() {
+ return null;
+ }
+
+ @Override
+ public boolean isAssignableFrom(JClassType possibleSubtype) {
+ return baseType.isAssignableFrom(possibleSubtype);
+ }
+
+ @Override
+ public boolean isAssignableTo(JClassType possibleSupertype) {
+ return baseType.isAssignableTo(possibleSupertype);
+ }
+
+ @Override
+ public JClassType isClass() {
+ return baseType.isClass();
+ }
+
+ @Override
+ public JClassType isClassOrInterface() {
+ return baseType.isClassOrInterface();
+ }
+
+ @Override
+ public boolean isDefaultInstantiable() {
+ return baseType.isDefaultInstantiable();
+ }
+
+ @Override
+ public JClassType isInterface() {
+ return baseType.isInterface();
+ }
+
+ @Override
+ public boolean isLocalType() {
+ return baseType.isLocalType();
+ }
+
+ @Override
+ public boolean isMemberType() {
+ return baseType.isMemberType();
+ }
+
+ @Override
+ public final JPrimitiveType isPrimitive() {
+ return null;
+ }
+
+ @Override
+ public boolean isPrivate() {
+ return baseType.isPrivate();
+ }
+
+ @Override
+ public boolean isProtected() {
+ return baseType.isProtected();
+ }
+
+ @Override
+ public boolean isPublic() {
+ return baseType.isPublic();
+ }
+
+ @Override
+ public boolean isStatic() {
+ return baseType.isStatic();
+ }
+
+ @Override
+ public void setSuperclass(JClassType type) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ public String toString() {
+ if (baseType.isInterface() != null) {
+ return "interface " + getQualifiedSourceName();
+ } else {
+ return "class " + getQualifiedSourceName();
+ }
+ }
+
+ @Override
+ protected void acceptSubtype(JClassType me) {
+ baseType.acceptSubtype(me);
+ }
+
+ @Override
+ protected int getModifierBits() {
+ return baseType.getModifierBits();
+ }
+
+ @Override
+ protected void getOverridableMethodsOnSuperclassesAndThisClass(
+ Map<String, JMethod> methodsBySignature) {
+ baseType.getOverridableMethodsOnSuperclassesAndThisClass(methodsBySignature);
+ }
+
+ @Override
+ protected void getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(
+ Map<String, JMethod> methodsBySignature) {
+ baseType.getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(methodsBySignature);
+ }
+
+ @Override
+ protected void notifySuperTypesOf(JClassType me) {
+ }
+
+ @Override
+ protected void removeSubtype(JClassType me) {
+ }
+
+ @Override
+ final void addConstructor(JConstructor ctor) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ final void addField(JField field) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ final void addMethod(JMethod method) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ final void addNestedType(JClassType type) {
+ throw new UnsupportedOperationException("modifying a "
+ + getClass().getSimpleName());
+ }
+
+ @Override
+ JClassType findNestedTypeImpl(String[] typeName, int index) {
+ return baseType.findNestedTypeImpl(typeName, index);
+ }
+
+ @Override
+ void notifySuperTypes() {
+ }
+
+ @Override
+ void removeFromSupertypes() {
+ }
+
+ final void setBaseType(JClassType baseType) {
+ this.baseType = baseType;
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
new file mode 100644
index 0000000..4347df4
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
@@ -0,0 +1,699 @@
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.typeinfo;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.util.Util;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Type representing a Java class or interface type.
+ */
+public class JRealClassType extends JClassType {
+
+ private final Set<JClassType> allSubtypes = new HashSet<JClassType>();
+
+ private final Annotations annotations = new Annotations();
+
+ private final int bodyEnd;
+
+ private final int bodyStart;
+
+ private JMethod[] cachedOverridableMethods;
+
+ private final List<JConstructor> constructors = new ArrayList<JConstructor>();
+
+ private final CompilationUnitProvider cup;
+
+ private final JPackage declaringPackage;
+
+ private final int declEnd;
+
+ private final int declStart;
+
+ private final JClassType enclosingType;
+
+ private final Map<String, JField> fields = new HashMap<String, JField>();
+
+ private final List<JClassType> interfaces = new ArrayList<JClassType>();
+
+ private final boolean isInterface;
+
+ private final boolean isLocalType;
+
+ private String lazyHash;
+
+ private String lazyQualifiedName;
+
+ private final HasMetaData metaData = new MetaData();
+
+ private final Map<String, List<JMethod>> methods = new HashMap<String, List<JMethod>>();
+
+ private int modifierBits;
+
+ private final String name;
+
+ private final String nestedName;
+
+ private final Map<String, JClassType> nestedTypes = new HashMap<String, JClassType>();
+
+ private final TypeOracle oracle;
+
+ private JClassType superclass;
+
+ public JRealClassType(TypeOracle oracle, CompilationUnitProvider cup,
+ JPackage declaringPackage, JClassType enclosingType, boolean isLocalType,
+ String name, int declStart, int declEnd, int bodyStart, int bodyEnd,
+ boolean isInterface) {
+ oracle.recordTypeInCompilationUnit(cup, this);
+ this.oracle = oracle;
+ this.cup = cup;
+ this.declaringPackage = declaringPackage;
+ this.enclosingType = enclosingType;
+ this.isLocalType = isLocalType;
+ this.name = name;
+ this.declStart = declStart;
+ this.declEnd = declEnd;
+ this.bodyStart = bodyStart;
+ this.bodyEnd = bodyEnd;
+ this.isInterface = isInterface;
+ if (enclosingType == null) {
+ // Add myself to my package.
+ //
+ declaringPackage.addType(this);
+ // The nested name of a top-level class is its simple name.
+ //
+ 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;
+ }
+ }
+
+ public void addAnnotations(
+ Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
+ annotations.addAnnotations(declaredAnnotations);
+ }
+
+ public void addImplementedInterface(JClassType intf) {
+ assert (intf != null);
+ interfaces.add(intf);
+ }
+
+ public void addMetaData(String tagName, String[] values) {
+ metaData.addMetaData(tagName, values);
+ }
+
+ public void addModifierBits(int bits) {
+ modifierBits |= bits;
+ }
+
+ public JConstructor findConstructor(JType[] paramTypes) {
+ JConstructor[] ctors = getConstructors();
+ for (int i = 0; i < ctors.length; i++) {
+ JConstructor candidate = ctors[i];
+ if (candidate.hasParamTypes(paramTypes)) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ public JField findField(String name) {
+ return fields.get(name);
+ }
+
+ public JMethod findMethod(String name, JType[] paramTypes) {
+ JMethod[] overloads = getOverloads(name);
+ for (int i = 0; i < overloads.length; i++) {
+ JMethod candidate = overloads[i];
+ if (candidate.hasParamTypes(paramTypes)) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ public JClassType findNestedType(String typeName) {
+ String[] parts = typeName.split("\\.");
+ return findNestedTypeImpl(parts, 0);
+ }
+
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return annotations.getAnnotation(annotationClass);
+ }
+
+ public Annotation[] getAnnotations() {
+ return annotations.getAnnotations();
+ }
+
+ public int getBodyEnd() {
+ return bodyEnd;
+ }
+
+ public int getBodyStart() {
+ return bodyStart;
+ }
+
+ public CompilationUnitProvider getCompilationUnit() {
+ return cup;
+ }
+
+ public JConstructor getConstructor(JType[] paramTypes)
+ throws NotFoundException {
+ JConstructor result = findConstructor(paramTypes);
+ if (result == null) {
+ throw new NotFoundException();
+ }
+ return result;
+ }
+
+ public JConstructor[] getConstructors() {
+ return constructors.toArray(TypeOracle.NO_JCTORS);
+ }
+
+ public Annotation[] getDeclaredAnnotations() {
+ return annotations.getDeclaredAnnotations();
+ }
+
+ public JClassType getEnclosingType() {
+ return enclosingType;
+ }
+
+ @Override
+ public JClassType getErasedType() {
+ return this;
+ }
+
+ public JField getField(String name) {
+ JField field = findField(name);
+ assert (field != null);
+ return field;
+ }
+
+ public JField[] getFields() {
+ return fields.values().toArray(TypeOracle.NO_JFIELDS);
+ }
+
+ public JClassType[] getImplementedInterfaces() {
+ return interfaces.toArray(TypeOracle.NO_JCLASSES);
+ }
+
+ @Override
+ public String getJNISignature() {
+ String typeName = nestedName.replace('.', '$');
+ String packageName = getPackage().getName().replace('.', '/');
+ if (packageName.length() > 0) {
+ packageName += "/";
+ }
+ return "L" + packageName + typeName + ";";
+ }
+
+ public String[][] getMetaData(String tagName) {
+ return metaData.getMetaData(tagName);
+ }
+
+ public String[] getMetaDataTags() {
+ return metaData.getMetaDataTags();
+ }
+
+ public JMethod getMethod(String name, JType[] paramTypes)
+ throws NotFoundException {
+ JMethod result = findMethod(name, paramTypes);
+ if (result == null) {
+ throw new NotFoundException();
+ }
+ return result;
+ }
+
+ /*
+ * Returns the declared methods of this class (not any superclasses or
+ * superinterfaces).
+ */
+ public JMethod[] getMethods() {
+ List<JMethod> resultMethods = new ArrayList<JMethod>();
+ for (List<JMethod> overloads : methods.values()) {
+ resultMethods.addAll(overloads);
+ }
+ return resultMethods.toArray(TypeOracle.NO_JMETHODS);
+ }
+
+ public String getName() {
+ return nestedName;
+ }
+
+ public JClassType getNestedType(String typeName) throws NotFoundException {
+ JClassType result = findNestedType(typeName);
+ if (result == null) {
+ throw new NotFoundException();
+ }
+ return result;
+ }
+
+ public JClassType[] getNestedTypes() {
+ return nestedTypes.values().toArray(TypeOracle.NO_JCLASSES);
+ }
+
+ public TypeOracle getOracle() {
+ return oracle;
+ }
+
+ public JMethod[] getOverloads(String name) {
+ List<?> resultMethods = methods.get(name);
+ if (resultMethods != null) {
+ return resultMethods.toArray(TypeOracle.NO_JMETHODS);
+ } else {
+ return TypeOracle.NO_JMETHODS;
+ }
+ }
+
+ /**
+ * Iterates over the most-derived declaration of each unique overridable
+ * method available in the type hierarchy of the specified type, including
+ * those found in superclasses and superinterfaces. A method is overridable if
+ * it is not <code>final</code> and its accessibility is <code>public</code>,
+ * <code>protected</code>, or package protected.
+ *
+ * Deferred binding generators often need to generate method implementations;
+ * this method offers a convenient way to find candidate methods to implement.
+ *
+ * Note that the behavior does not match
+ * {@link Class#getMethod(String, Class[])}, which does not return the most
+ * derived method in some cases.
+ *
+ * @return an array of {@link JMethod} objects representing overridable
+ * methods
+ */
+ public JMethod[] getOverridableMethods() {
+ if (cachedOverridableMethods == null) {
+ Map<String, JMethod> methodsBySignature = new TreeMap<String, JMethod>();
+ getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(methodsBySignature);
+ if (isClass() != null) {
+ getOverridableMethodsOnSuperclassesAndThisClass(methodsBySignature);
+ }
+ int size = methodsBySignature.size();
+ Collection<JMethod> leafMethods = methodsBySignature.values();
+ cachedOverridableMethods = leafMethods.toArray(new JMethod[size]);
+ }
+ return cachedOverridableMethods;
+ }
+
+ public JPackage getPackage() {
+ return declaringPackage;
+ }
+
+ @Override
+ public String getQualifiedSourceName() {
+ if (lazyQualifiedName == null) {
+ JPackage pkg = getPackage();
+ if (!pkg.isDefault()) {
+ lazyQualifiedName = pkg.getName() + "." + makeCompoundName(this);
+ } else {
+ lazyQualifiedName = makeCompoundName(this);
+ }
+ }
+ return lazyQualifiedName;
+ }
+
+ @Override
+ public String getSimpleSourceName() {
+ return name;
+ }
+
+ public JClassType[] getSubtypes() {
+ return allSubtypes.toArray(TypeOracle.NO_JCLASSES);
+ }
+
+ public JClassType getSuperclass() {
+ return superclass;
+ }
+
+ public String getTypeHash() throws UnableToCompleteException {
+ if (lazyHash == null) {
+ char[] source = cup.getSource();
+ int length = declEnd - declStart + 1;
+ String s = new String(source, declStart, length);
+ try {
+ lazyHash = Util.computeStrongName(s.getBytes(Util.DEFAULT_ENCODING));
+ } catch (UnsupportedEncodingException e) {
+ // Details, details...
+ throw new UnableToCompleteException();
+ }
+ }
+ return lazyHash;
+ }
+
+ public boolean isAbstract() {
+ return 0 != (modifierBits & TypeOracle.MOD_ABSTRACT);
+ }
+
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+ return annotations.isAnnotationPresent(annotationClass);
+ }
+
+ @Override
+ public JArrayType isArray() {
+ // intentional null
+ return null;
+ }
+
+ public boolean isAssignableFrom(JClassType possibleSubtype) {
+ if (possibleSubtype == this) {
+ return true;
+ }
+ if (allSubtypes.contains(possibleSubtype)) {
+ return true;
+ } else if (this == getOracle().getJavaLangObject()) {
+ // This case handles the odd "every interface is an Object"
+ // but doesn't actually have Object as a superclass.
+ //
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isAssignableTo(JClassType possibleSupertype) {
+ return possibleSupertype.isAssignableFrom(this);
+ }
+
+ @Override
+ public JClassType isClass() {
+ return isInterface ? null : this;
+ }
+
+ /**
+ * Determines if the class can be constructed using a simple <code>new</code>
+ * operation. Specifically, the class must
+ * <ul>
+ * <li>be a class rather than an interface, </li>
+ * <li>have either no constructors or a parameterless constructor, and</li>
+ * <li>be a top-level class or a static nested class.</li>
+ * </ul>
+ *
+ * @return <code>true</code> if the type is default instantiable, or
+ * <code>false</code> otherwise
+ */
+ public boolean isDefaultInstantiable() {
+ if (isInterface() != null) {
+ return false;
+ }
+ if (constructors.isEmpty()) {
+ return true;
+ }
+ JConstructor ctor = findConstructor(TypeOracle.NO_JTYPES);
+ if (ctor != null) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public JGenericType isGenericType() {
+ return null;
+ }
+
+ @Override
+ public JClassType isInterface() {
+ return isInterface ? this : null;
+ }
+
+ /**
+ * Tests if this type is a local type (within a method).
+ *
+ * @return true if this type is a local type, whether it is named or
+ * anonymous.
+ */
+ public boolean isLocalType() {
+ return isLocalType;
+ }
+
+ /**
+ * Tests if this type is contained within another type.
+ *
+ * @return true if this type has an enclosing type, false if this type is a
+ * top-level type
+ */
+ public boolean isMemberType() {
+ return enclosingType != null;
+ }
+
+ @Override
+ public JParameterizedType isParameterized() {
+ // intentional null
+ return null;
+ }
+
+ @Override
+ public JPrimitiveType isPrimitive() {
+ // intentional null
+ return null;
+ }
+
+ public boolean isPrivate() {
+ return 0 != (modifierBits & TypeOracle.MOD_PRIVATE);
+ }
+
+ public boolean isProtected() {
+ return 0 != (modifierBits & TypeOracle.MOD_PROTECTED);
+ }
+
+ public boolean isPublic() {
+ return 0 != (modifierBits & TypeOracle.MOD_PUBLIC);
+ }
+
+ @Override
+ public JRawType isRawType() {
+ // TODO Override in JGenericType?
+ return null;
+ }
+
+ public boolean isStatic() {
+ return 0 != (modifierBits & TypeOracle.MOD_STATIC);
+ }
+
+ public void setSuperclass(JClassType type) {
+ assert (type != null);
+ assert (isInterface() == null);
+ this.superclass = type;
+ JRealClassType realSuperType;
+ if (type.isParameterized() != null) {
+ realSuperType = type.isParameterized().getBaseType();
+ } else if (type.isRawType() != null) {
+ realSuperType = type.isRawType().getGenericType();
+ } else {
+ realSuperType = (JRealClassType) type;
+ }
+ annotations.setParent(realSuperType.annotations);
+ }
+
+ @Override
+ public String toString() {
+ if (isInterface) {
+ return "interface " + getQualifiedSourceName();
+ } else {
+ return "class " + getQualifiedSourceName();
+ }
+ }
+
+ protected void acceptSubtype(JClassType me) {
+ // TODO(scottb): revisit
+ allSubtypes.add(me);
+ notifySuperTypesOf(me);
+ }
+
+ protected int getModifierBits() {
+ return modifierBits;
+ }
+
+ protected void getOverridableMethodsOnSuperclassesAndThisClass(
+ Map<String, JMethod> methodsBySignature) {
+ assert (isClass() != null);
+
+ // Recurse first so that more derived methods will clobber less derived
+ // methods.
+ JClassType superClass = getSuperclass();
+ if (superClass != null) {
+ superClass.getOverridableMethodsOnSuperclassesAndThisClass(methodsBySignature);
+ }
+
+ JMethod[] declaredMethods = getMethods();
+ for (int i = 0; i < declaredMethods.length; i++) {
+ JMethod method = declaredMethods[i];
+
+ // Ensure that this method is overridable.
+ if (method.isFinal() || method.isPrivate()) {
+ // We cannot override this method, so skip it.
+ continue;
+ }
+
+ // We can override this method, so record it.
+ String sig = computeInternalSignature(method);
+ methodsBySignature.put(sig, method);
+ }
+ }
+
+ /**
+ * Gets the methods declared in interfaces that this type extends. If this
+ * type is a class, its own methods are not added. If this type is an
+ * interface, its own methods are added. Used internally by
+ * {@link #getOverridableMethods()}.
+ *
+ * @param methodsBySignature
+ */
+ protected void getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(
+ Map<String, JMethod> methodsBySignature) {
+ // Recurse first so that more derived methods will clobber less derived
+ // methods.
+ JClassType[] superIntfs = getImplementedInterfaces();
+ for (int i = 0; i < superIntfs.length; i++) {
+ JClassType superIntf = superIntfs[i];
+ superIntf.getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(methodsBySignature);
+ }
+
+ if (isInterface() == null) {
+ // This is not an interface, so we're done after having visited its
+ // implemented interfaces.
+ return;
+ }
+
+ JMethod[] declaredMethods = getMethods();
+ for (int i = 0; i < declaredMethods.length; i++) {
+ JMethod method = declaredMethods[i];
+
+ String sig = computeInternalSignature(method);
+ JMethod existing = methodsBySignature.get(sig);
+ if (existing != null) {
+ JClassType existingType = existing.getEnclosingType();
+ JClassType thisType = method.getEnclosingType();
+ if (thisType.isAssignableFrom(existingType)) {
+ // The existing method is in a more-derived type, so don't replace it.
+ continue;
+ }
+ }
+ methodsBySignature.put(sig, method);
+ }
+ }
+
+ /**
+ * Tells this type's superclasses and superinterfaces about it.
+ */
+ protected void notifySuperTypesOf(JClassType me) {
+ // TODO(scottb): revisit
+ if (superclass != null) {
+ superclass.acceptSubtype(me);
+ }
+ for (int i = 0, n = interfaces.size(); i < n; ++i) {
+ JClassType intf = interfaces.get(i);
+ intf.acceptSubtype(me);
+ }
+ }
+
+ protected void removeSubtype(JClassType me) {
+ // TODO(scottb): revisit
+ allSubtypes.remove(me);
+
+ if (superclass != null) {
+ superclass.removeSubtype(me);
+ }
+
+ for (int i = 0, n = interfaces.size(); i < n; ++i) {
+ JClassType intf = interfaces.get(i);
+
+ intf.removeSubtype(me);
+ }
+ }
+
+ void addConstructor(JConstructor ctor) {
+ assert (!constructors.contains(ctor));
+ constructors.add(ctor);
+ }
+
+ void addField(JField field) {
+ Object existing = fields.put(field.getName(), field);
+ assert (existing == null);
+ }
+
+ void addMethod(JMethod method) {
+ String methodName = method.getName();
+ List<JMethod> overloads = methods.get(methodName);
+ if (overloads == null) {
+ overloads = new ArrayList<JMethod>();
+ methods.put(methodName, overloads);
+ }
+ overloads.add(method);
+ }
+
+ void addNestedType(JClassType type) {
+ nestedTypes.put(type.getSimpleSourceName(), type);
+ }
+
+ JClassType findNestedTypeImpl(String[] typeName, int index) {
+ JClassType found = nestedTypes.get(typeName[index]);
+ if (found == null) {
+ return null;
+ } else if (index < typeName.length - 1) {
+ return found.findNestedTypeImpl(typeName, index + 1);
+ } else {
+ return found;
+ }
+ }
+
+ void notifySuperTypes() {
+ notifySuperTypesOf(this);
+ }
+
+ /**
+ * Removes references to this instance from all of its super types.
+ */
+ void removeFromSupertypes() {
+ removeSubtype(this);
+ }
+
+ private String computeInternalSignature(JMethod method) {
+ StringBuffer sb = new StringBuffer();
+ sb.setLength(0);
+ sb.append(method.getName());
+ JParameter[] params = method.getParameters();
+ for (int j = 0; j < params.length; j++) {
+ JParameter param = params[j];
+ sb.append("/");
+ sb.append(param.getType().getQualifiedSourceName());
+ }
+ return sb.toString();
+ }
+
+}