Enter.java revision 3796:031db713312f
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
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.KindSelector;
36import com.sun.tools.javac.code.Scope.*;
37import com.sun.tools.javac.code.Symbol.*;
38import com.sun.tools.javac.code.Type.*;
39import com.sun.tools.javac.main.Option.PkgInfo;
40import com.sun.tools.javac.resources.CompilerProperties.Errors;
41import com.sun.tools.javac.tree.*;
42import com.sun.tools.javac.tree.JCTree.*;
43import com.sun.tools.javac.util.*;
44import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
45import com.sun.tools.javac.util.List;
46
47import static com.sun.tools.javac.code.Flags.*;
48import 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 */
88public 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    /** The queue of modules whose imports still need to be checked. */
171    ListBuffer<JCCompilationUnit> unfinishedModules = new ListBuffer<>();
172
173    /** A dummy class to serve as enclClass for toplevel environments.
174     */
175    private JCClassDecl predefClassDef;
176
177/* ************************************************************************
178 * environment construction
179 *************************************************************************/
180
181
182    /** Create a fresh environment for class bodies.
183     *  This will create a fresh scope for local symbols of a class, referred
184     *  to by the environments info.scope field.
185     *  This scope will contain
186     *    - symbols for this and super
187     *    - symbols for any type parameters
188     *  In addition, it serves as an anchor for scopes of methods and initializers
189     *  which are nested in this scope via Scope.dup().
190     *  This scope should not be confused with the members scope of a class.
191     *
192     *  @param tree     The class definition.
193     *  @param env      The environment current outside of the class definition.
194     */
195    public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
196        Env<AttrContext> localEnv =
197            env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
198        localEnv.enclClass = tree;
199        localEnv.outer = env;
200        localEnv.info.isSelfCall = false;
201        localEnv.info.lint = null; // leave this to be filled in by Attr,
202                                   // when annotations have been processed
203        localEnv.info.isAnonymousDiamond = TreeInfo.isDiamond(env.tree);
204        return localEnv;
205    }
206
207    /** Create a fresh environment for toplevels.
208     *  @param tree     The toplevel tree.
209     */
210    Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
211        Env<AttrContext> localEnv = new Env<>(tree, new AttrContext());
212        localEnv.toplevel = tree;
213        localEnv.enclClass = predefClassDef;
214        tree.toplevelScope = WriteableScope.create(tree.packge);
215        tree.namedImportScope = new NamedImportScope(tree.packge, tree.toplevelScope);
216        tree.starImportScope = new StarImportScope(tree.packge);
217        localEnv.info.scope = tree.toplevelScope;
218        localEnv.info.lint = lint;
219        return localEnv;
220    }
221
222    public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) {
223        Env<AttrContext> localEnv = new Env<>(tree, new AttrContext());
224        localEnv.toplevel = tree;
225        localEnv.enclClass = predefClassDef;
226        localEnv.info.scope = tree.toplevelScope;
227        localEnv.info.lint = lint;
228        return localEnv;
229    }
230
231    /** The scope in which a member definition in environment env is to be entered
232     *  This is usually the environment's scope, except for class environments,
233     *  where the local scope is for type variables, and the this and super symbol
234     *  only, and members go into the class member scope.
235     */
236    WriteableScope enterScope(Env<AttrContext> env) {
237        return (env.tree.hasTag(JCTree.Tag.CLASSDEF))
238            ? ((JCClassDecl) env.tree).sym.members_field
239            : env.info.scope;
240    }
241
242    /** Create a fresh environment for modules.
243     *
244     *  @param tree     The module definition.
245     *  @param env      The environment current outside of the module definition.
246     */
247    public Env<AttrContext> moduleEnv(JCModuleDecl tree, Env<AttrContext> env) {
248        Assert.checkNonNull(tree.sym);
249        Env<AttrContext> localEnv =
250            env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
251        localEnv.enclClass = predefClassDef;
252        localEnv.outer = env;
253        localEnv.info.isSelfCall = false;
254        localEnv.info.lint = null; // leave this to be filled in by Attr,
255                                   // when annotations have been processed
256        return localEnv;
257    }
258
259
260/* ************************************************************************
261 * Visitor methods for phase 1: class enter
262 *************************************************************************/
263
264    /** Visitor argument: the current environment.
265     */
266    protected Env<AttrContext> env;
267
268    /** Visitor result: the computed type.
269     */
270    Type result;
271
272    /** Visitor method: enter all classes in given tree, catching any
273     *  completion failure exceptions. Return the tree's type.
274     *
275     *  @param tree    The tree to be visited.
276     *  @param env     The environment visitor argument.
277     */
278    Type classEnter(JCTree tree, Env<AttrContext> env) {
279        Env<AttrContext> prevEnv = this.env;
280        try {
281            this.env = env;
282            annotate.blockAnnotations();
283            tree.accept(this);
284            return result;
285        }  catch (CompletionFailure ex) {
286            return chk.completionError(tree.pos(), ex);
287        } finally {
288            annotate.unblockAnnotations();
289            this.env = prevEnv;
290        }
291    }
292
293    /** Visitor method: enter classes of a list of trees, returning a list of types.
294     */
295    <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) {
296        ListBuffer<Type> ts = new ListBuffer<>();
297        for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
298            Type t = classEnter(l.head, env);
299            if (t != null)
300                ts.append(t);
301        }
302        return ts.toList();
303    }
304
305    @Override
306    public void visitTopLevel(JCCompilationUnit tree) {
307//        Assert.checkNonNull(tree.modle, tree.sourcefile.toString());
308
309        JavaFileObject prev = log.useSource(tree.sourcefile);
310        boolean addEnv = false;
311        boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
312                                                             JavaFileObject.Kind.SOURCE);
313        if (TreeInfo.isModuleInfo(tree)) {
314            JCPackageDecl pd = tree.getPackage();
315            if (pd != null) {
316                log.error(pd.pos(), Errors.NoPkgInModuleInfoJava);
317            }
318            tree.packge = syms.rootPackage;
319            Env<AttrContext> topEnv = topLevelEnv(tree);
320            classEnter(tree.defs, topEnv);
321            tree.modle.usesProvidesCompleter = modules.getUsesProvidesCompleter();
322        } else {
323            JCPackageDecl pd = tree.getPackage();
324            if (pd != null) {
325                tree.packge = pd.packge = syms.enterPackage(tree.modle, TreeInfo.fullName(pd.pid));
326                if (   pd.annotations.nonEmpty()
327                    || pkginfoOpt == PkgInfo.ALWAYS
328                    || tree.docComments != null) {
329                    if (isPkgInfo) {
330                        addEnv = true;
331                    } else if (pd.annotations.nonEmpty()) {
332                        log.error(pd.annotations.head.pos(),
333                                  "pkg.annotations.sb.in.package-info.java");
334                    }
335                }
336            } else {
337                tree.packge = tree.modle.unnamedPackage;
338            }
339
340            Map<Name, PackageSymbol> visiblePackages = tree.modle.visiblePackages;
341            Optional<ModuleSymbol> dependencyWithPackage =
342                syms.listPackageModules(tree.packge.fullname)
343                    .stream()
344                    .filter(m -> m != tree.modle)
345                    .filter(cand -> visiblePackages.get(tree.packge.fullname) == syms.getPackage(cand, tree.packge.fullname))
346                    .findAny();
347
348            if (dependencyWithPackage.isPresent()) {
349                log.error(pd, Errors.PackageInOtherModule(dependencyWithPackage.get()));
350            }
351
352            tree.packge.complete(); // Find all classes in package.
353
354            Env<AttrContext> topEnv = topLevelEnv(tree);
355            Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
356
357            // Save environment of package-info.java file.
358            if (isPkgInfo) {
359                Env<AttrContext> env0 = typeEnvs.get(tree.packge);
360                if (env0 != null) {
361                    JCCompilationUnit tree0 = env0.toplevel;
362                    if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
363                        log.warning(pd != null ? pd.pid.pos() : null,
364                                    "pkg-info.already.seen",
365                                    tree.packge);
366                    }
367                }
368                typeEnvs.put(tree.packge, packageEnv);
369
370                for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
371                    q.flags_field |= EXISTS;
372
373                Name name = names.package_info;
374                ClassSymbol c = syms.enterClass(tree.modle, name, tree.packge);
375                c.flatname = names.fromString(tree.packge + "." + name);
376                c.sourcefile = tree.sourcefile;
377            c.completer = Completer.NULL_COMPLETER;
378                c.members_field = WriteableScope.create(c);
379                tree.packge.package_info = c;
380            }
381            classEnter(tree.defs, topEnv);
382            if (addEnv) {
383                todo.append(packageEnv);
384            }
385        }
386        log.useSource(prev);
387        result = null;
388    }
389
390    @Override
391    public void visitClassDef(JCClassDecl tree) {
392        Symbol owner = env.info.scope.owner;
393        WriteableScope enclScope = enterScope(env);
394        ClassSymbol c;
395        if (owner.kind == PCK) {
396            // We are seeing a toplevel class.
397            PackageSymbol packge = (PackageSymbol)owner;
398            for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
399                q.flags_field |= EXISTS;
400            c = syms.enterClass(env.toplevel.modle, tree.name, packge);
401            packge.members().enterIfAbsent(c);
402            if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
403                log.error(tree.pos(),
404                          "class.public.should.be.in.file", tree.name);
405            }
406        } else {
407            if (!tree.name.isEmpty() &&
408                !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
409                result = null;
410                return;
411            }
412            if (owner.kind == TYP) {
413                // We are seeing a member class.
414                c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
415                if (c.owner != owner) {
416                    //anonymous class loaded from a classfile may be recreated from source (see below)
417                    //if this class is a member of such an anonymous class, fix the owner:
418                    Assert.check(owner.owner.kind != TYP, () -> owner.toString());
419                    Assert.check(c.owner.kind == TYP, () -> c.owner.toString());
420                    ClassSymbol cowner = (ClassSymbol) c.owner;
421                    if (cowner.members_field != null) {
422                        cowner.members_field.remove(c);
423                    }
424                    c.owner = owner;
425                }
426                if ((owner.flags_field & INTERFACE) != 0) {
427                    tree.mods.flags |= PUBLIC | STATIC;
428                }
429            } else {
430                // We are seeing a local class.
431                c = syms.defineClass(tree.name, owner);
432                c.flatname = chk.localClassName(c);
433                if (!c.name.isEmpty())
434                    chk.checkTransparentClass(tree.pos(), c, env.info.scope);
435            }
436        }
437        tree.sym = c;
438
439        // Enter class into `compiled' table and enclosing scope.
440        if (chk.getCompiled(c) != null) {
441            duplicateClass(tree.pos(), c);
442            result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
443            tree.sym = (ClassSymbol)result.tsym;
444            return;
445        }
446        chk.putCompiled(c);
447        enclScope.enter(c);
448
449        // Set up an environment for class block and store in `typeEnvs'
450        // table, to be retrieved later in memberEnter and attribution.
451        Env<AttrContext> localEnv = classEnv(tree, env);
452        typeEnvs.put(c, localEnv);
453
454        // Fill out class fields.
455        c.completer = Completer.NULL_COMPLETER; // do not allow the initial completer linger on.
456        c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
457        c.sourcefile = env.toplevel.sourcefile;
458        c.members_field = WriteableScope.create(c);
459        c.clearAnnotationMetadata();
460
461        ClassType ct = (ClassType)c.type;
462        if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
463            // We are seeing a local or inner class.
464            // Set outer_field of this class to closest enclosing class
465            // which contains this class in a non-static context
466            // (its "enclosing instance class"), provided such a class exists.
467            Symbol owner1 = owner;
468            while (owner1.kind.matches(KindSelector.VAL_MTH) &&
469                   (owner1.flags_field & STATIC) == 0) {
470                owner1 = owner1.owner;
471            }
472            if (owner1.kind == TYP) {
473                ct.setEnclosingType(owner1.type);
474            }
475        }
476
477        // Enter type parameters.
478        ct.typarams_field = classEnter(tree.typarams, localEnv);
479        ct.allparams_field = null;
480
481        // install further completer for this type.
482        c.completer = typeEnter;
483
484        // Add non-local class to uncompleted, to make sure it will be
485        // completed later.
486        if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
487//      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG
488
489        // Recursively enter all member classes.
490        classEnter(tree.defs, localEnv);
491
492//        Assert.checkNonNull(c.modle, c.sourcefile.toString());
493
494        result = c.type;
495    }
496    //where
497        /** Does class have the same name as the file it appears in?
498         */
499        private static boolean classNameMatchesFileName(ClassSymbol c,
500                                                        Env<AttrContext> env) {
501            return env.toplevel.sourcefile.isNameCompatible(c.name.toString(),
502                                                            JavaFileObject.Kind.SOURCE);
503        }
504
505    /** Complain about a duplicate class. */
506    protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
507        log.error(pos, "duplicate.class", c.fullname);
508    }
509
510    /** Class enter visitor method for type parameters.
511     *  Enter a symbol for type parameter in local scope, after checking that it
512     *  is unique.
513     */
514    @Override
515    public void visitTypeParameter(JCTypeParameter tree) {
516        TypeVar a = (tree.type != null)
517            ? (TypeVar)tree.type
518            : new TypeVar(tree.name, env.info.scope.owner, syms.botType);
519        tree.type = a;
520        if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
521            env.info.scope.enter(a.tsym);
522        }
523        result = a;
524    }
525
526    @Override
527    public void visitModuleDef(JCModuleDecl tree) {
528        Env<AttrContext> moduleEnv = moduleEnv(tree, env);
529        typeEnvs.put(tree.sym, moduleEnv);
530        if (modules.isInModuleGraph(tree.sym)) {
531            todo.append(moduleEnv);
532        }
533    }
534
535    /** Default class enter visitor method: do nothing.
536     */
537    @Override
538    public void visitTree(JCTree tree) {
539        result = null;
540    }
541
542    /** Main method: enter all classes in a list of toplevel trees.
543     *  @param trees      The list of trees to be processed.
544     */
545    public void main(List<JCCompilationUnit> trees) {
546        complete(trees, null);
547    }
548
549    /** Main method: enter classes from the list of toplevel trees, possibly
550     *  skipping TypeEnter for all but 'c' by placing them on the uncompleted
551     *  list.
552     *  @param trees      The list of trees to be processed.
553     *  @param c          The class symbol to be processed or null to process all.
554     */
555    public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
556        annotate.blockAnnotations();
557        ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
558        if (typeEnter.completionEnabled) uncompleted = new ListBuffer<>();
559
560        try {
561            // enter all classes, and construct uncompleted list
562            classEnter(trees, null);
563
564            // complete all uncompleted classes in memberEnter
565            if (typeEnter.completionEnabled) {
566                while (uncompleted.nonEmpty()) {
567                    ClassSymbol clazz = uncompleted.next();
568                    if (c == null || c == clazz || prevUncompleted == null)
569                        clazz.complete();
570                    else
571                        // defer
572                        prevUncompleted.append(clazz);
573                }
574
575                if (!modules.modulesInitialized()) {
576                    for (JCCompilationUnit cut : trees) {
577                        if (cut.getModuleDecl() != null) {
578                            unfinishedModules.append(cut);
579                        } else {
580                            typeEnter.ensureImportsChecked(List.of(cut));
581                        }
582                    }
583                } else {
584                    typeEnter.ensureImportsChecked(unfinishedModules.toList());
585                    unfinishedModules.clear();
586                    typeEnter.ensureImportsChecked(trees);
587                }
588            }
589        } finally {
590            uncompleted = prevUncompleted;
591            annotate.unblockAnnotations();
592        }
593    }
594
595    public void newRound() {
596        typeEnvs.clear();
597    }
598}
599