1 /* 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.comp; 27 28 import java.util.*; 29 import javax.tools.JavaFileObject; 30 import javax.tools.JavaFileManager; 31 32 import com.sun.tools.javac.code.*; 33 import com.sun.tools.javac.code.Scope.*; 34 import com.sun.tools.javac.code.Symbol.*; 35 import com.sun.tools.javac.code.Type.*; 36 import com.sun.tools.javac.jvm.*; 37 import com.sun.tools.javac.main.RecognizedOptions.PkgInfo; 38 import com.sun.tools.javac.tree.*; 39 import com.sun.tools.javac.tree.JCTree.*; 40 import com.sun.tools.javac.util.*; 41 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 42 import com.sun.tools.javac.util.List; 43 44 45 import static com.sun.tools.javac.code.Flags.*; 46 import static com.sun.tools.javac.code.Kinds.*; 47 48 /** This class enters symbols for all encountered definitions into 49 * the symbol table. The pass consists of two phases, organized as 50 * follows: 51 * 52 * <p>In the first phase, all class symbols are intered into their 53 * enclosing scope, descending recursively down the tree for classes 54 * which are members of other classes. The class symbols are given a 55 * MemberEnter object as completer. 56 * 57 * <p>In the second phase classes are completed using 58 * MemberEnter.complete(). Completion might occur on demand, but 59 * any classes that are not completed that way will be eventually 60 * completed by processing the `uncompleted' queue. Completion 61 * entails (1) determination of a class's parameters, supertype and 62 * interfaces, as well as (2) entering all symbols defined in the 63 * class into its scope, with the exception of class symbols which 64 * have been entered in phase 1. (2) depends on (1) having been 65 * completed for a class and all its superclasses and enclosing 66 * classes. That's why, after doing (1), we put classes in a 67 * `halfcompleted' queue. Only when we have performed (1) for a class 68 * and all it's superclasses and enclosing classes, we proceed to 69 * (2). 70 * 71 * <p>Whereas the first phase is organized as a sweep through all 72 * compiled syntax trees, the second phase is demand. Members of a 73 * class are entered when the contents of a class are first 74 * accessed. This is accomplished by installing completer objects in 75 * class symbols for compiled classes which invoke the member-enter 76 * phase for the corresponding class tree. 77 * 78 * <p>Classes migrate from one phase to the next via queues: 79 * 80 * <pre> 81 * class enter -> (Enter.uncompleted) --> member enter (1) 82 * -> (MemberEnter.halfcompleted) --> member enter (2) 83 * -> (Todo) --> attribute 84 * (only for toplevel classes) 85 * </pre> 86 * 87 * <p><b>This is NOT part of any supported API. 88 * If you write code that depends on this, you do so at your own risk. 89 * This code and its internal interfaces are subject to change or 90 * deletion without notice.</b> 91 */ 92 public class Enter extends JCTree.Visitor { 93 protected static final Context.Key<Enter> enterKey = 94 new Context.Key<Enter>(); 95 96 Log log; 97 Symtab syms; 98 Check chk; 99 TreeMaker make; 100 ClassReader reader; 101 Annotate annotate; 102 MemberEnter memberEnter; 103 Types types; 104 Lint lint; 105 Names names; 106 JavaFileManager fileManager; 107 PkgInfo pkginfoOpt; 108 109 private final Todo todo; 110 111 public static Enter instance(Context context) { 112 Enter instance = context.get(enterKey); 113 if (instance == null) 114 instance = new Enter(context); 115 return instance; 116 } 117 118 protected Enter(Context context) { 119 context.put(enterKey, this); 120 121 log = Log.instance(context); 122 reader = ClassReader.instance(context); 123 make = TreeMaker.instance(context); 124 syms = Symtab.instance(context); 125 chk = Check.instance(context); 126 memberEnter = MemberEnter.instance(context); 127 types = Types.instance(context); 128 annotate = Annotate.instance(context); 129 lint = Lint.instance(context); 130 names = Names.instance(context); 131 132 predefClassDef = make.ClassDef( 133 make.Modifiers(PUBLIC), 134 syms.predefClass.name, null, null, null, null); 135 predefClassDef.sym = syms.predefClass; 136 todo = Todo.instance(context); 137 fileManager = context.get(JavaFileManager.class); 138 139 Options options = Options.instance(context); 140 pkginfoOpt = PkgInfo.get(options); 141 } 142 143 /** A hashtable mapping classes and packages to the environments current 144 * at the points of their definitions. 145 */ 146 Map<TypeSymbol,Env<AttrContext>> typeEnvs = 147 new HashMap<TypeSymbol,Env<AttrContext>>(); 148 149 /** Accessor for typeEnvs 150 */ 151 public Env<AttrContext> getEnv(TypeSymbol sym) { 152 return typeEnvs.get(sym); 153 } 154 155 public Env<AttrContext> getClassEnv(TypeSymbol sym) { 156 Env<AttrContext> localEnv = getEnv(sym); 157 Env<AttrContext> lintEnv = localEnv; 158 while (lintEnv.info.lint == null) 159 lintEnv = lintEnv.next; 160 localEnv.info.lint = lintEnv.info.lint.augment(sym.attributes_field, sym.flags()); 161 return localEnv; 162 } 163 164 /** The queue of all classes that might still need to be completed; 165 * saved and initialized by main(). 166 */ 167 ListBuffer<ClassSymbol> uncompleted; 168 169 /** A dummy class to serve as enclClass for toplevel environments. 170 */ 171 private JCClassDecl predefClassDef; 172 173 /* ************************************************************************ 174 * environment construction 175 *************************************************************************/ 176 177 178 /** Create a fresh environment for class bodies. 179 * This will create a fresh scope for local symbols of a class, referred 180 * to by the environments info.scope field. 181 * This scope will contain 182 * - symbols for this and super 183 * - symbols for any type parameters 184 * In addition, it serves as an anchor for scopes of methods and initializers 185 * which are nested in this scope via Scope.dup(). 186 * This scope should not be confused with the members scope of a class. 187 * 188 * @param tree The class definition. 189 * @param env The environment current outside of the class definition. 190 */ 191 public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) { 192 Env<AttrContext> localEnv = 193 env.dup(tree, env.info.dup(new Scope(tree.sym))); 194 localEnv.enclClass = tree; 195 localEnv.outer = env; 196 localEnv.info.isSelfCall = false; 197 localEnv.info.lint = null; // leave this to be filled in by Attr, 198 // when annotations have been processed 199 return localEnv; 200 } 201 202 /** Create a fresh environment for toplevels. 203 * @param tree The toplevel tree. 204 */ 205 Env<AttrContext> topLevelEnv(JCCompilationUnit tree) { 206 Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext()); 207 localEnv.toplevel = tree; 208 localEnv.enclClass = predefClassDef; 209 tree.namedImportScope = new ImportScope(tree.packge); 210 tree.starImportScope = new StarImportScope(tree.packge); 211 localEnv.info.scope = tree.namedImportScope; 212 localEnv.info.lint = lint; 213 return localEnv; 214 } 215 216 public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) { 217 Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext()); 218 localEnv.toplevel = tree; 219 localEnv.enclClass = predefClassDef; 220 localEnv.info.scope = tree.namedImportScope; 221 localEnv.info.lint = lint; 222 return localEnv; 223 } 224 225 /** The scope in which a member definition in environment env is to be entered 226 * This is usually the environment's scope, except for class environments, 227 * where the local scope is for type variables, and the this and super symbol 228 * only, and members go into the class member scope. 229 */ 230 Scope enterScope(Env<AttrContext> env) { 231 return (env.tree.getTag() == JCTree.CLASSDEF) 232 ? ((JCClassDecl) env.tree).sym.members_field 233 : env.info.scope; 234 } 235 236 /* ************************************************************************ 237 * Visitor methods for phase 1: class enter 238 *************************************************************************/ 239 240 /** Visitor argument: the current environment. 241 */ 242 protected Env<AttrContext> env; 243 244 /** Visitor result: the computed type. 245 */ 246 Type result; 247 248 /** Visitor method: enter all classes in given tree, catching any 249 * completion failure exceptions. Return the tree's type. 250 * 251 * @param tree The tree to be visited. 252 * @param env The environment visitor argument. 253 */ 254 Type classEnter(JCTree tree, Env<AttrContext> env) { 255 Env<AttrContext> prevEnv = this.env; 256 try { 257 this.env = env; 258 tree.accept(this); 259 return result; 260 } catch (CompletionFailure ex) { 261 return chk.completionError(tree.pos(), ex); 262 } finally { 263 this.env = prevEnv; 264 } 265 } 266 267 /** Visitor method: enter classes of a list of trees, returning a list of types. 268 */ 269 <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) { 270 ListBuffer<Type> ts = new ListBuffer<Type>(); 271 for (List<T> l = trees; l.nonEmpty(); l = l.tail) { 272 Type t = classEnter(l.head, env); 273 if (t != null) 274 ts.append(t); 275 } 276 return ts.toList(); 277 } 278 279 @Override 280 public void visitTopLevel(JCCompilationUnit tree) { 281 JavaFileObject prev = log.useSource(tree.sourcefile); 282 boolean addEnv = false; 283 boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", 284 JavaFileObject.Kind.SOURCE); 285 if (tree.pid != null) { 286 tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); 287 if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) { 288 if (isPkgInfo) { 289 addEnv = true; 290 } else { 291 log.error(tree.packageAnnotations.head.pos(), 292 "pkg.annotations.sb.in.package-info.java"); 293 } 294 } 295 } else { 296 tree.packge = syms.unnamedPackage; 297 } 298 tree.packge.complete(); // Find all classes in package. 299 Env<AttrContext> topEnv = topLevelEnv(tree); 300 301 // Save environment of package-info.java file. 302 if (isPkgInfo) { 303 Env<AttrContext> env0 = typeEnvs.get(tree.packge); 304 if (env0 == null) { 305 typeEnvs.put(tree.packge, topEnv); 306 } else { 307 JCCompilationUnit tree0 = env0.toplevel; 308 if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) { 309 log.warning(tree.pid != null ? tree.pid.pos() 310 : null, 311 "pkg-info.already.seen", 312 tree.packge); 313 if (addEnv || (tree0.packageAnnotations.isEmpty() && 314 tree.docComments != null && 315 tree.docComments.get(tree) != null)) { 316 typeEnvs.put(tree.packge, topEnv); 317 } 318 } 319 } 320 321 for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner) 322 q.flags_field |= EXISTS; 323 324 Name name = names.package_info; 325 ClassSymbol c = reader.enterClass(name, tree.packge); 326 c.flatname = names.fromString(tree.packge + "." + name); 327 c.sourcefile = tree.sourcefile; 328 c.completer = null; 329 c.members_field = new Scope(c); 330 tree.packge.package_info = c; 331 } 332 classEnter(tree.defs, topEnv); 333 if (addEnv) { 334 todo.append(topEnv); 335 } 336 log.useSource(prev); 337 result = null; 338 } 339 340 @Override 341 public void visitClassDef(JCClassDecl tree) { 342 Symbol owner = env.info.scope.owner; 343 Scope enclScope = enterScope(env); 344 ClassSymbol c; 345 if (owner.kind == PCK) { 346 // We are seeing a toplevel class. 347 PackageSymbol packge = (PackageSymbol)owner; 348 for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner) 349 q.flags_field |= EXISTS; 350 c = reader.enterClass(tree.name, packge); 351 packge.members().enterIfAbsent(c); 352 if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) { 353 log.error(tree.pos(), 354 "class.public.should.be.in.file", tree.name); 355 } 356 } else { 357 if (!tree.name.isEmpty() && 358 !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) { 359 result = null; 360 return; 361 } 362 if (owner.kind == TYP) { 363 // We are seeing a member class. 364 c = reader.enterClass(tree.name, (TypeSymbol)owner); 365 if ((owner.flags_field & INTERFACE) != 0) { 366 tree.mods.flags |= PUBLIC | STATIC; 367 } 368 } else { 369 // We are seeing a local class. 370 c = reader.defineClass(tree.name, owner); 371 c.flatname = chk.localClassName(c); 372 if (!c.name.isEmpty()) 373 chk.checkTransparentClass(tree.pos(), c, env.info.scope); 374 } 375 } 376 tree.sym = c; 377 378 // Enter class into `compiled' table and enclosing scope. 379 if (chk.compiled.get(c.flatname) != null) { 380 duplicateClass(tree.pos(), c); 381 result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType); 382 tree.sym = (ClassSymbol)result.tsym; 383 return; 384 } 385 chk.compiled.put(c.flatname, c); 386 enclScope.enter(c); 387 388 // Set up an environment for class block and store in `typeEnvs' 389 // table, to be retrieved later in memberEnter and attribution. 390 Env<AttrContext> localEnv = classEnv(tree, env); 391 typeEnvs.put(c, localEnv); 392 393 // Fill out class fields. 394 c.completer = memberEnter; 395 c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree); 396 c.sourcefile = env.toplevel.sourcefile; 397 c.members_field = new Scope(c); 398 399 ClassType ct = (ClassType)c.type; 400 if (owner.kind != PCK && (c.flags_field & STATIC) == 0) { 401 // We are seeing a local or inner class. 402 // Set outer_field of this class to closest enclosing class 403 // which contains this class in a non-static context 404 // (its "enclosing instance class"), provided such a class exists. 405 Symbol owner1 = owner; 406 while ((owner1.kind & (VAR | MTH)) != 0 && 407 (owner1.flags_field & STATIC) == 0) { 408 owner1 = owner1.owner; 409 } 410 if (owner1.kind == TYP) { 411 ct.setEnclosingType(owner1.type); 412 } 413 } 414 415 // Enter type parameters. 416 ct.typarams_field = classEnter(tree.typarams, localEnv); 417 418 // Add non-local class to uncompleted, to make sure it will be 419 // completed later. 420 if (!c.isLocal() && uncompleted != null) uncompleted.append(c); 421 // System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG 422 423 // Recursively enter all member classes. 424 classEnter(tree.defs, localEnv); 425 426 result = c.type; 427 } 428 //where 429 /** Does class have the same name as the file it appears in? 430 */ 431 private static boolean classNameMatchesFileName(ClassSymbol c, 432 Env<AttrContext> env) { 433 return env.toplevel.sourcefile.isNameCompatible(c.name.toString(), 434 JavaFileObject.Kind.SOURCE); 435 } 436 437 /** Complain about a duplicate class. */ 438 protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) { 439 log.error(pos, "duplicate.class", c.fullname); 440 } 441 442 /** Class enter visitor method for type parameters. 443 * Enter a symbol for type parameter in local scope, after checking that it 444 * is unique. 445 */ 446 @Override 447 public void visitTypeParameter(JCTypeParameter tree) { 448 TypeVar a = (tree.type != null) 449 ? (TypeVar)tree.type 450 : new TypeVar(tree.name, env.info.scope.owner, syms.botType); 451 tree.type = a; 452 if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) { 453 env.info.scope.enter(a.tsym); 454 } 455 result = a; 456 } 457 458 /** Default class enter visitor method: do nothing. 459 */ 460 @Override 461 public void visitTree(JCTree tree) { 462 result = null; 463 } 464 465 /** Main method: enter all classes in a list of toplevel trees. 466 * @param trees The list of trees to be processed. 467 */ 468 public void main(List<JCCompilationUnit> trees) { 469 complete(trees, null); 470 } 471 472 /** Main method: enter one class from a list of toplevel trees and 473 * place the rest on uncompleted for later processing. 474 * @param trees The list of trees to be processed. 475 * @param c The class symbol to be processed. 476 */ 477 public void complete(List<JCCompilationUnit> trees, ClassSymbol c) { 478 annotate.enterStart(); 479 ListBuffer<ClassSymbol> prevUncompleted = uncompleted; 480 if (memberEnter.completionEnabled) uncompleted = new ListBuffer<ClassSymbol>(); 481 482 try { 483 // enter all classes, and construct uncompleted list 484 classEnter(trees, null); 485 486 // complete all uncompleted classes in memberEnter 487 if (memberEnter.completionEnabled) { 488 while (uncompleted.nonEmpty()) { 489 ClassSymbol clazz = uncompleted.next(); 490 if (c == null || c == clazz || prevUncompleted == null) 491 clazz.complete(); 492 else 493 // defer 494 prevUncompleted.append(clazz); 495 } 496 497 // if there remain any unimported toplevels (these must have 498 // no classes at all), process their import statements as well. 499 for (JCCompilationUnit tree : trees) { 500 if (tree.starImportScope.elems == null) { 501 JavaFileObject prev = log.useSource(tree.sourcefile); 502 Env<AttrContext> topEnv = topLevelEnv(tree); 503 memberEnter.memberEnter(tree, topEnv); 504 log.useSource(prev); 505 } 506 } 507 } 508 } finally { 509 uncompleted = prevUncompleted; 510 annotate.enterDone(); 511 } 512 } 513 }