1 /* 2 * Copyright (c) 2003, 2013, 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.HashMap; 29 import java.util.HashSet; 30 import java.util.LinkedHashMap; 31 import java.util.Map; 32 import java.util.Set; 33 34 import javax.tools.JavaFileObject; 35 36 import com.sun.tools.javac.code.*; 37 import com.sun.tools.javac.jvm.*; 38 import com.sun.tools.javac.tree.*; 39 import com.sun.tools.javac.util.*; 40 41 import com.sun.tools.javac.code.Type.*; 42 import com.sun.tools.javac.code.Symbol.*; 43 import com.sun.tools.javac.tree.JCTree.*; 44 45 import static com.sun.tools.javac.code.Flags.*; 46 import static com.sun.tools.javac.code.Flags.ANNOTATION; 47 import static com.sun.tools.javac.code.Kinds.*; 48 import static com.sun.tools.javac.code.TypeTag.CLASS; 49 import static com.sun.tools.javac.code.TypeTag.ERROR; 50 import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 51 import static com.sun.tools.javac.tree.JCTree.Tag.*; 52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 53 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 54 55 /** This is the second phase of Enter, in which classes are completed 56 * by entering their members into the class scope using 57 * MemberEnter.complete(). See Enter for an overview. 58 * 59 * <p><b>This is NOT part of any supported API. 60 * If you write code that depends on this, you do so at your own risk. 61 * This code and its internal interfaces are subject to change or 62 * deletion without notice.</b> 63 */ 64 public class MemberEnter extends JCTree.Visitor implements Completer { 65 protected static final Context.Key<MemberEnter> memberEnterKey = 66 new Context.Key<MemberEnter>(); 67 68 /** A switch to determine whether we check for package/class conflicts 69 */ 70 final static boolean checkClash = true; 71 72 private final Names names; 73 private final Enter enter; 74 private final Log log; 75 private final Check chk; 76 private final Attr attr; 77 private final Symtab syms; 78 private final TreeMaker make; 79 private final ClassReader reader; 80 private final Todo todo; 81 private final Annotate annotate; 82 private final TypeAnnotations typeAnnotations; 83 private final Types types; 84 private final JCDiagnostic.Factory diags; 85 private final Source source; 86 private final Target target; 87 private final DeferredLintHandler deferredLintHandler; 88 private final Lint lint; 89 private final TypeEnvs typeEnvs; 90 instance(Context context)91 public static MemberEnter instance(Context context) { 92 MemberEnter instance = context.get(memberEnterKey); 93 if (instance == null) 94 instance = new MemberEnter(context); 95 return instance; 96 } 97 MemberEnter(Context context)98 protected MemberEnter(Context context) { 99 context.put(memberEnterKey, this); 100 names = Names.instance(context); 101 enter = Enter.instance(context); 102 log = Log.instance(context); 103 chk = Check.instance(context); 104 attr = Attr.instance(context); 105 syms = Symtab.instance(context); 106 make = TreeMaker.instance(context); 107 reader = ClassReader.instance(context); 108 todo = Todo.instance(context); 109 annotate = Annotate.instance(context); 110 typeAnnotations = TypeAnnotations.instance(context); 111 types = Types.instance(context); 112 diags = JCDiagnostic.Factory.instance(context); 113 source = Source.instance(context); 114 target = Target.instance(context); 115 deferredLintHandler = DeferredLintHandler.instance(context); 116 lint = Lint.instance(context); 117 typeEnvs = TypeEnvs.instance(context); 118 allowTypeAnnos = source.allowTypeAnnotations(); 119 allowRepeatedAnnos = source.allowRepeatedAnnotations(); 120 } 121 122 /** Switch: support type annotations. 123 */ 124 boolean allowTypeAnnos; 125 126 boolean allowRepeatedAnnos; 127 128 /** A queue for classes whose members still need to be entered into the 129 * symbol table. 130 */ 131 ListBuffer<Env<AttrContext>> halfcompleted = new ListBuffer<Env<AttrContext>>(); 132 133 /** Set to true only when the first of a set of classes is 134 * processed from the half completed queue. 135 */ 136 boolean isFirst = true; 137 138 /** A flag to disable completion from time to time during member 139 * enter, as we only need to look up types. This avoids 140 * unnecessarily deep recursion. 141 */ 142 boolean completionEnabled = true; 143 144 /* ---------- Processing import clauses ---------------- 145 */ 146 147 /** Import all classes of a class or package on demand. 148 * @param pos Position to be used for error reporting. 149 * @param tsym The class or package the members of which are imported. 150 * @param env The env in which the imported classes will be entered. 151 */ importAll(int pos, final TypeSymbol tsym, Env<AttrContext> env)152 private void importAll(int pos, 153 final TypeSymbol tsym, 154 Env<AttrContext> env) { 155 // Check that packages imported from exist (JLS ???). 156 if (tsym.kind == PCK && tsym.members().elems == null && !tsym.exists()) { 157 // If we can't find java.lang, exit immediately. 158 if (((PackageSymbol)tsym).fullname.equals(names.java_lang)) { 159 JCDiagnostic msg = diags.fragment("fatal.err.no.java.lang"); 160 throw new FatalError(msg); 161 } else { 162 log.error(DiagnosticFlag.RESOLVE_ERROR, pos, "doesnt.exist", tsym); 163 } 164 } 165 env.toplevel.starImportScope.importAll(tsym.members()); 166 } 167 168 /** Import all static members of a class or package on demand. 169 * @param pos Position to be used for error reporting. 170 * @param tsym The class or package the members of which are imported. 171 * @param env The env in which the imported classes will be entered. 172 */ importStaticAll(int pos, final TypeSymbol tsym, Env<AttrContext> env)173 private void importStaticAll(int pos, 174 final TypeSymbol tsym, 175 Env<AttrContext> env) { 176 final JavaFileObject sourcefile = env.toplevel.sourcefile; 177 final Scope toScope = env.toplevel.starImportScope; 178 final PackageSymbol packge = env.toplevel.packge; 179 final TypeSymbol origin = tsym; 180 181 // enter imported types immediately 182 new Object() { 183 Set<Symbol> processed = new HashSet<Symbol>(); 184 void importFrom(TypeSymbol tsym) { 185 if (tsym == null || !processed.add(tsym)) 186 return; 187 188 // also import inherited names 189 importFrom(types.supertype(tsym.type).tsym); 190 for (Type t : types.interfaces(tsym.type)) 191 importFrom(t.tsym); 192 193 final Scope fromScope = tsym.members(); 194 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { 195 Symbol sym = e.sym; 196 if (sym.kind == TYP && 197 (sym.flags() & STATIC) != 0 && 198 staticImportAccessible(sym, packge) && 199 sym.isMemberOf(origin, types) && 200 !toScope.includes(sym)) 201 toScope.enter(sym, fromScope, origin.members(), true); 202 } 203 } 204 }.importFrom(tsym); 205 206 // enter non-types before annotations that might use them 207 annotate.earlier(new Annotate.Worker() { 208 Set<Symbol> processed = new HashSet<Symbol>(); 209 210 public String toString() { 211 return "import static " + tsym + ".*" + " in " + sourcefile; 212 } 213 void importFrom(TypeSymbol tsym) { 214 if (tsym == null || !processed.add(tsym)) 215 return; 216 217 // also import inherited names 218 importFrom(types.supertype(tsym.type).tsym); 219 for (Type t : types.interfaces(tsym.type)) 220 importFrom(t.tsym); 221 222 final Scope fromScope = tsym.members(); 223 for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { 224 Symbol sym = e.sym; 225 if (sym.isStatic() && sym.kind != TYP && 226 staticImportAccessible(sym, packge) && 227 !toScope.includes(sym) && 228 sym.isMemberOf(origin, types)) { 229 toScope.enter(sym, fromScope, origin.members(), true); 230 } 231 } 232 } 233 public void run() { 234 importFrom(tsym); 235 } 236 }); 237 } 238 239 // is the sym accessible everywhere in packge? staticImportAccessible(Symbol sym, PackageSymbol packge)240 boolean staticImportAccessible(Symbol sym, PackageSymbol packge) { 241 int flags = (int)(sym.flags() & AccessFlags); 242 switch (flags) { 243 default: 244 case PUBLIC: 245 return true; 246 case PRIVATE: 247 return false; 248 case 0: 249 case PROTECTED: 250 return sym.packge() == packge; 251 } 252 } 253 254 /** Import statics types of a given name. Non-types are handled in Attr. 255 * @param pos Position to be used for error reporting. 256 * @param tsym The class from which the name is imported. 257 * @param name The (simple) name being imported. 258 * @param env The environment containing the named import 259 * scope to add to. 260 */ importNamedStatic(final DiagnosticPosition pos, final TypeSymbol tsym, final Name name, final Env<AttrContext> env)261 private void importNamedStatic(final DiagnosticPosition pos, 262 final TypeSymbol tsym, 263 final Name name, 264 final Env<AttrContext> env) { 265 if (tsym.kind != TYP) { 266 log.error(DiagnosticFlag.RECOVERABLE, pos, "static.imp.only.classes.and.interfaces"); 267 return; 268 } 269 270 final Scope toScope = env.toplevel.namedImportScope; 271 final PackageSymbol packge = env.toplevel.packge; 272 final TypeSymbol origin = tsym; 273 274 // enter imported types immediately 275 new Object() { 276 Set<Symbol> processed = new HashSet<Symbol>(); 277 void importFrom(TypeSymbol tsym) { 278 if (tsym == null || !processed.add(tsym)) 279 return; 280 281 // also import inherited names 282 importFrom(types.supertype(tsym.type).tsym); 283 for (Type t : types.interfaces(tsym.type)) 284 importFrom(t.tsym); 285 286 for (Scope.Entry e = tsym.members().lookup(name); 287 e.scope != null; 288 e = e.next()) { 289 Symbol sym = e.sym; 290 if (sym.isStatic() && 291 sym.kind == TYP && 292 staticImportAccessible(sym, packge) && 293 sym.isMemberOf(origin, types) && 294 chk.checkUniqueStaticImport(pos, sym, toScope)) 295 toScope.enter(sym, sym.owner.members(), origin.members(), true); 296 } 297 } 298 }.importFrom(tsym); 299 300 // enter non-types before annotations that might use them 301 annotate.earlier(new Annotate.Worker() { 302 Set<Symbol> processed = new HashSet<Symbol>(); 303 boolean found = false; 304 305 public String toString() { 306 return "import static " + tsym + "." + name; 307 } 308 void importFrom(TypeSymbol tsym) { 309 if (tsym == null || !processed.add(tsym)) 310 return; 311 312 // also import inherited names 313 importFrom(types.supertype(tsym.type).tsym); 314 for (Type t : types.interfaces(tsym.type)) 315 importFrom(t.tsym); 316 317 for (Scope.Entry e = tsym.members().lookup(name); 318 e.scope != null; 319 e = e.next()) { 320 Symbol sym = e.sym; 321 if (sym.isStatic() && 322 staticImportAccessible(sym, packge) && 323 sym.isMemberOf(origin, types)) { 324 found = true; 325 if (sym.kind != TYP) { 326 toScope.enter(sym, sym.owner.members(), origin.members(), true); 327 } 328 } 329 } 330 } 331 public void run() { 332 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 333 try { 334 importFrom(tsym); 335 if (!found) { 336 log.error(pos, "cant.resolve.location", 337 KindName.STATIC, 338 name, List.<Type>nil(), List.<Type>nil(), 339 Kinds.typeKindName(tsym.type), 340 tsym.type); 341 } 342 } finally { 343 log.useSource(prev); 344 } 345 } 346 }); 347 } 348 /** Import given class. 349 * @param pos Position to be used for error reporting. 350 * @param tsym The class to be imported. 351 * @param env The environment containing the named import 352 * scope to add to. 353 */ importNamed(DiagnosticPosition pos, Symbol tsym, Env<AttrContext> env)354 private void importNamed(DiagnosticPosition pos, Symbol tsym, Env<AttrContext> env) { 355 if (tsym.kind == TYP && 356 chk.checkUniqueImport(pos, tsym, env.toplevel.namedImportScope)) 357 env.toplevel.namedImportScope.enter(tsym, tsym.owner.members()); 358 } 359 360 /** Construct method type from method signature. 361 * @param typarams The method's type parameters. 362 * @param params The method's value parameters. 363 * @param res The method's result type, 364 * null if it is a constructor. 365 * @param recvparam The method's receiver parameter, 366 * null if none given; TODO: or already set here? 367 * @param thrown The method's thrown exceptions. 368 * @param env The method's (local) environment. 369 */ signature(MethodSymbol msym, List<JCTypeParameter> typarams, List<JCVariableDecl> params, JCTree res, JCVariableDecl recvparam, List<JCExpression> thrown, Env<AttrContext> env)370 Type signature(MethodSymbol msym, 371 List<JCTypeParameter> typarams, 372 List<JCVariableDecl> params, 373 JCTree res, 374 JCVariableDecl recvparam, 375 List<JCExpression> thrown, 376 Env<AttrContext> env) { 377 378 // Enter and attribute type parameters. 379 List<Type> tvars = enter.classEnter(typarams, env); 380 attr.attribTypeVariables(typarams, env); 381 382 // Enter and attribute value parameters. 383 ListBuffer<Type> argbuf = new ListBuffer<Type>(); 384 for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) { 385 memberEnter(l.head, env); 386 argbuf.append(l.head.vartype.type); 387 } 388 389 // Attribute result type, if one is given. 390 Type restype = res == null ? syms.voidType : attr.attribType(res, env); 391 392 // Attribute receiver type, if one is given. 393 Type recvtype; 394 if (recvparam!=null) { 395 memberEnter(recvparam, env); 396 recvtype = recvparam.vartype.type; 397 } else { 398 recvtype = null; 399 } 400 401 // Attribute thrown exceptions. 402 ListBuffer<Type> thrownbuf = new ListBuffer<Type>(); 403 for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) { 404 Type exc = attr.attribType(l.head, env); 405 if (!exc.hasTag(TYPEVAR)) { 406 exc = chk.checkClassType(l.head.pos(), exc); 407 } else if (exc.tsym.owner == msym) { 408 //mark inference variables in 'throws' clause 409 exc.tsym.flags_field |= THROWS; 410 } 411 thrownbuf.append(exc); 412 } 413 MethodType mtype = new MethodType(argbuf.toList(), 414 restype, 415 thrownbuf.toList(), 416 syms.methodClass); 417 mtype.recvtype = recvtype; 418 419 return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); 420 } 421 422 /* ******************************************************************** 423 * Visitor methods for member enter 424 *********************************************************************/ 425 426 /** Visitor argument: the current environment 427 */ 428 protected Env<AttrContext> env; 429 430 /** Enter field and method definitions and process import 431 * clauses, catching any completion failure exceptions. 432 */ memberEnter(JCTree tree, Env<AttrContext> env)433 protected void memberEnter(JCTree tree, Env<AttrContext> env) { 434 Env<AttrContext> prevEnv = this.env; 435 try { 436 this.env = env; 437 tree.accept(this); 438 } catch (CompletionFailure ex) { 439 chk.completionError(tree.pos(), ex); 440 } finally { 441 this.env = prevEnv; 442 } 443 } 444 445 /** Enter members from a list of trees. 446 */ memberEnter(List<? extends JCTree> trees, Env<AttrContext> env)447 void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) { 448 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 449 memberEnter(l.head, env); 450 } 451 452 /** Enter members for a class. 453 */ finishClass(JCClassDecl tree, Env<AttrContext> env)454 void finishClass(JCClassDecl tree, Env<AttrContext> env) { 455 if ((tree.mods.flags & Flags.ENUM) != 0 && 456 (types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) { 457 addEnumMembers(tree, env); 458 } 459 memberEnter(tree.defs, env); 460 } 461 462 /** Add the implicit members for an enum type 463 * to the symbol table. 464 */ addEnumMembers(JCClassDecl tree, Env<AttrContext> env)465 private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) { 466 JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass)); 467 468 // public static T[] values() { return ???; } 469 JCMethodDecl values = make. 470 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), 471 names.values, 472 valuesType, 473 List.<JCTypeParameter>nil(), 474 List.<JCVariableDecl>nil(), 475 List.<JCExpression>nil(), // thrown 476 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), 477 null); 478 memberEnter(values, env); 479 480 // public static T valueOf(String name) { return ???; } 481 JCMethodDecl valueOf = make. 482 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), 483 names.valueOf, 484 make.Type(tree.sym.type), 485 List.<JCTypeParameter>nil(), 486 List.of(make.VarDef(make.Modifiers(Flags.PARAMETER | 487 Flags.MANDATED), 488 names.fromString("name"), 489 make.Type(syms.stringType), null)), 490 List.<JCExpression>nil(), // thrown 491 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), 492 null); 493 memberEnter(valueOf, env); 494 } 495 visitTopLevel(JCCompilationUnit tree)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, null); 519 520 DiagnosticPosition prevLintPos = deferredLintHandler.immediate(); 521 Lint prevLint = chk.setLint(lint); 522 523 try { 524 // Import-on-demand java.lang. 525 importAll(tree.pos, reader.enterPackage(names.java_lang), env); 526 527 // Process all import clauses. 528 memberEnter(tree.defs, env); 529 } finally { 530 chk.setLint(prevLint); 531 deferredLintHandler.setPos(prevLintPos); 532 } 533 } 534 535 // process the non-static imports and the static imports of types. visitImport(JCImport tree)536 public void visitImport(JCImport tree) { 537 JCFieldAccess imp = (JCFieldAccess)tree.qualid; 538 Name name = TreeInfo.name(imp); 539 540 // Create a local environment pointing to this tree to disable 541 // effects of other imports in Resolve.findGlobalType 542 Env<AttrContext> localEnv = env.dup(tree); 543 544 TypeSymbol p = attr.attribImportQualifier(tree, localEnv).tsym; 545 if (name == names.asterisk) { 546 // Import on demand. 547 chk.checkCanonical(imp.selected); 548 if (tree.staticImport) 549 importStaticAll(tree.pos, p, env); 550 else 551 importAll(tree.pos, p, env); 552 } else { 553 // Named type import. 554 if (tree.staticImport) { 555 importNamedStatic(tree.pos(), p, name, localEnv); 556 chk.checkCanonical(imp.selected); 557 } else { 558 TypeSymbol c = attribImportType(imp, localEnv).tsym; 559 chk.checkCanonical(imp); 560 importNamed(tree.pos(), c, env); 561 } 562 } 563 } 564 visitMethodDef(JCMethodDecl tree)565 public void visitMethodDef(JCMethodDecl tree) { 566 Scope enclScope = enter.enterScope(env); 567 MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner); 568 m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree); 569 tree.sym = m; 570 571 //if this is a default method, add the DEFAULT flag to the enclosing interface 572 if ((tree.mods.flags & DEFAULT) != 0) { 573 m.enclClass().flags_field |= DEFAULT; 574 } 575 576 Env<AttrContext> localEnv = methodEnv(tree, env); 577 578 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 579 try { 580 // Compute the method type 581 m.type = signature(m, tree.typarams, tree.params, 582 tree.restype, tree.recvparam, 583 tree.thrown, 584 localEnv); 585 } finally { 586 deferredLintHandler.setPos(prevLintPos); 587 } 588 589 if (types.isSignaturePolymorphic(m)) { 590 m.flags_field |= SIGNATURE_POLYMORPHIC; 591 } 592 593 // Set m.params 594 ListBuffer<VarSymbol> params = new ListBuffer<VarSymbol>(); 595 JCVariableDecl lastParam = null; 596 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 597 JCVariableDecl param = lastParam = l.head; 598 params.append(Assert.checkNonNull(param.sym)); 599 } 600 m.params = params.toList(); 601 602 // mark the method varargs, if necessary 603 if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0) 604 m.flags_field |= Flags.VARARGS; 605 606 localEnv.info.scope.leave(); 607 if (chk.checkUnique(tree.pos(), m, enclScope)) { 608 enclScope.enter(m); 609 } 610 611 annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); 612 // Visit the signature of the method. Note that 613 // TypeAnnotate doesn't descend into the body. 614 typeAnnotate(tree, localEnv, m, tree.pos()); 615 616 if (tree.defaultValue != null) 617 annotateDefaultValueLater(tree.defaultValue, localEnv, m); 618 } 619 620 /** Create a fresh environment for method bodies. 621 * @param tree The method definition. 622 * @param env The environment current outside of the method definition. 623 */ methodEnv(JCMethodDecl tree, Env<AttrContext> env)624 Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) { 625 Env<AttrContext> localEnv = 626 env.dup(tree, env.info.dup(env.info.scope.dupUnshared())); 627 localEnv.enclMethod = tree; 628 localEnv.info.scope.owner = tree.sym; 629 if (tree.sym.type != null) { 630 //when this is called in the enter stage, there's no type to be set 631 localEnv.info.returnResult = attr.new ResultInfo(VAL, tree.sym.type.getReturnType()); 632 } 633 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; 634 return localEnv; 635 } 636 visitVarDef(JCVariableDecl tree)637 public void visitVarDef(JCVariableDecl tree) { 638 Env<AttrContext> localEnv = env; 639 if ((tree.mods.flags & STATIC) != 0 || 640 (env.info.scope.owner.flags() & INTERFACE) != 0) { 641 localEnv = env.dup(tree, env.info.dup()); 642 localEnv.info.staticLevel++; 643 } 644 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 645 try { 646 if (TreeInfo.isEnumInit(tree)) { 647 attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); 648 } else { 649 attr.attribType(tree.vartype, localEnv); 650 if (TreeInfo.isReceiverParam(tree)) 651 checkReceiver(tree, localEnv); 652 } 653 } finally { 654 deferredLintHandler.setPos(prevLintPos); 655 } 656 657 if ((tree.mods.flags & VARARGS) != 0) { 658 //if we are entering a varargs parameter, we need to 659 //replace its type (a plain array type) with the more 660 //precise VarargsType --- we need to do it this way 661 //because varargs is represented in the tree as a 662 //modifier on the parameter declaration, and not as a 663 //distinct type of array node. 664 ArrayType atype = (ArrayType)tree.vartype.type.unannotatedType(); 665 tree.vartype.type = atype.makeVarargs(); 666 } 667 Scope enclScope = enter.enterScope(env); 668 VarSymbol v = 669 new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner); 670 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); 671 tree.sym = v; 672 if (tree.init != null) { 673 v.flags_field |= HASINIT; 674 if ((v.flags_field & FINAL) != 0 && 675 needsLazyConstValue(tree.init)) { 676 Env<AttrContext> initEnv = getInitEnv(tree, env); 677 initEnv.info.enclVar = v; 678 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); 679 } 680 } 681 if (chk.checkUnique(tree.pos(), v, enclScope)) { 682 chk.checkTransparentVar(tree.pos(), v, enclScope); 683 enclScope.enter(v); 684 } 685 annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); 686 typeAnnotate(tree.vartype, env, v, tree.pos()); 687 v.pos = tree.pos; 688 } 689 // where checkType(JCTree tree, Type type, String diag)690 void checkType(JCTree tree, Type type, String diag) { 691 if (!tree.type.isErroneous() && !types.isSameType(tree.type, type)) { 692 log.error(tree, diag, type, tree.type); 693 } 694 } checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv)695 void checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv) { 696 attr.attribExpr(tree.nameexpr, localEnv); 697 MethodSymbol m = localEnv.enclMethod.sym; 698 if (m.isConstructor()) { 699 Type outertype = m.owner.owner.type; 700 if (outertype.hasTag(TypeTag.METHOD)) { 701 // we have a local inner class 702 outertype = m.owner.owner.owner.type; 703 } 704 if (outertype.hasTag(TypeTag.CLASS)) { 705 checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type"); 706 checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name"); 707 } else { 708 log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class"); 709 } 710 } else { 711 checkType(tree.vartype, m.owner.type, "incorrect.receiver.type"); 712 checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name"); 713 } 714 } 715 needsLazyConstValue(JCTree tree)716 public boolean needsLazyConstValue(JCTree tree) { 717 InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); 718 tree.accept(initTreeVisitor); 719 return initTreeVisitor.result; 720 } 721 722 /** Visitor class for expressions which might be constant expressions. 723 */ 724 static class InitTreeVisitor extends JCTree.Visitor { 725 726 private boolean result = true; 727 728 @Override visitTree(JCTree tree)729 public void visitTree(JCTree tree) {} 730 731 @Override visitNewClass(JCNewClass that)732 public void visitNewClass(JCNewClass that) { 733 result = false; 734 } 735 736 @Override visitNewArray(JCNewArray that)737 public void visitNewArray(JCNewArray that) { 738 result = false; 739 } 740 741 @Override visitLambda(JCLambda that)742 public void visitLambda(JCLambda that) { 743 result = false; 744 } 745 746 @Override visitReference(JCMemberReference that)747 public void visitReference(JCMemberReference that) { 748 result = false; 749 } 750 751 @Override visitApply(JCMethodInvocation that)752 public void visitApply(JCMethodInvocation that) { 753 result = false; 754 } 755 756 @Override visitSelect(JCFieldAccess tree)757 public void visitSelect(JCFieldAccess tree) { 758 tree.selected.accept(this); 759 } 760 761 @Override visitConditional(JCConditional tree)762 public void visitConditional(JCConditional tree) { 763 tree.cond.accept(this); 764 tree.truepart.accept(this); 765 tree.falsepart.accept(this); 766 } 767 768 @Override visitParens(JCParens tree)769 public void visitParens(JCParens tree) { 770 tree.expr.accept(this); 771 } 772 773 @Override visitTypeCast(JCTypeCast tree)774 public void visitTypeCast(JCTypeCast tree) { 775 tree.expr.accept(this); 776 } 777 } 778 779 /** Create a fresh environment for a variable's initializer. 780 * If the variable is a field, the owner of the environment's scope 781 * is be the variable itself, otherwise the owner is the method 782 * enclosing the variable definition. 783 * 784 * @param tree The variable definition. 785 * @param env The environment current outside of the variable definition. 786 */ initEnv(JCVariableDecl tree, Env<AttrContext> env)787 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) { 788 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup())); 789 if (tree.sym.owner.kind == TYP) { 790 localEnv.info.scope = env.info.scope.dupUnshared(); 791 localEnv.info.scope.owner = tree.sym; 792 } 793 if ((tree.mods.flags & STATIC) != 0 || 794 ((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null)) 795 localEnv.info.staticLevel++; 796 return localEnv; 797 } 798 799 /** Default member enter visitor method: do nothing 800 */ visitTree(JCTree tree)801 public void visitTree(JCTree tree) { 802 } 803 visitErroneous(JCErroneous tree)804 public void visitErroneous(JCErroneous tree) { 805 if (tree.errs != null) 806 memberEnter(tree.errs, env); 807 } 808 getMethodEnv(JCMethodDecl tree, Env<AttrContext> env)809 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { 810 Env<AttrContext> mEnv = methodEnv(tree, env); 811 mEnv.info.lint = mEnv.info.lint.augment(tree.sym); 812 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 813 mEnv.info.scope.enterIfAbsent(l.head.type.tsym); 814 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) 815 mEnv.info.scope.enterIfAbsent(l.head.sym); 816 return mEnv; 817 } 818 getInitEnv(JCVariableDecl tree, Env<AttrContext> env)819 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) { 820 Env<AttrContext> iEnv = initEnv(tree, env); 821 return iEnv; 822 } 823 824 /* ******************************************************************** 825 * Type completion 826 *********************************************************************/ 827 attribImportType(JCTree tree, Env<AttrContext> env)828 Type attribImportType(JCTree tree, Env<AttrContext> env) { 829 Assert.check(completionEnabled); 830 try { 831 // To prevent deep recursion, suppress completion of some 832 // types. 833 completionEnabled = false; 834 return attr.attribType(tree, env); 835 } finally { 836 completionEnabled = true; 837 } 838 } 839 840 /* ******************************************************************** 841 * Annotation processing 842 *********************************************************************/ 843 844 /** Queue annotations for later processing. */ annotateLater(final List<JCAnnotation> annotations, final Env<AttrContext> localEnv, final Symbol s, final DiagnosticPosition deferPos)845 void annotateLater(final List<JCAnnotation> annotations, 846 final Env<AttrContext> localEnv, 847 final Symbol s, 848 final DiagnosticPosition deferPos) { 849 if (annotations.isEmpty()) { 850 return; 851 } 852 if (s.kind != PCK) { 853 s.resetAnnotations(); // mark Annotations as incomplete for now 854 } 855 annotate.normal(new Annotate.Worker() { 856 @Override 857 public String toString() { 858 return "annotate " + annotations + " onto " + s + " in " + s.owner; 859 } 860 861 @Override 862 public void run() { 863 Assert.check(s.kind == PCK || s.annotationsPendingCompletion()); 864 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 865 DiagnosticPosition prevLintPos = 866 deferPos != null 867 ? deferredLintHandler.setPos(deferPos) 868 : deferredLintHandler.immediate(); 869 Lint prevLint = deferPos != null ? null : chk.setLint(lint); 870 try { 871 if (s.hasAnnotations() && 872 annotations.nonEmpty()) 873 log.error(annotations.head.pos, 874 "already.annotated", 875 kindName(s), s); 876 actualEnterAnnotations(annotations, localEnv, s); 877 } finally { 878 if (prevLint != null) 879 chk.setLint(prevLint); 880 deferredLintHandler.setPos(prevLintPos); 881 log.useSource(prev); 882 } 883 } 884 }); 885 886 annotate.validate(new Annotate.Worker() { //validate annotations 887 @Override 888 public void run() { 889 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 890 try { 891 chk.validateAnnotations(annotations, s); 892 } finally { 893 log.useSource(prev); 894 } 895 } 896 }); 897 } 898 899 /** 900 * Check if a list of annotations contains a reference to 901 * java.lang.Deprecated. 902 **/ hasDeprecatedAnnotation(List<JCAnnotation> annotations)903 private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) { 904 for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) { 905 JCAnnotation a = al.head; 906 if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty()) 907 return true; 908 } 909 return false; 910 } 911 912 /** Enter a set of annotations. */ actualEnterAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env, Symbol s)913 private void actualEnterAnnotations(List<JCAnnotation> annotations, 914 Env<AttrContext> env, 915 Symbol s) { 916 Map<TypeSymbol, ListBuffer<Attribute.Compound>> annotated = 917 new LinkedHashMap<TypeSymbol, ListBuffer<Attribute.Compound>>(); 918 Map<Attribute.Compound, DiagnosticPosition> pos = 919 new HashMap<Attribute.Compound, DiagnosticPosition>(); 920 921 for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) { 922 JCAnnotation a = al.head; 923 Attribute.Compound c = annotate.enterAnnotation(a, 924 syms.annotationType, 925 env); 926 if (c == null) { 927 continue; 928 } 929 930 if (annotated.containsKey(a.type.tsym)) { 931 if (!allowRepeatedAnnos) { 932 log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); 933 allowRepeatedAnnos = true; 934 } 935 ListBuffer<Attribute.Compound> l = annotated.get(a.type.tsym); 936 l = l.append(c); 937 annotated.put(a.type.tsym, l); 938 pos.put(c, a.pos()); 939 } else { 940 annotated.put(a.type.tsym, ListBuffer.of(c)); 941 pos.put(c, a.pos()); 942 } 943 944 // Note: @Deprecated has no effect on local variables and parameters 945 if (!c.type.isErroneous() 946 && s.owner.kind != MTH 947 && types.isSameType(c.type, syms.deprecatedType)) { 948 s.flags_field |= Flags.DEPRECATED; 949 } 950 } 951 952 s.setDeclarationAttributesWithCompletion( 953 annotate.new AnnotateRepeatedContext<Attribute.Compound>(env, annotated, pos, log, false)); 954 } 955 956 /** Queue processing of an attribute default value. */ annotateDefaultValueLater(final JCExpression defaultValue, final Env<AttrContext> localEnv, final MethodSymbol m)957 void annotateDefaultValueLater(final JCExpression defaultValue, 958 final Env<AttrContext> localEnv, 959 final MethodSymbol m) { 960 annotate.normal(new Annotate.Worker() { 961 @Override 962 public String toString() { 963 return "annotate " + m.owner + "." + 964 m + " default " + defaultValue; 965 } 966 967 @Override 968 public void run() { 969 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 970 try { 971 enterDefaultValue(defaultValue, localEnv, m); 972 } finally { 973 log.useSource(prev); 974 } 975 } 976 }); 977 annotate.validate(new Annotate.Worker() { //validate annotations 978 @Override 979 public void run() { 980 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 981 try { 982 // if default value is an annotation, check it is a well-formed 983 // annotation value (e.g. no duplicate values, no missing values, etc.) 984 chk.validateAnnotationTree(defaultValue); 985 } finally { 986 log.useSource(prev); 987 } 988 } 989 }); 990 } 991 992 /** Enter a default value for an attribute method. */ enterDefaultValue(final JCExpression defaultValue, final Env<AttrContext> localEnv, final MethodSymbol m)993 private void enterDefaultValue(final JCExpression defaultValue, 994 final Env<AttrContext> localEnv, 995 final MethodSymbol m) { 996 m.defaultValue = annotate.enterAttributeValue(m.type.getReturnType(), 997 defaultValue, 998 localEnv); 999 } 1000 1001 /* ******************************************************************** 1002 * Source completer 1003 *********************************************************************/ 1004 1005 /** Complete entering a class. 1006 * @param sym The symbol of the class to be completed. 1007 */ complete(Symbol sym)1008 public void complete(Symbol sym) throws CompletionFailure { 1009 // Suppress some (recursive) MemberEnter invocations 1010 if (!completionEnabled) { 1011 // Re-install same completer for next time around and return. 1012 Assert.check((sym.flags() & Flags.COMPOUND) == 0); 1013 sym.completer = this; 1014 return; 1015 } 1016 1017 ClassSymbol c = (ClassSymbol)sym; 1018 ClassType ct = (ClassType)c.type; 1019 Env<AttrContext> env = typeEnvs.get(c); 1020 JCClassDecl tree = (JCClassDecl)env.tree; 1021 boolean wasFirst = isFirst; 1022 isFirst = false; 1023 try { 1024 annotate.enterStart(); 1025 1026 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1027 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 1028 try { 1029 // Save class environment for later member enter (2) processing. 1030 halfcompleted.append(env); 1031 1032 // Mark class as not yet attributed. 1033 c.flags_field |= UNATTRIBUTED; 1034 1035 // If this is a toplevel-class, make sure any preceding import 1036 // clauses have been seen. 1037 if (c.owner.kind == PCK) { 1038 memberEnter(env.toplevel, env.enclosing(TOPLEVEL)); 1039 todo.append(env); 1040 } 1041 1042 if (c.owner.kind == TYP) 1043 c.owner.complete(); 1044 1045 // create an environment for evaluating the base clauses 1046 Env<AttrContext> baseEnv = baseEnv(tree, env); 1047 1048 if (tree.extending != null) 1049 typeAnnotate(tree.extending, baseEnv, sym, tree.pos()); 1050 for (JCExpression impl : tree.implementing) 1051 typeAnnotate(impl, baseEnv, sym, tree.pos()); 1052 annotate.flush(); 1053 1054 // Determine supertype. 1055 Type supertype = 1056 (tree.extending != null) 1057 ? attr.attribBase(tree.extending, baseEnv, true, false, true) 1058 : ((tree.mods.flags & Flags.ENUM) != 0) 1059 ? attr.attribBase(enumBase(tree.pos, c), baseEnv, 1060 true, false, false) 1061 : (c.fullname == names.java_lang_Object) 1062 ? Type.noType 1063 : syms.objectType; 1064 ct.supertype_field = modelMissingTypes(supertype, tree.extending, false); 1065 1066 // Determine interfaces. 1067 ListBuffer<Type> interfaces = new ListBuffer<Type>(); 1068 ListBuffer<Type> all_interfaces = null; // lazy init 1069 Set<Type> interfaceSet = new HashSet<Type>(); 1070 List<JCExpression> interfaceTrees = tree.implementing; 1071 for (JCExpression iface : interfaceTrees) { 1072 Type i = attr.attribBase(iface, baseEnv, false, true, true); 1073 if (i.hasTag(CLASS)) { 1074 interfaces.append(i); 1075 if (all_interfaces != null) all_interfaces.append(i); 1076 chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet); 1077 } else { 1078 if (all_interfaces == null) 1079 all_interfaces = new ListBuffer<Type>().appendList(interfaces); 1080 all_interfaces.append(modelMissingTypes(i, iface, true)); 1081 } 1082 } 1083 if ((c.flags_field & ANNOTATION) != 0) { 1084 ct.interfaces_field = List.of(syms.annotationType); 1085 ct.all_interfaces_field = ct.interfaces_field; 1086 } else { 1087 ct.interfaces_field = interfaces.toList(); 1088 ct.all_interfaces_field = (all_interfaces == null) 1089 ? ct.interfaces_field : all_interfaces.toList(); 1090 } 1091 1092 if (c.fullname == names.java_lang_Object) { 1093 if (tree.extending != null) { 1094 chk.checkNonCyclic(tree.extending.pos(), 1095 supertype); 1096 ct.supertype_field = Type.noType; 1097 } 1098 else if (tree.implementing.nonEmpty()) { 1099 chk.checkNonCyclic(tree.implementing.head.pos(), 1100 ct.interfaces_field.head); 1101 ct.interfaces_field = List.nil(); 1102 } 1103 } 1104 1105 // Annotations. 1106 // In general, we cannot fully process annotations yet, but we 1107 // can attribute the annotation types and then check to see if the 1108 // @Deprecated annotation is present. 1109 attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); 1110 if (hasDeprecatedAnnotation(tree.mods.annotations)) 1111 c.flags_field |= DEPRECATED; 1112 annotateLater(tree.mods.annotations, baseEnv, c, tree.pos()); 1113 // class type parameters use baseEnv but everything uses env 1114 1115 chk.checkNonCyclicDecl(tree); 1116 1117 attr.attribTypeVariables(tree.typarams, baseEnv); 1118 // Do this here, where we have the symbol. 1119 for (JCTypeParameter tp : tree.typarams) 1120 typeAnnotate(tp, baseEnv, sym, tree.pos()); 1121 1122 // Add default constructor if needed. 1123 if ((c.flags() & INTERFACE) == 0 && 1124 !TreeInfo.hasConstructors(tree.defs)) { 1125 List<Type> argtypes = List.nil(); 1126 List<Type> typarams = List.nil(); 1127 List<Type> thrown = List.nil(); 1128 long ctorFlags = 0; 1129 boolean based = false; 1130 boolean addConstructor = true; 1131 JCNewClass nc = null; 1132 if (c.name.isEmpty()) { 1133 nc = (JCNewClass)env.next.tree; 1134 if (nc.constructor != null) { 1135 addConstructor = nc.constructor.kind != ERR; 1136 Type superConstrType = types.memberType(c.type, 1137 nc.constructor); 1138 argtypes = superConstrType.getParameterTypes(); 1139 typarams = superConstrType.getTypeArguments(); 1140 ctorFlags = nc.constructor.flags() & VARARGS; 1141 if (nc.encl != null) { 1142 argtypes = argtypes.prepend(nc.encl.type); 1143 based = true; 1144 } 1145 thrown = superConstrType.getThrownTypes(); 1146 } 1147 } 1148 if (addConstructor) { 1149 MethodSymbol basedConstructor = nc != null ? 1150 (MethodSymbol)nc.constructor : null; 1151 JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, 1152 basedConstructor, 1153 typarams, argtypes, thrown, 1154 ctorFlags, based); 1155 tree.defs = tree.defs.prepend(constrDef); 1156 } 1157 } 1158 1159 // enter symbols for 'this' into current scope. 1160 VarSymbol thisSym = 1161 new VarSymbol(FINAL | HASINIT, names._this, c.type, c); 1162 thisSym.pos = Position.FIRSTPOS; 1163 env.info.scope.enter(thisSym); 1164 // if this is a class, enter symbol for 'super' into current scope. 1165 if ((c.flags_field & INTERFACE) == 0 && 1166 ct.supertype_field.hasTag(CLASS)) { 1167 VarSymbol superSym = 1168 new VarSymbol(FINAL | HASINIT, names._super, 1169 ct.supertype_field, c); 1170 superSym.pos = Position.FIRSTPOS; 1171 env.info.scope.enter(superSym); 1172 } 1173 1174 // check that no package exists with same fully qualified name, 1175 // but admit classes in the unnamed package which have the same 1176 // name as a top-level package. 1177 if (checkClash && 1178 c.owner.kind == PCK && c.owner != syms.unnamedPackage && 1179 reader.packageExists(c.fullname)) { 1180 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c); 1181 } 1182 if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 && 1183 !env.toplevel.sourcefile.isNameCompatible(c.name.toString(),JavaFileObject.Kind.SOURCE)) { 1184 c.flags_field |= AUXILIARY; 1185 } 1186 } catch (CompletionFailure ex) { 1187 chk.completionError(tree.pos(), ex); 1188 } finally { 1189 deferredLintHandler.setPos(prevLintPos); 1190 log.useSource(prev); 1191 } 1192 1193 // Enter all member fields and methods of a set of half completed 1194 // classes in a second phase. 1195 if (wasFirst) { 1196 try { 1197 while (halfcompleted.nonEmpty()) { 1198 Env<AttrContext> toFinish = halfcompleted.next(); 1199 finish(toFinish); 1200 if (allowTypeAnnos) { 1201 typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree); 1202 typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree); 1203 } 1204 } 1205 } finally { 1206 isFirst = true; 1207 } 1208 } 1209 } finally { 1210 annotate.enterDone(); 1211 } 1212 } 1213 1214 /* 1215 * If the symbol is non-null, attach the type annotation to it. 1216 */ actualEnterTypeAnnotations(final List<JCAnnotation> annotations, final Env<AttrContext> env, final Symbol s)1217 private void actualEnterTypeAnnotations(final List<JCAnnotation> annotations, 1218 final Env<AttrContext> env, 1219 final Symbol s) { 1220 Map<TypeSymbol, ListBuffer<Attribute.TypeCompound>> annotated = 1221 new LinkedHashMap<TypeSymbol, ListBuffer<Attribute.TypeCompound>>(); 1222 Map<Attribute.TypeCompound, DiagnosticPosition> pos = 1223 new HashMap<Attribute.TypeCompound, DiagnosticPosition>(); 1224 1225 for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) { 1226 JCAnnotation a = al.head; 1227 Attribute.TypeCompound tc = annotate.enterTypeAnnotation(a, 1228 syms.annotationType, 1229 env); 1230 if (tc == null) { 1231 continue; 1232 } 1233 1234 if (annotated.containsKey(a.type.tsym)) { 1235 if (source.allowRepeatedAnnotations()) { 1236 ListBuffer<Attribute.TypeCompound> l = annotated.get(a.type.tsym); 1237 l = l.append(tc); 1238 annotated.put(a.type.tsym, l); 1239 pos.put(tc, a.pos()); 1240 } else { 1241 log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); 1242 } 1243 } else { 1244 annotated.put(a.type.tsym, ListBuffer.of(tc)); 1245 pos.put(tc, a.pos()); 1246 } 1247 } 1248 1249 if (s != null) { 1250 s.appendTypeAttributesWithCompletion( 1251 annotate.new AnnotateRepeatedContext<Attribute.TypeCompound>(env, annotated, pos, log, true)); 1252 } 1253 } 1254 typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos)1255 public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos) { 1256 if (allowTypeAnnos) { 1257 tree.accept(new TypeAnnotate(env, sym, deferPos)); 1258 } 1259 } 1260 1261 /** 1262 * We need to use a TreeScanner, because it is not enough to visit the top-level 1263 * annotations. We also need to visit type arguments, etc. 1264 */ 1265 private class TypeAnnotate extends TreeScanner { 1266 private Env<AttrContext> env; 1267 private Symbol sym; 1268 private DiagnosticPosition deferPos; 1269 TypeAnnotate(final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos)1270 public TypeAnnotate(final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos) { 1271 this.env = env; 1272 this.sym = sym; 1273 this.deferPos = deferPos; 1274 } 1275 annotateTypeLater(final List<JCAnnotation> annotations)1276 void annotateTypeLater(final List<JCAnnotation> annotations) { 1277 if (annotations.isEmpty()) { 1278 return; 1279 } 1280 1281 final DiagnosticPosition deferPos = this.deferPos; 1282 1283 annotate.normal(new Annotate.Worker() { 1284 @Override 1285 public String toString() { 1286 return "type annotate " + annotations + " onto " + sym + " in " + sym.owner; 1287 } 1288 @Override 1289 public void run() { 1290 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1291 DiagnosticPosition prevLintPos = null; 1292 1293 if (deferPos != null) { 1294 prevLintPos = deferredLintHandler.setPos(deferPos); 1295 } 1296 try { 1297 actualEnterTypeAnnotations(annotations, env, sym); 1298 } finally { 1299 if (prevLintPos != null) 1300 deferredLintHandler.setPos(prevLintPos); 1301 log.useSource(prev); 1302 } 1303 } 1304 }); 1305 } 1306 1307 @Override visitAnnotatedType(final JCAnnotatedType tree)1308 public void visitAnnotatedType(final JCAnnotatedType tree) { 1309 annotateTypeLater(tree.annotations); 1310 super.visitAnnotatedType(tree); 1311 } 1312 1313 @Override visitTypeParameter(final JCTypeParameter tree)1314 public void visitTypeParameter(final JCTypeParameter tree) { 1315 annotateTypeLater(tree.annotations); 1316 super.visitTypeParameter(tree); 1317 } 1318 1319 @Override visitNewArray(final JCNewArray tree)1320 public void visitNewArray(final JCNewArray tree) { 1321 annotateTypeLater(tree.annotations); 1322 for (List<JCAnnotation> dimAnnos : tree.dimAnnotations) 1323 annotateTypeLater(dimAnnos); 1324 super.visitNewArray(tree); 1325 } 1326 1327 @Override visitMethodDef(final JCMethodDecl tree)1328 public void visitMethodDef(final JCMethodDecl tree) { 1329 scan(tree.mods); 1330 scan(tree.restype); 1331 scan(tree.typarams); 1332 scan(tree.recvparam); 1333 scan(tree.params); 1334 scan(tree.thrown); 1335 scan(tree.defaultValue); 1336 // Do not annotate the body, just the signature. 1337 // scan(tree.body); 1338 } 1339 1340 @Override visitVarDef(final JCVariableDecl tree)1341 public void visitVarDef(final JCVariableDecl tree) { 1342 DiagnosticPosition prevPos = deferPos; 1343 deferPos = tree.pos(); 1344 try { 1345 if (sym != null && sym.kind == Kinds.VAR) { 1346 // Don't visit a parameter once when the sym is the method 1347 // and once when the sym is the parameter. 1348 scan(tree.mods); 1349 scan(tree.vartype); 1350 } 1351 scan(tree.init); 1352 } finally { 1353 deferPos = prevPos; 1354 } 1355 } 1356 1357 @Override visitClassDef(JCClassDecl tree)1358 public void visitClassDef(JCClassDecl tree) { 1359 // We can only hit a classdef if it is declared within 1360 // a method. Ignore it - the class will be visited 1361 // separately later. 1362 } 1363 1364 @Override visitNewClass(JCNewClass tree)1365 public void visitNewClass(JCNewClass tree) { 1366 if (tree.def == null) { 1367 // For an anonymous class instantiation the class 1368 // will be visited separately. 1369 super.visitNewClass(tree); 1370 } 1371 } 1372 } 1373 1374 baseEnv(JCClassDecl tree, Env<AttrContext> env)1375 private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) { 1376 Scope baseScope = new Scope(tree.sym); 1377 //import already entered local classes into base scope 1378 for (Scope.Entry e = env.outer.info.scope.elems ; e != null ; e = e.sibling) { 1379 if (e.sym.isLocal()) { 1380 baseScope.enter(e.sym); 1381 } 1382 } 1383 //import current type-parameters into base scope 1384 if (tree.typarams != null) 1385 for (List<JCTypeParameter> typarams = tree.typarams; 1386 typarams.nonEmpty(); 1387 typarams = typarams.tail) 1388 baseScope.enter(typarams.head.type.tsym); 1389 Env<AttrContext> outer = env.outer; // the base clause can't see members of this class 1390 Env<AttrContext> localEnv = outer.dup(tree, outer.info.dup(baseScope)); 1391 localEnv.baseClause = true; 1392 localEnv.outer = outer; 1393 localEnv.info.isSelfCall = false; 1394 return localEnv; 1395 } 1396 1397 /** Enter member fields and methods of a class 1398 * @param env the environment current for the class block. 1399 */ finish(Env<AttrContext> env)1400 private void finish(Env<AttrContext> env) { 1401 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1402 try { 1403 JCClassDecl tree = (JCClassDecl)env.tree; 1404 finishClass(tree, env); 1405 } finally { 1406 log.useSource(prev); 1407 } 1408 } 1409 1410 /** Generate a base clause for an enum type. 1411 * @param pos The position for trees and diagnostics, if any 1412 * @param c The class symbol of the enum 1413 */ enumBase(int pos, ClassSymbol c)1414 private JCExpression enumBase(int pos, ClassSymbol c) { 1415 JCExpression result = make.at(pos). 1416 TypeApply(make.QualIdent(syms.enumSym), 1417 List.<JCExpression>of(make.Type(c.type))); 1418 return result; 1419 } 1420 modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected)1421 Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) { 1422 if (!t.hasTag(ERROR)) 1423 return t; 1424 1425 return new ErrorType(t.getOriginalType(), t.tsym) { 1426 private Type modelType; 1427 1428 @Override 1429 public Type getModelType() { 1430 if (modelType == null) 1431 modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree); 1432 return modelType; 1433 } 1434 }; 1435 } 1436 // where 1437 private class Synthesizer extends JCTree.Visitor { 1438 Type originalType; 1439 boolean interfaceExpected; 1440 List<ClassSymbol> synthesizedSymbols = List.nil(); 1441 Type result; 1442 Synthesizer(Type originalType, boolean interfaceExpected)1443 Synthesizer(Type originalType, boolean interfaceExpected) { 1444 this.originalType = originalType; 1445 this.interfaceExpected = interfaceExpected; 1446 } 1447 visit(JCTree tree)1448 Type visit(JCTree tree) { 1449 tree.accept(this); 1450 return result; 1451 } 1452 visit(List<? extends JCTree> trees)1453 List<Type> visit(List<? extends JCTree> trees) { 1454 ListBuffer<Type> lb = new ListBuffer<Type>(); 1455 for (JCTree t: trees) 1456 lb.append(visit(t)); 1457 return lb.toList(); 1458 } 1459 1460 @Override visitTree(JCTree tree)1461 public void visitTree(JCTree tree) { 1462 result = syms.errType; 1463 } 1464 1465 @Override visitIdent(JCIdent tree)1466 public void visitIdent(JCIdent tree) { 1467 if (!tree.type.hasTag(ERROR)) { 1468 result = tree.type; 1469 } else { 1470 result = synthesizeClass(tree.name, syms.unnamedPackage).type; 1471 } 1472 } 1473 1474 @Override visitSelect(JCFieldAccess tree)1475 public void visitSelect(JCFieldAccess tree) { 1476 if (!tree.type.hasTag(ERROR)) { 1477 result = tree.type; 1478 } else { 1479 Type selectedType; 1480 boolean prev = interfaceExpected; 1481 try { 1482 interfaceExpected = false; 1483 selectedType = visit(tree.selected); 1484 } finally { 1485 interfaceExpected = prev; 1486 } 1487 ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym); 1488 result = c.type; 1489 } 1490 } 1491 1492 @Override visitTypeApply(JCTypeApply tree)1493 public void visitTypeApply(JCTypeApply tree) { 1494 if (!tree.type.hasTag(ERROR)) { 1495 result = tree.type; 1496 } else { 1497 ClassType clazzType = (ClassType) visit(tree.clazz); 1498 if (synthesizedSymbols.contains(clazzType.tsym)) 1499 synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size()); 1500 final List<Type> actuals = visit(tree.arguments); 1501 result = new ErrorType(tree.type, clazzType.tsym) { 1502 @Override 1503 public List<Type> getTypeArguments() { 1504 return actuals; 1505 } 1506 }; 1507 } 1508 } 1509 synthesizeClass(Name name, Symbol owner)1510 ClassSymbol synthesizeClass(Name name, Symbol owner) { 1511 int flags = interfaceExpected ? INTERFACE : 0; 1512 ClassSymbol c = new ClassSymbol(flags, name, owner); 1513 c.members_field = new Scope.ErrorScope(c); 1514 c.type = new ErrorType(originalType, c) { 1515 @Override 1516 public List<Type> getTypeArguments() { 1517 return typarams_field; 1518 } 1519 }; 1520 synthesizedSymbols = synthesizedSymbols.prepend(c); 1521 return c; 1522 } 1523 synthesizeTyparams(ClassSymbol sym, int n)1524 void synthesizeTyparams(ClassSymbol sym, int n) { 1525 ClassType ct = (ClassType) sym.type; 1526 Assert.check(ct.typarams_field.isEmpty()); 1527 if (n == 1) { 1528 TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType); 1529 ct.typarams_field = ct.typarams_field.prepend(v); 1530 } else { 1531 for (int i = n; i > 0; i--) { 1532 TypeVar v = new TypeVar(names.fromString("T" + i), sym, syms.botType); 1533 ct.typarams_field = ct.typarams_field.prepend(v); 1534 } 1535 } 1536 } 1537 } 1538 1539 1540 /* *************************************************************************** 1541 * tree building 1542 ****************************************************************************/ 1543 1544 /** Generate default constructor for given class. For classes different 1545 * from java.lang.Object, this is: 1546 * 1547 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown { 1548 * super(x_0, ..., x_n) 1549 * } 1550 * 1551 * or, if based == true: 1552 * 1553 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown { 1554 * x_0.super(x_1, ..., x_n) 1555 * } 1556 * 1557 * @param make The tree factory. 1558 * @param c The class owning the default constructor. 1559 * @param argtypes The parameter types of the constructor. 1560 * @param thrown The thrown exceptions of the constructor. 1561 * @param based Is first parameter a this$n? 1562 */ DefaultConstructor(TreeMaker make, ClassSymbol c, MethodSymbol baseInit, List<Type> typarams, List<Type> argtypes, List<Type> thrown, long flags, boolean based)1563 JCTree DefaultConstructor(TreeMaker make, 1564 ClassSymbol c, 1565 MethodSymbol baseInit, 1566 List<Type> typarams, 1567 List<Type> argtypes, 1568 List<Type> thrown, 1569 long flags, 1570 boolean based) { 1571 JCTree result; 1572 if ((c.flags() & ENUM) != 0 && 1573 (types.supertype(c.type).tsym == syms.enumSym)) { 1574 // constructors of true enums are private 1575 flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR; 1576 } else 1577 flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR; 1578 if (c.name.isEmpty()) { 1579 flags |= ANONCONSTR; 1580 } 1581 Type mType = new MethodType(argtypes, null, thrown, c); 1582 Type initType = typarams.nonEmpty() ? 1583 new ForAll(typarams, mType) : 1584 mType; 1585 MethodSymbol init = new MethodSymbol(flags, names.init, 1586 initType, c); 1587 init.params = createDefaultConstructorParams(make, baseInit, init, 1588 argtypes, based); 1589 List<JCVariableDecl> params = make.Params(argtypes, init); 1590 List<JCStatement> stats = List.nil(); 1591 if (c.type != syms.objectType) { 1592 stats = stats.prepend(SuperCall(make, typarams, params, based)); 1593 } 1594 result = make.MethodDef(init, make.Block(0, stats)); 1595 return result; 1596 } 1597 createDefaultConstructorParams( TreeMaker make, MethodSymbol baseInit, MethodSymbol init, List<Type> argtypes, boolean based)1598 private List<VarSymbol> createDefaultConstructorParams( 1599 TreeMaker make, 1600 MethodSymbol baseInit, 1601 MethodSymbol init, 1602 List<Type> argtypes, 1603 boolean based) { 1604 List<VarSymbol> initParams = null; 1605 List<Type> argTypesList = argtypes; 1606 if (based) { 1607 /* In this case argtypes will have an extra type, compared to baseInit, 1608 * corresponding to the type of the enclosing instance i.e.: 1609 * 1610 * Inner i = outer.new Inner(1){} 1611 * 1612 * in the above example argtypes will be (Outer, int) and baseInit 1613 * will have parameter's types (int). So in this case we have to add 1614 * first the extra type in argtypes and then get the names of the 1615 * parameters from baseInit. 1616 */ 1617 initParams = List.nil(); 1618 VarSymbol param = new VarSymbol(PARAMETER, make.paramName(0), argtypes.head, init); 1619 initParams = initParams.append(param); 1620 argTypesList = argTypesList.tail; 1621 } 1622 if (baseInit != null && baseInit.params != null && 1623 baseInit.params.nonEmpty() && argTypesList.nonEmpty()) { 1624 initParams = (initParams == null) ? List.<VarSymbol>nil() : initParams; 1625 List<VarSymbol> baseInitParams = baseInit.params; 1626 while (baseInitParams.nonEmpty() && argTypesList.nonEmpty()) { 1627 VarSymbol param = new VarSymbol(baseInitParams.head.flags() | PARAMETER, 1628 baseInitParams.head.name, argTypesList.head, init); 1629 initParams = initParams.append(param); 1630 baseInitParams = baseInitParams.tail; 1631 argTypesList = argTypesList.tail; 1632 } 1633 } 1634 return initParams; 1635 } 1636 1637 /** Generate call to superclass constructor. This is: 1638 * 1639 * super(id_0, ..., id_n) 1640 * 1641 * or, if based == true 1642 * 1643 * id_0.super(id_1,...,id_n) 1644 * 1645 * where id_0, ..., id_n are the names of the given parameters. 1646 * 1647 * @param make The tree factory 1648 * @param params The parameters that need to be passed to super 1649 * @param typarams The type parameters that need to be passed to super 1650 * @param based Is first parameter a this$n? 1651 */ SuperCall(TreeMaker make, List<Type> typarams, List<JCVariableDecl> params, boolean based)1652 JCExpressionStatement SuperCall(TreeMaker make, 1653 List<Type> typarams, 1654 List<JCVariableDecl> params, 1655 boolean based) { 1656 JCExpression meth; 1657 if (based) { 1658 meth = make.Select(make.Ident(params.head), names._super); 1659 params = params.tail; 1660 } else { 1661 meth = make.Ident(names._super); 1662 } 1663 List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null; 1664 return make.Exec(make.Apply(typeargs, meth, make.Idents(params))); 1665 } 1666 } 1667