use of org.eclipse.ceylon.model.typechecker.model.TypeAlias in project ceylon by eclipse.
the class AbstractModelLoader method setContainer.
private void setContainer(ClassMirror classMirror, Declaration d, LazyPackage pkg) {
// add it to its package if it's not an inner class
if (!classMirror.isInnerClass() && !classMirror.isLocalClass()) {
d.setContainer(pkg);
d.setScope(pkg);
pkg.addCompiledMember(d);
if (d instanceof LazyInterface && ((LazyInterface) d).isCeylon()) {
setInterfaceCompanionClass(d, null, pkg);
}
ModelUtil.setVisibleScope(d);
} else if (classMirror.isLocalClass() && !classMirror.isInnerClass()) {
// set its container to the package for now, but don't add it to the package as a member because it's not
Scope localContainer = getLocalContainer(pkg, classMirror, d);
if (localContainer != null) {
d.setContainer(localContainer);
d.setScope(localContainer);
// do not add it as member, it has already been registered by getLocalContainer
} else {
d.setContainer(pkg);
d.setScope(pkg);
}
((LazyElement) d).setLocal(true);
} else if (d instanceof ClassOrInterface || d instanceof TypeAlias) {
// we have to set that one first
if (d instanceof Class == false || !((Class) d).isOverloaded()) {
ClassOrInterface container = getContainer(pkg.getModule(), classMirror);
if (d.isNativeHeader() && container.isNative()) {
container = (ClassOrInterface) ModelUtil.getNativeHeader(container);
} else if (d.isNativeImplementation() && // for every Java declaration, who don't have native headers
container.isNativeHeader()) {
container = (ClassOrInterface) ModelUtil.getNativeDeclaration(container, Backend.Java);
}
d.setContainer(container);
d.setScope(container);
if (d instanceof LazyInterface && ((LazyInterface) d).isCeylon()) {
setInterfaceCompanionClass(d, container, pkg);
}
// let's not trigger lazy-loading
((LazyContainer) container).addMember(d);
ModelUtil.setVisibleScope(d);
// now we can do overloads
if (d instanceof Class && ((Class) d).getOverloads() != null) {
for (Declaration overload : ((Class) d).getOverloads()) {
overload.setContainer(container);
overload.setScope(container);
// let's not trigger lazy-loading
((LazyContainer) container).addMember(overload);
ModelUtil.setVisibleScope(overload);
}
}
// Adds extra members for annotation interop.
if (d instanceof LazyInterface && !((LazyInterface) d).isCeylon() && ((LazyInterface) d).isAnnotationType()) {
for (Declaration decl : makeInteropAnnotation((LazyInterface) d, container)) {
container.addMember(decl);
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeAlias in project ceylon by eclipse.
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.getDeclarationModel()))
// 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 org.eclipse.ceylon.model.typechecker.model.TypeAlias 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.TypeAlias in project ceylon by eclipse.
the class ClassTransformer method transform.
public List<JCTree> transform(final Tree.TypeAliasDeclaration def) {
final TypeAlias model = def.getDeclarationModel();
// in that case
if (Decl.isAncestorLocal(model))
return List.nil();
naming.clearSubstitutions(model);
String ceylonClassName = def.getIdentifier().getText();
final String javaClassName = Naming.quoteClassName(def.getIdentifier().getText());
ClassDefinitionBuilder classBuilder = ClassDefinitionBuilder.klass(this, javaClassName, ceylonClassName, Decl.isLocal(model));
// class alias
classBuilder.getInitBuilder().modifiers(PRIVATE);
classBuilder.annotations(makeAtTypeAlias(model.getExtendedType()));
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
classBuilder.isAlias(true);
// make sure we set the container in case we move it out
addAtContainer(classBuilder, model);
transformTypeParameters(classBuilder, model);
visitClassOrInterfaceDefinition(def, classBuilder);
return classBuilder.modelAnnotations(model.getAnnotations()).modifiers(modifierTransformation().typeAlias(model)).satisfies(model.getSatisfiedTypes()).build();
}
use of org.eclipse.ceylon.model.typechecker.model.TypeAlias in project ceylon by eclipse.
the class ExpressionTransformer method makeTypeParameterDeclaration.
/**
* Makes an expression equivalent to the result of {@code `given T`}
* @param node
* @param declaration
* @return
*/
JCExpression makeTypeParameterDeclaration(Node node, TypeParameter declaration) {
Scope container = declaration.getContainer();
if (container instanceof Declaration) {
JCExpression containerExpr;
Declaration containerDeclaration = (Declaration) container;
if (containerDeclaration instanceof ClassOrInterface || containerDeclaration instanceof TypeAlias) {
JCExpression metamodelCall = makeTypeDeclarationLiteral((TypeDeclaration) containerDeclaration);
JCExpression metamodelCast = makeJavaType(typeFact().getLanguageModuleDeclarationTypeDeclaration("GenericDeclaration").getType(), JT_NO_PRIMITIVES);
containerExpr = make().TypeCast(metamodelCast, metamodelCall);
} else if (containerDeclaration.isToplevel()) {
containerExpr = makeTopLevelValueOrFunctionDeclarationLiteral(containerDeclaration);
} else {
containerExpr = makeMemberValueOrFunctionDeclarationLiteral(node, containerDeclaration);
}
// now it must be a ClassOrInterfaceDeclaration or a FunctionDeclaration, both of which have the method we need
return at(node).Apply(null, makeSelect(containerExpr, "getTypeParameterDeclaration"), List.of(ceylonLiteral(declaration.getName())));
} else {
return makeErroneous(node, "compiler bug: " + container + " is not a supported type parameter container");
}
}
Aggregations