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