use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class MethodDefinitionBuilder method getNonWideningParam.
public NonWideningParam getNonWideningParam(TypedReference typedRef, WideningRules wideningRules) {
TypedDeclaration nonWideningDecl = null;
int flags = 0;
Type nonWideningType;
FunctionOrValue mov = (FunctionOrValue) typedRef.getDeclaration();
if (Decl.isValue(mov)) {
TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef);
nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef);
nonWideningDecl = nonWideningTypedRef.getDeclaration();
} else {
// Stef: So here's the thing. I know this is wrong for Function where we should do getFullType(), BUT
// lots of methods call this and then feed the output into AT.makeJavaType(TypedDeclaration typeDecl, Type type, int flags)
// which adds the Callable type, so if we fix it here we have to remove it from there and there's lots of callers of that
// function which rely on its behaviour and frankly I've had enough of this refactoring, so a few callers of this function
// have to add the Callable back. It sucks, yeah, but so far it works, which is amazing enough that I don't want to touch it
// any more. More ambitious/courageous people are welcome to fix this properly.
nonWideningType = typedRef.getType();
nonWideningDecl = mov;
}
if (!CodegenUtil.isUnBoxed(nonWideningDecl))
flags |= AbstractTransformer.JT_NO_PRIMITIVES;
// make sure we don't accidentally narrow value parameters that would be erased in the topmost declaration
if (wideningRules != WideningRules.NONE && mov instanceof Value) {
TypedDeclaration refinedParameter = (TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(mov);
// mixin bridge methods have the same rules as when refining stuff except they are their own refined decl
if (wideningRules == WideningRules.FOR_MIXIN || !Decl.equal(refinedParameter, mov)) {
Type refinedParameterType;
// in the refined parameter type
if (refinedParameter instanceof Function)
refinedParameterType = refinedParameter.appliedTypedReference(null, Collections.<Type>emptyList()).getFullType();
else
refinedParameterType = refinedParameter.getType();
// if the supertype method itself got erased to Object, we can't do better than this
if (gen.willEraseToObject(refinedParameterType) && !gen.willEraseToBestBounds(mov))
nonWideningType = gen.typeFact().getObjectType();
else if (CodegenUtil.isRaw(refinedParameter)) {
flags |= AbstractTransformer.JT_RAW;
} else {
flags |= AbstractTransformer.JT_NARROWED;
}
}
}
// keep in sync with gen.willEraseToBestBounds()
if (wideningRules != WideningRules.NONE && (gen.typeFact().isUnion(nonWideningType) || gen.typeFact().isIntersection(nonWideningType))) {
final Type refinedType = ((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(nonWideningDecl)).getType();
if (refinedType.isTypeParameter() && !refinedType.getSatisfiedTypes().isEmpty()) {
nonWideningType = refinedType.getSatisfiedTypes().get(0);
// Could be parameterized, and type param won't be in scope, so have to go raw
flags |= AbstractTransformer.JT_RAW;
}
}
// this is to be done on the parameter's containing method, to see if that method must have raw parameters
if (mov.isParameter() && mov.getContainer() instanceof Declaration && gen.rawParameters((Declaration) mov.getContainer())) {
flags |= AbstractTransformer.JT_RAW;
}
return new NonWideningParam(flags, nonWideningType, nonWideningDecl);
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class Naming method addNamesForWrapperClass.
private <R> void addNamesForWrapperClass(TypeDeclarationBuilder<R> builder, TypedDeclaration decl, int namingOptions) {
if ((namingOptions & NA_FQ) != 0) {
if ((namingOptions & NA_WRAPPER) == 0 && (namingOptions & NA_WRAPPER_UNQUOTED) == 0) {
throw new BugException("If you pass FQ you must pass WRAPPER or WRAPPER_UNQUOTED too, or there's no class name to qualify!");
}
List<String> outerNames = null;
Scope s = decl.getContainer();
while (s != null) {
if (s instanceof Package) {
final List<String> packageName = ((Package) s).getName();
for (int ii = 0; ii < packageName.size(); ii++) {
if (ii == 0 && packageName.get(ii).isEmpty()) {
continue;
}
builder.select(quoteIfJavaKeyword(packageName.get(ii)));
}
break;
} else if (s instanceof ClassOrInterface) {
if (outerNames == null) {
outerNames = new ArrayList<String>(2);
}
outerNames.add(getQuotedClassName((ClassOrInterface) s, 0));
} else if (s instanceof TypedDeclaration) {
if (outerNames == null) {
outerNames = new ArrayList<String>(2);
}
outerNames.add(quoteIfJavaKeyword(((TypedDeclaration) s).getName()));
}
s = s.getContainer();
}
if (outerNames != null) {
for (int ii = outerNames.size() - 1; ii >= 0; ii--) {
String outerName = outerNames.get(ii);
builder.select(outerName);
}
}
}
if ((namingOptions & NA_WRAPPER) != 0) {
builder.select(getQuotedClassName(decl, namingOptions & (NA_GETTER | NA_SETTER)));
} else if ((namingOptions & NA_WRAPPER_UNQUOTED) != 0) {
builder.select(getRealName(decl, namingOptions & (NA_GETTER | NA_SETTER | NA_WRAPPER_UNQUOTED)));
} else if ((namingOptions & NA_Q_LOCAL_INSTANCE) != 0) {
if (Decl.isBoxedVariable(decl)) {
builder.select(getVariableBoxName(decl));
} else {
builder.select(getAttrClassName(decl, namingOptions & (NA_GETTER | NA_SETTER)));
}
}
if ((namingOptions & NA_WRAPPER_WITH_THIS) != 0) {
builder.select("this");
}
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration 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;
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class NamedArgumentInvocation method transformPrimary.
protected TransformedInvocationPrimary transformPrimary(JCExpression primaryExpr, String selector) {
if (Decl.isJavaStaticOrInterfacePrimary(getPrimary())) {
Declaration methodOrClass = ((Tree.QualifiedMemberOrTypeExpression) getPrimary()).getDeclaration();
if (methodOrClass instanceof Function) {
return new TransformedInvocationPrimary(gen.naming.makeName((Function) methodOrClass, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED), null);
} else if (methodOrClass instanceof Class) {
return new TransformedInvocationPrimary(gen.makeJavaType(((Class) methodOrClass).getType(), JT_RAW | JT_NO_PRIMITIVES), null);
}
}
if (isMemberRefInvocation()) {
JCExpression callable = gen.expressionGen().transformMemberReference((Tree.QualifiedMemberOrTypeExpression) getPrimary(), (Tree.MemberOrTypeExpression) getQmePrimary());
// The callable is a Callable we generate ourselves, it can never be erased to Object so there's no need to unerase
selector = Naming.getCallableMethodName();
return new TransformedInvocationPrimary(callable, selector);
}
JCExpression actualPrimExpr;
if (getPrimary() instanceof Tree.QualifiedTypeExpression && ((Tree.QualifiedTypeExpression) getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression && !Decl.isConstructor(getPrimaryDeclaration())) {
actualPrimExpr = gen.naming.makeQualifiedThis(primaryExpr);
} else {
actualPrimExpr = primaryExpr;
}
if (getPrimary() instanceof Tree.BaseTypeExpression) {
Tree.BaseTypeExpression type = (Tree.BaseTypeExpression) getPrimary();
Declaration declaration = type.getDeclaration();
if (Strategy.generateInstantiator(declaration)) {
if (Decl.withinInterface(declaration)) {
if (primaryExpr != null) {
// if we have some other primary then respect that
actualPrimExpr = primaryExpr;
} else {
// if the class being instantiated is
// within a class we expect the instantiation to be
// accessible from `this`, so use null
// otherwise we must be in an companion class, so we
// need to qualify the instantiator invocation with $this
actualPrimExpr = type.getScope().getInheritingDeclaration(declaration) instanceof Class ? null : gen.naming.makeQuotedThis();
}
} else if (declaration.isToplevel()) {
actualPrimExpr = null;
}
// if the decl is not toplevel (but the primary is a base type
// we must be invoking a member imported from an object
// in which case the qualifer is needed.
}
if (Decl.isConstructor(declaration)) {
selector = null;
}
} else {
if (getPrimary() instanceof Tree.QualifiedMemberOrTypeExpression) {
Tree.QualifiedMemberOrTypeExpression type = (Tree.QualifiedMemberOrTypeExpression) getPrimary();
Declaration declaration = type.getDeclaration();
if (Decl.isConstructor(declaration)) {
if (Decl.withinInterface(Decl.getConstructedClass(declaration))) {
if (Strategy.generateInstantiator(declaration)) {
actualPrimExpr = primaryExpr != null ? primaryExpr : gen.naming.makeQuotedThis();
} else {
actualPrimExpr = null;
}
}
}
} else if (getPrimary() instanceof Tree.BaseMemberOrTypeExpression) {
Tree.BaseMemberOrTypeExpression type = (Tree.BaseMemberOrTypeExpression) getPrimary();
Declaration declaration = type.getDeclaration();
if (Decl.isConstructor(declaration)) {
selector = null;
}
}
if (isIndirect()) {
if (getPrimaryDeclaration() != null && (Decl.isGetter(getPrimaryDeclaration()) || Decl.isToplevel(getPrimaryDeclaration()) || (Decl.isValueOrSharedOrCapturedParam(getPrimaryDeclaration()) && Decl.isCaptured(getPrimaryDeclaration()) && !Decl.isLocalNotInitializer(getPrimaryDeclaration())))) {
// We need to invoke the getter to obtain the Callable
actualPrimExpr = gen.make().Apply(null, gen.naming.makeQualIdent(primaryExpr, selector), List.<JCExpression>nil());
} else if (selector != null) {
actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
} else if (getPrimaryDeclaration() == null || !((TypedDeclaration) getPrimaryDeclaration()).getType().isTypeConstructor()) {
actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration) getPrimaryDeclaration(), Naming.NA_MEMBER);
}
actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
selector = Naming.getCallableVariadicMethodName();
this.callable = true;
} else {
selector = Naming.getCallableMethodName();
this.callable = true;
}
// If it's indirect the primary might be erased
actualPrimExpr = gen.expressionGen().applyErasureAndBoxing(actualPrimExpr, getPrimary().getTypeModel(), getPrimary().getTypeErased(), // boxed
true, BoxingStrategy.BOXED, getPrimary().getTypeModel(), 0);
} else if ((getPrimaryDeclaration() instanceof Function && // i.e. functional parameter
((Function) getPrimaryDeclaration()).isParameter() && // not class member, or not shared/captured
(!JvmBackendUtil.createMethod((Function) getPrimaryDeclaration())) || // we need to access the Callable parameter, no the member method
gen.expressionGen().isWithinDefaultParameterExpression(getPrimaryDeclaration().getContainer()))) {
if (selector != null) {
actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
} else {
actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration) getPrimaryDeclaration(), Naming.NA_MEMBER);
}
actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
selector = Naming.getCallableVariadicMethodName();
this.callable = true;
} else {
selector = Naming.getCallableMethodName();
this.callable = true;
}
}
}
return new TransformedInvocationPrimary(actualPrimExpr, selector);
}
use of com.redhat.ceylon.model.typechecker.model.TypedDeclaration in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformAssignment.
private JCExpression transformAssignment(Node op, Tree.Term leftTerm, JCExpression lhs, JCExpression rhs) {
JCExpression result = null;
// FIXME: can this be anything else than a Tree.StaticMemberOrTypeExpression or Tree.ParameterizedExpression?
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 {
// instanceof Tree.ParameterizedExpression
decl = (TypedDeclaration) ((Tree.MemberOrTypeExpression) ((Tree.ParameterizedExpression) leftTerm).getPrimary()).getDeclaration();
}
boolean variable = decl.isVariable();
at(op);
String selector = naming.selector(decl, Naming.NA_SETTER);
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()) {
JCExpression attr = gen().transformAttributeGetter(decl, rhs);
result = at(op).Assign(naming.makeQualifiedName(lhs, decl, Naming.NA_WRAPPER), attr);
} else {
// must use the setter
if (Decl.isLocal(decl)) {
lhs = naming.makeQualifiedName(lhs, decl, Naming.NA_WRAPPER | Naming.NA_SETTER);
} else if (decl.isStaticallyImportable()) {
lhs = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) decl.getContainer(), DeclNameFlag.QUALIFIED);
}
}
} else if (decl instanceof Function && Decl.isDeferred(decl)) {
if (Decl.isLocal(decl)) {
// Deferred method initialization of a local function
// The Callable field has the same name as the method, so use NA_MEMBER
result = at(op).Assign(naming.makeQualifiedName(lhs, decl, Naming.NA_WRAPPER_UNQUOTED | Naming.NA_MEMBER), rhs);
} else {
// Deferred method initialization of a class function
result = at(op).Assign(naming.makeQualifiedName(lhs, decl, Naming.NA_MEMBER), rhs);
}
} else if ((variable || decl.isLate()) && (Decl.isClassAttribute(decl))) {
// must use the setter, nothing to do, unless it's a java field
if (Decl.isJavaField(decl)) {
if (decl.isStaticallyImportable()) {
// static field
result = at(op).Assign(naming.makeName(decl, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED), rhs);
} else {
// normal field
result = at(op).Assign(naming.makeQualifiedName(lhs, decl, Naming.NA_IDENT), rhs);
}
}
} else if (variable && (decl.isCaptured() || decl.isShared())) {
// must use the qualified setter
if (Decl.isBoxedVariable(decl)) {
result = at(op).Assign(naming.makeName(decl, Naming.NA_Q_LOCAL_INSTANCE | Naming.NA_MEMBER | Naming.NA_SETTER), rhs);
} else if (Decl.isLocalNotInitializer(decl)) {
lhs = naming.makeQualifiedName(lhs, decl, Naming.NA_WRAPPER);
} else if (isWithinSuperInvocation() && decl.isCaptured() && decl.isVariable()) {
lhs = naming.makeUnquotedIdent(Naming.getAliasedParameterName(((Value) decl).getInitializerParameter()));
result = at(op).Assign(lhs, rhs);
}
} else {
result = at(op).Assign(naming.makeQualifiedName(lhs, decl, Naming.NA_IDENT), rhs);
}
if (result == null) {
result = make().Apply(List.<JCTree.JCExpression>nil(), makeQualIdent(lhs, selector), List.<JCTree.JCExpression>of(rhs));
}
return result;
}
Aggregations