| package aQute.bnd.compatibility; |
| |
| import java.lang.reflect.*; |
| |
| public class RuntimeSignatureBuilder { |
| final Scope root; |
| |
| public RuntimeSignatureBuilder(Scope root) { |
| this.root = root; |
| } |
| |
| static public String identity(Class< ? > c) { |
| return Scope.classIdentity(c.getName()); |
| } |
| |
| static public String identity(Method m) { |
| return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m.getParameterTypes())); |
| } |
| |
| static public String identity(Constructor< ? > m) { |
| return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes())); |
| } |
| |
| static public String identity(Field m) { |
| return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null)); |
| } |
| |
| static public String getDescriptor(Class< ? > base, Class< ? >[] parameters) { |
| StringBuilder sb = new StringBuilder(); |
| if (parameters != null) { |
| sb.append("("); |
| for (Class< ? > parameter : parameters) { |
| sb.append(getDescriptor(parameter)); |
| } |
| sb.append(")"); |
| } |
| sb.append(getDescriptor(base)); |
| return sb.toString(); |
| } |
| |
| public Scope add(Class< ? > c) { |
| Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(), Kind.CLASS, identity(c), |
| c.getGenericSuperclass(), c.getGenericInterfaces(), null); |
| |
| for (Field f : c.getDeclaredFields()) { |
| add(local, // declaring scope |
| local, // enclosing |
| f.getModifiers(), // access modifiers |
| null, // fields have no type vars |
| Kind.FIELD, // field |
| identity(f), // the name of the field |
| f.getGenericType(), // the type of the field |
| null, // fields have no parameters |
| null // fields have no exceptions |
| ); |
| } |
| |
| for (Constructor< ? > constr : c.getConstructors()) { |
| add(local, // class scope |
| local, // enclosing |
| constr.getModifiers(), // access modifiers |
| constr.getTypeParameters(), // Type vars |
| Kind.CONSTRUCTOR, // constructor |
| identity(constr), // <init>(type*) |
| void.class, // Always void |
| constr.getGenericParameterTypes(), // parameters types |
| constr.getGenericExceptionTypes() // exception types |
| ); |
| } |
| |
| for (Method m : c.getDeclaredMethods()) { |
| if (m.getDeclaringClass() != Object.class) { |
| add(local, // class scope |
| local, // enclosing |
| m.getModifiers(), // access modifiers |
| m.getTypeParameters(), Kind.METHOD, // method |
| identity(m), // <name>(type*)return |
| m.getGenericReturnType(), // return type |
| m.getGenericParameterTypes(), // parameter types |
| m.getGenericExceptionTypes() // exception types |
| ); |
| } |
| } |
| |
| return local; |
| } |
| |
| private Scope getEnclosingScope(Class< ? > c) { |
| Method m = c.getEnclosingMethod(); |
| if (m != null) { |
| Scope s = getGlobalScope(m.getDeclaringClass()); |
| return s.getScope(identity(m)); |
| } |
| // TODO |
| // Constructor cnstr = c.getEnclosingConstructor(); |
| // if (m != null) { |
| // Scope s = getGlobalScope(cnstr.getDeclaringClass()); |
| // return s.getScope(identity(cnstr)); |
| // |
| // } |
| Class< ? > enclosingClass = c.getEnclosingClass(); |
| if (enclosingClass != null) { |
| return getGlobalScope(enclosingClass); |
| } |
| |
| return null; |
| } |
| |
| private Scope getGlobalScope(Class< ? > c) { |
| if (c == null) |
| return null; |
| String id = identity(c); |
| return root.getScope(id); |
| } |
| |
| private Scope add(Scope declaring, Scope enclosing, int modifiers, TypeVariable< ? >[] typeVariables, Kind kind, |
| String id, Type mainType, Type[] parameterTypes, Type exceptionTypes[]) { |
| |
| Scope scope = declaring.getScope(id); |
| assert scope.access == Access.UNKNOWN; |
| scope.setAccess(Access.modifier(modifiers)); |
| scope.setKind(kind); |
| scope.setGenericParameter(convert(typeVariables)); |
| scope.setBase(convert(scope, mainType)); |
| scope.setParameterTypes(convert(parameterTypes)); |
| scope.setExceptionTypes(convert(exceptionTypes)); |
| scope.setDeclaring(declaring); |
| scope.setEnclosing(enclosing); |
| return scope; |
| } |
| |
| private GenericType convert(Scope source, Type t) { |
| if (t instanceof ParameterizedType) { |
| // C<P..> |
| ParameterizedType pt = (ParameterizedType) t; |
| /* Scope reference = */root.getScope(identity((Class< ? >) pt.getRawType())); |
| Type args[] = pt.getActualTypeArguments(); |
| GenericType[] arguments = new GenericType[args.length]; |
| int n = 0; |
| for (Type arg : args) |
| arguments[n++] = convert(source, arg); |
| // return new GenericType(reference,null,arguments); |
| |
| } else if (t instanceof TypeVariable) { |
| // TypeVariable tv = (TypeVariable) t; |
| // return new GenericType(source,tv.getName(), null); |
| } else if (t instanceof WildcardType) { |
| // WildcardType wc = (WildcardType) t; |
| // wc. |
| } else if (t instanceof GenericArrayType) { |
| |
| } |
| if (t instanceof Class< ? >) { |
| // raw = ((Class<?>) t).getName() + ";"; |
| } else |
| throw new IllegalArgumentException(t.toString()); |
| |
| return null; |
| } |
| |
| private GenericParameter[] convert(TypeVariable< ? > vars[]) { |
| if (vars == null) |
| return null; |
| |
| GenericParameter out[] = new GenericParameter[vars.length]; |
| for (int i = 0; i < vars.length; i++) { |
| GenericType gss[] = convert(vars[i].getBounds()); |
| out[i] = new GenericParameter(vars[i].getName(), gss); |
| } |
| return out; |
| } |
| |
| private GenericType[] convert(Type[] parameterTypes) { |
| if (parameterTypes == null || parameterTypes.length == 0) |
| return GenericType.EMPTY; |
| |
| GenericType tss[] = new GenericType[parameterTypes.length]; |
| for (int i = 0; i < parameterTypes.length; i++) { |
| // tss[i] = new GenericType(parameterTypes[i]); |
| } |
| return tss; |
| } |
| |
| private static String getDescriptor(Class< ? > c) { |
| StringBuilder sb = new StringBuilder(); |
| if (c.isPrimitive()) { |
| if (c == boolean.class) |
| sb.append("Z"); |
| else if (c == byte.class) |
| sb.append("Z"); |
| else if (c == char.class) |
| sb.append("C"); |
| else if (c == short.class) |
| sb.append("S"); |
| else if (c == int.class) |
| sb.append("I"); |
| else if (c == long.class) |
| sb.append("J"); |
| else if (c == float.class) |
| sb.append("F"); |
| else if (c == double.class) |
| sb.append("D"); |
| else if (c == void.class) |
| sb.append("V"); |
| else |
| throw new IllegalArgumentException("unknown primitive type: " + c); |
| } else if (c.isArray()) { |
| sb.append("["); |
| sb.append(getDescriptor(c)); |
| } else { |
| sb.append("L"); |
| sb.append(c.getName().replace('.', '/')); |
| sb.append(";"); |
| } |
| return sb.toString(); |
| } |
| |
| } |