1 /* 2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.comp; 27 28 import java.util.*; 29 import java.util.Set; 30 import javax.tools.JavaFileObject; 31 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; 37 38 import com.sun.tools.javac.code.Type.*; 39 import com.sun.tools.javac.code.Symbol.*; 40 import com.sun.tools.javac.tree.JCTree.*; 41 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; 46 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>(); 59 60 /** A switch to determine whether we check for package/class conflicts 61 */ 62 final static boolean checkClash = true; 63 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 TreeMaker make; 71 private final ClassReader reader; 72 private final Todo todo; 73 private final Annotate annotate; 74 private final Types types; 75 private final JCDiagnostic.Factory diags; 76 private final Target target; 77 private final DeferredLintHandler deferredLintHandler; 78 79 private final boolean skipAnnotations; 80 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 } 87 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 make = TreeMaker.instance(context); 97 reader = ClassReader.instance(context); 98 todo = Todo.instance(context); 99 annotate = Annotate.instance(context); 100 types = Types.instance(context); 101 diags = JCDiagnostic.Factory.instance(context); 102 target = Target.instance(context); 103 deferredLintHandler = DeferredLintHandler.instance(context); 104 Options options = Options.instance(context); 105 skipAnnotations = options.isSet("skipAnnotations"); 106 } 107 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>>(); 112 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; 117 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; 123 124 /* ---------- Processing import clauses ---------------- 125 */ 126 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 env.toplevel.starImportScope.importAll(tsym.members()); 147 } 148 149 /** Import all static members of a class or package on demand. 150 * @param pos Position to be used for error reporting. 151 * @param tsym The class or package the members of which are imported. 152 * @param toScope The (import) scope in which imported classes 153 * are entered. 154 */ 155 private void importStaticAll(int pos, 156 final TypeSymbol tsym, 157 Env<AttrContext> env) { 158 final JavaFileObject sourcefile = env.toplevel.sourcefile; 159 final Scope toScope = env.toplevel.starImportScope; 160 final PackageSymbol packge = env.toplevel.packge; 161 final TypeSymbol origin = tsym; 162 163 // enter imported types immediately 164 new Object() { 165 Set<Symbol> processed = new HashSet<Symbol>(); 166 void importFrom(TypeSymbol tsym) { 167 if (tsym == null || !processed.add(tsym)) 168 return; 169 170 // also import inherited names 171 importFrom(types.supertype(tsym.type).tsym); 172 for (Type t : types.interfaces(tsym.type)) 173 importFrom(t.tsym); 174 175 final Scope fromScope = tsym.members(); 176 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { 177 Symbol sym = e.sym; 178 if (sym.kind == TYP && 179 (sym.flags() & STATIC) != 0 && 180 staticImportAccessible(sym, packge) && 181 sym.isMemberOf(origin, types) && 182 !toScope.includes(sym)) 183 toScope.enter(sym, fromScope, origin.members()); 184 } 185 } 186 }.importFrom(tsym); 187 188 // enter non-types before annotations that might use them 189 annotate.earlier(new Annotate.Annotator() { 190 Set<Symbol> processed = new HashSet<Symbol>(); 191 192 public String toString() { 193 return "import static " + tsym + ".*" + " in " + sourcefile; 194 } 195 void importFrom(TypeSymbol tsym) { 196 if (tsym == null || !processed.add(tsym)) 197 return; 198 199 // also import inherited names 200 importFrom(types.supertype(tsym.type).tsym); 201 for (Type t : types.interfaces(tsym.type)) 202 importFrom(t.tsym); 203 204 final Scope fromScope = tsym.members(); 205 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { 206 Symbol sym = e.sym; 207 if (sym.isStatic() && sym.kind != TYP && 208 staticImportAccessible(sym, packge) && 209 !toScope.includes(sym) && 210 sym.isMemberOf(origin, types)) { 211 toScope.enter(sym, fromScope, origin.members()); 212 } 213 } 214 } 215 public void enterAnnotation() { 216 importFrom(tsym); 217 } 218 }); 219 } 220 221 // is the sym accessible everywhere in packge? 222 boolean staticImportAccessible(Symbol sym, PackageSymbol packge) { 223 int flags = (int)(sym.flags() & AccessFlags); 224 switch (flags) { 225 default: 226 case PUBLIC: 227 return true; 228 case PRIVATE: 229 return false; 230 case 0: 231 case PROTECTED: 232 return sym.packge() == packge; 233 } 234 } 235 236 /** Import statics types of a given name. Non-types are handled in Attr. 237 * @param pos Position to be used for error reporting. 238 * @param tsym The class from which the name is imported. 239 * @param name The (simple) name being imported. 240 * @param env The environment containing the named import 241 * scope to add to. 242 */ 243 private void importNamedStatic(final DiagnosticPosition pos, 244 final TypeSymbol tsym, 245 final Name name, 246 final Env<AttrContext> env) { 247 if (tsym.kind != TYP) { 248 log.error(pos, "static.imp.only.classes.and.interfaces"); 249 return; 250 } 251 252 final Scope toScope = env.toplevel.namedImportScope; 253 final PackageSymbol packge = env.toplevel.packge; 254 final TypeSymbol origin = tsym; 255 256 // enter imported types immediately 257 new Object() { 258 Set<Symbol> processed = new HashSet<Symbol>(); 259 void importFrom(TypeSymbol tsym) { 260 if (tsym == null || !processed.add(tsym)) 261 return; 262 263 // also import inherited names 264 importFrom(types.supertype(tsym.type).tsym); 265 for (Type t : types.interfaces(tsym.type)) 266 importFrom(t.tsym); 267 268 for (Scope.Entry e = tsym.members().lookup(name); 269 e.scope != null; 270 e = e.next()) { 271 Symbol sym = e.sym; 272 if (sym.isStatic() && 273 sym.kind == TYP && 274 staticImportAccessible(sym, packge) && 275 sym.isMemberOf(origin, types) && 276 chk.checkUniqueStaticImport(pos, sym, toScope)) 277 toScope.enter(sym, sym.owner.members(), origin.members()); 278 } 279 } 280 }.importFrom(tsym); 281 282 // enter non-types before annotations that might use them 283 annotate.earlier(new Annotate.Annotator() { 284 Set<Symbol> processed = new HashSet<Symbol>(); 285 boolean found = false; 286 287 public String toString() { 288 return "import static " + tsym + "." + name; 289 } 290 void importFrom(TypeSymbol tsym) { 291 if (tsym == null || !processed.add(tsym)) 292 return; 293 294 // also import inherited names 295 importFrom(types.supertype(tsym.type).tsym); 296 for (Type t : types.interfaces(tsym.type)) 297 importFrom(t.tsym); 298 299 for (Scope.Entry e = tsym.members().lookup(name); 300 e.scope != null; 301 e = e.next()) { 302 Symbol sym = e.sym; 303 if (sym.isStatic() && 304 staticImportAccessible(sym, packge) && 305 sym.isMemberOf(origin, types)) { 306 found = true; 307 if (sym.kind == MTH || 308 sym.kind != TYP && chk.checkUniqueStaticImport(pos, sym, toScope)) 309 toScope.enter(sym, sym.owner.members(), origin.members()); 310 } 311 } 312 } 313 public void enterAnnotation() { 314 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 315 try { 316 importFrom(tsym); 317 if (!found) { 318 log.error(pos, "cant.resolve.location", 319 KindName.STATIC, 320 name, List.<Type>nil(), List.<Type>nil(), 321 Kinds.typeKindName(tsym.type), 322 tsym.type); 323 } 324 } finally { 325 log.useSource(prev); 326 } 327 } 328 }); 329 } 330 /** Import given class. 331 * @param pos Position to be used for error reporting. 332 * @param tsym The class to be imported. 333 * @param env The environment containing the named import 334 * scope to add to. 335 */ 336 private void importNamed(DiagnosticPosition pos, Symbol tsym, Env<AttrContext> env) { 337 if (tsym.kind == TYP && 338 chk.checkUniqueImport(pos, tsym, env.toplevel.namedImportScope)) 339 env.toplevel.namedImportScope.enter(tsym, tsym.owner.members()); 340 } 341 342 /** Construct method type from method signature. 343 * @param typarams The method's type parameters. 344 * @param params The method's value parameters. 345 * @param res The method's result type, 346 * null if it is a constructor. 347 * @param thrown The method's thrown exceptions. 348 * @param env The method's (local) environment. 349 */ 350 Type signature(List<JCTypeParameter> typarams, 351 List<JCVariableDecl> params, 352 JCTree res, 353 List<JCExpression> thrown, 354 Env<AttrContext> env) { 355 356 // Enter and attribute type parameters. 357 List<Type> tvars = enter.classEnter(typarams, env); 358 attr.attribTypeVariables(typarams, env); 359 360 // Enter and attribute value parameters. 361 ListBuffer<Type> argbuf = new ListBuffer<Type>(); 362 for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) { 363 memberEnter(l.head, env); 364 argbuf.append(l.head.vartype.type); 365 } 366 367 // Attribute result type, if one is given. 368 Type restype = res == null ? syms.voidType : attr.attribType(res, env); 369 370 // Attribute thrown exceptions. 371 ListBuffer<Type> thrownbuf = new ListBuffer<Type>(); 372 for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) { 373 Type exc = attr.attribType(l.head, env); 374 if (exc.tag != TYPEVAR) 375 exc = chk.checkClassType(l.head.pos(), exc); 376 thrownbuf.append(exc); 377 } 378 Type mtype = new MethodType(argbuf.toList(), 379 restype, 380 thrownbuf.toList(), 381 syms.methodClass); 382 return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); 383 } 384 385 /* ******************************************************************** 386 * Visitor methods for member enter 387 *********************************************************************/ 388 389 /** Visitor argument: the current environment 390 */ 391 protected Env<AttrContext> env; 392 393 /** Enter field and method definitions and process import 394 * clauses, catching any completion failure exceptions. 395 */ 396 protected void memberEnter(JCTree tree, Env<AttrContext> env) { 397 Env<AttrContext> prevEnv = this.env; 398 try { 399 this.env = env; 400 tree.accept(this); 401 } catch (CompletionFailure ex) { 402 chk.completionError(tree.pos(), ex); 403 } finally { 404 this.env = prevEnv; 405 } 406 } 407 408 /** Enter members from a list of trees. 409 */ 410 void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) { 411 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 412 memberEnter(l.head, env); 413 } 414 415 /** Enter members for a class. 416 */ 417 void finishClass(JCClassDecl tree, Env<AttrContext> env) { 418 if ((tree.mods.flags & Flags.ENUM) != 0 && 419 (types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) { 420 addEnumMembers(tree, env); 421 } 422 memberEnter(tree.defs, env); 423 } 424 425 /** Add the implicit members for an enum type 426 * to the symbol table. 427 */ 428 private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) { 429 JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass)); 430 431 // public static T[] values() { return ???; } 432 JCMethodDecl values = make. 433 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), 434 names.values, 435 valuesType, 436 List.<JCTypeParameter>nil(), 437 List.<JCVariableDecl>nil(), 438 List.<JCExpression>nil(), // thrown 439 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), 440 null); 441 memberEnter(values, env); 442 443 // public static T valueOf(String name) { return ???; } 444 JCMethodDecl valueOf = make. 445 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), 446 names.valueOf, 447 make.Type(tree.sym.type), 448 List.<JCTypeParameter>nil(), 449 List.of(make.VarDef(make.Modifiers(Flags.PARAMETER), 450 names.fromString("name"), 451 make.Type(syms.stringType), null)), 452 List.<JCExpression>nil(), // thrown 453 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), 454 null); 455 memberEnter(valueOf, env); 456 457 // the remaining members are for bootstrapping only 458 if (!target.compilerBootstrap(tree.sym)) return; 459 460 // public final int ordinal() { return ???; } 461 JCMethodDecl ordinal = make.at(tree.pos). 462 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.FINAL), 463 names.ordinal, 464 make.Type(syms.intType), 465 List.<JCTypeParameter>nil(), 466 List.<JCVariableDecl>nil(), 467 List.<JCExpression>nil(), 468 null, 469 null); 470 memberEnter(ordinal, env); 471 472 // public final String name() { return ???; } 473 JCMethodDecl name = make. 474 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.FINAL), 475 names._name, 476 make.Type(syms.stringType), 477 List.<JCTypeParameter>nil(), 478 List.<JCVariableDecl>nil(), 479 List.<JCExpression>nil(), 480 null, 481 null); 482 memberEnter(name, env); 483 484 // public int compareTo(E other) { return ???; } 485 MethodSymbol compareTo = new 486 MethodSymbol(Flags.PUBLIC, 487 names.compareTo, 488 new MethodType(List.of(tree.sym.type), 489 syms.intType, 490 List.<Type>nil(), 491 syms.methodClass), 492 tree.sym); 493 memberEnter(make.MethodDef(compareTo, null), env); 494 } 495 496 public void visitTopLevel(JCCompilationUnit tree) { 497 if (tree.starImportScope.elems != null) { 498 // we must have already processed this toplevel 499 return; 500 } 501 502 // check that no class exists with same fully qualified name as 503 // toplevel package 504 if (checkClash && tree.pid != null) { 505 Symbol p = tree.packge; 506 while (p.owner != syms.rootPackage) { 507 p.owner.complete(); // enter all class members of p 508 if (syms.classes.get(p.getQualifiedName()) != null) { 509 log.error(tree.pos, 510 "pkg.clashes.with.class.of.same.name", 511 p); 512 } 513 p = p.owner; 514 } 515 } 516 517 // process package annotations 518 annotateLater(tree.packageAnnotations, env, tree.packge); 519 520 // Import-on-demand java.lang. 521 importAll(tree.pos, reader.enterPackage(names.java_lang), env); 522 523 // Process all import clauses. 524 memberEnter(tree.defs, env); 525 } 526 527 // process the non-static imports and the static imports of types. 528 public void visitImport(JCImport tree) { 529 JCTree imp = tree.qualid; 530 Name name = TreeInfo.name(imp); 531 TypeSymbol p; 532 533 // Create a local environment pointing to this tree to disable 534 // effects of other imports in Resolve.findGlobalType 535 Env<AttrContext> localEnv = env.dup(tree); 536 537 // Attribute qualifying package or class. 538 JCFieldAccess s = (JCFieldAccess) imp; 539 p = attr. 540 attribTree(s.selected, 541 localEnv, 542 tree.staticImport ? TYP : (TYP | PCK), 543 Type.noType).tsym; 544 if (name == names.asterisk) { 545 // Import on demand. 546 chk.checkCanonical(s.selected); 547 if (tree.staticImport) 548 importStaticAll(tree.pos, p, env); 549 else 550 importAll(tree.pos, p, env); 551 } else { 552 // Named type import. 553 if (tree.staticImport) { 554 importNamedStatic(tree.pos(), p, name, localEnv); 555 chk.checkCanonical(s.selected); 556 } else { 557 TypeSymbol c = attribImportType(imp, localEnv).tsym; 558 chk.checkCanonical(imp); 559 importNamed(tree.pos(), c, env); 560 } 561 } 562 } 563 564 public void visitMethodDef(JCMethodDecl tree) { 565 Scope enclScope = enter.enterScope(env); 566 MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner); 567 m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree); 568 tree.sym = m; 569 Env<AttrContext> localEnv = methodEnv(tree, env); 570 571 DeferredLintHandler prevLintHandler = 572 chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos())); 573 try { 574 // Compute the method type 575 m.type = signature(tree.typarams, tree.params, 576 tree.restype, tree.thrown, 577 localEnv); 578 } finally { 579 chk.setDeferredLintHandler(prevLintHandler); 580 } 581 582 // Set m.params 583 ListBuffer<VarSymbol> params = new ListBuffer<VarSymbol>(); 584 JCVariableDecl lastParam = null; 585 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 586 JCVariableDecl param = lastParam = l.head; 587 params.append(Assert.checkNonNull(param.sym)); 588 } 589 m.params = params.toList(); 590 591 // mark the method varargs, if necessary 592 if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0) 593 m.flags_field |= Flags.VARARGS; 594 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 } 603 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 } 616 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 DeferredLintHandler prevLintHandler = 625 chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos())); 626 try { 627 attr.attribType(tree.vartype, localEnv); 628 } finally { 629 chk.setDeferredLintHandler(prevLintHandler); 630 } 631 632 if ((tree.mods.flags & VARARGS) != 0) { 633 //if we are entering a varargs parameter, we need to replace its type 634 //(a plain array type) with the more precise VarargsType --- we need 635 //to do it this way because varargs is represented in the tree as a modifier 636 //on the parameter declaration, and not as a distinct type of array node. 637 ArrayType atype = (ArrayType)tree.vartype.type; 638 tree.vartype.type = atype.makeVarargs(); 639 } 640 Scope enclScope = enter.enterScope(env); 641 VarSymbol v = 642 new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner); 643 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); 644 tree.sym = v; 645 if (tree.init != null) { 646 v.flags_field |= HASINIT; 647 if ((v.flags_field & FINAL) != 0 && tree.init.getTag() != JCTree.NEWCLASS) { 648 Env<AttrContext> initEnv = getInitEnv(tree, env); 649 initEnv.info.enclVar = v; 650 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init); 651 } 652 } 653 if (chk.checkUnique(tree.pos(), v, enclScope)) { 654 chk.checkTransparentVar(tree.pos(), v, enclScope); 655 enclScope.enter(v); 656 } 657 annotateLater(tree.mods.annotations, localEnv, v); 658 v.pos = tree.pos; 659 } 660 661 /** Create a fresh environment for a variable's initializer. 662 * If the variable is a field, the owner of the environment's scope 663 * is be the variable itself, otherwise the owner is the method 664 * enclosing the variable definition. 665 * 666 * @param tree The variable definition. 667 * @param env The environment current outside of the variable definition. 668 */ 669 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) { 670 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup())); 671 if (tree.sym.owner.kind == TYP) { 672 localEnv.info.scope = new Scope.DelegatedScope(env.info.scope); 673 localEnv.info.scope.owner = tree.sym; 674 } 675 if ((tree.mods.flags & STATIC) != 0 || 676 (env.enclClass.sym.flags() & INTERFACE) != 0) 677 localEnv.info.staticLevel++; 678 return localEnv; 679 } 680 681 /** Default member enter visitor method: do nothing 682 */ 683 public void visitTree(JCTree tree) { 684 } 685 686 public void visitErroneous(JCErroneous tree) { 687 if (tree.errs != null) 688 memberEnter(tree.errs, env); 689 } 690 691 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { 692 Env<AttrContext> mEnv = methodEnv(tree, env); 693 mEnv.info.lint = mEnv.info.lint.augment(tree.sym.attributes_field, tree.sym.flags()); 694 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 695 mEnv.info.scope.enterIfAbsent(l.head.type.tsym); 696 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) 697 mEnv.info.scope.enterIfAbsent(l.head.sym); 698 return mEnv; 699 } 700 701 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) { 702 Env<AttrContext> iEnv = initEnv(tree, env); 703 return iEnv; 704 } 705 706 /* ******************************************************************** 707 * Type completion 708 *********************************************************************/ 709 710 Type attribImportType(JCTree tree, Env<AttrContext> env) { 711 Assert.check(completionEnabled); 712 try { 713 // To prevent deep recursion, suppress completion of some 714 // types. 715 completionEnabled = false; 716 return attr.attribType(tree, env); 717 } finally { 718 completionEnabled = true; 719 } 720 } 721 722 /* ******************************************************************** 723 * Annotation processing 724 *********************************************************************/ 725 726 /** Queue annotations for later processing. */ 727 void annotateLater(final List<JCAnnotation> annotations, 728 final Env<AttrContext> localEnv, 729 final Symbol s) { 730 if (annotations.isEmpty()) return; 731 if (s.kind != PCK) s.attributes_field = null; // mark it incomplete for now 732 annotate.later(new Annotate.Annotator() { 733 public String toString() { 734 return "annotate " + annotations + " onto " + s + " in " + s.owner; 735 } 736 public void enterAnnotation() { 737 Assert.check(s.kind == PCK || s.attributes_field == null); 738 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 739 try { 740 if (s.attributes_field != null && 741 s.attributes_field.nonEmpty() && 742 annotations.nonEmpty()) 743 log.error(annotations.head.pos, 744 "already.annotated", 745 kindName(s), s); 746 enterAnnotations(annotations, localEnv, s); 747 } finally { 748 log.useSource(prev); 749 } 750 } 751 }); 752 } 753 754 /** 755 * Check if a list of annotations contains a reference to 756 * java.lang.Deprecated. 757 **/ 758 private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) { 759 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { 760 JCAnnotation a = al.head; 761 if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty()) 762 return true; 763 } 764 return false; 765 } 766 767 768 /** Enter a set of annotations. */ 769 private void enterAnnotations(List<JCAnnotation> annotations, 770 Env<AttrContext> env, 771 Symbol s) { 772 ListBuffer<Attribute.Compound> buf = 773 new ListBuffer<Attribute.Compound>(); 774 Set<TypeSymbol> annotated = new HashSet<TypeSymbol>(); 775 if (!skipAnnotations) 776 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { 777 JCAnnotation a = al.head; 778 Attribute.Compound c = annotate.enterAnnotation(a, 779 syms.annotationType, 780 env); 781 if (c == null) continue; 782 buf.append(c); 783 // Note: @Deprecated has no effect on local variables and parameters 784 if (!c.type.isErroneous() 785 && s.owner.kind != MTH 786 && types.isSameType(c.type, syms.deprecatedType)) 787 s.flags_field |= Flags.DEPRECATED; 788 // Internally to java.lang.invoke, a @PolymorphicSignature annotation 789 // acts like a classfile attribute. 790 if (!c.type.isErroneous() && 791 types.isSameType(c.type, syms.polymorphicSignatureType)) { 792 if (!target.hasMethodHandles()) { 793 // Somebody is compiling JDK7 source code to a JDK6 target. 794 // Make it an error, since it is unlikely but important. 795 log.error(env.tree.pos(), 796 "wrong.target.for.polymorphic.signature.definition", 797 target.name); 798 } 799 // Pull the flag through for better diagnostics, even on a bad target. 800 s.flags_field |= Flags.POLYMORPHIC_SIGNATURE; 801 } 802 if (!annotated.add(a.type.tsym)) 803 log.error(a.pos, "duplicate.annotation"); 804 } 805 s.attributes_field = buf.toList(); 806 } 807 808 /** Queue processing of an attribute default value. */ 809 void annotateDefaultValueLater(final JCExpression defaultValue, 810 final Env<AttrContext> localEnv, 811 final MethodSymbol m) { 812 annotate.later(new Annotate.Annotator() { 813 public String toString() { 814 return "annotate " + m.owner + "." + 815 m + " default " + defaultValue; 816 } 817 public void enterAnnotation() { 818 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 819 try { 820 enterDefaultValue(defaultValue, localEnv, m); 821 } finally { 822 log.useSource(prev); 823 } 824 } 825 }); 826 } 827 828 /** Enter a default value for an attribute method. */ 829 private void enterDefaultValue(final JCExpression defaultValue, 830 final Env<AttrContext> localEnv, 831 final MethodSymbol m) { 832 m.defaultValue = annotate.enterAttributeValue(m.type.getReturnType(), 833 defaultValue, 834 localEnv); 835 } 836 837 /* ******************************************************************** 838 * Source completer 839 *********************************************************************/ 840 841 /** Complete entering a class. 842 * @param sym The symbol of the class to be completed. 843 */ 844 public void complete(Symbol sym) throws CompletionFailure { 845 // Suppress some (recursive) MemberEnter invocations 846 if (!completionEnabled) { 847 // Re-install same completer for next time around and return. 848 Assert.check((sym.flags() & Flags.COMPOUND) == 0); 849 sym.completer = this; 850 return; 851 } 852 853 ClassSymbol c = (ClassSymbol)sym; 854 ClassType ct = (ClassType)c.type; 855 Env<AttrContext> env = enter.typeEnvs.get(c); 856 JCClassDecl tree = (JCClassDecl)env.tree; 857 boolean wasFirst = isFirst; 858 isFirst = false; 859 860 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 861 try { 862 // Save class environment for later member enter (2) processing. 863 halfcompleted.append(env); 864 865 // Mark class as not yet attributed. 866 c.flags_field |= UNATTRIBUTED; 867 868 // If this is a toplevel-class, make sure any preceding import 869 // clauses have been seen. 870 if (c.owner.kind == PCK) { 871 memberEnter(env.toplevel, env.enclosing(JCTree.TOPLEVEL)); 872 todo.append(env); 873 } 874 875 if (c.owner.kind == TYP) 876 c.owner.complete(); 877 878 // create an environment for evaluating the base clauses 879 Env<AttrContext> baseEnv = baseEnv(tree, env); 880 881 // Determine supertype. 882 Type supertype = 883 (tree.extending != null) 884 ? attr.attribBase(tree.extending, baseEnv, true, false, true) 885 : ((tree.mods.flags & Flags.ENUM) != 0 && !target.compilerBootstrap(c)) 886 ? attr.attribBase(enumBase(tree.pos, c), baseEnv, 887 true, false, false) 888 : (c.fullname == names.java_lang_Object) 889 ? Type.noType 890 : syms.objectType; 891 ct.supertype_field = modelMissingTypes(supertype, tree.extending, false); 892 893 // Determine interfaces. 894 ListBuffer<Type> interfaces = new ListBuffer<Type>(); 895 ListBuffer<Type> all_interfaces = null; // lazy init 896 Set<Type> interfaceSet = new HashSet<Type>(); 897 List<JCExpression> interfaceTrees = tree.implementing; 898 if ((tree.mods.flags & Flags.ENUM) != 0 && target.compilerBootstrap(c)) { 899 // add interface Comparable<T> 900 interfaceTrees = 901 interfaceTrees.prepend(make.Type(new ClassType(syms.comparableType.getEnclosingType(), 902 List.of(c.type), 903 syms.comparableType.tsym))); 904 // add interface Serializable 905 interfaceTrees = 906 interfaceTrees.prepend(make.Type(syms.serializableType)); 907 } 908 for (JCExpression iface : interfaceTrees) { 909 Type i = attr.attribBase(iface, baseEnv, false, true, true); 910 if (i.tag == CLASS) { 911 interfaces.append(i); 912 if (all_interfaces != null) all_interfaces.append(i); 913 chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet); 914 } else { 915 if (all_interfaces == null) 916 all_interfaces = new ListBuffer<Type>().appendList(interfaces); 917 all_interfaces.append(modelMissingTypes(i, iface, true)); 918 } 919 } 920 if ((c.flags_field & ANNOTATION) != 0) { 921 ct.interfaces_field = List.of(syms.annotationType); 922 ct.all_interfaces_field = ct.interfaces_field; 923 } else { 924 ct.interfaces_field = interfaces.toList(); 925 ct.all_interfaces_field = (all_interfaces == null) 926 ? ct.interfaces_field : all_interfaces.toList(); 927 } 928 929 if (c.fullname == names.java_lang_Object) { 930 if (tree.extending != null) { 931 chk.checkNonCyclic(tree.extending.pos(), 932 supertype); 933 ct.supertype_field = Type.noType; 934 } 935 else if (tree.implementing.nonEmpty()) { 936 chk.checkNonCyclic(tree.implementing.head.pos(), 937 ct.interfaces_field.head); 938 ct.interfaces_field = List.nil(); 939 } 940 } 941 942 // Annotations. 943 // In general, we cannot fully process annotations yet, but we 944 // can attribute the annotation types and then check to see if the 945 // @Deprecated annotation is present. 946 attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); 947 if (hasDeprecatedAnnotation(tree.mods.annotations)) 948 c.flags_field |= DEPRECATED; 949 annotateLater(tree.mods.annotations, baseEnv, c); 950 951 chk.checkNonCyclicDecl(tree); 952 953 attr.attribTypeVariables(tree.typarams, baseEnv); 954 955 // Add default constructor if needed. 956 if ((c.flags() & INTERFACE) == 0 && 957 !TreeInfo.hasConstructors(tree.defs)) { 958 List<Type> argtypes = List.nil(); 959 List<Type> typarams = List.nil(); 960 List<Type> thrown = List.nil(); 961 long ctorFlags = 0; 962 boolean based = false; 963 if (c.name.isEmpty()) { 964 JCNewClass nc = (JCNewClass)env.next.tree; 965 if (nc.constructor != null) { 966 Type superConstrType = types.memberType(c.type, 967 nc.constructor); 968 argtypes = superConstrType.getParameterTypes(); 969 typarams = superConstrType.getTypeArguments(); 970 ctorFlags = nc.constructor.flags() & VARARGS; 971 if (nc.encl != null) { 972 argtypes = argtypes.prepend(nc.encl.type); 973 based = true; 974 } 975 thrown = superConstrType.getThrownTypes(); 976 } 977 } 978 JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, 979 typarams, argtypes, thrown, 980 ctorFlags, based); 981 tree.defs = tree.defs.prepend(constrDef); 982 } 983 984 // If this is a class, enter symbols for this and super into 985 // current scope. 986 if ((c.flags_field & INTERFACE) == 0) { 987 VarSymbol thisSym = 988 new VarSymbol(FINAL | HASINIT, names._this, c.type, c); 989 thisSym.pos = Position.FIRSTPOS; 990 env.info.scope.enter(thisSym); 991 if (ct.supertype_field.tag == CLASS) { 992 VarSymbol superSym = 993 new VarSymbol(FINAL | HASINIT, names._super, 994 ct.supertype_field, c); 995 superSym.pos = Position.FIRSTPOS; 996 env.info.scope.enter(superSym); 997 } 998 } 999 1000 // check that no package exists with same fully qualified name, 1001 // but admit classes in the unnamed package which have the same 1002 // name as a top-level package. 1003 if (checkClash && 1004 c.owner.kind == PCK && c.owner != syms.unnamedPackage && 1005 reader.packageExists(c.fullname)) 1006 { 1007 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c); 1008 } 1009 1010 } catch (CompletionFailure ex) { 1011 chk.completionError(tree.pos(), ex); 1012 } finally { 1013 log.useSource(prev); 1014 } 1015 1016 // Enter all member fields and methods of a set of half completed 1017 // classes in a second phase. 1018 if (wasFirst) { 1019 try { 1020 while (halfcompleted.nonEmpty()) { 1021 finish(halfcompleted.next()); 1022 } 1023 } finally { 1024 isFirst = true; 1025 } 1026 1027 // commit pending annotations 1028 annotate.flush(); 1029 } 1030 } 1031 1032 private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) { 1033 Scope baseScope = new Scope(tree.sym); 1034 //import already entered local classes into base scope 1035 for (Scope.Entry e = env.outer.info.scope.elems ; e != null ; e = e.sibling) { 1036 if (e.sym.isLocal()) { 1037 baseScope.enter(e.sym); 1038 } 1039 } 1040 //import current type-parameters into base scope 1041 if (tree.typarams != null) 1042 for (List<JCTypeParameter> typarams = tree.typarams; 1043 typarams.nonEmpty(); 1044 typarams = typarams.tail) 1045 baseScope.enter(typarams.head.type.tsym); 1046 Env<AttrContext> outer = env.outer; // the base clause can't see members of this class 1047 Env<AttrContext> localEnv = outer.dup(tree, outer.info.dup(baseScope)); 1048 localEnv.baseClause = true; 1049 localEnv.outer = outer; 1050 localEnv.info.isSelfCall = false; 1051 return localEnv; 1052 } 1053 1054 /** Enter member fields and methods of a class 1055 * @param env the environment current for the class block. 1056 */ 1057 private void finish(Env<AttrContext> env) { 1058 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1059 try { 1060 JCClassDecl tree = (JCClassDecl)env.tree; 1061 finishClass(tree, env); 1062 } finally { 1063 log.useSource(prev); 1064 } 1065 } 1066 1067 /** Generate a base clause for an enum type. 1068 * @param pos The position for trees and diagnostics, if any 1069 * @param c The class symbol of the enum 1070 */ 1071 private JCExpression enumBase(int pos, ClassSymbol c) { 1072 JCExpression result = make.at(pos). 1073 TypeApply(make.QualIdent(syms.enumSym), 1074 List.<JCExpression>of(make.Type(c.type))); 1075 return result; 1076 } 1077 1078 Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) { 1079 if (t.tag != ERROR) 1080 return t; 1081 1082 return new ErrorType(((ErrorType) t).getOriginalType(), t.tsym) { 1083 private Type modelType; 1084 1085 @Override 1086 public Type getModelType() { 1087 if (modelType == null) 1088 modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree); 1089 return modelType; 1090 } 1091 }; 1092 } 1093 // where 1094 private class Synthesizer extends JCTree.Visitor { 1095 Type originalType; 1096 boolean interfaceExpected; 1097 List<ClassSymbol> synthesizedSymbols = List.nil(); 1098 Type result; 1099 1100 Synthesizer(Type originalType, boolean interfaceExpected) { 1101 this.originalType = originalType; 1102 this.interfaceExpected = interfaceExpected; 1103 } 1104 1105 Type visit(JCTree tree) { 1106 tree.accept(this); 1107 return result; 1108 } 1109 1110 List<Type> visit(List<? extends JCTree> trees) { 1111 ListBuffer<Type> lb = new ListBuffer<Type>(); 1112 for (JCTree t: trees) 1113 lb.append(visit(t)); 1114 return lb.toList(); 1115 } 1116 1117 @Override 1118 public void visitTree(JCTree tree) { 1119 result = syms.errType; 1120 } 1121 1122 @Override 1123 public void visitIdent(JCIdent tree) { 1124 if (tree.type.tag != ERROR) { 1125 result = tree.type; 1126 } else { 1127 result = synthesizeClass(tree.name, syms.unnamedPackage).type; 1128 } 1129 } 1130 1131 @Override 1132 public void visitSelect(JCFieldAccess tree) { 1133 if (tree.type.tag != ERROR) { 1134 result = tree.type; 1135 } else { 1136 Type selectedType; 1137 boolean prev = interfaceExpected; 1138 try { 1139 interfaceExpected = false; 1140 selectedType = visit(tree.selected); 1141 } finally { 1142 interfaceExpected = prev; 1143 } 1144 ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym); 1145 result = c.type; 1146 } 1147 } 1148 1149 @Override 1150 public void visitTypeApply(JCTypeApply tree) { 1151 if (tree.type.tag != ERROR) { 1152 result = tree.type; 1153 } else { 1154 ClassType clazzType = (ClassType) visit(tree.clazz); 1155 if (synthesizedSymbols.contains(clazzType.tsym)) 1156 synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size()); 1157 final List<Type> actuals = visit(tree.arguments); 1158 result = new ErrorType(tree.type, clazzType.tsym) { 1159 @Override 1160 public List<Type> getTypeArguments() { 1161 return actuals; 1162 } 1163 }; 1164 } 1165 } 1166 1167 ClassSymbol synthesizeClass(Name name, Symbol owner) { 1168 int flags = interfaceExpected ? INTERFACE : 0; 1169 ClassSymbol c = new ClassSymbol(flags, name, owner); 1170 c.members_field = new Scope.ErrorScope(c); 1171 c.type = new ErrorType(originalType, c) { 1172 @Override 1173 public List<Type> getTypeArguments() { 1174 return typarams_field; 1175 } 1176 }; 1177 synthesizedSymbols = synthesizedSymbols.prepend(c); 1178 return c; 1179 } 1180 1181 void synthesizeTyparams(ClassSymbol sym, int n) { 1182 ClassType ct = (ClassType) sym.type; 1183 Assert.check(ct.typarams_field.isEmpty()); 1184 if (n == 1) { 1185 TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType); 1186 ct.typarams_field = ct.typarams_field.prepend(v); 1187 } else { 1188 for (int i = n; i > 0; i--) { 1189 TypeVar v = new TypeVar(names.fromString("T" + i), sym, syms.botType); 1190 ct.typarams_field = ct.typarams_field.prepend(v); 1191 } 1192 } 1193 } 1194 } 1195 1196 1197 /* *************************************************************************** 1198 * tree building 1199 ****************************************************************************/ 1200 1201 /** Generate default constructor for given class. For classes different 1202 * from java.lang.Object, this is: 1203 * 1204 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown { 1205 * super(x_0, ..., x_n) 1206 * } 1207 * 1208 * or, if based == true: 1209 * 1210 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown { 1211 * x_0.super(x_1, ..., x_n) 1212 * } 1213 * 1214 * @param make The tree factory. 1215 * @param c The class owning the default constructor. 1216 * @param argtypes The parameter types of the constructor. 1217 * @param thrown The thrown exceptions of the constructor. 1218 * @param based Is first parameter a this$n? 1219 */ 1220 JCTree DefaultConstructor(TreeMaker make, 1221 ClassSymbol c, 1222 List<Type> typarams, 1223 List<Type> argtypes, 1224 List<Type> thrown, 1225 long flags, 1226 boolean based) { 1227 List<JCVariableDecl> params = make.Params(argtypes, syms.noSymbol); 1228 List<JCStatement> stats = List.nil(); 1229 if (c.type != syms.objectType) 1230 stats = stats.prepend(SuperCall(make, typarams, params, based)); 1231 if ((c.flags() & ENUM) != 0 && 1232 (types.supertype(c.type).tsym == syms.enumSym || 1233 target.compilerBootstrap(c))) { 1234 // constructors of true enums are private 1235 flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR; 1236 } else 1237 flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR; 1238 if (c.name.isEmpty()) flags |= ANONCONSTR; 1239 JCTree result = make.MethodDef( 1240 make.Modifiers(flags), 1241 names.init, 1242 null, 1243 make.TypeParams(typarams), 1244 params, 1245 make.Types(thrown), 1246 make.Block(0, stats), 1247 null); 1248 return result; 1249 } 1250 1251 /** Generate call to superclass constructor. This is: 1252 * 1253 * super(id_0, ..., id_n) 1254 * 1255 * or, if based == true 1256 * 1257 * id_0.super(id_1,...,id_n) 1258 * 1259 * where id_0, ..., id_n are the names of the given parameters. 1260 * 1261 * @param make The tree factory 1262 * @param params The parameters that need to be passed to super 1263 * @param typarams The type parameters that need to be passed to super 1264 * @param based Is first parameter a this$n? 1265 */ 1266 JCExpressionStatement SuperCall(TreeMaker make, 1267 List<Type> typarams, 1268 List<JCVariableDecl> params, 1269 boolean based) { 1270 JCExpression meth; 1271 if (based) { 1272 meth = make.Select(make.Ident(params.head), names._super); 1273 params = params.tail; 1274 } else { 1275 meth = make.Ident(names._super); 1276 } 1277 List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null; 1278 return make.Exec(make.Apply(typeargs, meth, make.Idents(params))); 1279 } 1280 }