use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method walkSatisfiedInterfacesInternal.
private void walkSatisfiedInterfacesInternal(final Class model, Type type, Class via, SatisfactionVisitor visitor, Set<Interface> satisfiedInterfaces) {
type = type.resolveAliases();
Type ext = type.getExtendedType();
if (ext != null) {
// recurse up this extended class
walkSatisfiedInterfacesInternal(model, ext, (Class) ext.getDeclaration(), visitor, satisfiedInterfaces);
}
for (Type sat : type.getSatisfiedTypes()) {
Interface iface = (Interface) sat.getDeclaration();
if (iface.getType().isExactly(typeFact().getIdentifiableDeclaration().getType())) {
return;
}
// recurse up this satisfies interface
walkSatisfiedInterfacesInternal(model, sat, via, visitor, satisfiedInterfaces);
boolean alreadySatisfied = !satisfiedInterfaces.add((Interface) model.getType().getSupertype(iface).getDeclaration());
if (via != null) {
visitor.satisfiesIndirectlyViaClass(model, iface, via, alreadySatisfied);
} else if (model.getType().equals(type)) {
visitor.satisfiesDirectly(model, iface, alreadySatisfied);
} else {
visitor.satisfiesIndirectly(model, iface, alreadySatisfied);
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method transformClassOrCtorParameters.
private void transformClassOrCtorParameters(Tree.AnyClass def, Class cls, Constructor constructor, Tree.Declaration node, Tree.ParameterList paramList, boolean delegationConstructor, ClassDefinitionBuilder classBuilder, ParameterizedBuilder<?> constructorBuilder, boolean generateInstantiator, ClassDefinitionBuilder instantiatorDeclCb, ClassDefinitionBuilder instantiatorImplCb) {
for (final Tree.Parameter param : paramList.getParameters()) {
// Overloaded instantiators
Parameter paramModel = param.getParameterModel();
Parameter refinedParam = CodegenUtil.findParamForDecl((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(param.getParameterModel().getModel()));
at(param);
Tree.TypedDeclaration member = def != null ? Decl.getMemberDeclaration(def, param) : null;
// transform the parameter and its annotations
transformParameter(constructorBuilder, param, paramModel, member);
if (Strategy.hasDefaultParameterValueMethod(paramModel) || Strategy.hasDefaultParameterOverload(paramModel) || (generateInstantiator && refinedParam != null && (Strategy.hasDefaultParameterValueMethod(refinedParam) || Strategy.hasDefaultParameterOverload(refinedParam)))) {
ClassDefinitionBuilder cbForDevaultValues;
ClassDefinitionBuilder cbForDevaultValuesDecls = null;
switch(Strategy.defaultParameterMethodOwner(constructor != null ? constructor : cls)) {
case STATIC:
cbForDevaultValues = classBuilder;
break;
case OUTER:
cbForDevaultValues = classBuilder.getContainingClassBuilder();
break;
case OUTER_COMPANION:
cbForDevaultValues = classBuilder.getContainingClassBuilder().getCompanionBuilder(Decl.getClassOrInterfaceContainer(cls, true));
if ((constructor == null || constructor.isShared()) && cls.isShared()) {
cbForDevaultValuesDecls = classBuilder.getContainingClassBuilder();
}
break;
default:
cbForDevaultValues = classBuilder.getCompanionBuilder(cls);
}
if (!delegationConstructor) {
if ((Strategy.hasDefaultParameterValueMethod(paramModel) || (refinedParam != null && Strategy.hasDefaultParameterValueMethod(refinedParam)))) {
if (!generateInstantiator || Decl.equal(refinedParam, paramModel)) {
// transform the default value into a method
cbForDevaultValues.method(makeParamDefaultValueMethod(false, constructor != null ? constructor : cls, paramList, param));
if (cbForDevaultValuesDecls != null) {
cbForDevaultValuesDecls.method(makeParamDefaultValueMethod(true, constructor != null ? constructor : cls, paramList, param));
}
} else if (Strategy.hasDelegatedDpm(cls) && cls.getContainer() instanceof Class) {
// generate a dpm which delegates to the companion
java.util.List<Parameter> parameters = paramList.getModel().getParameters();
MethodDefinitionBuilder mdb = makeDelegateToCompanion((Interface) cls.getRefinedDeclaration().getContainer(), paramModel.getModel().appliedTypedReference(cls.getType(), null), ((TypeDeclaration) cls.getContainer()).getType(), FINAL | (transformClassDeclFlags(cls) & ~ABSTRACT), List.<TypeParameter>nil(), Collections.<java.util.List<Type>>emptyList(), paramModel.getType().getFullType(), Naming.getDefaultedParamMethodName(cls, paramModel), parameters.subList(0, parameters.indexOf(paramModel)), false, Naming.getDefaultedParamMethodName(cls, paramModel), DelegateType.FOR_DEFAULT_VALUE);
cbForDevaultValues.method(mdb);
}
}
}
boolean addOverloadedConstructor = false;
if (generateInstantiator) {
if (Decl.withinInterface(cls)) {
MethodDefinitionBuilder instBuilder = new DefaultedArgumentInstantiator(daoAbstract, cls, constructor, instantiatorDeclCb.isCompanionBuilder()).makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
instantiatorDeclCb.method(instBuilder);
}
if (!Decl.withinInterface(cls) || !cls.isFormal()) {
MethodDefinitionBuilder instBuilder = new DefaultedArgumentInstantiator(new DaoThis(node, paramList), cls, constructor, instantiatorImplCb.isCompanionBuilder()).makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
instantiatorImplCb.method(instBuilder);
} else {
addOverloadedConstructor = true;
}
} else {
addOverloadedConstructor = true;
}
if (addOverloadedConstructor) {
// Add overloaded constructors for defaulted parameter
MethodDefinitionBuilder overloadBuilder;
DefaultedArgumentConstructor dac;
if (constructor != null) {
dac = new DefaultedArgumentConstructor(classBuilder.addConstructor(), constructor, node, paramList, delegationConstructor);
} else {
dac = new DefaultedArgumentConstructor(classBuilder.addConstructor(), cls, node, paramList, delegationConstructor);
}
overloadBuilder = dac.makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
}
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
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.getType().isExactly(typeFact().getIdentifiableDeclaration().getType())) {
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 (!Decl.isCeylon(iface)) {
// let's not try to implement CMI for Java interfaces
return;
}
// For each super interface
for (Declaration member : 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, Collections.<Type>emptyList());
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, typedParameter, model.getType(), PUBLIC | FINAL, typeParameters, producedTypeParameterBounds, typedParameter.getFullType(), Naming.getDefaultedParamMethodName(method, param), parameters.subList(0, parameters.indexOf(param)), param.getModel().getTypeErased(), null, DelegateType.FOR_DEFAULT_VALUE);
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(), PUBLIC | (method.isDefault() ? 0 : FINAL), typeParameters, producedTypeParameterBounds, typedMember.getType(), naming.selector(method), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), null, DelegateType.OTHER);
classBuilder.method(concreteMemberDelegate);
}
if (hasOverloads && (method.isDefault() || method.isShared() && !method.isFormal()) && Decl.equal(method, subMethod)) {
final MethodDefinitionBuilder canonicalMethod = makeDelegateToCompanion(iface, typedMember, model.getType(), PRIVATE, subMethod.getTypeParameters(), producedTypeParameterBounds, typedMember.getType(), Naming.selector(method, Naming.NA_CANONICAL_METHOD), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), naming.selector(method), DelegateType.OTHER);
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) {
if (member instanceof JavaBeanValue) {
setter = ((Value) member).getSetter();
}
final MethodDefinitionBuilder getterDelegate = makeDelegateToCompanion(iface, typedMember, model.getType(), PUBLIC | (attr.isDefault() ? 0 : FINAL), Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typedMember.getType(), Naming.getGetterName(attr), Collections.<Parameter>emptyList(), attr.getTypeErased(), null, DelegateType.OTHER);
classBuilder.method(getterDelegate);
}
if (setter != null) {
final MethodDefinitionBuilder setterDelegate = makeDelegateToCompanion(iface, satisfiedType.getTypedMember(setter, null), model.getType(), PUBLIC | (setter.getGetter().isDefault() ? 0 : FINAL), Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typeFact().getAnythingType(), Naming.getSetterName(attr), Collections.<Parameter>singletonList(setter.getParameter()), setter.getTypeErased(), null, DelegateType.OTHER);
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 com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ExpressionTransformer method makeQualifiedDollarThis.
private JCExpression makeQualifiedDollarThis(Tree.BaseMemberExpression expr) {
Declaration decl = expr.getDeclaration();
Interface interf = (Interface) Decl.getClassOrInterfaceContainer(decl);
// find the target container interface that is or satisfies the given interface
Scope scope = expr.getScope();
boolean needsQualified = false;
while (scope != null) {
if (scope instanceof Interface) {
if (Decl.equalScopeDecl(scope, interf) || ((Interface) scope).inherits(interf)) {
break;
}
// we only need to qualify it if we're aiming for a $this of an outer interface than the interface we are caught in
needsQualified = true;
}
scope = scope.getContainer();
}
if (!needsQualified)
return naming.makeQuotedThis();
interf = (Interface) scope;
return makeQualifiedDollarThis(interf.getType());
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ExpressionTransformer method addThisOrObjectQualifierIfRequired.
/**
* We may need to force a qualified this prefix (direct or outer) in the following cases:
*
* - Required because of mixin inheritance with different type arguments (the same is already
* done for qualified references, but not for direct references)
* - The compiler generates anonymous local classes for things like
* Callables and Comprehensions. When referring to a member foo
* within one of those things we need a qualified {@code this}
* to ensure we're accessing the outer instances member, not
* a member of the anonymous local class that happens to have the same name.
*/
private JCExpression addThisOrObjectQualifierIfRequired(JCExpression qualExpr, Tree.StaticMemberOrTypeExpression expr, Declaration decl) {
if (qualExpr == null && // statics are not members that can be inherited
!decl.isStaticallyImportable() && !Decl.isConstructor(decl) && decl.isMember() && // and have a name mapping)
expr.getTarget().getDeclaration() == decl && !Decl.isLocalToInitializer(decl) && !isWithinSuperInvocation()) {
// First check whether the expression is captured from an enclosing scope
TypeDeclaration outer = null;
// get the ClassOrInterface container of the declaration
Scope stop = Decl.getClassOrInterfaceContainer(decl, false);
if (stop instanceof TypeDeclaration) {
// reified scope
Scope scope = expr.getScope();
while (!(scope instanceof Package)) {
if (scope.equals(stop)) {
outer = (TypeDeclaration) stop;
break;
}
scope = scope.getContainer();
}
}
// If not it might be inherited...
if (outer == null) {
outer = expr.getScope().getInheritingDeclaration(decl);
}
if (outer != null) {
Type targetType = expr.getTarget().getQualifyingType();
Type declarationContainerType = ((TypeDeclaration) outer).getType();
// check if we need a variance cast
VarianceCastResult varianceCastResult = getVarianceCastResult(targetType, declarationContainerType);
// if we are within a comprehension body, or if we need a variance cast
if (isWithinSyntheticClassBody() || varianceCastResult != null) {
if (decl.isShared() && outer instanceof Interface) {
// always prefer qualified
qualExpr = makeQualifiedDollarThis(declarationContainerType);
} else {
// Class or companion class,
qualExpr = naming.makeQualifiedThis(makeJavaType(((TypeDeclaration) outer).getType(), JT_RAW | (outer instanceof Interface ? JT_COMPANION : 0)));
}
// add the variance cast if required
if (varianceCastResult != null) {
qualExpr = applyVarianceCasts(qualExpr, targetType, varianceCastResult, 0);
}
}
} else if (decl.isClassMember() && ((Class) decl.getContainer()).isAnonymous() && ((Class) decl.getContainer()).isToplevel()) {
Class container = (Class) decl.getContainer();
Value value = (Value) ((Package) container.getContainer()).getMember(container.getName(), null, false);
qualExpr = make().Apply(null, naming.makeName(value, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER), List.<JCExpression>nil());
} else if (decl.isMember() && !expr.getStaticMethodReference()) {
throw new BugException(expr, decl.getQualifiedNameString() + " was unexpectedly a member");
}
}
return qualExpr;
}
Aggregations