use of com.redhat.ceylon.model.typechecker.model.ClassOrInterface in project ceylon-compiler by ceylon.
the class ClassTransformer method addAtMembers.
private void addAtMembers(ClassDefinitionBuilder classBuilder, ClassOrInterface model, Tree.ClassOrInterface def) {
List<JCExpression> members = List.nil();
for (Declaration member : model.getMembers()) {
if (member instanceof ClassOrInterface == false && member instanceof TypeAlias == false) {
continue;
}
TypeDeclaration innerType = (TypeDeclaration) member;
Tree.Declaration innerTypeTree = findInnerType(def, innerType.getName());
if (innerTypeTree != null) {
TransformationPlan plan = errors().hasDeclarationAndMarkBrokenness(innerTypeTree);
if (plan instanceof Drop) {
continue;
}
}
if (innerType.isAlias() && innerTypeTree != null && Decl.isAncestorLocal(innerTypeTree))
// for the same reason we do not generate aliases in transform(ClassOrInterface def) let's not list them
continue;
JCAnnotation atMember;
// interfaces are moved to toplevel so they can lose visibility of member types if they are local
if (Decl.isLocal(model) && model instanceof Interface)
atMember = makeAtMember(innerType.getName());
else
atMember = makeAtMember(innerType.getType());
members = members.prepend(atMember);
}
classBuilder.annotations(makeAtMembers(members));
}
use of com.redhat.ceylon.model.typechecker.model.ClassOrInterface in project ceylon-compiler by ceylon.
the class ClassTransformer method transform.
public List<JCTree> transform(final Tree.ClassOrInterface def) {
final ClassOrInterface model = def.getDeclarationModel();
// in that case
if (model.isAlias() && Decl.isAncestorLocal(def))
return List.nil();
naming.clearSubstitutions(model);
final String javaClassName;
String ceylonClassName = def.getIdentifier().getText();
if (def instanceof Tree.AnyInterface) {
javaClassName = naming.makeTypeDeclarationName(model, QUALIFIED).replaceFirst(".*\\.", "");
} else {
javaClassName = Naming.quoteClassName(ceylonClassName);
}
ClassDefinitionBuilder instantiatorImplCb;
ClassDefinitionBuilder instantiatorDeclCb;
if (Decl.withinInterface(model)) {
instantiatorImplCb = gen().current().getCompanionBuilder((Interface) model.getContainer());
instantiatorDeclCb = gen().current();
} else {
instantiatorImplCb = gen().current();
instantiatorDeclCb = null;
}
ClassDefinitionBuilder classBuilder = ClassDefinitionBuilder.klass(this, javaClassName, ceylonClassName, Decl.isLocal(model)).forDefinition(model).hasDelegatingConstructors(CodegenUtil.hasDelegatingConstructors(def));
// Very special case for Anything
if ("ceylon.language::Anything".equals(model.getQualifiedNameString())) {
classBuilder.extending(model.getType(), null);
}
if (def instanceof Tree.AnyClass) {
classBuilder.getInitBuilder().modifiers(transformConstructorDeclFlags(model));
Tree.AnyClass classDef = (Tree.AnyClass) def;
Class cls = classDef.getDeclarationModel();
// Member classes need a instantiator method
boolean generateInstantiator = Strategy.generateInstantiator(cls);
if (!cls.hasConstructors()) {
classBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, def));
}
if (generateInstantiator && !cls.hasConstructors() && !cls.hasEnumerated()) {
classBuilder.getInitBuilder().modifiers(PROTECTED);
generateInstantiators(classBuilder, cls, null, instantiatorDeclCb, instantiatorImplCb, classDef, classDef.getParameterList());
}
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
if (def instanceof Tree.ClassDefinition) {
transformClass((Tree.ClassDefinition) def, cls, classBuilder, classDef.getParameterList(), generateInstantiator, instantiatorDeclCb, instantiatorImplCb);
} else {
// class alias
classBuilder.getInitBuilder().modifiers(PRIVATE);
transformClassAlias((Tree.ClassDeclaration) def, classBuilder);
}
addMissingUnrefinedMembers(def, cls, classBuilder);
}
if (def instanceof Tree.AnyInterface) {
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
if (def instanceof Tree.InterfaceDefinition) {
transformInterface(def, (Interface) model, classBuilder);
} else {
// interface alias
classBuilder.annotations(makeAtAlias(model.getExtendedType(), null));
classBuilder.isAlias(true);
}
classBuilder.isDynamic(model.isDynamic());
}
// make sure we set the container in case we move it out
addAtContainer(classBuilder, model);
// Transform the class/interface members
List<JCStatement> childDefs = visitClassOrInterfaceDefinition(def, classBuilder);
// everything else is synthetic
at(null);
TransformationPlan plan = errors().hasDeclarationError(def);
if (plan instanceof ThrowerCatchallConstructor) {
MethodDefinitionBuilder initBuilder = classBuilder.addConstructor();
initBuilder.body(statementGen().makeThrowUnresolvedCompilationError(plan.getErrorMessage().getMessage()));
// Although we have the class pl which we could use we don't know
// that it won't collide with the default named constructor's pl
// which would cause a javac error about two constructors with the same sig
// so we generate a Object... here. There's still a risk of collision though
// when the default constructor has pl (ObjectArray).
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.implicitParameter(this, "ignored");
pdb.modifiers(VARARGS);
pdb.type(make().TypeArray(make().Type(syms().objectType)), null);
initBuilder.parameter(pdb);
}
// If it's a Class without initializer parameters...
if (Strategy.generateMain(def)) {
// ... then add a main() method
classBuilder.method(makeMainForClass(model));
}
classBuilder.modelAnnotations(model.getAnnotations()).modifiers(transformClassDeclFlags(model)).satisfies(model.getSatisfiedTypes()).caseTypes(model.getCaseTypes(), model.getSelfType()).defs((List) childDefs);
// aliases and native headers don't need a $getType method
if (!model.isAlias()) {
// only classes get a $getType method
if (model instanceof Class)
classBuilder.addGetTypeMethod(model.getType());
if (supportsReifiedAlias(model))
classBuilder.reifiedAlias(model.getType());
}
// we can add things which depend on knowing all the fields
if (Strategy.generateJpaCtor(def)) {
buildJpaConstructor((Class) def.getDeclarationModel(), classBuilder);
}
if (model instanceof Class && !(model instanceof ClassAlias)) {
Class c = (Class) model;
if (Strategy.introduceJavaIoSerializable(c, typeFact().getJavaIoSerializable())) {
classBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
if (Strategy.useSerializationProxy(c) && noValueConstructorErrors((Tree.ClassDefinition) def)) {
addWriteReplace(c, classBuilder);
}
}
serialization(c, classBuilder);
}
// reset position before initializer constructor is generated.
at(def);
List<JCTree> result;
if (Decl.isAnnotationClass(def)) {
ListBuffer<JCTree> trees = ListBuffer.lb();
trees.addAll(transformAnnotationClass((Tree.AnyClass) def));
transformAnnotationClassConstructor((Tree.AnyClass) def, classBuilder);
// you only need that method if you satisfy Annotation which is erased to j.l.a.Annotation
if (model.inherits(typeFact().getAnnotationDeclaration()))
classBuilder.addAnnotationTypeMethod(model.getType());
trees.addAll(classBuilder.build());
result = trees.toList();
} else {
result = classBuilder.build();
}
return result;
}
use of com.redhat.ceylon.model.typechecker.model.ClassOrInterface in project ceylon-compiler by ceylon.
the class ClassTransformer method addAtContainer.
private void addAtContainer(ClassDefinitionBuilder classBuilder, TypeDeclaration model) {
Scope scope = Decl.getNonSkippedContainer((Scope) model);
Scope declarationScope = Decl.getFirstDeclarationContainer((Scope) model);
boolean inlineObjectInToplevelAttr = Decl.isTopLevelObjectExpressionType(model);
if (scope == null || (scope instanceof Package && !inlineObjectInToplevelAttr) && scope == declarationScope)
return;
if (scope instanceof ClassOrInterface && scope == declarationScope && !inlineObjectInToplevelAttr && // we do not check for types inside initialiser section which are private and not captured because we treat them as members
!(model instanceof Interface && Decl.hasLocalNotInitializerAncestor(model))) {
ClassOrInterface container = (ClassOrInterface) scope;
List<JCAnnotation> atContainer = makeAtContainer(container.getType());
classBuilder.annotations(atContainer);
} else {
if (model instanceof Interface)
classBuilder.annotations(makeLocalContainerPath((Interface) model));
Declaration declarationContainer = getDeclarationContainer(model);
classBuilder.annotations(makeAtLocalDeclaration(model.getQualifier(), declarationContainer == null));
}
}
use of com.redhat.ceylon.model.typechecker.model.ClassOrInterface in project ceylon-compiler by ceylon.
the class ClassTransformer method addWriteReplace.
/**
* Adds a write replace method which replaces value constructor instances
* with a SerializationProxy
* @param model
* @param classBuilder
*/
protected void addWriteReplace(final Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, "writeReplace");
mdb.resultType(null, make().Type(syms().objectType));
mdb.modifiers(PRIVATE | FINAL);
ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
SyntheticName name = naming.synthetic(Unfix.$name$);
stmts.add(makeVar(FINAL, name, make().Type(syms().stringType), null));
if (model.hasEnumerated()) {
JCStatement tail;
if (Decl.hasOnlyValueConstructors(model)) {
tail = make().Throw(statementGen().makeNewEnumeratedTypeError("Instance not of any constructor"));
} else {
tail = make().Return(naming.makeThis());
}
for (Declaration member : model.getMembers()) {
if (Decl.isValueConstructor(member)) {
Value val = (Value) member;
tail = make().If(make().Binary(JCTree.EQ, naming.makeThis(), naming.getValueConstructorFieldName(val).makeIdent()), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName(member)))))), tail);
}
}
stmts.add(tail);
} else if (model.isAnonymous()) {
stmts.add(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName((Value) model.getContainer().getDirectMember(model.getName(), null, false))))));
} else {
throw new BugException("Unsupported need for writeReplace()");
}
// final String name;
// if(this == instA) {
// name = "getInstA";
// } // ... else { throw new
// return new SerializationProxy(outer, Foo.clazz, name);
List<JCExpression> args = List.<JCExpression>of(name.makeIdent());
if (model.isMember()) {
ClassOrInterface outer = (ClassOrInterface) model.getContainer();
args = args.prepend(makeClassLiteral(outer.getType()));
args = args.prepend(naming.makeQualifiedThis(naming.makeTypeDeclarationExpression(null, outer, DeclNameFlag.QUALIFIED)));
} else {
args = args.prepend(makeClassLiteral(model.getType()));
}
stmts.add(make().Return(make().NewClass(null, null, make().QualIdent(syms().ceylonSerializationProxyType.tsym), args, null)));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of com.redhat.ceylon.model.typechecker.model.ClassOrInterface in project ceylon-compiler by ceylon.
the class CeylonVisitor method visit.
public void visit(Tree.ExtendedType extendedType) {
ClassOrInterface forDefinition = classBuilder.getForDefinition();
Type thisType = forDefinition != null ? forDefinition.getType() : null;
Type extended = extendedType.getType().getTypeModel();
if (extended.getDeclaration() instanceof Constructor) {
extended = extended.getQualifyingType();
}
classBuilder.extending(thisType, extended);
gen.expressionGen().transformSuperInvocation(extendedType, classBuilder);
}
Aggregations