blob: 9e6b09015eb8ba47eb1b678aa5de5373027da295 [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.bnd.compatibility;
2
3import java.lang.reflect.*;
4
5public class RuntimeSignatureBuilder {
6 final Scope root;
7
8 public RuntimeSignatureBuilder(Scope root) {
9 this.root = root;
10 }
11
Stuart McCulloch2286f232012-06-15 13:27:53 +000012 static public String identity(Class< ? > c) {
Stuart McCullochbb014372012-06-07 21:57:32 +000013 return Scope.classIdentity(c.getName());
14 }
15
16 static public String identity(Method m) {
Stuart McCulloch2286f232012-06-15 13:27:53 +000017 return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m.getParameterTypes()));
Stuart McCullochbb014372012-06-07 21:57:32 +000018 }
19
Stuart McCulloch2286f232012-06-15 13:27:53 +000020 static public String identity(Constructor< ? > m) {
Stuart McCullochbb014372012-06-07 21:57:32 +000021 return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes()));
22 }
23
24 static public String identity(Field m) {
25 return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null));
26 }
27
Stuart McCulloch2286f232012-06-15 13:27:53 +000028 static public String getDescriptor(Class< ? > base, Class< ? >[] parameters) {
Stuart McCullochbb014372012-06-07 21:57:32 +000029 StringBuilder sb = new StringBuilder();
30 if (parameters != null) {
31 sb.append("(");
Stuart McCulloch2286f232012-06-15 13:27:53 +000032 for (Class< ? > parameter : parameters) {
Stuart McCullochbb014372012-06-07 21:57:32 +000033 sb.append(getDescriptor(parameter));
34 }
35 sb.append(")");
36 }
37 sb.append(getDescriptor(base));
38 return sb.toString();
39 }
40
Stuart McCulloch2286f232012-06-15 13:27:53 +000041 public Scope add(Class< ? > c) {
42 Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(), Kind.CLASS, identity(c),
43 c.getGenericSuperclass(), c.getGenericInterfaces(), null);
Stuart McCullochbb014372012-06-07 21:57:32 +000044
45 for (Field f : c.getDeclaredFields()) {
46 add(local, // declaring scope
47 local, // enclosing
48 f.getModifiers(), // access modifiers
49 null, // fields have no type vars
50 Kind.FIELD, // field
51 identity(f), // the name of the field
52 f.getGenericType(), // the type of the field
53 null, // fields have no parameters
54 null // fields have no exceptions
55 );
56 }
57
Stuart McCulloch2286f232012-06-15 13:27:53 +000058 for (Constructor< ? > constr : c.getConstructors()) {
Stuart McCullochbb014372012-06-07 21:57:32 +000059 add(local, // class scope
60 local, // enclosing
61 constr.getModifiers(), // access modifiers
62 constr.getTypeParameters(), // Type vars
63 Kind.CONSTRUCTOR, // constructor
64 identity(constr), // <init>(type*)
65 void.class, // Always void
66 constr.getGenericParameterTypes(), // parameters types
67 constr.getGenericExceptionTypes() // exception types
68 );
69 }
70
71 for (Method m : c.getDeclaredMethods()) {
72 if (m.getDeclaringClass() != Object.class) {
73 add(local, // class scope
74 local, // enclosing
75 m.getModifiers(), // access modifiers
76 m.getTypeParameters(), Kind.METHOD, // method
77 identity(m), // <name>(type*)return
78 m.getGenericReturnType(), // return type
79 m.getGenericParameterTypes(), // parameter types
80 m.getGenericExceptionTypes() // exception types
81 );
82 }
83 }
84
85 return local;
86 }
87
Stuart McCulloch2286f232012-06-15 13:27:53 +000088 private Scope getEnclosingScope(Class< ? > c) {
Stuart McCullochbb014372012-06-07 21:57:32 +000089 Method m = c.getEnclosingMethod();
90 if (m != null) {
91 Scope s = getGlobalScope(m.getDeclaringClass());
92 return s.getScope(identity(m));
93 }
Stuart McCulloch2286f232012-06-15 13:27:53 +000094 // TODO
95 // Constructor cnstr = c.getEnclosingConstructor();
96 // if (m != null) {
97 // Scope s = getGlobalScope(cnstr.getDeclaringClass());
98 // return s.getScope(identity(cnstr));
99 //
100 // }
101 Class< ? > enclosingClass = c.getEnclosingClass();
Stuart McCullochbb014372012-06-07 21:57:32 +0000102 if (enclosingClass != null) {
103 return getGlobalScope(enclosingClass);
104 }
105
106 return null;
107 }
108
Stuart McCulloch2286f232012-06-15 13:27:53 +0000109 private Scope getGlobalScope(Class< ? > c) {
Stuart McCullochbb014372012-06-07 21:57:32 +0000110 if (c == null)
111 return null;
112 String id = identity(c);
113 return root.getScope(id);
114 }
115
Stuart McCulloch2286f232012-06-15 13:27:53 +0000116 private Scope add(Scope declaring, Scope enclosing, int modifiers, TypeVariable< ? >[] typeVariables, Kind kind,
117 String id, Type mainType, Type[] parameterTypes, Type exceptionTypes[]) {
Stuart McCullochbb014372012-06-07 21:57:32 +0000118
119 Scope scope = declaring.getScope(id);
120 assert scope.access == Access.UNKNOWN;
121 scope.setAccess(Access.modifier(modifiers));
122 scope.setKind(kind);
123 scope.setGenericParameter(convert(typeVariables));
Stuart McCulloch2286f232012-06-15 13:27:53 +0000124 scope.setBase(convert(scope, mainType));
Stuart McCullochbb014372012-06-07 21:57:32 +0000125 scope.setParameterTypes(convert(parameterTypes));
126 scope.setExceptionTypes(convert(exceptionTypes));
127 scope.setDeclaring(declaring);
128 scope.setEnclosing(enclosing);
129 return scope;
130 }
131
132 private GenericType convert(Scope source, Type t) {
133 if (t instanceof ParameterizedType) {
134 // C<P..>
135 ParameterizedType pt = (ParameterizedType) t;
Stuart McCulloch2286f232012-06-15 13:27:53 +0000136 /* Scope reference = */root.getScope(identity((Class< ? >) pt.getRawType()));
Stuart McCullochbb014372012-06-07 21:57:32 +0000137 Type args[] = pt.getActualTypeArguments();
138 GenericType[] arguments = new GenericType[args.length];
139 int n = 0;
140 for (Type arg : args)
Stuart McCulloch2286f232012-06-15 13:27:53 +0000141 arguments[n++] = convert(source, arg);
142 // return new GenericType(reference,null,arguments);
143
Stuart McCullochbb014372012-06-07 21:57:32 +0000144 } else if (t instanceof TypeVariable) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000145 // TypeVariable tv = (TypeVariable) t;
146 // return new GenericType(source,tv.getName(), null);
Stuart McCullochbb014372012-06-07 21:57:32 +0000147 } else if (t instanceof WildcardType) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000148 // WildcardType wc = (WildcardType) t;
149 // wc.
Stuart McCullochbb014372012-06-07 21:57:32 +0000150 } else if (t instanceof GenericArrayType) {
151
152 }
Stuart McCulloch2286f232012-06-15 13:27:53 +0000153 if (t instanceof Class< ? >) {
154 // raw = ((Class<?>) t).getName() + ";";
Stuart McCullochbb014372012-06-07 21:57:32 +0000155 } else
156 throw new IllegalArgumentException(t.toString());
157
158 return null;
159 }
160
Stuart McCulloch2286f232012-06-15 13:27:53 +0000161 private GenericParameter[] convert(TypeVariable< ? > vars[]) {
Stuart McCullochbb014372012-06-07 21:57:32 +0000162 if (vars == null)
163 return null;
164
165 GenericParameter out[] = new GenericParameter[vars.length];
166 for (int i = 0; i < vars.length; i++) {
167 GenericType gss[] = convert(vars[i].getBounds());
168 out[i] = new GenericParameter(vars[i].getName(), gss);
169 }
170 return out;
171 }
172
173 private GenericType[] convert(Type[] parameterTypes) {
174 if (parameterTypes == null || parameterTypes.length == 0)
175 return GenericType.EMPTY;
176
177 GenericType tss[] = new GenericType[parameterTypes.length];
178 for (int i = 0; i < parameterTypes.length; i++) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000179 // tss[i] = new GenericType(parameterTypes[i]);
Stuart McCullochbb014372012-06-07 21:57:32 +0000180 }
181 return tss;
182 }
183
Stuart McCulloch2286f232012-06-15 13:27:53 +0000184 private static String getDescriptor(Class< ? > c) {
Stuart McCullochbb014372012-06-07 21:57:32 +0000185 StringBuilder sb = new StringBuilder();
186 if (c.isPrimitive()) {
187 if (c == boolean.class)
188 sb.append("Z");
189 else if (c == byte.class)
190 sb.append("Z");
191 else if (c == char.class)
192 sb.append("C");
193 else if (c == short.class)
194 sb.append("S");
195 else if (c == int.class)
196 sb.append("I");
197 else if (c == long.class)
198 sb.append("J");
199 else if (c == float.class)
200 sb.append("F");
201 else if (c == double.class)
202 sb.append("D");
203 else if (c == void.class)
204 sb.append("V");
205 else
206 throw new IllegalArgumentException("unknown primitive type: " + c);
207 } else if (c.isArray()) {
208 sb.append("[");
209 sb.append(getDescriptor(c));
210 } else {
211 sb.append("L");
212 sb.append(c.getName().replace('.', '/'));
213 sb.append(";");
214 }
215 return sb.toString();
216 }
217
218}