Home » openjdk-7 » com.sun.tools » javac » comp » [javadoc | source]

    1   /*
    2    * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package com.sun.tools.javac.comp;
   27   
   28   import java.util;
   29   import javax.tools.JavaFileObject;
   30   import javax.tools.JavaFileManager;
   31   
   32   import com.sun.tools.javac.code;
   33   import com.sun.tools.javac.code.Scope;
   34   import com.sun.tools.javac.code.Symbol;
   35   import com.sun.tools.javac.code.Type;
   36   import com.sun.tools.javac.jvm;
   37   import com.sun.tools.javac.main.RecognizedOptions.PkgInfo;
   38   import com.sun.tools.javac.tree;
   39   import com.sun.tools.javac.tree.JCTree;
   40   import com.sun.tools.javac.util;
   41   import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
   42   import com.sun.tools.javac.util.List;
   43   
   44   
   45   import static com.sun.tools.javac.code.Flags.*;
   46   import static com.sun.tools.javac.code.Kinds.*;
   47   
   48   /** This class enters symbols for all encountered definitions into
   49    *  the symbol table. The pass consists of two phases, organized as
   50    *  follows:
   51    *
   52    *  <p>In the first phase, all class symbols are intered into their
   53    *  enclosing scope, descending recursively down the tree for classes
   54    *  which are members of other classes. The class symbols are given a
   55    *  MemberEnter object as completer.
   56    *
   57    *  <p>In the second phase classes are completed using
   58    *  MemberEnter.complete().  Completion might occur on demand, but
   59    *  any classes that are not completed that way will be eventually
   60    *  completed by processing the `uncompleted' queue.  Completion
   61    *  entails (1) determination of a class's parameters, supertype and
   62    *  interfaces, as well as (2) entering all symbols defined in the
   63    *  class into its scope, with the exception of class symbols which
   64    *  have been entered in phase 1.  (2) depends on (1) having been
   65    *  completed for a class and all its superclasses and enclosing
   66    *  classes. That's why, after doing (1), we put classes in a
   67    *  `halfcompleted' queue. Only when we have performed (1) for a class
   68    *  and all it's superclasses and enclosing classes, we proceed to
   69    *  (2).
   70    *
   71    *  <p>Whereas the first phase is organized as a sweep through all
   72    *  compiled syntax trees, the second phase is demand. Members of a
   73    *  class are entered when the contents of a class are first
   74    *  accessed. This is accomplished by installing completer objects in
   75    *  class symbols for compiled classes which invoke the member-enter
   76    *  phase for the corresponding class tree.
   77    *
   78    *  <p>Classes migrate from one phase to the next via queues:
   79    *
   80    *  <pre>
   81    *  class enter -> (Enter.uncompleted)         --> member enter (1)
   82    *              -> (MemberEnter.halfcompleted) --> member enter (2)
   83    *              -> (Todo)                      --> attribute
   84    *                                              (only for toplevel classes)
   85    *  </pre>
   86    *
   87    *  <p><b>This is NOT part of any supported API.
   88    *  If you write code that depends on this, you do so at your own risk.
   89    *  This code and its internal interfaces are subject to change or
   90    *  deletion without notice.</b>
   91    */
   92   public class Enter extends JCTree.Visitor {
   93       protected static final Context.Key<Enter> enterKey =
   94           new Context.Key<Enter>();
   95   
   96       Log log;
   97       Symtab syms;
   98       Check chk;
   99       TreeMaker make;
  100       ClassReader reader;
  101       Annotate annotate;
  102       MemberEnter memberEnter;
  103       Types types;
  104       Lint lint;
  105       Names names;
  106       JavaFileManager fileManager;
  107       PkgInfo pkginfoOpt;
  108   
  109       private final Todo todo;
  110   
  111       public static Enter instance(Context context) {
  112           Enter instance = context.get(enterKey);
  113           if (instance == null)
  114               instance = new Enter(context);
  115           return instance;
  116       }
  117   
  118       protected Enter(Context context) {
  119           context.put(enterKey, this);
  120   
  121           log = Log.instance(context);
  122           reader = ClassReader.instance(context);
  123           make = TreeMaker.instance(context);
  124           syms = Symtab.instance(context);
  125           chk = Check.instance(context);
  126           memberEnter = MemberEnter.instance(context);
  127           types = Types.instance(context);
  128           annotate = Annotate.instance(context);
  129           lint = Lint.instance(context);
  130           names = Names.instance(context);
  131   
  132           predefClassDef = make.ClassDef(
  133               make.Modifiers(PUBLIC),
  134               syms.predefClass.name, null, null, null, null);
  135           predefClassDef.sym = syms.predefClass;
  136           todo = Todo.instance(context);
  137           fileManager = context.get(JavaFileManager.class);
  138   
  139           Options options = Options.instance(context);
  140           pkginfoOpt = PkgInfo.get(options);
  141       }
  142   
  143       /** A hashtable mapping classes and packages to the environments current
  144        *  at the points of their definitions.
  145        */
  146       Map<TypeSymbol,Env<AttrContext>> typeEnvs =
  147               new HashMap<TypeSymbol,Env<AttrContext>>();
  148   
  149       /** Accessor for typeEnvs
  150        */
  151       public Env<AttrContext> getEnv(TypeSymbol sym) {
  152           return typeEnvs.get(sym);
  153       }
  154   
  155       public Env<AttrContext> getClassEnv(TypeSymbol sym) {
  156           Env<AttrContext> localEnv = getEnv(sym);
  157           Env<AttrContext> lintEnv = localEnv;
  158           while (lintEnv.info.lint == null)
  159               lintEnv = lintEnv.next;
  160           localEnv.info.lint = lintEnv.info.lint.augment(sym.attributes_field, sym.flags());
  161           return localEnv;
  162       }
  163   
  164       /** The queue of all classes that might still need to be completed;
  165        *  saved and initialized by main().
  166        */
  167       ListBuffer<ClassSymbol> uncompleted;
  168   
  169       /** A dummy class to serve as enclClass for toplevel environments.
  170        */
  171       private JCClassDecl predefClassDef;
  172   
  173   /* ************************************************************************
  174    * environment construction
  175    *************************************************************************/
  176   
  177   
  178       /** Create a fresh environment for class bodies.
  179        *  This will create a fresh scope for local symbols of a class, referred
  180        *  to by the environments info.scope field.
  181        *  This scope will contain
  182        *    - symbols for this and super
  183        *    - symbols for any type parameters
  184        *  In addition, it serves as an anchor for scopes of methods and initializers
  185        *  which are nested in this scope via Scope.dup().
  186        *  This scope should not be confused with the members scope of a class.
  187        *
  188        *  @param tree     The class definition.
  189        *  @param env      The environment current outside of the class definition.
  190        */
  191       public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
  192           Env<AttrContext> localEnv =
  193               env.dup(tree, env.info.dup(new Scope(tree.sym)));
  194           localEnv.enclClass = tree;
  195           localEnv.outer = env;
  196           localEnv.info.isSelfCall = false;
  197           localEnv.info.lint = null; // leave this to be filled in by Attr,
  198                                      // when annotations have been processed
  199           return localEnv;
  200       }
  201   
  202       /** Create a fresh environment for toplevels.
  203        *  @param tree     The toplevel tree.
  204        */
  205       Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
  206           Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
  207           localEnv.toplevel = tree;
  208           localEnv.enclClass = predefClassDef;
  209           tree.namedImportScope = new ImportScope(tree.packge);
  210           tree.starImportScope = new StarImportScope(tree.packge);
  211           localEnv.info.scope = tree.namedImportScope;
  212           localEnv.info.lint = lint;
  213           return localEnv;
  214       }
  215   
  216       public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) {
  217           Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
  218           localEnv.toplevel = tree;
  219           localEnv.enclClass = predefClassDef;
  220           localEnv.info.scope = tree.namedImportScope;
  221           localEnv.info.lint = lint;
  222           return localEnv;
  223       }
  224   
  225       /** The scope in which a member definition in environment env is to be entered
  226        *  This is usually the environment's scope, except for class environments,
  227        *  where the local scope is for type variables, and the this and super symbol
  228        *  only, and members go into the class member scope.
  229        */
  230       Scope enterScope(Env<AttrContext> env) {
  231           return (env.tree.getTag() == JCTree.CLASSDEF)
  232               ? ((JCClassDecl) env.tree).sym.members_field
  233               : env.info.scope;
  234       }
  235   
  236   /* ************************************************************************
  237    * Visitor methods for phase 1: class enter
  238    *************************************************************************/
  239   
  240       /** Visitor argument: the current environment.
  241        */
  242       protected Env<AttrContext> env;
  243   
  244       /** Visitor result: the computed type.
  245        */
  246       Type result;
  247   
  248       /** Visitor method: enter all classes in given tree, catching any
  249        *  completion failure exceptions. Return the tree's type.
  250        *
  251        *  @param tree    The tree to be visited.
  252        *  @param env     The environment visitor argument.
  253        */
  254       Type classEnter(JCTree tree, Env<AttrContext> env) {
  255           Env<AttrContext> prevEnv = this.env;
  256           try {
  257               this.env = env;
  258               tree.accept(this);
  259               return result;
  260           }  catch (CompletionFailure ex) {
  261               return chk.completionError(tree.pos(), ex);
  262           } finally {
  263               this.env = prevEnv;
  264           }
  265       }
  266   
  267       /** Visitor method: enter classes of a list of trees, returning a list of types.
  268        */
  269       <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) {
  270           ListBuffer<Type> ts = new ListBuffer<Type>();
  271           for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
  272               Type t = classEnter(l.head, env);
  273               if (t != null)
  274                   ts.append(t);
  275           }
  276           return ts.toList();
  277       }
  278   
  279       @Override
  280       public void visitTopLevel(JCCompilationUnit tree) {
  281           JavaFileObject prev = log.useSource(tree.sourcefile);
  282           boolean addEnv = false;
  283           boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
  284                                                                JavaFileObject.Kind.SOURCE);
  285           if (tree.pid != null) {
  286               tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
  287               if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) {
  288                   if (isPkgInfo) {
  289                       addEnv = true;
  290                   } else {
  291                       log.error(tree.packageAnnotations.head.pos(),
  292                                 "pkg.annotations.sb.in.package-info.java");
  293                   }
  294               }
  295           } else {
  296               tree.packge = syms.unnamedPackage;
  297           }
  298           tree.packge.complete(); // Find all classes in package.
  299           Env<AttrContext> topEnv = topLevelEnv(tree);
  300   
  301           // Save environment of package-info.java file.
  302           if (isPkgInfo) {
  303               Env<AttrContext> env0 = typeEnvs.get(tree.packge);
  304               if (env0 == null) {
  305                   typeEnvs.put(tree.packge, topEnv);
  306               } else {
  307                   JCCompilationUnit tree0 = env0.toplevel;
  308                   if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
  309                       log.warning(tree.pid != null ? tree.pid.pos()
  310                                                    : null,
  311                                   "pkg-info.already.seen",
  312                                   tree.packge);
  313                       if (addEnv || (tree0.packageAnnotations.isEmpty() &&
  314                                      tree.docComments != null &&
  315                                      tree.docComments.get(tree) != null)) {
  316                           typeEnvs.put(tree.packge, topEnv);
  317                       }
  318                   }
  319               }
  320   
  321               for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
  322                   q.flags_field |= EXISTS;
  323   
  324               Name name = names.package_info;
  325               ClassSymbol c = reader.enterClass(name, tree.packge);
  326               c.flatname = names.fromString(tree.packge + "." + name);
  327               c.sourcefile = tree.sourcefile;
  328               c.completer = null;
  329               c.members_field = new Scope(c);
  330               tree.packge.package_info = c;
  331           }
  332           classEnter(tree.defs, topEnv);
  333           if (addEnv) {
  334               todo.append(topEnv);
  335           }
  336           log.useSource(prev);
  337           result = null;
  338       }
  339   
  340       @Override
  341       public void visitClassDef(JCClassDecl tree) {
  342           Symbol owner = env.info.scope.owner;
  343           Scope enclScope = enterScope(env);
  344           ClassSymbol c;
  345           if (owner.kind == PCK) {
  346               // We are seeing a toplevel class.
  347               PackageSymbol packge = (PackageSymbol)owner;
  348               for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
  349                   q.flags_field |= EXISTS;
  350               c = reader.enterClass(tree.name, packge);
  351               packge.members().enterIfAbsent(c);
  352               if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
  353                   log.error(tree.pos(),
  354                             "class.public.should.be.in.file", tree.name);
  355               }
  356           } else {
  357               if (!tree.name.isEmpty() &&
  358                   !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
  359                   result = null;
  360                   return;
  361               }
  362               if (owner.kind == TYP) {
  363                   // We are seeing a member class.
  364                   c = reader.enterClass(tree.name, (TypeSymbol)owner);
  365                   if ((owner.flags_field & INTERFACE) != 0) {
  366                       tree.mods.flags |= PUBLIC | STATIC;
  367                   }
  368               } else {
  369                   // We are seeing a local class.
  370                   c = reader.defineClass(tree.name, owner);
  371                   c.flatname = chk.localClassName(c);
  372                   if (!c.name.isEmpty())
  373                       chk.checkTransparentClass(tree.pos(), c, env.info.scope);
  374               }
  375           }
  376           tree.sym = c;
  377   
  378           // Enter class into `compiled' table and enclosing scope.
  379           if (chk.compiled.get(c.flatname) != null) {
  380               duplicateClass(tree.pos(), c);
  381               result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
  382               tree.sym = (ClassSymbol)result.tsym;
  383               return;
  384           }
  385           chk.compiled.put(c.flatname, c);
  386           enclScope.enter(c);
  387   
  388           // Set up an environment for class block and store in `typeEnvs'
  389           // table, to be retrieved later in memberEnter and attribution.
  390           Env<AttrContext> localEnv = classEnv(tree, env);
  391           typeEnvs.put(c, localEnv);
  392   
  393           // Fill out class fields.
  394           c.completer = memberEnter;
  395           c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
  396           c.sourcefile = env.toplevel.sourcefile;
  397           c.members_field = new Scope(c);
  398   
  399           ClassType ct = (ClassType)c.type;
  400           if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
  401               // We are seeing a local or inner class.
  402               // Set outer_field of this class to closest enclosing class
  403               // which contains this class in a non-static context
  404               // (its "enclosing instance class"), provided such a class exists.
  405               Symbol owner1 = owner;
  406               while ((owner1.kind & (VAR | MTH)) != 0 &&
  407                      (owner1.flags_field & STATIC) == 0) {
  408                   owner1 = owner1.owner;
  409               }
  410               if (owner1.kind == TYP) {
  411                   ct.setEnclosingType(owner1.type);
  412               }
  413           }
  414   
  415           // Enter type parameters.
  416           ct.typarams_field = classEnter(tree.typarams, localEnv);
  417   
  418           // Add non-local class to uncompleted, to make sure it will be
  419           // completed later.
  420           if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
  421   //      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG
  422   
  423           // Recursively enter all member classes.
  424           classEnter(tree.defs, localEnv);
  425   
  426           result = c.type;
  427       }
  428       //where
  429           /** Does class have the same name as the file it appears in?
  430            */
  431           private static boolean classNameMatchesFileName(ClassSymbol c,
  432                                                           Env<AttrContext> env) {
  433               return env.toplevel.sourcefile.isNameCompatible(c.name.toString(),
  434                                                               JavaFileObject.Kind.SOURCE);
  435           }
  436   
  437       /** Complain about a duplicate class. */
  438       protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
  439           log.error(pos, "duplicate.class", c.fullname);
  440       }
  441   
  442       /** Class enter visitor method for type parameters.
  443        *  Enter a symbol for type parameter in local scope, after checking that it
  444        *  is unique.
  445        */
  446       @Override
  447       public void visitTypeParameter(JCTypeParameter tree) {
  448           TypeVar a = (tree.type != null)
  449               ? (TypeVar)tree.type
  450               : new TypeVar(tree.name, env.info.scope.owner, syms.botType);
  451           tree.type = a;
  452           if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
  453               env.info.scope.enter(a.tsym);
  454           }
  455           result = a;
  456       }
  457   
  458       /** Default class enter visitor method: do nothing.
  459        */
  460       @Override
  461       public void visitTree(JCTree tree) {
  462           result = null;
  463       }
  464   
  465       /** Main method: enter all classes in a list of toplevel trees.
  466        *  @param trees      The list of trees to be processed.
  467        */
  468       public void main(List<JCCompilationUnit> trees) {
  469           complete(trees, null);
  470       }
  471   
  472       /** Main method: enter one class from a list of toplevel trees and
  473        *  place the rest on uncompleted for later processing.
  474        *  @param trees      The list of trees to be processed.
  475        *  @param c          The class symbol to be processed.
  476        */
  477       public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
  478           annotate.enterStart();
  479           ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
  480           if (memberEnter.completionEnabled) uncompleted = new ListBuffer<ClassSymbol>();
  481   
  482           try {
  483               // enter all classes, and construct uncompleted list
  484               classEnter(trees, null);
  485   
  486               // complete all uncompleted classes in memberEnter
  487               if  (memberEnter.completionEnabled) {
  488                   while (uncompleted.nonEmpty()) {
  489                       ClassSymbol clazz = uncompleted.next();
  490                       if (c == null || c == clazz || prevUncompleted == null)
  491                           clazz.complete();
  492                       else
  493                           // defer
  494                           prevUncompleted.append(clazz);
  495                   }
  496   
  497                   // if there remain any unimported toplevels (these must have
  498                   // no classes at all), process their import statements as well.
  499                   for (JCCompilationUnit tree : trees) {
  500                       if (tree.starImportScope.elems == null) {
  501                           JavaFileObject prev = log.useSource(tree.sourcefile);
  502                           Env<AttrContext> topEnv = topLevelEnv(tree);
  503                           memberEnter.memberEnter(tree, topEnv);
  504                           log.useSource(prev);
  505                       }
  506                   }
  507               }
  508           } finally {
  509               uncompleted = prevUncompleted;
  510               annotate.enterDone();
  511           }
  512       }
  513   }

Home » openjdk-7 » com.sun.tools » javac » comp » [javadoc | source]