Fri, 12 Nov 2010 12:32:43 +0000
6598108: com.sun.source.util.Trees.isAccessible incorrect
Summary: JavacTrees' version of isAccessible should take into account enclosing class accessibility
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2003, 2008, 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 */
26 package com.sun.tools.javac.comp;
28 import java.util.*;
29 import java.util.Set;
30 import javax.tools.JavaFileObject;
32 import com.sun.tools.javac.code.*;
33 import com.sun.tools.javac.jvm.*;
34 import com.sun.tools.javac.tree.*;
35 import com.sun.tools.javac.util.*;
36 import com.sun.tools.javac.util.List;
38 import com.sun.tools.javac.code.Type.*;
39 import com.sun.tools.javac.code.Symbol.*;
40 import com.sun.tools.javac.tree.JCTree.*;
42 import static com.sun.tools.javac.code.Flags.*;
43 import static com.sun.tools.javac.code.Kinds.*;
44 import static com.sun.tools.javac.code.TypeTags.*;
45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
47 /** This is the second phase of Enter, in which classes are completed
48 * by entering their members into the class scope using
49 * MemberEnter.complete(). See Enter for an overview.
50 *
51 * <p><b>This is NOT part of any supported API.
52 * If you write code that depends on this, you do so at your own risk.
53 * This code and its internal interfaces are subject to change or
54 * deletion without notice.</b>
55 */
56 public class MemberEnter extends JCTree.Visitor implements Completer {
57 protected static final Context.Key<MemberEnter> memberEnterKey =
58 new Context.Key<MemberEnter>();
60 /** A switch to determine whether we check for package/class conflicts
61 */
62 final static boolean checkClash = true;
64 private final Names names;
65 private final Enter enter;
66 private final Log log;
67 private final Check chk;
68 private final Attr attr;
69 private final Symtab syms;
70 private final Scope.ScopeCounter scopeCounter;
71 private final TreeMaker make;
72 private final ClassReader reader;
73 private final Todo todo;
74 private final Annotate annotate;
75 private final Types types;
76 private final JCDiagnostic.Factory diags;
77 private final Target target;
79 private final boolean skipAnnotations;
81 public static MemberEnter instance(Context context) {
82 MemberEnter instance = context.get(memberEnterKey);
83 if (instance == null)
84 instance = new MemberEnter(context);
85 return instance;
86 }
88 protected MemberEnter(Context context) {
89 context.put(memberEnterKey, this);
90 names = Names.instance(context);
91 enter = Enter.instance(context);
92 log = Log.instance(context);
93 chk = Check.instance(context);
94 attr = Attr.instance(context);
95 syms = Symtab.instance(context);
96 scopeCounter = Scope.ScopeCounter.instance(context);
97 make = TreeMaker.instance(context);
98 reader = ClassReader.instance(context);
99 todo = Todo.instance(context);
100 annotate = Annotate.instance(context);
101 types = Types.instance(context);
102 diags = JCDiagnostic.Factory.instance(context);
103 target = Target.instance(context);
104 Options options = Options.instance(context);
105 skipAnnotations = options.isSet("skipAnnotations");
106 }
108 /** A queue for classes whose members still need to be entered into the
109 * symbol table.
110 */
111 ListBuffer<Env<AttrContext>> halfcompleted = new ListBuffer<Env<AttrContext>>();
113 /** Set to true only when the first of a set of classes is
114 * processed from the halfcompleted queue.
115 */
116 boolean isFirst = true;
118 /** A flag to disable completion from time to time during member
119 * enter, as we only need to look up types. This avoids
120 * unnecessarily deep recursion.
121 */
122 boolean completionEnabled = true;
124 /* ---------- Processing import clauses ----------------
125 */
127 /** Import all classes of a class or package on demand.
128 * @param pos Position to be used for error reporting.
129 * @param tsym The class or package the members of which are imported.
130 * @param toScope The (import) scope in which imported classes
131 * are entered.
132 */
133 private void importAll(int pos,
134 final TypeSymbol tsym,
135 Env<AttrContext> env) {
136 // Check that packages imported from exist (JLS ???).
137 if (tsym.kind == PCK && tsym.members().elems == null && !tsym.exists()) {
138 // If we can't find java.lang, exit immediately.
139 if (((PackageSymbol)tsym).fullname.equals(names.java_lang)) {
140 JCDiagnostic msg = diags.fragment("fatal.err.no.java.lang");
141 throw new FatalError(msg);
142 } else {
143 log.error(pos, "doesnt.exist", tsym);
144 }
145 }
146 final Scope fromScope = tsym.members();
147 final Scope toScope = env.toplevel.starImportScope;
148 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
149 if (e.sym.kind == TYP && !toScope.includes(e.sym))
150 toScope.enter(e.sym, fromScope);
151 }
152 }
154 /** Import all static members of a class or package on demand.
155 * @param pos Position to be used for error reporting.
156 * @param tsym The class or package the members of which are imported.
157 * @param toScope The (import) scope in which imported classes
158 * are entered.
159 */
160 private void importStaticAll(int pos,
161 final TypeSymbol tsym,
162 Env<AttrContext> env) {
163 final JavaFileObject sourcefile = env.toplevel.sourcefile;
164 final Scope toScope = env.toplevel.starImportScope;
165 final PackageSymbol packge = env.toplevel.packge;
166 final TypeSymbol origin = tsym;
168 // enter imported types immediately
169 new Object() {
170 Set<Symbol> processed = new HashSet<Symbol>();
171 void importFrom(TypeSymbol tsym) {
172 if (tsym == null || !processed.add(tsym))
173 return;
175 // also import inherited names
176 importFrom(types.supertype(tsym.type).tsym);
177 for (Type t : types.interfaces(tsym.type))
178 importFrom(t.tsym);
180 final Scope fromScope = tsym.members();
181 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
182 Symbol sym = e.sym;
183 if (sym.kind == TYP &&
184 (sym.flags() & STATIC) != 0 &&
185 staticImportAccessible(sym, packge) &&
186 sym.isMemberOf(origin, types) &&
187 !toScope.includes(sym))
188 toScope.enter(sym, fromScope, origin.members());
189 }
190 }
191 }.importFrom(tsym);
193 // enter non-types before annotations that might use them
194 annotate.earlier(new Annotate.Annotator() {
195 Set<Symbol> processed = new HashSet<Symbol>();
197 public String toString() {
198 return "import static " + tsym + ".*" + " in " + sourcefile;
199 }
200 void importFrom(TypeSymbol tsym) {
201 if (tsym == null || !processed.add(tsym))
202 return;
204 // also import inherited names
205 importFrom(types.supertype(tsym.type).tsym);
206 for (Type t : types.interfaces(tsym.type))
207 importFrom(t.tsym);
209 final Scope fromScope = tsym.members();
210 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
211 Symbol sym = e.sym;
212 if (sym.isStatic() && sym.kind != TYP &&
213 staticImportAccessible(sym, packge) &&
214 !toScope.includes(sym) &&
215 sym.isMemberOf(origin, types)) {
216 toScope.enter(sym, fromScope, origin.members());
217 }
218 }
219 }
220 public void enterAnnotation() {
221 importFrom(tsym);
222 }
223 });
224 }
226 // is the sym accessible everywhere in packge?
227 boolean staticImportAccessible(Symbol sym, PackageSymbol packge) {
228 int flags = (int)(sym.flags() & AccessFlags);
229 switch (flags) {
230 default:
231 case PUBLIC:
232 return true;
233 case PRIVATE:
234 return false;
235 case 0:
236 case PROTECTED:
237 return sym.packge() == packge;
238 }
239 }
241 /** Import statics types of a given name. Non-types are handled in Attr.
242 * @param pos Position to be used for error reporting.
243 * @param tsym The class from which the name is imported.
244 * @param name The (simple) name being imported.
245 * @param env The environment containing the named import
246 * scope to add to.
247 */
248 private void importNamedStatic(final DiagnosticPosition pos,
249 final TypeSymbol tsym,
250 final Name name,
251 final Env<AttrContext> env) {
252 if (tsym.kind != TYP) {
253 log.error(pos, "static.imp.only.classes.and.interfaces");
254 return;
255 }
257 final Scope toScope = env.toplevel.namedImportScope;
258 final PackageSymbol packge = env.toplevel.packge;
259 final TypeSymbol origin = tsym;
261 // enter imported types immediately
262 new Object() {
263 Set<Symbol> processed = new HashSet<Symbol>();
264 void importFrom(TypeSymbol tsym) {
265 if (tsym == null || !processed.add(tsym))
266 return;
268 // also import inherited names
269 importFrom(types.supertype(tsym.type).tsym);
270 for (Type t : types.interfaces(tsym.type))
271 importFrom(t.tsym);
273 for (Scope.Entry e = tsym.members().lookup(name);
274 e.scope != null;
275 e = e.next()) {
276 Symbol sym = e.sym;
277 if (sym.isStatic() &&
278 sym.kind == TYP &&
279 staticImportAccessible(sym, packge) &&
280 sym.isMemberOf(origin, types) &&
281 chk.checkUniqueStaticImport(pos, sym, toScope))
282 toScope.enter(sym, sym.owner.members(), origin.members());
283 }
284 }
285 }.importFrom(tsym);
287 // enter non-types before annotations that might use them
288 annotate.earlier(new Annotate.Annotator() {
289 Set<Symbol> processed = new HashSet<Symbol>();
290 boolean found = false;
292 public String toString() {
293 return "import static " + tsym + "." + name;
294 }
295 void importFrom(TypeSymbol tsym) {
296 if (tsym == null || !processed.add(tsym))
297 return;
299 // also import inherited names
300 importFrom(types.supertype(tsym.type).tsym);
301 for (Type t : types.interfaces(tsym.type))
302 importFrom(t.tsym);
304 for (Scope.Entry e = tsym.members().lookup(name);
305 e.scope != null;
306 e = e.next()) {
307 Symbol sym = e.sym;
308 if (sym.isStatic() &&
309 staticImportAccessible(sym, packge) &&
310 sym.isMemberOf(origin, types)) {
311 found = true;
312 if (sym.kind == MTH ||
313 sym.kind != TYP && chk.checkUniqueStaticImport(pos, sym, toScope))
314 toScope.enter(sym, sym.owner.members(), origin.members());
315 }
316 }
317 }
318 public void enterAnnotation() {
319 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
320 try {
321 importFrom(tsym);
322 if (!found) {
323 log.error(pos, "cant.resolve.location",
324 KindName.STATIC,
325 name, List.<Type>nil(), List.<Type>nil(),
326 Kinds.typeKindName(tsym.type),
327 tsym.type);
328 }
329 } finally {
330 log.useSource(prev);
331 }
332 }
333 });
334 }
335 /** Import given class.
336 * @param pos Position to be used for error reporting.
337 * @param tsym The class to be imported.
338 * @param env The environment containing the named import
339 * scope to add to.
340 */
341 private void importNamed(DiagnosticPosition pos, Symbol tsym, Env<AttrContext> env) {
342 if (tsym.kind == TYP &&
343 chk.checkUniqueImport(pos, tsym, env.toplevel.namedImportScope))
344 env.toplevel.namedImportScope.enter(tsym, tsym.owner.members());
345 }
347 /** Construct method type from method signature.
348 * @param typarams The method's type parameters.
349 * @param params The method's value parameters.
350 * @param res The method's result type,
351 * null if it is a constructor.
352 * @param thrown The method's thrown exceptions.
353 * @param env The method's (local) environment.
354 */
355 Type signature(List<JCTypeParameter> typarams,
356 List<JCVariableDecl> params,
357 JCTree res,
358 List<JCExpression> thrown,
359 Env<AttrContext> env) {
361 // Enter and attribute type parameters.
362 List<Type> tvars = enter.classEnter(typarams, env);
363 attr.attribTypeVariables(typarams, env);
365 // Enter and attribute value parameters.
366 ListBuffer<Type> argbuf = new ListBuffer<Type>();
367 for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) {
368 memberEnter(l.head, env);
369 argbuf.append(l.head.vartype.type);
370 }
372 // Attribute result type, if one is given.
373 Type restype = res == null ? syms.voidType : attr.attribType(res, env);
375 // Attribute thrown exceptions.
376 ListBuffer<Type> thrownbuf = new ListBuffer<Type>();
377 for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) {
378 Type exc = attr.attribType(l.head, env);
379 if (exc.tag != TYPEVAR)
380 exc = chk.checkClassType(l.head.pos(), exc);
381 thrownbuf.append(exc);
382 }
383 Type mtype = new MethodType(argbuf.toList(),
384 restype,
385 thrownbuf.toList(),
386 syms.methodClass);
387 return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype);
388 }
390 /* ********************************************************************
391 * Visitor methods for member enter
392 *********************************************************************/
394 /** Visitor argument: the current environment
395 */
396 protected Env<AttrContext> env;
398 /** Enter field and method definitions and process import
399 * clauses, catching any completion failure exceptions.
400 */
401 protected void memberEnter(JCTree tree, Env<AttrContext> env) {
402 Env<AttrContext> prevEnv = this.env;
403 try {
404 this.env = env;
405 tree.accept(this);
406 } catch (CompletionFailure ex) {
407 chk.completionError(tree.pos(), ex);
408 } finally {
409 this.env = prevEnv;
410 }
411 }
413 /** Enter members from a list of trees.
414 */
415 void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) {
416 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
417 memberEnter(l.head, env);
418 }
420 /** Enter members for a class.
421 */
422 void finishClass(JCClassDecl tree, Env<AttrContext> env) {
423 if ((tree.mods.flags & Flags.ENUM) != 0 &&
424 (types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) {
425 addEnumMembers(tree, env);
426 }
427 memberEnter(tree.defs, env);
428 }
430 /** Add the implicit members for an enum type
431 * to the symbol table.
432 */
433 private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) {
434 JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass));
436 // public static T[] values() { return ???; }
437 JCMethodDecl values = make.
438 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC),
439 names.values,
440 valuesType,
441 List.<JCTypeParameter>nil(),
442 List.<JCVariableDecl>nil(),
443 List.<JCExpression>nil(), // thrown
444 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
445 null);
446 memberEnter(values, env);
448 // public static T valueOf(String name) { return ???; }
449 JCMethodDecl valueOf = make.
450 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC),
451 names.valueOf,
452 make.Type(tree.sym.type),
453 List.<JCTypeParameter>nil(),
454 List.of(make.VarDef(make.Modifiers(Flags.PARAMETER),
455 names.fromString("name"),
456 make.Type(syms.stringType), null)),
457 List.<JCExpression>nil(), // thrown
458 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
459 null);
460 memberEnter(valueOf, env);
462 // the remaining members are for bootstrapping only
463 if (!target.compilerBootstrap(tree.sym)) return;
465 // public final int ordinal() { return ???; }
466 JCMethodDecl ordinal = make.at(tree.pos).
467 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.FINAL),
468 names.ordinal,
469 make.Type(syms.intType),
470 List.<JCTypeParameter>nil(),
471 List.<JCVariableDecl>nil(),
472 List.<JCExpression>nil(),
473 null,
474 null);
475 memberEnter(ordinal, env);
477 // public final String name() { return ???; }
478 JCMethodDecl name = make.
479 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.FINAL),
480 names._name,
481 make.Type(syms.stringType),
482 List.<JCTypeParameter>nil(),
483 List.<JCVariableDecl>nil(),
484 List.<JCExpression>nil(),
485 null,
486 null);
487 memberEnter(name, env);
489 // public int compareTo(E other) { return ???; }
490 MethodSymbol compareTo = new
491 MethodSymbol(Flags.PUBLIC,
492 names.compareTo,
493 new MethodType(List.of(tree.sym.type),
494 syms.intType,
495 List.<Type>nil(),
496 syms.methodClass),
497 tree.sym);
498 memberEnter(make.MethodDef(compareTo, null), env);
499 }
501 public void visitTopLevel(JCCompilationUnit tree) {
502 if (tree.starImportScope.elems != null) {
503 // we must have already processed this toplevel
504 return;
505 }
507 // check that no class exists with same fully qualified name as
508 // toplevel package
509 if (checkClash && tree.pid != null) {
510 Symbol p = tree.packge;
511 while (p.owner != syms.rootPackage) {
512 p.owner.complete(); // enter all class members of p
513 if (syms.classes.get(p.getQualifiedName()) != null) {
514 log.error(tree.pos,
515 "pkg.clashes.with.class.of.same.name",
516 p);
517 }
518 p = p.owner;
519 }
520 }
522 // process package annotations
523 annotateLater(tree.packageAnnotations, env, tree.packge);
525 // Import-on-demand java.lang.
526 importAll(tree.pos, reader.enterPackage(names.java_lang), env);
528 // Process all import clauses.
529 memberEnter(tree.defs, env);
530 }
532 // process the non-static imports and the static imports of types.
533 public void visitImport(JCImport tree) {
534 JCTree imp = tree.qualid;
535 Name name = TreeInfo.name(imp);
536 TypeSymbol p;
538 // Create a local environment pointing to this tree to disable
539 // effects of other imports in Resolve.findGlobalType
540 Env<AttrContext> localEnv = env.dup(tree);
542 // Attribute qualifying package or class.
543 JCFieldAccess s = (JCFieldAccess) imp;
544 p = attr.
545 attribTree(s.selected,
546 localEnv,
547 tree.staticImport ? TYP : (TYP | PCK),
548 Type.noType).tsym;
549 if (name == names.asterisk) {
550 // Import on demand.
551 chk.checkCanonical(s.selected);
552 if (tree.staticImport)
553 importStaticAll(tree.pos, p, env);
554 else
555 importAll(tree.pos, p, env);
556 } else {
557 // Named type import.
558 if (tree.staticImport) {
559 importNamedStatic(tree.pos(), p, name, localEnv);
560 chk.checkCanonical(s.selected);
561 } else {
562 TypeSymbol c = attribImportType(imp, localEnv).tsym;
563 chk.checkCanonical(imp);
564 importNamed(tree.pos(), c, env);
565 }
566 }
567 }
569 public void visitMethodDef(JCMethodDecl tree) {
570 Scope enclScope = enter.enterScope(env);
571 MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner);
572 m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree);
573 tree.sym = m;
574 Env<AttrContext> localEnv = methodEnv(tree, env);
576 // Compute the method type
577 m.type = signature(tree.typarams, tree.params,
578 tree.restype, tree.thrown,
579 localEnv);
581 // Set m.params
582 ListBuffer<VarSymbol> params = new ListBuffer<VarSymbol>();
583 JCVariableDecl lastParam = null;
584 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
585 JCVariableDecl param = lastParam = l.head;
586 assert param.sym != null;
587 params.append(param.sym);
588 }
589 m.params = params.toList();
591 // mark the method varargs, if necessary
592 if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0)
593 m.flags_field |= Flags.VARARGS;
595 localEnv.info.scope.leave();
596 if (chk.checkUnique(tree.pos(), m, enclScope)) {
597 enclScope.enter(m);
598 }
599 annotateLater(tree.mods.annotations, localEnv, m);
600 if (tree.defaultValue != null)
601 annotateDefaultValueLater(tree.defaultValue, localEnv, m);
602 }
604 /** Create a fresh environment for method bodies.
605 * @param tree The method definition.
606 * @param env The environment current outside of the method definition.
607 */
608 Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) {
609 Env<AttrContext> localEnv =
610 env.dup(tree, env.info.dup(env.info.scope.dupUnshared()));
611 localEnv.enclMethod = tree;
612 localEnv.info.scope.owner = tree.sym;
613 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
614 return localEnv;
615 }
617 public void visitVarDef(JCVariableDecl tree) {
618 Env<AttrContext> localEnv = env;
619 if ((tree.mods.flags & STATIC) != 0 ||
620 (env.info.scope.owner.flags() & INTERFACE) != 0) {
621 localEnv = env.dup(tree, env.info.dup());
622 localEnv.info.staticLevel++;
623 }
624 attr.attribType(tree.vartype, localEnv);
625 Scope enclScope = enter.enterScope(env);
626 VarSymbol v =
627 new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner);
628 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree);
629 tree.sym = v;
630 if (tree.init != null) {
631 v.flags_field |= HASINIT;
632 if ((v.flags_field & FINAL) != 0 && tree.init.getTag() != JCTree.NEWCLASS) {
633 Env<AttrContext> initEnv = getInitEnv(tree, env);
634 initEnv.info.enclVar = v;
635 v.setLazyConstValue(initEnv(tree, initEnv), log, attr, tree.init);
636 }
637 }
638 if (chk.checkUnique(tree.pos(), v, enclScope)) {
639 chk.checkTransparentVar(tree.pos(), v, enclScope);
640 enclScope.enter(v);
641 }
642 annotateLater(tree.mods.annotations, localEnv, v);
643 v.pos = tree.pos;
644 }
646 /** Create a fresh environment for a variable's initializer.
647 * If the variable is a field, the owner of the environment's scope
648 * is be the variable itself, otherwise the owner is the method
649 * enclosing the variable definition.
650 *
651 * @param tree The variable definition.
652 * @param env The environment current outside of the variable definition.
653 */
654 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) {
655 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup()));
656 if (tree.sym.owner.kind == TYP) {
657 localEnv.info.scope = new Scope.DelegatedScope(env.info.scope);
658 localEnv.info.scope.owner = tree.sym;
659 }
660 if ((tree.mods.flags & STATIC) != 0 ||
661 (env.enclClass.sym.flags() & INTERFACE) != 0)
662 localEnv.info.staticLevel++;
663 return localEnv;
664 }
666 /** Default member enter visitor method: do nothing
667 */
668 public void visitTree(JCTree tree) {
669 }
671 public void visitErroneous(JCErroneous tree) {
672 if (tree.errs != null)
673 memberEnter(tree.errs, env);
674 }
676 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) {
677 Env<AttrContext> mEnv = methodEnv(tree, env);
678 mEnv.info.lint = mEnv.info.lint.augment(tree.sym.attributes_field, tree.sym.flags());
679 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
680 mEnv.info.scope.enterIfAbsent(l.head.type.tsym);
681 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail)
682 mEnv.info.scope.enterIfAbsent(l.head.sym);
683 return mEnv;
684 }
686 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) {
687 Env<AttrContext> iEnv = initEnv(tree, env);
688 return iEnv;
689 }
691 /* ********************************************************************
692 * Type completion
693 *********************************************************************/
695 Type attribImportType(JCTree tree, Env<AttrContext> env) {
696 assert completionEnabled;
697 try {
698 // To prevent deep recursion, suppress completion of some
699 // types.
700 completionEnabled = false;
701 return attr.attribType(tree, env);
702 } finally {
703 completionEnabled = true;
704 }
705 }
707 /* ********************************************************************
708 * Annotation processing
709 *********************************************************************/
711 /** Queue annotations for later processing. */
712 void annotateLater(final List<JCAnnotation> annotations,
713 final Env<AttrContext> localEnv,
714 final Symbol s) {
715 if (annotations.isEmpty()) return;
716 if (s.kind != PCK) s.attributes_field = null; // mark it incomplete for now
717 annotate.later(new Annotate.Annotator() {
718 public String toString() {
719 return "annotate " + annotations + " onto " + s + " in " + s.owner;
720 }
721 public void enterAnnotation() {
722 assert s.kind == PCK || s.attributes_field == null;
723 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
724 try {
725 if (s.attributes_field != null &&
726 s.attributes_field.nonEmpty() &&
727 annotations.nonEmpty())
728 log.error(annotations.head.pos,
729 "already.annotated",
730 kindName(s), s);
731 enterAnnotations(annotations, localEnv, s);
732 } finally {
733 log.useSource(prev);
734 }
735 }
736 });
737 }
739 /**
740 * Check if a list of annotations contains a reference to
741 * java.lang.Deprecated.
742 **/
743 private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) {
744 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
745 JCAnnotation a = al.head;
746 if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty())
747 return true;
748 }
749 return false;
750 }
753 /** Enter a set of annotations. */
754 private void enterAnnotations(List<JCAnnotation> annotations,
755 Env<AttrContext> env,
756 Symbol s) {
757 ListBuffer<Attribute.Compound> buf =
758 new ListBuffer<Attribute.Compound>();
759 Set<TypeSymbol> annotated = new HashSet<TypeSymbol>();
760 if (!skipAnnotations)
761 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
762 JCAnnotation a = al.head;
763 Attribute.Compound c = annotate.enterAnnotation(a,
764 syms.annotationType,
765 env);
766 if (c == null) continue;
767 buf.append(c);
768 // Note: @Deprecated has no effect on local variables and parameters
769 if (!c.type.isErroneous()
770 && s.owner.kind != MTH
771 && types.isSameType(c.type, syms.deprecatedType))
772 s.flags_field |= Flags.DEPRECATED;
773 // Internally to java.dyn, a @PolymorphicSignature annotation
774 // acts like a classfile attribute.
775 if (!c.type.isErroneous() &&
776 types.isSameType(c.type, syms.polymorphicSignatureType)) {
777 if (!target.hasMethodHandles()) {
778 // Somebody is compiling JDK7 source code to a JDK6 target.
779 // Make it a strict warning, since it is unlikely but important.
780 log.strictWarning(env.tree.pos(),
781 "wrong.target.for.polymorphic.signature.definition",
782 target.name);
783 }
784 // Pull the flag through for better diagnostics, even on a bad target.
785 s.flags_field |= Flags.POLYMORPHIC_SIGNATURE;
786 }
787 if (!annotated.add(a.type.tsym))
788 log.error(a.pos, "duplicate.annotation");
789 }
790 s.attributes_field = buf.toList();
791 }
793 /** Queue processing of an attribute default value. */
794 void annotateDefaultValueLater(final JCExpression defaultValue,
795 final Env<AttrContext> localEnv,
796 final MethodSymbol m) {
797 annotate.later(new Annotate.Annotator() {
798 public String toString() {
799 return "annotate " + m.owner + "." +
800 m + " default " + defaultValue;
801 }
802 public void enterAnnotation() {
803 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
804 try {
805 enterDefaultValue(defaultValue, localEnv, m);
806 } finally {
807 log.useSource(prev);
808 }
809 }
810 });
811 }
813 /** Enter a default value for an attribute method. */
814 private void enterDefaultValue(final JCExpression defaultValue,
815 final Env<AttrContext> localEnv,
816 final MethodSymbol m) {
817 m.defaultValue = annotate.enterAttributeValue(m.type.getReturnType(),
818 defaultValue,
819 localEnv);
820 }
822 /* ********************************************************************
823 * Source completer
824 *********************************************************************/
826 /** Complete entering a class.
827 * @param sym The symbol of the class to be completed.
828 */
829 public void complete(Symbol sym) throws CompletionFailure {
830 // Suppress some (recursive) MemberEnter invocations
831 if (!completionEnabled) {
832 // Re-install same completer for next time around and return.
833 assert (sym.flags() & Flags.COMPOUND) == 0;
834 sym.completer = this;
835 return;
836 }
838 ClassSymbol c = (ClassSymbol)sym;
839 ClassType ct = (ClassType)c.type;
840 Env<AttrContext> env = enter.typeEnvs.get(c);
841 JCClassDecl tree = (JCClassDecl)env.tree;
842 boolean wasFirst = isFirst;
843 isFirst = false;
845 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
846 try {
847 // Save class environment for later member enter (2) processing.
848 halfcompleted.append(env);
850 // Mark class as not yet attributed.
851 c.flags_field |= UNATTRIBUTED;
853 // If this is a toplevel-class, make sure any preceding import
854 // clauses have been seen.
855 if (c.owner.kind == PCK) {
856 memberEnter(env.toplevel, env.enclosing(JCTree.TOPLEVEL));
857 todo.append(env);
858 }
860 if (c.owner.kind == TYP)
861 c.owner.complete();
863 // create an environment for evaluating the base clauses
864 Env<AttrContext> baseEnv = baseEnv(tree, env);
866 // Determine supertype.
867 Type supertype =
868 (tree.extending != null)
869 ? attr.attribBase(tree.extending, baseEnv, true, false, true)
870 : ((tree.mods.flags & Flags.ENUM) != 0 && !target.compilerBootstrap(c))
871 ? attr.attribBase(enumBase(tree.pos, c), baseEnv,
872 true, false, false)
873 : (c.fullname == names.java_lang_Object)
874 ? Type.noType
875 : syms.objectType;
876 ct.supertype_field = supertype;
878 // Determine interfaces.
879 ListBuffer<Type> interfaces = new ListBuffer<Type>();
880 Set<Type> interfaceSet = new HashSet<Type>();
881 List<JCExpression> interfaceTrees = tree.implementing;
882 if ((tree.mods.flags & Flags.ENUM) != 0 && target.compilerBootstrap(c)) {
883 // add interface Comparable<T>
884 interfaceTrees =
885 interfaceTrees.prepend(make.Type(new ClassType(syms.comparableType.getEnclosingType(),
886 List.of(c.type),
887 syms.comparableType.tsym)));
888 // add interface Serializable
889 interfaceTrees =
890 interfaceTrees.prepend(make.Type(syms.serializableType));
891 }
892 for (JCExpression iface : interfaceTrees) {
893 Type i = attr.attribBase(iface, baseEnv, false, true, true);
894 if (i.tag == CLASS) {
895 interfaces.append(i);
896 chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet);
897 }
898 }
899 if ((c.flags_field & ANNOTATION) != 0)
900 ct.interfaces_field = List.of(syms.annotationType);
901 else
902 ct.interfaces_field = interfaces.toList();
904 if (c.fullname == names.java_lang_Object) {
905 if (tree.extending != null) {
906 chk.checkNonCyclic(tree.extending.pos(),
907 supertype);
908 ct.supertype_field = Type.noType;
909 }
910 else if (tree.implementing.nonEmpty()) {
911 chk.checkNonCyclic(tree.implementing.head.pos(),
912 ct.interfaces_field.head);
913 ct.interfaces_field = List.nil();
914 }
915 }
917 // Annotations.
918 // In general, we cannot fully process annotations yet, but we
919 // can attribute the annotation types and then check to see if the
920 // @Deprecated annotation is present.
921 attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
922 if (hasDeprecatedAnnotation(tree.mods.annotations))
923 c.flags_field |= DEPRECATED;
924 annotateLater(tree.mods.annotations, baseEnv, c);
925 // class type parameters use baseEnv but everything uses env
926 for (JCTypeParameter tp : tree.typarams)
927 tp.accept(new TypeAnnotate(baseEnv));
928 tree.accept(new TypeAnnotate(env));
930 chk.checkNonCyclicDecl(tree);
932 attr.attribTypeVariables(tree.typarams, baseEnv);
934 // Add default constructor if needed.
935 if ((c.flags() & INTERFACE) == 0 &&
936 !TreeInfo.hasConstructors(tree.defs)) {
937 List<Type> argtypes = List.nil();
938 List<Type> typarams = List.nil();
939 List<Type> thrown = List.nil();
940 long ctorFlags = 0;
941 boolean based = false;
942 if (c.name.isEmpty()) {
943 JCNewClass nc = (JCNewClass)env.next.tree;
944 if (nc.constructor != null) {
945 Type superConstrType = types.memberType(c.type,
946 nc.constructor);
947 argtypes = superConstrType.getParameterTypes();
948 typarams = superConstrType.getTypeArguments();
949 ctorFlags = nc.constructor.flags() & VARARGS;
950 if (nc.encl != null) {
951 argtypes = argtypes.prepend(nc.encl.type);
952 based = true;
953 }
954 thrown = superConstrType.getThrownTypes();
955 }
956 }
957 JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
958 typarams, argtypes, thrown,
959 ctorFlags, based);
960 tree.defs = tree.defs.prepend(constrDef);
961 }
963 // If this is a class, enter symbols for this and super into
964 // current scope.
965 if ((c.flags_field & INTERFACE) == 0) {
966 VarSymbol thisSym =
967 new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
968 thisSym.pos = Position.FIRSTPOS;
969 env.info.scope.enter(thisSym);
970 if (ct.supertype_field.tag == CLASS) {
971 VarSymbol superSym =
972 new VarSymbol(FINAL | HASINIT, names._super,
973 ct.supertype_field, c);
974 superSym.pos = Position.FIRSTPOS;
975 env.info.scope.enter(superSym);
976 }
977 }
979 // check that no package exists with same fully qualified name,
980 // but admit classes in the unnamed package which have the same
981 // name as a top-level package.
982 if (checkClash &&
983 c.owner.kind == PCK && c.owner != syms.unnamedPackage &&
984 reader.packageExists(c.fullname))
985 {
986 log.error(tree.pos, "clash.with.pkg.of.same.name", c);
987 }
989 } catch (CompletionFailure ex) {
990 chk.completionError(tree.pos(), ex);
991 } finally {
992 log.useSource(prev);
993 }
995 // Enter all member fields and methods of a set of half completed
996 // classes in a second phase.
997 if (wasFirst) {
998 try {
999 while (halfcompleted.nonEmpty()) {
1000 finish(halfcompleted.next());
1001 }
1002 } finally {
1003 isFirst = true;
1004 }
1006 // commit pending annotations
1007 annotate.flush();
1008 }
1009 }
1011 // A sub-phase that "compiles" annotations in annotated types.
1012 private class TypeAnnotate extends TreeScanner {
1013 private Env<AttrContext> env;
1014 public TypeAnnotate(Env<AttrContext> env) { this.env = env; }
1016 private void enterTypeAnnotations(List<JCTypeAnnotation> annotations) {
1017 Set<TypeSymbol> annotated = new HashSet<TypeSymbol>();
1018 if (!skipAnnotations)
1019 for (List<JCTypeAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
1020 JCTypeAnnotation a = al.head;
1021 Attribute.Compound c = annotate.enterAnnotation(a,
1022 syms.annotationType,
1023 env);
1024 if (c == null) continue;
1025 Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, a.annotation_position);
1026 a.attribute_field = tc;
1027 // Note: @Deprecated has no effect on local variables and parameters
1028 if (!annotated.add(a.type.tsym))
1029 log.error(a.pos, "duplicate.annotation");
1030 }
1031 }
1033 // each class (including enclosed inner classes) should be visited
1034 // separately through MemberEnter.complete(Symbol)
1035 // this flag is used to prevent from visiting inner classes.
1036 private boolean isEnclosingClass = false;
1037 @Override
1038 public void visitClassDef(final JCClassDecl tree) {
1039 if (isEnclosingClass)
1040 return;
1041 isEnclosingClass = true;
1042 scan(tree.mods);
1043 // type parameter need to be visited with a separate env
1044 // scan(tree.typarams);
1045 scan(tree.extending);
1046 scan(tree.implementing);
1047 scan(tree.defs);
1048 }
1050 private void annotate(final JCTree tree, final List<JCTypeAnnotation> annotations) {
1051 annotate.later(new Annotate.Annotator() {
1052 public String toString() {
1053 return "annotate " + annotations + " onto " + tree;
1054 }
1055 public void enterAnnotation() {
1056 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
1057 try {
1058 enterTypeAnnotations(annotations);
1059 } finally {
1060 log.useSource(prev);
1061 }
1062 }
1063 });
1064 }
1066 @Override
1067 public void visitAnnotatedType(final JCAnnotatedType tree) {
1068 annotate(tree, tree.annotations);
1069 super.visitAnnotatedType(tree);
1070 }
1071 @Override
1072 public void visitTypeParameter(final JCTypeParameter tree) {
1073 annotate(tree, tree.annotations);
1074 super.visitTypeParameter(tree);
1075 }
1076 @Override
1077 public void visitNewArray(final JCNewArray tree) {
1078 annotate(tree, tree.annotations);
1079 for (List<JCTypeAnnotation> dimAnnos : tree.dimAnnotations)
1080 annotate(tree, dimAnnos);
1081 super.visitNewArray(tree);
1082 }
1083 @Override
1084 public void visitMethodDef(JCMethodDecl tree) {
1085 annotate(tree, tree.receiverAnnotations);
1086 super.visitMethodDef(tree);
1087 }
1088 }
1091 private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) {
1092 Scope baseScope = new Scope.ClassScope(tree.sym, scopeCounter);
1093 //import already entered local classes into base scope
1094 for (Scope.Entry e = env.outer.info.scope.elems ; e != null ; e = e.sibling) {
1095 if (e.sym.isLocal()) {
1096 baseScope.enter(e.sym);
1097 }
1098 }
1099 //import current type-parameters into base scope
1100 if (tree.typarams != null)
1101 for (List<JCTypeParameter> typarams = tree.typarams;
1102 typarams.nonEmpty();
1103 typarams = typarams.tail)
1104 baseScope.enter(typarams.head.type.tsym);
1105 Env<AttrContext> outer = env.outer; // the base clause can't see members of this class
1106 Env<AttrContext> localEnv = outer.dup(tree, outer.info.dup(baseScope));
1107 localEnv.baseClause = true;
1108 localEnv.outer = outer;
1109 localEnv.info.isSelfCall = false;
1110 return localEnv;
1111 }
1113 /** Enter member fields and methods of a class
1114 * @param env the environment current for the class block.
1115 */
1116 private void finish(Env<AttrContext> env) {
1117 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
1118 try {
1119 JCClassDecl tree = (JCClassDecl)env.tree;
1120 finishClass(tree, env);
1121 } finally {
1122 log.useSource(prev);
1123 }
1124 }
1126 /** Generate a base clause for an enum type.
1127 * @param pos The position for trees and diagnostics, if any
1128 * @param c The class symbol of the enum
1129 */
1130 private JCExpression enumBase(int pos, ClassSymbol c) {
1131 JCExpression result = make.at(pos).
1132 TypeApply(make.QualIdent(syms.enumSym),
1133 List.<JCExpression>of(make.Type(c.type)));
1134 return result;
1135 }
1137 /* ***************************************************************************
1138 * tree building
1139 ****************************************************************************/
1141 /** Generate default constructor for given class. For classes different
1142 * from java.lang.Object, this is:
1143 *
1144 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
1145 * super(x_0, ..., x_n)
1146 * }
1147 *
1148 * or, if based == true:
1149 *
1150 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
1151 * x_0.super(x_1, ..., x_n)
1152 * }
1153 *
1154 * @param make The tree factory.
1155 * @param c The class owning the default constructor.
1156 * @param argtypes The parameter types of the constructor.
1157 * @param thrown The thrown exceptions of the constructor.
1158 * @param based Is first parameter a this$n?
1159 */
1160 JCTree DefaultConstructor(TreeMaker make,
1161 ClassSymbol c,
1162 List<Type> typarams,
1163 List<Type> argtypes,
1164 List<Type> thrown,
1165 long flags,
1166 boolean based) {
1167 List<JCVariableDecl> params = make.Params(argtypes, syms.noSymbol);
1168 List<JCStatement> stats = List.nil();
1169 if (c.type != syms.objectType)
1170 stats = stats.prepend(SuperCall(make, typarams, params, based));
1171 if ((c.flags() & ENUM) != 0 &&
1172 (types.supertype(c.type).tsym == syms.enumSym ||
1173 target.compilerBootstrap(c))) {
1174 // constructors of true enums are private
1175 flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR;
1176 } else
1177 flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;
1178 if (c.name.isEmpty()) flags |= ANONCONSTR;
1179 JCTree result = make.MethodDef(
1180 make.Modifiers(flags),
1181 names.init,
1182 null,
1183 make.TypeParams(typarams),
1184 params,
1185 make.Types(thrown),
1186 make.Block(0, stats),
1187 null);
1188 return result;
1189 }
1191 /** Generate call to superclass constructor. This is:
1192 *
1193 * super(id_0, ..., id_n)
1194 *
1195 * or, if based == true
1196 *
1197 * id_0.super(id_1,...,id_n)
1198 *
1199 * where id_0, ..., id_n are the names of the given parameters.
1200 *
1201 * @param make The tree factory
1202 * @param params The parameters that need to be passed to super
1203 * @param typarams The type parameters that need to be passed to super
1204 * @param based Is first parameter a this$n?
1205 */
1206 JCExpressionStatement SuperCall(TreeMaker make,
1207 List<Type> typarams,
1208 List<JCVariableDecl> params,
1209 boolean based) {
1210 JCExpression meth;
1211 if (based) {
1212 meth = make.Select(make.Ident(params.head), names._super);
1213 params = params.tail;
1214 } else {
1215 meth = make.Ident(names._super);
1216 }
1217 List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null;
1218 return make.Exec(make.Apply(typeargs, meth, make.Idents(params)));
1219 }
1220 }