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                 @SuppressWarnings("deprecation")
 343                 ModuleSymbol moduleSymbol = dependencyWithPackage.get();
 344                 log.error(pd, Errors.PackageInOtherModule(moduleSymbol));
 345             }
 346 
 347             tree.packge.complete(); // Find all classes in package.
 348 
 349             Env<AttrContext> topEnv = topLevelEnv(tree);
 350             Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
 351 
 352             // Save environment of package-info.java file.
 353             if (isPkgInfo) {
 354                 Env<AttrContext> env0 = typeEnvs.get(tree.packge);
 355                 if (env0 != null) {
 356                     JCCompilationUnit tree0 = env0.toplevel;
 357                     if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
 358                         log.warning(pd != null ? pd.pid.pos() : null,
 359                                     "pkg-info.already.seen",
 360                                     tree.packge);
 361                     }
 362                 }
 363                 typeEnvs.put(tree.packge, packageEnv);
 364 
 365                 for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
 366                     q.flags_field |= EXISTS;
 367 
 368                 Name name = names.package_info;
 369                 ClassSymbol c = syms.enterClass(tree.modle, name, tree.packge);
 370                 c.flatname = names.fromString(tree.packge + "." + name);
 371                 c.sourcefile = tree.sourcefile;
 372             c.completer = Completer.NULL_COMPLETER;
 373                 c.members_field = WriteableScope.create(c);
 374                 tree.packge.package_info = c;
 375             }
 376             classEnter(tree.defs, topEnv);
 377             if (addEnv) {
 378                 todo.append(packageEnv);
 379             }
 380         }
 381         log.useSource(prev);
 382         result = null;
 383     }
 384 
 385     @Override
 386     public void visitClassDef(JCClassDecl tree) {
 387         Symbol owner = env.info.scope.owner;
 388         WriteableScope enclScope = enterScope(env);
 389         ClassSymbol c;
 390         if (owner.kind == PCK) {
 391             // We are seeing a toplevel class.
 392             PackageSymbol packge = (PackageSymbol)owner;
 393             for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
 394                 q.flags_field |= EXISTS;
 395             c = syms.enterClass(env.toplevel.modle, tree.name, packge);
 396             packge.members().enterIfAbsent(c);
 397             if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
 398                 log.error(tree.pos(),
 399                           "class.public.should.be.in.file", tree.name);
 400             }
 401         } else {
 402             if (!tree.name.isEmpty() &&
 403                 !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
 404                 result = null;
 405                 return;
 406             }
 407             if (owner.kind == TYP) {
 408                 // We are seeing a member class.
 409                 c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
 410                 if ((owner.flags_field & INTERFACE) != 0) {
 411                     tree.mods.flags |= PUBLIC | STATIC;
 412                 }
 413             } else {
 414                 // We are seeing a local class.
 415                 c = syms.defineClass(tree.name, owner);
 416                 c.flatname = chk.localClassName(c);
 417                 if (!c.name.isEmpty())
 418                     chk.checkTransparentClass(tree.pos(), c, env.info.scope);
 419             }
 420         }
 421         tree.sym = c;
 422 
 423         // Enter class into `compiled' table and enclosing scope.
 424         if (chk.getCompiled(c) != null) {
 425             duplicateClass(tree.pos(), c);
 426             result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
 427             tree.sym = (ClassSymbol)result.tsym;
 428             return;
 429         }
 430         chk.putCompiled(c);
 431         enclScope.enter(c);
 432 
 433         // Set up an environment for class block and store in `typeEnvs'
 434         // table, to be retrieved later in memberEnter and attribution.
 435         Env<AttrContext> localEnv = classEnv(tree, env);
 436         typeEnvs.put(c, localEnv);
 437 
 438         // Fill out class fields.
 439         c.completer = Completer.NULL_COMPLETER; // do not allow the initial completer linger on.
 440         c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
 441         c.sourcefile = env.toplevel.sourcefile;
 442         c.members_field = WriteableScope.create(c);
 443 
 444         ClassType ct = (ClassType)c.type;
 445         if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
 446             // We are seeing a local or inner class.
 447             // Set outer_field of this class to closest enclosing class
 448             // which contains this class in a non-static context
 449             // (its "enclosing instance class"), provided such a class exists.
 450             Symbol owner1 = owner;
 451             while (owner1.kind.matches(KindSelector.VAL_MTH) &&
 452                    (owner1.flags_field & STATIC) == 0) {
 453                 owner1 = owner1.owner;
 454             }
 455             if (owner1.kind == TYP) {
 456                 ct.setEnclosingType(owner1.type);
 457             }
 458         }
 459 
 460         // Enter type parameters.
 461         ct.typarams_field = classEnter(tree.typarams, localEnv);
 462 
 463         // install further completer for this type.
 464         c.completer = typeEnter;
 465 
 466         // Add non-local class to uncompleted, to make sure it will be
 467         // completed later.
 468         if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
 469 //      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG
 470 
 471         // Recursively enter all member classes.
 472         classEnter(tree.defs, localEnv);
 473 
 474 //        Assert.checkNonNull(c.modle, c.sourcefile.toString());
 475 
 476         result = c.type;
 477     }
 478     //where
 479         /** Does class have the same name as the file it appears in?
 480          */
 481         private static boolean classNameMatchesFileName(ClassSymbol c,
 482                                                         Env<AttrContext> env) {
 483             return env.toplevel.sourcefile.isNameCompatible(c.name.toString(),
 484                                                             JavaFileObject.Kind.SOURCE);
 485         }
 486 
 487     /** Complain about a duplicate class. */
 488     protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
 489         log.error(pos, "duplicate.class", c.fullname);
 490     }
 491 
 492     /** Class enter visitor method for type parameters.
 493      *  Enter a symbol for type parameter in local scope, after checking that it
 494      *  is unique.
 495      */
 496     @Override
 497     public void visitTypeParameter(JCTypeParameter tree) {
 498         TypeVar a = (tree.type != null)
 499             ? (TypeVar)tree.type
 500             : new TypeVar(tree.name, env.info.scope.owner, syms.botType);
 501         tree.type = a;
 502         if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
 503             env.info.scope.enter(a.tsym);
 504         }
 505         result = a;
 506     }
 507 
 508     @Override
 509     public void visitModuleDef(JCModuleDecl tree) {
 510         Env<AttrContext> moduleEnv = moduleEnv(tree, env);
 511         typeEnvs.put(tree.sym, moduleEnv);
 512         todo.append(moduleEnv);
 513     }
 514 
 515     /** Default class enter visitor method: do nothing.
 516      */
 517     @Override
 518     public void visitTree(JCTree tree) {
 519         result = null;
 520     }
 521 
 522     /** Main method: enter all classes in a list of toplevel trees.
 523      *  @param trees      The list of trees to be processed.
 524      */
 525     public void main(List<JCCompilationUnit> trees) {
 526         complete(trees, null);
 527     }
 528 
 529     /** Main method: enter classes from the list of toplevel trees, possibly
 530      *  skipping TypeEnter for all but 'c' by placing them on the uncompleted
 531      *  list.
 532      *  @param trees      The list of trees to be processed.
 533      *  @param c          The class symbol to be processed or null to process all.
 534      */
 535     public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
 536         annotate.blockAnnotations();
 537         ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
 538         if (typeEnter.completionEnabled) uncompleted = new ListBuffer<>();
 539 
 540         try {
 541             // enter all classes, and construct uncompleted list
 542             classEnter(trees, null);
 543 
 544             // complete all uncompleted classes in memberEnter
 545             if (typeEnter.completionEnabled) {
 546                 while (uncompleted.nonEmpty()) {
 547                     ClassSymbol clazz = uncompleted.next();
 548                     if (c == null || c == clazz || prevUncompleted == null)
 549                         clazz.complete();
 550                     else
 551                         // defer
 552                         prevUncompleted.append(clazz);
 553                 }
 554 
 555                 typeEnter.ensureImportsChecked(trees);
 556             }
 557         } finally {
 558             uncompleted = prevUncompleted;
 559             annotate.unblockAnnotations();
 560         }
 561     }
 562 
 563     public void newRound() {
 564         typeEnvs.clear();
 565     }
 566 }