Skip to content

Commit

Permalink
Mostly doc changes to ClassDeclaration/ConstructorDeclaration
Browse files Browse the repository at this point in the history
Part of #750
  • Loading branch information
tombentley committed Sep 29, 2015
1 parent 62887e9 commit 4d7306d
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 78 deletions.
Expand Up @@ -10,6 +10,7 @@
import ceylon.language.empty_;
import ceylon.language.meta.declaration.CallableConstructorDeclaration;
import ceylon.language.meta.declaration.ClassDeclaration$impl;
import ceylon.language.meta.declaration.ConstructorDeclaration;
import ceylon.language.meta.declaration.FunctionOrValueDeclaration;
import ceylon.language.meta.declaration.ValueConstructorDeclaration;
import ceylon.language.meta.declaration.ValueDeclaration;
Expand Down Expand Up @@ -343,13 +344,13 @@ public String toString() {

@TypeInfo("ceylon.language.meta.declaration::ConstructorDeclaration|ceylon.language::Null")
@Override
public ceylon.language.meta.declaration.Declaration getConstructorDeclaration(
public ceylon.language.meta.declaration.ConstructorDeclaration getConstructorDeclaration(
@Name("name")
String name) {
checkInit();
for (ceylon.language.meta.declaration.Declaration ctor : this.constructors) {
if (ctor.getName().equals(name)) {
return ctor;
return (ConstructorDeclaration)ctor;
}
}
return null;
Expand Down
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import ceylon.language.Sequence;
import ceylon.language.Sequential;
import ceylon.language.Singleton;
import ceylon.language.empty_;
Expand Down Expand Up @@ -45,21 +46,28 @@ public FreeClassWithInitializer(com.redhat.ceylon.model.typechecker.model.Class

@TypeInfo("ceylon.language::ConstructorDeclaration[]")
@Override
public Sequential<? extends ConstructorDeclaration> constructorDeclarations() {
public Sequence<? extends ConstructorDeclaration> constructorDeclarations() {
return new Singleton<ConstructorDeclaration>(ConstructorDeclaration.$TypeDescriptor$, getDefaultConstructor());
}

@TypeInfo("ceylon.language::ConstructorDeclaration[]")
@Override
public <A extends java.lang.annotation.Annotation> Sequential<? extends ConstructorDeclaration> annotatedConstructorDeclarations(TypeDescriptor reified$Annotation) {
public <A extends java.lang.annotation.Annotation> Sequential<? extends CallableConstructorDeclaration> annotatedConstructorDeclarations(TypeDescriptor reified$Annotation) {
// TODO test the single ctor against the preditace and return a singleton or not
return (Sequential)empty_.get_();
}

@Override
public CallableConstructorDeclaration getDefaultConstructor() {
return new FreeInitializerConstructor((com.redhat.ceylon.model.typechecker.model.Class)declaration);
}

@TypeInfo("ceylon.language.meta.declaration::CallableConstructorDeclaration")
@Override
public ceylon.language.meta.declaration.CallableConstructorDeclaration getConstructorDeclaration(String name) {
return (ceylon.language.meta.declaration.CallableConstructorDeclaration)super.getConstructorDeclaration(name);
}

@Override
@TypeInfo("ceylon.language::Sequential<ceylon.language.meta.declaration::FunctionOrValueDeclaration>")
public Sequential<? extends ceylon.language.meta.declaration.FunctionOrValueDeclaration> getParameterDeclarations(){
Expand Down
Expand Up @@ -24,6 +24,10 @@ import ceylon.language.meta.declaration {
CallableConstructorDeclaration default = `new WithConstructors`;
CallableConstructorDeclaration clone = `new WithConstructors.clone`;
The initializer of a class with a parameter list can also be
[[represented|ClassWithInitializerDeclaration.defaultConstructor]]
as a `CallableConstructorDeclaration`.
"""
see (`interface ValueConstructorDeclaration`)
shared sealed interface CallableConstructorDeclaration
Expand Down
91 changes: 25 additions & 66 deletions src/ceylon/language/meta/declaration/ClassDeclaration.ceylon
Expand Up @@ -9,6 +9,16 @@ import ceylon.language.meta.model {

"""Class declaration.
### Callable classes
Since Ceylon 1.2 classes are not always directly invokable
(if the class has constructors, but not a default constructor). Thus
members of `ClassDeclaration` which depend on the class parameter
list typically have optional type, but are refined on
[[ClassWithInitializerDeclaration]] to be non-optional. The exceptions to
this are [[instantiate]] and [[memberInstantiate]],
which throw exceptions.
<a name="toplevel-sample"></a>
### Usage sample for toplevel classes
Expand Down Expand Up @@ -53,16 +63,14 @@ shared sealed interface ClassDeclaration
of ClassWithInitializerDeclaration | ClassWithConstructorsDeclaration
satisfies ClassOrInterfaceDeclaration {

"A constructor declaration representing the clas initializer or
the default initializer, or null if the class lacks
"A constructor declaration representing the class initializer
(for a class with a parameter list) or
the default constructor, or null if the class lacks
both a parameter list and a default constructor."
shared formal CallableConstructorDeclaration? defaultConstructor;

"True if the current declaration is an annotation class or function."
shared formal Boolean annotation;

"The list of parameter declarations for this class.
Returns `null` of the class lacks both a parameter list and a
Returns `null` if the class lacks both a parameter list and a
default constructor."
shared formal FunctionOrValueDeclaration[]? parameterDeclarations;

Expand All @@ -72,6 +80,9 @@ shared sealed interface ClassDeclaration
or if no such parameter exists in the parameter list."
shared formal FunctionOrValueDeclaration? getParameterDeclaration(String name);

"True if the current declaration is an annotation class or function."
shared formal Boolean annotation;

"True if the class has an [[abstract|ceylon.language::abstract]] annotation."
shared formal Boolean abstract;

Expand Down Expand Up @@ -114,17 +125,21 @@ shared sealed interface ClassDeclaration
(AppliedType<Object> containerType, AppliedType<>* typeArguments)
given Arguments satisfies Anything[];

"Creates a new instance of this toplevel class, by applying the specified type arguments and value arguments."
"Creates a new instance of this toplevel class,
by applying the specified type arguments and value arguments."
throws(`class IncompatibleTypeException`,
"If the specified type or value arguments are not compatible with
this toplevel class.")
this toplevel class, or if the class lacks both a parameter list
and a default constructor.")
shared default Object instantiate(AppliedType<>[] typeArguments = [], Anything* arguments)
=> classApply<Object, Nothing>(*typeArguments).apply(*arguments);

"Creates a new instance of this member class, by applying the specified type arguments and value arguments."
"Creates a new instance of this member class, by applying the specified
type arguments and value arguments."
throws(`class IncompatibleTypeException`,
"If the specified container, type or value arguments are not
compatible with this method.")
compatible with this method, or if the class lacks both a parameter list
and a default constructor.")
shared default Object memberInstantiate
(Object container, AppliedType<>[] typeArguments = [], Anything* arguments)
=> memberClassApply<Nothing, Object, Nothing>(`Nothing`, *typeArguments).bind(container).apply(*arguments);
Expand All @@ -144,59 +159,3 @@ shared sealed interface ClassDeclaration
given Annotation satisfies AnnotationType;
}

"""The declaration model of a class that has a parameter list. For example:
class WithParameterList() {
}
"""
see(`interface ClassWithConstructorsDeclaration`)
shared sealed interface ClassWithInitializerDeclaration
satisfies ClassDeclaration {

shared actual formal CallableConstructorDeclaration defaultConstructor;

"The list of parameter declarations for this class."
shared actual formal FunctionOrValueDeclaration[] parameterDeclarations;

shared actual default [] constructorDeclarations() => [];

shared actual default Null getConstructorDeclaration(String name) => null;

shared actual default [] annotatedConstructorDeclarations<Annotation>()
given Annotation satisfies AnnotationType => [];
}

"""The declaration model of a class that has constructors. For example:
class WithConstructors {
shared new() {
// ...
}
shared clone(WithConstructors other) {
// ...
}
}
"""
see(`interface ClassWithInitializerDeclaration`)
shared sealed interface ClassWithConstructorsDeclaration
satisfies ClassDeclaration {

"Instantiates this class if it has a default constructor,
using the given type and value arguments.
Otherwise throws [[IncompatibleTypeException]]"
throws (`class IncompatibleTypeException`,
"If the class lacks a default constructor, or is a member class")
shared actual default Nothing instantiate(AppliedType<>[] typeArguments, Anything* arguments) {
throw IncompatibleTypeException("class has constructors");
}

"Instantiates this member class if it has a default constructor,
using the given container instances, type and value arguments.
Otherwise throws [[IncompatibleTypeException]]"
throws (`class IncompatibleTypeException`,
"If the class lacks a default constructor, or is not a member class")
shared actual default Nothing memberInstantiate(Object container, AppliedType<>[] typeArguments, Anything* arguments) {
throw IncompatibleTypeException("class has constructors");
}
}
@@ -0,0 +1,32 @@
import ceylon.language { AnnotationType = Annotation }
import ceylon.language.meta.model {
Class,
MemberClass,
AppliedType = Type,
IncompatibleTypeException,
TypeApplicationException
}


"""The declaration model of a class that has constructors. For example:
class Point {
shared new(Float x, Float y) {
// ...
}
shared new polar(Float r, Float theta) {
// ...
}
shared new origin {
// ...
}
}
Such classes may not have a default (unnamed) constructor,
so [[defaultConstructor|ClassDeclaration.defaultConstructor]]
has optional type.
"""
see(`interface ClassWithInitializerDeclaration`)
shared sealed interface ClassWithConstructorsDeclaration
satisfies ClassDeclaration {
}
@@ -0,0 +1,46 @@
import ceylon.language { AnnotationType = Annotation }
import ceylon.language.meta.model {
Class,
MemberClass,
AppliedType = Type,
IncompatibleTypeException,
TypeApplicationException
}



"""The declaration model of a class that has a parameter list rather than
explicit constructors. For example:
class Color(Integer rgba) {
}
Such classes have a meaningful parameter list and for abstraction purposes
have a single [[defaultConstructor]] representing the
class' parameter list and the class initializer code.
This "constructor" will have the same
[[SharedAnnotation]], [[DeprecationAnnotation]]
and [[ThrownExceptionAnnotation]]
annotations as the class, but will have no
other annotations.
"""
see(`interface ClassWithConstructorsDeclaration`)
shared sealed interface ClassWithInitializerDeclaration
satisfies ClassDeclaration {

"A CallableConstructorDeclaration representing the class initializer."
shared actual formal CallableConstructorDeclaration defaultConstructor;

"The list of parameter declarations for this class."
shared actual formal FunctionOrValueDeclaration[] parameterDeclarations;

"A singleton sequence containing the [[defaultConstructor]]."
shared actual default Sequence<CallableConstructorDeclaration> constructorDeclarations()
=> Singleton(defaultConstructor);

shared actual default CallableConstructorDeclaration? getConstructorDeclaration(String name)
=> if (name.empty) then defaultConstructor else null;

shared actual formal CallableConstructorDeclaration[] annotatedConstructorDeclarations<Annotation>()
given Annotation satisfies AnnotationType;
}
34 changes: 26 additions & 8 deletions test/metamodel/bug750.ceylon
Expand Up @@ -2,7 +2,6 @@ import ceylon.language.meta.declaration{...}
import ceylon.language.meta.model{CallableConstructor, TypeApplicationException}


"doc"
class Bug750Init<T>(String s) {

}
Expand All @@ -14,11 +13,21 @@ class Bug750NoDefault<T> {
shared new other(String s) {}
}

"doc"
shared
throws(`class Exception`, "Always")
deprecated()
class Bug750Anno() {
throw Exception();
}


@test
shared void bug750() {
ClassWithInitializerDeclaration bug750Init = `class Bug750Init`;
ClassWithConstructorsDeclaration bug750Ctors= `class Bug750Ctors`;
ClassWithConstructorsDeclaration bug750NoDefault= `class Bug750NoDefault`;
ClassWithInitializerDeclaration bug750Anno = `class Bug750Anno`;
CallableConstructorDeclaration ctor = `new Bug750Ctors`;
CallableConstructorDeclaration init = bug750Init.defaultConstructor;

Expand Down Expand Up @@ -50,13 +59,16 @@ shared void bug750() {
assert(!init.formal);
assert(init.shared);
assert(!init.toplevel);
// XXX What are the semantics fo this? In Ceylon-land a ClassWithInitiaizer
// I guess it should return all those annotations which are permitted on a constructor?
//assert(!init.annotated<SharedAnnotation>());
//assert(init.annotated<DocAnnotation>());
//assert(!init.annotated<FormalAnnotation>());
//assert(init.annotations<SharedAnnotation>().empty);
//assert(!init.annotations<DocAnnotation>().empty);
// annotations
value annos = bug750Anno.constructorDeclarations();
assert(annos == bug750Anno.annotatedConstructorDeclarations<SharedAnnotation>());
assert(annos == bug750Anno.annotatedConstructorDeclarations<DeprecationAnnotation>());
assert(annos == bug750Anno.annotatedConstructorDeclarations<ThrownExceptionAnnotation>());
assert(bug750Anno.annotatedConstructorDeclarations<DocAnnotation>().empty);
assert(bug750Anno.defaultConstructor.annotated<SharedAnnotation>());
assert(bug750Anno.defaultConstructor.annotated<DeprecationAnnotation>());
assert(bug750Anno.defaultConstructor.annotated<ThrownExceptionAnnotation>());
assert(bug750Anno.defaultConstructor.annotated<DocAnnotation>());

// apply
CallableConstructor<Bug750Init<String>,[String]> appliedCtor = init.apply<Bug750Init<String>,[String]>(`String`);
Expand Down Expand Up @@ -84,6 +96,12 @@ shared void bug750() {
// qualifiedName
assert("metamodel::Bug750Init" == init.qualifiedName);

Sequence<CallableConstructorDeclaration> xxx = bug750Init.constructorDeclarations();
assert(init in xxx);

CallableConstructorDeclaration? yyy = bug750Init.getConstructorDeclaration("");
assert(yyy exists);

Bug750Outer().bug750();
}

Expand Down

0 comments on commit 4d7306d

Please sign in to comment.