use of org.eclipse.ceylon.compiler.java.runtime.metamodel.Metamodel in project ceylon by eclipse.
the class ClassOrInterfaceImpl method lookupMember.
@SuppressWarnings("unchecked")
private <T extends NestableDeclarationImpl, Container> MemberLookup<T, Container> lookupMember(@Ignore TypeDescriptor $reifiedT, @Ignore TypeDescriptor $reifiedContainer, org.eclipse.ceylon.model.typechecker.model.Type reifiedContainer, T value) {
ClassOrInterfaceImpl<Container> containerMetamodel;
org.eclipse.ceylon.model.typechecker.model.Type qualifyingType;
if ($reifiedContainer == TypeDescriptor.NothingType) {
// wildcard: everything goes
qualifyingType = this.producedType.getSupertype((TypeDeclaration) value.declaration.getContainer());
} else {
// get the declaration as seen from the container
Declaration memberInContainer = reifiedContainer.getDeclaration().getMember(value.getName(), null, false);
// cheaper this way than through reflection type checks
if ($reifiedT == ValueDeclarationImpl.$TypeDescriptor$) {
if (memberInContainer instanceof org.eclipse.ceylon.model.typechecker.model.Value == false)
return null;
} else if ($reifiedT == FunctionDeclarationImpl.$TypeDescriptor$) {
if (memberInContainer instanceof org.eclipse.ceylon.model.typechecker.model.Function == false)
return null;
} else if ($reifiedT == InterfaceDeclarationImpl.$TypeDescriptor$) {
if (memberInContainer instanceof org.eclipse.ceylon.model.typechecker.model.Interface == false)
return null;
} else if ($reifiedT == ClassDeclarationImpl.$TypeDescriptor$) {
if (memberInContainer instanceof org.eclipse.ceylon.model.typechecker.model.Class == false)
return null;
} else if ($reifiedT == ClassOrInterfaceDeclarationImpl.$TypeDescriptor$) {
if (memberInContainer instanceof org.eclipse.ceylon.model.typechecker.model.ClassOrInterface == false)
return null;
} else {
throw new AssertionError("Member type not supported: " + $reifiedT);
}
// get the right container type
qualifyingType = reifiedContainer.getSupertype((TypeDeclaration) memberInContainer.getContainer());
}
if (qualifyingType == null)
throw new AssertionError("Could not find qualifying type for reifiedContainer: " + $reifiedContainer);
// now get the right metamodel for the qualifying type
containerMetamodel = (ClassOrInterfaceImpl<Container>) Metamodel.getAppliedMetamodel(qualifyingType);
if (containerMetamodel == null)
throw new AssertionError("Could not find metamodel for qualifying type: " + qualifyingType);
// we already have the right member for the wildcard
if ($reifiedContainer != TypeDescriptor.NothingType) {
// now get the right member
value = ((ClassOrInterfaceDeclarationImpl) containerMetamodel.getDeclaration()).findDeclaredDeclaration($reifiedT, value.getName());
}
return new MemberLookup<T, Container>($reifiedT, $reifiedContainer, value, qualifyingType, containerMetamodel);
}
use of org.eclipse.ceylon.compiler.java.runtime.metamodel.Metamodel in project ceylon by eclipse.
the class ClassDeclarationImpl method init.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected void init() {
super.init();
// anonymous classes don't have parameter lists
if (!declaration.isAnonymous()) {
org.eclipse.ceylon.model.typechecker.model.Class classDeclaration = (org.eclipse.ceylon.model.typechecker.model.Class) declaration;
if (classDeclaration.isAbstraction()) {
List<Declaration> overloads = classDeclaration.getOverloads();
if (overloads.size() == 1) {
classDeclaration = (org.eclipse.ceylon.model.typechecker.model.Class) overloads.get(0);
}
// else{
// throw Metamodel.newModelError("Class has more than one overloaded constructor: "+classDeclaration.getNameAsString());
// }
}
ParameterList parameterList = classDeclaration.getParameterList();
if (parameterList != null) {
this.parameters = FunctionalUtil.getParameters(classDeclaration);
} else {
this.parameters = null;
}
} else {
this.parameters = null;
}
if (((Class) declaration).hasConstructors() || ((Class) declaration).hasEnumerated()) {
this.constructors = new LinkedList<ceylon.language.meta.declaration.Declaration>();
for (Declaration d : declaration.getMembers()) {
if (d instanceof Constructor) {
this.constructors.add(Metamodel.<ceylon.language.meta.declaration.Declaration>getOrCreateMetamodel(d));
}
}
} else {
this.constructors = Collections.emptyList();
}
}
use of org.eclipse.ceylon.compiler.java.runtime.metamodel.Metamodel 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.compiler.java.runtime.metamodel.Metamodel 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.compiler.java.runtime.metamodel.Metamodel in project ceylon by eclipse.
the class ValueConstructorImpl 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;
Method m = getJavaMethod(declaration);
// local classes have no getters
if (m == null)
return;
String getterName = m.getName();
try {
if (decl instanceof JavaBeanValue) {
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
boolean isJavaArray = MethodHandleUtil.isJavaArray(javaClass);
// 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
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);
}
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
} else if (ModelUtil.isEnumeratedConstructor(decl)) {
java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
if (ModelUtil.getConstructedClass(decl).isMember()) {
// the getter for member classes is on the enclosing class.
javaClass = javaClass.getEnclosingClass();
}
// 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
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);
}
// if(!ModelUtil.getConstructedClass(decl).isMember()) {
// we need to cast to Object because this is what comes out when calling it in $call
getter = getter.asType(MethodType.methodType(Object.class));
// }
} 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 (SecurityException | IllegalAccessException e) {
throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
}
}
Aggregations