summaryrefslogtreecommitdiff
path: root/gnu/java/lang/reflect/GenericSignatureParser.java
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2006-04-03 20:09:13 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2006-04-03 20:09:13 +0000
commit2a8df925bcd276fa213b64d1fca0cf4a52c4040d (patch)
tree3bbb67d6bbc77ccaf38bb627c179bf14f3f2554b /gnu/java/lang/reflect/GenericSignatureParser.java
parent3f864b39e567ca569021118e754891eb1956610c (diff)
downloadclasspath-2a8df925bcd276fa213b64d1fca0cf4a52c4040d.tar.gz
2006-04-03 Andrew John Hughes <gnu_andrew@member.fsf.org>
* gnu/java/lang/reflect/ClassSignatureParser.java, * gnu/java/lang/reflect/FieldSignatureParser.java, * gnu/java/lang/reflect/GenericSignatureParser.java, * gnu/java/lang/reflect/MethodSignatureParser.java, * gnu/java/lang/reflect/TypeImpl.java, * java/lang/Class.java, * java/lang/reflect/GenericDeclaration.java, * java/lang/reflect/MalformedParameterizedTypeException.java, * java/lang/reflect/TypeVariable.java, * java/util/Arrays.java, * vm/reference/java/lang/VMClass.java, * vm/reference/java/lang/reflect/Constructor.java, * vm/reference/java/lang/reflect/Method.java: Incorporate changes from the generics branch. 2005-10-01 Jeroen Frijters <jeroen@frijters.net> * vm/reference/java/lang/reflect/Constructor.java (getSignature): New method. (getGenericExceptionTypes): New method. (getGenericParameterTypes): New method. * vm/reference/java/lang/reflect/Method.java (getSignature): New method. (getGenericExceptionTypes): New method. (getGenericParameterTypes): New method. (getGenericReturnType): New method. 2005-09-30 Jeroen Frijters <jeroen@frijters.net> * gnu/java/lang/reflect/FieldSignatureParser.java: New file. * gnu/java/lang/reflect/ClassSignatureParser.java, gnu/java/lang/reflect/GenericSignatureParser.java, gnu/java/lang/reflect/MethodSignatureParser.java: Finished implementation. 2005-09-25 Jeroen Frijters <jeroen@frijters.net> * gnu/java/lang/reflect/ClassSignatureParser.java, gnu/java/lang/reflect/GenericSignatureParser.java, gnu/java/lang/reflect/MethodSignatureParser.java: New files. * java/lang/Class.java (getGenericInterfaces, getGenericSuperclass, getTypeParameters): Implemented. * vm/reference/java/lang/VMClass.java (getSimpleName, getDeclaredAnnotations, getCanonicalName, getEnclosingClass, getEnclosingConstructor, getEnclosingMethod, isAnonymousClass, isLocalClass, isMemberClass): Removed generic types from signatures. (getGenericInterfaces, getGenericSuperclass, getTypeParameters): Removed. (getClassSignature): New method. * vm/reference/java/lang/reflect/Constructor.java (getTypeParameters): Implemented. * vm/reference/java/lang/reflect/Method.java (getTypeParameters, getSignature): New methods. 2005-06-09 Andrew John Hughes <gnu_andrew@member.fsf.org> * java/lang/Class.java: (asSubclass(Class)): Documented. (getCanonicalName()): Implemented. (getEnclosingClass()): Implemented. (getEnclosingConstructor()): Implemented. (getEnclosingMethod()): Implemented. (getGenericInterfaces()): Implemented. (getGenericSuperclass()): Implemented. (getTypeParameters()): Implemented. (isAnonymousClass()): Implemented. (isLocalClass()): Implemented. (isMemberClass()): Implemented. * vm/reference/java/lang/VMClass.java: (getSuperClass(Class<?>)): Updated return type. (getSimpleName(Class<?>)): Use VM methods directly. (getCanonicalName(Class<?>)): Implemented. (getEnclosingClass(Class<?>)): New native method. (getEnclosingConstructor(Class<?>)): New native method. (getEnclosingMethod(Class<?>)): New native method. (getGenericInterfaces(Class<?>)): New native method. (getGenericSuperclass(Class<?>)): New native method. (getTypeParameters(Class<T>)): New native method. (isAnonymousClass(Class<?>)): New native method. (isLocalClass(Class<?>)): New native method. (isMemberClass(Class<?>)): New native method. * vm/reference/java/lang/reflect/Constructor.java: (getTypeParameters()): Changed to native method. 2005-05-05 Andrew John Hughes <gnu_andrew@member.fsf.org> * java/lang/Class.java: (getSimpleName()): Implemented. * vm/reference/java/lang/VMClass.java: (getSimpleName()): Reference implementation. 2005-04-20 Tom Tromey <tromey@redhat.com> * java/util/Arrays.java (hashCode): New methods. (deepHashCode): New method. (deepEquals): Likewise. (toString): New methods. (deepToString): New method. 2005-04-04 Andrew John Hughes <gnu_andrew@member.fsf.org> * java/lang/Class.java: (isEnum()): New method implemented. (isSynthetic()): New method implemented. (isAnnotation()): New method implemented. * vm/reference/java/lang/VMClass.java: (isEnum()): New native method. (isSynthetic()): New native method. (isAnnotation()): New native method. 2005-03-21 Andrew John Hughes <gnu_andrew@member.fsf.org> * java/lang/Class.java: Implements java.lang.reflect.Type
Diffstat (limited to 'gnu/java/lang/reflect/GenericSignatureParser.java')
-rw-r--r--gnu/java/lang/reflect/GenericSignatureParser.java622
1 files changed, 622 insertions, 0 deletions
diff --git a/gnu/java/lang/reflect/GenericSignatureParser.java b/gnu/java/lang/reflect/GenericSignatureParser.java
new file mode 100644
index 000000000..399f1bdc4
--- /dev/null
+++ b/gnu/java/lang/reflect/GenericSignatureParser.java
@@ -0,0 +1,622 @@
+/* GenericSignatureParser.java
+ Copyright (C) 2005
+ Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.lang.reflect;
+
+import java.lang.reflect.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+final class TypeVariableImpl extends TypeImpl implements TypeVariable
+{
+ private GenericDeclaration decl;
+ private Type[] bounds;
+ private String name;
+
+ TypeVariableImpl(GenericDeclaration decl, Type[] bounds, String name)
+ {
+ this.decl = decl;
+ this.bounds = bounds;
+ this.name = name;
+ }
+
+ Type resolve()
+ {
+ return this;
+ }
+
+ /* FIXME[GENERICS]: Remove cast */
+ public Type[] getBounds()
+ {
+ resolve(bounds);
+ return (Type[]) bounds.clone();
+ }
+
+ public GenericDeclaration getGenericDeclaration()
+ {
+ return decl;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof TypeVariableImpl)
+ {
+ TypeVariableImpl other = (TypeVariableImpl)obj;
+ return decl.equals(other.decl) && name.equals(other.name);
+ }
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return 0x5f4d5156 ^ decl.hashCode() ^ name.hashCode();
+ }
+
+ public String toString()
+ {
+ return name;
+ }
+}
+
+final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType
+{
+ private String rawTypeName;
+ private ClassLoader loader;
+ private Class rawType;
+ private Type owner;
+ private Type[] typeArgs;
+
+ ParameterizedTypeImpl(String rawTypeName, ClassLoader loader, Type owner,
+ Type[] typeArgs)
+ {
+ this.rawTypeName = rawTypeName;
+ this.loader = loader;
+ this.owner = owner;
+ this.typeArgs = typeArgs;
+ }
+
+ Type resolve()
+ {
+ if (rawType == null)
+ {
+ try
+ {
+ rawType = Class.forName(rawTypeName, false, loader);
+ }
+ catch (ClassNotFoundException x)
+ {
+ throw new TypeNotPresentException(rawTypeName, x);
+ }
+ }
+ if (typeArgs == null)
+ {
+ if (owner == null)
+ {
+ return rawType;
+ }
+ typeArgs = new Type[0];
+ }
+ resolve(typeArgs);
+ owner = resolve(owner);
+ return this;
+ }
+
+ /* FIXME[GENERICS]: Remove cast */
+ public Type[] getActualTypeArguments()
+ {
+ return (Type[]) typeArgs.clone();
+ }
+
+ public Type getRawType()
+ {
+ return rawType;
+ }
+
+ public Type getOwnerType()
+ {
+ return owner;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ParameterizedTypeImpl)
+ {
+ ParameterizedTypeImpl other = (ParameterizedTypeImpl)obj;
+ return rawType.equals(other.rawType)
+ && ((owner == null && other.owner == null)
+ || owner.equals(other.owner))
+ && Arrays.deepEquals(typeArgs, other.typeArgs);
+ }
+ return false;
+ }
+
+ public int hashCode()
+ {
+ int h = 0x58158970 ^ rawType.hashCode();
+ if (owner != null)
+ {
+ h ^= Integer.reverse(owner.hashCode());
+ }
+ for (int i = 0; i < typeArgs.length; i++)
+ {
+ h ^= Integer.rotateLeft(typeArgs[i].hashCode(), i);
+ }
+ return h;
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ if (owner != null)
+ {
+ sb.append(owner);
+ sb.append('.');
+ sb.append(rawType.getSimpleName());
+ }
+ else
+ {
+ sb.append(rawTypeName);
+ }
+ if (typeArgs.length > 0)
+ {
+ sb.append('<');
+ for (int i = 0; i < typeArgs.length; i++)
+ {
+ if (i > 0)
+ sb.append(", ");
+ if (typeArgs[i] instanceof Class)
+ {
+ sb.append(((Class)typeArgs[i]).getName());
+ }
+ else
+ {
+ sb.append(typeArgs[i]);
+ }
+ }
+ sb.append('>');
+ }
+ return sb.toString();
+ }
+}
+
+final class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType
+{
+ private Type componentType;
+
+ GenericArrayTypeImpl(Type componentType)
+ {
+ this.componentType = componentType;
+ }
+
+ Type resolve()
+ {
+ componentType = resolve(componentType);
+ return this;
+ }
+
+ public Type getGenericComponentType()
+ {
+ return componentType;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof GenericArrayTypeImpl)
+ {
+ GenericArrayTypeImpl other = (GenericArrayTypeImpl)obj;
+ return componentType.equals(other.componentType);
+ }
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return 0x4be37a7f ^ componentType.hashCode();
+ }
+
+ public String toString()
+ {
+ return componentType + "[]";
+ }
+}
+
+final class UnresolvedTypeVariable extends TypeImpl implements Type
+{
+ private GenericDeclaration decl;
+ private String name;
+
+ UnresolvedTypeVariable(GenericDeclaration decl, String name)
+ {
+ this.decl = decl;
+ this.name = name;
+ }
+
+ Type resolve()
+ {
+ GenericDeclaration d = decl;
+ while (d != null)
+ {
+ TypeVariable[] vars = d.getTypeParameters();
+ for (int a = 0; a < vars.length ; ++a)
+ {
+ if (vars[a].getName().equals(name))
+ {
+ return vars[a];
+ }
+ }
+ d = getParent(d);
+ }
+ throw new MalformedParameterizedTypeException();
+ }
+
+ private static GenericDeclaration getParent(GenericDeclaration d)
+ {
+ if (d instanceof Class)
+ {
+ Method m = ((Class)d).getEnclosingMethod();
+ if (m != null)
+ {
+ return m;
+ }
+ Constructor c = ((Class)d).getEnclosingConstructor();
+ if (c != null)
+ {
+ return c;
+ }
+ return ((Class)d).getEnclosingClass();
+ }
+ else if (d instanceof Method)
+ {
+ return ((Method)d).getDeclaringClass();
+ }
+ else if (d instanceof Constructor)
+ {
+ return ((Constructor)d).getDeclaringClass();
+ }
+ else
+ {
+ // TODO figure out what this represents
+ throw new Error();
+ }
+ }
+}
+
+final class WildcardTypeImpl extends TypeImpl implements WildcardType
+{
+ private Type lower;
+ private Type upper;
+
+ WildcardTypeImpl(Type lower, Type upper)
+ {
+ this.lower = lower;
+ this.upper = upper;
+ }
+
+ Type resolve()
+ {
+ upper = resolve(upper);
+ lower = resolve(lower);
+ return this;
+ }
+
+ public Type[] getUpperBounds()
+ {
+ if (upper == null)
+ {
+ return new Type[0];
+ }
+ return new Type[] { upper };
+ }
+
+ public Type[] getLowerBounds()
+ {
+ if (lower == null)
+ {
+ return new Type[0];
+ }
+ return new Type[] { lower };
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof WildcardTypeImpl)
+ {
+ WildcardTypeImpl other = (WildcardTypeImpl)obj;
+ return Arrays.deepEquals(getUpperBounds(), other.getUpperBounds())
+ && Arrays.deepEquals(getLowerBounds(), other.getLowerBounds());
+ }
+ return false;
+ }
+
+ public int hashCode()
+ {
+ int h = 0x75d074fd;
+ if (upper != null)
+ {
+ h ^= upper.hashCode();
+ }
+ if (lower != null)
+ {
+ h ^= lower.hashCode();
+ }
+ return h;
+ }
+
+ public String toString()
+ {
+ if (lower != null)
+ {
+ return "? super " + lower;
+ }
+ if (upper == java.lang.Object.class)
+ {
+ return "?";
+ }
+ return "? extends " + upper;
+ }
+}
+
+class GenericSignatureParser
+{
+ private ClassLoader loader;
+ private GenericDeclaration container;
+ private String signature;
+ private int pos;
+
+ GenericSignatureParser(GenericDeclaration container, ClassLoader loader,
+ String signature)
+ {
+ this.container = container;
+ this.loader = loader;
+ this.signature = signature;
+ }
+
+ TypeVariable[] readFormalTypeParameters()
+ {
+ consume('<');
+ ArrayList params = new ArrayList();
+ do
+ {
+ // TODO should we handle name clashes?
+ params.add(readFormalTypeParameter());
+ } while (peekChar() != '>');
+ consume('>');
+ TypeVariable[] list = new TypeVariable[params.size()];
+ params.toArray(list);
+ return list;
+ }
+
+ private TypeVariable readFormalTypeParameter()
+ {
+ String identifier = readIdentifier();
+ consume(':');
+ ArrayList bounds = new ArrayList();
+ if (peekChar() != ':')
+ {
+ bounds.add(readFieldTypeSignature());
+ }
+ while (peekChar() == ':')
+ {
+ consume(':');
+ bounds.add(readFieldTypeSignature());
+ }
+ Type[] b = new Type[bounds.size()];
+ bounds.toArray(b);
+ return new TypeVariableImpl(container, b, identifier);
+ }
+
+ Type readFieldTypeSignature()
+ {
+ switch (peekChar())
+ {
+ case 'L':
+ return readClassTypeSignature();
+ case '[':
+ return readArrayTypeSignature();
+ case 'T':
+ return readTypeVariableSignature();
+ default:
+ throw new GenericSignatureFormatError();
+ }
+ }
+
+ Type readClassTypeSignature()
+ {
+ consume('L');
+ String className = "";
+ for (;;)
+ {
+ String part = readIdentifier();
+ if (peekChar() != '/')
+ {
+ className += part;
+ break;
+ }
+ consume('/');
+ className += part + ".";
+ }
+ Type[] typeArguments = null;
+ if (peekChar() == '<')
+ {
+ typeArguments = readTypeArguments();
+ }
+ Type type = new ParameterizedTypeImpl(className, loader, null,
+ typeArguments);
+ while (peekChar() == '.')
+ {
+ consume('.');
+ className += "$" + readIdentifier();
+ typeArguments = null;
+ if (peekChar() == '<')
+ {
+ typeArguments = readTypeArguments();
+ }
+ type = new ParameterizedTypeImpl(className, loader, type,
+ typeArguments);
+ }
+ consume(';');
+ return type;
+ }
+
+ private Type[] readTypeArguments()
+ {
+ consume('<');
+ ArrayList list = new ArrayList();
+ do
+ {
+ list.add(readTypeArgument());
+ } while ((peekChar() != '>'));
+ consume('>');
+ Type[] arr = new Type[list.size()];
+ list.toArray(arr);
+ return arr;
+ }
+
+ private Type readTypeArgument()
+ {
+ char c = peekChar();
+ if (c == '+')
+ {
+ consume('+');
+ return new WildcardTypeImpl(null, readFieldTypeSignature());
+ }
+ else if (c == '-')
+ {
+ consume('-');
+ return new WildcardTypeImpl(readFieldTypeSignature(),
+ java.lang.Object.class);
+ }
+ else if (c == '*')
+ {
+ consume('*');
+ return new WildcardTypeImpl(null, java.lang.Object.class);
+ }
+ else
+ {
+ return readFieldTypeSignature();
+ }
+ }
+
+ Type readArrayTypeSignature()
+ {
+ consume('[');
+ switch (peekChar())
+ {
+ case 'L':
+ case '[':
+ case 'T':
+ return new GenericArrayTypeImpl(readFieldTypeSignature());
+ case 'Z':
+ consume('Z');
+ return boolean[].class;
+ case 'B':
+ consume('B');
+ return byte[].class;
+ case 'S':
+ consume('S');
+ return short[].class;
+ case 'C':
+ consume('C');
+ return char[].class;
+ case 'I':
+ consume('I');
+ return int[].class;
+ case 'F':
+ consume('F');
+ return float[].class;
+ case 'J':
+ consume('J');
+ return long[].class;
+ case 'D':
+ consume('D');
+ return double[].class;
+ default:
+ throw new GenericSignatureFormatError();
+ }
+ }
+
+ Type readTypeVariableSignature()
+ {
+ consume('T');
+ String identifier = readIdentifier();
+ consume(';');
+ return new UnresolvedTypeVariable(container, identifier);
+ }
+
+ private String readIdentifier()
+ {
+ int start = pos;
+ char c;
+ do
+ {
+ readChar();
+ c = peekChar();
+ } while (";:./<>-+*".indexOf(c) == -1);
+ return signature.substring(start, pos);
+ }
+
+ final char peekChar()
+ {
+ if (pos == signature.length())
+ return '\u0000';
+ else
+ return signature.charAt(pos);
+ }
+
+ final char readChar()
+ {
+ return signature.charAt(pos++);
+ }
+
+ final void consume(char c)
+ {
+ if (readChar() != c)
+ throw new GenericSignatureFormatError();
+ }
+
+ final void end()
+ {
+ if (pos != signature.length())
+ throw new GenericSignatureFormatError();
+ }
+}