The Ceylon metamodel base package.
The Ceylon metamodel allows you to:
There are a few concepts and terms in the Ceylon metamodel API that you should be familiar with:
For example, given the following Ceylon program:
shared abstract class MyList<T>() satisfies List<T>{}
The declaration of MyList
represents the class declaration and contains the information that it is
abstract
and that it satisfies the List<T>
open type. That type is open because it contains an
unbound type variable T
, which is not bound when we inspect the MyList
class declaration.
Given an particular instance of MyList
, we can query its (closed) type with the type()
function,
and we obtain a closed type representing (for example) MyList<Integer>
. Object instances necessarily
have a closed type at runtime, since in order to instantiate an object, all type arguments must be
provided and known during instantiation, so the type of an object instance at runtime is necessarily
a closed type: they cannot contain unbound type variables.
Closed types that represent class or interfaces are also models. For example, the closed type of our
MyList<Integer>
instance is both a closed type and a class model: you can query its satisfied types
and find that it satisfies List<Integer>
closed type and model (as opposed to the class declaration
of MyList
which satisfies the List<T>
open type). You can also invoke that model to obtain a new
instance of MyList<Integer>
.
Ceylon supports getting declaration values using either the declaration API or using declaration literals:
`module ceylon.file`
returns the Module
declaration which corresponds to the ceylon.file
module you imported in your module descriptor, or
to the current module if it is ceylon.file
. You can also obtain a reference to the current module
with `module`
.`package ceylon.language.meta`
returns the Package
declaration from your current module or its imports. You can also obtain a reference to the current package
with `package`
.`interface List`
returns the InterfaceDeclaration
for the List type. You can also obtain a reference to the current interface
with `interface`
.`class Integer`
returns the ClassDeclaration
for the Integer type. You can also obtain a reference to the current class
with `class`
.`new Array.ofSize`
returns the
CallableConstructorDeclaration
for the Array.ofSize()
constructor. Similarly `new Color.black`
for
value constructors.`function type`
returns the FunctionDeclaration
for the type()
function. Similarly `function List.shorterThan`
for methods.`value modules`
returns the ValueDeclaration
for the modules
value. Similarly `function List.size`
for attributes.`alias AliasName`
returns the AliasDeclaration
for the AliasName
type alias.`given T`
returns the TypeParameter
for the T
type parameter.Note that declaration literals cannot have type arguments specified on types or methods, as declarations are not types.
You can also get access to closed types and model using either the model API or using literals:
`List<Integer>`
returns the Interface model and
closed type for the List type applied with the Integer type argument.`Integer`
returns the Class model and closed type
for the Integer type.`Array.ofSize`
returns the
CallableConstructor model
for the Array`Color.black`
for
value constructor models.`type<Integer>`
returns the Function model
for the type()
function applied with the Integer type argument.
Similarly `List<Integer>.shorterThan`
for
method models.`modules`
returns the Value model
for the modules
value. Similarly `List<Integer>.size`
for
attribute models.`A & B`
returns a IntersectionType
for the A & B
intersection type.`A | B`
returns a UnionType
for the A | B
union type.`T`
returns a Type representing the runtime type
argument value for the T
type parameter.Notice that all model and close type literals must be applied with all required type arguments.
Aside from declaration and model literals there are several ways you can start using the metamodel API:
modules
object contains a list of all currently loaded Module
declarations. Note that these contain even modules you did not import as it contains all transitive
dependencies, and may contain multiple different versions of the same module.classDeclaration()
function will return the
ClassDeclaration
of the given instance.type()
function will return the closed type of the given instance, which can only be a
ClassModel since only classes can be instantiated.typeLiteral()
function is the functional equivalent to closed type literals: it turns a type argument
value into a metamodel closed type.Constrained annotations can be inspected using the annotations()
function, like this:
// Does the process declaration have the Shared annotation? value isShared = annotations(`SharedAnnotation`, `value process`) exists;
or the related optionalAnnotation()
and sequencedAnnotations()
functions.
Note that annotations are queried for via their
Annotation
type,
not by the annotation constructor which was used to annotate
the program element.
Subpackages | |
ceylon.language.meta.declaration | The Ceylon metamodel open type and declaration package. |
ceylon.language.meta.model | The Ceylon metamodel closed type and model package. |
Values | |
modules | Source Codeshared modules modules Represents the list of Ceylon modules currently loaded at runtime. Note that this contains all loaded modules, including those that are not imported by your module. Since Ceylon supports module isolation at runtime, it is possible that there are more than one version of a given module loaded at the same time. Usage exampleHere's how you would iterate all the loaded modules and print their name and version: import ceylon.language.meta { modules } for(mod in modules.list){ print("Module: ``mod.name``/``mod.version``"); } |
Functions | |
annotations | Source Codeshared Values annotations<Value, Values, in ProgramElement>(Class<ConstrainedAnnotation<Value,Values,ProgramElement,Anything>,Nothing> annotationType, ProgramElement programElement) The annotations of the given type applied to the given program element. For example: // Does the process declaration have any annotations // of type SharedAnnotation? value isShared = annotations(`SharedAnnotation`, `value process`) exists; The annotations may be returned in any order. |
classDeclaration | Source Codeshared ClassDeclaration classDeclaration(Anything instance) Returns the class declaration for a given instance. Since only classes
can be instantiated, this will always be a Using |
optionalAnnotation | Source Codeshared Value? optionalAnnotation<Value, in ProgramElement>(Class<OptionalAnnotation<Value,ProgramElement,Anything>,Nothing> annotationType, ProgramElement programElement) The value of given optional annotation type on the given program element, or null if the program element was not annotated with that annotation type. For example: // Does the process declaration have the Shared annotation? value isShared = optionalAnnotation(`SharedAnnotation`, `value process`) exists; |
sequencedAnnotations | Source Codeshared Value[] sequencedAnnotations<Value, in ProgramElement>(Class<SequencedAnnotation<Value,ProgramElement,Anything>,Nothing> annotationType, ProgramElement programElement) The values of given sequenced annotation type on the given program element, or empty if the program element was not annotated with that annotation type. For example: // Does the sum declaration have any ThrownException annotations? value throwsSomething = sequencedAnnotation(`ThrownException`, `function sum`) nonempty; The annotations may be returned in any order. |
type | Source Codeshared ClassModel<Type,Nothing> type<out Type>(Type instance) Returns the closed type and model of a given instance. Since only classes
can be instantiated, this will always be a See also classDeclaration() |
typeLiteral | Source Codeshared ClosedType<Type> typeLiteral<out Type>() Functional equivalent to type literals. Allows you to get a closed type instance for a given type argument. For example: assert(is Interface<List<Integer>> listOfIntegers = typeLiteral<List<Integer>>()); |
Classes | |
modules | Source Codeshared modules Represents the list of Ceylon modules currently loaded at runtime. Note that this contains all loaded modules, including those that are not imported by your module. Since Ceylon supports module isolation at runtime, it is possible that there are more than one version of a given module loaded at the same time. Usage exampleHere's how you would iterate all the loaded modules and print their name and version: import ceylon.language.meta { modules } for(mod in modules.list){ print("Module: ``mod.name``/``mod.version``"); } |