use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration 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.TypedDeclaration in project ceylon-compiler by ceylon.
the class ClassTransformer method transform.
List<MethodDefinitionBuilder> transform(Tree.AnyMethod def, ClassDefinitionBuilder classBuilder, List<JCStatement> body) {
final Function model = def.getDeclarationModel();
List<MethodDefinitionBuilder> result = List.<MethodDefinitionBuilder>nil();
if (!Decl.withinInterface(model)) {
// Transform to the class
boolean refinedResultType = !model.getType().isExactly(((TypedDeclaration) model.getRefinedDeclaration()).getType());
result = transformMethod(def, true, true, true, transformMplBodyUnlessSpecifier(def, model, body), refinedResultType && !Decl.withinInterface(model.getRefinedDeclaration()) ? new DaoSuper() : new DaoThis(def, def.getParameterLists().get(0)), !Strategy.defaultParameterMethodOnSelf(model));
} else {
// Is within interface
// Transform the definition to the companion class, how depends
// on what kind of method it is
List<MethodDefinitionBuilder> companionDefs;
if (def instanceof Tree.MethodDeclaration) {
final SpecifierExpression specifier = ((Tree.MethodDeclaration) def).getSpecifierExpression();
if (specifier == null) {
// formal or abstract
// (still need overloads and DPMs on the companion)
companionDefs = transformMethod(def, false, true, true, null, new DaoCompanion(def, def.getParameterLists().get(0)), false);
} else {
companionDefs = transformMethod(def, true, false, !model.isShared(), transformMplBodyUnlessSpecifier(def, model, body), new DaoCompanion(def, def.getParameterLists().get(0)), false);
}
} else if (def instanceof Tree.MethodDefinition) {
companionDefs = transformMethod(def, true, false, !model.isShared(), transformMplBodyUnlessSpecifier(def, model, body), new DaoCompanion(def, def.getParameterLists().get(0)), false);
} else {
throw BugException.unhandledNodeCase(def);
}
if (!companionDefs.isEmpty())
classBuilder.getCompanionBuilder((TypeDeclaration) model.getContainer()).methods(companionDefs);
// but only if it's shared
if (Decl.isShared(model)) {
result = transformMethod(def, true, true, true, null, daoAbstract, !Strategy.defaultParameterMethodOnSelf(model));
}
}
return result;
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class CeylonTransformer method transformAttribute.
public List<JCTree> transformAttribute(Tree.TypedDeclaration decl, Tree.AttributeSetterDefinition setterDecl) {
at(decl);
TypedDeclaration declarationModel = decl.getDeclarationModel();
final String attrName = declarationModel.getName();
final String attrClassName = Naming.getAttrClassName(declarationModel, 0);
final Tree.SpecifierOrInitializerExpression expression;
final Tree.Block block;
if (decl instanceof Tree.AttributeDeclaration) {
Tree.AttributeDeclaration adecl = (Tree.AttributeDeclaration) decl;
expression = adecl.getSpecifierOrInitializerExpression();
block = null;
} else if (decl instanceof Tree.AttributeGetterDefinition) {
expression = null;
Tree.AttributeGetterDefinition gdef = (Tree.AttributeGetterDefinition) decl;
block = gdef.getBlock();
} else if (decl instanceof Tree.AttributeSetterDefinition) {
Tree.AttributeSetterDefinition sdef = (Tree.AttributeSetterDefinition) decl;
block = sdef.getBlock();
expression = sdef.getSpecifierExpression();
if (Decl.isLocal(decl)) {
declarationModel = ((Tree.AttributeSetterDefinition) decl).getDeclarationModel().getParameter().getModel();
}
} else {
throw new RuntimeException();
}
return transformAttribute(declarationModel, attrName, attrClassName, decl, block, expression, decl, setterDecl);
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformMemberReference.
JCExpression transformMemberReference(Tree.QualifiedMemberOrTypeExpression expr, Tree.MemberOrTypeExpression primary) {
Declaration member = expr.getDeclaration();
Type qualifyingType = primary.getTypeModel();
Tree.TypeArguments typeArguments = expr.getTypeArguments();
boolean prevSyntheticClassBody = withinSyntheticClassBody(true);
try {
if (member.isStaticallyImportable()) {
if (member instanceof Function) {
Function method = (Function) member;
Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
return CallableBuilder.javaStaticMethodReference(gen(), expr.getTypeModel(), method, producedReference).build();
} else if (member instanceof FieldValue) {
return naming.makeName((TypedDeclaration) member, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED);
} else if (member instanceof Value) {
CallBuilder callBuilder = CallBuilder.instance(this);
JCExpression qualExpr = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) member.getContainer(), DeclNameFlag.QUALIFIED);
callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
return callBuilder.build();
} else if (member instanceof Class) {
Reference producedReference = expr.getTarget();
return CallableBuilder.javaStaticMethodReference(gen(), expr.getTypeModel(), (Class) member, producedReference).build();
}
}
if (member instanceof Value) {
if (expr.getStaticMethodReference() && Decl.isEnumeratedConstructor((Value) member)) {
CallBuilder callBuilder = CallBuilder.instance(this);
JCExpression qualExpr;
Class class1 = (Class) member.getContainer();
if (class1.isToplevel()) {
qualExpr = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) member.getContainer(), DeclNameFlag.QUALIFIED);
callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
} else if (class1.isMember()) {
// creates a Callable<Outer.Inner,[Outer]> that returns the enumeratedConstructor given an outer instance
if (primary instanceof Tree.QualifiedMemberOrTypeExpression && ((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary() instanceof Tree.BaseTypeExpression)
return CallableBuilder.unboundValueMemberReference(gen(), expr, expr.getTypeModel(), ((TypedDeclaration) member)).build();
else {
qualExpr = primary instanceof Tree.QualifiedMemberOrTypeExpression ? transformExpression(((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary()) : null;
callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
}
} else {
callBuilder.fieldRead(naming.makeName((TypedDeclaration) member, Naming.NA_IDENT));
}
return callBuilder.build();
} else {
return CallableBuilder.unboundValueMemberReference(gen(), expr, expr.getTypeModel(), ((TypedDeclaration) member)).build();
}
} else if (Decl.isConstructor(member)) {
Reference producedReference = expr.getTarget();
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), Decl.getConstructor(member), producedReference).build();
} else if (member instanceof Function) {
Function method = (Function) member;
if (!method.isParameter()) {
Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), method, producedReference).build();
} else {
Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), method, producedReference).build();
}
} else if (member instanceof Class) {
Reference producedReference = expr.getTarget();
return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), (Class) member, producedReference).build();
} else {
return makeErroneous(expr, "compiler bug: member reference of " + expr + " not supported yet");
}
} finally {
withinSyntheticClassBody(prevSyntheticClassBody);
}
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class CodegenUtil method getJavaNameOfDeclaration.
/**
* <p>Returns the fully qualified name java name of the given declaration,
* for example
* {@code ceylon.language.sum_.sum} or {@code my.package.Outer.Inner}.
* for any toplevel or externally visible Ceylon declaration.</p>
*
* <p>Used by the IDE to support finding/renaming Ceylon declarations
* called from Java.</p>
* */
public static String getJavaNameOfDeclaration(Declaration decl) {
Scope s = decl.getScope();
while (!(s instanceof Package)) {
if (!(s instanceof TypeDeclaration)) {
throw new IllegalArgumentException();
}
s = s.getContainer();
}
String result;
Naming n = new Naming(null, null);
if (decl instanceof TypeDeclaration) {
result = n.makeTypeDeclarationName((TypeDeclaration) decl, DeclNameFlag.QUALIFIED);
// remove initial .
result = result.substring(1);
if (decl.isAnonymous()) {
result += "." + Unfix.get_.toString();
}
} else if (decl instanceof TypedDeclaration) {
if (decl.isToplevel()) {
result = n.getName((TypedDeclaration) decl, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER);
// remove initial .
result = result.substring(1);
} else {
Scope container = decl.getContainer();
if (container instanceof TypeDeclaration) {
String qualifier = getJavaNameOfDeclaration((TypeDeclaration) container);
result = qualifier + n.getName((TypedDeclaration) decl, Naming.NA_MEMBER);
} else {
throw new IllegalArgumentException();
}
}
} else {
throw new RuntimeException();
}
return result;
}
Aggregations