use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.
the class Lower method visitConditional.
// Simplify conditionals with known constant controlling expressions.
// This allows us to avoid generating supporting declarations for
// the dead code, which will not be eliminated during code generation.
// Note that Flow.isFalse and Flow.isTrue only return true
// for constant expressions in the sense of JLS 15.27, which
// are guaranteed to have no side-effects. More aggressive
// constant propagation would require that we take care to
// preserve possible side-effects in the condition expression.
/**
* Visitor method for conditional expressions.
*/
@Override
public void visitConditional(JCConditional tree) {
JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
if (cond.type.isTrue()) {
result = convert(translate(tree.truepart, tree.type), tree.type);
addPrunedInfo(cond);
} else if (cond.type.isFalse()) {
result = convert(translate(tree.falsepart, tree.type), tree.type);
addPrunedInfo(cond);
} else {
// Condition is not a compile-time constant.
tree.truepart = translate(tree.truepart, tree.type);
tree.falsepart = translate(tree.falsepart, tree.type);
result = tree;
}
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.
the class Lower method visitAssignop.
public void visitAssignop(final JCAssignOp tree) {
JCTree lhsAccess = access(TreeInfo.skipParens(tree.lhs));
final boolean boxingReq = !tree.lhs.type.isPrimitive() && tree.operator.type.getReturnType().isPrimitive();
if (boxingReq || lhsAccess.hasTag(APPLY)) {
// boxing required; need to rewrite as x = (unbox typeof x)(x op y);
// or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y)
// (but without recomputing x)
JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() {
public JCTree build(final JCTree lhs) {
JCTree.Tag newTag = tree.getTag().noAssignOp();
// Erasure (TransTypes) can change the type of
// tree.lhs. However, we can still get the
// unerased type of tree.lhs as it is stored
// in tree.type in Attr.
Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), newTag, attrEnv, tree.type, tree.rhs.type);
JCExpression expr = (JCExpression) lhs;
if (expr.type != tree.type)
expr = make.TypeCast(tree.type, expr);
JCBinary opResult = make.Binary(newTag, expr, tree.rhs);
opResult.operator = newOperator;
opResult.type = newOperator.type.getReturnType();
JCExpression newRhs = boxingReq ? make.TypeCast(types.unboxedType(tree.type), opResult) : opResult;
return make.Assign((JCExpression) lhs, newRhs).setType(tree.type);
}
});
result = translate(newTree);
return;
}
tree.lhs = translate(tree.lhs, tree);
tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
// right hand side as last argument of the access method.
if (tree.lhs.hasTag(APPLY)) {
JCMethodInvocation app = (JCMethodInvocation) tree.lhs;
// if operation is a += on strings,
// make sure to convert argument to string
JCExpression rhs = (((OperatorSymbol) tree.operator).opcode == string_add) ? makeString(tree.rhs) : tree.rhs;
app.args = List.of(rhs).prependList(app.args);
result = app;
} else {
result = tree;
}
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.
the class MemberEnter method DefaultConstructor.
/* ***************************************************************************
* tree building
****************************************************************************/
/**
* Generate default constructor for given class. For classes different
* from java.lang.Object, this is:
*
* c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
* super(x_0, ..., x_n)
* }
*
* or, if based == true:
*
* c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
* x_0.super(x_1, ..., x_n)
* }
*
* @param make The tree factory.
* @param c The class owning the default constructor.
* @param argtypes The parameter types of the constructor.
* @param thrown The thrown exceptions of the constructor.
* @param based Is first parameter a this$n?
*/
JCTree DefaultConstructor(TreeMaker make, ClassSymbol c, MethodSymbol baseInit, List<Type> typarams, List<Type> argtypes, List<Type> thrown, long flags, boolean based) {
JCTree result;
if ((c.flags() & ENUM) != 0 && (types.supertype(c.type).tsym == syms.enumSym)) {
// constructors of true enums are private
flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR;
} else
flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;
if (c.name.isEmpty()) {
flags |= ANONCONSTR;
}
Type mType = new MethodType(argtypes, null, thrown, c);
Type initType = typarams.nonEmpty() ? new ForAll(typarams, mType) : mType;
MethodSymbol init = new MethodSymbol(flags, names.init, initType, c);
init.params = createDefaultConstructorParams(make, baseInit, init, argtypes, based);
List<JCVariableDecl> params = make.Params(argtypes, init);
List<JCStatement> stats = List.nil();
if (c.type != syms.objectType) {
stats = stats.prepend(SuperCall(make, typarams, params, based));
}
result = make.MethodDef(init, make.Block(0, stats));
return result;
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.
the class MemberEnter method complete.
/* ********************************************************************
* Source completer
*********************************************************************/
/**
* Complete entering a class.
* @param sym The symbol of the class to be completed.
*/
public void complete(Symbol sym) throws CompletionFailure {
// Suppress some (recursive) MemberEnter invocations
if (!completionEnabled) {
// Re-install same completer for next time around and return.
Assert.check((sym.flags() & Flags.COMPOUND) == 0);
sym.completer = this;
return;
}
ClassSymbol c = (ClassSymbol) sym;
ClassType ct = (ClassType) c.type;
Env<AttrContext> env = typeEnvs.get(c);
JCClassDecl tree = (JCClassDecl) env.tree;
boolean wasFirst = isFirst;
isFirst = false;
try {
annotate.enterStart();
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
try {
// Save class environment for later member enter (2) processing.
halfcompleted.append(env);
// Mark class as not yet attributed.
c.flags_field |= UNATTRIBUTED;
// clauses have been seen.
if (c.owner.kind == PCK) {
memberEnter(env.toplevel, env.enclosing(TOPLEVEL));
todo.append(env);
}
if (c.owner.kind == TYP)
c.owner.complete();
// create an environment for evaluating the base clauses
Env<AttrContext> baseEnv = baseEnv(tree, env);
if (tree.extending != null)
typeAnnotate(tree.extending, baseEnv, sym, tree.pos());
for (JCExpression impl : tree.implementing) typeAnnotate(impl, baseEnv, sym, tree.pos());
annotate.flush();
// Determine supertype.
Type supertype = (tree.extending != null) ? attr.attribBase(tree.extending, baseEnv, true, false, true) : ((tree.mods.flags & Flags.ENUM) != 0) ? attr.attribBase(enumBase(tree.pos, c), baseEnv, true, false, false) : (c.fullname == names.java_lang_Object) ? Type.noType : syms.objectType;
ct.supertype_field = modelMissingTypes(supertype, tree.extending, false);
// Determine interfaces.
ListBuffer<Type> interfaces = new ListBuffer<Type>();
// lazy init
ListBuffer<Type> all_interfaces = null;
Set<Type> interfaceSet = new HashSet<Type>();
List<JCExpression> interfaceTrees = tree.implementing;
for (JCExpression iface : interfaceTrees) {
Type i = attr.attribBase(iface, baseEnv, false, true, true);
if (i.hasTag(CLASS)) {
interfaces.append(i);
if (all_interfaces != null)
all_interfaces.append(i);
chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet);
} else {
if (all_interfaces == null)
all_interfaces = new ListBuffer<Type>().appendList(interfaces);
all_interfaces.append(modelMissingTypes(i, iface, true));
}
}
if ((c.flags_field & Flags.ANNOTATION) != 0) {
ct.interfaces_field = List.of(syms.annotationType);
ct.all_interfaces_field = ct.interfaces_field;
} else {
ct.interfaces_field = interfaces.toList();
ct.all_interfaces_field = (all_interfaces == null) ? ct.interfaces_field : all_interfaces.toList();
}
if (c.fullname == names.java_lang_Object) {
if (tree.extending != null) {
chk.checkNonCyclic(tree.extending.pos(), supertype);
ct.supertype_field = Type.noType;
} else if (tree.implementing.nonEmpty()) {
chk.checkNonCyclic(tree.implementing.head.pos(), ct.interfaces_field.head);
ct.interfaces_field = List.nil();
}
}
// Annotations.
// In general, we cannot fully process annotations yet, but we
// can attribute the annotation types and then check to see if the
// @Deprecated annotation is present.
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
if (hasDeprecatedAnnotation(tree.mods.annotations))
c.flags_field |= DEPRECATED;
annotateLater(tree.mods.annotations, baseEnv, c, tree.pos());
// class type parameters use baseEnv but everything uses env
chk.checkNonCyclicDecl(tree);
attr.attribTypeVariables(tree.typarams, baseEnv);
// Do this here, where we have the symbol.
for (JCTypeParameter tp : tree.typarams) typeAnnotate(tp, baseEnv, sym, tree.pos());
// Add default constructor if needed.
if ((c.flags() & INTERFACE) == 0 && !TreeInfo.hasConstructors(tree.defs)) {
List<Type> argtypes = List.nil();
List<Type> typarams = List.nil();
List<Type> thrown = List.nil();
long ctorFlags = 0;
boolean based = false;
boolean addConstructor = true;
JCNewClass nc = null;
if (c.name.isEmpty()) {
nc = (JCNewClass) env.next.tree;
if (nc.constructor != null) {
addConstructor = nc.constructor.kind != ERR;
Type superConstrType = types.memberType(c.type, nc.constructor);
argtypes = superConstrType.getParameterTypes();
typarams = superConstrType.getTypeArguments();
ctorFlags = nc.constructor.flags() & VARARGS;
if (nc.encl != null) {
argtypes = argtypes.prepend(nc.encl.type);
based = true;
}
thrown = superConstrType.getThrownTypes();
}
}
if (addConstructor) {
MethodSymbol basedConstructor = nc != null ? (MethodSymbol) nc.constructor : null;
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, basedConstructor, typarams, argtypes, thrown, ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
}
}
// enter symbols for 'this' into current scope.
VarSymbol thisSym = new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
thisSym.pos = Position.FIRSTPOS;
env.info.scope.enter(thisSym);
// if this is a class, enter symbol for 'super' into current scope.
if ((c.flags_field & INTERFACE) == 0 && ct.supertype_field.hasTag(CLASS)) {
VarSymbol superSym = new VarSymbol(FINAL | HASINIT, names._super, ct.supertype_field, c);
superSym.pos = Position.FIRSTPOS;
env.info.scope.enter(superSym);
}
// name as a top-level package.
if (checkClash && c.owner.kind == PCK && c.owner != syms.unnamedPackage && reader.packageExists(c.fullname)) {
log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
}
if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 && !env.toplevel.sourcefile.isNameCompatible(c.name.toString(), JavaFileObject.Kind.SOURCE)) {
c.flags_field |= AUXILIARY;
}
} catch (CompletionFailure ex) {
chk.completionError(tree.pos(), ex);
} finally {
deferredLintHandler.setPos(prevLintPos);
log.useSource(prev);
}
// classes in a second phase.
if (wasFirst) {
try {
while (halfcompleted.nonEmpty()) {
Env<AttrContext> toFinish = halfcompleted.next();
finish(toFinish);
if (allowTypeAnnos) {
typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl) toFinish.tree);
typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl) toFinish.tree);
}
}
} finally {
isFirst = true;
}
}
} finally {
annotate.enterDone();
}
}
use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree 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);
}
Aggregations