MemberEnter.java revision 2680:834b3d80c734
1/* 2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.comp; 27 28import java.util.Collections; 29import java.util.HashSet; 30import java.util.IdentityHashMap; 31import java.util.Set; 32 33import javax.tools.JavaFileObject; 34 35import com.sun.tools.javac.code.*; 36import com.sun.tools.javac.code.Scope.ImportFilter; 37import com.sun.tools.javac.code.Scope.NamedImportScope; 38import com.sun.tools.javac.code.Scope.StarImportScope; 39import com.sun.tools.javac.code.Scope.WriteableScope; 40import com.sun.tools.javac.jvm.*; 41import com.sun.tools.javac.tree.*; 42import com.sun.tools.javac.util.*; 43import com.sun.tools.javac.util.DefinedBy.Api; 44 45import com.sun.tools.javac.code.Symbol.*; 46import com.sun.tools.javac.code.Type.*; 47import com.sun.tools.javac.tree.JCTree.*; 48 49import static com.sun.tools.javac.code.Flags.*; 50import static com.sun.tools.javac.code.Flags.ANNOTATION; 51import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 52import static com.sun.tools.javac.code.Kinds.*; 53import static com.sun.tools.javac.code.Kinds.Kind.*; 54import static com.sun.tools.javac.code.TypeTag.CLASS; 55import static com.sun.tools.javac.code.TypeTag.ERROR; 56import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 57import static com.sun.tools.javac.tree.JCTree.Tag.*; 58 59import com.sun.tools.javac.util.Dependencies.AttributionKind; 60import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 61import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 62 63/** This is the second phase of Enter, in which classes are completed 64 * by entering their members into the class scope using 65 * MemberEnter.complete(). See Enter for an overview. 66 * 67 * <p><b>This is NOT part of any supported API. 68 * If you write code that depends on this, you do so at your own risk. 69 * This code and its internal interfaces are subject to change or 70 * deletion without notice.</b> 71 */ 72public class MemberEnter extends JCTree.Visitor implements Completer { 73 protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<>(); 74 75 /** A switch to determine whether we check for package/class conflicts 76 */ 77 final static boolean checkClash = true; 78 79 private final Names names; 80 private final Enter enter; 81 private final Log log; 82 private final Check chk; 83 private final Attr attr; 84 private final Symtab syms; 85 private final TreeMaker make; 86 private final Todo todo; 87 private final Annotate annotate; 88 private final TypeAnnotations typeAnnotations; 89 private final Types types; 90 private final JCDiagnostic.Factory diags; 91 private final Source source; 92 private final Target target; 93 private final DeferredLintHandler deferredLintHandler; 94 private final Lint lint; 95 private final TypeEnvs typeEnvs; 96 private final Dependencies dependencies; 97 98 public static MemberEnter instance(Context context) { 99 MemberEnter instance = context.get(memberEnterKey); 100 if (instance == null) 101 instance = new MemberEnter(context); 102 return instance; 103 } 104 105 protected MemberEnter(Context context) { 106 context.put(memberEnterKey, this); 107 names = Names.instance(context); 108 enter = Enter.instance(context); 109 log = Log.instance(context); 110 chk = Check.instance(context); 111 attr = Attr.instance(context); 112 syms = Symtab.instance(context); 113 make = TreeMaker.instance(context); 114 todo = Todo.instance(context); 115 annotate = Annotate.instance(context); 116 typeAnnotations = TypeAnnotations.instance(context); 117 types = Types.instance(context); 118 diags = JCDiagnostic.Factory.instance(context); 119 source = Source.instance(context); 120 target = Target.instance(context); 121 deferredLintHandler = DeferredLintHandler.instance(context); 122 lint = Lint.instance(context); 123 typeEnvs = TypeEnvs.instance(context); 124 dependencies = Dependencies.instance(context); 125 allowTypeAnnos = source.allowTypeAnnotations(); 126 } 127 128 /** Switch: support type annotations. 129 */ 130 boolean allowTypeAnnos; 131 132 /** A queue for classes whose members still need to be entered into the 133 * symbol table. 134 */ 135 ListBuffer<Env<AttrContext>> halfcompleted = new ListBuffer<>(); 136 137 /** Set to true only when the first of a set of classes is 138 * processed from the half completed queue. 139 */ 140 boolean isFirst = true; 141 142 /** A flag to disable completion from time to time during member 143 * enter, as we only need to look up types. This avoids 144 * unnecessarily deep recursion. 145 */ 146 boolean completionEnabled = true; 147 148 /* ---------- Processing import clauses ---------------- 149 */ 150 151 /** Import all classes of a class or package on demand. 152 * @param pos Position to be used for error reporting. 153 * @param tsym The class or package the members of which are imported. 154 * @param env The env in which the imported classes will be entered. 155 */ 156 private void importAll(int pos, 157 final TypeSymbol tsym, 158 Env<AttrContext> env) { 159 // Check that packages imported from exist (JLS ???). 160 if (tsym.kind == PCK && tsym.members().isEmpty() && !tsym.exists()) { 161 // If we can't find java.lang, exit immediately. 162 if (((PackageSymbol)tsym).fullname.equals(names.java_lang)) { 163 JCDiagnostic msg = diags.fragment("fatal.err.no.java.lang"); 164 throw new FatalError(msg); 165 } else { 166 log.error(DiagnosticFlag.RESOLVE_ERROR, pos, "doesnt.exist", tsym); 167 } 168 } 169 env.toplevel.starImportScope.importAll(tsym.members(), tsym.members(), typeImportFilter, false); 170 } 171 172 /** Import all static members of a class or package on demand. 173 * @param pos Position to be used for error reporting. 174 * @param tsym The class or package the members of which are imported. 175 * @param env The env in which the imported classes will be entered. 176 */ 177 private void importStaticAll(int pos, 178 final TypeSymbol tsym, 179 Env<AttrContext> env) { 180 final StarImportScope toScope = env.toplevel.starImportScope; 181 final PackageSymbol packge = env.toplevel.packge; 182 final TypeSymbol origin = tsym; 183 184 // enter imported types immediately 185 new SymbolImporter() { 186 void doImport(TypeSymbol tsym) { 187 toScope.importAll(tsym.members(), origin.members(), staticImportFilter, true); 188 } 189 }.importFrom(tsym); 190 } 191 192 /** Import statics types of a given name. Non-types are handled in Attr. 193 * @param pos Position to be used for error reporting. 194 * @param tsym The class from which the name is imported. 195 * @param name The (simple) name being imported. 196 * @param env The environment containing the named import 197 * scope to add to. 198 */ 199 private void importNamedStatic(final DiagnosticPosition pos, 200 final TypeSymbol tsym, 201 final Name name, 202 final Env<AttrContext> env) { 203 if (tsym.kind != TYP) { 204 log.error(DiagnosticFlag.RECOVERABLE, pos, "static.imp.only.classes.and.interfaces"); 205 return; 206 } 207 208 final NamedImportScope toScope = env.toplevel.namedImportScope; 209 final Scope originMembers = tsym.members(); 210 211 // enter imported types immediately 212 new SymbolImporter() { 213 void doImport(TypeSymbol tsym) { 214 Set<Symbol> maskedOut = null; 215 for (Symbol sym : tsym.members().getSymbolsByName(name)) { 216 if (sym.kind == TYP && 217 staticImportFilter.accepts(originMembers, sym) && 218 !chk.checkUniqueStaticImport(pos, env.toplevel, sym)) { 219 if (maskedOut == null) 220 maskedOut = Collections.newSetFromMap(new IdentityHashMap<Symbol, Boolean>()); 221 maskedOut.add(sym); 222 } 223 } 224 ImportFilter importFilter = maskedOut != null ? 225 new MaskedImportFilter(staticImportFilter, maskedOut) : 226 staticImportFilter; 227 toScope.importByName(tsym.members(), originMembers, name, importFilter); 228 } 229 }.importFrom(tsym); 230 } 231 //where: 232 class MaskedImportFilter implements ImportFilter { 233 234 private final ImportFilter delegate; 235 private final Set<Symbol> maskedOut; 236 237 public MaskedImportFilter(ImportFilter delegate, Set<Symbol> maskedOut) { 238 this.delegate = delegate; 239 this.maskedOut = maskedOut; 240 } 241 242 @Override 243 public boolean accepts(Scope origin, Symbol sym) { 244 return !maskedOut.contains(sym) && delegate.accepts(origin, sym); 245 } 246 } 247 abstract class SymbolImporter { 248 Set<Symbol> processed = new HashSet<>(); 249 void importFrom(TypeSymbol tsym) { 250 if (tsym == null || !processed.add(tsym)) 251 return; 252 253 // also import inherited names 254 importFrom(types.supertype(tsym.type).tsym); 255 for (Type t : types.interfaces(tsym.type)) 256 importFrom(t.tsym); 257 258 doImport(tsym); 259 } 260 abstract void doImport(TypeSymbol tsym); 261 } 262 263 /** Import given class. 264 * @param pos Position to be used for error reporting. 265 * @param tsym The class to be imported. 266 * @param env The environment containing the named import 267 * scope to add to. 268 */ 269 private void importNamed(DiagnosticPosition pos, final Symbol tsym, Env<AttrContext> env) { 270 if (tsym.kind == TYP && 271 chk.checkUniqueImport(pos, env.toplevel, tsym)) 272 env.toplevel.namedImportScope.importType(tsym.owner.members(), tsym.owner.members(), tsym); 273 } 274 275 /** Construct method type from method signature. 276 * @param typarams The method's type parameters. 277 * @param params The method's value parameters. 278 * @param res The method's result type, 279 * null if it is a constructor. 280 * @param recvparam The method's receiver parameter, 281 * null if none given; TODO: or already set here? 282 * @param thrown The method's thrown exceptions. 283 * @param env The method's (local) environment. 284 */ 285 Type signature(MethodSymbol msym, 286 List<JCTypeParameter> typarams, 287 List<JCVariableDecl> params, 288 JCTree res, 289 JCVariableDecl recvparam, 290 List<JCExpression> thrown, 291 Env<AttrContext> env) { 292 293 // Enter and attribute type parameters. 294 List<Type> tvars = enter.classEnter(typarams, env); 295 attr.attribTypeVariables(typarams, env); 296 297 // Enter and attribute value parameters. 298 ListBuffer<Type> argbuf = new ListBuffer<>(); 299 for (List<JCVariableDecl> l = params; l.nonEmpty(); l = l.tail) { 300 memberEnter(l.head, env); 301 argbuf.append(l.head.vartype.type); 302 } 303 304 // Attribute result type, if one is given. 305 Type restype = res == null ? syms.voidType : attr.attribType(res, env); 306 307 // Attribute receiver type, if one is given. 308 Type recvtype; 309 if (recvparam!=null) { 310 memberEnter(recvparam, env); 311 recvtype = recvparam.vartype.type; 312 } else { 313 recvtype = null; 314 } 315 316 // Attribute thrown exceptions. 317 ListBuffer<Type> thrownbuf = new ListBuffer<>(); 318 for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) { 319 Type exc = attr.attribType(l.head, env); 320 if (!exc.hasTag(TYPEVAR)) { 321 exc = chk.checkClassType(l.head.pos(), exc); 322 } else if (exc.tsym.owner == msym) { 323 //mark inference variables in 'throws' clause 324 exc.tsym.flags_field |= THROWS; 325 } 326 thrownbuf.append(exc); 327 } 328 MethodType mtype = new MethodType(argbuf.toList(), 329 restype, 330 thrownbuf.toList(), 331 syms.methodClass); 332 mtype.recvtype = recvtype; 333 334 return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); 335 } 336 337/* ******************************************************************** 338 * Visitor methods for member enter 339 *********************************************************************/ 340 341 ImportFilter staticImportFilter; 342 ImportFilter typeImportFilter = new ImportFilter() { 343 @Override 344 public boolean accepts(Scope origin, Symbol t) { 345 return t.kind == TYP; 346 } 347 }; 348 349 protected void memberEnter(JCCompilationUnit tree, Env<AttrContext> env) { 350 ImportFilter prevStaticImportFilter = staticImportFilter; 351 try { 352 final PackageSymbol packge = env.toplevel.packge; 353 this.staticImportFilter = new ImportFilter() { 354 @Override 355 public boolean accepts(Scope origin, Symbol sym) { 356 return sym.isStatic() && 357 chk.staticImportAccessible(sym, packge) && 358 sym.isMemberOf((TypeSymbol) origin.owner, types); 359 } 360 }; 361 memberEnter((JCTree) tree, env); 362 } finally { 363 this.staticImportFilter = prevStaticImportFilter; 364 } 365 } 366 367 /** Visitor argument: the current environment 368 */ 369 protected Env<AttrContext> env; 370 371 /** Enter field and method definitions and process import 372 * clauses, catching any completion failure exceptions. 373 */ 374 protected void memberEnter(JCTree tree, Env<AttrContext> env) { 375 Env<AttrContext> prevEnv = this.env; 376 try { 377 this.env = env; 378 tree.accept(this); 379 } catch (CompletionFailure ex) { 380 chk.completionError(tree.pos(), ex); 381 } finally { 382 this.env = prevEnv; 383 } 384 } 385 386 /** Enter members from a list of trees. 387 */ 388 void memberEnter(List<? extends JCTree> trees, Env<AttrContext> env) { 389 for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) 390 memberEnter(l.head, env); 391 } 392 393 /** Enter members for a class. 394 */ 395 void finishClass(JCClassDecl tree, Env<AttrContext> env) { 396 if ((tree.mods.flags & Flags.ENUM) != 0 && 397 (types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) { 398 addEnumMembers(tree, env); 399 } 400 memberEnter(tree.defs, env); 401 } 402 403 /** Add the implicit members for an enum type 404 * to the symbol table. 405 */ 406 private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) { 407 JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass)); 408 409 // public static T[] values() { return ???; } 410 JCMethodDecl values = make. 411 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), 412 names.values, 413 valuesType, 414 List.<JCTypeParameter>nil(), 415 List.<JCVariableDecl>nil(), 416 List.<JCExpression>nil(), // thrown 417 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), 418 null); 419 memberEnter(values, env); 420 421 // public static T valueOf(String name) { return ???; } 422 JCMethodDecl valueOf = make. 423 MethodDef(make.Modifiers(Flags.PUBLIC|Flags.STATIC), 424 names.valueOf, 425 make.Type(tree.sym.type), 426 List.<JCTypeParameter>nil(), 427 List.of(make.VarDef(make.Modifiers(Flags.PARAMETER | 428 Flags.MANDATED), 429 names.fromString("name"), 430 make.Type(syms.stringType), null)), 431 List.<JCExpression>nil(), // thrown 432 null, //make.Block(0, Tree.emptyList.prepend(make.Return(make.Ident(names._null)))), 433 null); 434 memberEnter(valueOf, env); 435 } 436 437 public void visitTopLevel(JCCompilationUnit tree) { 438 if (!tree.starImportScope.isEmpty()) { 439 // we must have already processed this toplevel 440 return; 441 } 442 443 DiagnosticPosition prevLintPos = deferredLintHandler.immediate(); 444 Lint prevLint = chk.setLint(lint); 445 446 try { 447 // Import-on-demand java.lang. 448 importAll(tree.pos, syms.enterPackage(names.java_lang), env); 449 450 // Process the package def and all import clauses. 451 memberEnter(tree.defs, env); 452 } finally { 453 chk.setLint(prevLint); 454 deferredLintHandler.setPos(prevLintPos); 455 } 456 } 457 458 public void visitPackageDef(JCPackageDecl tree) { 459 // check that no class exists with same fully qualified name as 460 // toplevel package 461 if (checkClash && tree.pid != null) { 462 Symbol p = env.toplevel.packge; 463 while (p.owner != syms.rootPackage) { 464 p.owner.complete(); // enter all class members of p 465 if (syms.classes.get(p.getQualifiedName()) != null) { 466 log.error(tree.pos, 467 "pkg.clashes.with.class.of.same.name", 468 p); 469 } 470 p = p.owner; 471 } 472 } 473 // process package annotations 474 annotate.annotateLater(tree.annotations, env, env.toplevel.packge, null); 475 } 476 477 // process the non-static imports and the static imports of types. 478 public void visitImport(JCImport tree) { 479 dependencies.push(AttributionKind.IMPORT, tree); 480 JCFieldAccess imp = (JCFieldAccess)tree.qualid; 481 Name name = TreeInfo.name(imp); 482 483 // Create a local environment pointing to this tree to disable 484 // effects of other imports in Resolve.findGlobalType 485 Env<AttrContext> localEnv = env.dup(tree); 486 487 TypeSymbol p = attr.attribImportQualifier(tree, localEnv).tsym; 488 if (name == names.asterisk) { 489 // Import on demand. 490 chk.checkCanonical(imp.selected); 491 if (tree.staticImport) 492 importStaticAll(tree.pos, p, env); 493 else 494 importAll(tree.pos, p, env); 495 } else { 496 // Named type import. 497 if (tree.staticImport) { 498 importNamedStatic(tree.pos(), p, name, localEnv); 499 chk.checkCanonical(imp.selected); 500 } else { 501 TypeSymbol c = attribImportType(imp, localEnv).tsym; 502 chk.checkCanonical(imp); 503 importNamed(tree.pos(), c, env); 504 } 505 } 506 dependencies.pop(); 507 } 508 509 public void visitMethodDef(JCMethodDecl tree) { 510 WriteableScope enclScope = enter.enterScope(env); 511 MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner); 512 m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree); 513 tree.sym = m; 514 515 //if this is a default method, add the DEFAULT flag to the enclosing interface 516 if ((tree.mods.flags & DEFAULT) != 0) { 517 m.enclClass().flags_field |= DEFAULT; 518 } 519 520 Env<AttrContext> localEnv = methodEnv(tree, env); 521 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 522 try { 523 // Compute the method type 524 m.type = signature(m, tree.typarams, tree.params, 525 tree.restype, tree.recvparam, 526 tree.thrown, 527 localEnv); 528 } finally { 529 deferredLintHandler.setPos(prevLintPos); 530 } 531 532 if (types.isSignaturePolymorphic(m)) { 533 m.flags_field |= SIGNATURE_POLYMORPHIC; 534 } 535 536 // Set m.params 537 ListBuffer<VarSymbol> params = new ListBuffer<>(); 538 JCVariableDecl lastParam = null; 539 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 540 JCVariableDecl param = lastParam = l.head; 541 params.append(Assert.checkNonNull(param.sym)); 542 } 543 m.params = params.toList(); 544 545 // mark the method varargs, if necessary 546 if (lastParam != null && (lastParam.mods.flags & Flags.VARARGS) != 0) 547 m.flags_field |= Flags.VARARGS; 548 549 localEnv.info.scope.leave(); 550 if (chk.checkUnique(tree.pos(), m, enclScope)) { 551 enclScope.enter(m); 552 } 553 554 annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); 555 // Visit the signature of the method. Note that 556 // TypeAnnotate doesn't descend into the body. 557 annotate.annotateTypeLater(tree, localEnv, m, tree.pos()); 558 559 if (tree.defaultValue != null) 560 annotateDefaultValueLater(tree.defaultValue, localEnv, m); 561 } 562 563 /** Create a fresh environment for method bodies. 564 * @param tree The method definition. 565 * @param env The environment current outside of the method definition. 566 */ 567 Env<AttrContext> methodEnv(JCMethodDecl tree, Env<AttrContext> env) { 568 Env<AttrContext> localEnv = 569 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(tree.sym))); 570 localEnv.enclMethod = tree; 571 if (tree.sym.type != null) { 572 //when this is called in the enter stage, there's no type to be set 573 localEnv.info.returnResult = attr.new ResultInfo(KindSelector.VAL, 574 tree.sym.type.getReturnType()); 575 } 576 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; 577 return localEnv; 578 } 579 580 public void visitVarDef(JCVariableDecl tree) { 581 Env<AttrContext> localEnv = env; 582 if ((tree.mods.flags & STATIC) != 0 || 583 (env.info.scope.owner.flags() & INTERFACE) != 0) { 584 localEnv = env.dup(tree, env.info.dup()); 585 localEnv.info.staticLevel++; 586 } 587 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 588 try { 589 if (TreeInfo.isEnumInit(tree)) { 590 attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); 591 } else { 592 attr.attribType(tree.vartype, localEnv); 593 if (TreeInfo.isReceiverParam(tree)) 594 checkReceiver(tree, localEnv); 595 } 596 } finally { 597 deferredLintHandler.setPos(prevLintPos); 598 } 599 600 if ((tree.mods.flags & VARARGS) != 0) { 601 //if we are entering a varargs parameter, we need to 602 //replace its type (a plain array type) with the more 603 //precise VarargsType --- we need to do it this way 604 //because varargs is represented in the tree as a 605 //modifier on the parameter declaration, and not as a 606 //distinct type of array node. 607 ArrayType atype = (ArrayType)tree.vartype.type; 608 tree.vartype.type = atype.makeVarargs(); 609 } 610 WriteableScope enclScope = enter.enterScope(env); 611 VarSymbol v = 612 new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner); 613 v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); 614 tree.sym = v; 615 if (tree.init != null) { 616 v.flags_field |= HASINIT; 617 if ((v.flags_field & FINAL) != 0 && 618 needsLazyConstValue(tree.init)) { 619 Env<AttrContext> initEnv = getInitEnv(tree, env); 620 initEnv.info.enclVar = v; 621 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); 622 } 623 } 624 if (chk.checkUnique(tree.pos(), v, enclScope)) { 625 chk.checkTransparentVar(tree.pos(), v, enclScope); 626 enclScope.enter(v); 627 } 628 629 annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); 630 annotate.annotateTypeLater(tree.vartype, localEnv, v, tree.pos()); 631 632 v.pos = tree.pos; 633 } 634 // where 635 void checkType(JCTree tree, Type type, String diag) { 636 if (!tree.type.isErroneous() && !types.isSameType(tree.type, type)) { 637 log.error(tree, diag, type, tree.type); 638 } 639 } 640 void checkReceiver(JCVariableDecl tree, Env<AttrContext> localEnv) { 641 attr.attribExpr(tree.nameexpr, localEnv); 642 MethodSymbol m = localEnv.enclMethod.sym; 643 if (m.isConstructor()) { 644 Type outertype = m.owner.owner.type; 645 if (outertype.hasTag(TypeTag.METHOD)) { 646 // we have a local inner class 647 outertype = m.owner.owner.owner.type; 648 } 649 if (outertype.hasTag(TypeTag.CLASS)) { 650 checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type"); 651 checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name"); 652 } else { 653 log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class"); 654 } 655 } else { 656 checkType(tree.vartype, m.owner.type, "incorrect.receiver.type"); 657 checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name"); 658 } 659 } 660 661 public boolean needsLazyConstValue(JCTree tree) { 662 InitTreeVisitor initTreeVisitor = new InitTreeVisitor(); 663 tree.accept(initTreeVisitor); 664 return initTreeVisitor.result; 665 } 666 667 /** Visitor class for expressions which might be constant expressions. 668 */ 669 static class InitTreeVisitor extends JCTree.Visitor { 670 671 private boolean result = true; 672 673 @Override 674 public void visitTree(JCTree tree) {} 675 676 @Override 677 public void visitNewClass(JCNewClass that) { 678 result = false; 679 } 680 681 @Override 682 public void visitNewArray(JCNewArray that) { 683 result = false; 684 } 685 686 @Override 687 public void visitLambda(JCLambda that) { 688 result = false; 689 } 690 691 @Override 692 public void visitReference(JCMemberReference that) { 693 result = false; 694 } 695 696 @Override 697 public void visitApply(JCMethodInvocation that) { 698 result = false; 699 } 700 701 @Override 702 public void visitSelect(JCFieldAccess tree) { 703 tree.selected.accept(this); 704 } 705 706 @Override 707 public void visitConditional(JCConditional tree) { 708 tree.cond.accept(this); 709 tree.truepart.accept(this); 710 tree.falsepart.accept(this); 711 } 712 713 @Override 714 public void visitParens(JCParens tree) { 715 tree.expr.accept(this); 716 } 717 718 @Override 719 public void visitTypeCast(JCTypeCast tree) { 720 tree.expr.accept(this); 721 } 722 } 723 724 /** Create a fresh environment for a variable's initializer. 725 * If the variable is a field, the owner of the environment's scope 726 * is be the variable itself, otherwise the owner is the method 727 * enclosing the variable definition. 728 * 729 * @param tree The variable definition. 730 * @param env The environment current outside of the variable definition. 731 */ 732 Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) { 733 Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup())); 734 if (tree.sym.owner.kind == TYP) { 735 localEnv.info.scope = env.info.scope.dupUnshared(tree.sym); 736 } 737 if ((tree.mods.flags & STATIC) != 0 || 738 ((env.enclClass.sym.flags() & INTERFACE) != 0 && env.enclMethod == null)) 739 localEnv.info.staticLevel++; 740 return localEnv; 741 } 742 743 /** Default member enter visitor method: do nothing 744 */ 745 public void visitTree(JCTree tree) { 746 } 747 748 public void visitErroneous(JCErroneous tree) { 749 if (tree.errs != null) 750 memberEnter(tree.errs, env); 751 } 752 753 public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { 754 Env<AttrContext> mEnv = methodEnv(tree, env); 755 mEnv.info.lint = mEnv.info.lint.augment(tree.sym); 756 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 757 mEnv.info.scope.enterIfAbsent(l.head.type.tsym); 758 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) 759 mEnv.info.scope.enterIfAbsent(l.head.sym); 760 return mEnv; 761 } 762 763 public Env<AttrContext> getInitEnv(JCVariableDecl tree, Env<AttrContext> env) { 764 Env<AttrContext> iEnv = initEnv(tree, env); 765 return iEnv; 766 } 767 768/* ******************************************************************** 769 * Type completion 770 *********************************************************************/ 771 772 Type attribImportType(JCTree tree, Env<AttrContext> env) { 773 Assert.check(completionEnabled); 774 try { 775 // To prevent deep recursion, suppress completion of some 776 // types. 777 completionEnabled = false; 778 return attr.attribType(tree, env); 779 } finally { 780 completionEnabled = true; 781 } 782 } 783 784 /** 785 * Check if a list of annotations contains a reference to 786 * java.lang.Deprecated. 787 **/ 788 private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) { 789 for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) { 790 JCAnnotation a = al.head; 791 if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty()) 792 return true; 793 } 794 return false; 795 } 796 797 /** Queue processing of an attribute default value. */ 798 void annotateDefaultValueLater(final JCExpression defaultValue, 799 final Env<AttrContext> localEnv, 800 final MethodSymbol m) { 801 annotate.normal(new Annotate.Worker() { 802 @Override 803 public String toString() { 804 return "annotate " + m.owner + "." + 805 m + " default " + defaultValue; 806 } 807 808 @Override 809 public void run() { 810 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 811 try { 812 enterDefaultValue(defaultValue, localEnv, m); 813 } finally { 814 log.useSource(prev); 815 } 816 } 817 }); 818 annotate.validate(new Annotate.Worker() { //validate annotations 819 @Override 820 public void run() { 821 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); 822 try { 823 // if default value is an annotation, check it is a well-formed 824 // annotation value (e.g. no duplicate values, no missing values, etc.) 825 chk.validateAnnotationTree(defaultValue); 826 } finally { 827 log.useSource(prev); 828 } 829 } 830 }); 831 } 832 833 /** Enter a default value for an attribute method. */ 834 private void enterDefaultValue(final JCExpression defaultValue, 835 final Env<AttrContext> localEnv, 836 final MethodSymbol m) { 837 m.defaultValue = annotate.enterAttributeValue(m.type.getReturnType(), 838 defaultValue, 839 localEnv); 840 } 841 842/* ******************************************************************** 843 * Source completer 844 *********************************************************************/ 845 846 /** Complete entering a class. 847 * @param sym The symbol of the class to be completed. 848 */ 849 public void complete(Symbol sym) throws CompletionFailure { 850 // Suppress some (recursive) MemberEnter invocations 851 if (!completionEnabled) { 852 // Re-install same completer for next time around and return. 853 Assert.check((sym.flags() & Flags.COMPOUND) == 0); 854 sym.completer = this; 855 return; 856 } 857 858 try { 859 annotate.enterStart(); 860 861 ClassSymbol c = (ClassSymbol)sym; 862 ClassType ct = (ClassType)c.type; 863 Env<AttrContext> env = typeEnvs.get(c); 864 JCClassDecl tree = (JCClassDecl)env.tree; 865 boolean wasFirst = isFirst; 866 isFirst = false; 867 868 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 869 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); 870 try { 871 dependencies.push(c); 872 873 // Save class environment for later member enter (2) processing. 874 halfcompleted.append(env); 875 876 // Mark class as not yet attributed. 877 c.flags_field |= UNATTRIBUTED; 878 879 // If this is a toplevel-class, make sure any preceding import 880 // clauses have been seen. 881 if (c.owner.kind == PCK) { 882 memberEnter(env.toplevel, env.enclosing(TOPLEVEL)); 883 todo.append(env); 884 } 885 886 if (c.owner.kind == TYP) 887 c.owner.complete(); 888 889 // create an environment for evaluating the base clauses 890 Env<AttrContext> baseEnv = baseEnv(tree, env); 891 892 if (tree.extending != null) 893 annotate.annotateTypeLater(tree.extending, baseEnv, sym, tree.pos()); 894 for (JCExpression impl : tree.implementing) 895 annotate.annotateTypeLater(impl, baseEnv, sym, tree.pos()); 896 annotate.flush(); 897 898 // Determine supertype. 899 Type supertype; 900 if (tree.extending != null) { 901 dependencies.push(AttributionKind.EXTENDS, tree.extending); 902 try { 903 supertype = attr.attribBase(tree.extending, baseEnv, 904 true, false, true); 905 } finally { 906 dependencies.pop(); 907 } 908 } else { 909 supertype = ((tree.mods.flags & Flags.ENUM) != 0) 910 ? attr.attribBase(enumBase(tree.pos, c), baseEnv, 911 true, false, false) 912 : (c.fullname == names.java_lang_Object) 913 ? Type.noType 914 : syms.objectType; 915 } 916 ct.supertype_field = modelMissingTypes(supertype, tree.extending, false); 917 918 // Determine interfaces. 919 ListBuffer<Type> interfaces = new ListBuffer<>(); 920 ListBuffer<Type> all_interfaces = null; // lazy init 921 Set<Type> interfaceSet = new HashSet<>(); 922 List<JCExpression> interfaceTrees = tree.implementing; 923 for (JCExpression iface : interfaceTrees) { 924 dependencies.push(AttributionKind.IMPLEMENTS, iface); 925 try { 926 Type it = attr.attribBase(iface, baseEnv, false, true, true); 927 if (it.hasTag(CLASS)) { 928 interfaces.append(it); 929 if (all_interfaces != null) all_interfaces.append(it); 930 chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet); 931 } else { 932 if (all_interfaces == null) 933 all_interfaces = new ListBuffer<Type>().appendList(interfaces); 934 all_interfaces.append(modelMissingTypes(it, iface, true)); 935 } 936 } finally { 937 dependencies.pop(); 938 } 939 } 940 941 if ((c.flags_field & ANNOTATION) != 0) { 942 ct.interfaces_field = List.of(syms.annotationType); 943 ct.all_interfaces_field = ct.interfaces_field; 944 } else { 945 ct.interfaces_field = interfaces.toList(); 946 ct.all_interfaces_field = (all_interfaces == null) 947 ? ct.interfaces_field : all_interfaces.toList(); 948 } 949 950 if (c.fullname == names.java_lang_Object) { 951 if (tree.extending != null) { 952 chk.checkNonCyclic(tree.extending.pos(), 953 supertype); 954 ct.supertype_field = Type.noType; 955 } 956 else if (tree.implementing.nonEmpty()) { 957 chk.checkNonCyclic(tree.implementing.head.pos(), 958 ct.interfaces_field.head); 959 ct.interfaces_field = List.nil(); 960 } 961 } 962 963 // Annotations. 964 // In general, we cannot fully process annotations yet, but we 965 // can attribute the annotation types and then check to see if the 966 // @Deprecated annotation is present. 967 attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); 968 if (hasDeprecatedAnnotation(tree.mods.annotations)) 969 c.flags_field |= DEPRECATED; 970 annotate.annotateLater(tree.mods.annotations, baseEnv, 971 c, tree.pos()); 972 973 chk.checkNonCyclicDecl(tree); 974 975 // class type parameters use baseEnv but everything uses env 976 attr.attribTypeVariables(tree.typarams, baseEnv); 977 for (JCTypeParameter tp : tree.typarams) 978 annotate.annotateTypeLater(tp, baseEnv, sym, tree.pos()); 979 980 // Add default constructor if needed. 981 if ((c.flags() & INTERFACE) == 0 && 982 !TreeInfo.hasConstructors(tree.defs)) { 983 List<Type> argtypes = List.nil(); 984 List<Type> typarams = List.nil(); 985 List<Type> thrown = List.nil(); 986 long ctorFlags = 0; 987 boolean based = false; 988 boolean addConstructor = true; 989 JCNewClass nc = null; 990 if (c.name.isEmpty()) { 991 nc = (JCNewClass)env.next.tree; 992 if (nc.constructor != null) { 993 addConstructor = nc.constructor.kind != ERR; 994 Type superConstrType = types.memberType(c.type, 995 nc.constructor); 996 argtypes = superConstrType.getParameterTypes(); 997 typarams = superConstrType.getTypeArguments(); 998 ctorFlags = nc.constructor.flags() & VARARGS; 999 if (nc.encl != null) { 1000 argtypes = argtypes.prepend(nc.encl.type); 1001 based = true; 1002 } 1003 thrown = superConstrType.getThrownTypes(); 1004 } 1005 } 1006 if (addConstructor) { 1007 MethodSymbol basedConstructor = nc != null ? 1008 (MethodSymbol)nc.constructor : null; 1009 JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, 1010 basedConstructor, 1011 typarams, argtypes, thrown, 1012 ctorFlags, based); 1013 tree.defs = tree.defs.prepend(constrDef); 1014 } 1015 } 1016 1017 // enter symbols for 'this' into current scope. 1018 VarSymbol thisSym = 1019 new VarSymbol(FINAL | HASINIT, names._this, c.type, c); 1020 thisSym.pos = Position.FIRSTPOS; 1021 env.info.scope.enter(thisSym); 1022 // if this is a class, enter symbol for 'super' into current scope. 1023 if ((c.flags_field & INTERFACE) == 0 && 1024 ct.supertype_field.hasTag(CLASS)) { 1025 VarSymbol superSym = 1026 new VarSymbol(FINAL | HASINIT, names._super, 1027 ct.supertype_field, c); 1028 superSym.pos = Position.FIRSTPOS; 1029 env.info.scope.enter(superSym); 1030 } 1031 1032 // check that no package exists with same fully qualified name, 1033 // but admit classes in the unnamed package which have the same 1034 // name as a top-level package. 1035 if (checkClash && 1036 c.owner.kind == PCK && c.owner != syms.unnamedPackage && 1037 syms.packageExists(c.fullname)) { 1038 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c); 1039 } 1040 if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 && 1041 !env.toplevel.sourcefile.isNameCompatible(c.name.toString(),JavaFileObject.Kind.SOURCE)) { 1042 c.flags_field |= AUXILIARY; 1043 } 1044 } catch (CompletionFailure ex) { 1045 chk.completionError(tree.pos(), ex); 1046 } finally { 1047 deferredLintHandler.setPos(prevLintPos); 1048 log.useSource(prev); 1049 dependencies.pop(); 1050 } 1051 1052 // Enter all member fields and methods of a set of half completed 1053 // classes in a second phase. 1054 if (wasFirst) { 1055 Set<JCCompilationUnit> topLevels = new HashSet<>(); 1056 try { 1057 while (halfcompleted.nonEmpty()) { 1058 Env<AttrContext> toFinish = halfcompleted.next(); 1059 topLevels.add(toFinish.toplevel); 1060 finish(toFinish); 1061 if (allowTypeAnnos) { 1062 typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree); 1063 typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl)toFinish.tree); 1064 } 1065 } 1066 } finally { 1067 isFirst = true; 1068 } 1069 1070 for (JCCompilationUnit toplevel : topLevels) { 1071 chk.checkImportsResolvable(toplevel); 1072 } 1073 1074 } 1075 } finally { 1076 annotate.enterDone(); 1077 } 1078 } 1079 1080 private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) { 1081 WriteableScope baseScope = WriteableScope.create(tree.sym); 1082 //import already entered local classes into base scope 1083 for (Symbol sym : env.outer.info.scope.getSymbols(NON_RECURSIVE)) { 1084 if (sym.isLocal()) { 1085 baseScope.enter(sym); 1086 } 1087 } 1088 //import current type-parameters into base scope 1089 if (tree.typarams != null) 1090 for (List<JCTypeParameter> typarams = tree.typarams; 1091 typarams.nonEmpty(); 1092 typarams = typarams.tail) 1093 baseScope.enter(typarams.head.type.tsym); 1094 Env<AttrContext> outer = env.outer; // the base clause can't see members of this class 1095 Env<AttrContext> localEnv = outer.dup(tree, outer.info.dup(baseScope)); 1096 localEnv.baseClause = true; 1097 localEnv.outer = outer; 1098 localEnv.info.isSelfCall = false; 1099 return localEnv; 1100 } 1101 1102 /** Enter member fields and methods of a class 1103 * @param env the environment current for the class block. 1104 */ 1105 private void finish(Env<AttrContext> env) { 1106 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1107 try { 1108 JCClassDecl tree = (JCClassDecl)env.tree; 1109 finishClass(tree, env); 1110 } finally { 1111 log.useSource(prev); 1112 } 1113 } 1114 1115 /** Generate a base clause for an enum type. 1116 * @param pos The position for trees and diagnostics, if any 1117 * @param c The class symbol of the enum 1118 */ 1119 private JCExpression enumBase(int pos, ClassSymbol c) { 1120 JCExpression result = make.at(pos). 1121 TypeApply(make.QualIdent(syms.enumSym), 1122 List.<JCExpression>of(make.Type(c.type))); 1123 return result; 1124 } 1125 1126 Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) { 1127 if (!t.hasTag(ERROR)) 1128 return t; 1129 1130 return new ErrorType(t.getOriginalType(), t.tsym) { 1131 private Type modelType; 1132 1133 @Override 1134 public Type getModelType() { 1135 if (modelType == null) 1136 modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree); 1137 return modelType; 1138 } 1139 }; 1140 } 1141 // where 1142 private class Synthesizer extends JCTree.Visitor { 1143 Type originalType; 1144 boolean interfaceExpected; 1145 List<ClassSymbol> synthesizedSymbols = List.nil(); 1146 Type result; 1147 1148 Synthesizer(Type originalType, boolean interfaceExpected) { 1149 this.originalType = originalType; 1150 this.interfaceExpected = interfaceExpected; 1151 } 1152 1153 Type visit(JCTree tree) { 1154 tree.accept(this); 1155 return result; 1156 } 1157 1158 List<Type> visit(List<? extends JCTree> trees) { 1159 ListBuffer<Type> lb = new ListBuffer<>(); 1160 for (JCTree t: trees) 1161 lb.append(visit(t)); 1162 return lb.toList(); 1163 } 1164 1165 @Override 1166 public void visitTree(JCTree tree) { 1167 result = syms.errType; 1168 } 1169 1170 @Override 1171 public void visitIdent(JCIdent tree) { 1172 if (!tree.type.hasTag(ERROR)) { 1173 result = tree.type; 1174 } else { 1175 result = synthesizeClass(tree.name, syms.unnamedPackage).type; 1176 } 1177 } 1178 1179 @Override 1180 public void visitSelect(JCFieldAccess tree) { 1181 if (!tree.type.hasTag(ERROR)) { 1182 result = tree.type; 1183 } else { 1184 Type selectedType; 1185 boolean prev = interfaceExpected; 1186 try { 1187 interfaceExpected = false; 1188 selectedType = visit(tree.selected); 1189 } finally { 1190 interfaceExpected = prev; 1191 } 1192 ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym); 1193 result = c.type; 1194 } 1195 } 1196 1197 @Override 1198 public void visitTypeApply(JCTypeApply tree) { 1199 if (!tree.type.hasTag(ERROR)) { 1200 result = tree.type; 1201 } else { 1202 ClassType clazzType = (ClassType) visit(tree.clazz); 1203 if (synthesizedSymbols.contains(clazzType.tsym)) 1204 synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size()); 1205 final List<Type> actuals = visit(tree.arguments); 1206 result = new ErrorType(tree.type, clazzType.tsym) { 1207 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1208 public List<Type> getTypeArguments() { 1209 return actuals; 1210 } 1211 }; 1212 } 1213 } 1214 1215 ClassSymbol synthesizeClass(Name name, Symbol owner) { 1216 int flags = interfaceExpected ? INTERFACE : 0; 1217 ClassSymbol c = new ClassSymbol(flags, name, owner); 1218 c.members_field = new Scope.ErrorScope(c); 1219 c.type = new ErrorType(originalType, c) { 1220 @Override @DefinedBy(Api.LANGUAGE_MODEL) 1221 public List<Type> getTypeArguments() { 1222 return typarams_field; 1223 } 1224 }; 1225 synthesizedSymbols = synthesizedSymbols.prepend(c); 1226 return c; 1227 } 1228 1229 void synthesizeTyparams(ClassSymbol sym, int n) { 1230 ClassType ct = (ClassType) sym.type; 1231 Assert.check(ct.typarams_field.isEmpty()); 1232 if (n == 1) { 1233 TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType); 1234 ct.typarams_field = ct.typarams_field.prepend(v); 1235 } else { 1236 for (int i = n; i > 0; i--) { 1237 TypeVar v = new TypeVar(names.fromString("T" + i), sym, 1238 syms.botType); 1239 ct.typarams_field = ct.typarams_field.prepend(v); 1240 } 1241 } 1242 } 1243 } 1244 1245 1246/* *************************************************************************** 1247 * tree building 1248 ****************************************************************************/ 1249 1250 /** Generate default constructor for given class. For classes different 1251 * from java.lang.Object, this is: 1252 * 1253 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown { 1254 * super(x_0, ..., x_n) 1255 * } 1256 * 1257 * or, if based == true: 1258 * 1259 * c(argtype_0 x_0, ..., argtype_n x_n) throws thrown { 1260 * x_0.super(x_1, ..., x_n) 1261 * } 1262 * 1263 * @param make The tree factory. 1264 * @param c The class owning the default constructor. 1265 * @param argtypes The parameter types of the constructor. 1266 * @param thrown The thrown exceptions of the constructor. 1267 * @param based Is first parameter a this$n? 1268 */ 1269 JCTree DefaultConstructor(TreeMaker make, 1270 ClassSymbol c, 1271 MethodSymbol baseInit, 1272 List<Type> typarams, 1273 List<Type> argtypes, 1274 List<Type> thrown, 1275 long flags, 1276 boolean based) { 1277 JCTree result; 1278 if ((c.flags() & ENUM) != 0 && 1279 (types.supertype(c.type).tsym == syms.enumSym)) { 1280 // constructors of true enums are private 1281 flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR; 1282 } else 1283 flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR; 1284 if (c.name.isEmpty()) { 1285 flags |= ANONCONSTR; 1286 } 1287 Type mType = new MethodType(argtypes, null, thrown, c); 1288 Type initType = typarams.nonEmpty() ? 1289 new ForAll(typarams, mType) : 1290 mType; 1291 MethodSymbol init = new MethodSymbol(flags, names.init, 1292 initType, c); 1293 init.params = createDefaultConstructorParams(make, baseInit, init, 1294 argtypes, based); 1295 List<JCVariableDecl> params = make.Params(argtypes, init); 1296 List<JCStatement> stats = List.nil(); 1297 if (c.type != syms.objectType) { 1298 stats = stats.prepend(SuperCall(make, typarams, params, based)); 1299 } 1300 result = make.MethodDef(init, make.Block(0, stats)); 1301 return result; 1302 } 1303 1304 private List<VarSymbol> createDefaultConstructorParams( 1305 TreeMaker make, 1306 MethodSymbol baseInit, 1307 MethodSymbol init, 1308 List<Type> argtypes, 1309 boolean based) { 1310 List<VarSymbol> initParams = null; 1311 List<Type> argTypesList = argtypes; 1312 if (based) { 1313 /* In this case argtypes will have an extra type, compared to baseInit, 1314 * corresponding to the type of the enclosing instance i.e.: 1315 * 1316 * Inner i = outer.new Inner(1){} 1317 * 1318 * in the above example argtypes will be (Outer, int) and baseInit 1319 * will have parameter's types (int). So in this case we have to add 1320 * first the extra type in argtypes and then get the names of the 1321 * parameters from baseInit. 1322 */ 1323 initParams = List.nil(); 1324 VarSymbol param = new VarSymbol(PARAMETER, make.paramName(0), argtypes.head, init); 1325 initParams = initParams.append(param); 1326 argTypesList = argTypesList.tail; 1327 } 1328 if (baseInit != null && baseInit.params != null && 1329 baseInit.params.nonEmpty() && argTypesList.nonEmpty()) { 1330 initParams = (initParams == null) ? List.<VarSymbol>nil() : initParams; 1331 List<VarSymbol> baseInitParams = baseInit.params; 1332 while (baseInitParams.nonEmpty() && argTypesList.nonEmpty()) { 1333 VarSymbol param = new VarSymbol(baseInitParams.head.flags() | PARAMETER, 1334 baseInitParams.head.name, argTypesList.head, init); 1335 initParams = initParams.append(param); 1336 baseInitParams = baseInitParams.tail; 1337 argTypesList = argTypesList.tail; 1338 } 1339 } 1340 return initParams; 1341 } 1342 1343 /** Generate call to superclass constructor. This is: 1344 * 1345 * super(id_0, ..., id_n) 1346 * 1347 * or, if based == true 1348 * 1349 * id_0.super(id_1,...,id_n) 1350 * 1351 * where id_0, ..., id_n are the names of the given parameters. 1352 * 1353 * @param make The tree factory 1354 * @param params The parameters that need to be passed to super 1355 * @param typarams The type parameters that need to be passed to super 1356 * @param based Is first parameter a this$n? 1357 */ 1358 JCExpressionStatement SuperCall(TreeMaker make, 1359 List<Type> typarams, 1360 List<JCVariableDecl> params, 1361 boolean based) { 1362 JCExpression meth; 1363 if (based) { 1364 meth = make.Select(make.Ident(params.head), names._super); 1365 params = params.tail; 1366 } else { 1367 meth = make.Ident(names._super); 1368 } 1369 List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null; 1370 return make.Exec(make.Apply(typeargs, meth, make.Idents(params))); 1371 } 1372} 1373