use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ExpressionErrorVisitor method visit.
public void visit(Tree.MetaLiteral that) {
Declaration declaration = that.getDeclaration();
if (declaration instanceof TypedDeclaration) {
checkType(that, ((TypedDeclaration) declaration).getTypedReference().getFullType());
} else if (declaration instanceof TypeDeclaration) {
checkType(that, ((TypeDeclaration) declaration).getType());
}
super.visit(that);
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class TypeParser method loadType.
private Type loadType(String pkg, String fullName, Part part, Type qualifyingType) {
// try to find a qualified type
try {
Declaration newDeclaration;
if (qualifyingType == null) {
// FIXME: this only works for packages not contained in multiple modules
Package foundPackage = moduleScope.getPackage(pkg);
if (foundPackage != null)
newDeclaration = loader.getDeclaration(foundPackage.getModule(), pkg, fullName, scope);
else if (scope != null && !pkg.isEmpty() && loader.isDynamicMetamodel()) {
// try the default module, damnit
newDeclaration = loader.getDeclaration(loader.getLoadedModule(Module.DEFAULT_MODULE_NAME, null), pkg, fullName, scope);
} else if (scope != null) {
// if we did not find any package and the scope is null, chances are we're after a type variable
// or a relative type, so use the module scope
newDeclaration = loader.getDeclaration(moduleScope, pkg, fullName, scope);
} else
newDeclaration = null;
} else {
// look it up via its qualifying type or decl
Declaration qualifyingDeclaration = qualifyingType.getDeclaration();
if (qualifyingType.isUnion() || qualifyingType.isIntersection()) {
newDeclaration = qualifyingDeclaration.getMember(part.name, null, false);
} else {
if (qualifyingDeclaration instanceof FunctionOrValueInterface)
qualifyingDeclaration = ((FunctionOrValueInterface) qualifyingDeclaration).getUnderlyingDeclaration();
newDeclaration = AbstractModelLoader.getDirectMember((Scope) qualifyingDeclaration, part.name);
}
if (newDeclaration == null)
throw new ModelResolutionException("Failed to resolve inner type or declaration " + part.name + " in " + qualifyingDeclaration.getQualifiedNameString());
}
if (newDeclaration == null)
return null;
TypeDeclaration newTypeDeclaration;
if (newDeclaration instanceof TypeDeclaration)
newTypeDeclaration = (TypeDeclaration) newDeclaration;
else
newTypeDeclaration = new FunctionOrValueInterface((TypedDeclaration) newDeclaration);
Type ret = newTypeDeclaration.appliedType(qualifyingType, part.getParameters());
// set the use-site variance if required, now that we know the TypeParameter declarations
if (!part.getVariance().isEmpty()) {
List<TypeParameter> tps = newTypeDeclaration.getTypeParameters();
List<SiteVariance> variance = part.getVariance();
for (int i = 0, l1 = tps.size(), l2 = variance.size(); i < l1 && i < l2; i++) {
SiteVariance siteVariance = variance.get(i);
if (siteVariance != null) {
ret.setVariance(tps.get(i), siteVariance);
}
}
}
return ret;
} catch (ModelResolutionException x) {
// - if we have type parameters we must have a type
if (qualifyingType != null || (part.parameters != null && !part.parameters.isEmpty()))
throw x;
return null;
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class NamingBase method getGetterName.
public static String getGetterName(Declaration decl, boolean indirect) {
// always use the refined decl
decl = decl.getRefinedDeclaration();
if (decl instanceof FieldValue) {
return ((FieldValue) decl).getRealName();
}
if (decl instanceof JavaBeanValue && !indirect) {
return ((JavaBeanValue) decl).getGetterName();
}
boolean enumeratedConstructor = false;
if (decl instanceof Value) {
Type type = ((Value) decl).getType();
enumeratedConstructor = type != null && type.getDeclaration() instanceof org.eclipse.ceylon.model.typechecker.model.Constructor;
}
if (decl.isClassOrInterfaceMember() && (!isLocalToInitializer(decl) || enumeratedConstructor || decl.isStatic()) && !indirect) {
if (enumeratedConstructor) {
Class constructedClass = getConstructedClass(decl);
// See CeylonVisitor.transformSingletonConstructor for that logic
if (constructedClass.isToplevel() || constructedClass.isClassMember())
return getGetterName(((Class) decl.getContainer()).getName() + "$" + decl.getName());
return name(Unfix.ref);
}
return getErasedGetterName(decl);
} else if (decl instanceof TypedDeclaration && isBoxedVariable((TypedDeclaration) decl)) {
return name(Unfix.ref);
} else {
return name(Unfix.get_);
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method transformMemberExpression.
private JCExpression transformMemberExpression(Tree.StaticMemberOrTypeExpression expr, JCExpression primaryExpr, TermTransformer transformer) {
JCExpression result = null;
// do not throw, an error will already have been reported
Declaration decl = expr.getDeclaration();
if (decl == null) {
return makeErroneous(expr, "compiler bug: expression with no declaration");
}
// creating a tmp variable (in which case we have a substitution for it)
while (decl instanceof TypedDeclaration) {
TypedDeclaration typedDecl = (TypedDeclaration) decl;
if (!naming.isSubstituted(decl) && typedDecl.getOriginalDeclaration() != null) {
decl = ((TypedDeclaration) decl).getOriginalDeclaration();
} else {
break;
}
}
// (the header might look like a field while the implementation is a getter)
if (decl.isNativeHeader()) {
Declaration d = ModelUtil.getNativeDeclaration(decl, Backend.Java);
if (d != null) {
decl = d;
}
}
// Explanation: primaryExpr and qualExpr both specify what is to come before the selector
// but the important difference is that primaryExpr is used for those situations where
// the result comes from the actual Ceylon code while qualExpr is used for those situations
// where we need to refer to synthetic objects (like wrapper classes for toplevel methods)
JCExpression qualExpr = null;
String selector = null;
// true for Java interop using fields, and for super constructor parameters, which must use
// parameters rather than getter methods
boolean mustUseField = false;
// true for default parameter methods
boolean mustUseParameter = false;
if (decl instanceof Functional && (!(decl instanceof Class) || ((Class) decl).getParameterList() != null) && (!(decl instanceof Function) || !decl.isParameter() || functionalParameterRequiresCallable((Function) decl, expr)) && isFunctionalResult(expr.getTypeModel())) {
result = transformFunctional(expr, (Functional) decl, expectedType);
} else if (coerced && decl instanceof Value && isFunctionalResult(expr.getTypeModel()) && checkForFunctionalInterface(expectedType) != null) {
result = transformFunctionalInterfaceBridge(expr, (Value) decl, expectedType);
} else if (coerced && decl instanceof Functional && decl.isParameter() && isFunctionalResult(expr.getTypeModel()) && checkForFunctionalInterface(expectedType) != null) {
result = transformFunctional(expr, (Functional) decl, expectedType);
// } else if (coerced
// && decl instanceof Value
// && isJavaFunctionalInterfaceResult(expr.getTypeModel())
// && expectedType != null
// && isCeylonCallable(expectedType)) {
// result = transformCallableBridge(expr, (Value)decl, expectedType);
} else if (Decl.isGetter(decl)) {
// invoke the getter
if (decl.isToplevel()) {
primaryExpr = null;
qualExpr = naming.makeName((Value) decl, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER);
selector = null;
} else if (decl.isClassOrInterfaceMember() && !ModelUtil.isLocalToInitializer(decl)) {
selector = naming.selector((Value) decl);
} else {
// method local attr
if (!isRecursiveReference(expr)) {
primaryExpr = naming.makeQualifiedName(primaryExpr, (Value) decl, Naming.NA_Q_LOCAL_INSTANCE);
}
selector = naming.selector((Value) decl);
}
} else if (Decl.isValueOrSharedOrCapturedParam(decl)) {
if (decl.isToplevel()) {
// ERASURE
if (isNullValue(decl)) {
result = makeNull();
} else if (isBooleanTrue(decl)) {
result = makeBoolean(true);
} else if (isBooleanFalse(decl)) {
result = makeBoolean(false);
} else {
// it's a toplevel attribute
primaryExpr = naming.makeName((TypedDeclaration) decl, Naming.NA_FQ | Naming.NA_WRAPPER);
selector = naming.selector((TypedDeclaration) decl);
}
} else if (Decl.isClassAttribute(decl) || Decl.isClassParameter(decl)) {
mustUseField = Decl.isJavaField(decl) || (isWithinSuperInvocation() && primaryExpr == null && withinSuperInvocation == decl.getContainer());
mustUseParameter = (primaryExpr == null && isWithinDefaultParameterExpression(decl.getContainer()));
if (mustUseField || mustUseParameter) {
if (decl instanceof FieldValue) {
selector = ((FieldValue) decl).getRealName();
} else if (decl.isParameter()) {
selector = Naming.getAliasedParameterName(((Value) decl).getInitializerParameter());
} else {
selector = decl.getName();
}
} else {
// invoke the getter, using the Java interop form of Util.getGetterName because this is the only case
// (Value inside a Class) where we might refer to JavaBean properties
selector = naming.selector((TypedDeclaration) decl);
}
} else if (ModelUtil.isCaptured(decl)) {
TypedDeclaration typedDecl = ((TypedDeclaration) decl);
TypeDeclaration typeDecl = typedDecl.getType().getDeclaration();
mustUseField = Decl.isBoxedVariable((TypedDeclaration) decl);
if (ModelUtil.isLocalNotInitializer(typeDecl) && typeDecl.isAnonymous() && // we need the box if it's a captured object
!typedDecl.isSelfCaptured()) {
// accessing a local 'object' declaration, so don't need a getter
} else if (decl.isCaptured() && !((TypedDeclaration) decl).isVariable() && // captured objects are never variable but need the box
!typedDecl.isSelfCaptured()) {
// accessing a local that is not getter wrapped
} else {
primaryExpr = naming.makeQualifiedName(primaryExpr, (TypedDeclaration) decl, Naming.NA_Q_LOCAL_INSTANCE);
selector = naming.selector((TypedDeclaration) decl);
}
}
} else if (Decl.isMethodOrSharedOrCapturedParam(decl)) {
mustUseParameter = (primaryExpr == null && decl.isParameter() && isWithinDefaultParameterExpression(decl.getContainer()));
if (!decl.isParameter() && (ModelUtil.isLocalNotInitializer(decl) || (ModelUtil.isLocalToInitializer(decl) && ((Function) decl).isDeferred()))) {
primaryExpr = null;
int flags = Naming.NA_MEMBER;
if (!isRecursiveReference(expr)) {
// Only want to quote the method name
// e.g. enum.$enum()
flags |= Naming.NA_WRAPPER_UNQUOTED;
} else if (!isReferenceInSameScope(expr)) {
// always qualify it with this
flags |= Naming.NA_WRAPPER | Naming.NA_WRAPPER_WITH_THIS;
}
qualExpr = naming.makeName((Function) decl, flags);
selector = null;
} else if (decl.isToplevel()) {
primaryExpr = null;
qualExpr = naming.makeName((Function) decl, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER);
selector = null;
} else if (!isWithinInvocation()) {
selector = null;
} else if (decl.isClassOrInterfaceMember()) {
selector = naming.selector((Function) decl);
} else {
selector = null;
}
}
boolean isCtor = decl instanceof Function && ((Function) decl).getTypeDeclaration() instanceof Constructor;
if (result == null) {
boolean useGetter = !(decl instanceof Function || isCtor) && !mustUseField && !mustUseParameter;
if (qualExpr == null && selector == null && !(isCtor)) {
useGetter = Decl.isClassAttribute(decl) && CodegenUtil.isErasedAttribute(decl.getName());
if (useGetter) {
selector = naming.selector((TypedDeclaration) decl);
} else {
selector = naming.substitute(decl);
}
}
if (qualExpr == null) {
qualExpr = primaryExpr;
}
// cases
if (!mustUseParameter) {
qualExpr = addQualifierForObjectMembersOfInterface(expr, decl, qualExpr);
qualExpr = addInterfaceImplAccessorIfRequired(qualExpr, expr, decl);
qualExpr = addThisOrObjectQualifierIfRequired(qualExpr, expr, decl);
if (qualExpr == null && expr instanceof Tree.BaseMemberExpression && needDollarThis(expr)) {
qualExpr = makeQualifiedDollarThis((Tree.BaseMemberExpression) expr);
}
}
boolean isEnumeratedConstructorGetter = false;
if ((decl instanceof Value && ModelUtil.isEnumeratedConstructor((Value) decl))) {
Class constructedClass = ModelUtil.getConstructedClass(decl);
// See CeylonVisitor.transformSingletonConstructor for that logic
if (constructedClass.isToplevel() || constructedClass.isClassMember())
isEnumeratedConstructorGetter = true;
else {
// Local enumerated constructor values are boxed
// local class will use a field
useGetter = false;
qualExpr = naming.makeQualifiedName(primaryExpr, (TypedDeclaration) decl, Naming.NA_Q_LOCAL_INSTANCE);
selector = naming.selector((TypedDeclaration) decl);
}
}
if (qualExpr == null && (decl.isStatic() || isEnumeratedConstructorGetter) && // and not classes
decl.getContainer() instanceof TypeDeclaration) {
qualExpr = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) decl.getContainer(), DeclNameFlag.QUALIFIED);
}
if (Decl.isPrivateAccessRequiringUpcast(expr)) {
qualExpr = makePrivateAccessUpcast(expr, qualExpr);
}
if (transformer != null) {
if (decl instanceof TypedDeclaration && ((TypedDeclaration) decl).getType().isTypeConstructor()) {
// This is a bit of a hack, but we're "invoking a type constructor"
// so recurse to get the applied expression.
qualExpr = transformMemberExpression(expr, qualExpr, null);
selector = null;
}
result = transformer.transform(qualExpr, selector);
} else {
Tree.Primary qmePrimary = null;
if (expr instanceof Tree.QualifiedMemberOrTypeExpression) {
qmePrimary = ((Tree.QualifiedMemberOrTypeExpression) expr).getPrimary();
}
boolean safeMemberJavaArray = expr instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) expr).getMemberOperator() instanceof Tree.SafeMemberOp && isJavaArray(qmePrimary.getTypeModel());
if ((safeMemberJavaArray || Decl.isValueTypeDecl(qmePrimary)) && // Safe operators always work on boxed things, so don't use value types
(safeMemberJavaArray || (expr instanceof Tree.QualifiedMemberOrTypeExpression == false) || ((Tree.QualifiedMemberOrTypeExpression) expr).getMemberOperator() instanceof Tree.MemberOp) && // We never want to use value types on boxed things, unless they are java arrays
(CodegenUtil.isUnBoxed(qmePrimary) || isJavaArray(qmePrimary.getTypeModel())) && // Java arrays length property does not go via value types
(!isJavaArray(qmePrimary.getTypeModel()) || (!"length".equals(selector) && !"hashCode".equals(selector)))) {
JCExpression primTypeExpr = makeJavaType(qmePrimary.getTypeModel(), JT_NO_PRIMITIVES | JT_VALUE_TYPE);
result = makeQualIdent(primTypeExpr, selector);
result = make().Apply(List.<JCTree.JCExpression>nil(), result, List.<JCTree.JCExpression>of(qualExpr));
} else if (expr instanceof Tree.QualifiedMemberOrTypeExpression && isThrowableMessage((Tree.QualifiedMemberOrTypeExpression) expr)) {
result = utilInvocation().throwableMessage(qualExpr);
} else if (expr instanceof Tree.QualifiedMemberOrTypeExpression && isThrowableSuppressed((Tree.QualifiedMemberOrTypeExpression) expr)) {
result = utilInvocation().suppressedExceptions(qualExpr);
} else {
result = makeQualIdent(qualExpr, selector);
if (useGetter) {
result = make().Apply(List.<JCTree.JCExpression>nil(), result, List.<JCTree.JCExpression>nil());
}
}
}
}
if (transformer == null && decl instanceof TypedDeclaration && ((TypedDeclaration) decl).getType().isTypeConstructor() && !expr.getTypeArguments().getTypeModels().isEmpty()) {
// applying a type constructor
ListBuffer<JCExpression> tds = new ListBuffer<JCExpression>();
for (Type t : expr.getTypeArguments().getTypeModels()) {
tds.add(makeReifiedTypeArgument(t));
}
result = make().Apply(null, makeQualIdent(result, Naming.Unfix.apply.toString()), List.<JCExpression>of(make().NewArray(make().Type(syms().ceylonTypeDescriptorType), List.<JCExpression>nil(), tds.toList())));
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.
the class ExpressionTransformer method makeAssignment.
private JCExpression makeAssignment(Node op, Tree.Term leftTerm, final JCExpression lhs, JCExpression rhs) {
TypedDeclaration decl;
if (leftTerm instanceof Tree.StaticMemberOrTypeExpression) {
decl = (TypedDeclaration) ((Tree.StaticMemberOrTypeExpression) leftTerm).getDeclaration();
} else if (leftTerm instanceof Tree.IndexExpression) {
// in this case lhs is null anyway, so let's discard it
return transformIndexAssignment(op, (Tree.IndexExpression) leftTerm, rhs);
} 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());
}
rhs = adjustRhs(decl, rhs);
JCExpression varExpr = makeAssignmentVariable(op, lhs, decl);
JCExpression result;
if (varExpr != null) {
result = at(op).Assign(varExpr, rhs);
} else {
ListBuffer<JCExpression> typeArguments = new ListBuffer<JCExpression>();
ListBuffer<JCExpression> reifiedTypeArguments = new ListBuffer<JCExpression>();
if (decl.isStatic() && ModelUtil.isCeylonDeclaration(decl)) {
Type primType = ((Tree.StaticMemberOrTypeExpression) leftTerm).getTarget().getQualifyingType();
if (primType != null) {
for (Type pt : primType.getTypeArgumentList()) {
typeArguments.add(makeJavaType(pt, JT_TYPE_ARGUMENT));
reifiedTypeArguments.add(makeReifiedTypeArgument(pt));
}
}
}
String selector = Naming.selector(decl, Naming.NA_SETTER);
result = make().Apply(typeArguments.toList(), makeQualIdent(lhs, selector), reifiedTypeArguments.toList().append(rhs));
}
return result;
}
Aggregations