use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method visitTypeApply.
/**
* Visitor method for parameterized types.
* Bound checking is left until later, since types are attributed
* before supertype structure is completely known
*/
public void visitTypeApply(JCTypeApply tree) {
Type owntype = types.createErrorType(tree.type);
// Attribute functor part of application and make sure it's a class.
Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env));
// Attribute type parameters
List<Type> actuals = attribTypes(tree.arguments, env);
if (clazztype.hasTag(CLASS)) {
List<Type> formals = clazztype.tsym.type.getTypeArguments();
if (// diamond
actuals.isEmpty())
actuals = formals;
if (actuals.length() == formals.length()) {
List<Type> a = actuals;
List<Type> f = formals;
while (a.nonEmpty()) {
a.head = a.head.withTypeVar(f.head);
a = a.tail;
f = f.tail;
}
// Compute the proper generic outer
Type clazzOuter = clazztype.getEnclosingType();
if (clazzOuter.hasTag(CLASS)) {
Type site;
JCExpression clazz = TreeInfo.typeIn(tree.clazz);
if (clazz.hasTag(IDENT)) {
site = env.enclClass.sym.type;
} else if (clazz.hasTag(SELECT)) {
site = ((JCFieldAccess) clazz).selected.type;
} else
throw new AssertionError("" + tree);
if (clazzOuter.hasTag(CLASS) && site != clazzOuter) {
if (site.hasTag(CLASS))
site = types.asOuterSuper(site, clazzOuter.tsym);
if (site == null)
site = types.erasure(clazzOuter);
clazzOuter = site;
}
}
owntype = new ClassType(clazzOuter, actuals, clazztype.tsym);
} else {
if (formals.length() != 0) {
log.error(tree.pos(), "wrong.number.type.args", Integer.toString(formals.length()));
} else {
log.error(tree.pos(), "type.doesnt.take.params", clazztype.tsym);
}
owntype = types.createErrorType(tree.type);
}
}
result = check(tree, owntype, TYP, resultInfo);
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method visitApply.
/**
* Visitor method for method invocations.
* NOTE: The method part of an application will have in its type field
* the return type of the method, not the method's type itself!
*/
public void visitApply(JCMethodInvocation tree) {
// The local environment of a method application is
// a new environment nested in the current one.
Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
// The types of the actual method arguments.
List<Type> argtypes;
// The types of the actual method type arguments.
List<Type> typeargtypes = null;
Name methName = TreeInfo.name(tree.meth);
boolean isConstructorCall = methName == names._this || methName == names._super;
ListBuffer<Type> argtypesBuf = new ListBuffer<>();
if (isConstructorCall) {
// Check that this is the first statement in a constructor.
if (checkFirstConstructorStat(tree, env)) {
// Record the fact
// that this is a constructor call (using isSelfCall).
localEnv.info.isSelfCall = true;
// Attribute arguments, yielding list of argument types.
int kind = attribArgs(MTH, tree.args, localEnv, argtypesBuf);
argtypes = argtypesBuf.toList();
typeargtypes = attribTypes(tree.typeargs, localEnv);
// Variable `site' points to the class in which the called
// constructor is defined.
Type site = env.enclClass.sym.type;
if (methName == names._super) {
if (site == syms.objectType) {
log.error(tree.meth.pos(), "no.superclass", site);
site = types.createErrorType(syms.objectType);
} else {
site = types.supertype(site);
}
}
if (site.hasTag(CLASS)) {
Type encl = site.getEnclosingType();
while (encl != null && encl.hasTag(TYPEVAR)) encl = encl.getUpperBound();
if (encl.hasTag(CLASS)) {
if (tree.meth.hasTag(SELECT)) {
JCTree qualifier = ((JCFieldAccess) tree.meth).selected;
// We are seeing a prefixed call, of the form
// <expr>.super(...).
// Check that the prefix expression conforms
// to the outer instance type of the class.
chk.checkRefType(qualifier.pos(), attribExpr(qualifier, localEnv, encl));
} else if (methName == names._super) {
// qualifier omitted; check for existence
// of an appropriate implicit qualifier.
rs.resolveImplicitThis(tree.meth.pos(), localEnv, site, true);
}
} else if (tree.meth.hasTag(SELECT)) {
log.error(tree.meth.pos(), "illegal.qual.not.icls", site.tsym);
}
// prefix the implicit String and int parameters
if (site.tsym == syms.enumSym && allowEnums)
argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);
// Resolve the called constructor under the assumption
// that we are referring to a superclass instance of the
// current instance (JLS ???).
boolean selectSuperPrev = localEnv.info.selectSuper;
localEnv.info.selectSuper = true;
localEnv.info.pendingResolutionPhase = null;
Symbol sym = rs.resolveConstructor(tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
localEnv.info.selectSuper = selectSuperPrev;
// Set method symbol to resolved constructor...
TreeInfo.setSymbol(tree.meth, sym);
// ...and check that it is legal in the current context.
// (this will also set the tree's type)
Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
checkId(tree.meth, site, sym, localEnv, new ResultInfo(kind, mpt));
}
// Otherwise, `site' is an error type and we do nothing
}
result = tree.type = syms.voidType;
} else {
// Otherwise, we are seeing a regular method call.
// Attribute the arguments, yielding list of argument types, ...
int kind = attribArgs(VAL, tree.args, localEnv, argtypesBuf);
argtypes = argtypesBuf.toList();
typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
// ... and attribute the method using as a prototype a methodtype
// whose formal argument types is exactly the list of actual
// arguments (this will also set the method symbol).
Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
localEnv.info.pendingResolutionPhase = null;
Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(kind, mpt, resultInfo.checkContext));
// Compute the result type.
Type restype = mtype.getReturnType();
if (restype.hasTag(TypeTag.WILDCARD))
throw new AssertionError(mtype);
Type qualifier = (tree.meth.hasTag(SELECT)) ? ((JCFieldAccess) tree.meth).selected.type : env.enclClass.sym.type;
restype = adjustMethodReturnType(qualifier, methName, argtypes, restype);
chk.checkRefTypes(tree.typeargs, typeargtypes);
// Check that value of resulting type is admissible in the
// current context. Also, capture the return type
result = check(tree, capture(restype), VAL, resultInfo);
}
chk.validate(tree.typeargs, localEnv);
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method lambdaEnv.
/* This method returns an environment to be used to attribute a lambda
* expression.
*
* The owner of this environment is a method symbol. If the current owner
* is not a method, for example if the lambda is used to initialize
* a field, then if the field is:
*
* - an instance field, we use the first constructor.
* - a static field, we create a fake clinit method.
*/
public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
Env<AttrContext> lambdaEnv;
Symbol owner = env.info.scope.owner;
if (owner.kind == VAR && owner.owner.kind == TYP) {
// field initializer
lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared()));
ClassSymbol enclClass = owner.enclClass();
/* if the field isn't static, then we can get the first constructor
* and use it as the owner of the environment. This is what
* LTM code is doing to look for type annotations so we are fine.
*/
if ((owner.flags() & STATIC) == 0) {
for (Symbol s : enclClass.members_field.getElementsByName(names.init)) {
lambdaEnv.info.scope.owner = s;
break;
}
} else {
/* if the field is static then we need to create a fake clinit
* method, this method can later be reused by LTM.
*/
MethodSymbol clinit = clinits.get(enclClass);
if (clinit == null) {
Type clinitType = new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass);
clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE, names.clinit, clinitType, enclClass);
clinit.params = List.<VarSymbol>nil();
clinits.put(enclClass, clinit);
}
lambdaEnv.info.scope.owner = clinit;
}
} else {
lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
}
return lambdaEnv;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method visitSwitch.
public void visitSwitch(JCSwitch tree) {
Type seltype = attribExpr(tree.selector, env);
Env<AttrContext> switchEnv = env.dup(tree, env.info.dup(env.info.scope.dup()));
try {
boolean enumSwitch = allowEnums && (seltype.tsym.flags() & Flags.ENUM) != 0;
boolean stringSwitch = false;
if (types.isSameType(seltype, syms.stringType)) {
if (allowStringsInSwitch) {
stringSwitch = true;
} else {
log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName);
}
}
if (!enumSwitch && !stringSwitch)
seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
// Attribute all cases and
// check that there are no duplicate case labels or default clauses.
// The set of case labels.
Set<Object> labels = new HashSet<Object>();
// Is there a default label?
boolean hasDefault = false;
for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
JCCase c = l.head;
Env<AttrContext> caseEnv = switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
try {
if (c.pat != null) {
if (enumSwitch) {
Symbol sym = enumConstant(c.pat, seltype);
if (sym == null) {
log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
} else if (!labels.add(sym)) {
log.error(c.pos(), "duplicate.case.label");
}
} else {
Type pattype = attribExpr(c.pat, switchEnv, seltype);
if (!pattype.hasTag(ERROR)) {
if (pattype.constValue() == null) {
log.error(c.pat.pos(), (stringSwitch ? "string.const.req" : "const.expr.req"));
} else if (labels.contains(pattype.constValue())) {
log.error(c.pos(), "duplicate.case.label");
} else {
labels.add(pattype.constValue());
}
}
}
} else if (hasDefault) {
log.error(c.pos(), "duplicate.default.label");
} else {
hasDefault = true;
}
attribStats(c.stats, caseEnv);
} finally {
caseEnv.info.scope.leave();
addVars(c.stats, switchEnv.info.scope);
}
}
result = null;
} finally {
switchEnv.info.scope.leave();
}
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Attr method visitTypeCast.
public void visitTypeCast(final JCTypeCast tree) {
Type clazztype = attribType(tree.clazz, env);
chk.validate(tree.clazz, env, false);
// a fresh environment is required for 292 inference to work properly ---
// see Infer.instantiatePolymorphicSignatureInstance()
Env<AttrContext> localEnv = env.dup(tree);
// should we propagate the target type?
final ResultInfo castInfo;
JCExpression expr = TreeInfo.skipParens(tree.expr);
boolean isPoly = allowPoly && (expr.hasTag(LAMBDA) || expr.hasTag(REFERENCE));
if (isPoly) {
// expression is a poly - we need to propagate target type info
castInfo = new ResultInfo(VAL, clazztype, new Check.NestedCheckContext(resultInfo.checkContext) {
@Override
public boolean compatible(Type found, Type req, Warner warn) {
return types.isCastable(found, req, warn);
}
});
} else {
// standalone cast - target-type info is not propagated
castInfo = unknownExprInfo;
}
Type exprtype = attribTree(tree.expr, localEnv, castInfo);
Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
if (exprtype.constValue() != null)
owntype = cfolder.coerce(exprtype, owntype);
result = check(tree, capture(owntype), VAL, resultInfo);
if (!isPoly)
chk.checkRedundantCast(localEnv, tree);
}
Aggregations