use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Resolve method findInheritedMemberType.
/**
* Find a member type inherited from a superclass or interface.
* @param env The current environment.
* @param site The original type from where the selection takes
* place.
* @param name The type's name.
* @param c The class to search for the member type. This is
* always a superclass or implemented interface of
* site's class.
*/
Symbol findInheritedMemberType(Env<AttrContext> env, Type site, Name name, TypeSymbol c) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
Type st = types.supertype(c.type);
if (st != null && st.hasTag(CLASS)) {
sym = findMemberType(env, site, name, st.tsym);
if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
for (List<Type> l = types.interfaces(c.type); bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); l = l.tail) {
sym = findMemberType(env, site, name, l.head.tsym);
if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS && sym.owner != bestSoFar.owner)
bestSoFar = new AmbiguityError(bestSoFar, sym);
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
return bestSoFar;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Resolve method findIdentInType.
/**
* Find an identifier among the members of a given type `site'.
* @param env The current environment.
* @param site The type containing the symbol to be found.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP).
*/
Symbol findIdentInType(Env<AttrContext> env, Type site, Name name, int kind) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
if ((kind & VAR) != 0) {
sym = findField(env, site, name, site.tsym);
if (sym.exists())
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
if ((kind & TYP) != 0) {
sym = findMemberType(env, site, name, site.tsym);
if (sym.exists())
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
return bestSoFar;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Resolve method mostSpecific.
/* Return the most specific of the two methods for a call,
* given that both are accessible and applicable.
* @param m1 A new candidate for most specific.
* @param m2 The previous most specific candidate.
* @param env The current environment.
* @param site The original type from where the selection
* takes place.
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
Symbol mostSpecific(List<Type> argtypes, Symbol m1, Symbol m2, Env<AttrContext> env, final Type site, boolean allowBoxing, boolean useVarargs) {
switch(m2.kind) {
case MTH:
if (m1 == m2)
return m1;
boolean m1SignatureMoreSpecific = signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
boolean m2SignatureMoreSpecific = signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
Type mt1 = types.memberType(site, m1);
Type mt2 = types.memberType(site, m2);
if (!types.overrideEquivalent(mt1, mt2))
return ambiguityError(m1, m2);
// one, or (d) merge both abstract signatures
if ((m1.flags() & BRIDGE) != (m2.flags() & BRIDGE))
return ((m1.flags() & BRIDGE) != 0) ? m2 : m1;
// if one overrides or hides the other, use it
TypeSymbol m1Owner = (TypeSymbol) m1.owner;
TypeSymbol m2Owner = (TypeSymbol) m2.owner;
if (types.asSuper(m1Owner.type, m2Owner) != null && ((m1.owner.flags_field & INTERFACE) == 0 || (m2.owner.flags_field & INTERFACE) != 0) && m1.overrides(m2, m1Owner, types, false))
return m1;
if (types.asSuper(m2Owner.type, m1Owner) != null && ((m2.owner.flags_field & INTERFACE) == 0 || (m1.owner.flags_field & INTERFACE) != 0) && m2.overrides(m1, m2Owner, types, false))
return m2;
boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
if (m1Abstract && !m2Abstract)
return m2;
if (m2Abstract && !m1Abstract)
return m1;
// both abstract or both concrete
return ambiguityError(m1, m2);
}
if (m1SignatureMoreSpecific)
return m1;
if (m2SignatureMoreSpecific)
return m2;
return ambiguityError(m1, m2);
case AMBIGUOUS:
// compare m1 to ambiguous methods in m2
AmbiguityError e = (AmbiguityError) m2.baseSymbol();
boolean m1MoreSpecificThanAnyAmbiguous = true;
boolean allAmbiguousMoreSpecificThanM1 = true;
for (Symbol s : e.ambiguousSyms) {
Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs);
m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1;
allAmbiguousMoreSpecificThanM1 &= moreSpecific == s;
}
if (m1MoreSpecificThanAnyAmbiguous)
return m1;
// more specific than m1, add it as a new ambiguous method:
if (!allAmbiguousMoreSpecificThanM1)
e.addAmbiguousSymbol(m1);
return e;
default:
throw new AssertionError();
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Annotate method enterAttributeValue.
Attribute enterAttributeValue(Type expected, JCExpression tree, Env<AttrContext> env) {
// ordinary resolution diagnostic.
try {
expected.tsym.complete();
} catch (CompletionFailure e) {
log.error(tree.pos(), "cant.resolve", Kinds.kindName(e.sym), e.sym);
expected = syms.errType;
}
if (expected.hasTag(ARRAY)) {
if (!tree.hasTag(NEWARRAY)) {
tree = make.at(tree.pos).NewArray(null, List.<JCExpression>nil(), List.of(tree));
}
JCNewArray na = (JCNewArray) tree;
if (na.elemtype != null) {
log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
}
ListBuffer<Attribute> buf = new ListBuffer<Attribute>();
for (List<JCExpression> l = na.elems; l.nonEmpty(); l = l.tail) {
buf.append(enterAttributeValue(types.elemtype(expected), l.head, env));
}
na.type = expected;
return new Attribute.Array(expected, buf.toArray(new Attribute[buf.length()]));
}
if (tree.hasTag(NEWARRAY)) {
// error recovery
if (!expected.isErroneous())
log.error(tree.pos(), "annotation.value.not.allowable.type");
JCNewArray na = (JCNewArray) tree;
if (na.elemtype != null) {
log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
}
for (List<JCExpression> l = na.elems; l.nonEmpty(); l = l.tail) {
enterAttributeValue(syms.errType, l.head, env);
}
return new Attribute.Error(syms.errType);
}
if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) {
if (tree.hasTag(ANNOTATION)) {
return enterAnnotation((JCAnnotation) tree, expected, env);
} else {
log.error(tree.pos(), "annotation.value.must.be.annotation");
expected = syms.errType;
}
}
if (tree.hasTag(ANNOTATION)) {
// error recovery
if (!expected.isErroneous())
log.error(tree.pos(), "annotation.not.valid.for.type", expected);
enterAnnotation((JCAnnotation) tree, syms.errType, env);
return new Attribute.Error(((JCAnnotation) tree).annotationType.type);
}
if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) {
Type result = attr.attribExpr(tree, env, expected);
if (result.isErroneous())
return new Attribute.Error(result.getOriginalType());
if (result.constValue() == null) {
log.error(tree.pos(), "attribute.value.must.be.constant");
return new Attribute.Error(expected);
}
result = cfolder.coerce(result, expected);
return new Attribute.Constant(expected, result.constValue());
}
if (expected.tsym == syms.classType.tsym) {
Type result = attr.attribExpr(tree, env, expected);
if (result.isErroneous()) {
// Does it look like an unresolved class literal?
if (TreeInfo.name(tree) == names._class && ((JCFieldAccess) tree).selected.type.isErroneous()) {
Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName();
return new Attribute.UnresolvedClass(expected, types.createErrorType(n, syms.unknownSymbol, syms.classType));
} else {
return new Attribute.Error(result.getOriginalType());
}
}
// at the tree level
if (TreeInfo.name(tree) != names._class) {
log.error(tree.pos(), "annotation.value.must.be.class.literal");
return new Attribute.Error(syms.errType);
}
return new Attribute.Class(types, (((JCFieldAccess) tree).selected).type);
}
if (expected.hasTag(CLASS) && (expected.tsym.flags() & Flags.ENUM) != 0) {
Type result = attr.attribExpr(tree, env, expected);
Symbol sym = TreeInfo.symbol(tree);
if (sym == null || TreeInfo.nonstaticSelect(tree) || sym.kind != Kinds.VAR || (sym.flags() & Flags.ENUM) == 0) {
log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
return new Attribute.Error(result.getOriginalType());
}
VarSymbol enumerator = (VarSymbol) sym;
return new Attribute.Enum(expected, enumerator);
}
// error recovery:
if (!expected.isErroneous())
log.error(tree.pos(), "annotation.value.not.allowable.type");
return new Attribute.Error(attr.attribExpr(tree, env, expected));
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.
the class Annotate method validateContainer.
/* Validate that the suggested targetContainerType Type is a valid
* container type for repeated instances of originalAnnoType
* annotations. Return null and report errors if this is not the
* case, return the MethodSymbol of the value element in
* targetContainerType if it is suitable (this is needed to
* synthesize the container). */
private MethodSymbol validateContainer(Type targetContainerType, Type originalAnnoType, DiagnosticPosition pos) {
MethodSymbol containerValueSymbol = null;
boolean fatalError = false;
// Validate that there is a (and only 1) value method
Scope scope = targetContainerType.tsym.members();
int nr_value_elems = 0;
boolean error = false;
for (Symbol elm : scope.getElementsByName(names.value)) {
nr_value_elems++;
if (nr_value_elems == 1 && elm.kind == Kinds.MTH) {
containerValueSymbol = (MethodSymbol) elm;
} else {
error = true;
}
}
if (error) {
log.error(pos, "invalid.repeatable.annotation.multiple.values", targetContainerType, nr_value_elems);
return null;
} else if (nr_value_elems == 0) {
log.error(pos, "invalid.repeatable.annotation.no.value", targetContainerType);
return null;
}
// probably "impossible" to fail this
if (containerValueSymbol.kind != Kinds.MTH) {
log.error(pos, "invalid.repeatable.annotation.invalid.value", targetContainerType);
fatalError = true;
}
// validate that the 'value' element has the correct return type
// i.e. array of original anno
Type valueRetType = containerValueSymbol.type.getReturnType();
Type expectedType = types.makeArrayType(originalAnnoType);
if (!(types.isArray(valueRetType) && types.isSameType(expectedType, valueRetType))) {
log.error(pos, "invalid.repeatable.annotation.value.return", targetContainerType, valueRetType, expectedType);
fatalError = true;
}
if (error) {
fatalError = true;
}
return fatalError ? null : containerValueSymbol;
}
Aggregations