use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method addAtMembers.
private void addAtMembers(ClassDefinitionBuilder classBuilder, ClassOrInterface model, Tree.ClassOrInterface def) {
List<JCExpression> members = List.nil();
for (Declaration member : model.getMembers()) {
if (member instanceof ClassOrInterface == false && member instanceof TypeAlias == false) {
continue;
}
TypeDeclaration innerType = (TypeDeclaration) member;
Tree.Declaration innerTypeTree = findInnerType(def, innerType.getName());
if (innerTypeTree != null) {
TransformationPlan plan = errors().hasDeclarationAndMarkBrokenness(innerTypeTree);
if (plan instanceof Drop) {
continue;
}
}
if (innerType.isAlias() && innerTypeTree != null && Decl.isAncestorLocal(innerTypeTree))
// for the same reason we do not generate aliases in transform(ClassOrInterface def) let's not list them
continue;
JCAnnotation atMember;
// interfaces are moved to toplevel so they can lose visibility of member types if they are local
if (Decl.isLocal(model) && model instanceof Interface)
atMember = makeAtMember(innerType.getName());
else
atMember = makeAtMember(innerType.getType());
members = members.prepend(atMember);
}
classBuilder.annotations(makeAtMembers(members));
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method addAmbiguousMembers.
private void addAmbiguousMembers(ClassDefinitionBuilder classBuilder, Interface model) {
// only if we refine more than one interface
java.util.List<Type> satisfiedTypes = model.getSatisfiedTypes();
if (satisfiedTypes.size() <= 1)
return;
Set<Interface> satisfiedInterfaces = new HashSet<Interface>();
for (Type interfaceDecl : model.getSatisfiedTypes()) {
collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
}
Set<Interface> ambiguousInterfaces = new HashSet<Interface>();
for (Interface satisfiedInterface : satisfiedInterfaces) {
if (isInheritedWithDifferentTypeArguments(satisfiedInterface, model.getType()) != null) {
ambiguousInterfaces.add(satisfiedInterface);
}
}
Set<String> treated = new HashSet<String>();
for (Interface ambiguousInterface : ambiguousInterfaces) {
for (Declaration member : ambiguousInterface.getMembers()) {
String name = member.getName();
// skip if already handled
if (treated.contains(name))
continue;
// skip if it's implemented directly
if (model.getDirectMember(name, null, false) != null) {
treated.add(name);
continue;
}
// find if we have different implementations in two direct interfaces
LOOKUP: for (int i = 0; i < satisfiedTypes.size(); i++) {
Type firstInterface = satisfiedTypes.get(i);
Declaration member1 = firstInterface.getDeclaration().getMember(name, null, false);
// if we can't find it in this interface, move to the next
if (member1 == null)
continue;
// try to find member in other interfaces
for (int j = i + 1; j < satisfiedTypes.size(); j++) {
Type secondInterface = satisfiedTypes.get(j);
Declaration member2 = secondInterface.getDeclaration().getMember(name, null, false);
// if we can't find it in this interface, move to the next
if (member2 == null)
continue;
// we have it in two separate interfaces
Reference typedMember1 = firstInterface.getTypedReference(member1, Collections.<Type>emptyList());
Reference typedMember2 = secondInterface.getTypedReference(member2, Collections.<Type>emptyList());
Type type1 = simplifyType(typedMember1.getType());
Type type2 = simplifyType(typedMember2.getType());
if (!type1.isExactly(type2)) {
// treat it and stop looking for other interfaces
addAmbiguousMember(classBuilder, model, name);
break LOOKUP;
}
}
}
// that member has no conflict
treated.add(name);
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method makeNamedConstructor.
/**
* Makes a named constructor
* @param that
* @param classBuilder
* @param mods
* @param ctorName
* @param ctorBody
* @param declFlags
* @return
*/
public List<JCTree> makeNamedConstructor(Tree.Declaration that, Tree.ParameterList parameterList, Constructor ctor, ClassDefinitionBuilder classBuilder, boolean generateInstantiator, int mods, boolean atIgnoreCtor, String ctorName, List<JCStatement> ctorBody, DeclNameFlag... declFlags) {
ListBuffer<JCTree> result = ListBuffer.<JCTree>lb();
Class clz = (Class) ctor.getContainer();
at(that);
MethodDefinitionBuilder ctorDb = MethodDefinitionBuilder.constructor(this);
ClassDefinitionBuilder decl = null;
ClassDefinitionBuilder impl = null;
if (generateInstantiator) {
if (clz.getContainer() instanceof Interface) {
decl = classBuilder.getContainingClassBuilder();
impl = classBuilder.getContainingClassBuilder().getCompanionBuilder((Interface) clz.getContainer());
} else {
decl = classBuilder.getContainingClassBuilder();
impl = classBuilder.getContainingClassBuilder();
}
generateInstantiators(classBuilder, clz, ctor, decl, impl, that, parameterList);
}
ctorDb.userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, that));
if (atIgnoreCtor) {
ctorDb.modelAnnotations(makeAtIgnore());
} else if (!Decl.isDefaultConstructor(ctor)) {
ctorDb.modelAnnotations(makeAtName(ctor.getName()));
}
if (Decl.isEnumeratedConstructor(ctor)) {
ctorDb.modelAnnotations(makeAtEnumerated());
}
ctorDb.modifiers(mods);
for (TypeParameter tp : clz.getTypeParameters()) {
ctorDb.reifiedTypeParameter(tp);
}
if (ctorName != null) {
// generate a constructor name class (and constant)
transformConstructorName(classBuilder, result, ctor, clz, mods, ctorName, declFlags);
// Add the name paramter
ctorDb.parameter(makeConstructorNameParameter(ctor, declFlags));
}
// Add the rest of the parameters (this worries about aliasing)
if (parameterList != null) {
transformClassOrCtorParameters(null, (Class) ctor.getContainer(), ctor, that, parameterList, contains(declFlags, DeclNameFlag.DELEGATION), classBuilder, ctorDb, generateInstantiator, decl, impl);
}
// Transformation of body has to happen after transformation of parameter so we know about parameter aliasing.
at(that);
ctorDb.block(make().Block(0, ctorBody));
result.add(ctorDb.build());
return result.toList();
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method makeCompanionInstanceAssignment.
/**
* Returns the companion instances assignment expression used in the constructor,
* e.g.
* <pre>
* this.$ceylon$language$Enumerable$this$ = new .ceylon.language.Enumerable$impl<.com.redhat.ceylon.compiler.java.test.structure.klass.SerializableEnumerable>(.com.redhat.ceylon.compiler.java.test.structure.klass.SerializableEnumerable.$TypeDescriptor$, this);
* </pre>
* @param classBuilder
* @return
*/
private JCExpressionStatement makeCompanionInstanceAssignment(final Class model, final Interface iface, final Type satisfiedType) {
final Type bestSatisfiedType = getBestSatisfiedType(model.getType(), iface);
JCExpression containerInstance = null;
if (!Decl.isToplevel(iface) && !Decl.isLocal(iface)) {
// if it's a member type we need to qualify the new instance with its $impl container
ClassOrInterface interfaceContainer = Decl.getClassOrInterfaceContainer(iface, false);
if (interfaceContainer instanceof Interface) {
ClassOrInterface modelContainer = model;
// first try to find exactly the interface we are looking for
while ((modelContainer = Decl.getClassOrInterfaceContainer(modelContainer, false)) != null && !modelContainer.equals(interfaceContainer)) {
// keep searching
}
// then find one that inherits it
if (modelContainer == null) {
modelContainer = model;
while ((modelContainer = Decl.getClassOrInterfaceContainer(modelContainer, false)) != null && modelContainer.getType().getSupertype(interfaceContainer) == null) {
// keep searching
}
}
if (modelContainer == null) {
throw new BugException("Could not find container that satisfies interface " + iface.getQualifiedNameString() + " to find qualifying instance for companion instance for " + model.getQualifiedNameString());
}
// if it's an interface we just qualify it properly
if (modelContainer instanceof Interface) {
JCExpression containerType = makeJavaType(modelContainer.getType(), JT_COMPANION | JT_SATISFIES | JT_RAW);
containerInstance = makeSelect(containerType, "this");
} else {
// it's a class: find the right field used for the interface container impl
String containerFieldName = getCompanionFieldName((Interface) interfaceContainer);
JCExpression containerType = makeJavaType(modelContainer.getType(), JT_SATISFIES);
containerInstance = makeSelect(makeSelect(containerType, "this"), containerFieldName);
}
}
}
List<JCExpression> state = List.nil();
// pass all reified type info to the constructor
for (JCExpression t : makeReifiedTypeArguments(satisfiedType)) {
state = state.append(t);
}
// pass the instance of this
state = state.append(expressionGen().applyErasureAndBoxing(naming.makeThis(), model.getType(), false, true, BoxingStrategy.BOXED, bestSatisfiedType, ExpressionTransformer.EXPR_FOR_COMPANION));
final JCExpression ifaceImplType;
if (!Decl.isToplevel(iface) && !Decl.isLocal(iface) && Decl.getClassOrInterfaceContainer(iface, false) instanceof Interface) {
ifaceImplType = makeJavaType(bestSatisfiedType, JT_COMPANION | JT_CLASS_NEW | JT_NON_QUALIFIED);
} else {
ifaceImplType = makeJavaType(bestSatisfiedType, JT_COMPANION | JT_CLASS_NEW);
}
JCExpression newInstance = make().NewClass(containerInstance, null, ifaceImplType, state, null);
JCExpressionStatement companionInstanceAssign = make().Exec(make().Assign(// TODO Use qualified name for quoting?
makeSelect("this", getCompanionFieldName(iface)), newInstance));
return companionInstanceAssign;
}
use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.
the class ClassTransformer method satisfaction.
private void satisfaction(Tree.SatisfiedTypes satisfied, final Class model, ClassDefinitionBuilder classBuilder) {
Set<Interface> satisfiedInterfaces = new HashSet<Interface>();
// start by saying that we already satisfied each interface from superclasses
Type superClass = model.getExtendedType();
while (superClass != null) {
for (Type interfaceDecl : superClass.getSatisfiedTypes()) {
collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
}
superClass = superClass.getExtendedType();
}
// now satisfy each new interface
if (satisfied != null) {
for (Tree.StaticType type : satisfied.getTypes()) {
try {
Type satisfiedType = type.getTypeModel();
TypeDeclaration decl = satisfiedType.getDeclaration();
if (!(decl instanceof Interface)) {
continue;
}
// make sure we get the right instantiation of the interface
satisfiedType = model.getType().getSupertype(decl);
concreteMembersFromSuperinterfaces(model, classBuilder, satisfiedType, satisfiedInterfaces);
} catch (BugException e) {
e.addError(type);
}
}
}
// now find the set of interfaces we implemented twice with more refined type parameters
if (model.getExtendedType() != null) {
// reuse that Set
satisfiedInterfaces.clear();
for (Type interfaceDecl : model.getSatisfiedTypes()) {
collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
}
if (!satisfiedInterfaces.isEmpty()) {
// sort it to facilitate test comparisons that work in JDK7 and 8
ArrayList<Interface> sortedInterfaces = new ArrayList<Interface>(satisfiedInterfaces.size());
sortedInterfaces.addAll(satisfiedInterfaces);
Collections.sort(sortedInterfaces, DeclarationComparator);
// now see if we refined them
for (Interface iface : sortedInterfaces) {
// skip those we can't do anything about
if (!supportsReified(iface) || !CodegenUtil.isCompanionClassNeeded(iface))
continue;
Type thisType = model.getType().getSupertype(iface);
Type superClassType = model.getExtendedType().getSupertype(iface);
if (thisType != null && superClassType != null && !thisType.isExactly(superClassType) && thisType.isSubtypeOf(superClassType)) {
// we're refining it
classBuilder.refineReifiedType(thisType);
}
}
}
}
}
Aggregations