use of com.redhat.ceylon.model.typechecker.model.Scope in project ceylon-compiler by ceylon.
the class ExpressionTransformer method appendDeclarationLiteralForAnnotation.
/**
* Appends into the given builder a String representation of the given
* declaration, suitable for parsing my the DeclarationParser.
*/
private static void appendDeclarationLiteralForAnnotation(Declaration decl, StringBuilder sb) {
Scope container = decl.getContainer();
while (true) {
if (container instanceof Declaration) {
appendDeclarationLiteralForAnnotation((Declaration) container, sb);
sb.append(".");
break;
} else if (container instanceof Package) {
appendDeclarationLiteralForAnnotation((Package) container, sb);
sb.append(":");
break;
}
container = container.getContainer();
}
if (decl instanceof Class) {
sb.append("C").append(decl.getName());
} else if (decl instanceof Interface) {
sb.append("I").append(decl.getName());
} else if (decl instanceof TypeAlias) {
sb.append("A").append(decl.getName());
} else if (decl instanceof Value) {
sb.append("V").append(decl.getName());
} else if (decl instanceof Function) {
sb.append("F").append(decl.getName());
} else if (decl instanceof TypeParameter) {
sb.append("P").append(decl.getName());
} else if (decl instanceof Constructor) {
sb.append("c").append(decl.getName());
} else {
throw BugException.unhandledDeclarationCase(decl);
}
}
use of com.redhat.ceylon.model.typechecker.model.Scope in project ceylon-compiler by ceylon.
the class ExpressionTransformer method needDollarThis.
private boolean needDollarThis(Tree.StaticMemberOrTypeExpression expr) {
if (expr instanceof Tree.BaseMemberExpression) {
// We need to add a `$this` prefix to the member expression if:
// * The member was declared on an interface I and
// * The member is being used in the companion class of I or
// // REMOVED: some subinterface of I, and
// some member type of I, and
// * The member is shared (non-shared means its only on the companion class)
// FIXME: https://github.com/ceylon/ceylon-compiler/issues/1019
final Declaration decl = expr.getDeclaration();
if (!Decl.withinInterface(decl))
return false;
// Find the method/getter/setter where the expr is being used
Scope scope = expr.getScope();
while (scope != null) {
// Is it being used in an interface (=> impl)
if (scope instanceof Interface && ((Interface) scope).getType().isSubtypeOf(scope.getDeclaringType(decl))) {
return decl.isShared();
}
scope = scope.getContainer();
}
}
return false;
}
use of com.redhat.ceylon.model.typechecker.model.Scope in project ceylon-compiler by ceylon.
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");
}
}
use of com.redhat.ceylon.model.typechecker.model.Scope in project ceylon-compiler by ceylon.
the class ExpressionTransformer method addInterfaceImplAccessorIfRequired.
//
// Array access
private JCExpression addInterfaceImplAccessorIfRequired(JCExpression qualExpr, Tree.StaticMemberOrTypeExpression expr, Declaration decl) {
// For interfaces we sometimes need to access either the interface instance or its $impl class
if (decl instanceof Constructor) {
decl = (Class) Decl.container(decl);
}
Scope declContainer = Decl.container(decl);
if (qualExpr != null && // this is only for interface containers
declContainer instanceof Interface && // we only ever need the $impl if the declaration is not shared
!decl.isShared() && (!(expr instanceof Tree.QualifiedMemberExpression) || !isSuperOrSuperOf(((Tree.QualifiedMemberExpression) expr).getPrimary()))) {
Interface declaration = (Interface) declContainer;
// access the interface $impl instance
qualExpr = naming.makeCompanionAccessorCall(qualExpr, declaration);
// so we need to cast it to the type of the companion
if (Decl.isAncestorLocal(declaration)) {
Type type;
// try to find the best type
if (expr instanceof Tree.QualifiedMemberOrTypeExpression)
type = ((Tree.QualifiedMemberOrTypeExpression) expr).getPrimary().getTypeModel();
else
type = declaration.getType();
qualExpr = make().TypeCast(makeJavaType(type, JT_COMPANION), qualExpr);
}
}
return qualExpr;
}
use of com.redhat.ceylon.model.typechecker.model.Scope in project ceylon-compiler by ceylon.
the class Naming method appendTypeDeclaration.
private void appendTypeDeclaration(final TypeDeclaration decl, EnumSet<DeclNameFlag> flags, TypeDeclarationBuilder<?> typeDeclarationBuilder, Scope scope, final boolean last) {
if (scope instanceof Class || scope instanceof TypeAlias || (scope instanceof Constructor && (scope.equals(decl) || !Decl.isLocalNotInitializerScope(scope)))) {
TypeDeclaration klass = (TypeDeclaration) scope;
if (klass.isAnonymous() && !klass.isNamed())
typeDeclarationBuilder.clear();
typeDeclarationBuilder.append(escapeClassName(klass.getName() != null ? klass.getName() : ""));
if (Decl.isCeylon(klass)) {
if (flags.contains(DeclNameFlag.COMPANION) && Decl.isLocalNotInitializer(klass) && last) {
typeDeclarationBuilder.append(IMPL_POSTFIX);
} else if (flags.contains(DeclNameFlag.ANNOTATION) && last) {
typeDeclarationBuilder.append(ANNO_POSTFIX);
} else if (flags.contains(DeclNameFlag.ANNOTATIONS) && last) {
typeDeclarationBuilder.append(ANNOS_POSTFIX);
} else if (flags.contains(DeclNameFlag.DELEGATION) && last) {
typeDeclarationBuilder.append(DELEGATION_POSTFIX);
}
}
} else if (scope instanceof Interface) {
Interface iface = (Interface) scope;
typeDeclarationBuilder.append(iface.getName());
if (Decl.isCeylon(iface) && ((decl instanceof Class || decl instanceof Constructor || decl instanceof TypeAlias || scope instanceof Constructor) || flags.contains(DeclNameFlag.COMPANION))) {
typeDeclarationBuilder.append(IMPL_POSTFIX);
}
} else if (Decl.isLocalNotInitializerScope(scope)) {
if (flags.contains(DeclNameFlag.COMPANION) || !(decl instanceof Interface)) {
typeDeclarationBuilder.clear();
} else if (flags.contains(DeclNameFlag.QUALIFIED) || (decl instanceof Interface)) {
Scope nonLocal = scope;
while (!(nonLocal instanceof Declaration)) {
nonLocal = nonLocal.getContainer();
}
typeDeclarationBuilder.append(((Declaration) nonLocal).getPrefixedName());
if (!Decl.equalScopes(scope, nonLocal)) {
typeDeclarationBuilder.append('$');
typeDeclarationBuilder.append(getLocalId(scope));
}
if (decl instanceof Interface) {
typeDeclarationBuilder.append('$');
} else {
if (flags.contains(DeclNameFlag.QUALIFIED)) {
typeDeclarationBuilder.selectAppended();
} else {
typeDeclarationBuilder.clear();
}
}
}
return;
} else if (scope instanceof TypedDeclaration && ((Declaration) scope).isToplevel()) {
// nothing? that's just weird
}
if (!last) {
if (decl instanceof Interface && Decl.isCeylon((TypeDeclaration) decl) && !flags.contains(DeclNameFlag.COMPANION)) {
typeDeclarationBuilder.append('$');
} else if (decl instanceof Constructor && ((Class) decl.getContainer()).isMember() && decl.getContainer().equals(scope)) {
typeDeclarationBuilder.append('$');
} else {
if (flags.contains(DeclNameFlag.QUALIFIED)) {
typeDeclarationBuilder.selectAppended();
} else {
typeDeclarationBuilder.clear();
}
}
} else {
typeDeclarationBuilder.selectAppended();
}
return;
}
Aggregations