The Ceylon metamodel open type and declaration package.
As described in the ceylon.language.meta documentation, this package contains all the types that represent Ceylon declarations and open types.
The following code will list all the classes in the ceylon.language
package and print their
extended type:
for(decl in `package ceylon.language`.members<ClassDeclaration>()){ if(exists extendedType = decl.extendedType){ print("Class ``decl.name`` extends: ``extendedType``"); }else{ print("Class ``decl.name`` does not extend anything"); } }
The following code will iterate all the class declarations in the ceylon.language
package that
are not abstract, anonymous or annotations, and that have no type parameters nor initialiser
parameters. For each matching class, we will apply it to get a class model which we can then
use to instantiate the class and display its instance:
for(decl in `package ceylon.language`.members<ClassDeclaration>()){ if(!decl.abstract && !decl.anonymous && !decl.annotation && decl.parameterDeclarations.empty && decl.typeParameterDeclarations.empty){ Class<Object,[]> classModel = decl.classApply<Object,[]>(); Object instance = classModel(); print("Instance of ``decl.name`` is: ``instance``"); } }
Values | |
contravariant | Source Code shared contravariant contravariant Contravariant means that supertypes of the given type may be accepted. |
covariant | Source Code shared covariant covariant Covariant means that subtypes of the given type may be returned. |
invariant | Source Code shared invariant invariant Invariant means that neither subtype nor supertype can be accepted, the type has to be exactly that which is declared. |
nothingType | Source Code shared nothingType nothingType The singleton open type for Nothing. |
Interfaces | |
AliasDeclaration | Source Code shared AliasDeclaration Type alias declaration. While type aliases are erased (substituted for what they alias is a better term) from every declaration that uses them during compile-time, the declaration of the type alias is still visible at run-time. |
AnnotatedDeclaration | Source Code shared AnnotatedDeclaration Declaration which can be annotated, such as: You can query annotations that are placed on a given annotated declaration with: |
ClassDeclaration | Source Code shared ClassDeclaration Class declaration. Usage sample for toplevel classesBecause some classes have type parameters, getting a model requires applying type arguments to the class declaration with classApply in order to be able to instantiate that class. For example, here is how you would obtain a class model that you can instantiate from a toplevel class declaration: class Foo<T>(){ string => "Hello, our T is: ``typeLiteral<T>()``"; } void test(){ // We need to apply the Integer closed type to the Foo declaration in order to get the Foo<Integer> closed type Class<Foo<Integer>,[]> classModel = `class Foo`.classApply<Foo<Integer>,[]>(`Integer`); // This will print: Hello, our T is: ceylon.language::Integer print(classModel()); } Usage sample for member classesFor member classes it is a bit longer, because member classes need to be applied not only their type arguments but also the containing type, so you should use memberClassApply and start by giving the containing closed type: class Outer(){ shared class Inner(){ string => "Hello"; } } void test(){ // apply the containing closed type `Outer` to the member class declaration `Outer.Inner` MemberClass<Outer,Outer.Inner,[]> memberClassModel = `class Outer.Inner`.memberClassApply<Outer,Outer.Inner,[]>(`Outer`); // We now have a MemberClass, which needs to be applied to a containing instance in order to become an // invokable class model: Class<Outer.Inner,[]> boundMemberClassModel = memberClassModel(Outer()); // This will print: Hello print(boundMemberClassModel()); } |
ClassOrInterfaceDeclaration | Source Code shared ClassOrInterfaceDeclaration A class or interface declaration. Usage sample for toplevel classesBecause some classes have type parameters, getting a model requires applying type arguments to the class declaration with apply in order to be able to instantiate that class. For example, here is how you would obtain a class or interface model that you can instantiate from a toplevel class declaration: class Foo<T>() { string => "Hello, our T is: ``typeLiteral<T>()``"; } void test(){ // We need to apply the Integer closed type to the Foo declaration in order to get the Foo<Integer> closed type ClassOrInterface<Foo<Integer>> classOrInterfaceModel = `class Foo`.apply<Foo<Integer>>(`Integer`); assert(is Class<Foo<Integer>,[]> classOrInterfaceModel); // This will print: Hello, our T is: ceylon.language::Integer print(classOrInterfaceModel()); } Note that there are more specialised versions of apply in ClassDeclaration.classApply and InterfaceDeclaration.interfaceApply. Usage sample for member classesFor member classes or interfaces it is a bit longer, because member types need to be applied not only their type arguments but also the containing type, so you should use memberApply and start by giving the containing closed type: class Outer(){ shared class Inner(){ string => "Hello"; } } void test(){ // apply the containing closed type `Outer` to the member class declaration `Outer.Inner` value memberClassModel = `class Outer.Inner`.memberApply<Outer,Outer.Inner>(`Outer`); assert(is MemberClass<Outer,Outer.Inner,[]> memberClassModel); // We now have a MemberClass, which needs to be applied to a containing instance in order to become an // invokable class model: Class<Outer.Inner,[]> boundMemberClassModel = memberClassModel(Outer()); // This will print: Hello print(boundMemberClassModel()); } Note that there are more specialised versions of memberApply in ClassDeclaration.memberClassApply and InterfaceDeclaration.memberInterfaceApply. |
Declaration | Source Code shared Declaration A declaration. There are only two types of declarations:
|
FunctionDeclaration | Source Code shared FunctionDeclaration A function declaration. Usage sample for toplevel functionBecause some functions have type parameters, getting a model requires applying type arguments to the function declaration with apply in order to be able to invoke that function. For example, here is how you would obtain a function model that you can invoke from a toplevel function declaration: String foo<T>(){ return "Hello, our T is: ``typeLiteral<T>()``"; } void test(){ // We need to apply the Integer closed type to the foo declaration in order to get the foo<Integer> function model Function<String,[]> functionModel = `function foo`.apply<String,[]>(`Integer`); // This will print: Hello, our T is: ceylon.language::Integer print(functionModel()); } Usage sample for methodsFor methods it is a bit longer, because methods need to be applied not only their type arguments but also the containing type, so you should use memberApply and start by giving the containing closed type: class Outer(){ shared String hello() => "Hello"; } void test(){ // apply the containing closed type `Outer` to the method declaration `Outer.hello` Method<Outer,String,[]> methodModel = `function Outer.hello`.memberApply<Outer,String,[]>(`Outer`); // We now have a Method, which needs to be applied to a containing instance in order to become an // invokable function: Function<String,[]> boundMethodModel = methodModel(Outer()); // This will print: Hello print(boundMethodModel()); } |
FunctionOrValueDeclaration | Source Code shared FunctionOrValueDeclaration A function or value declaration. |
FunctionalDeclaration | Source Code shared FunctionalDeclaration Declaration which can be invoked, and may have parameters. Classes and functions are functional declarations. Note that multiple-parameter lists are not reified at runtime, so if you have a function declaration like this: Integer add(Integer a)(Integer b) => a + b; It will only have a single parameter list at runtime (the first), and its return
type will be |
GenericDeclaration | Source Code shared GenericDeclaration A declaration that can have type parameters. |
Import | Source Code shared Import Model of an |
InterfaceDeclaration | Source Code shared InterfaceDeclaration An interface declaration. Usage sample for toplevel interfacesBecause some interfaces have type parameters, getting a model requires applying type arguments to the interface declaration with interfaceApply in order to be able to get a closed type. For example, here is how you would obtain an interface model from a toplevel interface declaration: interface Foo<T> satisfies List<T> { } void test(){ // We need to apply the Integer closed type to the Foo declaration in order to get the Foo<Integer> closed type Interface<Foo<Integer>> interfaceModel = `interface Foo`.interfaceApply<Foo<Integer>>(`Integer`); // This will print: ceylon.language::List<ceylon.language::Integer> for(satisfiedType in interfaceModel.satisfiedTypes){ print(satisfiedType); } } Usage sample for member interfacesFor member interfaces it is a bit longer, because member interfaces need to be applied not only their type arguments but also the containing type, so you should use memberInterfaceApply and start by giving the containing closed type: class Outer(){ shared interface Inner<T> satisfies List<T> { } } void test(){ // apply the containing closed type `Outer` to the member class declaration `Outer.Inner` MemberInterface<Outer,Outer.Inner<Integer>> memberInterfaceModel = `interface Outer.Inner`.memberInterfaceApply<Outer,Outer.Inner<Integer>>(`Outer`, `Integer`); // This will print: ceylon.language::List<ceylon.language::Integer> for(satisfiedType in memberInterfaceModel.satisfiedTypes){ print(satisfiedType); } } |
Module | Source Code shared Module A |
NestableDeclaration | Source Code shared NestableDeclaration A declaration which can be contained in a Package or in another NestableDeclaration. Functions, values, classes, interfaes and aliases are such declarations. |
OpenClassOrInterfaceType | Source Code shared OpenClassOrInterfaceType An open class or interface, with open type arguments. For example, |
OpenClassType | Source Code shared OpenClassType An open class type. |
OpenInterfaceType | Source Code shared OpenInterfaceType An open interface type. |
OpenIntersection | Source Code shared OpenIntersection An open intersection type. |
OpenType | Source Code shared OpenType An open type. An open type is a type which may contain unbound type variables, such as |
OpenTypeVariable | Source Code shared OpenTypeVariable An open type variable. |
OpenUnion | Source Code shared OpenUnion An open union type. |
Package | Source Code shared Package Model of a |
SetterDeclaration | Source Code shared SetterDeclaration A setter declaration for a variable |
TypeParameter | Source Code shared TypeParameter A type parameter declaration. |
TypedDeclaration | Source Code shared TypedDeclaration Declaration which has an open type. |
ValueDeclaration | Source Code shared ValueDeclaration A value declaration. Usage sample for toplevel valueGetting a model requires applying type arguments to the value declaration with apply in order to be able to read that value. For example, here is how you would obtain a value model that you can read from a toplevel attribute declaration: String foo = "Hello"; void test(){ // We need to apply the the foo declaration in order to get the foo value model Value<String> valueModel = `value foo`.apply<String>(); // This will print: Hello print(valueModel.get()); } Usage sample for attributesFor attributes it is a bit longer, because attributes need to be applied the containing type, so you should use memberApply and start by giving the containing closed type: class Outer(){ shared String foo => "Hello"; } void test(){ // Apply the containing closed type `Outer` to the attribute declaration `Outer.foo` Attribute<Outer,String> valueModel = `value Outer.foo`.memberApply<Outer,String>(`Outer`); // We now have an Attribute, which needs to be applied to a containing instance in order to become a // readable value: Value<String> boundValueModel = valueModel(Outer()); // This will print: Hello print(boundValueModel.get()); } |
Variance | Source Code shared Variance Variance information. |
Classes | |
contravariant | Source Code shared contravariant Contravariant means that supertypes of the given type may be accepted. |
covariant | Source Code shared covariant Covariant means that subtypes of the given type may be returned. |
invariant | Source Code shared invariant Invariant means that neither subtype nor supertype can be accepted, the type has to be exactly that which is declared. |
nothingType | Source Code shared nothingType The singleton open type for Nothing. |