use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method qualifyLhs.
protected JCExpression qualifyLhs(final Node op, Tree.Term leftTerm, JCExpression lhs) {
TypedDeclaration decl;
if (leftTerm instanceof Tree.StaticMemberOrTypeExpression) {
decl = (TypedDeclaration) ((Tree.StaticMemberOrTypeExpression) leftTerm).getDeclaration();
lhs = addInterfaceImplAccessorIfRequired(lhs, (Tree.StaticMemberOrTypeExpression) leftTerm, decl);
lhs = addThisOrObjectQualifierIfRequired(lhs, (Tree.StaticMemberOrTypeExpression) leftTerm, decl);
} else if (leftTerm instanceof Tree.IndexExpression) {
// in this case lhs is null anyway, so let's discard it
return lhs;
} else if (leftTerm instanceof Tree.ParameterizedExpression) {
// instanceof Tree.ParameterizedExpression
decl = (TypedDeclaration) ((Tree.MemberOrTypeExpression) ((Tree.ParameterizedExpression) leftTerm).getPrimary()).getDeclaration();
} else {
return makeErroneous(op, "Unexpected LHS in assignment: " + leftTerm.getNodeType());
}
if (decl.isToplevel()) {
// must use top level setter
lhs = naming.makeName(decl, Naming.NA_FQ | Naming.NA_WRAPPER);
} else if (Decl.isGetter(decl)) {
if (Decl.isTransient(decl) && !decl.isVariable()) {
} else {
// must use the setter
if (Decl.isLocal(decl)) {
lhs = naming.makeQualifiedName(lhs, decl, Naming.NA_WRAPPER | Naming.NA_SETTER);
} else if (decl.isStatic()) {
lhs = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) decl.getContainer(), DeclNameFlag.QUALIFIED);
}
}
} else if (decl instanceof Function && Decl.isDeferred(decl)) {
} else if ((decl.isVariable() || decl.isLate()) && (Decl.isClassAttribute(decl))) {
} else if (decl.isVariable() && ModelUtil.isCaptured(decl)) {
// must use the qualified setter
if (Decl.isBoxedVariable(decl)) {
} else if (ModelUtil.isLocalNotInitializer(decl)) {
lhs = naming.makeQualifiedName(lhs, decl, Naming.NA_WRAPPER);
}
}
return lhs;
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method transformAnonymousAnnotation.
public void transformAnonymousAnnotation(Tree.AnonymousAnnotation annotation, Map<Class, ListBuffer<JCAnnotation>> annos) {
Type docType = ((TypeDeclaration) typeFact().getLanguageModuleDeclaration("DocAnnotation")).getType();
JCAnnotation docAnnotation = at(annotation).Annotation(makeJavaType(docType, JT_ANNOTATION), List.<JCExpression>of(make().Assign(naming.makeUnquotedIdent("description"), transform(annotation.getStringLiteral()))));
putAnnotation(annos, docAnnotation, (Class) docType.getDeclaration());
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method transform.
public JCTree transform(Tree.MemberLiteral expr) {
at(expr);
Declaration declaration = expr.getDeclaration();
if (declaration == null)
return makeErroneous(expr, "compiler bug: missing declaration");
if (declaration.isToplevel()) {
return makeTopLevelValueOrFunctionLiteral(expr);
} else if (expr.getWantsDeclaration()) {
return makeMemberValueOrFunctionDeclarationLiteral(expr, declaration);
} else {
// get its produced ref
Reference producedReference = expr.getTarget();
// it's a member we get from its container type
Type containerType = producedReference.getQualifyingType();
// if we have no container type it means we have an object member
boolean objectMember = containerType.getDeclaration().isAnonymous();
JCExpression memberCall;
if (objectMember) {
// We don't care about the type args for the cast, nor for the reified container expr, because
// we take the real reified container type from the container instance, and that one has the type
// arguments
containerType = ((Class) declaration.getContainer()).getType();
}
JCExpression typeCall = makeTypeLiteralCall(containerType, false, expr.getTypeModel());
// make sure we cast it to ClassOrInterface
String metatypeName;
if (Decl.isConstructor(declaration)) {
Class constructedClass = ModelUtil.getConstructedClass(declaration);
Declaration container = getDeclarationContainer(constructedClass);
if (constructedClass.isToplevel() || container instanceof TypeDeclaration == false) {
metatypeName = "Class";
} else {
metatypeName = "MemberClass";
}
} else {
metatypeName = "ClassOrInterface";
}
TypeDeclaration classOrInterfaceDeclaration = (TypeDeclaration) typeFact().getLanguageModuleModelDeclaration(metatypeName);
JCExpression classOrInterfaceTypeExpr = makeJavaType(classOrInterfaceDeclaration.appliedReference(null, Arrays.asList(containerType)).getType());
typeCall = make().TypeCast(classOrInterfaceTypeExpr, typeCall);
// we will need a TD for the container
// Note that we don't use Basic for the container for object members, because that's not how we represent
// anonymous types.
JCExpression reifiedContainerExpr = makeReifiedTypeArgument(containerType);
// make a raw call and cast
if (Decl.isConstructor(declaration)) {
Type callableType = producedReference.getFullType();
/*JCExpression reifiedArgumentsExpr;
if (Decl.isEnumeratedConstructor(Decl.getConstructor(declaration))) {
reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType.getQualifyingType()));
} else {
reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
}*/
JCExpression reifiedArguments;
if (ModelUtil.isEnumeratedConstructor(ModelUtil.getConstructor(declaration))) {
reifiedArguments = makeReifiedTypeArgument(typeFact().getNothingType());
} else {
reifiedArguments = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
}
List<JCExpression> arguments = List.of(reifiedArguments, ceylonLiteral(declaration.getName()));
JCExpression classModel = makeSelect(typeCall, "getDeclaredConstructor");
memberCall = make().Apply(null, classModel, arguments);
} else if (declaration instanceof Function) {
// we need to get types for each type argument
JCExpression closedTypesExpr = null;
if (expr.getTypeArgumentList() != null) {
java.util.List<Type> typeModels = expr.getTypeArgumentList().getTypeModels();
if (typeModels != null) {
closedTypesExpr = getClosedTypesSequential(typeModels);
}
}
// we also need type descriptors for ret and args
Type callableType = producedReference.getFullType();
JCExpression reifiedReturnTypeExpr = makeReifiedTypeArgument(typeFact().getCallableReturnType(callableType));
JCExpression reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
List<JCExpression> arguments;
if (closedTypesExpr != null)
arguments = List.of(reifiedContainerExpr, reifiedReturnTypeExpr, reifiedArgumentsExpr, ceylonLiteral(declaration.getName()), closedTypesExpr);
else
arguments = List.of(reifiedContainerExpr, reifiedReturnTypeExpr, reifiedArgumentsExpr, ceylonLiteral(declaration.getName()));
memberCall = make().Apply(null, makeSelect(typeCall, "getMethod"), arguments);
} else if (declaration instanceof Value) {
JCExpression reifiedGetExpr = makeReifiedTypeArgument(producedReference.getType());
String getterName = "getAttribute";
Type ptype;
if (!((Value) declaration).isVariable())
ptype = typeFact().getNothingType();
else
ptype = producedReference.getType();
JCExpression reifiedSetExpr = makeReifiedTypeArgument(ptype);
memberCall = make().Apply(null, makeSelect(typeCall, getterName), List.of(reifiedContainerExpr, reifiedGetExpr, reifiedSetExpr, ceylonLiteral(declaration.getName())));
} else {
return makeErroneous(expr, "Unsupported member type: " + declaration);
}
// if(objectMember){
// // now get the instance and bind it
// // I don't think we need any expected type since objects can't be erased
// JCExpression object = transformExpression(expr.getObjectExpression());
// // reset the location after we transformed the expression
// memberCall = at(expr).Apply(null, makeSelect(memberCall, "bind"), List.of(object));
// }
// cast the member call because we invoke it with no Java generics
memberCall = make().TypeCast(makeJavaType(expr.getTypeModel(), JT_RAW | JT_NO_PRIMITIVES), memberCall);
memberCall = make().TypeCast(makeJavaType(expr.getTypeModel(), JT_NO_PRIMITIVES), memberCall);
return memberCall;
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method addThisOrObjectQualifierIfRequired.
/**
* We may need to force a qualified this prefix (direct or outer) in the following cases:
*
* - Required because of mixin inheritance with different type arguments (the same is already
* done for qualified references, but not for direct references)
* - The compiler generates anonymous local classes for things like
* Callables and Comprehensions. When referring to a member foo
* within one of those things we need a qualified {@code this}
* to ensure we're accessing the outer instances member, not
* a member of the anonymous local class that happens to have the same name.
*/
private JCExpression addThisOrObjectQualifierIfRequired(JCExpression qualExpr, Tree.StaticMemberOrTypeExpression expr, Declaration decl) {
// find out the real target
Declaration typeDecl;
if (Decl.isConstructor(decl))
typeDecl = ModelUtil.getConstructedClass(decl);
else
typeDecl = decl;
if (qualExpr == null && // statics are not members that can be inherited
!decl.isStatic() && (!Decl.isConstructor(decl) || !Decl.isConstructor(typeDecl)) && typeDecl.isMember() && // and have a name mapping)
expr.getTarget().getDeclaration() == decl && !ModelUtil.isLocalToInitializer(typeDecl) && !isWithinSuperInvocation()) {
// First check whether the expression is captured from an enclosing scope
TypeDeclaration outer = Decl.getOuterScopeOfMemberInvocation(expr, typeDecl);
if (outer != null) {
Type targetType = expr.getTarget().getQualifyingType();
Type declarationContainerType = ((TypeDeclaration) outer).getType();
// check if we need a variance cast
VarianceCastResult varianceCastResult = getVarianceCastResult(targetType, declarationContainerType);
// if we are within a comprehension body, or if we need a variance cast
if (isWithinSyntheticClassBody() || varianceCastResult != null) {
if (decl.isShared() && outer instanceof Interface) {
// always prefer qualified
qualExpr = makeQualifiedDollarThis(declarationContainerType);
} else {
// Class or companion class,
qualExpr = naming.makeQualifiedThis(makeJavaType(((TypeDeclaration) outer).getType(), JT_RAW | (outer instanceof Interface ? JT_COMPANION : 0)));
}
// add the variance cast if required
if (varianceCastResult != null) {
qualExpr = applyVarianceCasts(qualExpr, targetType, varianceCastResult, 0);
}
}
} else if (typeDecl.isClassOrInterfaceMember()) {
ClassOrInterface container;
if (((ClassOrInterface) typeDecl.getContainer()).isAnonymous() && ((ClassOrInterface) typeDecl.getContainer()).isToplevel()) {
// easy
container = (Class) typeDecl.getContainer();
} else {
// find the import
Import foundImport = statementGen().findImport(expr, decl);
container = (Class) foundImport.getTypeDeclaration();
}
Value value = (Value) ((Package) container.getContainer()).getMember(container.getName(), null, false);
qualExpr = make().Apply(null, naming.makeName(value, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER), List.<JCExpression>nil());
} else if (decl.isMember() && !expr.getStaticMethodReference()) {
throw new BugException(expr, decl.getQualifiedNameString() + " was unexpectedly a member");
}
}
return qualExpr;
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class MethodDefinitionBuilder method isParamTypeLocalToMethod.
private boolean isParamTypeLocalToMethod(Parameter parameter, Type nonWideningType) {
// error recovery
if (nonWideningType == null)
return false;
if (parameter.getModel().getTypeErased()) {
return false;
}
// make sure we resolve aliases
nonWideningType = nonWideningType.resolveAliases();
Declaration method = parameter.getDeclaration();
TypeDeclaration paramTypeDecl = nonWideningType.getDeclaration();
if (paramTypeDecl instanceof TypeParameter && Decl.equalScopeDecl(paramTypeDecl.getContainer(), method)) {
return false;
}
Scope scope = paramTypeDecl.getContainer();
while (scope != null && !(scope instanceof Package)) {
if (Decl.equalScopeDecl(scope, method)) {
return true;
}
scope = scope.getContainer();
}
return false;
}
Aggregations