use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method transformSpreadOperator.
private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
at(expr);
boolean spreadMethodReferenceOuter = !expr.equals(spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
boolean spreadMethodReferenceInner = expr.equals(spreading) && isWithinInvocation();
Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
if (spreadMethodReferenceOuter) {
spreading = expr;
}
try {
Naming.SyntheticName varBaseName = naming.alias("spread");
ListBuffer<JCStatement> letStmts = new ListBuffer<JCStatement>();
final Naming.SyntheticName srcIterableName;
if (spreadMethodReferenceInner) {
// use the var we initialized in the outer
srcIterableName = this.memberPrimary;
} else {
srcIterableName = varBaseName.suffixedBy(Suffix.$iterable$);
}
if (spreadMethodReferenceOuter) {
// if we're in the outer, note then name of the var for use in the inner.
this.memberPrimary = srcIterableName;
}
Naming.SyntheticName srcIteratorName = varBaseName.suffixedBy(Suffix.$iterator$);
Type srcElementType = expr.getTarget().getQualifyingType();
JCExpression srcIterableExpr;
boolean isSuperOrSuperOf = false;
Type srcIterableType;
if (typeFact().isIterableType(expr.getPrimary().getTypeModel())) {
srcIterableType = typeFact().getIterableType(srcElementType);
} else if (typeFact().isJavaIterableType(expr.getPrimary().getTypeModel())) {
srcIterableType = typeFact().getJavaIterableDeclaration().appliedType(null, Collections.singletonList(srcElementType));
} else if (typeFact().isJavaArrayType(expr.getPrimary().getTypeModel())) {
srcIterableType = expr.getPrimary().getTypeModel();
srcElementType = typeFact().getJavaArrayElementType(srcIterableType);
} else {
return makeErroneous(expr, "unhandled iterable type");
}
if (spreadMethodReferenceInner) {
srcIterableExpr = srcIterableName.makeIdent();
} else {
boolean isSuper = isSuper(expr.getPrimary());
isSuperOrSuperOf = isSuper || isSuperOf(expr.getPrimary());
if (isSuperOrSuperOf) {
// so we just refer to it later
if (isSuper) {
Declaration member = expr.getPrimary().getTypeModel().getDeclaration().getMember("iterator", null, false);
srcIterableExpr = transformSuper(expr, (TypeDeclaration) member.getContainer());
} else
srcIterableExpr = transformSuperOf(expr, expr.getPrimary(), "iterator");
} else {
srcIterableExpr = transformExpression(expr.getPrimary(), BoxingStrategy.BOXED, srcIterableType);
}
}
// do not capture the iterable for super invocations: see above
if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
JCVariableDecl srcIterable = null;
JCExpression srcIterableTypeExpr = makeJavaType(srcIterableType, JT_NO_PRIMITIVES);
srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
letStmts.prepend(srcIterable);
}
/* public Object next() {
* Object result;
* if (!((result = iterator.next()) instanceof Finished)) {
* result = transformedMember(result);
* }
* return result;
*/
/* Any arguments in the member of the spread would get re-evaluated on each iteration
* so we need to shift them to the scope of the Let to ensure they're evaluated once.
*/
boolean aliasArguments = transformer instanceof InvocationTermTransformer && ((InvocationTermTransformer) transformer).invocation.getNode() instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) ((InvocationTermTransformer) transformer).invocation.getNode()).getPositionalArgumentList() != null;
if (aliasArguments) {
((InvocationTermTransformer) transformer).callBuilder.argumentHandling(CallBuilder.CB_ALIAS_ARGS, varBaseName);
}
JCNewClass iterableClass;
boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
try {
Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
JCExpression transformedElement = applyErasureAndBoxing(iteratorResultName.makeIdent(), typeFact().getAnythingType(), CodegenUtil.hasTypeErased(expr.getPrimary()), true, BoxingStrategy.BOXED, srcElementType, 0);
transformedElement = transformMemberExpression(expr, transformedElement, transformer);
// be handled by the previous recursion
if (spreadMethodReferenceOuter) {
return make().LetExpr(letStmts.toList(), transformedElement);
}
Type resultElementType = expr.getTarget().getType();
final Type resultAbsentType;
transformedElement = applyErasureAndBoxing(transformedElement, resultElementType, // not necessarily of the applied member
expr.getTarget().getDeclaration() instanceof TypedDeclaration ? CodegenUtil.hasTypeErased((TypedDeclaration) expr.getTarget().getDeclaration()) : false, !CodegenUtil.isUnBoxed(expr), BoxingStrategy.BOXED, resultElementType, 0);
MethodDefinitionBuilder nextMdb = MethodDefinitionBuilder.systemMethod(this, "next");
nextMdb.isOverride(true);
nextMdb.annotationFlags(Annotations.IGNORE);
nextMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
nextMdb.resultType(new TransformedType(make().Type(syms().objectType)));
final List<JCTree> l;
if (typeFact().isIterableType(expr.getPrimary().getTypeModel())) {
// private Iterator<srcElementType> iterator = srcIterableName.iterator();
JCVariableDecl srcIterator = makeVar(Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
resultAbsentType = typeFact().getIteratedAbsentType(expr.getPrimary().getTypeModel());
nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.Tag.NOT, make().TypeTest(make().Assign(iteratorResultName.makeIdent(), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Type(syms().ceylonFinishedType))), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(iteratorResultName.makeIdent(), transformedElement)))), null), make().Return(iteratorResultName.makeIdent())));
l = List.of(srcIterator, nextMdb.build());
} else if (typeFact().isJavaIterableType(expr.getPrimary().getTypeModel())) {
// private Iterator<srcElementType> iterator = srcIterableName.iterator();
JCVariableDecl srcIterator = makeVar(Flags.PRIVATE | Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getJavaIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
resultAbsentType = typeFact().getNullType();
nextMdb.body(List.<JCStatement>of(make().If(make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "hasNext"), List.<JCExpression>nil()), make().Block(0, List.<JCStatement>of(makeVar(iteratorResultName, make().Type(syms().objectType), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Return(transformedElement))), make().Return(makeFinished()))));
l = List.of(srcIterator, nextMdb.build());
} else if (typeFact().isJavaArrayType(expr.getPrimary().getTypeModel())) {
resultAbsentType = typeFact().getNullType();
JCVariableDecl srcIndex = makeVar(Flags.PRIVATE, srcIteratorName, make().Type(syms().intType), make().Literal(0));
JCExpression indexed = make().Indexed(srcIterableName.makeIdent(), make().Unary(Tag.POSTINC, srcIteratorName.makeIdent()));
if (typeFact().isJavaPrimitiveArrayType(expr.getPrimary().getTypeModel())) {
indexed = applyErasureAndBoxing(indexed, srcElementType, false, BoxingStrategy.BOXED, srcElementType);
}
nextMdb.body(List.<JCStatement>of(make().If(make().Binary(Tag.LT, srcIteratorName.makeIdent(), // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "length")), make().Block(0, List.<JCStatement>of(makeVar(iteratorResultName, make().Type(syms().objectType), indexed), make().Return(transformedElement))), make().Return(makeFinished()))));
l = List.of(srcIndex, nextMdb.build());
} else {
return makeErroneous(expr, "unhandled iterable type");
}
// new AbstractIterator()
JCNewClass iteratorClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIteratorType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType)), make().AnonymousClassDef(make().Modifiers(0), l));
MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
iteratorMdb.isOverride(true);
iteratorMdb.annotationFlags(Annotations.IGNORE);
iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
iteratorMdb.resultType(new TransformedType(makeJavaType(typeFact().getIteratorType(resultElementType)), makeAtNonNull()));
iteratorMdb.body(make().Return(iteratorClass));
// new AbstractIterable()
iterableClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIterableType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT), makeJavaType(resultAbsentType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType), makeReifiedTypeArgument(resultAbsentType)), make().AnonymousClassDef(make().Modifiers(0), List.<JCTree>of(iteratorMdb.build())));
} finally {
expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
}
if (aliasArguments) {
letStmts = letStmts.appendList(((InvocationTermTransformer) transformer).callBuilder.getStatements());
}
JCMethodInvocation result = make().Apply(null, naming.makeQualIdent(iterableClass, "sequence"), List.<JCExpression>nil());
JCExpression spread = letStmts.isEmpty() ? result : make().LetExpr(letStmts.toList(), result);
// Do we *statically* know the result must be a Sequence
final boolean primaryIsSequence = typeFact().isNonemptyIterableType(expr.getPrimary().getTypeModel());
Type returnElementType = expr.getTarget().getType();
if (primaryIsSequence) {
int flags = EXPR_DOWN_CAST;
spread = applyErasureAndBoxing(spread, typeFact().getSequentialType(returnElementType), false, true, BoxingStrategy.BOXED, primaryIsSequence ? typeFact().getSequenceType(returnElementType) : typeFact().getSequentialType(returnElementType), flags);
}
return spread;
} finally {
spreading = oldSpreading;
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ClassTransformer method concreteMembersFromSuperinterfaces.
/**
* Generates companion fields ($Foo$impl) and methods
*/
private void concreteMembersFromSuperinterfaces(final Class model, ClassDefinitionBuilder classBuilder, Type satisfiedType, Set<Interface> satisfiedInterfaces) {
satisfiedType = satisfiedType.resolveAliases();
Interface iface = (Interface) satisfiedType.getDeclaration();
if (satisfiedInterfaces.contains(iface) || iface.isIdentifiable()) {
return;
}
// then don't instantiate it...
if (hasImpl(iface)) {
// ... otherwise for each satisfied interface,
// instantiate an instance of the
// companion class in the constructor and assign it to a
// $Interface$impl field
transformInstantiateCompanions(classBuilder, model, iface, satisfiedType);
}
if (!ModelUtil.isCeylonDeclaration(iface)) {
// let's not try to implement CMI for Java interfaces
return;
}
// For each super interface
for (Declaration member : sortedMembers(iface.getMembers())) {
if (member instanceof Class) {
Class klass = (Class) member;
final Type typedMember = satisfiedType.getTypeMember(klass, Collections.<Type>emptyList());
if (Strategy.generateInstantiator(member) && !klass.hasConstructors() && !model.isFormal() && needsCompanionDelegate(model, typedMember) && model.getDirectMember(member.getName(), null, false) == null) {
// instantiator method implementation
generateInstantiatorDelegate(classBuilder, satisfiedType, iface, klass, null, model.getType(), !member.isFormal());
}
if (klass.hasConstructors()) {
for (Declaration m : klass.getMembers()) {
if (m instanceof Constructor && Strategy.generateInstantiator(m)) {
Constructor ctor = (Constructor) m;
generateInstantiatorDelegate(classBuilder, satisfiedType, iface, klass, ctor, model.getType(), true);
}
}
}
}
// type aliases are on the $impl class
if (member instanceof TypeAlias)
continue;
if (Strategy.onlyOnCompanion(member)) {
// (they're just private methods on the $impl)
continue;
}
if (member instanceof Function) {
Function method = (Function) member;
final TypedReference typedMember = satisfiedType.getTypedMember(method, typesOfTypeParameters(method.getTypeParameters()));
Declaration sub = (Declaration) model.getMember(method.getName(), getSignatureIfRequired(typedMember), false, true);
if (sub instanceof Function) /* && !sub.isAbstraction()*/
{
Function subMethod = (Function) sub;
if (subMethod.getParameterLists().isEmpty()) {
continue;
}
java.util.List<java.util.List<Type>> producedTypeParameterBounds = producedTypeParameterBounds(typedMember, subMethod);
// final TypedReference refinedTypedMember = model.getType().getTypedMember(subMethod, Collections.<Type>emptyList());
final java.util.List<TypeParameter> typeParameters = subMethod.getTypeParameters();
final java.util.List<Parameter> parameters = subMethod.getFirstParameterList().getParameters();
boolean hasOverloads = false;
if (!satisfiedInterfaces.contains((Interface) method.getContainer())) {
for (Parameter param : parameters) {
if (Strategy.hasDefaultParameterValueMethod(param) && CodegenUtil.getTopmostRefinedDeclaration(param.getModel()).getContainer().equals(member)) {
final TypedReference typedParameter = typedMember.getTypedParameter(param);
// If that method has a defaulted parameter,
// we need to generate a default value method
// which also delegates to the $impl
final MethodDefinitionBuilder defaultValueDelegate = makeDelegateToCompanion(iface, typedMember, model.getType(), modifierTransformation().defaultValueMethodBridge(), typeParameters, producedTypeParameterBounds, typedParameter.getFullType(), Naming.getDefaultedParamMethodName(method, param), parameters.subList(0, parameters.indexOf(param)), param.getModel().getTypeErased(), null, param);
classBuilder.method(defaultValueDelegate);
}
if (Strategy.hasDefaultParameterOverload(param)) {
if ((method.isDefault() || method.isShared() && !method.isFormal()) && Decl.equal(method, subMethod)) {
MethodDefinitionBuilder overload = new DefaultedArgumentMethodTyped(new DaoThis((Tree.AnyMethod) null, null), MethodDefinitionBuilder.method(this, subMethod), typedMember, true).makeOverload(subMethod.getFirstParameterList(), param, typeParameters);
classBuilder.method(overload);
}
hasOverloads = true;
}
}
}
// delegating to the $impl instance
if (needsCompanionDelegate(model, typedMember)) {
final MethodDefinitionBuilder concreteMemberDelegate = makeDelegateToCompanion(iface, typedMember, model.getType(), modifierTransformation().methodBridge(method), typeParameters, producedTypeParameterBounds, typedMember.getType(), naming.selector(method), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), null, null);
classBuilder.method(concreteMemberDelegate);
}
if (hasOverloads && (method.isDefault() || method.isShared() && !method.isFormal()) && Decl.equal(method, subMethod)) {
final MethodDefinitionBuilder canonicalMethod = makeDelegateToCompanion(iface, typedMember, model.getType(), modifierTransformation().canonicalMethodBridge(), subMethod.getTypeParameters(), producedTypeParameterBounds, typedMember.getType(), Naming.selector(method, Naming.NA_CANONICAL_METHOD), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), naming.selector(method), null);
classBuilder.method(canonicalMethod);
}
}
} else if (member instanceof Value || member instanceof Setter) {
TypedDeclaration attr = (TypedDeclaration) member;
final TypedReference typedMember = satisfiedType.getTypedMember(attr, null);
if (needsCompanionDelegate(model, typedMember)) {
Setter setter = (member instanceof Setter) ? (Setter) member : null;
if (member instanceof Value) {
Value getter = (Value) member;
if (member instanceof JavaBeanValue) {
setter = ((Value) member).getSetter();
}
final MethodDefinitionBuilder getterDelegate = makeDelegateToCompanion(iface, typedMember, model.getType(), modifierTransformation().getterBridge(getter), Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typedMember.getType(), Naming.getGetterName(getter), Collections.<Parameter>emptyList(), getter.getTypeErased(), null, null);
classBuilder.method(getterDelegate);
}
if (setter != null) {
final MethodDefinitionBuilder setterDelegate = makeDelegateToCompanion(iface, satisfiedType.getTypedMember(setter, null), model.getType(), modifierTransformation().setterBridge(setter), Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typeFact().getAnythingType(), Naming.getSetterName(attr), Collections.<Parameter>singletonList(setter.getParameter()), setter.getTypeErased(), null, null);
classBuilder.method(setterDelegate);
}
if (Decl.isValue(member) && ((Value) attr).isVariable()) {
// $impl to delegate to
throw new BugException("assertion failed: " + member.getQualifiedNameString() + " was unexpectedly a variable value");
}
}
} else {
Reference typedMember = member instanceof TypeDeclaration ? satisfiedType.getTypeMember((TypeDeclaration) member, Collections.<Type>emptyList()) : satisfiedType.getTypedMember((TypedDeclaration) member, Collections.<Type>emptyList());
if (needsCompanionDelegate(model, typedMember)) {
throw new BugException("unhandled concrete interface member " + member.getQualifiedNameString() + " " + member.getClass());
}
}
}
// Add $impl instances for the whole interface hierarchy
satisfiedInterfaces.add(iface);
for (Type sat : iface.getSatisfiedTypes()) {
sat = model.getType().getSupertype(sat.getDeclaration());
concreteMembersFromSuperinterfaces(model, classBuilder, sat, satisfiedInterfaces);
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ClassTransformer method transform.
List<MethodDefinitionBuilder> transform(Tree.AnyMethod def, ClassDefinitionBuilder classBuilder, List<JCStatement> body) {
final Function model = def.getDeclarationModel();
List<MethodDefinitionBuilder> result = List.<MethodDefinitionBuilder>nil();
if (!model.isInterfaceMember() || model.isStatic()) {
// Transform to the class
TypedDeclaration rd = (TypedDeclaration) model.getRefinedDeclaration();
boolean refinedResultType = !model.getType().isExactly(rd.getType());
result = transformMethod(def, true, true, true, transformMplBodyUnlessSpecifier(def, model, body), refinedResultType && !rd.isInterfaceMember() ? new DaoSuper() : new DaoThis(def, def.getParameterLists().get(0)), !Strategy.defaultParameterMethodOnSelf(model) && !Strategy.defaultParameterMethodStatic(model));
} else {
// Is within interface
// Transform the definition to the companion class, how depends
// on what kind of method it is
List<MethodDefinitionBuilder> companionDefs;
if (def instanceof Tree.MethodDeclaration) {
final SpecifierExpression specifier = ((Tree.MethodDeclaration) def).getSpecifierExpression();
if (specifier == null) {
// formal or abstract
// (still need overloads and DPMs on the companion)
companionDefs = transformMethod(def, false, true, true, null, new DaoCompanion(def, def.getParameterLists().get(0)), false);
} else {
companionDefs = transformMethod(def, true, false, !model.isShared(), transformMplBodyUnlessSpecifier(def, model, body), new DaoCompanion(def, def.getParameterLists().get(0)), false);
}
} else if (def instanceof Tree.MethodDefinition) {
companionDefs = transformMethod(def, true, false, !model.isShared(), transformMplBodyUnlessSpecifier(def, model, body), new DaoCompanion(def, def.getParameterLists().get(0)), false);
} else {
throw BugException.unhandledNodeCase(def);
}
if (!companionDefs.isEmpty())
classBuilder.getCompanionBuilder((TypeDeclaration) model.getContainer()).methods(companionDefs);
// but only if it's shared and not java native
if (model.isShared() && !model.isJavaNative()) {
result = transformMethod(def, true, true, true, null, daoAbstract, !Strategy.defaultParameterMethodOnSelf(model));
}
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ClassTransformer method transformMethod.
private List<MethodDefinitionBuilder> transformMethod(final Function methodModel, Tree.TypeParameterList typeParameterList, Tree.AnyMethod node, java.util.List<Tree.ParameterList> parameterLists, Tree.Declaration annotated, boolean transformMethod, boolean actual, boolean includeAnnotations, List<JCStatement> body, DaoBody daoTransformation, boolean defaultValuesBody) {
ListBuffer<MethodDefinitionBuilder> lb = new ListBuffer<MethodDefinitionBuilder>();
Declaration refinedDeclaration = methodModel.getRefinedDeclaration();
final MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.method(this, methodModel);
// do the reified type param arguments
if (AbstractTransformer.supportsReified(methodModel)) {
methodBuilder.reifiedTypeParameters(Strategy.getEffectiveTypeParameters(methodModel));
}
if (methodModel.getParameterLists().size() > 1) {
methodBuilder.mpl(methodModel.getParameterLists());
}
boolean hasOverloads = false;
Tree.ParameterList parameterList = parameterLists.get(0);
int flags = 0;
if (rawParameters(methodModel)) {
flags |= JT_RAW;
}
for (final Tree.Parameter parameter : parameterList.getParameters()) {
Parameter parameterModel = parameter.getParameterModel();
List<JCAnnotation> annotations = null;
if (includeAnnotations) {
Tree.TypedDeclaration typedDeclaration = Decl.getMemberDeclaration(annotated, parameter);
// f = function(Integer param) => 2;
if (typedDeclaration != null)
annotations = expressionGen().transformAnnotations(OutputElement.PARAMETER, typedDeclaration);
}
// methodModel.getTypedReference().getTypedParameter(parameterModel).getType()
// parameterModel.getModel().getTypedReference().getType()
methodBuilder.parameter(parameter, parameterModel, annotations, flags, WideningRules.CAN_WIDEN);
if (Strategy.hasDefaultParameterValueMethod(parameterModel) || Strategy.hasDefaultParameterOverload(parameterModel)) {
if (Decl.equal(refinedDeclaration, methodModel) || (!methodModel.isInterfaceMember() && body != null) || methodModel.isInterfaceMember() && daoTransformation instanceof DaoCompanion == false) {
if (daoTransformation != null && (daoTransformation instanceof DaoCompanion == false || body != null)) {
DaoBody daoTrans = (body == null && !methodModel.isJavaNative()) ? daoAbstract : new DaoThis(node, parameterList);
MethodDefinitionBuilder overloadedMethod = new DefaultedArgumentMethod(daoTrans, MethodDefinitionBuilder.method(this, methodModel), methodModel).makeOverload(parameterList.getModel(), parameter.getParameterModel(), Strategy.getEffectiveTypeParameters(methodModel));
overloadedMethod.location(null);
lb.append(overloadedMethod);
}
if (Decl.equal(refinedDeclaration, methodModel) && Strategy.hasDefaultParameterValueMethod(parameterModel)) {
lb.append(makeParamDefaultValueMethod(defaultValuesBody, methodModel, parameterList, parameter));
}
}
hasOverloads = true;
}
}
// Determine if we need to generate a "canonical" method
boolean createCanonical = hasOverloads && methodModel.isClassOrInterfaceMember() && (body != null || methodModel.isJavaNative());
if (createCanonical) {
// Creates the private "canonical" method containing the actual body
MethodDefinitionBuilder canonicalMethod = new CanonicalMethod(daoTransformation, methodModel, body).makeOverload(parameterList.getModel(), null, Strategy.getEffectiveTypeParameters(methodModel));
lb.append(canonicalMethod);
}
if (transformMethod) {
methodBuilder.modifiers(modifierTransformation().method(methodModel) | (methodModel.isJavaNative() && !createCanonical ? Flags.NATIVE : 0));
if (actual) {
methodBuilder.isOverride(methodModel.isActual());
}
if (includeAnnotations) {
methodBuilder.userAnnotations(expressionGen().transformAnnotations(OutputElement.METHOD, annotated));
methodBuilder.modelAnnotations(methodModel.getAnnotations());
if (!methodModel.isDefault() && isEe(methodModel)) {
methodBuilder.modelAnnotations(makeAtFinal());
}
} else {
methodBuilder.ignoreModelAnnotations();
}
methodBuilder.resultType(methodModel, 0);
copyTypeParameters(methodModel, methodBuilder);
if (createCanonical) {
// Creates method that redirects to the "canonical" method containing the actual body
MethodDefinitionBuilder overloadedMethod = new CanonicalMethod(new DaoThis(node, parameterList), methodBuilder, methodModel).makeOverload(parameterList.getModel(), null, Strategy.getEffectiveTypeParameters(methodModel));
lb.append(overloadedMethod);
} else {
if (body != null) {
// Construct the outermost method using the body we've built so far
methodBuilder.body(body);
} else {
methodBuilder.noBody();
}
lb.append(methodBuilder);
}
}
return lb.toList();
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ClassTransformer method makeAttributeForValueParameter.
private void makeAttributeForValueParameter(ClassDefinitionBuilder classBuilder, Tree.Parameter parameterTree, Tree.TypedDeclaration memberTree) {
Parameter decl = parameterTree.getParameterModel();
if (!(decl.getModel() instanceof Value)) {
return;
}
final Value value = (Value) decl.getModel();
if (decl.getDeclaration() instanceof Constructor) {
classBuilder.field(PUBLIC | FINAL, decl.getName(), makeJavaType(decl.getType()), null, false, expressionGen().transformAnnotations(OutputElement.FIELD, memberTree));
classBuilder.getInitBuilder().init(make().Exec(make().Assign(naming.makeQualIdent(naming.makeThis(), decl.getName()), naming.makeName(value, Naming.NA_IDENT))));
} else if (parameterTree instanceof Tree.ValueParameterDeclaration && ModelUtil.isCaptured(value)) {
makeFieldForParameter(classBuilder, decl, memberTree);
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.getter(this, decl.getName(), decl.getModel());
adb.modifiers(classGen().modifierTransformation().getterSetter(decl.getModel(), false));
adb.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, memberTree));
classBuilder.attribute(adb);
if (value.isVariable()) {
AttributeDefinitionBuilder setter = AttributeDefinitionBuilder.setter(this, parameterTree, decl.getName(), decl.getModel());
setter.modifiers(classGen().modifierTransformation().getterSetter(decl.getModel(), false));
// setter.userAnnotations(expressionGen().transform(AnnotationTarget.SETTER, memberTree.getAnnotationList()));
classBuilder.attribute(setter);
}
} else if (decl.isHidden() && // TODO Isn't this always true here? We know this is a parameter to a Class
(decl.getDeclaration() instanceof TypeDeclaration)) {
Declaration member = CodegenUtil.findMethodOrValueForParam(decl);
if (Strategy.createField(decl, (Value) member)) {
// The field itself is created by when we transform the AttributeDeclaration
// but it has to be initialized here so all the fields are initialized in parameter order
at(parameterTree);
JCExpression parameterExpr = makeUnquotedIdent(Naming.getAliasedParameterName(decl));
TypedReference typedRef = getTypedReference(value);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type paramType = nonWideningType(typedRef, nonWideningTypedRef);
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.field(this, memberTree, value.getName(), value, false);
if (!paramType.isExactly(decl.getType())) {
// The parameter type follows normal erasure rules, not affected by inheritance
// but the attribute respects non-widening rules, so we may need to cast
// the parameter to the field type (see #1728)
parameterExpr = make().TypeCast(adb.valueFieldType(), parameterExpr);
}
at(parameterTree);
BoxingStrategy exprBoxed = CodegenUtil.isUnBoxed((TypedDeclaration) member) ? BoxingStrategy.UNBOXED : BoxingStrategy.BOXED;
adb.initialValue(parameterExpr, exprBoxed);
classBuilder.getInitBuilder().init(adb.buildInit(true));
}
}
}
Aggregations