1 /*
   2  * Copyright (c) 1999, 2016, 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.Map;
  29 import java.util.Optional;
  30 
  31 import javax.tools.JavaFileObject;
  32 import javax.tools.JavaFileManager;
  33 
  34 import com.sun.tools.javac.code.*;
  35 import com.sun.tools.javac.code.Kinds.KindSelector;
  36 import com.sun.tools.javac.code.Scope.*;
  37 import com.sun.tools.javac.code.Symbol.*;
  38 import com.sun.tools.javac.code.Type.*;
  39 import com.sun.tools.javac.main.Option.PkgInfo;
  40 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  41 import com.sun.tools.javac.tree.*;
  42 import com.sun.tools.javac.tree.JCTree.*;
  43 import com.sun.tools.javac.util.*;
  44 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  45 import com.sun.tools.javac.util.List;
  46 
  47 import static com.sun.tools.javac.code.Flags.*;
  48 import static com.sun.tools.javac.code.Kinds.Kind.*;
  49 
  50 /** This class enters symbols for all encountered definitions into
  51  *  the symbol table. The pass consists of high-level two phases,
  52  *  organized as follows:
  53  *
  54  *  <p>In the first phase, all class symbols are entered into their
  55  *  enclosing scope, descending recursively down the tree for classes
  56  *  which are members of other classes. The class symbols are given a
  57  *  TypeEnter object as completer.
  58  *
  59  *  <p>In the second phase classes are completed using
  60  *  TypeEnter.complete(). Completion might occur on demand, but
  61  *  any classes that are not completed that way will be eventually
  62  *  completed by processing the `uncompleted' queue. Completion
  63  *  entails determination of a class's parameters, supertype and
  64  *  interfaces, as well as entering all symbols defined in the
  65  *  class into its scope, with the exception of class symbols which
  66  *  have been entered in phase 1.
  67  *
  68  *  <p>Whereas the first phase is organized as a sweep through all
  69  *  compiled syntax trees, the second phase is on-demand. Members of a
  70  *  class are entered when the contents of a class are first
  71  *  accessed. This is accomplished by installing completer objects in
  72  *  class symbols for compiled classes which invoke the type-enter
  73  *  phase for the corresponding class tree.
  74  *
  75  *  <p>Classes migrate from one phase to the next via queues:
  76  *
  77  *  <pre>{@literal
  78  *  class enter -> (Enter.uncompleted)         --> type enter
  79  *              -> (Todo)                      --> attribute
  80  *                                              (only for toplevel classes)
  81  *  }</pre>
  82  *
  83  *  <p><b>This is NOT part of any supported API.
  84  *  If you write code that depends on this, you do so at your own risk.
  85  *  This code and its internal interfaces are subject to change or
  86  *  deletion without notice.</b>
  87  */
  88 public class Enter extends JCTree.Visitor {
  89     protected static final Context.Key<Enter> enterKey = new Context.Key<>();
  90 
  91     Annotate annotate;
  92     Log log;
  93     Symtab syms;
  94     Check chk;
  95     TreeMaker make;
  96     TypeEnter typeEnter;
  97     Types types;
  98     Lint lint;
  99     Names names;
 100     JavaFileManager fileManager;
 101     PkgInfo pkginfoOpt;
 102     TypeEnvs typeEnvs;
 103     Modules modules;
 104     JCDiagnostic.Factory diags;
 105 
 106     private final Todo todo;
 107 
 108     public static Enter instance(Context context) {
 109         Enter instance = context.get(enterKey);
 110         if (instance == null)
 111             instance = new Enter(context);
 112         return instance;
 113     }
 114 
 115     protected Enter(Context context) {
 116         context.put(enterKey, this);
 117 
 118         log = Log.instance(context);
 119         make = TreeMaker.instance(context);
 120         syms = Symtab.instance(context);
 121         chk = Check.instance(context);
 122         typeEnter = TypeEnter.instance(context);
 123         types = Types.instance(context);
 124         annotate = Annotate.instance(context);
 125         lint = Lint.instance(context);
 126         names = Names.instance(context);
 127         modules = Modules.instance(context);
 128         diags = JCDiagnostic.Factory.instance(context);
 129 
 130         predefClassDef = make.ClassDef(
 131             make.Modifiers(PUBLIC),
 132             syms.predefClass.name,
 133             List.<JCTypeParameter>nil(),
 134             null,
 135             List.<JCExpression>nil(),
 136             List.<JCTree>nil());
 137         predefClassDef.sym = syms.predefClass;
 138         todo = Todo.instance(context);
 139         fileManager = context.get(JavaFileManager.class);
 140 
 141         Options options = Options.instance(context);
 142         pkginfoOpt = PkgInfo.get(options);
 143         typeEnvs = TypeEnvs.instance(context);
 144     }
 145 
 146     /** Accessor for typeEnvs
 147      */
 148     public Env<AttrContext> getEnv(TypeSymbol sym) {
 149         return typeEnvs.get(sym);
 150     }
 151 
 152     public Iterable<Env<AttrContext>> getEnvs() {
 153         return typeEnvs.values();
 154     }
 155 
 156     public Env<AttrContext> getClassEnv(TypeSymbol sym) {
 157         Env<AttrContext> localEnv = getEnv(sym);
 158         Env<AttrContext> lintEnv = localEnv;
 159         while (lintEnv.info.lint == null)
 160             lintEnv = lintEnv.next;
 161         localEnv.info.lint = lintEnv.info.lint.augment(sym);
 162         return localEnv;
 163     }
 164 
 165     /** The queue of all classes that might still need to be completed;
 166      *  saved and initialized by main().
 167      */
 168     ListBuffer<ClassSymbol> uncompleted;
 169 
 170     /** A dummy class to serve as enclClass for toplevel environments.
 171      */
 172     private JCClassDecl predefClassDef;
 173 
 174 /* ************************************************************************
 175  * environment construction
 176  *************************************************************************/
 177 
 178 
 179     /** Create a fresh environment for class bodies.
 180      *  This will create a fresh scope for local symbols of a class, referred
 181      *  to by the environments info.scope field.
 182      *  This scope will contain
 183      *    - symbols for this and super
 184      *    - symbols for any type parameters
 185      *  In addition, it serves as an anchor for scopes of methods and initializers
 186      *  which are nested in this scope via Scope.dup().
 187      *  This scope should not be confused with the members scope of a class.
 188      *
 189      *  @param tree     The class definition.
 190      *  @param env      The environment current outside of the class definition.
 191      */
 192     public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
 193         Env<AttrContext> localEnv =
 194             env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
 195         localEnv.enclClass = tree;
 196         localEnv.outer = env;
 197         localEnv.info.isSelfCall = false;
 198         localEnv.info.lint = null; // leave this to be filled in by Attr,
 199                                    // when annotations have been processed
 200         localEnv.info.isAnonymousDiamond = TreeInfo.isDiamond(env.tree);
 201         return localEnv;
 202     }
 203 
 204     /** Create a fresh environment for toplevels.
 205      *  @param tree     The toplevel tree.
 206      */
 207     Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
 208         Env<AttrContext> localEnv = new Env<>(tree, new AttrContext());
 209         localEnv.toplevel = tree;
 210         localEnv.enclClass = predefClassDef;
 211         tree.toplevelScope = WriteableScope.create(tree.packge);
 212         tree.namedImportScope = new NamedImportScope(tree.packge, tree.toplevelScope);
 213         tree.starImportScope = new StarImportScope(tree.packge);
 214         localEnv.info.scope = tree.toplevelScope;
 215         localEnv.info.lint = lint;
 216         return localEnv;
 217     }
 218 
 219     public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) {
 220         Env<AttrContext> localEnv = new Env<>(tree, new AttrContext());
 221         localEnv.toplevel = tree;
 222         localEnv.enclClass = predefClassDef;
 223         localEnv.info.scope = tree.toplevelScope;
 224         localEnv.info.lint = lint;
 225         return localEnv;
 226     }
 227 
 228     /** The scope in which a member definition in environment env is to be entered
 229      *  This is usually the environment's scope, except for class environments,
 230      *  where the local scope is for type variables, and the this and super symbol
 231      *  only, and members go into the class member scope.
 232      */
 233     WriteableScope enterScope(Env<AttrContext> env) {
 234         return (env.tree.hasTag(JCTree.Tag.CLASSDEF))
 235             ? ((JCClassDecl) env.tree).sym.members_field
 236             : env.info.scope;
 237     }
 238 
 239     /** Create a fresh environment for modules.
 240      *
 241      *  @param tree     The module definition.
 242      *  @param env      The environment current outside of the module definition.
 243      */
 244     public Env<AttrContext> moduleEnv(JCModuleDecl tree, Env<AttrContext> env) {
 245         Assert.checkNonNull(tree.sym);
 246         Env<AttrContext> localEnv =
 247             env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
 248         localEnv.enclClass = predefClassDef;
 249         localEnv.outer = env;
 250         localEnv.info.isSelfCall = false;
 251         localEnv.info.lint = null; // leave this to be filled in by Attr,
 252                                    // when annotations have been processed
 253         return localEnv;
 254     }
 255 
 256 
 257 /* ************************************************************************
 258  * Visitor methods for phase 1: class enter
 259  *************************************************************************/
 260 
 261     /** Visitor argument: the current environment.
 262      */
 263     protected Env<AttrContext> env;
 264 
 265     /** Visitor result: the computed type.
 266      */
 267     Type result;
 268 
 269     /** Visitor method: enter all classes in given tree, catching any
 270      *  completion failure exceptions. Return the tree's type.
 271      *
 272      *  @param tree    The tree to be visited.
 273      *  @param env     The environment visitor argument.
 274      */
 275     Type classEnter(JCTree tree, Env<AttrContext> env) {
 276         Env<AttrContext> prevEnv = this.env;
 277         try {
 278             this.env = env;
 279             annotate.blockAnnotations();
 280             tree.accept(this);
 281             return result;
 282         }  catch (CompletionFailure ex) {
 283             return chk.completionError(tree.pos(), ex);
 284         } finally {
 285             annotate.unblockAnnotations();
 286             this.env = prevEnv;
 287         }
 288     }
 289 
 290     /** Visitor method: enter classes of a list of trees, returning a list of types.
 291      */
 292     <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) {
 293         ListBuffer<Type> ts = new ListBuffer<>();
 294         for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
 295             Type t = classEnter(l.head, env);
 296             if (t != null)
 297                 ts.append(t);
 298         }
 299         return ts.toList();
 300     }
 301 
 302     @Override
 303     public void visitTopLevel(JCCompilationUnit tree) {
 304 //        Assert.checkNonNull(tree.modle, tree.sourcefile.toString());
 305 
 306         JavaFileObject prev = log.useSource(tree.sourcefile);
 307         boolean addEnv = false;
 308         boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
 309                                                              JavaFileObject.Kind.SOURCE);
 310         if (TreeInfo.isModuleInfo(tree)) {
 311             tree.packge = syms.rootPackage;
 312             Env<AttrContext> topEnv = topLevelEnv(tree);
 313             classEnter(tree.defs, topEnv);
 314             tree.modle.usesProvidesCompleter = modules.getUsesProvidesCompleter();
 315         } else {
 316             JCPackageDecl pd = tree.getPackage();
 317             if (pd != null) {
 318                 tree.packge = pd.packge = syms.enterPackage(tree.modle, TreeInfo.fullName(pd.pid));
 319                 if (   pd.annotations.nonEmpty()
 320                     || pkginfoOpt == PkgInfo.ALWAYS
 321                     || tree.docComments != null) {
 322                     if (isPkgInfo) {
 323                         addEnv = true;
 324                     } else if (pd.annotations.nonEmpty()) {
 325                         log.error(pd.annotations.head.pos(),
 326                                   "pkg.annotations.sb.in.package-info.java");
 327                     }
 328                 }
 329             } else {
 330                 tree.packge = tree.modle.unnamedPackage;
 331             }
 332 
 333             Map<Name, PackageSymbol> visiblePackages = tree.modle.visiblePackages;
 334             Optional<ModuleSymbol> dependencyWithPackage =
 335                 syms.listPackageModules(tree.packge.fullname)
 336                     .stream()
 337                     .filter(m -> m != tree.modle)
 338                     .filter(cand -> visiblePackages.get(tree.packge.fullname) == syms.getPackage(cand, tree.packge.fullname))
 339                     .findAny();
 340 
 341             if (dependencyWithPackage.isPresent()) {
 342                 log.error(pd, Errors.PackageInOtherModule(dependencyWithPackage.get()));
 343             }
 344 
 345             tree.packge.complete(); // Find all classes in package.
 346 
 347             Env<AttrContext> topEnv = topLevelEnv(tree);
 348             Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
 349 
 350             // Save environment of package-info.java file.
 351             if (isPkgInfo) {
 352                 Env<AttrContext> env0 = typeEnvs.get(tree.packge);
 353                 if (env0 != null) {
 354                     JCCompilationUnit tree0 = env0.toplevel;
 355                     if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
 356                         log.warning(pd != null ? pd.pid.pos() : null,
 357                                     "pkg-info.already.seen",
 358                                     tree.packge);
 359                     }
 360                 }
 361                 typeEnvs.put(tree.packge, packageEnv);
 362 
 363                 for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
 364                     q.flags_field |= EXISTS;
 365 
 366                 Name name = names.package_info;
 367                 ClassSymbol c = syms.enterClass(tree.modle, name, tree.packge);
 368                 c.flatname = names.fromString(tree.packge + "." + name);
 369                 c.sourcefile = tree.sourcefile;
 370             c.completer = Completer.NULL_COMPLETER;
 371                 c.members_field = WriteableScope.create(c);
 372                 tree.packge.package_info = c;
 373             }
 374             classEnter(tree.defs, topEnv);
 375             if (addEnv) {
 376                 todo.append(packageEnv);
 377             }
 378         }
 379         log.useSource(prev);
 380         result = null;
 381     }
 382 
 383     @Override
 384     public void visitClassDef(JCClassDecl tree) {
 385         Symbol owner = env.info.scope.owner;
 386         WriteableScope enclScope = enterScope(env);
 387         ClassSymbol c;
 388         if (owner.kind == PCK) {
 389             // We are seeing a toplevel class.
 390             PackageSymbol packge = (PackageSymbol)owner;
 391             for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
 392                 q.flags_field |= EXISTS;
 393             c = syms.enterClass(env.toplevel.modle, tree.name, packge);
 394             packge.members().enterIfAbsent(c);
 395             if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
 396                 log.error(tree.pos(),
 397                           "class.public.should.be.in.file", tree.name);
 398             }
 399         } else {
 400             if (!tree.name.isEmpty() &&
 401                 !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
 402                 result = null;
 403                 return;
 404             }
 405             if (owner.kind == TYP) {
 406                 // We are seeing a member class.
 407                 c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
 408                 if ((owner.flags_field & INTERFACE) != 0) {
 409                     tree.mods.flags |= PUBLIC | STATIC;
 410                 }
 411             } else {
 412                 // We are seeing a local class.
 413                 c = syms.defineClass(tree.name, owner);
 414                 c.flatname = chk.localClassName(c);
 415                 if (!c.name.isEmpty())
 416                     chk.checkTransparentClass(tree.pos(), c, env.info.scope);
 417             }
 418         }
 419         tree.sym = c;
 420 
 421         // Enter class into `compiled' table and enclosing scope.
 422         if (chk.getCompiled(c) != null) {
 423             duplicateClass(tree.pos(), c);
 424             result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
 425             tree.sym = (ClassSymbol)result.tsym;
 426             return;
 427         }
 428         chk.putCompiled(c);
 429         enclScope.enter(c);
 430 
 431         // Set up an environment for class block and store in `typeEnvs'
 432         // table, to be retrieved later in memberEnter and attribution.
 433         Env<AttrContext> localEnv = classEnv(tree, env);
 434         typeEnvs.put(c, localEnv);
 435 
 436         // Fill out class fields.
 437         c.completer = Completer.NULL_COMPLETER; // do not allow the initial completer linger on.
 438         c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
 439         c.sourcefile = env.toplevel.sourcefile;
 440         c.members_field = WriteableScope.create(c);
 441 
 442         ClassType ct = (ClassType)c.type;
 443         if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
 444             // We are seeing a local or inner class.
 445             // Set outer_field of this class to closest enclosing class
 446             // which contains this class in a non-static context
 447             // (its "enclosing instance class"), provided such a class exists.
 448             Symbol owner1 = owner;
 449             while (owner1.kind.matches(KindSelector.VAL_MTH) &&
 450                    (owner1.flags_field & STATIC) == 0) {
 451                 owner1 = owner1.owner;
 452             }
 453             if (owner1.kind == TYP) {
 454                 ct.setEnclosingType(owner1.type);
 455             }
 456         }
 457 
 458         // Enter type parameters.
 459         ct.typarams_field = classEnter(tree.typarams, localEnv);
 460 
 461         // install further completer for this type.
 462         c.completer = typeEnter;
 463 
 464         // Add non-local class to uncompleted, to make sure it will be
 465         // completed later.
 466         if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
 467 //      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG
 468 
 469         // Recursively enter all member classes.
 470         classEnter(tree.defs, localEnv);
 471 
 472 //        Assert.checkNonNull(c.modle, c.sourcefile.toString());
 473 
 474         result = c.type;
 475     }
 476     //where
 477         /** Does class have the same name as the file it appears in?
 478          */
 479         private static boolean classNameMatchesFileName(ClassSymbol c,
 480                                                         Env<AttrContext> env) {
 481             return env.toplevel.sourcefile.isNameCompatible(c.name.toString(),
 482                                                             JavaFileObject.Kind.SOURCE);
 483         }
 484 
 485     /** Complain about a duplicate class. */
 486     protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
 487         log.error(pos, "duplicate.class", c.fullname);
 488     }
 489 
 490     /** Class enter visitor method for type parameters.
 491      *  Enter a symbol for type parameter in local scope, after checking that it
 492      *  is unique.
 493      */
 494     @Override
 495     public void visitTypeParameter(JCTypeParameter tree) {
 496         TypeVar a = (tree.type != null)
 497             ? (TypeVar)tree.type
 498             : new TypeVar(tree.name, env.info.scope.owner, syms.botType);
 499         tree.type = a;
 500         if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
 501             env.info.scope.enter(a.tsym);
 502         }
 503         result = a;
 504     }
 505 
 506     @Override
 507     public void visitModuleDef(JCModuleDecl tree) {
 508         Env<AttrContext> moduleEnv = moduleEnv(tree, env);
 509         typeEnvs.put(tree.sym, moduleEnv);
 510         todo.append(moduleEnv);
 511     }
 512 
 513     /** Default class enter visitor method: do nothing.
 514      */
 515     @Override
 516     public void visitTree(JCTree tree) {
 517         result = null;
 518     }
 519 
 520     /** Main method: enter all classes in a list of toplevel trees.
 521      *  @param trees      The list of trees to be processed.
 522      */
 523     public void main(List<JCCompilationUnit> trees) {
 524         complete(trees, null);
 525     }
 526 
 527     /** Main method: enter classes from the list of toplevel trees, possibly
 528      *  skipping TypeEnter for all but 'c' by placing them on the uncompleted
 529      *  list.
 530      *  @param trees      The list of trees to be processed.
 531      *  @param c          The class symbol to be processed or null to process all.
 532      */
 533     public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
 534         annotate.blockAnnotations();
 535         ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
 536         if (typeEnter.completionEnabled) uncompleted = new ListBuffer<>();
 537 
 538         try {
 539             // enter all classes, and construct uncompleted list
 540             classEnter(trees, null);
 541 
 542             // complete all uncompleted classes in memberEnter
 543             if (typeEnter.completionEnabled) {
 544                 while (uncompleted.nonEmpty()) {
 545                     ClassSymbol clazz = uncompleted.next();
 546                     if (c == null || c == clazz || prevUncompleted == null)
 547                         clazz.complete();
 548                     else
 549                         // defer
 550                         prevUncompleted.append(clazz);
 551                 }
 552 
 553                 typeEnter.ensureImportsChecked(trees);
 554             }
 555         } finally {
 556             uncompleted = prevUncompleted;
 557             annotate.unblockAnnotations();
 558         }
 559     }
 560 
 561     public void newRound() {
 562         typeEnvs.clear();
 563     }
 564 }