use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.
the class AbstractTransformer method makeTypeArgs.
private ListBuffer<JCExpression> makeTypeArgs(boolean isCeylonCallable, int flags, Map<TypeParameter, Type> tas, java.util.List<TypeParameter> tps, Type simpleType) {
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
for (TypeParameter tp : tps) {
Type ta = tas.get(tp);
// error handling
if (ta == null)
continue;
boolean isDependedOn = hasDependentTypeParameters(tps, tp);
// record whether we were initially working with Anything, because getNonNullType turns it into Object
// and we need to treat "in Anything" specially below
boolean isAnything = isAnything(ta);
// we want, so we make sure it's not Null
if (isOptional(ta) && !isNull(ta)) {
// For an optional type T?:
// - The Ceylon type Foo<T?> results in the Java type Foo<T>.
ta = getNonNullType(ta);
}
// In a type argument Foo<X&Object> or Foo<X?> transform to just Foo<X>
ta = simplifyType(ta);
if (typeFact().isUnion(ta) || typeFact().isIntersection(ta)) {
// conform with where raw types would be used between expressions and constructors
if (((flags & (JT_EXTENDS | JT_SATISFIES)) != 0 && tp.getSelfTypedDeclaration() != null)) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
typeArgs = null;
break;
} else if ((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) == 0) {
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
typeArgs = null;
break;
}
// otherwise just go on
}
if (isCeylonBoolean(ta) && !isTypeParameter(ta)) {
ta = typeFact.getBooleanType();
}
JCExpression jta;
if (!tp.getSatisfiedTypes().isEmpty()) {
boolean needsCastForBounds = false;
for (Type bound : tp.getSatisfiedTypes()) {
bound = bound.substitute(tas, null);
needsCastForBounds |= expressionGen().needsCast(ta, bound, false, false, false);
}
if (needsCastForBounds) {
// replace with the first bound
ta = tp.getSatisfiedTypes().get(0).substitute(tas, null);
if (tp.getSatisfiedTypes().size() > 1 || isBoundsSelfDependant(tp) || isBoundsRecursive(simpleType, tp) || willEraseToObject(ta) || // we should reject it for all non-covariant types, unless we're in satisfies/extends
((flags & (JT_SATISFIES | JT_EXTENDS)) == 0 && !simpleType.isCovariant(tp))) {
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
typeArgs = null;
break;
}
}
}
if (ta.isExactlyNothing() || // use the same erasure rules as bottom: prefer wildcards
((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) != 0 && (typeFact().isUnion(ta) || typeFact().isIntersection(ta)))) {
// For the bottom type Bottom:
if ((flags & (JT_CLASS_NEW)) != 0) {
// A bit ugly, but we need to escape from the loop and create a raw type, no generics
if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
typeArgs = null;
break;
} else {
// Foo<Object> (see https://github.com/ceylon/ceylon-compiler/issues/633 for why)
if ((flags & (JT_SATISFIES | JT_EXTENDS)) != 0) {
if (ta.isExactlyNothing()) {
jta = make().Type(syms().objectType);
} else {
if (!tp.getSatisfiedTypes().isEmpty()) {
// union or intersection: Use the common upper bound of the types
jta = makeJavaType(tp.getSatisfiedTypes().get(0), JT_TYPE_ARGUMENT);
} else {
jta = make().Type(syms().objectType);
}
}
} else if (ta.isExactlyNothing()) {
// see https://github.com/ceylon/ceylon-compiler/issues/1003
if (simpleType.isContravariant(tp)) {
typeArgs = null;
break;
} else if (tp.isCovariant() && !isDependedOn) {
// DO NOT trust use-site covariance for Nothing, because we consider "out Nothing" to be the same
// as "Nothing". Only look at declaration-site covariance
jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), make().Type(syms().objectType));
} else {
jta = make().Type(syms().objectType);
}
} else {
// see https://github.com/ceylon/ceylon/issues/6365
if (((flags & JT_CLASS_NEW) == 0) && simpleType.isContravariant(tp)) /* && !isDependedOn*/
{
jta = make().Wildcard(make().TypeBoundKind(BoundKind.SUPER), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else if (((flags & JT_CLASS_NEW) == 0) && simpleType.isCovariant(tp) && !isDependedOn) {
jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else {
jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
}
}
}
} else {
// For an ordinary class or interface type T:
if ((flags & (JT_SATISFIES | JT_EXTENDS)) != 0) {
// - The Ceylon type Foo<T> appearing in an extends or satisfies clause
// results in the Java type Foo<T>
jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
} else {
// - Foo<? super T> if Foo is contravariant in T
if (((flags & JT_CLASS_NEW) == 0) && simpleType.isContravariant(tp) && (!isAnything || tp.isContravariant())) // FIXME: it may be necessary to uncomment this in the future,
// see https://github.com/ceylon/ceylon/issues/6365
/*&& !isDependedOn*/
{
// DO NOT trust use-site contravariance for Anything, because we consider "in Anything" to be the same
// as "Anything". Only look at declaration-site contravariance
jta = make().Wildcard(make().TypeBoundKind(BoundKind.SUPER), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else if (((flags & JT_CLASS_NEW) == 0) && simpleType.isCovariant(tp) && !isDependedOn) {
jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), makeJavaType(ta, JT_TYPE_ARGUMENT));
} else {
jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
}
}
}
typeArgs.add(jta);
if (isCeylonCallable) {
// In the runtime Callable only has a single type param
break;
}
}
return typeArgs;
}
use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.
the class AbstractTransformer method makeAtLocalContainer.
protected List<JCAnnotation> makeAtLocalContainer(List<String> path, String companionClassName) {
if (path.isEmpty())
return List.nil();
ListBuffer<JCExpression> array = new ListBuffer<JCTree.JCExpression>();
for (String val : path) array.add(make().Literal(val));
JCExpression pathAttr = make().Assign(naming.makeUnquotedIdent("path"), make().NewArray(null, null, array.toList()));
JCExpression companionAttr = make().Assign(naming.makeUnquotedIdent("companionClassName"), make().Literal(companionClassName == null ? "" : companionClassName));
return makeModelAnnotation(syms().ceylonAtLocalContainerType, List.of(pathAttr, companionAttr));
}
use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.
the class AbstractTransformer method getLicenseAuthorsDocAnnotationArguments.
/**
* Returns a ListBuffer with assignment expressions for the doc, license and by arguments, as well as name,
* to be used in an annotation which requires them (such as Module and Package)
*/
ListBuffer<JCExpression> getLicenseAuthorsDocAnnotationArguments(String name, java.util.List<Annotation> anns) {
ListBuffer<JCExpression> authors = new ListBuffer<JCTree.JCExpression>();
ListBuffer<JCExpression> res = new ListBuffer<JCExpression>();
res.add(make().Assign(naming.makeUnquotedIdent("name"), make().Literal(name)));
for (Annotation a : anns) {
if (a.getPositionalArguments() != null && !a.getPositionalArguments().isEmpty()) {
if (a.getName().equals("doc")) {
res.add(make().Assign(naming.makeUnquotedIdent("doc"), make().Literal(a.getPositionalArguments().get(0))));
} else if (a.getName().equals("label")) {
res.add(make().Assign(naming.makeUnquotedIdent("label"), make().Literal(a.getPositionalArguments().get(0))));
} else if (a.getName().equals("license")) {
res.add(make().Assign(naming.makeUnquotedIdent("license"), make().Literal(a.getPositionalArguments().get(0))));
} else if (a.getName().equals("by")) {
for (String author : a.getPositionalArguments()) {
authors.add(make().Literal(author));
}
}
}
}
if (!authors.isEmpty()) {
res.add(make().Assign(naming.makeUnquotedIdent("by"), make().NewArray(null, null, authors.toList())));
}
return res;
}
use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.
the class AbstractTransformer method makeReifiedTypeArgumentResolved.
private JCExpression makeReifiedTypeArgumentResolved(Type pt, boolean qualified, TypeArgumentAccessor typeArgumentAccessor, boolean wantsRaw) {
if (pt.isUnion()) {
// FIXME: refactor this shite
List<JCExpression> typeTestArguments = List.nil();
java.util.List<Type> typeParameters = pt.getCaseTypes();
if (typeParameters.size() == 2) {
Type alternative = null;
if (typeParameters.get(0).isEmpty())
alternative = typeParameters.get(1);
else if (typeParameters.get(1).isEmpty())
alternative = typeParameters.get(0);
if (alternative != null && alternative.isTuple()) {
JCExpression tupleType = makeTupleTypeDescriptor(alternative, true);
if (tupleType != null)
return tupleType;
}
}
for (int i = typeParameters.size() - 1; i >= 0; i--) {
typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
}
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "union"), typeTestArguments);
} else if (pt.isIntersection()) {
List<JCExpression> typeTestArguments = List.nil();
java.util.List<Type> typeParameters = pt.getSatisfiedTypes();
for (int i = typeParameters.size() - 1; i >= 0; i--) {
typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
}
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "intersection"), typeTestArguments);
} else if (pt.isNothing()) {
return makeNothingTypeDescriptor();
}
TypeDeclaration declaration = pt.getDeclaration();
if (declaration instanceof Constructor) {
pt = pt.getExtendedType();
declaration = pt.getDeclaration();
}
if (pt.isClassOrInterface()) {
// see if we have an alias for it
if (supportsReifiedAlias((ClassOrInterface) declaration)) {
JCExpression qualifier = naming.makeDeclarationName(declaration, DeclNameFlag.QUALIFIED);
return makeSelect(qualifier, naming.getTypeDescriptorAliasName());
}
if (pt.isTuple()) {
JCExpression tupleType = makeTupleTypeDescriptor(pt, false);
if (tupleType != null)
return tupleType;
}
// no alias, must build it
List<JCExpression> typeTestArguments;
JCExpression thisType = makeUnerasedClassLiteral(declaration);
if (!wantsRaw) {
typeTestArguments = makeReifiedTypeArgumentsResolved(pt.getTypeArgumentList(), qualified, typeArgumentAccessor);
// do we have variance overrides?
Map<TypeParameter, SiteVariance> varianceOverrides = pt.getVarianceOverrides();
if (!varianceOverrides.isEmpty()) {
// we need to pass them as second argument then, in an array
ListBuffer<JCExpression> varianceElements = new ListBuffer<JCExpression>();
for (TypeParameter typeParameter : declaration.getTypeParameters()) {
SiteVariance useSiteVariance = varianceOverrides.get(typeParameter);
String selector;
if (useSiteVariance != null) {
switch(useSiteVariance) {
case IN:
selector = "IN";
break;
case OUT:
selector = "OUT";
break;
default:
selector = "NONE";
break;
}
} else {
selector = "NONE";
}
JCExpression varianceElement = make().Select(makeIdent(syms().ceylonVarianceType), names().fromString(selector));
varianceElements.append(varianceElement);
}
JCNewArray varianceArray = make().NewArray(makeIdent(syms().ceylonVarianceType), List.<JCExpression>nil(), varianceElements.toList());
typeTestArguments = typeTestArguments.prepend(varianceArray);
}
} else {
typeTestArguments = List.nil();
}
typeTestArguments = typeTestArguments.prepend(thisType);
JCExpression classDescriptor = make().Apply(null, makeSelect(makeTypeDescriptorType(), "klass"), typeTestArguments);
Type qualifyingType = pt.getQualifyingType();
JCExpression containerType = null;
if (qualifyingType == null) {
// it may be contained in a function or value, and we want its type
// or static class members may have no qualifying type but we want the TDs to treat
// them as members anyway
Declaration enclosingDeclaration = getDeclarationContainer(declaration);
if (enclosingDeclaration instanceof TypedDeclaration)
containerType = makeTypedDeclarationTypeDescriptorResolved((TypedDeclaration) enclosingDeclaration, typeArgumentAccessor);
else if (enclosingDeclaration instanceof TypeDeclaration) {
qualifyingType = ((TypeDeclaration) enclosingDeclaration).getType();
}
}
if (qualifyingType != null && qualifyingType.isConstructor()) {
qualifyingType = qualifyingType.getQualifyingType();
}
if (qualifyingType != null) {
if (declaration.isStatic() && supportsReified(declaration)) {
// There is no outer instance with a $reified$T field
final Type t = pt;
containerType = makeReifiedTypeArgumentResolved(qualifyingType, true, new TypeArgumentAccessor() {
public JCExpression getTypeDescriptor(TypeParameter tp, boolean qualified) {
return makeSelect(naming.makeQualifiedThis(makeJavaType(t, JT_RAW)), naming.getTypeArgumentDescriptorName(tp));
}
}, false);
} else {
containerType = makeReifiedTypeArgumentResolved(qualifyingType, true, typeArgumentAccessor, // we want raw containers, since we can't capture their TPs
declaration.isStatic());
}
}
if (containerType == null) {
return classDescriptor;
} else {
return make().Apply(null, makeSelect(makeTypeDescriptorType(), "member"), List.of(containerType, classDescriptor));
}
} else if (pt.isTypeParameter()) {
return typeArgumentAccessor.getTypeDescriptor((TypeParameter) declaration, qualified);
} else {
throw BugException.unhandledDeclarationCase(declaration);
}
}
use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.
the class AbstractTransformer method makeAtAnnotation.
private JCExpression makeAtAnnotation(Annotation annotation) {
JCExpression valueAttribute = make().Assign(naming.makeUnquotedIdent("value"), make().Literal(annotation.getName()));
List<JCExpression> attributes;
if (!annotation.getPositionalArguments().isEmpty()) {
java.util.List<String> positionalArguments = annotation.getPositionalArguments();
ListBuffer<JCExpression> array = new ListBuffer<JCTree.JCExpression>();
for (String val : positionalArguments) array.add(make().Literal(val));
JCExpression argumentsAttribute = make().Assign(naming.makeUnquotedIdent("arguments"), make().NewArray(null, null, array.toList()));
attributes = List.of(valueAttribute, argumentsAttribute);
} else if (!annotation.getNamedArguments().isEmpty()) {
Map<String, String> namedArguments = annotation.getNamedArguments();
ListBuffer<JCExpression> array = new ListBuffer<JCTree.JCExpression>();
for (Entry<String, String> entry : namedArguments.entrySet()) {
JCExpression argNameAttribute = make().Assign(naming.makeUnquotedIdent("name"), make().Literal(entry.getKey()));
JCExpression argValueAttribute = make().Assign(naming.makeUnquotedIdent("value"), make().Literal(entry.getValue()));
JCAnnotation namedArg = make().Annotation(makeIdent(syms().ceylonAtNamedArgumentType), List.of(argNameAttribute, argValueAttribute));
array.add(namedArg);
}
JCExpression argumentsAttribute = make().Assign(naming.makeUnquotedIdent("namedArguments"), make().NewArray(null, null, array.toList()));
attributes = List.of(valueAttribute, argumentsAttribute);
} else
attributes = List.of(valueAttribute);
return make().Annotation(makeIdent(syms().ceylonAtAnnotationType), attributes);
}
Aggregations