blob: 9e6b09015eb8ba47eb1b678aa5de5373027da295 [file] [log] [blame]
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();
}
}