Enter.java revision 3964:7729c633b9f1
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.tree.*;
43import com.sun.tools.javac.tree.JCTree.*;
44import com.sun.tools.javac.util.*;
45import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
46import com.sun.tools.javac.util.List;
47
48import static com.sun.tools.javac.code.Flags.*;
49import static com.sun.tools.javac.code.Kinds.Kind.*;
50
51/** This class enters symbols for all encountered definitions into
52 *  the symbol table. The pass consists of high-level two phases,
53 *  organized as follows:
54 *
55 *  <p>In the first phase, all class symbols are entered into their
56 *  enclosing scope, descending recursively down the tree for classes
57 *  which are members of other classes. The class symbols are given a
58 *  TypeEnter object as completer.
59 *
60 *  <p>In the second phase classes are completed using
61 *  TypeEnter.complete(). Completion might occur on demand, but
62 *  any classes that are not completed that way will be eventually
63 *  completed by processing the `uncompleted' queue. Completion
64 *  entails determination of a class's parameters, supertype and
65 *  interfaces, as well as entering all symbols defined in the
66 *  class into its scope, with the exception of class symbols which
67 *  have been entered in phase 1.
68 *
69 *  <p>Whereas the first phase is organized as a sweep through all
70 *  compiled syntax trees, the second phase is on-demand. Members of a
71 *  class are entered when the contents of a class are first
72 *  accessed. This is accomplished by installing completer objects in
73 *  class symbols for compiled classes which invoke the type-enter
74 *  phase for the corresponding class tree.
75 *
76 *  <p>Classes migrate from one phase to the next via queues:
77 *
78 *  <pre>{@literal
79 *  class enter -> (Enter.uncompleted)         --> type enter
80 *              -> (Todo)                      --> attribute
81 *                                              (only for toplevel classes)
82 *  }</pre>
83 *
84 *  <p><b>This is NOT part of any supported API.
85 *  If you write code that depends on this, you do so at your own risk.
86 *  This code and its internal interfaces are subject to change or
87 *  deletion without notice.</b>
88 */
89public class Enter extends JCTree.Visitor {
90    protected static final Context.Key<Enter> enterKey = new Context.Key<>();
91
92    Annotate annotate;
93    Log log;
94    Symtab syms;
95    Check chk;
96    TreeMaker make;
97    TypeEnter typeEnter;
98    Types types;
99    Lint lint;
100    Names names;
101    JavaFileManager fileManager;
102    PkgInfo pkginfoOpt;
103    TypeEnvs typeEnvs;
104    Modules modules;
105    JCDiagnostic.Factory diags;
106
107    private final Todo todo;
108
109    public static Enter instance(Context context) {
110        Enter instance = context.get(enterKey);
111        if (instance == null)
112            instance = new Enter(context);
113        return instance;
114    }
115
116    protected Enter(Context context) {
117        context.put(enterKey, this);
118
119        log = Log.instance(context);
120        make = TreeMaker.instance(context);
121        syms = Symtab.instance(context);
122        chk = Check.instance(context);
123        typeEnter = TypeEnter.instance(context);
124        types = Types.instance(context);
125        annotate = Annotate.instance(context);
126        lint = Lint.instance(context);
127        names = Names.instance(context);
128        modules = Modules.instance(context);
129        diags = JCDiagnostic.Factory.instance(context);
130
131        predefClassDef = make.ClassDef(
132            make.Modifiers(PUBLIC),
133            syms.predefClass.name,
134            List.nil(),
135            null,
136            List.nil(),
137            List.nil());
138        predefClassDef.sym = syms.predefClass;
139        todo = Todo.instance(context);
140        fileManager = context.get(JavaFileManager.class);
141
142        Options options = Options.instance(context);
143        pkginfoOpt = PkgInfo.get(options);
144        typeEnvs = TypeEnvs.instance(context);
145    }
146
147    /** Accessor for typeEnvs
148     */
149    public Env<AttrContext> getEnv(TypeSymbol sym) {
150        return typeEnvs.get(sym);
151    }
152
153    public Iterable<Env<AttrContext>> getEnvs() {
154        return typeEnvs.values();
155    }
156
157    public Env<AttrContext> getClassEnv(TypeSymbol sym) {
158        Env<AttrContext> localEnv = getEnv(sym);
159        if (localEnv == null) return null;
160        Env<AttrContext> lintEnv = localEnv;
161        while (lintEnv.info.lint == null)
162            lintEnv = lintEnv.next;
163        localEnv.info.lint = lintEnv.info.lint.augment(sym);
164        return localEnv;
165    }
166
167    /** The queue of all classes that might still need to be completed;
168     *  saved and initialized by main().
169     */
170    ListBuffer<ClassSymbol> uncompleted;
171
172    /** The queue of modules whose imports still need to be checked. */
173    ListBuffer<JCCompilationUnit> unfinishedModules = new ListBuffer<>();
174
175    /** A dummy class to serve as enclClass for toplevel environments.
176     */
177    private JCClassDecl predefClassDef;
178
179/* ************************************************************************
180 * environment construction
181 *************************************************************************/
182
183
184    /** Create a fresh environment for class bodies.
185     *  This will create a fresh scope for local symbols of a class, referred
186     *  to by the environments info.scope field.
187     *  This scope will contain
188     *    - symbols for this and super
189     *    - symbols for any type parameters
190     *  In addition, it serves as an anchor for scopes of methods and initializers
191     *  which are nested in this scope via Scope.dup().
192     *  This scope should not be confused with the members scope of a class.
193     *
194     *  @param tree     The class definition.
195     *  @param env      The environment current outside of the class definition.
196     */
197    public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
198        Env<AttrContext> localEnv =
199            env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
200        localEnv.enclClass = tree;
201        localEnv.outer = env;
202        localEnv.info.isSelfCall = false;
203        localEnv.info.lint = null; // leave this to be filled in by Attr,
204                                   // when annotations have been processed
205        localEnv.info.isAnonymousDiamond = TreeInfo.isDiamond(env.tree);
206        return localEnv;
207    }
208
209    /** Create a fresh environment for toplevels.
210     *  @param tree     The toplevel tree.
211     */
212    Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
213        Env<AttrContext> localEnv = new Env<>(tree, new AttrContext());
214        localEnv.toplevel = tree;
215        localEnv.enclClass = predefClassDef;
216        tree.toplevelScope = WriteableScope.create(tree.packge);
217        tree.namedImportScope = new NamedImportScope(tree.packge, tree.toplevelScope);
218        tree.starImportScope = new StarImportScope(tree.packge);
219        localEnv.info.scope = tree.toplevelScope;
220        localEnv.info.lint = lint;
221        return localEnv;
222    }
223
224    public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) {
225        Env<AttrContext> localEnv = new Env<>(tree, new AttrContext());
226        localEnv.toplevel = tree;
227        localEnv.enclClass = predefClassDef;
228        localEnv.info.scope = tree.toplevelScope;
229        localEnv.info.lint = lint;
230        return localEnv;
231    }
232
233    /** The scope in which a member definition in environment env is to be entered
234     *  This is usually the environment's scope, except for class environments,
235     *  where the local scope is for type variables, and the this and super symbol
236     *  only, and members go into the class member scope.
237     */
238    WriteableScope enterScope(Env<AttrContext> env) {
239        return (env.tree.hasTag(JCTree.Tag.CLASSDEF))
240            ? ((JCClassDecl) env.tree).sym.members_field
241            : env.info.scope;
242    }
243
244    /** Create a fresh environment for modules.
245     *
246     *  @param tree     The module definition.
247     *  @param env      The environment current outside of the module definition.
248     */
249    public Env<AttrContext> moduleEnv(JCModuleDecl tree, Env<AttrContext> env) {
250        Assert.checkNonNull(tree.sym);
251        Env<AttrContext> localEnv =
252            env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
253        localEnv.enclClass = predefClassDef;
254        localEnv.outer = env;
255        localEnv.info.isSelfCall = false;
256        localEnv.info.lint = null; // leave this to be filled in by Attr,
257                                   // when annotations have been processed
258        return localEnv;
259    }
260
261
262/* ************************************************************************
263 * Visitor methods for phase 1: class enter
264 *************************************************************************/
265
266    /** Visitor argument: the current environment.
267     */
268    protected Env<AttrContext> env;
269
270    /** Visitor result: the computed type.
271     */
272    Type result;
273
274    /** Visitor method: enter all classes in given tree, catching any
275     *  completion failure exceptions. Return the tree's type.
276     *
277     *  @param tree    The tree to be visited.
278     *  @param env     The environment visitor argument.
279     */
280    Type classEnter(JCTree tree, Env<AttrContext> env) {
281        Env<AttrContext> prevEnv = this.env;
282        try {
283            this.env = env;
284            annotate.blockAnnotations();
285            tree.accept(this);
286            return result;
287        }  catch (CompletionFailure ex) {
288            return chk.completionError(tree.pos(), ex);
289        } finally {
290            annotate.unblockAnnotations();
291            this.env = prevEnv;
292        }
293    }
294
295    /** Visitor method: enter classes of a list of trees, returning a list of types.
296     */
297    <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) {
298        ListBuffer<Type> ts = new ListBuffer<>();
299        for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
300            Type t = classEnter(l.head, env);
301            if (t != null)
302                ts.append(t);
303        }
304        return ts.toList();
305    }
306
307    @Override
308    public void visitTopLevel(JCCompilationUnit tree) {
309//        Assert.checkNonNull(tree.modle, tree.sourcefile.toString());
310
311        JavaFileObject prev = log.useSource(tree.sourcefile);
312        boolean addEnv = false;
313        boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
314                                                             JavaFileObject.Kind.SOURCE);
315        if (TreeInfo.isModuleInfo(tree)) {
316            JCPackageDecl pd = tree.getPackage();
317            if (pd != null) {
318                log.error(pd.pos(), Errors.NoPkgInModuleInfoJava);
319            }
320            tree.packge = syms.rootPackage;
321            Env<AttrContext> topEnv = topLevelEnv(tree);
322            classEnter(tree.defs, topEnv);
323            tree.modle.usesProvidesCompleter = modules.getUsesProvidesCompleter();
324        } else {
325            JCPackageDecl pd = tree.getPackage();
326            if (pd != null) {
327                tree.packge = pd.packge = syms.enterPackage(tree.modle, TreeInfo.fullName(pd.pid));
328                if (   pd.annotations.nonEmpty()
329                    || pkginfoOpt == PkgInfo.ALWAYS
330                    || tree.docComments != null) {
331                    if (isPkgInfo) {
332                        addEnv = true;
333                    } else if (pd.annotations.nonEmpty()) {
334                        log.error(pd.annotations.head.pos(),
335                                  "pkg.annotations.sb.in.package-info.java");
336                    }
337                }
338            } else {
339                tree.packge = tree.modle.unnamedPackage;
340            }
341
342            Map<Name, PackageSymbol> visiblePackages = tree.modle.visiblePackages;
343            Optional<ModuleSymbol> dependencyWithPackage =
344                syms.listPackageModules(tree.packge.fullname)
345                    .stream()
346                    .filter(m -> m != tree.modle)
347                    .filter(cand -> visiblePackages.get(tree.packge.fullname) == syms.getPackage(cand, tree.packge.fullname))
348                    .findAny();
349
350            if (dependencyWithPackage.isPresent()) {
351                log.error(pd, Errors.PackageInOtherModule(dependencyWithPackage.get()));
352            }
353
354            tree.packge.complete(); // Find all classes in package.
355
356            Env<AttrContext> topEnv = topLevelEnv(tree);
357            Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
358
359            // Save environment of package-info.java file.
360            if (isPkgInfo) {
361                Env<AttrContext> env0 = typeEnvs.get(tree.packge);
362                if (env0 != null) {
363                    JCCompilationUnit tree0 = env0.toplevel;
364                    if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
365                        log.warning(pd != null ? pd.pid.pos() : null,
366                                    "pkg-info.already.seen",
367                                    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                          "class.public.should.be.in.file", 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, "duplicate.class", 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