0001: /*
0002: * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package com.sun.tools.javac.comp;
0027:
0028: import java.util.*;
0029: import java.util.Set;
0030: import javax.tools.JavaFileObject;
0031:
0032: import com.sun.tools.javac.code.*;
0033: import com.sun.tools.javac.jvm.*;
0034: import com.sun.tools.javac.tree.*;
0035: import com.sun.tools.javac.util.*;
0036: import com.sun.tools.javac.util.List;
0037:
0038: import com.sun.tools.javac.code.Type.*;
0039: import com.sun.tools.javac.code.Symbol.*;
0040: import com.sun.tools.javac.tree.JCTree.*;
0041:
0042: import static com.sun.tools.javac.code.Flags.*;
0043: import static com.sun.tools.javac.code.Kinds.*;
0044: import static com.sun.tools.javac.code.TypeTags.*;
0045: import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
0046:
0047: /** This is the second phase of Enter, in which classes are completed
0048: * by entering their members into the class scope using
0049: * MemberEnter.complete(). See Enter for an overview.
0050: *
0051: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
0052: * you write code that depends on this, you do so at your own risk.
0053: * This code and its internal interfaces are subject to change or
0054: * deletion without notice.</b>
0055: */
0056: @Version("@(#)MemberEnter.java 1.72 07/06/14")
0057: public class MemberEnter extends JCTree.Visitor implements Completer {
0058: protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<MemberEnter>();
0059:
0060: /** A switch to determine whether we check for package/class conflicts
0061: */
0062: final static boolean checkClash = true;
0063:
0064: private final Name.Table names;
0065: private final Enter enter;
0066: private final Log log;
0067: private final Check chk;
0068: private final Attr attr;
0069: private final Symtab syms;
0070: private final TreeMaker make;
0071: private final ClassReader reader;
0072: private final Todo todo;
0073: private final Annotate annotate;
0074: private final Types types;
0075: private final Target target;
0076:
0077: private final boolean skipAnnotations;
0078:
0079: public static MemberEnter instance(Context context) {
0080: MemberEnter instance = context.get(memberEnterKey);
0081: if (instance == null)
0082: instance = new MemberEnter(context);
0083: return instance;
0084: }
0085:
0086: protected MemberEnter(Context context) {
0087: context.put(memberEnterKey, this );
0088: names = Name.Table.instance(context);
0089: enter = Enter.instance(context);
0090: log = Log.instance(context);
0091: chk = Check.instance(context);
0092: attr = Attr.instance(context);
0093: syms = Symtab.instance(context);
0094: make = TreeMaker.instance(context);
0095: reader = ClassReader.instance(context);
0096: todo = Todo.instance(context);
0097: annotate = Annotate.instance(context);
0098: types = Types.instance(context);
0099: target = Target.instance(context);
0100: skipAnnotations = Options.instance(context).get(
0101: "skipAnnotations") != null;
0102: }
0103:
0104: /** A queue for classes whose members still need to be entered into the
0105: * symbol table.
0106: */
0107: ListBuffer<Env<AttrContext>> halfcompleted = new ListBuffer<Env<AttrContext>>();
0108:
0109: /** Set to true only when the first of a set of classes is
0110: * processed from the halfcompleted queue.
0111: */
0112: boolean isFirst = true;
0113:
0114: /** A flag to disable completion from time to time during member
0115: * enter, as we only need to look up types. This avoids
0116: * unnecessarily deep recursion.
0117: */
0118: boolean completionEnabled = true;
0119:
0120: /* ---------- Processing import clauses ----------------
0121: */
0122:
0123: /** Import all classes of a class or package on demand.
0124: * @param pos Position to be used for error reporting.
0125: * @param tsym The class or package the members of which are imported.
0126: * @param toScope The (import) scope in which imported classes
0127: * are entered.
0128: */
0129: private void importAll(int pos, final TypeSymbol tsym,
0130: Env<AttrContext> env) {
0131: // Check that packages imported from exist (JLS ???).
0132: if (tsym.kind == PCK && tsym.members().elems == null
0133: && !tsym.exists()) {
0134: // If we can't find java.lang, exit immediately.
0135: if (((PackageSymbol) tsym).fullname.equals(names.java_lang)) {
0136: JCDiagnostic msg = JCDiagnostic
0137: .fragment("fatal.err.no.java.lang");
0138: throw new FatalError(msg);
0139: } else {
0140: log.error(pos, "doesnt.exist", tsym);
0141: }
0142: }
0143: final Scope fromScope = tsym.members();
0144: final Scope toScope = env.toplevel.starImportScope;
0145: for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
0146: if (e.sym.kind == TYP && !toScope.includes(e.sym))
0147: toScope.enter(e.sym, fromScope);
0148: }
0149: }
0150:
0151: /** Import all static members of a class or package on demand.
0152: * @param pos Position to be used for error reporting.
0153: * @param tsym The class or package the members of which are imported.
0154: * @param toScope The (import) scope in which imported classes
0155: * are entered.
0156: */
0157: private void importStaticAll(int pos, final TypeSymbol tsym,
0158: Env<AttrContext> env) {
0159: final JavaFileObject sourcefile = env.toplevel.sourcefile;
0160: final Scope toScope = env.toplevel.starImportScope;
0161: final PackageSymbol packge = env.toplevel.packge;
0162: final TypeSymbol origin = tsym;
0163:
0164: // enter imported types immediately
0165: new Object() {
0166: Set<Symbol> processed = new HashSet<Symbol>();
0167:
0168: void importFrom(TypeSymbol tsym) {
0169: if (tsym == null || !processed.add(tsym))
0170: return;
0171:
0172: // also import inherited names
0173: importFrom(types.super type(tsym.type).tsym);
0174: for (Type t : types.interfaces(tsym.type))
0175: importFrom(t.tsym);
0176:
0177: final Scope fromScope = tsym.members();
0178: for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
0179: Symbol sym = e.sym;
0180: if (sym.kind == TYP && (sym.flags() & STATIC) != 0
0181: && staticImportAccessible(sym, packge)
0182: && sym.isMemberOf(origin, types)
0183: && !toScope.includes(sym))
0184: toScope.enter(sym, fromScope, origin.members());
0185: }
0186: }
0187: }.importFrom(tsym);
0188:
0189: // enter non-types before annotations that might use them
0190: annotate.earlier(new Annotate.Annotator() {
0191: Set<Symbol> processed = new HashSet<Symbol>();
0192:
0193: public String toString() {
0194: return "import static " + tsym + ".*" + " in "
0195: + sourcefile;
0196: }
0197:
0198: void importFrom(TypeSymbol tsym) {
0199: if (tsym == null || !processed.add(tsym))
0200: return;
0201:
0202: // also import inherited names
0203: importFrom(types.super type(tsym.type).tsym);
0204: for (Type t : types.interfaces(tsym.type))
0205: importFrom(t.tsym);
0206:
0207: final Scope fromScope = tsym.members();
0208: for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
0209: Symbol sym = e.sym;
0210: if (sym.isStatic() && sym.kind != TYP
0211: && staticImportAccessible(sym, packge)
0212: && !toScope.includes(sym)
0213: && sym.isMemberOf(origin, types)) {
0214: toScope.enter(sym, fromScope, origin.members());
0215: }
0216: }
0217: }
0218:
0219: public void enterAnnotation() {
0220: importFrom(tsym);
0221: }
0222: });
0223: }
0224:
0225: // is the sym accessible everywhere in packge?
0226: boolean staticImportAccessible(Symbol sym, PackageSymbol packge) {
0227: int flags = (int) (sym.flags() & AccessFlags);
0228: switch (flags) {
0229: default:
0230: case PUBLIC:
0231: return true;
0232: case PRIVATE:
0233: return false;
0234: case 0:
0235: case PROTECTED:
0236: return sym.packge() == packge;
0237: }
0238: }
0239:
0240: /** Import statics types of a given name. Non-types are handled in Attr.
0241: * @param pos Position to be used for error reporting.
0242: * @param tsym The class from which the name is imported.
0243: * @param name The (simple) name being imported.
0244: * @param env The environment containing the named import
0245: * scope to add to.
0246: */
0247: private void importNamedStatic(final DiagnosticPosition pos,
0248: final TypeSymbol tsym, final Name name,
0249: final Env<AttrContext> env) {
0250: if (tsym.kind != TYP) {
0251: log.error(pos, "static.imp.only.classes.and.interfaces");
0252: return;
0253: }
0254:
0255: final Scope toScope = env.toplevel.namedImportScope;
0256: final PackageSymbol packge = env.toplevel.packge;
0257: final TypeSymbol origin = tsym;
0258:
0259: // enter imported types immediately
0260: new Object() {
0261: Set<Symbol> processed = new HashSet<Symbol>();
0262:
0263: void importFrom(TypeSymbol tsym) {
0264: if (tsym == null || !processed.add(tsym))
0265: return;
0266:
0267: // also import inherited names
0268: importFrom(types.super type(tsym.type).tsym);
0269: for (Type t : types.interfaces(tsym.type))
0270: importFrom(t.tsym);
0271:
0272: for (Scope.Entry e = tsym.members().lookup(name); e.scope != null; e = e
0273: .next()) {
0274: Symbol sym = e.sym;
0275: if (sym.isStatic()
0276: && sym.kind == TYP
0277: && staticImportAccessible(sym, packge)
0278: && sym.isMemberOf(origin, types)
0279: && chk.checkUniqueStaticImport(pos, sym,
0280: toScope))
0281: toScope.enter(sym, sym.owner.members(), origin
0282: .members());
0283: }
0284: }
0285: }.importFrom(tsym);
0286:
0287: // enter non-types before annotations that might use them
0288: annotate.earlier(new Annotate.Annotator() {
0289: Set<Symbol> processed = new HashSet<Symbol>();
0290: boolean found = false;
0291:
0292: public String toString() {
0293: return "import static " + tsym + "." + name;
0294: }
0295:
0296: void importFrom(TypeSymbol tsym) {
0297: if (tsym == null || !processed.add(tsym))
0298: return;
0299:
0300: // also import inherited names
0301: importFrom(types.super type(tsym.type).tsym);
0302: for (Type t : types.interfaces(tsym.type))
0303: importFrom(t.tsym);
0304:
0305: for (Scope.Entry e = tsym.members().lookup(name); e.scope != null; e = e
0306: .next()) {
0307: Symbol sym = e.sym;
0308: if (sym.isStatic()
0309: && staticImportAccessible(sym, packge)
0310: && sym.isMemberOf(origin, types)) {
0311: found = true;
0312: if (sym.kind == MTH
0313: || sym.kind != TYP
0314: && chk.checkUniqueStaticImport(pos,
0315: sym, toScope))
0316: toScope.enter(sym, sym.owner.members(),
0317: origin.members());
0318: }
0319: }
0320: }
0321:
0322: public void enterAnnotation() {
0323: JavaFileObject prev = log
0324: .useSource(env.toplevel.sourcefile);
0325: try {
0326: importFrom(tsym);
0327: if (!found) {
0328: log.error(pos, "cant.resolve.location",
0329: JCDiagnostic
0330: .fragment("kindname.static"),
0331: name, "", "", Resolve
0332: .typeKindName(tsym.type),
0333: tsym.type);
0334: }
0335: } finally {
0336: log.useSource(prev);
0337: }
0338: }
0339: });
0340: }
0341:
0342: /** Import given class.
0343: * @param pos Position to be used for error reporting.
0344: * @param tsym The class to be imported.
0345: * @param env The environment containing the named import
0346: * scope to add to.
0347: */
0348: private void importNamed(DiagnosticPosition pos, Symbol tsym,
0349: Env<AttrContext> env) {
0350: if (tsym.kind == TYP
0351: && chk.checkUniqueImport(pos, tsym,
0352: env.toplevel.namedImportScope))
0353: env.toplevel.namedImportScope.enter(tsym, tsym.owner
0354: .members());
0355: }
0356:
0357: /** Construct method type from method signature.
0358: * @param typarams The method's type parameters.
0359: * @param params The method's value parameters.
0360: * @param res The method's result type,
0361: * null if it is a constructor.
0362: * @param thrown The method's thrown exceptions.
0363: * @param env The method's (local) environment.
0364: */
0365: Type signature(List<JCTypeParameter> typarams,
0366: List<JCVariableDecl> params, JCTree res,
0367: List<JCExpression> thrown, Env<AttrContext> env) {
0368:
0369: // Enter and attribute type parameters.
0370: List<Type> tvars = enter.classEnter(typarams, env);
0371: attr.attribTypeVariables(typarams, env);
0372:
0373: // Enter and attribute value parameters.
0374: ListBuffer<Type> argbuf = new ListBuffer<Type>();
0375: for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) {
0376: memberEnter(l.head, env);
0377: argbuf.append(l.head.vartype.type);
0378: }
0379:
0380: // Attribute result type, if one is given.
0381: Type restype = res == null ? syms.voidType : attr.attribType(
0382: res, env);
0383:
0384: // Attribute thrown exceptions.
0385: ListBuffer<Type> thrownbuf = new ListBuffer<Type>();
0386: for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) {
0387: Type exc = attr.attribType(l.head, env);
0388: if (exc.tag != TYPEVAR)
0389: exc = chk.checkClassType(l.head.pos(), exc);
0390: thrownbuf.append(exc);
0391: }
0392: Type mtype = new MethodType(argbuf.toList(), restype, thrownbuf
0393: .toList(), syms.methodClass);
0394: return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype);
0395: }
0396:
0397: /* ********************************************************************
0398: * Visitor methods for member enter
0399: *********************************************************************/
0400:
0401: /** Visitor argument: the current environment
0402: */
0403: protected Env<AttrContext> env;
0404:
0405: /** Enter field and method definitions and process import
0406: * clauses, catching any completion failure exceptions.
0407: */
0408: protected void memberEnter(JCTree tree, Env<AttrContext> env) {
0409: Env<AttrContext> prevEnv = this .env;
0410: try {
0411: this .env = env;
0412: tree.accept(this );
0413: } catch (CompletionFailure ex) {
0414: chk.completionError(tree.pos(), ex);
0415: } finally {
0416: this .env = prevEnv;
0417: }
0418: }
0419:
0420: /** Enter members from a list of trees.
0421: */
0422: void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) {
0423: for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
0424: memberEnter(l.head, env);
0425: }
0426:
0427: /** Enter members for a class.
0428: */
0429: void finishClass(JCClassDecl tree, Env<AttrContext> env) {
0430: if ((tree.mods.flags & Flags.ENUM) != 0
0431: && (types.super type(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) {
0432: addEnumMembers(tree, env);
0433: }
0434: memberEnter(tree.defs, env);
0435: }
0436:
0437: /** Add the implicit members for an enum type
0438: * to the symbol table.
0439: */
0440: private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) {
0441: JCExpression valuesType = make.Type(new ArrayType(
0442: tree.sym.type, syms.arrayClass));
0443:
0444: // public static T[] values() { return ???; }
0445: JCMethodDecl values = make.MethodDef(make
0446: .Modifiers(Flags.PUBLIC | Flags.STATIC), names.values,
0447: valuesType, List.<JCTypeParameter> nil(), List
0448: .<JCVariableDecl> nil(), List
0449: .<JCExpression> nil(), // thrown
0450: null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
0451: null);
0452: memberEnter(values, env);
0453:
0454: // public static T valueOf(String name) { return ???; }
0455: JCMethodDecl valueOf = make.MethodDef(make
0456: .Modifiers(Flags.PUBLIC | Flags.STATIC), names.valueOf,
0457: make.Type(tree.sym.type), List.<JCTypeParameter> nil(),
0458: List.of(make.VarDef(make.Modifiers(Flags.PARAMETER),
0459: names.fromString("name"), make
0460: .Type(syms.stringType), null)), List
0461: .<JCExpression> nil(), // thrown
0462: null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
0463: null);
0464: memberEnter(valueOf, env);
0465:
0466: // the remaining members are for bootstrapping only
0467: if (!target.compilerBootstrap(tree.sym))
0468: return;
0469:
0470: // public final int ordinal() { return ???; }
0471: JCMethodDecl ordinal = make.at(tree.pos).MethodDef(
0472: make.Modifiers(Flags.PUBLIC | Flags.FINAL),
0473: names.ordinal, make.Type(syms.intType),
0474: List.<JCTypeParameter> nil(),
0475: List.<JCVariableDecl> nil(), List.<JCExpression> nil(),
0476: null, null);
0477: memberEnter(ordinal, env);
0478:
0479: // public final String name() { return ???; }
0480: JCMethodDecl name = make.MethodDef(make.Modifiers(Flags.PUBLIC
0481: | Flags.FINAL), names._name,
0482: make.Type(syms.stringType), List
0483: .<JCTypeParameter> nil(), List
0484: .<JCVariableDecl> nil(), List
0485: .<JCExpression> nil(), null, null);
0486: memberEnter(name, env);
0487:
0488: // public int compareTo(E other) { return ???; }
0489: MethodSymbol compareTo = new MethodSymbol(Flags.PUBLIC,
0490: names.compareTo, new MethodType(List.of(tree.sym.type),
0491: syms.intType, List.<Type> nil(),
0492: syms.methodClass), tree.sym);
0493: memberEnter(make.MethodDef(compareTo, null), env);
0494: }
0495:
0496: public void visitTopLevel(JCCompilationUnit tree) {
0497: if (tree.starImportScope.elems != null) {
0498: // we must have already processed this toplevel
0499: return;
0500: }
0501:
0502: // check that no class exists with same fully qualified name as
0503: // toplevel package
0504: if (checkClash && tree.pid != null) {
0505: Symbol p = tree.packge;
0506: while (p.owner != syms.rootPackage) {
0507: p.owner.complete(); // enter all class members of p
0508: if (syms.classes.get(p.getQualifiedName()) != null) {
0509: log.error(tree.pos,
0510: "pkg.clashes.with.class.of.same.name", p);
0511: }
0512: p = p.owner;
0513: }
0514: }
0515:
0516: // process package annotations
0517: annotateLater(tree.packageAnnotations, env, tree.packge);
0518:
0519: // Import-on-demand java.lang.
0520: importAll(tree.pos, reader.enterPackage(names.java_lang), env);
0521:
0522: // Process all import clauses.
0523: memberEnter(tree.defs, env);
0524: }
0525:
0526: // process the non-static imports and the static imports of types.
0527: public void visitImport(JCImport tree) {
0528: JCTree imp = tree.qualid;
0529: Name name = TreeInfo.name(imp);
0530: TypeSymbol p;
0531:
0532: // Create a local environment pointing to this tree to disable
0533: // effects of other imports in Resolve.findGlobalType
0534: Env<AttrContext> localEnv = env.dup(tree);
0535:
0536: // Attribute qualifying package or class.
0537: JCFieldAccess s = (JCFieldAccess) imp;
0538: p = attr.attribTree(s.selected, localEnv,
0539: tree.staticImport ? TYP : (TYP | PCK), Type.noType).tsym;
0540: if (name == names.asterisk) {
0541: // Import on demand.
0542: chk.checkCanonical(s.selected);
0543: if (tree.staticImport)
0544: importStaticAll(tree.pos, p, env);
0545: else
0546: importAll(tree.pos, p, env);
0547: } else {
0548: // Named type import.
0549: if (tree.staticImport) {
0550: importNamedStatic(tree.pos(), p, name, localEnv);
0551: chk.checkCanonical(s.selected);
0552: } else {
0553: TypeSymbol c = attribImportType(imp, localEnv).tsym;
0554: chk.checkCanonical(imp);
0555: importNamed(tree.pos(), c, env);
0556: }
0557: }
0558: }
0559:
0560: public void visitMethodDef(JCMethodDecl tree) {
0561: Scope enclScope = enter.enterScope(env);
0562: MethodSymbol m = new MethodSymbol(0, tree.name, null,
0563: enclScope.owner);
0564: m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m,
0565: tree);
0566: tree.sym = m;
0567: Env<AttrContext> localEnv = methodEnv(tree, env);
0568:
0569: // Compute the method type
0570: m.type = signature(tree.typarams, tree.params, tree.restype,
0571: tree.thrown, localEnv);
0572:
0573: // Set m.params
0574: ListBuffer<VarSymbol> params = new ListBuffer<VarSymbol>();
0575: JCVariableDecl lastParam = null;
0576: for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
0577: JCVariableDecl param = lastParam = l.head;
0578: assert param.sym != null;
0579: params.append(param.sym);
0580: }
0581: m.params = params.toList();
0582:
0583: // mark the method varargs, if necessary
0584: if (lastParam != null
0585: && (lastParam.mods.flags & Flags.VARARGS) != 0)
0586: m.flags_field |= Flags.VARARGS;
0587:
0588: localEnv.info.scope.leave();
0589: if (chk.checkUnique(tree.pos(), m, enclScope)) {
0590: enclScope.enter(m);
0591: }
0592: annotateLater(tree.mods.annotations, localEnv, m);
0593: if (tree.defaultValue != null)
0594: annotateDefaultValueLater(tree.defaultValue, localEnv, m);
0595: }
0596:
0597: /** Create a fresh environment for method bodies.
0598: * @param tree The method definition.
0599: * @param env The environment current outside of the method definition.
0600: */
0601: Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) {
0602: Env<AttrContext> localEnv = env.dup(tree, env.info
0603: .dup(env.info.scope.dupUnshared()));
0604: localEnv.enclMethod = tree;
0605: localEnv.info.scope.owner = tree.sym;
0606: if ((tree.mods.flags & STATIC) != 0)
0607: localEnv.info.staticLevel++;
0608: return localEnv;
0609: }
0610:
0611: public void visitVarDef(JCVariableDecl tree) {
0612: Env<AttrContext> localEnv = env;
0613: if ((tree.mods.flags & STATIC) != 0
0614: || (env.info.scope.owner.flags() & INTERFACE) != 0) {
0615: localEnv = env.dup(tree, env.info.dup());
0616: localEnv.info.staticLevel++;
0617: }
0618: attr.attribType(tree.vartype, localEnv);
0619: Scope enclScope = enter.enterScope(env);
0620: VarSymbol v = new VarSymbol(0, tree.name, tree.vartype.type,
0621: enclScope.owner);
0622: v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v,
0623: tree);
0624: tree.sym = v;
0625: if (tree.init != null) {
0626: v.flags_field |= HASINIT;
0627: if ((v.flags_field & FINAL) != 0
0628: && tree.init.getTag() != JCTree.NEWCLASS)
0629: v.setLazyConstValue(initEnv(tree, env), log, attr,
0630: tree.init);
0631: }
0632: if (chk.checkUnique(tree.pos(), v, enclScope)) {
0633: chk.checkTransparentVar(tree.pos(), v, enclScope);
0634: enclScope.enter(v);
0635: }
0636: annotateLater(tree.mods.annotations, localEnv, v);
0637: v.pos = tree.pos;
0638: }
0639:
0640: /** Create a fresh environment for a variable's initializer.
0641: * If the variable is a field, the owner of the environment's scope
0642: * is be the variable itself, otherwise the owner is the method
0643: * enclosing the variable definition.
0644: *
0645: * @param tree The variable definition.
0646: * @param env The environment current outside of the variable definition.
0647: */
0648: Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) {
0649: Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree,
0650: env.info.dup()));
0651: if (tree.sym.owner.kind == TYP) {
0652: localEnv.info.scope = new Scope.DelegatedScope(
0653: env.info.scope);
0654: localEnv.info.scope.owner = tree.sym;
0655: }
0656: if ((tree.mods.flags & STATIC) != 0
0657: || (env.enclClass.sym.flags() & INTERFACE) != 0)
0658: localEnv.info.staticLevel++;
0659: return localEnv;
0660: }
0661:
0662: /** Default member enter visitor method: do nothing
0663: */
0664: public void visitTree(JCTree tree) {
0665: }
0666:
0667: public void visitErroneous(JCErroneous tree) {
0668: memberEnter(tree.errs, env);
0669: }
0670:
0671: public Env<AttrContext> getMethodEnv(JCMethodDecl tree,
0672: Env<AttrContext> env) {
0673: Env<AttrContext> mEnv = methodEnv(tree, env);
0674: mEnv.info.lint = mEnv.info.lint.augment(
0675: tree.sym.attributes_field, tree.sym.flags());
0676: for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
0677: mEnv.info.scope.enterIfAbsent(l.head.type.tsym);
0678: for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail)
0679: mEnv.info.scope.enterIfAbsent(l.head.sym);
0680: return mEnv;
0681: }
0682:
0683: public Env<AttrContext> getInitEnv(JCVariableDecl tree,
0684: Env<AttrContext> env) {
0685: Env<AttrContext> iEnv = initEnv(tree, env);
0686: return iEnv;
0687: }
0688:
0689: /* ********************************************************************
0690: * Type completion
0691: *********************************************************************/
0692:
0693: Type attribImportType(JCTree tree, Env<AttrContext> env) {
0694: assert completionEnabled;
0695: try {
0696: // To prevent deep recursion, suppress completion of some
0697: // types.
0698: completionEnabled = false;
0699: return attr.attribType(tree, env);
0700: } finally {
0701: completionEnabled = true;
0702: }
0703: }
0704:
0705: /* ********************************************************************
0706: * Annotation processing
0707: *********************************************************************/
0708:
0709: /** Queue annotations for later processing. */
0710: void annotateLater(final List<JCAnnotation> annotations,
0711: final Env<AttrContext> localEnv, final Symbol s) {
0712: if (annotations.isEmpty())
0713: return;
0714: if (s.kind != PCK)
0715: s.attributes_field = null; // mark it incomplete for now
0716: annotate.later(new Annotate.Annotator() {
0717: public String toString() {
0718: return "annotate " + annotations + " onto " + s
0719: + " in " + s.owner;
0720: }
0721:
0722: public void enterAnnotation() {
0723: assert s.kind == PCK || s.attributes_field == null;
0724: JavaFileObject prev = log
0725: .useSource(localEnv.toplevel.sourcefile);
0726: try {
0727: if (s.attributes_field != null
0728: && s.attributes_field.nonEmpty()
0729: && annotations.nonEmpty())
0730: log.error(annotations.head.pos,
0731: "already.annotated", Resolve
0732: .kindName(s), s);
0733: enterAnnotations(annotations, localEnv, s);
0734: } finally {
0735: log.useSource(prev);
0736: }
0737: }
0738: });
0739: }
0740:
0741: /**
0742: * Check if a list of annotations contains a reference to
0743: * java.lang.Deprecated.
0744: **/
0745: private boolean hasDeprecatedAnnotation(
0746: List<JCAnnotation> annotations) {
0747: for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
0748: JCAnnotation a = al.head;
0749: if (a.annotationType.type == syms.deprecatedType
0750: && a.args.isEmpty())
0751: return true;
0752: }
0753: return false;
0754: }
0755:
0756: /** Enter a set of annotations. */
0757: private void enterAnnotations(List<JCAnnotation> annotations,
0758: Env<AttrContext> env, Symbol s) {
0759: ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
0760: Set<TypeSymbol> annotated = new HashSet<TypeSymbol>();
0761: if (!skipAnnotations)
0762: for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
0763: JCAnnotation a = al.head;
0764: Attribute.Compound c = annotate.enterAnnotation(a,
0765: syms.annotationType, env);
0766: if (c == null)
0767: continue;
0768: buf.append(c);
0769: // Note: @Deprecated has no effect on local variables and parameters
0770: if (!c.type.isErroneous()
0771: && s.owner.kind != MTH
0772: && types
0773: .isSameType(c.type, syms.deprecatedType))
0774: s.flags_field |= Flags.DEPRECATED;
0775: if (!annotated.add(a.type.tsym))
0776: log.error(a.pos, "duplicate.annotation");
0777: }
0778: s.attributes_field = buf.toList();
0779: }
0780:
0781: /** Queue processing of an attribute default value. */
0782: void annotateDefaultValueLater(final JCExpression defaultValue,
0783: final Env<AttrContext> localEnv, final MethodSymbol m) {
0784: annotate.later(new Annotate.Annotator() {
0785: public String toString() {
0786: return "annotate " + m.owner + "." + m + " default "
0787: + defaultValue;
0788: }
0789:
0790: public void enterAnnotation() {
0791: JavaFileObject prev = log
0792: .useSource(localEnv.toplevel.sourcefile);
0793: try {
0794: enterDefaultValue(defaultValue, localEnv, m);
0795: } finally {
0796: log.useSource(prev);
0797: }
0798: }
0799: });
0800: }
0801:
0802: /** Enter a default value for an attribute method. */
0803: private void enterDefaultValue(final JCExpression defaultValue,
0804: final Env<AttrContext> localEnv, final MethodSymbol m) {
0805: m.defaultValue = annotate.enterAttributeValue(m.type
0806: .getReturnType(), defaultValue, localEnv);
0807: }
0808:
0809: /* ********************************************************************
0810: * Source completer
0811: *********************************************************************/
0812:
0813: /** Complete entering a class.
0814: * @param sym The symbol of the class to be completed.
0815: */
0816: public void complete(Symbol sym) throws CompletionFailure {
0817: // Suppress some (recursive) MemberEnter invocations
0818: if (!completionEnabled) {
0819: // Re-install same completer for next time around and return.
0820: assert (sym.flags() & Flags.COMPOUND) == 0;
0821: sym.completer = this ;
0822: return;
0823: }
0824:
0825: ClassSymbol c = (ClassSymbol) sym;
0826: ClassType ct = (ClassType) c.type;
0827: Env<AttrContext> env = enter.typeEnvs.get(c);
0828: JCClassDecl tree = (JCClassDecl) env.tree;
0829: boolean wasFirst = isFirst;
0830: isFirst = false;
0831:
0832: JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
0833: try {
0834: // Save class environment for later member enter (2) processing.
0835: halfcompleted.append(env);
0836:
0837: // If this is a toplevel-class, make sure any preceding import
0838: // clauses have been seen.
0839: if (c.owner.kind == PCK) {
0840: memberEnter(env.toplevel, env
0841: .enclosing(JCTree.TOPLEVEL));
0842: todo.append(env);
0843: }
0844:
0845: // Mark class as not yet attributed.
0846: c.flags_field |= UNATTRIBUTED;
0847:
0848: if (c.owner.kind == TYP)
0849: c.owner.complete();
0850:
0851: // create an environment for evaluating the base clauses
0852: Env<AttrContext> baseEnv = baseEnv(tree, env);
0853:
0854: // Determine supertype.
0855: Type super type = (tree.extending != null) ? attr
0856: .attribBase(tree.extending, baseEnv, true, false,
0857: true)
0858: : ((tree.mods.flags & Flags.ENUM) != 0 && !target
0859: .compilerBootstrap(c)) ? attr.attribBase(
0860: enumBase(tree.pos, c), baseEnv, true,
0861: false, false)
0862: : (c.fullname == names.java_lang_Object) ? Type.noType
0863: : syms.objectType;
0864: ct.super type_field = super type;
0865:
0866: // Determine interfaces.
0867: ListBuffer<Type> interfaces = new ListBuffer<Type>();
0868: Set<Type> interfaceSet = new HashSet<Type>();
0869: List<JCExpression> interfaceTrees = tree.implementing;
0870: if ((tree.mods.flags & Flags.ENUM) != 0
0871: && target.compilerBootstrap(c)) {
0872: // add interface Comparable<T>
0873: interfaceTrees = interfaceTrees.prepend(make
0874: .Type(new ClassType(syms.comparableType
0875: .getEnclosingType(), List.of(c.type),
0876: syms.comparableType.tsym)));
0877: // add interface Serializable
0878: interfaceTrees = interfaceTrees.prepend(make
0879: .Type(syms.serializableType));
0880: }
0881: for (JCExpression iface : interfaceTrees) {
0882: Type i = attr.attribBase(iface, baseEnv, false, true,
0883: true);
0884: if (i.tag == CLASS) {
0885: interfaces.append(i);
0886: chk.checkNotRepeated(iface.pos(), types.erasure(i),
0887: interfaceSet);
0888: }
0889: }
0890: if ((c.flags_field & ANNOTATION) != 0)
0891: ct.interfaces_field = List.of(syms.annotationType);
0892: else
0893: ct.interfaces_field = interfaces.toList();
0894:
0895: if (c.fullname == names.java_lang_Object) {
0896: if (tree.extending != null) {
0897: chk.checkNonCyclic(tree.extending.pos(), super type);
0898: ct.super type_field = Type.noType;
0899: } else if (tree.implementing.nonEmpty()) {
0900: chk.checkNonCyclic(tree.implementing.head.pos(),
0901: ct.interfaces_field.head);
0902: ct.interfaces_field = List.nil();
0903: }
0904: }
0905:
0906: // Annotations.
0907: // In general, we cannot fully process annotations yet, but we
0908: // can attribute the annotation types and then check to see if the
0909: // @Deprecated annotation is present.
0910: attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
0911: if (hasDeprecatedAnnotation(tree.mods.annotations))
0912: c.flags_field |= DEPRECATED;
0913: annotateLater(tree.mods.annotations, baseEnv, c);
0914:
0915: attr.attribTypeVariables(tree.typarams, baseEnv);
0916:
0917: chk.checkNonCyclic(tree.pos(), c.type);
0918:
0919: // Add default constructor if needed.
0920: if ((c.flags() & INTERFACE) == 0
0921: && !TreeInfo.hasConstructors(tree.defs)) {
0922: List<Type> argtypes = List.nil();
0923: List<Type> typarams = List.nil();
0924: List<Type> thrown = List.nil();
0925: long ctorFlags = 0;
0926: boolean based = false;
0927: if (c.name.len == 0) {
0928: JCNewClass nc = (JCNewClass) env.next.tree;
0929: if (nc.constructor != null) {
0930: Type super ConstrType = types.memberType(c.type,
0931: nc.constructor);
0932: argtypes = super ConstrType.getParameterTypes();
0933: typarams = super ConstrType.getTypeArguments();
0934: ctorFlags = nc.constructor.flags() & VARARGS;
0935: if (nc.encl != null) {
0936: argtypes = argtypes.prepend(nc.encl.type);
0937: based = true;
0938: }
0939: thrown = super ConstrType.getThrownTypes();
0940: }
0941: }
0942: JCTree constrDef = DefaultConstructor(
0943: make.at(tree.pos), c, typarams, argtypes,
0944: thrown, ctorFlags, based);
0945: tree.defs = tree.defs.prepend(constrDef);
0946: }
0947:
0948: // If this is a class, enter symbols for this and super into
0949: // current scope.
0950: if ((c.flags_field & INTERFACE) == 0) {
0951: VarSymbol this Sym = new VarSymbol(FINAL | HASINIT,
0952: names._this , c.type, c);
0953: this Sym.pos = Position.FIRSTPOS;
0954: env.info.scope.enter(this Sym);
0955: if (ct.super type_field.tag == CLASS) {
0956: VarSymbol super Sym = new VarSymbol(FINAL | HASINIT,
0957: names._super , ct.super type_field, c);
0958: super Sym.pos = Position.FIRSTPOS;
0959: env.info.scope.enter(super Sym);
0960: }
0961: }
0962:
0963: // check that no package exists with same fully qualified name,
0964: // but admit classes in the unnamed package which have the same
0965: // name as a top-level package.
0966: if (checkClash && c.owner.kind == PCK
0967: && c.owner != syms.unnamedPackage
0968: && reader.packageExists(c.fullname)) {
0969: log.error(tree.pos, "clash.with.pkg.of.same.name", c);
0970: }
0971:
0972: } catch (CompletionFailure ex) {
0973: chk.completionError(tree.pos(), ex);
0974: } finally {
0975: log.useSource(prev);
0976: }
0977:
0978: // Enter all member fields and methods of a set of half completed
0979: // classes in a second phase.
0980: if (wasFirst) {
0981: try {
0982: while (halfcompleted.nonEmpty()) {
0983: finish(halfcompleted.next());
0984: }
0985: } finally {
0986: isFirst = true;
0987: }
0988:
0989: // commit pending annotations
0990: annotate.flush();
0991: }
0992: }
0993:
0994: private Env<AttrContext> baseEnv(JCClassDecl tree,
0995: Env<AttrContext> env) {
0996: Scope typaramScope = new Scope(tree.sym);
0997: if (tree.typarams != null)
0998: for (List<JCTypeParameter> typarams = tree.typarams; typarams
0999: .nonEmpty(); typarams = typarams.tail)
1000: typaramScope.enter(typarams.head.type.tsym);
1001: Env<AttrContext> outer = env.outer; // the base clause can't see members of this class
1002: Env<AttrContext> localEnv = outer.dup(tree, outer.info
1003: .dup(typaramScope));
1004: localEnv.baseClause = true;
1005: localEnv.outer = outer;
1006: localEnv.info.isSelfCall = false;
1007: return localEnv;
1008: }
1009:
1010: /** Enter member fields and methods of a class
1011: * @param env the environment current for the class block.
1012: */
1013: private void finish(Env<AttrContext> env) {
1014: JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
1015: try {
1016: JCClassDecl tree = (JCClassDecl) env.tree;
1017: finishClass(tree, env);
1018: } finally {
1019: log.useSource(prev);
1020: }
1021: }
1022:
1023: /** Generate a base clause for an enum type.
1024: * @param pos The position for trees and diagnostics, if any
1025: * @param c The class symbol of the enum
1026: */
1027: private JCExpression enumBase(int pos, ClassSymbol c) {
1028: JCExpression result = make.at(pos).TypeApply(
1029: make.QualIdent(syms.enumSym),
1030: List.<JCExpression> of(make.Type(c.type)));
1031: return result;
1032: }
1033:
1034: /* ***************************************************************************
1035: * tree building
1036: ****************************************************************************/
1037:
1038: /** Generate default constructor for given class. For classes different
1039: * from java.lang.Object, this is:
1040: *
1041: * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
1042: * super(x_0, ..., x_n)
1043: * }
1044: *
1045: * or, if based == true:
1046: *
1047: * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
1048: * x_0.super(x_1, ..., x_n)
1049: * }
1050: *
1051: * @param make The tree factory.
1052: * @param c The class owning the default constructor.
1053: * @param argtypes The parameter types of the constructor.
1054: * @param thrown The thrown exceptions of the constructor.
1055: * @param based Is first parameter a this$n?
1056: */
1057: JCTree DefaultConstructor(TreeMaker make, ClassSymbol c,
1058: List<Type> typarams, List<Type> argtypes,
1059: List<Type> thrown, long flags, boolean based) {
1060: List<JCVariableDecl> params = make.Params(argtypes,
1061: syms.noSymbol);
1062: List<JCStatement> stats = List.nil();
1063: if (c.type != syms.objectType)
1064: stats = stats.prepend(SuperCall(make, typarams, params,
1065: based));
1066: if ((c.flags() & ENUM) != 0
1067: && (types.super type(c.type).tsym == syms.enumSym || target
1068: .compilerBootstrap(c))) {
1069: // constructors of true enums are private
1070: flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR;
1071: } else
1072: flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;
1073: if (c.name.len == 0)
1074: flags |= ANONCONSTR;
1075: JCTree result = make.MethodDef(make.Modifiers(flags),
1076: names.init, null, make.TypeParams(typarams), params,
1077: make.Types(thrown), make.Block(0, stats), null);
1078: return result;
1079: }
1080:
1081: /** Generate call to superclass constructor. This is:
1082: *
1083: * super(id_0, ..., id_n)
1084: *
1085: * or, if based == true
1086: *
1087: * id_0.super(id_1,...,id_n)
1088: *
1089: * where id_0, ..., id_n are the names of the given parameters.
1090: *
1091: * @param make The tree factory
1092: * @param params The parameters that need to be passed to super
1093: * @param typarams The type parameters that need to be passed to super
1094: * @param based Is first parameter a this$n?
1095: */
1096: JCExpressionStatement SuperCall(TreeMaker make,
1097: List<Type> typarams, List<JCVariableDecl> params,
1098: boolean based) {
1099: JCExpression meth;
1100: if (based) {
1101: meth = make.Select(make.Ident(params.head), names._super );
1102: params = params.tail;
1103: } else {
1104: meth = make.Ident(names._super );
1105: }
1106: List<JCExpression> typeargs = typarams.nonEmpty() ? make
1107: .Types(typarams) : null;
1108: return make.Exec(make
1109: .Apply(typeargs, meth, make.Idents(params)));
1110: }
1111: }
|