1 package org.simantics.scl.compiler.constants.generic;
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Field;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Modifier;
7 import java.util.ArrayList;
8 import java.util.Collections;
11 import org.cojen.classfile.TypeDesc;
12 import org.simantics.scl.compiler.constants.generic.MethodRef.ConstructorRef;
13 import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
14 import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;
15 import org.simantics.scl.compiler.constants.generic.MethodRef.SetFieldRef;
16 import org.simantics.scl.compiler.constants.generic.MethodRef.SetStaticFieldRef;
17 import org.simantics.scl.compiler.constants.generic.MethodRef.StaticFieldRef;
18 import org.simantics.scl.compiler.constants.generic.MethodRef.StaticMethodRef;
19 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
21 import gnu.trove.map.hash.THashMap;
24 * This class is a reference to a Java class that contains a map of MethodRef for each
25 * method declared by the referenced class.
27 * Use {@link #getMethodRefs(String)} to get a list of overloaded methods for a given name.
29 public class ClassRef {
31 * A zero length array used as the value of argument lists of zero-arity methods.
33 public static final TypeDesc[] NO_PARAMS = new TypeDesc[0];
36 * A map from method names to lists of identically named methods.
38 private THashMap<String, ArrayList<MethodRef>> methods =
39 new THashMap<String, ArrayList<MethodRef>>();
42 * Get a list of methods with a given name.
43 * @param methodName A method name
44 * @return A list of {@link MethodRef} instances that share the name {@code methodName}.
46 public List<MethodRef> getMethodRefs(String methodName) {
47 List<MethodRef> refs = methods.get(methodName);
49 return Collections.emptyList();
54 * Construct a {@link ClassRef} with class loaders and a class name.
55 * @throws ClassNotFoundException if the class is not found.
57 public ClassRef(ClassLoader classLoader, String className) throws ClassNotFoundException {
58 analyzeClass(classLoader.loadClass(className), className);
62 * Construct a {@link ClassRef} for a Java class object.
64 public ClassRef(Class<?> clazz) {
65 analyzeClass(clazz, MethodBuilderBase.getClassName(clazz));
69 * Analyse the Java class and store {@link MethodRef} entries for all methods implemented by the class.
71 private void analyzeClass(Class<?> clazz, String className) {
72 boolean isInterface = clazz.isInterface();
73 for(Constructor<?> constructor : clazz.getConstructors()) {
74 addMethodRef("<init>", new ConstructorRef(
76 toTypeDescs(constructor.getParameterTypes())
79 for(Method method : clazz.getMethods()) {
80 if(method.isSynthetic())
82 String methodName = method.getName();
83 TypeDesc returnType = TypeDesc.forClass(method.getReturnType());
84 TypeDesc[] parameters = toTypeDescs(method.getParameterTypes());
86 int modifiers = method.getModifiers();
87 if(Modifier.isStatic(modifiers))
88 addMethodRef(methodName, new StaticMethodRef(
89 className, methodName,
94 addMethodRef(methodName, new ObjectMethodRef(
96 className, methodName,
101 for(Field field : clazz.getFields()) {
102 String fieldName = field.getName();
103 TypeDesc type = TypeDesc.forClass(field.getType());
105 int modifiers = field.getModifiers();
106 if(Modifier.isStatic(modifiers)) {
107 addMethodRef(fieldName, new StaticFieldRef(
112 addMethodRef("<set>" + fieldName, new SetStaticFieldRef(
119 addMethodRef(fieldName, new FieldRef(
124 addMethodRef("<set>" + fieldName, new SetFieldRef(
134 * Create an array of {@link TypeDesc} instances for an array of Class instances.
135 * For an empty array of classes the result will always be the empty array constant {@link #NO_PARAMS}.
137 private static TypeDesc[] toTypeDescs(Class<?>[] classes) {
138 if(classes.length == 0)
140 TypeDesc[] result = new TypeDesc[classes.length];
141 for(int i=0;i<result.length;++i)
142 result[i] = TypeDesc.forClass(classes[i]);
147 * Add a {@code MethodRef} to the {@link #methods} map.
149 private void addMethodRef(String name, MethodRef ref) {
150 ArrayList<MethodRef> l = methods.get(name);
152 l = new ArrayList<MethodRef>(2);
153 methods.put(name, l);