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