use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method transformObject.
private List<JCTree> transformObject(Node def, Tree.Declaration annotated, Tree.SatisfiedTypes satisfiesTypes, Value model, Class klass, ClassDefinitionBuilder containingClassBuilder, boolean makeLocalInstance) {
naming.clearSubstitutions(klass);
String name = klass.getName();
String javaClassName = Naming.quoteClassName(name);
ClassDefinitionBuilder objectClassBuilder = ClassDefinitionBuilder.object(this, javaClassName, name, Decl.isLocal(klass)).forDefinition(klass);
if (Strategy.introduceJavaIoSerializable(klass, typeFact().getJavaIoSerializable())) {
objectClassBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
if (def instanceof Tree.ObjectDefinition && klass.isMember() && (klass.isShared() || klass.isCaptured() || model.isCaptured())) {
addWriteReplace(klass, objectClassBuilder);
}
}
makeReadResolve(objectClassBuilder, klass, model);
// Make sure top types satisfy reified type
addReifiedTypeInterface(objectClassBuilder, klass);
if (supportsReifiedAlias(klass))
objectClassBuilder.reifiedAlias(klass.getType());
CeylonVisitor visitor = gen().visitor;
final ListBuffer<JCTree> prevDefs = visitor.defs;
final boolean prevInInitializer = visitor.inInitializer;
final ClassDefinitionBuilder prevClassBuilder = visitor.classBuilder;
List<JCStatement> childDefs;
try {
visitor.defs = new ListBuffer<JCTree>();
visitor.inInitializer = true;
visitor.classBuilder = objectClassBuilder;
def.visitChildren(visitor);
childDefs = (List<JCStatement>) visitor.getResult().toList();
} finally {
visitor.classBuilder = prevClassBuilder;
visitor.inInitializer = prevInInitializer;
visitor.defs = prevDefs;
}
addMissingUnrefinedMembers(def, klass, objectClassBuilder);
satisfaction(satisfiesTypes, klass, objectClassBuilder);
serialization(klass, objectClassBuilder);
if (model != null && Decl.isToplevel(model) && def instanceof Tree.ObjectDefinition) {
// generate a field and getter
AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.wrapped(this, null, objectClassBuilder, model.getName(), model, true).userAnnotations(makeAtIgnore()).userAnnotationsSetter(makeAtIgnore()).immutable().initialValue(makeNewClass(naming.makeName(model, Naming.NA_FQ | Naming.NA_WRAPPER))).is(PUBLIC, Decl.isShared(klass)).is(STATIC, true);
if (annotated != null) {
builder.fieldAnnotations(expressionGen().transformAnnotations(OutputElement.FIELD, annotated));
builder.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, annotated));
}
objectClassBuilder.defs(builder.build());
}
if (annotated != null) {
objectClassBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, annotated));
objectClassBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, annotated));
}
// make sure we set the container in case we move it out
addAtContainer(objectClassBuilder, klass);
objectClassBuilder.annotations(makeAtObject()).satisfies(klass.getSatisfiedTypes()).defs((List) childDefs);
objectClassBuilder.getInitBuilder().modifiers(PRIVATE);
objectClassBuilder.addGetTypeMethod(klass.getType());
if (model != null)
objectClassBuilder.modelAnnotations(model.getAnnotations()).modifiers(transformObjectDeclFlags(model));
List<JCTree> result = objectClassBuilder.build();
if (makeLocalInstance) {
if (model.isSelfCaptured()) {
// if it's captured we need to box it and define the var before the class, so it can access it
JCNewClass newInstance = makeNewClass(objectClassBuilder.getClassName(), false, null);
JCFieldAccess setter = naming.makeSelect(Naming.getLocalValueName(model), Naming.getSetterName(model));
JCStatement assign = make().Exec(make().Assign(setter, newInstance));
result = result.prepend(assign);
JCVariableDecl localDecl = makeVariableBoxDecl(null, model);
result = result.prepend(localDecl);
} else {
// not captured, we can define the var after the class
JCVariableDecl localDecl = makeLocalIdentityInstance(name, objectClassBuilder.getClassName(), false);
result = result.append(localDecl);
}
} else if (model != null && Decl.withinClassOrInterface(model)) {
boolean generateGetter = Decl.isCaptured(model);
JCExpression type = makeJavaType(klass.getType());
if (generateGetter) {
int modifiers = TRANSIENT | PRIVATE;
JCExpression initialValue = makeNull();
containingClassBuilder.field(modifiers, name, type, initialValue, false);
AttributeDefinitionBuilder getter = AttributeDefinitionBuilder.getter(this, name, model).modifiers(transformAttributeGetSetDeclFlags(model, false));
if (def instanceof Tree.ObjectDefinition) {
getter.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, ((Tree.ObjectDefinition) def)));
}
ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
stmts.add(make().If(make().Binary(JCTree.EQ, naming.makeUnquotedIdent(Naming.quoteFieldName(name)), makeNull()), make().Exec(make().Assign(naming.makeUnquotedIdent(Naming.quoteFieldName(name)), makeNewClass(makeJavaType(klass.getType()), null))), null));
stmts.add(make().Return(naming.makeUnquotedIdent(Naming.quoteFieldName(name))));
getter.getterBlock(make().Block(0, stmts.toList()));
result = result.appendList(getter.build());
} else {
int modifiers = FINAL;
JCExpression initialValue = makeNewClass(makeJavaType(klass.getType()), null);
containingClassBuilder.field(modifiers, name, type, initialValue, true);
}
}
return result;
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method serializationConstructor.
/**
* <p>Generates the serialization constructor
* with signature {@code ($Serialization$)} which:</p>
* <ul>
* <li>invokes {@code super()}, if the super class is also
* serializable,</li>
* <li>initializes all companion instance fields to a
* newly instantiated companion instance,</li>
* <li>initializes all reified type argument fields to null,</li>
* <li>initializes all reference attribute fields to null,</li>
* <li>initializesall primitive attribute fields to a default
* value (basically some kind of 0)</li>
* </ul>
*/
private void serializationConstructor(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder ctor = classBuilder.addConstructor();
ctor.ignoreModelAnnotations();
ctor.modifiers(PUBLIC);
ParameterDefinitionBuilder serializationPdb = ParameterDefinitionBuilder.systemParameter(this, "ignored");
serializationPdb.modifiers(FINAL);
serializationPdb.type(make().Type(syms().ceylonSerializationType), null);
ctor.parameter(serializationPdb);
for (TypeParameter tp : model.getTypeParameters()) {
ctor.reifiedTypeParameter(tp);
}
final ListBuffer<JCStatement> stmts = ListBuffer.lb();
if (extendsSerializable(model)) {
// invoke super
ListBuffer<JCExpression> superArgs = ListBuffer.<JCExpression>lb();
superArgs.add(naming.makeUnquotedIdent("ignored"));
for (JCExpression ta : makeReifiedTypeArguments(model.getExtendedType())) {
superArgs.add(ta);
}
stmts.add(make().Exec(make().Apply(null, naming.makeSuper(), superArgs.toList())));
}
buildFieldInits(model, classBuilder, stmts);
ctor.body(stmts.toList());
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method serializationReferences.
/**
* <p>Generates the {@code $deserialize$()} method to deserialize
* the classes state, which:</p>
* <ul>
* <li>invokes {@code super.$deserialize$()}, if the super class is also
* serializable,</li>
* <li>assigns each reified type argument in the
* class by invoking {@code dted.getTypeArgument()},</li>
* <li>assigns each field in the
* class by invoking {@code dted.getValue()}.</li>
* </ul>
*/
private void serializationReferences(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$references$.toString());
mdb.isOverride(true);
mdb.ignoreModelAnnotations();
mdb.modifiers(PUBLIC);
mdb.resultType(null, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))));
ListBuffer<JCStatement> stmts = ListBuffer.lb();
// TODO this is all static information, but the method itself needs to be
// callable virtually, so we should cache it somehow.
SyntheticName r = naming.synthetic(Unfix.reference);
if (extendsSerializable(model)) {
// prepend the invocation of super.$serialize$()
stmts.add(makeVar(r, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$references$.toString()), List.<JCExpression>nil())));
} else {
stmts.add(makeVar(r, make().TypeApply(naming.makeQuotedFQIdent("java.util.Collection"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), make().NewClass(null, null, make().TypeApply(naming.makeQuotedFQIdent("java.util.ArrayList"), List.<JCExpression>of(make().Type(syms().ceylonReachableReferenceType))), List.<JCExpression>nil(), null)));
}
if (model.isMember()) {
JCExpressionStatement outer = make().Exec(make().Apply(null, naming.makeQualIdent(r.makeIdent(), "add"), List.<JCExpression>of(make().Apply(null, naming.makeQualIdent(make().Type(syms().ceylonOuterImplType), "get_"), List.<JCExpression>nil()))));
stmts.add(outer);
}
for (Declaration member : model.getMembers()) {
if (hasField(member)) {
// Obtain a ValueDeclaration
JCExpression valueDeclaration = expressionGen().makeMemberValueOrFunctionDeclarationLiteral(null, member, false);
// Create a MemberImpl
JCExpression mi = make().NewClass(null, null, make().QualIdent(syms().ceylonMemberImplType.tsym), List.of(valueDeclaration), null);
JCExpressionStatement attribute = make().Exec(make().Apply(null, naming.makeQualIdent(r.makeIdent(), "add"), List.of(mi)));
stmts.add(attribute);
}
}
stmts.add(make().Return(r.makeIdent()));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method transformMethodBlock.
private List<JCStatement> transformMethodBlock(final Tree.MethodDefinition def) {
final Function model = def.getDeclarationModel();
final Tree.Block block = def.getBlock();
List<JCStatement> body;
boolean prevNoExpressionlessReturn = statementGen().noExpressionlessReturn;
try {
statementGen().noExpressionlessReturn = Decl.isMpl(model) || Strategy.useBoxedVoid(model);
body = statementGen().transformBlock(block);
} finally {
statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
}
// We void methods need to have their Callables return null
// so adjust here.
HasErrorException error = errors().getFirstErrorBlock(block);
if ((Decl.isMpl(model) || Strategy.useBoxedVoid(model)) && !block.getDefinitelyReturns() && error == null) {
if (Decl.isUnboxedVoid(model)) {
body = body.append(make().Return(makeNull()));
} else {
body = body.append(make().Return(makeErroneous(block, "compiler bug: non-void method doesn't definitely return")));
}
}
return body;
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassDefinitionBuilder method addAnnotationTypeMethod.
public ClassDefinitionBuilder addAnnotationTypeMethod(Type type) {
MethodDefinitionBuilder method = MethodDefinitionBuilder.systemMethod(gen, "annotationType");
method.modifiers(PUBLIC);
method.resultType(List.<JCAnnotation>nil(), gen.make().TypeApply(gen.make().QualIdent(gen.syms().classType.tsym), List.<JCTree.JCExpression>of(gen.make().Wildcard(gen.make().TypeBoundKind(BoundKind.EXTENDS), gen.make().Type(gen.syms().annotationType)))));
method.isOverride(true);
List<JCStatement> body = List.<JCStatement>of(gen.make().Return(gen.makeClassLiteral(type, AbstractTransformer.JT_ANNOTATION)));
method.body(body);
JCMethodDecl build = method.build();
defs(build);
return this;
}
Aggregations