use of org.eclipse.ceylon.model.loader.impl.reflect.mirror.ReflectionClass in project ceylon by eclipse.
the class Metamodel method getTypeDescriptorForProducedType.
public static TypeDescriptor getTypeDescriptorForProducedType(org.eclipse.ceylon.model.typechecker.model.Type type) {
TypeDeclaration declaration = type.getDeclaration();
if (type.isNothing()) {
return TypeDescriptor.NothingType;
}
if (type.isUnion()) {
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getCaseTypes());
return TypeDescriptor.union(tdArgs);
}
if (type.isIntersection()) {
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getSatisfiedTypes());
return TypeDescriptor.intersection(tdArgs);
}
if (declaration instanceof LazyClass) {
ReflectionClass classMirror = (ReflectionClass) ((LazyClass) declaration).classMirror;
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getTypeArgumentList());
TypeDescriptor ret = TypeDescriptor.klass(classMirror.klass, tdArgs);
if (type.getQualifyingType() != null)
return TypeDescriptor.member(getTypeDescriptorForProducedType(type.getQualifyingType()), ret);
return ret;
}
if (declaration instanceof LazyInterface) {
ReflectionClass classMirror = (ReflectionClass) ((LazyInterface) declaration).classMirror;
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getTypeArgumentList());
TypeDescriptor ret = TypeDescriptor.klass(classMirror.klass, tdArgs);
if (type.getQualifyingType() != null)
return TypeDescriptor.member(getTypeDescriptorForProducedType(type.getQualifyingType()), ret);
return ret;
}
if (declaration instanceof FunctionOrValueInterface) {
TypedDeclaration underlyingDeclaration = ((FunctionOrValueInterface) declaration).getUnderlyingDeclaration();
TypeDescriptor[] tdArgs = getTypeDescriptorsForProducedTypes(type.getTypeArgumentList());
TypeDescriptor ret;
if (underlyingDeclaration.isToplevel()) {
ReflectionClass classMirror;
// type arguments
if (underlyingDeclaration instanceof Setter)
underlyingDeclaration = ((Setter) underlyingDeclaration).getGetter();
if (underlyingDeclaration instanceof LazyValue)
classMirror = (ReflectionClass) ((LazyValue) underlyingDeclaration).classMirror;
else if (underlyingDeclaration instanceof LazyFunction)
classMirror = (ReflectionClass) ((LazyFunction) underlyingDeclaration).classMirror;
else
throw Metamodel.newModelError("Unsupported underlying declaration type: " + underlyingDeclaration);
ret = TypeDescriptor.functionOrValue(classMirror.klass, tdArgs);
} else
ret = TypeDescriptor.functionOrValue(underlyingDeclaration.getPrefixedName(), tdArgs);
if (type.getQualifyingType() != null)
return TypeDescriptor.member(getTypeDescriptorForProducedType(type.getQualifyingType()), ret);
return ret;
}
if (declaration instanceof UnknownType) {
((UnknownType) declaration).reportErrors();
}
throw Metamodel.newModelError("Unsupported declaration type: " + (declaration == null ? "null" : declaration.getClass()));
}
use of org.eclipse.ceylon.model.loader.impl.reflect.mirror.ReflectionClass in project ceylon by eclipse.
the class ValueConstructorImpl method getJavaMethod.
// /////////////////////////////////////////
/**
* Gets the getter {@code java.lang.reflect.Method} for the
* given value constructor.
*/
@Ignore
public static Method getJavaMethod(ValueConstructorDeclarationImpl declaration) {
org.eclipse.ceylon.model.typechecker.model.Value decl = (org.eclipse.ceylon.model.typechecker.model.Value) declaration.declaration;
String getterName = "";
try {
if (decl instanceof JavaBeanValue) {
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
getterName = ((JavaBeanValue) decl).getGetterName();
java.lang.Class<?>[] params = NO_PARAMS;
boolean isJavaArray = MethodHandleUtil.isJavaArray(javaClass);
if (isJavaArray)
params = MethodHandleUtil.getJavaArrayGetArrayParameterTypes(javaClass, getterName);
// if it is shared we may want to get an inherited getter, but if it's private we need the declared method to return it
Method m = decl.isShared() ? javaClass.getMethod(getterName, params) : javaClass.getDeclaredMethod(getterName, params);
return m;
} else if (decl instanceof LazyValue) {
LazyValue lazyDecl = (LazyValue) decl;
java.lang.Class<?> javaClass = ((ReflectionClass) lazyDecl.classMirror).klass;
// FIXME: we should really save the getter name in the LazyDecl
getterName = NamingBase.getGetterName(lazyDecl);
// toplevels don't have inheritance
Method m = javaClass.getDeclaredMethod(getterName);
return m;
} else if (ModelUtil.isEnumeratedConstructor(decl)) {
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
Class constructedClass = ModelUtil.getConstructedClass(decl);
if (constructedClass.isMember()) {
// the getter for member classes is on the enclosing class.
javaClass = javaClass.getEnclosingClass();
} else if (ModelUtil.isLocalNotInitializer(constructedClass))
// local class has no way to get the value
return null;
getterName = NamingBase.getGetterName(decl);
java.lang.Class<?>[] params = NO_PARAMS;
// if it is shared we may want to get an inherited getter, but if it's private we need the declared method to return it
Method m = javaClass.getDeclaredMethod(getterName, params);
return m;
} else {
throw new StorageException("Attribute " + decl.getName() + " is neither captured nor shared so it has no physical storage allocated and cannot be read by the metamodel");
}
} catch (NoSuchMethodException | SecurityException e) {
throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
}
}
use of org.eclipse.ceylon.model.loader.impl.reflect.mirror.ReflectionClass in project ceylon by eclipse.
the class ValueImpl method initField.
private void initField(Object instance, Type valueType) {
org.eclipse.ceylon.model.typechecker.model.Value decl = (org.eclipse.ceylon.model.typechecker.model.Value) declaration.declaration;
String name = decl.getName();
if (decl instanceof JavaBeanValue) {
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
if (javaClass == ceylon.language.Object.class || javaClass == ceylon.language.Basic.class || javaClass == ceylon.language.Identifiable.class) {
if ("string".equals(name) || "hash".equals(name)) {
// look it up on j.l.Object, getterName should work
javaClass = java.lang.Object.class;
} else {
throw Metamodel.newModelError("Object/Basic/Identifiable member not supported: " + name);
}
} else if (javaClass == ceylon.language.Throwable.class) {
if ("cause".equals(name) || "message".equals(name) || "suppressed".equals(name)) {
javaClass = instance.getClass();
isSuppressed = "suppressed".equals(name);
}
}
String getterName = ((JavaBeanValue) decl).getGetterName();
try {
Class<?>[] params;
if (!declaration.getStatic()) {
params = NO_PARAMS;
} else {
int numCapturedTypeParams = ((ClassOrInterface) declaration.declaration.getContainer()).getTypeParameters().size();
params = new Class[numCapturedTypeParams];
Arrays.fill(params, TypeDescriptor.class);
}
boolean isJavaArray = MethodHandleUtil.isJavaArray(javaClass);
if (isJavaArray)
params = MethodHandleUtil.getJavaArrayGetArrayParameterTypes(javaClass, getterName);
// if it is shared we may want to get an inherited getter, but if it's private we need the declared method to return it
Method m = decl.isShared() ? javaClass.getMethod(getterName, params) : javaClass.getDeclaredMethod(getterName, params);
m.setAccessible(true);
getter = MethodHandles.lookup().unreflect(m);
java.lang.Class<?> getterType = m.getReturnType();
getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
if (instance != null && // XXXArray.getArray is static but requires an instance as first param
(isJavaArray || !Modifier.isStatic(m.getModifiers()))) {
getter = getter.bindTo(instance);
}
if (declaration.getStatic()) {
getter = getter.asType(MethodType.methodType(Object.class, params));
TypeDescriptor[] typeArguments = ((TypeDescriptor.Class) ((ClassOrInterfaceImpl<?>) container).$reifiedType).getTypeArguments();
getter = getter.asSpreader(TypeDescriptor[].class, typeArguments.length);
getter = getter.bindTo(typeArguments);
} else {
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
}
initSetter(decl, javaClass, getterType, instance, valueType);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
}
} else if (decl instanceof LazyValue) {
LazyValue lazyDecl = (LazyValue) decl;
java.lang.Class<?> javaClass = ((ReflectionClass) lazyDecl.classMirror).klass;
// FIXME: we should really save the getter name in the LazyDecl
String getterName = NamingBase.getGetterName(lazyDecl);
try {
// toplevels don't have inheritance
Method m = javaClass.getDeclaredMethod(getterName);
m.setAccessible(true);
getter = MethodHandles.lookup().unreflect(m);
java.lang.Class<?> getterType = m.getReturnType();
getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
initSetter(decl, javaClass, getterType, null, valueType);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
}
} else if (decl instanceof FieldValue) {
FieldValue fieldDecl = (FieldValue) decl;
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
String fieldName = fieldDecl.getRealName();
if (MethodHandleUtil.isJavaArray(javaClass)) {
try {
Method method = Array.class.getDeclaredMethod("getLength", Object.class);
getter = MethodHandles.lookup().unreflect(method);
java.lang.Class<?> getterType = method.getReturnType();
getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
// this one is static but requires an instance a first param
if (instance != null)
getter = getter.bindTo(instance);
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw Metamodel.newModelError("Failed to find Array.getLength method for: " + decl, e);
}
} else {
try {
// fields are not inherited
Field f = javaClass.getDeclaredField(fieldName);
f.setAccessible(true);
getter = MethodHandles.lookup().unreflectGetter(f);
java.lang.Class<?> getterType = f.getType();
getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
if (instance != null && !Modifier.isStatic(f.getModifiers()))
getter = getter.bindTo(instance);
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
initSetter(decl, javaClass, getterType, instance, valueType);
} catch (NoSuchFieldException | SecurityException | IllegalAccessException e) {
throw Metamodel.newModelError("Failed to find field " + fieldName + " for: " + decl, e);
}
}
} else if (ModelUtil.isEnumeratedConstructor(decl)) {
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
String getterName = NamingBase.getGetterName(decl);
try {
Class<?>[] params = NO_PARAMS;
// if it is shared we may want to get an inherited getter, but if it's private we need the declared method to return it
Method m = decl.isShared() ? javaClass.getMethod(getterName, params) : javaClass.getDeclaredMethod(getterName, params);
m.setAccessible(true);
getter = MethodHandles.lookup().unreflect(m);
java.lang.Class<?> getterType = m.getReturnType();
getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
if (instance != null && // XXXArray.getArray is static but requires an instance as first param
(!Modifier.isStatic(m.getModifiers()))) {
getter = getter.bindTo(instance);
}
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
initSetter(decl, javaClass, getterType, instance, valueType);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
}
} else
throw new StorageException("Attribute " + name + " is neither captured nor shared so it has no physical storage allocated and cannot be read by the metamodel");
}
use of org.eclipse.ceylon.model.loader.impl.reflect.mirror.ReflectionClass in project ceylon by eclipse.
the class RuntimeModelLoader method findModuleForClassMirror.
@Override
public Module findModuleForClassMirror(ClassMirror classMirror) {
Class<?> klass = ((ReflectionClass) classMirror).klass;
Module ret = findModuleForClass(klass);
if (ret == null)
throw new ModelResolutionException("Could not find module for class " + klass);
return ret;
}
use of org.eclipse.ceylon.model.loader.impl.reflect.mirror.ReflectionClass in project ceylon by eclipse.
the class ReflectionModelLoader method lookupNewClassMirror.
@Override
public ClassMirror lookupNewClassMirror(Module module, String name) {
Class<?> klass = null;
// first try with the same name, for Java interop with classes with lowercase name
klass = loadClass(module, JVMModuleUtil.quoteJavaKeywords(name));
if (klass == null && lastPartHasLowerInitial(name) && !name.endsWith("_")) {
klass = loadClass(module, JVMModuleUtil.quoteJavaKeywords(name + "_"));
}
return klass != null ? new ReflectionClass(klass) : null;
}
Aggregations