use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class ClassTransformer method transformAnnotationClassConstructor.
/**
* Generates a constructor for an annotation class which takes the
* annotation type as parameter.
* @param classBuilder
*/
private void transformAnnotationClassConstructor(Tree.AnyClass def, ClassDefinitionBuilder classBuilder) {
Class klass = def.getDeclarationModel();
MethodDefinitionBuilder annoCtor = classBuilder.addConstructor(klass.isDeprecated());
annoCtor.ignoreModelAnnotations();
// constructors are never final
annoCtor.modifiers(modifierTransformation().classFlags(klass) & ~FINAL);
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, "anno");
pdb.type(new TransformedType(makeJavaType(klass.getType(), JT_ANNOTATION), null, makeAtNonNull()));
annoCtor.parameter(pdb);
// It's up to the caller to invoke value() on the Java annotation for a sequenced
// annotation
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
for (Tree.Parameter parameter : def.getParameterList().getParameters()) {
at(parameter);
Parameter parameterModel = parameter.getParameterModel();
JCExpression annoAttr = make().Apply(null, naming.makeQuotedQualIdent(naming.makeUnquotedIdent("anno"), parameter.getParameterModel().getName()), List.<JCExpression>nil());
Type parameterType = parameterModel.getType();
JCExpression argExpr;
if (typeFact().isIterableType(parameterType) && !isCeylonString(parameterType)) {
// Convert from array to Sequential
Type iteratedType = typeFact().getIteratedType(parameterType);
boolean nonEmpty = typeFact().isNonemptyIterableType(parameterType);
if (isCeylonBasicType(iteratedType)) {
argExpr = utilInvocation().sequentialWrapperBoxed(annoAttr);
} else if (Decl.isAnnotationClass(iteratedType.getDeclaration())) {
// Can't use Util.sequentialAnnotation becase we need to 'box'
// the Java annotations in their Ceylon annotation class
argExpr = make().Apply(null, naming.makeUnquotedIdent(naming.getAnnotationSequenceMethodName()), List.of(annoAttr));
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
SyntheticName array = naming.synthetic(Unfix.$array$);
SyntheticName sb = naming.synthetic(Unfix.$sb$);
SyntheticName index = naming.synthetic(Unfix.$index$);
SyntheticName element = naming.synthetic(Unfix.$element$);
stmts.append(makeVar(FINAL, sb, make().TypeArray(make().Type(syms().objectType)), make().NewArray(make().Type(syms().objectType), List.of(naming.makeQualIdent(array.makeIdent(), "length")), null)));
stmts.append(makeVar(index, make().Type(syms().intType), make().Literal(0)));
stmts.append(make().ForeachLoop(makeVar(element, makeJavaType(iteratedType, JT_ANNOTATION), null), array.makeIdent(), make().Exec(make().Assign(make().Indexed(sb.makeIdent(), make().Unary(JCTree.Tag.POSTINC, index.makeIdent())), instantiateAnnotationClass(iteratedType, element.makeIdent())))));
stmts.append(make().Return(make().NewClass(null, null, make().QualIdent(syms().ceylonTupleType.tsym), List.of(makeReifiedTypeArgument(iteratedType), sb.makeIdent(), makeEmpty(), make().Literal(false)), null)));
classBuilder.method(MethodDefinitionBuilder.systemMethod(this, naming.getAnnotationSequenceMethodName()).ignoreModelAnnotations().modifiers(PRIVATE | STATIC).resultType(new TransformedType(makeJavaType(typeFact().getSequentialType(iteratedType)), null, makeAtNonNull())).parameter(ParameterDefinitionBuilder.systemParameter(this, array.getName()).type(new TransformedType(make().TypeArray(makeJavaType(iteratedType, JT_ANNOTATION))))).body(stmts.toList()));
} else if (isCeylonMetamodelDeclaration(iteratedType)) {
argExpr = makeMetamodelInvocation("parseMetamodelReferences", List.<JCExpression>of(makeReifiedTypeArgument(iteratedType), annoAttr), List.<JCExpression>of(makeJavaType(iteratedType, JT_TYPE_ARGUMENT)));
} else if (Decl.isEnumeratedTypeWithAnonCases(iteratedType)) {
argExpr = makeMetamodelInvocation("parseEnumerationReferences", List.<JCExpression>of(makeReifiedTypeArgument(iteratedType), annoAttr), List.<JCExpression>of(makeJavaType(iteratedType, JT_TYPE_ARGUMENT)));
} else {
argExpr = makeErroneous(parameter, "compiler bug");
}
if (nonEmpty) {
argExpr = make().TypeCast(makeJavaType(parameterType), argExpr);
}
} else if (Decl.isAnnotationClass(parameterType.getDeclaration())) {
argExpr = instantiateAnnotationClass(parameterType, annoAttr);
} else if (isCeylonMetamodelDeclaration(parameterType)) {
argExpr = makeMetamodelInvocation("parseMetamodelReference", List.<JCExpression>of(annoAttr), List.<JCExpression>of(makeJavaType(parameterType, JT_TYPE_ARGUMENT)));
} else if (Decl.isEnumeratedTypeWithAnonCases(parameterType)) {
argExpr = makeMetamodelInvocation("parseEnumerationReference", List.<JCExpression>of(annoAttr), null);
} else {
argExpr = annoAttr;
argExpr = expressionGen().applyErasureAndBoxing(annoAttr, parameterType.withoutUnderlyingType(), false, BoxingStrategy.UNBOXED, parameterType);
}
args.add(argExpr);
}
annoCtor.body(at(def).Exec(make().Apply(null, naming.makeThis(), args.toList())));
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class ClassTransformer method serializationSet.
private void serializationSet(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$set$.toString());
mdb.isOverride(true);
mdb.ignoreModelAnnotations();
mdb.modifiers(PUBLIC);
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, Unfix.reference.toString());
pdb.modifiers(FINAL);
pdb.type(new TransformedType(make().Type(syms().ceylonReachableReferenceType), null, makeAtNonNull()));
mdb.parameter(pdb);
ParameterDefinitionBuilder pdb2 = ParameterDefinitionBuilder.systemParameter(this, Unfix.instance.toString());
pdb2.modifiers(FINAL);
pdb2.type(new TransformedType(make().Type(syms().objectType), null, makeAtNonNull()));
mdb.parameter(pdb2);
// mdb.resultType(null, naming.makeQuotedFQIdent("java.util.Collection"));
/*
* public void $set$(Object reference, Object instance) {
* switch((String)reference) {
* case ("attr1")
* this.field1 = ...;
* break;
* // ... other fields of this class
* default:
* super.set(reference, instance);
*/
SyntheticName reference = naming.synthetic(Unfix.reference);
SyntheticName instance = naming.synthetic(Unfix.instance);
ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
boolean[] needsLookup = new boolean[] { false };
for (Declaration member : model.getMembers()) {
if (hasField(member)) {
if (member instanceof Function)
// TODO: This class is not serializable
continue;
ListBuffer<JCStatement> caseStmts = new ListBuffer<JCStatement>();
if (member instanceof Value && ((Value) member).isLate()) {
caseStmts.add(make().If(make().TypeTest(instance.makeIdent(), make().Type(syms().ceylonUninitializedLateValueType)), make().Break(null), null));
}
caseStmts.add(makeDeserializationAssignment((Value) member, needsLookup));
caseStmts.add(make().Break(null));
cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
}
}
ListBuffer<JCStatement> defaultCase = new ListBuffer<JCStatement>();
if (extendsSerializable(model)) {
// super.set(reference, instance);
defaultCase.add(make().Exec(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$set$.toString()), List.<JCExpression>of(reference.makeIdent(), instance.makeIdent()))));
} else {
// throw (or pass to something else to throw, based on policy)
defaultCase.add(make().Throw(make().NewClass(null, null, naming.makeQuotedFQIdent("java.lang.RuntimeException"), List.<JCExpression>of(make().Literal("unknown attribute")), null)));
}
cases.add(make().Case(null, defaultCase.toList()));
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
if (needsLookup[0]) {
// if we needed to use a lookup object to reset final fields,
// prepend that variable
stmts.add(makeVar(FINAL, "lookup", naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"), make().Apply(null, naming.makeQuotedFQIdent("java.lang.invoke.MethodHandles.lookup"), List.<JCExpression>nil())));
}
JCSwitch swtch = make().Switch(make().Apply(null, naming.makeSelect(make().Apply(null, naming.makeSelect(make().TypeCast(make().Type(syms().ceylonMemberType), reference.makeIdent()), "getAttribute"), List.<JCExpression>nil()), "getQualifiedName"), List.<JCExpression>nil()), cases.toList());
stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonMemberType)), swtch, make().Throw(make().NewClass(null, null, make().Type(syms().ceylonAssertionErrorType), List.<JCExpression>of(make().Binary(JCTree.Tag.PLUS, make().Literal("unexpected reachable reference "), reference.makeIdent())), null))));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class ClassTransformer method transform.
public List<MethodDefinitionBuilder> transform(Tree.AnyMethod def, TransformationPlan plan, ClassDefinitionBuilder classBuilder) {
Function model = def.getDeclarationModel();
if (model.isParameter()) {
return List.nil();
}
if (plan instanceof ThrowerMethod) {
addRefinedThrowerMethod(classBuilder, plan.getErrorMessage().getMessage(), (Class) model.getContainer(), (Function) model.getRefinedDeclaration());
return List.<MethodDefinitionBuilder>nil();
}
// Transform the method body of the 'inner-most method'
boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(Decl.isMpl(model) || ModelUtil.isLocalNotInitializer(model) || expressionGen().isWithinSyntheticClassBody());
List<JCStatement> body = transformMethodBody(def);
expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
return transform(def, classBuilder, body);
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
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;
Substitution substitution = null;
JCStatement varDef = null;
Parameter lastParameter = Decl.getLastParameterFromFirstParameterList(model);
if (lastParameter != null && Decl.isJavaVariadicIncludingInheritance(lastParameter)) {
SyntheticName alias = naming.alias(lastParameter.getName());
substitution = naming.addVariableSubst(lastParameter.getModel(), alias.getName());
varDef = substituteSequentialForJavaVariadic(alias, lastParameter);
}
try {
statementGen().noExpressionlessReturn = Decl.isMpl(model) || Strategy.useBoxedVoid(model);
body = statementGen().transformBlock(block);
} finally {
statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
if (substitution != null)
substitution.close();
}
// 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")));
}
}
if (varDef != null)
body = body.prepend(varDef);
return body;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement in project ceylon by eclipse.
the class AttributeDefinitionBuilder method initWithExceptionHandling.
/**
* surrounda the init expression with a try/catch that saves the exception
*/
private List<JCStatement> initWithExceptionHandling(List<JCStatement> stmts) {
// doesn't matter
String exceptionName = "x";
// $initException$ = null
stmts = stmts.append(owner.make().Exec(owner.make().Assign(makeExceptionFieldAccess(), owner.makeNull())));
// $initException$ = x
JCStatement saveException = owner.make().Exec(owner.make().Assign(makeExceptionFieldAccess(), owner.makeUnquotedIdent(exceptionName)));
// value = null
JCStatement nullValue = owner.make().Exec(owner.make().Assign(makeValueFieldAccess(), owner.makeDefaultExprForType(attrType)));
// the catch statements
List<JCStatement> handlerStmts = List.<JCStatement>nil();
JCStatement initFlagFalse = initTest.makeInitInitialized(false);
if (initFlagFalse != null) {
handlerStmts = handlerStmts.prepend(initFlagFalse);
}
handlerStmts = handlerStmts.prepend(nullValue);
handlerStmts = handlerStmts.prepend(saveException);
JCBlock handlerBlock = owner.make().Block(0, handlerStmts);
// the catch block
JCExpression throwableType = owner.makeJavaType(owner.syms().throwableType.tsym);
JCVariableDecl exceptionParam = owner.make().VarDef(owner.make().Modifiers(0), owner.naming.makeUnquotedName(exceptionName), throwableType, null);
JCCatch catchers = owner.make().Catch(exceptionParam, handlerBlock);
// the try/catch
JCTree.JCTry try_ = owner.make().Try(owner.make().Block(0, stmts), List.<JCTree.JCCatch>of(catchers), null);
return List.<JCTree.JCStatement>of(try_);
}
Aggregations