use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class DeclarationVisitor method visit.
public void visit(Tree.SequencedType that) {
super.visit(that);
if (inExtends) {
final Type type = that.getType().getTypeModel();
final boolean atLeastOne = that.getAtLeastOne();
Type t = new LazyType(unit) {
@Override
public boolean isUnknown() {
return false;
}
@Override
public TypeDeclaration initDeclaration() {
return atLeastOne ? unit.getSequenceDeclaration() : unit.getSequentialDeclaration();
}
@Override
public Map<TypeParameter, Type> initTypeArguments() {
Interface dec = atLeastOne ? unit.getSequenceDeclaration() : unit.getSequentialDeclaration();
List<TypeParameter> stps = dec.getTypeParameters();
return singletonMap(stps.get(0), type);
}
};
that.setTypeModel(t);
}
}
use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class ClassTransformer method transform.
public void transform(Tree.AttributeDeclaration decl, ClassDefinitionBuilder classBuilder) {
final Value model = decl.getDeclarationModel();
boolean withinInterface = model.isInterfaceMember();
Tree.SpecifierOrInitializerExpression initializer = decl.getSpecifierOrInitializerExpression();
final boolean lazy = initializer instanceof Tree.LazySpecifierExpression;
String attrName = decl.getIdentifier().getText();
boolean memoized = Decl.isMemoized(decl);
boolean isStatic = model.isStatic();
// Only a non-formal or a concrete-non-lazy attribute has a corresponding field
// and if a captured class parameter exists with the same name we skip this part as well
Parameter parameter = CodegenUtil.findParamForDecl(decl);
boolean useField = !lazy && Strategy.useField(model);
boolean createField = !lazy && !model.isFormal() && Strategy.createField(parameter, model) && !model.isJavaNative();
boolean createCompanionField = !lazy && withinInterface && initializer != null;
JCThrow err = null;
JCExpression memoizedInitialValue = null;
if (createCompanionField || createField) {
TypedReference typedRef = getTypedReference(model);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
if (Decl.isIndirect(decl)) {
attrName = Naming.getAttrClassName(model, 0);
nonWideningType = getGetterInterfaceType(model);
}
JCExpression initialValue = null;
BoxingStrategy boxingStrategy = null;
if (initializer != null) {
Tree.Expression expression = initializer.getExpression();
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getTerm());
int flags = CodegenUtil.downcastForSmall(expression, model) ? ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK : 0;
flags |= model.hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0;
if (error != null) {
initialValue = null;
err = makeThrowUnresolvedCompilationError(error.getErrorMessage().getMessage());
} else {
boxingStrategy = useJavaBox(model, nonWideningType) && javaBoxExpression(expression.getTypeModel(), nonWideningType) ? BoxingStrategy.JAVA : CodegenUtil.getBoxingStrategy(model);
initialValue = expressionGen().transformExpression(expression, boxingStrategy, isStatic && nonWideningType.isTypeParameter() ? typeFact().getAnythingType() : nonWideningType, flags);
}
}
if (memoized) {
memoizedInitialValue = initialValue;
initialValue = makeDefaultExprForType(nonWideningType);
}
int flags = 0;
if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
flags |= JT_NO_PRIMITIVES;
}
long modifiers = useField ? modifierTransformation().field(decl) : modifierTransformation().localVar(decl);
// does it in those cases)
if (parameter == null || parameter.isHidden()) {
JCExpression type;
if (isStatic && nonWideningType.isTypeParameter()) {
type = make().Type(syms().objectType);
} else {
type = makeJavaType(nonWideningType, flags);
}
if (createCompanionField) {
classBuilder.getCompanionBuilder((TypeDeclaration) model.getContainer()).field(modifiers, attrName, type, initialValue, !useField);
} else {
List<JCAnnotation> annos = makeAtIgnore().prependList(expressionGen().transformAnnotations(OutputElement.FIELD, decl));
if (classBuilder.hasDelegatingConstructors()) {
annos = annos.prependList(makeAtNoInitCheck());
}
// fields should be ignored, they are accessed by the getters
if (err == null) {
// TODO This should really be using AttributeDefinitionBuilder somehow
if (useField) {
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.field(this, null, attrName, model, Decl.isIndirect(decl)).fieldAnnotations(annos).fieldNullability(makeNullabilityAnnotations(model)).initialValue(initialValue, boxingStrategy).fieldVisibilityModifiers(modifiers).modifiers(modifiers);
classBuilder.defs(adb.buildFields());
List<JCStatement> buildInit = adb.buildInit(false);
if (!buildInit.isEmpty()) {
if (isStatic) {
classBuilder.defs(make().Block(STATIC, buildInit));
} else {
classBuilder.getInitBuilder().init(buildInit);
}
}
} else if (!memoized) {
classBuilder.field(modifiers, attrName, type, initialValue, !useField, annos);
if (!isEe(model) && model.isLate() && CodegenUtil.needsLateInitField(model, typeFact())) {
classBuilder.field(PRIVATE | Flags.VOLATILE | Flags.TRANSIENT, Naming.getInitializationFieldName(attrName), make().Type(syms().booleanType), make().Literal(false), false, makeAtIgnore());
}
}
}
}
}
// A shared attribute might be initialized in a for statement, so
// we might need a def-assignment subst for it
JCStatement outerSubs = statementGen().openOuterSubstitutionIfNeeded(model, model.getType(), 0);
if (outerSubs != null) {
classBuilder.getInitBuilder().init(outerSubs);
}
}
if (useField || withinInterface || lazy) {
boolean generateInClassOrInterface = !withinInterface || model.isShared() || isStatic;
boolean generateInCompanionClass = withinInterface && lazy && !isStatic;
if (generateInClassOrInterface) {
// Generate getter in main class or interface (when shared)
at(decl.getType());
AttributeDefinitionBuilder getter = makeGetter(decl, false, memoizedInitialValue);
if (err != null) {
getter.getterBlock(make().Block(0, List.<JCStatement>of(err)));
}
classBuilder.attribute(getter);
}
if (generateInCompanionClass) {
Interface container = (Interface) model.getContainer();
// Generate getter in companion class
classBuilder.getCompanionBuilder(container).attribute(makeGetter(decl, true, null));
}
if (Decl.isVariable(model) || model.isLate()) {
if (generateInClassOrInterface) {
// Generate setter in main class or interface (when shared)
classBuilder.attribute(makeSetter(decl, false, memoizedInitialValue));
}
if (generateInCompanionClass) {
Interface container = (Interface) model.getContainer();
// Generate setter in companion class
classBuilder.getCompanionBuilder(container).attribute(makeSetter(decl, true, null));
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
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<.org.eclipse.ceylon.compiler.java.test.structure.klass.SerializableEnumerable>(.org.eclipse.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 (!iface.isToplevel() && !Decl.isLocal(iface)) {
// if it's a member type we need to qualify the new instance with its $impl container
ClassOrInterface interfaceContainer = ModelUtil.getClassOrInterfaceContainer(iface, false);
if (interfaceContainer instanceof Interface) {
ClassOrInterface modelContainer = model;
// first try to find exactly the interface we are looking for
while ((modelContainer = ModelUtil.getClassOrInterfaceContainer(modelContainer, false)) != null && !modelContainer.equals(interfaceContainer)) {
// keep searching
}
// then find one that inherits it
if (modelContainer == null) {
modelContainer = model;
while ((modelContainer = ModelUtil.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 (!iface.isToplevel() && !Decl.isLocal(iface) && ModelUtil.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 org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
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 org.eclipse.ceylon.model.typechecker.model.Interface in project ceylon by eclipse.
the class ClassTransformer method transform.
public List<JCTree> transform(final Tree.ClassOrInterface def) {
final ClassOrInterface model = def.getDeclarationModel();
if (model.isToplevel() && isEe(model)) {
replaceModifierTransformation(new EeModifierTransformation());
}
// in that case
if (model.isAlias() && Decl.isAncestorLocal(model))
return List.nil();
naming.clearSubstitutions(model);
final String javaClassName;
String ceylonClassName = def.getIdentifier().getText();
if (def instanceof Tree.AnyInterface) {
javaClassName = naming.makeTypeDeclarationName(model, QUALIFIED).replaceFirst(".*\\.", "");
} else {
javaClassName = Naming.quoteClassName(ceylonClassName);
}
ClassDefinitionBuilder instantiatorImplCb;
ClassDefinitionBuilder instantiatorDeclCb;
if (model.isInterfaceMember()) {
instantiatorImplCb = gen().current().getCompanionBuilder((Interface) model.getContainer());
instantiatorDeclCb = gen().current();
} else {
instantiatorImplCb = gen().current();
instantiatorDeclCb = null;
}
ClassDefinitionBuilder classBuilder = ClassDefinitionBuilder.klass(this, javaClassName, ceylonClassName, Decl.isLocal(model)).forDefinition(model).hasDelegatingConstructors(CodegenUtil.hasDelegatingConstructors(def));
classBuilder.getInitBuilder().deprecated(model.isDeprecated());
// Very special case for Anything
if (model.isAnything()) {
classBuilder.extending(model.getType(), null);
}
if (def instanceof Tree.AnyClass) {
classBuilder.getInitBuilder().modifiers(modifierTransformation().constructor(model));
Tree.AnyClass classDef = (Tree.AnyClass) def;
Class cls = classDef.getDeclarationModel();
// Member classes need a instantiator method
boolean generateInstantiator = Strategy.generateInstantiator(cls);
if (!cls.hasConstructors()) {
classBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, def));
}
if (generateInstantiator && !cls.hasConstructors() && !cls.hasEnumerated()) {
if (!cls.isStatic()) {
classBuilder.getInitBuilder().modifiers(PROTECTED);
}
generateInstantiators(classBuilder, cls, null, instantiatorDeclCb, instantiatorImplCb, classDef, classDef.getParameterList());
}
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
if (def instanceof Tree.ClassDefinition) {
transformClass((Tree.ClassDefinition) def, cls, classBuilder, classDef.getParameterList(), generateInstantiator, instantiatorDeclCb, instantiatorImplCb);
} else {
// class alias
classBuilder.getInitBuilder().modifiers(PRIVATE);
transformClassAlias((Tree.ClassDeclaration) def, classBuilder);
}
addMissingUnrefinedMembers(def, cls, classBuilder);
}
if (def instanceof Tree.AnyInterface) {
classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
if (def instanceof Tree.InterfaceDefinition) {
transformInterface(def, (Interface) model, classBuilder);
} else {
// interface alias
classBuilder.annotations(makeAtAlias(model.getExtendedType(), null));
classBuilder.isAlias(true);
}
classBuilder.isDynamic(model.isDynamic());
}
// make sure we set the container in case we move it out
addAtContainer(classBuilder, model);
transformTypeParameters(classBuilder, model);
// Transform the class/interface members
List<JCStatement> childDefs = visitClassOrInterfaceDefinition(def, classBuilder);
// everything else is synthetic
at(null);
TransformationPlan plan = errors().hasDeclarationError(def);
if (plan instanceof ThrowerCatchallConstructor) {
classBuilder.broken();
MethodDefinitionBuilder initBuilder = classBuilder.noInitConstructor().addConstructor(model.isDeprecated());
initBuilder.body(statementGen().makeThrowUnresolvedCompilationError(plan.getErrorMessage().getMessage()));
// Although we have the class pl which we could use we don't know
// that it won't collide with the default named constructor's pl
// which would cause a javac error about two constructors with the same sig
// so we generate a Object... here. There's still a risk of collision though
// when the default constructor has pl (ObjectArray).
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.implicitParameter(this, "ignored");
pdb.modifiers(VARARGS);
pdb.type(new TransformedType(make().TypeArray(make().Type(syms().objectType))));
initBuilder.parameter(pdb);
} else if (plan instanceof PrivateConstructorOnly) {
classBuilder.broken();
MethodDefinitionBuilder initBuilder = classBuilder.noInitConstructor().addConstructor(model.isDeprecated());
initBuilder.body(statementGen().makeThrowUnresolvedCompilationError(plan.getErrorMessage().getMessage()));
initBuilder.modifiers(PRIVATE);
}
// If it's a Class without initializer parameters...
if (Strategy.generateMain(def)) {
// ... then add a main() method
classBuilder.method(makeMainForClass(model));
}
classBuilder.modelAnnotations(model.getAnnotations()).modifiers(modifierTransformation().classFlags(model)).satisfies(model.getSatisfiedTypes()).caseTypes(model.getCaseTypes(), model.getSelfType()).defs(childDefs);
// aliases and native headers don't need a $getType method
if (!model.isAlias()) {
// only classes get a $getType method
if (model instanceof Class)
classBuilder.addGetTypeMethod(model.getType());
if (supportsReifiedAlias(model))
classBuilder.reifiedAlias(model.getType());
}
// we can add things which depend on knowing all the fields
if (Strategy.generateJpaCtor(model) && plan instanceof Generate) {
buildJpaConstructor((Class) model, classBuilder);
}
if (model instanceof Class && !(model instanceof ClassAlias) && plan instanceof Generate) {
Class c = (Class) model;
if (Strategy.introduceJavaIoSerializable(c, typeFact().getJavaIoSerializable())) {
classBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
if (Strategy.useSerializationProxy(c) && noValueConstructorErrors((Tree.ClassDefinition) def)) {
at(def);
addWriteReplace(c, classBuilder);
}
}
serialization(c, classBuilder);
}
// reset position before initializer constructor is generated.
at(def);
classBuilder.at(def);
List<JCTree> result;
if (Decl.isAnnotationClass(def.getDeclarationModel())) {
ListBuffer<JCTree> trees = new ListBuffer<JCTree>();
trees.addAll(transformAnnotationClass((Tree.AnyClass) def));
transformAnnotationClassConstructor((Tree.AnyClass) def, classBuilder);
// you only need that method if you satisfy Annotation which is erased to j.l.a.Annotation
if (model.inherits(typeFact().getAnnotationDeclaration()))
classBuilder.addAnnotationTypeMethod(model.getType());
trees.addAll(classBuilder.build());
result = trees.toList();
} else {
result = classBuilder.build();
}
if (model.isToplevel() && isEe(model)) {
replaceModifierTransformation(new ModifierTransformation());
}
return result;
}
Aggregations