use of org.eclipse.ceylon.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class MethodDefinitionBuilder method resultType.
public MethodDefinitionBuilder resultType(Function method, int flags) {
if (method.isParameter()) {
if (Decl.isUnboxedVoid(method) && !Strategy.useBoxedVoid(method)) {
return resultType(new TransformedType(gen.make().Type(gen.syms().voidType), gen.makeJavaTypeAnnotations(method, false), gen.makeNullabilityAnnotations(method)));
} else {
Parameter parameter = method.getInitializerParameter();
Type resultType = parameter.getType();
for (int ii = 1; ii < method.getParameterLists().size(); ii++) {
resultType = gen.typeFact().getCallableType(resultType);
}
return resultType(gen.makeJavaType(resultType, CodegenUtil.isUnBoxed(method) ? 0 : AbstractTransformer.JT_NO_PRIMITIVES), method);
}
}
TypedReference typedRef = gen.getTypedReference(method);
TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
Type nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef);
if (method.isActual() && CodegenUtil.hasTypeErased(method))
flags |= AbstractTransformer.JT_RAW;
if (method.isShortcutRefinement() && Decl.isSmall(method.getRefinedDeclaration())) {
flags |= AbstractTransformer.JT_SMALL;
}
return resultType(makeResultType(nonWideningTypedRef.getDeclaration(), nonWideningType, flags), method);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class ExpressionTransformer method transform.
JCExpression transform(Tree.FunctionArgument functionArg) {
Function model = functionArg.getDeclarationModel();
TypedReference functionalInterface = gen().checkForFunctionalInterface(expectedType);
int flags = 0;
// even if we are a Callable<X>, if the FI returns void don't check for non-null return types
if (functionalInterface != null && Decl.isUnboxedVoid(functionalInterface.getDeclaration()))
flags |= EXPR_TARGET_ACCEPTS_NULL;
List<JCStatement> body;
boolean prevNoExpressionlessReturn = statementGen().noExpressionlessReturn;
boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
Function prevCoercedFunctionalInterfaceNeedsNoNullChecks = expressionGen().coercedFunctionalInterfaceNeedsNoNullChecks;
try {
statementGen().noExpressionlessReturn = isAnything(model.getType());
expressionGen().coercedFunctionalInterfaceNeedsNoNullChecks = (flags & EXPR_TARGET_ACCEPTS_NULL) != 0 ? model : null;
if (functionArg.getBlock() != null) {
body = statementGen().transformBlock(functionArg.getBlock());
if (!functionArg.getBlock().getDefinitelyReturns()) {
if (isAnything(model.getType())) {
body = body.append(make().Return(makeNull()));
} else {
body = body.append(make().Return(makeErroneous(functionArg.getBlock(), "compiler bug: non-void method does not definitely return")));
}
}
} else {
Tree.Expression expr = functionArg.getExpression();
JCExpression transExpr = expressionGen().transformExpression(expr, flags);
JCReturn returnStat = make().Return(transExpr);
body = List.<JCStatement>of(returnStat);
}
} finally {
expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
expressionGen().coercedFunctionalInterfaceNeedsNoNullChecks = prevCoercedFunctionalInterfaceNeedsNoNullChecks;
statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
}
Type callableType = functionArg.getTypeModel();
CallableBuilder callableBuilder = CallableBuilder.methodArgument(gen(), functionArg, model, callableType, Collections.singletonList(functionArg.getParameterLists().get(0)), classGen().transformMplBody(functionArg.getParameterLists(), model, body));
callableBuilder.checkForFunctionalInterface(expectedType);
JCExpression result = callableBuilder.build();
result = applyErasureAndBoxing(result, callableType, true, BoxingStrategy.BOXED, expectedType);
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedReference 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.TypedReference 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));
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedReference in project ceylon by eclipse.
the class ClassTransformer method addAmbiguousMember.
private void addAmbiguousMember(ClassDefinitionBuilder classBuilder, Interface model, String name) {
Declaration member = model.getMember(name, null, false);
Type satisfiedType = model.getType().getSupertype(model);
if (member instanceof Class) {
Class klass = (Class) member;
if (Strategy.generateInstantiator(member) && !klass.hasConstructors()) {
// instantiator method implementation
generateInstantiatorDelegate(classBuilder, satisfiedType, model, klass, null, model.getType(), false);
}
if (klass.hasConstructors()) {
for (Declaration m : klass.getMembers()) {
if (m instanceof Constructor && Strategy.generateInstantiator(m)) {
Constructor ctor = (Constructor) m;
generateInstantiatorDelegate(classBuilder, satisfiedType, model, klass, ctor, model.getType(), false);
}
}
}
} else if (member instanceof Function) {
Function method = (Function) member;
final TypedReference typedMember = satisfiedType.getTypedMember(method, Collections.<Type>emptyList());
java.util.List<java.util.List<Type>> producedTypeParameterBounds = producedTypeParameterBounds(typedMember, method);
final java.util.List<TypeParameter> typeParameters = method.getTypeParameters();
final java.util.List<Parameter> parameters = method.getFirstParameterList().getParameters();
for (Parameter param : parameters) {
if (Strategy.hasDefaultParameterOverload(param)) {
MethodDefinitionBuilder overload = new DefaultedArgumentMethodTyped(null, MethodDefinitionBuilder.method(this, method), typedMember, true).makeOverload(method.getFirstParameterList(), param, typeParameters);
overload.modifiers(PUBLIC | ABSTRACT);
classBuilder.method(overload);
}
}
final MethodDefinitionBuilder concreteMemberDelegate = makeDelegateToCompanion(null, typedMember, model.getType(), PUBLIC | ABSTRACT, method.getTypeParameters(), producedTypeParameterBounds, typedMember.getType(), naming.selector(method), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), null, null, false);
classBuilder.method(concreteMemberDelegate);
} else if (member instanceof Value || member instanceof Setter) {
TypedDeclaration attr = (TypedDeclaration) member;
final TypedReference typedMember = satisfiedType.getTypedMember(attr, Collections.<Type>emptyList());
if (member instanceof Value) {
final MethodDefinitionBuilder getterDelegate = makeDelegateToCompanion(null, typedMember, model.getType(), PUBLIC | ABSTRACT, Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typedMember.getType(), Naming.getGetterName(attr), Collections.<Parameter>emptyList(), attr.getTypeErased(), null, null, false);
classBuilder.method(getterDelegate);
}
if (member instanceof Setter) {
final MethodDefinitionBuilder setterDelegate = makeDelegateToCompanion(null, typedMember, model.getType(), PUBLIC | ABSTRACT, Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typeFact().getAnythingType(), Naming.getSetterName(attr), Collections.<Parameter>singletonList(((Setter) member).getParameter()), ((Setter) member).getTypeErased(), null, null, false);
classBuilder.method(setterDelegate);
}
}
}
Aggregations