| 1 | /* | 
| 2 |  * Copyright 1999-2006 Sun Microsystems, Inc.  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.  Sun designates this | 
| 8 |  * particular file as subject to the "Classpath" exception as provided | 
| 9 |  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 
| 22 |  * CA 95054 USA or visit www.sun.com if you need additional information or | 
| 23 |  * have any questions. | 
| 24 |  */ | 
| 25 |   | 
| 26 | package com.sun.tools.javac.comp; | 
| 27 |   | 
| 28 | import java.util.*; | 
| 29 | import java.util.Set; | 
| 30 | import javax.tools.JavaFileObject; | 
| 31 | import javax.tools.JavaFileManager; | 
| 32 |   | 
| 33 | import com.sun.tools.javac.code.*; | 
| 34 | import com.sun.tools.javac.jvm.*; | 
| 35 | import com.sun.tools.javac.tree.*; | 
| 36 | import com.sun.tools.javac.util.*; | 
| 37 | import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; | 
| 38 | import com.sun.tools.javac.util.List; | 
| 39 |   | 
| 40 | import com.sun.tools.javac.code.Type.*; | 
| 41 | import com.sun.tools.javac.code.Symbol.*; | 
| 42 | import com.sun.tools.javac.tree.JCTree.*; | 
| 43 |   | 
| 44 | import static com.sun.tools.javac.code.Flags.*; | 
| 45 | import static com.sun.tools.javac.code.Kinds.*; | 
| 46 | import static com.sun.tools.javac.code.TypeTags.*; | 
| 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 API supported by Sun Microsystems.  If | 
| 88 |  *  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 |     Lint lint; | 
| 104 |     JavaFileManager fileManager; | 
| 105 |   | 
| 106 |     private final Todo todo; | 
| 107 |   | 
| 108 |     public static Enter instance(Context context) { | 
| 109 |         Enter instance = context.get(enterKey); | 
| 110 |         if (instance == null) | 
| 111 |             instance = new Enter(context); | 
| 112 |         return instance; | 
| 113 |     } | 
| 114 |   | 
| 115 |     protected Enter(Context context) { | 
| 116 |         context.put(enterKey, this); | 
| 117 |   | 
| 118 |         log = Log.instance(context); | 
| 119 |         reader = ClassReader.instance(context); | 
| 120 |         make = TreeMaker.instance(context); | 
| 121 |         syms = Symtab.instance(context); | 
| 122 |         chk = Check.instance(context); | 
| 123 |         memberEnter = MemberEnter.instance(context); | 
| 124 |         annotate = Annotate.instance(context); | 
| 125 |         lint = Lint.instance(context); | 
| 126 |   | 
| 127 |         predefClassDef = make.ClassDef( | 
| 128 |             make.Modifiers(PUBLIC), | 
| 129 |             syms.predefClass.name, null, null, null, null); | 
| 130 |         predefClassDef.sym = syms.predefClass; | 
| 131 |         todo = Todo.instance(context); | 
| 132 |         fileManager = context.get(JavaFileManager.class); | 
| 133 |     } | 
| 134 |   | 
| 135 |     /** A hashtable mapping classes and packages to the environments current | 
| 136 |      *  at the points of their definitions. | 
| 137 |      */ | 
| 138 |     Map<TypeSymbol,Env<AttrContext>> typeEnvs = | 
| 139 |             new HashMap<TypeSymbol,Env<AttrContext>>(); | 
| 140 |   | 
| 141 |     /** Accessor for typeEnvs | 
| 142 |      */ | 
| 143 |     public Env<AttrContext> getEnv(TypeSymbol sym) { | 
| 144 |         return typeEnvs.get(sym); | 
| 145 |     } | 
| 146 |   | 
| 147 |     public Env<AttrContext> getClassEnv(TypeSymbol sym) { | 
| 148 |         Env<AttrContext> localEnv = getEnv(sym); | 
| 149 |         Env<AttrContext> lintEnv = localEnv; | 
| 150 |         while (lintEnv.info.lint == null) | 
| 151 |             lintEnv = lintEnv.next; | 
| 152 |         localEnv.info.lint = lintEnv.info.lint.augment(sym.attributes_field, sym.flags()); | 
| 153 |         return localEnv; | 
| 154 |     } | 
| 155 |   | 
| 156 |     /** The queue of all classes that might still need to be completed; | 
| 157 |      *  saved and initialized by main(). | 
| 158 |      */ | 
| 159 |     ListBuffer<ClassSymbol> uncompleted; | 
| 160 |   | 
| 161 |     /** A dummy class to serve as enclClass for toplevel environments. | 
| 162 |      */ | 
| 163 |     private JCClassDecl predefClassDef; | 
| 164 |   | 
| 165 | /* ************************************************************************ | 
| 166 |  * environment construction | 
| 167 |  *************************************************************************/ | 
| 168 |   | 
| 169 |   | 
| 170 |     /** Create a fresh environment for class bodies. | 
| 171 |      *  This will create a fresh scope for local symbols of a class, referred | 
| 172 |      *  to by the environments info.scope field. | 
| 173 |      *  This scope will contain | 
| 174 |      *    - symbols for this and super | 
| 175 |      *    - symbols for any type parameters | 
| 176 |      *  In addition, it serves as an anchor for scopes of methods and initializers | 
| 177 |      *  which are nested in this scope via Scope.dup(). | 
| 178 |      *  This scope should not be confused with the members scope of a class. | 
| 179 |      * | 
| 180 |      *  @param tree     The class definition. | 
| 181 |      *  @param env      The environment current outside of the class definition. | 
| 182 |      */ | 
| 183 |     public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) { | 
| 184 |         Env<AttrContext> localEnv = | 
| 185 |             env.dup(tree, env.info.dup(new Scope(tree.sym))); | 
| 186 |         localEnv.enclClass = tree; | 
| 187 |         localEnv.outer = env; | 
| 188 |         localEnv.info.isSelfCall = false; | 
| 189 |         localEnv.info.lint = null; // leave this to be filled in by Attr, | 
| 190 |                                    // when annotations have been processed | 
| 191 |         return localEnv; | 
| 192 |     } | 
| 193 |   | 
| 194 |     /** Create a fresh environment for toplevels. | 
| 195 |      *  @param tree     The toplevel tree. | 
| 196 |      */ | 
| 197 |     Env<AttrContext> topLevelEnv(JCCompilationUnit tree) { | 
| 198 |         Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext()); | 
| 199 |         localEnv.toplevel = tree; | 
| 200 |         localEnv.enclClass = predefClassDef; | 
| 201 |         tree.namedImportScope = new Scope.ImportScope(tree.packge); | 
| 202 |         tree.starImportScope = new Scope.ImportScope(tree.packge); | 
| 203 |         localEnv.info.scope = tree.namedImportScope; | 
| 204 |         localEnv.info.lint = lint; | 
| 205 |         return localEnv; | 
| 206 |     } | 
| 207 |   | 
| 208 |     public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) { | 
| 209 |         Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext()); | 
| 210 |         localEnv.toplevel = tree; | 
| 211 |         localEnv.enclClass = predefClassDef; | 
| 212 |         localEnv.info.scope = tree.namedImportScope; | 
| 213 |         localEnv.info.lint = lint; | 
| 214 |         return localEnv; | 
| 215 |     } | 
| 216 |   | 
| 217 |     /** The scope in which a member definition in environment env is to be entered | 
| 218 |      *  This is usually the environment's scope, except for class environments, | 
| 219 |      *  where the local scope is for type variables, and the this and super symbol | 
| 220 |      *  only, and members go into the class member scope. | 
| 221 |      */ | 
| 222 |     Scope enterScope(Env<AttrContext> env) { | 
| 223 |         return (env.tree.getTag() == JCTree.CLASSDEF) | 
| 224 |             ? ((JCClassDecl) env.tree).sym.members_field | 
| 225 |             : env.info.scope; | 
| 226 |     } | 
| 227 |   | 
| 228 | /* ************************************************************************ | 
| 229 |  * Visitor methods for phase 1: class enter | 
| 230 |  *************************************************************************/ | 
| 231 |   | 
| 232 |     /** Visitor argument: the current environment. | 
| 233 |      */ | 
| 234 |     protected Env<AttrContext> env; | 
| 235 |   | 
| 236 |     /** Visitor result: the computed type. | 
| 237 |      */ | 
| 238 |     Type result; | 
| 239 |   | 
| 240 |     /** Visitor method: enter all classes in given tree, catching any | 
| 241 |      *  completion failure exceptions. Return the tree's type. | 
| 242 |      * | 
| 243 |      *  @param tree    The tree to be visited. | 
| 244 |      *  @param env     The environment visitor argument. | 
| 245 |      */ | 
| 246 |     Type classEnter(JCTree tree, Env<AttrContext> env) { | 
| 247 |         Env<AttrContext> prevEnv = this.env; | 
| 248 |         try { | 
| 249 |             this.env = env; | 
| 250 |             tree.accept(this); | 
| 251 |             return result; | 
| 252 |         }  catch (CompletionFailure ex) { | 
| 253 |             return chk.completionError(tree.pos(), ex); | 
| 254 |         } finally { | 
| 255 |             this.env = prevEnv; | 
| 256 |         } | 
| 257 |     } | 
| 258 |   | 
| 259 |     /** Visitor method: enter classes of a list of trees, returning a list of types. | 
| 260 |      */ | 
| 261 |     <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) { | 
| 262 |         ListBuffer<Type> ts = new ListBuffer<Type>(); | 
| 263 |         for (List<T> l = trees; l.nonEmpty(); l = l.tail) | 
| 264 |             ts.append(classEnter(l.head, env)); | 
| 265 |         return ts.toList(); | 
| 266 |     } | 
| 267 |   | 
| 268 |     public void visitTopLevel(JCCompilationUnit tree) { | 
| 269 |         JavaFileObject prev = log.useSource(tree.sourcefile); | 
| 270 |         boolean addEnv = false; | 
| 271 |         boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", | 
| 272 |                                                              JavaFileObject.Kind.SOURCE); | 
| 273 |         if (tree.pid != null) { | 
| 274 |             tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); | 
| 275 |             if (tree.packageAnnotations.nonEmpty()) { | 
| 276 |                 if (isPkgInfo) { | 
| 277 |                     addEnv = true; | 
| 278 |                 } else { | 
| 279 |                     log.error(tree.packageAnnotations.head.pos(), | 
| 280 |                               "pkg.annotations.sb.in.package-info.java"); | 
| 281 |                 } | 
| 282 |             } | 
| 283 |         } else { | 
| 284 |             tree.packge = syms.unnamedPackage; | 
| 285 |         } | 
| 286 |         tree.packge.complete(); // Find all classes in package. | 
| 287 |         Env<AttrContext> env = topLevelEnv(tree); | 
| 288 |   | 
| 289 |         // Save environment of package-info.java file. | 
| 290 |         if (isPkgInfo) { | 
| 291 |             Env<AttrContext> env0 = typeEnvs.get(tree.packge); | 
| 292 |             if (env0 == null) { | 
| 293 |                 typeEnvs.put(tree.packge, env); | 
| 294 |             } else { | 
| 295 |                 JCCompilationUnit tree0 = env0.toplevel; | 
| 296 |                 if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) { | 
| 297 |                     log.warning(tree.pid != null ? tree.pid.pos() | 
| 298 |                                                  : null, | 
| 299 |                                 "pkg-info.already.seen", | 
| 300 |                                 tree.packge); | 
| 301 |                     if (addEnv || (tree0.packageAnnotations.isEmpty() && | 
| 302 |                                    tree.docComments != null && | 
| 303 |                                    tree.docComments.get(tree) != null)) { | 
| 304 |                         typeEnvs.put(tree.packge, env); | 
| 305 |                     } | 
| 306 |                 } | 
| 307 |             } | 
| 308 |         } | 
| 309 |         classEnter(tree.defs, env); | 
| 310 |         if (addEnv) { | 
| 311 |             todo.append(env); | 
| 312 |         } | 
| 313 |         log.useSource(prev); | 
| 314 |         result = null; | 
| 315 |     } | 
| 316 |   | 
| 317 |     public void visitClassDef(JCClassDecl tree) { | 
| 318 |         Symbol owner = env.info.scope.owner; | 
| 319 |         Scope enclScope = enterScope(env); | 
| 320 |         ClassSymbol c; | 
| 321 |         if (owner.kind == PCK) { | 
| 322 |             // We are seeing a toplevel class. | 
| 323 |             PackageSymbol packge = (PackageSymbol)owner; | 
| 324 |             for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner) | 
| 325 |                 q.flags_field |= EXISTS; | 
| 326 |             c = reader.enterClass(tree.name, packge); | 
| 327 |             packge.members().enterIfAbsent(c); | 
| 328 |             if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) { | 
| 329 |                 log.error(tree.pos(), | 
| 330 |                           "class.public.should.be.in.file", tree.name); | 
| 331 |             } | 
| 332 |         } else { | 
| 333 |             if (tree.name.len != 0 && | 
| 334 |                 !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) { | 
| 335 |                 result = null; | 
| 336 |                 return; | 
| 337 |             } | 
| 338 |             if (owner.kind == TYP) { | 
| 339 |                 // We are seeing a member class. | 
| 340 |                 c = reader.enterClass(tree.name, (TypeSymbol)owner); | 
| 341 |                 if ((owner.flags_field & INTERFACE) != 0) { | 
| 342 |                     tree.mods.flags |= PUBLIC | STATIC; | 
| 343 |                 } | 
| 344 |             } else { | 
| 345 |                 // We are seeing a local class. | 
| 346 |                 c = reader.defineClass(tree.name, owner); | 
| 347 |                 c.flatname = chk.localClassName(c); | 
| 348 |                 if (c.name.len != 0) | 
| 349 |                     chk.checkTransparentClass(tree.pos(), c, env.info.scope); | 
| 350 |             } | 
| 351 |         } | 
| 352 |         tree.sym = c; | 
| 353 |   | 
| 354 |         // Enter class into `compiled' table and enclosing scope. | 
| 355 |         if (chk.compiled.get(c.flatname) != null) { | 
| 356 |             duplicateClass(tree.pos(), c); | 
| 357 |             result = new ErrorType(tree.name, (TypeSymbol)owner); | 
| 358 |             tree.sym = (ClassSymbol)result.tsym; | 
| 359 |             return; | 
| 360 |         } | 
| 361 |         chk.compiled.put(c.flatname, c); | 
| 362 |         enclScope.enter(c); | 
| 363 |   | 
| 364 |         // Set up an environment for class block and store in `typeEnvs' | 
| 365 |         // table, to be retrieved later in memberEnter and attribution. | 
| 366 |         Env<AttrContext> localEnv = classEnv(tree, env); | 
| 367 |         typeEnvs.put(c, localEnv); | 
| 368 |   | 
| 369 |         // Fill out class fields. | 
| 370 |         c.completer = memberEnter; | 
| 371 |         c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree); | 
| 372 |         c.sourcefile = env.toplevel.sourcefile; | 
| 373 |         c.members_field = new Scope(c); | 
| 374 |   | 
| 375 |         ClassType ct = (ClassType)c.type; | 
| 376 |         if (owner.kind != PCK && (c.flags_field & STATIC) == 0) { | 
| 377 |             // We are seeing a local or inner class. | 
| 378 |             // Set outer_field of this class to closest enclosing class | 
| 379 |             // which contains this class in a non-static context | 
| 380 |             // (its "enclosing instance class"), provided such a class exists. | 
| 381 |             Symbol owner1 = owner; | 
| 382 |             while ((owner1.kind & (VAR | MTH)) != 0 && | 
| 383 |                    (owner1.flags_field & STATIC) == 0) { | 
| 384 |                 owner1 = owner1.owner; | 
| 385 |             } | 
| 386 |             if (owner1.kind == TYP) { | 
| 387 |                 ct.setEnclosingType(owner1.type); | 
| 388 |             } | 
| 389 |         } | 
| 390 |   | 
| 391 |         // Enter type parameters. | 
| 392 |         ct.typarams_field = classEnter(tree.typarams, localEnv); | 
| 393 |   | 
| 394 |         // Add non-local class to uncompleted, to make sure it will be | 
| 395 |         // completed later. | 
| 396 |         if (!c.isLocal() && uncompleted != null) uncompleted.append(c); | 
| 397 | //      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG | 
| 398 |   | 
| 399 |         // Recursively enter all member classes. | 
| 400 |         classEnter(tree.defs, localEnv); | 
| 401 |   | 
| 402 |         result = c.type; | 
| 403 |     } | 
| 404 |     //where | 
| 405 |         /** Does class have the same name as the file it appears in? | 
| 406 |          */ | 
| 407 |         private static boolean classNameMatchesFileName(ClassSymbol c, | 
| 408 |                                                         Env<AttrContext> env) { | 
| 409 |             return env.toplevel.sourcefile.isNameCompatible(c.name.toString(), | 
| 410 |                                                             JavaFileObject.Kind.SOURCE); | 
| 411 |         } | 
| 412 |   | 
| 413 |     /** Complain about a duplicate class. */ | 
| 414 |     protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) { | 
| 415 |         log.error(pos, "duplicate.class", c.fullname); | 
| 416 |     } | 
| 417 |   | 
| 418 |     /** Class enter visitor method for type parameters. | 
| 419 |      *  Enter a symbol for type parameter in local scope, after checking that it | 
| 420 |      *  is unique. | 
| 421 |      */ | 
| 422 |     public void visitTypeParameter(JCTypeParameter tree) { | 
| 423 |         TypeVar a = (tree.type != null) | 
| 424 |             ? (TypeVar)tree.type | 
| 425 |             : new TypeVar(tree.name, env.info.scope.owner, syms.botType); | 
| 426 |         tree.type = a; | 
| 427 |         if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) { | 
| 428 |             env.info.scope.enter(a.tsym); | 
| 429 |         } | 
| 430 |         result = a; | 
| 431 |     } | 
| 432 |   | 
| 433 |     /** Default class enter visitor method: do nothing. | 
| 434 |      */ | 
| 435 |     public void visitTree(JCTree tree) { | 
| 436 |         result = null; | 
| 437 |     } | 
| 438 |   | 
| 439 |     /** Main method: enter all classes in a list of toplevel trees. | 
| 440 |      *  @param trees      The list of trees to be processed. | 
| 441 |      */ | 
| 442 |     public void main(List<JCCompilationUnit> trees) { | 
| 443 |         complete(trees, null); | 
| 444 |     } | 
| 445 |   | 
| 446 |     /** Main method: enter one class from a list of toplevel trees and | 
| 447 |      *  place the rest on uncompleted for later processing. | 
| 448 |      *  @param trees      The list of trees to be processed. | 
| 449 |      *  @param c          The class symbol to be processed. | 
| 450 |      */ | 
| 451 |     public void complete(List<JCCompilationUnit> trees, ClassSymbol c) { | 
| 452 |         annotate.enterStart(); | 
| 453 |         ListBuffer<ClassSymbol> prevUncompleted = uncompleted; | 
| 454 |         if (memberEnter.completionEnabled) uncompleted = new ListBuffer<ClassSymbol>(); | 
| 455 |   | 
| 456 |         try { | 
| 457 |             // enter all classes, and construct uncompleted list | 
| 458 |             classEnter(trees, null); | 
| 459 |   | 
| 460 |             // complete all uncompleted classes in memberEnter | 
| 461 |             if  (memberEnter.completionEnabled) { | 
| 462 |                 while (uncompleted.nonEmpty()) { | 
| 463 |                     ClassSymbol clazz = uncompleted.next(); | 
| 464 |                     if (c == null || c == clazz || prevUncompleted == null) | 
| 465 |                         clazz.complete(); | 
| 466 |                     else | 
| 467 |                         // defer | 
| 468 |                         prevUncompleted.append(clazz); | 
| 469 |                 } | 
| 470 |   | 
| 471 |                 // if there remain any unimported toplevels (these must have | 
| 472 |                 // no classes at all), process their import statements as well. | 
| 473 |                 for (JCCompilationUnit tree : trees) { | 
| 474 |                     if (tree.starImportScope.elems == null) { | 
| 475 |                         JavaFileObject prev = log.useSource(tree.sourcefile); | 
| 476 |                         Env<AttrContext> env = typeEnvs.get(tree); | 
| 477 |                         if (env == null) | 
| 478 |                             env = topLevelEnv(tree); | 
| 479 |                         memberEnter.memberEnter(tree, env); | 
| 480 |                         log.useSource(prev); | 
| 481 |                     } | 
| 482 |                 } | 
| 483 |             } | 
| 484 |         } finally { | 
| 485 |             uncompleted = prevUncompleted; | 
| 486 |             annotate.enterDone(); | 
| 487 |         } | 
| 488 |     } | 
| 489 | } |