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.code; |
27 | |
28 | import java.util.ArrayList; |
29 | import java.util.Collections; |
30 | import java.util.Set; |
31 | import java.util.concurrent.Callable; |
32 | import javax.lang.model.element.*; |
33 | import javax.lang.model.type.ReferenceType; |
34 | import javax.lang.model.type.TypeMirror; |
35 | import javax.tools.JavaFileObject; |
36 | |
37 | import com.sun.tools.javac.util.*; |
38 | import com.sun.tools.javac.util.Name; |
39 | import com.sun.tools.javac.code.Type.*; |
40 | import com.sun.tools.javac.comp.Attr; |
41 | import com.sun.tools.javac.comp.AttrContext; |
42 | import com.sun.tools.javac.comp.Env; |
43 | import com.sun.tools.javac.jvm.*; |
44 | import com.sun.tools.javac.model.*; |
45 | import com.sun.tools.javac.tree.JCTree; |
46 | |
47 | import static com.sun.tools.javac.code.Flags.*; |
48 | import static com.sun.tools.javac.code.Kinds.*; |
49 | import static com.sun.tools.javac.code.TypeTags.*; |
50 | |
51 | /** Root class for Java symbols. It contains subclasses |
52 | * for specific sorts of symbols, such as variables, methods and operators, |
53 | * types, packages. Each subclass is represented as a static inner class |
54 | * inside Symbol. |
55 | * |
56 | * <p><b>This is NOT part of any API supported by Sun Microsystems. If |
57 | * you write code that depends on this, you do so at your own risk. |
58 | * This code and its internal interfaces are subject to change or |
59 | * deletion without notice.</b> |
60 | */ |
61 | public abstract class Symbol implements Element { |
62 | // public Throwable debug = new Throwable(); |
63 | |
64 | /** The kind of this symbol. |
65 | * @see Kinds |
66 | */ |
67 | public int kind; |
68 | |
69 | /** The flags of this symbol. |
70 | */ |
71 | public long flags_field; |
72 | |
73 | /** An accessor method for the flags of this symbol. |
74 | * Flags of class symbols should be accessed through the accessor |
75 | * method to make sure that the class symbol is loaded. |
76 | */ |
77 | public long flags() { return flags_field; } |
78 | |
79 | /** The attributes of this symbol. |
80 | */ |
81 | public List<Attribute.Compound> attributes_field; |
82 | |
83 | /** An accessor method for the attributes of this symbol. |
84 | * Attributes of class symbols should be accessed through the accessor |
85 | * method to make sure that the class symbol is loaded. |
86 | */ |
87 | public List<Attribute.Compound> getAnnotationMirrors() { |
88 | assert attributes_field != null; |
89 | return attributes_field; |
90 | } |
91 | |
92 | /** Fetch a particular annotation from a symbol. */ |
93 | public Attribute.Compound attribute(Symbol anno) { |
94 | for (Attribute.Compound a : getAnnotationMirrors()) |
95 | if (a.type.tsym == anno) return a; |
96 | return null; |
97 | } |
98 | |
99 | /** The name of this symbol in Utf8 representation. |
100 | */ |
101 | public Name name; |
102 | |
103 | /** The type of this symbol. |
104 | */ |
105 | public Type type; |
106 | |
107 | /** The owner of this symbol. |
108 | */ |
109 | public Symbol owner; |
110 | |
111 | /** The completer of this symbol. |
112 | */ |
113 | public Completer completer; |
114 | |
115 | /** A cache for the type erasure of this symbol. |
116 | */ |
117 | public Type erasure_field; |
118 | |
119 | /** Construct a symbol with given kind, flags, name, type and owner. |
120 | */ |
121 | public Symbol(int kind, long flags, Name name, Type type, Symbol owner) { |
122 | this.kind = kind; |
123 | this.flags_field = flags; |
124 | this.type = type; |
125 | this.owner = owner; |
126 | this.completer = null; |
127 | this.erasure_field = null; |
128 | this.attributes_field = List.nil(); |
129 | this.name = name; |
130 | } |
131 | |
132 | /** Clone this symbol with new owner. |
133 | * Legal only for fields and methods. |
134 | */ |
135 | public Symbol clone(Symbol newOwner) { |
136 | throw new AssertionError(); |
137 | } |
138 | |
139 | /** The Java source which this symbol represents. |
140 | * A description of this symbol; overrides Object. |
141 | */ |
142 | public String toString() { |
143 | return name.toString(); |
144 | } |
145 | |
146 | /** A Java source description of the location of this symbol; used for |
147 | * error reporting. Use of this method may result in the loss of the |
148 | * symbol's description. |
149 | */ |
150 | public String location() { |
151 | if (owner.name == null || (owner.name.len == 0 && owner.kind != PCK)) { |
152 | return ""; |
153 | } |
154 | return owner.toString(); |
155 | } |
156 | |
157 | public String location(Type site, Types types) { |
158 | if (owner.name == null || owner.name.len == 0) { |
159 | return location(); |
160 | } |
161 | if (owner.type.tag == CLASS) { |
162 | Type ownertype = types.asOuterSuper(site, owner); |
163 | if (ownertype != null) return ownertype.toString(); |
164 | } |
165 | return owner.toString(); |
166 | } |
167 | |
168 | /** The symbol's erased type. |
169 | */ |
170 | public Type erasure(Types types) { |
171 | if (erasure_field == null) |
172 | erasure_field = types.erasure(type); |
173 | return erasure_field; |
174 | } |
175 | |
176 | /** The external type of a symbol. This is the symbol's erased type |
177 | * except for constructors of inner classes which get the enclosing |
178 | * instance class added as first argument. |
179 | */ |
180 | public Type externalType(Types types) { |
181 | Type t = erasure(types); |
182 | if (name == name.table.init && owner.hasOuterInstance()) { |
183 | Type outerThisType = types.erasure(owner.type.getEnclosingType()); |
184 | return new MethodType(t.getParameterTypes().prepend(outerThisType), |
185 | t.getReturnType(), |
186 | t.getThrownTypes(), |
187 | t.tsym); |
188 | } else { |
189 | return t; |
190 | } |
191 | } |
192 | |
193 | public boolean isStatic() { |
194 | return |
195 | (flags() & STATIC) != 0 || |
196 | (owner.flags() & INTERFACE) != 0 && kind != MTH; |
197 | } |
198 | |
199 | public boolean isInterface() { |
200 | return (flags() & INTERFACE) != 0; |
201 | } |
202 | |
203 | /** Is this symbol declared (directly or indirectly) local |
204 | * to a method or variable initializer? |
205 | * Also includes fields of inner classes which are in |
206 | * turn local to a method or variable initializer. |
207 | */ |
208 | public boolean isLocal() { |
209 | return |
210 | (owner.kind & (VAR | MTH)) != 0 || |
211 | (owner.kind == TYP && owner.isLocal()); |
212 | } |
213 | |
214 | /** Is this symbol a constructor? |
215 | */ |
216 | public boolean isConstructor() { |
217 | return name == name.table.init; |
218 | } |
219 | |
220 | /** The fully qualified name of this symbol. |
221 | * This is the same as the symbol's name except for class symbols, |
222 | * which are handled separately. |
223 | */ |
224 | public Name getQualifiedName() { |
225 | return name; |
226 | } |
227 | |
228 | /** The fully qualified name of this symbol after converting to flat |
229 | * representation. This is the same as the symbol's name except for |
230 | * class symbols, which are handled separately. |
231 | */ |
232 | public Name flatName() { |
233 | return getQualifiedName(); |
234 | } |
235 | |
236 | /** If this is a class or package, its members, otherwise null. |
237 | */ |
238 | public Scope members() { |
239 | return null; |
240 | } |
241 | |
242 | /** A class is an inner class if it it has an enclosing instance class. |
243 | */ |
244 | public boolean isInner() { |
245 | return type.getEnclosingType().tag == CLASS; |
246 | } |
247 | |
248 | /** An inner class has an outer instance if it is not an interface |
249 | * it has an enclosing instance class which might be referenced from the class. |
250 | * Nested classes can see instance members of their enclosing class. |
251 | * Their constructors carry an additional this$n parameter, inserted |
252 | * implicitly by the compiler. |
253 | * |
254 | * @see #isInner |
255 | */ |
256 | public boolean hasOuterInstance() { |
257 | return |
258 | type.getEnclosingType().tag == CLASS && (flags() & (INTERFACE | NOOUTERTHIS)) == 0; |
259 | } |
260 | |
261 | /** The closest enclosing class of this symbol's declaration. |
262 | */ |
263 | public ClassSymbol enclClass() { |
264 | Symbol c = this; |
265 | while (c != null && |
266 | ((c.kind & TYP) == 0 || c.type.tag != CLASS)) { |
267 | c = c.owner; |
268 | } |
269 | return (ClassSymbol)c; |
270 | } |
271 | |
272 | /** The outermost class which indirectly owns this symbol. |
273 | */ |
274 | public ClassSymbol outermostClass() { |
275 | Symbol sym = this; |
276 | Symbol prev = null; |
277 | while (sym.kind != PCK) { |
278 | prev = sym; |
279 | sym = sym.owner; |
280 | } |
281 | return (ClassSymbol) prev; |
282 | } |
283 | |
284 | /** The package which indirectly owns this symbol. |
285 | */ |
286 | public PackageSymbol packge() { |
287 | Symbol sym = this; |
288 | while (sym.kind != PCK) { |
289 | sym = sym.owner; |
290 | } |
291 | return (PackageSymbol) sym; |
292 | } |
293 | |
294 | /** Is this symbol a subclass of `base'? Only defined for ClassSymbols. |
295 | */ |
296 | public boolean isSubClass(Symbol base, Types types) { |
297 | throw new AssertionError("isSubClass " + this); |
298 | } |
299 | |
300 | /** Fully check membership: hierarchy, protection, and hiding. |
301 | * Does not exclude methods not inherited due to overriding. |
302 | */ |
303 | public boolean isMemberOf(TypeSymbol clazz, Types types) { |
304 | return |
305 | owner == clazz || |
306 | clazz.isSubClass(owner, types) && |
307 | isInheritedIn(clazz, types) && |
308 | !hiddenIn((ClassSymbol)clazz, types); |
309 | } |
310 | |
311 | /** Is this symbol the same as or enclosed by the given class? */ |
312 | public boolean isEnclosedBy(ClassSymbol clazz) { |
313 | for (Symbol sym = this; sym.kind != PCK; sym = sym.owner) |
314 | if (sym == clazz) return true; |
315 | return false; |
316 | } |
317 | |
318 | /** Check for hiding. Note that this doesn't handle multiple |
319 | * (interface) inheritance. */ |
320 | private boolean hiddenIn(ClassSymbol clazz, Types types) { |
321 | if (kind == MTH && (flags() & STATIC) == 0) return false; |
322 | while (true) { |
323 | if (owner == clazz) return false; |
324 | Scope.Entry e = clazz.members().lookup(name); |
325 | while (e.scope != null) { |
326 | if (e.sym == this) return false; |
327 | if (e.sym.kind == kind && |
328 | (kind != MTH || |
329 | (e.sym.flags() & STATIC) != 0 && |
330 | types.isSubSignature(e.sym.type, type))) |
331 | return true; |
332 | e = e.next(); |
333 | } |
334 | Type superType = types.supertype(clazz.type); |
335 | if (superType.tag != TypeTags.CLASS) return false; |
336 | clazz = (ClassSymbol)superType.tsym; |
337 | } |
338 | } |
339 | |
340 | /** Is this symbol inherited into a given class? |
341 | * PRE: If symbol's owner is a interface, |
342 | * it is already assumed that the interface is a superinterface |
343 | * of given class. |
344 | * @param clazz The class for which we want to establish membership. |
345 | * This must be a subclass of the member's owner. |
346 | */ |
347 | public boolean isInheritedIn(Symbol clazz, Types types) { |
348 | switch ((int)(flags_field & Flags.AccessFlags)) { |
349 | default: // error recovery |
350 | case PUBLIC: |
351 | return true; |
352 | case PRIVATE: |
353 | return this.owner == clazz; |
354 | case PROTECTED: |
355 | // we model interfaces as extending Object |
356 | return (clazz.flags() & INTERFACE) == 0; |
357 | case 0: |
358 | PackageSymbol thisPackage = this.packge(); |
359 | for (Symbol sup = clazz; |
360 | sup != null && sup != this.owner; |
361 | sup = types.supertype(sup.type).tsym) { |
362 | if (sup.type.isErroneous()) |
363 | return true; // error recovery |
364 | if ((sup.flags() & COMPOUND) != 0) |
365 | continue; |
366 | if (sup.packge() != thisPackage) |
367 | return false; |
368 | } |
369 | return (clazz.flags() & INTERFACE) == 0; |
370 | } |
371 | } |
372 | |
373 | /** The (variable or method) symbol seen as a member of given |
374 | * class type`site' (this might change the symbol's type). |
375 | * This is used exclusively for producing diagnostics. |
376 | */ |
377 | public Symbol asMemberOf(Type site, Types types) { |
378 | throw new AssertionError(); |
379 | } |
380 | |
381 | /** Does this method symbol override `other' symbol, when both are seen as |
382 | * members of class `origin'? It is assumed that _other is a member |
383 | * of origin. |
384 | * |
385 | * It is assumed that both symbols have the same name. The static |
386 | * modifier is ignored for this test. |
387 | * |
388 | * See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 |
389 | */ |
390 | public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) { |
391 | return false; |
392 | } |
393 | |
394 | /** Complete the elaboration of this symbol's definition. |
395 | */ |
396 | public void complete() throws CompletionFailure { |
397 | if (completer != null) { |
398 | Completer c = completer; |
399 | completer = null; |
400 | c.complete(this); |
401 | } |
402 | } |
403 | |
404 | /** True if the symbol represents an entity that exists. |
405 | */ |
406 | public boolean exists() { |
407 | return true; |
408 | } |
409 | |
410 | public Type asType() { |
411 | return type; |
412 | } |
413 | |
414 | public Symbol getEnclosingElement() { |
415 | return owner; |
416 | } |
417 | |
418 | public ElementKind getKind() { |
419 | return ElementKind.OTHER; // most unkind |
420 | } |
421 | |
422 | public Set<Modifier> getModifiers() { |
423 | return Flags.asModifierSet(flags()); |
424 | } |
425 | |
426 | public Name getSimpleName() { |
427 | return name; |
428 | } |
429 | |
430 | /** |
431 | * @deprecated this method should never be used by javac internally. |
432 | */ |
433 | @Deprecated |
434 | public <A extends java.lang.annotation.Annotation> A getAnnotation(Class<A> annoType) { |
435 | return JavacElements.getAnnotation(this, annoType); |
436 | } |
437 | |
438 | // TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList |
439 | public java.util.List<Symbol> getEnclosedElements() { |
440 | return List.nil(); |
441 | } |
442 | |
443 | public List<TypeSymbol> getTypeParameters() { |
444 | ListBuffer<TypeSymbol> l = ListBuffer.lb(); |
445 | for (Type t : type.getTypeArguments()) { |
446 | l.append(t.tsym); |
447 | } |
448 | return l.toList(); |
449 | } |
450 | |
451 | public static class DelegatedSymbol extends Symbol { |
452 | protected Symbol other; |
453 | public DelegatedSymbol(Symbol other) { |
454 | super(other.kind, other.flags_field, other.name, other.type, other.owner); |
455 | this.other = other; |
456 | } |
457 | public String toString() { return other.toString(); } |
458 | public String location() { return other.location(); } |
459 | public String location(Type site, Types types) { return other.location(site, types); } |
460 | public Type erasure(Types types) { return other.erasure(types); } |
461 | public Type externalType(Types types) { return other.externalType(types); } |
462 | public boolean isLocal() { return other.isLocal(); } |
463 | public boolean isConstructor() { return other.isConstructor(); } |
464 | public Name getQualifiedName() { return other.getQualifiedName(); } |
465 | public Name flatName() { return other.flatName(); } |
466 | public Scope members() { return other.members(); } |
467 | public boolean isInner() { return other.isInner(); } |
468 | public boolean hasOuterInstance() { return other.hasOuterInstance(); } |
469 | public ClassSymbol enclClass() { return other.enclClass(); } |
470 | public ClassSymbol outermostClass() { return other.outermostClass(); } |
471 | public PackageSymbol packge() { return other.packge(); } |
472 | public boolean isSubClass(Symbol base, Types types) { return other.isSubClass(base, types); } |
473 | public boolean isMemberOf(TypeSymbol clazz, Types types) { return other.isMemberOf(clazz, types); } |
474 | public boolean isEnclosedBy(ClassSymbol clazz) { return other.isEnclosedBy(clazz); } |
475 | public boolean isInheritedIn(Symbol clazz, Types types) { return other.isInheritedIn(clazz, types); } |
476 | public Symbol asMemberOf(Type site, Types types) { return other.asMemberOf(site, types); } |
477 | public void complete() throws CompletionFailure { other.complete(); } |
478 | |
479 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
480 | return other.accept(v, p); |
481 | } |
482 | } |
483 | |
484 | /** A class for type symbols. Type variables are represented by instances |
485 | * of this class, classes and packages by instances of subclasses. |
486 | */ |
487 | public static class TypeSymbol |
488 | extends Symbol implements TypeParameterElement { |
489 | // Implements TypeParameterElement because type parameters don't |
490 | // have their own TypeSymbol subclass. |
491 | // TODO: type parameters should have their own TypeSymbol subclass |
492 | |
493 | public TypeSymbol(long flags, Name name, Type type, Symbol owner) { |
494 | super(TYP, flags, name, type, owner); |
495 | } |
496 | |
497 | /** form a fully qualified name from a name and an owner |
498 | */ |
499 | static public Name formFullName(Name name, Symbol owner) { |
500 | if (owner == null) return name; |
501 | if (((owner.kind != ERR)) && |
502 | ((owner.kind & (VAR | MTH)) != 0 |
503 | || (owner.kind == TYP && owner.type.tag == TYPEVAR) |
504 | )) return name; |
505 | Name prefix = owner.getQualifiedName(); |
506 | if (prefix == null || prefix == prefix.table.empty) |
507 | return name; |
508 | else return prefix.append('.', name); |
509 | } |
510 | |
511 | /** form a fully qualified name from a name and an owner, after |
512 | * converting to flat representation |
513 | */ |
514 | static public Name formFlatName(Name name, Symbol owner) { |
515 | if (owner == null || |
516 | (owner.kind & (VAR | MTH)) != 0 |
517 | || (owner.kind == TYP && owner.type.tag == TYPEVAR) |
518 | ) return name; |
519 | char sep = owner.kind == TYP ? '$' : '.'; |
520 | Name prefix = owner.flatName(); |
521 | if (prefix == null || prefix == prefix.table.empty) |
522 | return name; |
523 | else return prefix.append(sep, name); |
524 | } |
525 | |
526 | /** |
527 | * A total ordering between type symbols that refines the |
528 | * class inheritance graph. |
529 | * |
530 | * Typevariables always precede other kinds of symbols. |
531 | */ |
532 | public final boolean precedes(TypeSymbol that, Types types) { |
533 | if (this == that) |
534 | return false; |
535 | if (this.type.tag == that.type.tag) { |
536 | if (this.type.tag == CLASS) { |
537 | return |
538 | types.rank(that.type) < types.rank(this.type) || |
539 | types.rank(that.type) == types.rank(this.type) && |
540 | that.getQualifiedName().compareTo(this.getQualifiedName()) < 0; |
541 | } else if (this.type.tag == TYPEVAR) { |
542 | return types.isSubtype(this.type, that.type); |
543 | } |
544 | } |
545 | return this.type.tag == TYPEVAR; |
546 | } |
547 | |
548 | // For type params; overridden in subclasses. |
549 | public ElementKind getKind() { |
550 | return ElementKind.TYPE_PARAMETER; |
551 | } |
552 | |
553 | public java.util.List<Symbol> getEnclosedElements() { |
554 | List<Symbol> list = List.nil(); |
555 | for (Scope.Entry e = members().elems; e != null; e = e.sibling) { |
556 | if (e.sym != null && (e.sym.flags() & SYNTHETIC) == 0 && e.sym.owner == this) |
557 | list = list.prepend(e.sym); |
558 | } |
559 | return list; |
560 | } |
561 | |
562 | // For type params. |
563 | // Perhaps not needed if getEnclosingElement can be spec'ed |
564 | // to do the same thing. |
565 | // TODO: getGenericElement() might not be needed |
566 | public Symbol getGenericElement() { |
567 | return owner; |
568 | } |
569 | |
570 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
571 | assert type.tag == TYPEVAR; // else override will be invoked |
572 | return v.visitTypeParameter(this, p); |
573 | } |
574 | |
575 | public List<Type> getBounds() { |
576 | TypeVar t = (TypeVar)type; |
577 | Type bound = t.getUpperBound(); |
578 | if (!bound.isCompound()) |
579 | return List.of(bound); |
580 | ClassType ct = (ClassType)bound; |
581 | if (!ct.tsym.erasure_field.isInterface()) { |
582 | return ct.interfaces_field.prepend(ct.supertype_field); |
583 | } else { |
584 | // No superclass was given in bounds. |
585 | // In this case, supertype is Object, erasure is first interface. |
586 | return ct.interfaces_field; |
587 | } |
588 | } |
589 | } |
590 | |
591 | /** A class for package symbols |
592 | */ |
593 | public static class PackageSymbol extends TypeSymbol |
594 | implements PackageElement { |
595 | |
596 | public Scope members_field; |
597 | public Name fullname; |
598 | public ClassSymbol package_info; // see bug 6443073 |
599 | |
600 | public PackageSymbol(Name name, Type type, Symbol owner) { |
601 | super(0, name, type, owner); |
602 | this.kind = PCK; |
603 | this.members_field = null; |
604 | this.fullname = formFullName(name, owner); |
605 | } |
606 | |
607 | public PackageSymbol(Name name, Symbol owner) { |
608 | this(name, null, owner); |
609 | this.type = new PackageType(this); |
610 | } |
611 | |
612 | public String toString() { |
613 | return fullname.toString(); |
614 | } |
615 | |
616 | public Name getQualifiedName() { |
617 | return fullname; |
618 | } |
619 | |
620 | public boolean isUnnamed() { |
621 | return name.isEmpty() && owner != null; |
622 | } |
623 | |
624 | public Scope members() { |
625 | if (completer != null) complete(); |
626 | return members_field; |
627 | } |
628 | |
629 | public long flags() { |
630 | if (completer != null) complete(); |
631 | return flags_field; |
632 | } |
633 | |
634 | public List<Attribute.Compound> getAnnotationMirrors() { |
635 | if (completer != null) complete(); |
636 | assert attributes_field != null; |
637 | return attributes_field; |
638 | } |
639 | |
640 | /** A package "exists" if a type or package that exists has |
641 | * been seen within it. |
642 | */ |
643 | public boolean exists() { |
644 | return (flags_field & EXISTS) != 0; |
645 | } |
646 | |
647 | public ElementKind getKind() { |
648 | return ElementKind.PACKAGE; |
649 | } |
650 | |
651 | public Symbol getEnclosingElement() { |
652 | return null; |
653 | } |
654 | |
655 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
656 | return v.visitPackage(this, p); |
657 | } |
658 | } |
659 | |
660 | /** A class for class symbols |
661 | */ |
662 | public static class ClassSymbol extends TypeSymbol implements TypeElement { |
663 | |
664 | /** a scope for all class members; variables, methods and inner classes |
665 | * type parameters are not part of this scope |
666 | */ |
667 | public Scope members_field; |
668 | |
669 | /** the fully qualified name of the class, i.e. pck.outer.inner. |
670 | * null for anonymous classes |
671 | */ |
672 | public Name fullname; |
673 | |
674 | /** the fully qualified name of the class after converting to flat |
675 | * representation, i.e. pck.outer$inner, |
676 | * set externally for local and anonymous classes |
677 | */ |
678 | public Name flatname; |
679 | |
680 | /** the sourcefile where the class came from |
681 | */ |
682 | public JavaFileObject sourcefile; |
683 | |
684 | /** the classfile from where to load this class |
685 | * this will have extension .class or .java |
686 | */ |
687 | public JavaFileObject classfile; |
688 | |
689 | /** the constant pool of the class |
690 | */ |
691 | public Pool pool; |
692 | |
693 | public ClassSymbol(long flags, Name name, Type type, Symbol owner) { |
694 | super(flags, name, type, owner); |
695 | this.members_field = null; |
696 | this.fullname = formFullName(name, owner); |
697 | this.flatname = formFlatName(name, owner); |
698 | this.sourcefile = null; |
699 | this.classfile = null; |
700 | this.pool = null; |
701 | } |
702 | |
703 | public ClassSymbol(long flags, Name name, Symbol owner) { |
704 | this( |
705 | flags, |
706 | name, |
707 | new ClassType(Type.noType, null, null), |
708 | owner); |
709 | this.type.tsym = this; |
710 | } |
711 | |
712 | /** The Java source which this symbol represents. |
713 | */ |
714 | public String toString() { |
715 | return className(); |
716 | } |
717 | |
718 | public long flags() { |
719 | if (completer != null) complete(); |
720 | return flags_field; |
721 | } |
722 | |
723 | public Scope members() { |
724 | if (completer != null) complete(); |
725 | return members_field; |
726 | } |
727 | |
728 | public List<Attribute.Compound> getAnnotationMirrors() { |
729 | if (completer != null) complete(); |
730 | assert attributes_field != null; |
731 | return attributes_field; |
732 | } |
733 | |
734 | public Type erasure(Types types) { |
735 | if (erasure_field == null) |
736 | erasure_field = new ClassType(types.erasure(type.getEnclosingType()), |
737 | List.<Type>nil(), this); |
738 | return erasure_field; |
739 | } |
740 | |
741 | public String className() { |
742 | if (name.len == 0) |
743 | return |
744 | Log.getLocalizedString("anonymous.class", flatname); |
745 | else |
746 | return fullname.toString(); |
747 | } |
748 | |
749 | public Name getQualifiedName() { |
750 | return fullname; |
751 | } |
752 | |
753 | public Name flatName() { |
754 | return flatname; |
755 | } |
756 | |
757 | public boolean isSubClass(Symbol base, Types types) { |
758 | if (this == base) { |
759 | return true; |
760 | } else if ((base.flags() & INTERFACE) != 0) { |
761 | for (Type t = type; t.tag == CLASS; t = types.supertype(t)) |
762 | for (List<Type> is = types.interfaces(t); |
763 | is.nonEmpty(); |
764 | is = is.tail) |
765 | if (is.head.tsym.isSubClass(base, types)) return true; |
766 | } else { |
767 | for (Type t = type; t.tag == CLASS; t = types.supertype(t)) |
768 | if (t.tsym == base) return true; |
769 | } |
770 | return false; |
771 | } |
772 | |
773 | /** Complete the elaboration of this symbol's definition. |
774 | */ |
775 | public void complete() throws CompletionFailure { |
776 | try { |
777 | super.complete(); |
778 | } catch (CompletionFailure ex) { |
779 | // quiet error recovery |
780 | flags_field |= (PUBLIC|STATIC); |
781 | this.type = new ErrorType(this); |
782 | throw ex; |
783 | } |
784 | } |
785 | |
786 | public List<Type> getInterfaces() { |
787 | complete(); |
788 | if (type instanceof ClassType) { |
789 | ClassType t = (ClassType)type; |
790 | if (t.interfaces_field == null) // FIXME: shouldn't be null |
791 | t.interfaces_field = List.nil(); |
792 | return t.interfaces_field; |
793 | } else { |
794 | return List.nil(); |
795 | } |
796 | } |
797 | |
798 | public Type getSuperclass() { |
799 | complete(); |
800 | if (type instanceof ClassType) { |
801 | ClassType t = (ClassType)type; |
802 | if (t.supertype_field == null) // FIXME: shouldn't be null |
803 | t.supertype_field = Type.noType; |
804 | // An interface has no superclass; its supertype is Object. |
805 | return t.isInterface() |
806 | ? Type.noType |
807 | : t.supertype_field; |
808 | } else { |
809 | return Type.noType; |
810 | } |
811 | } |
812 | |
813 | public ElementKind getKind() { |
814 | long flags = flags(); |
815 | if ((flags & ANNOTATION) != 0) |
816 | return ElementKind.ANNOTATION_TYPE; |
817 | else if ((flags & INTERFACE) != 0) |
818 | return ElementKind.INTERFACE; |
819 | else if ((flags & ENUM) != 0) |
820 | return ElementKind.ENUM; |
821 | else |
822 | return ElementKind.CLASS; |
823 | } |
824 | |
825 | public NestingKind getNestingKind() { |
826 | complete(); |
827 | if (owner.kind == PCK) |
828 | return NestingKind.TOP_LEVEL; |
829 | else if (name.isEmpty()) |
830 | return NestingKind.ANONYMOUS; |
831 | else if (owner.kind == MTH) |
832 | return NestingKind.LOCAL; |
833 | else |
834 | return NestingKind.MEMBER; |
835 | } |
836 | |
837 | /** |
838 | * @deprecated this method should never be used by javac internally. |
839 | */ |
840 | @Override @Deprecated |
841 | public <A extends java.lang.annotation.Annotation> A getAnnotation(Class<A> annoType) { |
842 | return JavacElements.getAnnotation(this, annoType); |
843 | } |
844 | |
845 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
846 | return v.visitType(this, p); |
847 | } |
848 | } |
849 | |
850 | |
851 | /** A class for variable symbols |
852 | */ |
853 | public static class VarSymbol extends Symbol implements VariableElement { |
854 | |
855 | /** The variable's declaration position. |
856 | */ |
857 | public int pos = Position.NOPOS; |
858 | |
859 | /** The variable's address. Used for different purposes during |
860 | * flow analysis, translation and code generation. |
861 | * Flow analysis: |
862 | * If this is a blank final or local variable, its sequence number. |
863 | * Translation: |
864 | * If this is a private field, its access number. |
865 | * Code generation: |
866 | * If this is a local variable, its logical slot number. |
867 | */ |
868 | public int adr = -1; |
869 | |
870 | /** Construct a variable symbol, given its flags, name, type and owner. |
871 | */ |
872 | public VarSymbol(long flags, Name name, Type type, Symbol owner) { |
873 | super(VAR, flags, name, type, owner); |
874 | } |
875 | |
876 | /** Clone this symbol with new owner. |
877 | */ |
878 | public VarSymbol clone(Symbol newOwner) { |
879 | VarSymbol v = new VarSymbol(flags_field, name, type, newOwner); |
880 | v.pos = pos; |
881 | v.adr = adr; |
882 | v.data = data; |
883 | // System.out.println("clone " + v + " in " + newOwner);//DEBUG |
884 | return v; |
885 | } |
886 | |
887 | public String toString() { |
888 | return name.toString(); |
889 | } |
890 | |
891 | public Symbol asMemberOf(Type site, Types types) { |
892 | return new VarSymbol(flags_field, name, types.memberType(site, this), owner); |
893 | } |
894 | |
895 | public ElementKind getKind() { |
896 | long flags = flags(); |
897 | if ((flags & PARAMETER) != 0) { |
898 | if (isExceptionParameter()) |
899 | return ElementKind.EXCEPTION_PARAMETER; |
900 | else |
901 | return ElementKind.PARAMETER; |
902 | } else if ((flags & ENUM) != 0) { |
903 | return ElementKind.ENUM_CONSTANT; |
904 | } else if (owner.kind == TYP || owner.kind == ERR) { |
905 | return ElementKind.FIELD; |
906 | } else { |
907 | return ElementKind.LOCAL_VARIABLE; |
908 | } |
909 | } |
910 | |
911 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
912 | return v.visitVariable(this, p); |
913 | } |
914 | |
915 | public Object getConstantValue() { // Mirror API |
916 | return Constants.decode(getConstValue(), type); |
917 | } |
918 | |
919 | public void setLazyConstValue(final Env<AttrContext> env, |
920 | final Log log, |
921 | final Attr attr, |
922 | final JCTree.JCExpression initializer) |
923 | { |
924 | setData(new Callable<Object>() { |
925 | public Object call() { |
926 | JavaFileObject source = log.useSource(env.toplevel.sourcefile); |
927 | try { |
928 | // In order to catch self-references, we set |
929 | // the variable's declaration position to |
930 | // maximal possible value, effectively marking |
931 | // the variable as undefined. |
932 | int pos = VarSymbol.this.pos; |
933 | VarSymbol.this.pos = Position.MAXPOS; |
934 | Type itype = attr.attribExpr(initializer, env, type); |
935 | VarSymbol.this.pos = pos; |
936 | if (itype.constValue() != null) |
937 | return attr.coerce(itype, type).constValue(); |
938 | else |
939 | return null; |
940 | } finally { |
941 | log.useSource(source); |
942 | } |
943 | } |
944 | }); |
945 | } |
946 | |
947 | /** |
948 | * The variable's constant value, if this is a constant. |
949 | * Before the constant value is evaluated, it points to an |
950 | * initalizer environment. If this is not a constant, it can |
951 | * be used for other stuff. |
952 | */ |
953 | private Object data; |
954 | |
955 | public boolean isExceptionParameter() { |
956 | return data == ElementKind.EXCEPTION_PARAMETER; |
957 | } |
958 | |
959 | public Object getConstValue() { |
960 | // TODO: Consider if getConstValue and getConstantValue can be collapsed |
961 | if (data == ElementKind.EXCEPTION_PARAMETER) { |
962 | return null; |
963 | } else if (data instanceof Callable<?>) { |
964 | // In this case, this is final a variable, with an as |
965 | // yet unevaluated initializer. |
966 | Callable<?> eval = (Callable<?>)data; |
967 | data = null; // to make sure we don't evaluate this twice. |
968 | try { |
969 | data = eval.call(); |
970 | } catch (Exception ex) { |
971 | throw new AssertionError(ex); |
972 | } |
973 | } |
974 | return data; |
975 | } |
976 | |
977 | public void setData(Object data) { |
978 | assert !(data instanceof Env<?>) : this; |
979 | this.data = data; |
980 | } |
981 | } |
982 | |
983 | /** A class for method symbols. |
984 | */ |
985 | public static class MethodSymbol extends Symbol implements ExecutableElement { |
986 | |
987 | /** The code of the method. */ |
988 | public Code code = null; |
989 | |
990 | /** The parameters of the method. */ |
991 | public List<VarSymbol> params = null; |
992 | |
993 | /** The names of the parameters */ |
994 | public List<Name> savedParameterNames; |
995 | |
996 | /** For an attribute field accessor, its default value if any. |
997 | * The value is null if none appeared in the method |
998 | * declaration. |
999 | */ |
1000 | public Attribute defaultValue = null; |
1001 | |
1002 | /** Construct a method symbol, given its flags, name, type and owner. |
1003 | */ |
1004 | public MethodSymbol(long flags, Name name, Type type, Symbol owner) { |
1005 | super(MTH, flags, name, type, owner); |
1006 | assert owner.type.tag != TYPEVAR : owner + "." + name; |
1007 | } |
1008 | |
1009 | /** Clone this symbol with new owner. |
1010 | */ |
1011 | public MethodSymbol clone(Symbol newOwner) { |
1012 | MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner); |
1013 | m.code = code; |
1014 | return m; |
1015 | } |
1016 | |
1017 | /** The Java source which this symbol represents. |
1018 | */ |
1019 | public String toString() { |
1020 | if ((flags() & BLOCK) != 0) { |
1021 | return owner.name.toString(); |
1022 | } else { |
1023 | String s = (name == name.table.init) |
1024 | ? owner.name.toString() |
1025 | : name.toString(); |
1026 | if (type != null) { |
1027 | if (type.tag == FORALL) |
1028 | s = "<" + ((ForAll)type).getTypeArguments() + ">" + s; |
1029 | s += "(" + type.argtypes((flags() & VARARGS) != 0) + ")"; |
1030 | } |
1031 | return s; |
1032 | } |
1033 | } |
1034 | |
1035 | /** find a symbol that this (proxy method) symbol implements. |
1036 | * @param c The class whose members are searched for |
1037 | * implementations |
1038 | */ |
1039 | public Symbol implemented(TypeSymbol c, Types types) { |
1040 | Symbol impl = null; |
1041 | for (List<Type> is = types.interfaces(c.type); |
1042 | impl == null && is.nonEmpty(); |
1043 | is = is.tail) { |
1044 | TypeSymbol i = is.head.tsym; |
1045 | for (Scope.Entry e = i.members().lookup(name); |
1046 | impl == null && e.scope != null; |
1047 | e = e.next()) { |
1048 | if (this.overrides(e.sym, (TypeSymbol)owner, types, true) && |
1049 | // FIXME: I suspect the following requires a |
1050 | // subst() for a parametric return type. |
1051 | types.isSameType(type.getReturnType(), |
1052 | types.memberType(owner.type, e.sym).getReturnType())) { |
1053 | impl = e.sym; |
1054 | } |
1055 | if (impl == null) |
1056 | impl = implemented(i, types); |
1057 | } |
1058 | } |
1059 | return impl; |
1060 | } |
1061 | |
1062 | /** Will the erasure of this method be considered by the VM to |
1063 | * override the erasure of the other when seen from class `origin'? |
1064 | */ |
1065 | public boolean binaryOverrides(Symbol _other, TypeSymbol origin, Types types) { |
1066 | if (isConstructor() || _other.kind != MTH) return false; |
1067 | |
1068 | if (this == _other) return true; |
1069 | MethodSymbol other = (MethodSymbol)_other; |
1070 | |
1071 | // check for a direct implementation |
1072 | if (other.isOverridableIn((TypeSymbol)owner) && |
1073 | types.asSuper(owner.type, other.owner) != null && |
1074 | types.isSameType(erasure(types), other.erasure(types))) |
1075 | return true; |
1076 | |
1077 | // check for an inherited implementation |
1078 | return |
1079 | (flags() & ABSTRACT) == 0 && |
1080 | other.isOverridableIn(origin) && |
1081 | this.isMemberOf(origin, types) && |
1082 | types.isSameType(erasure(types), other.erasure(types)); |
1083 | } |
1084 | |
1085 | /** The implementation of this (abstract) symbol in class origin, |
1086 | * from the VM's point of view, null if method does not have an |
1087 | * implementation in class. |
1088 | * @param origin The class of which the implementation is a member. |
1089 | */ |
1090 | public MethodSymbol binaryImplementation(ClassSymbol origin, Types types) { |
1091 | for (TypeSymbol c = origin; c != null; c = types.supertype(c.type).tsym) { |
1092 | for (Scope.Entry e = c.members().lookup(name); |
1093 | e.scope != null; |
1094 | e = e.next()) { |
1095 | if (e.sym.kind == MTH && |
1096 | ((MethodSymbol)e.sym).binaryOverrides(this, origin, types)) |
1097 | return (MethodSymbol)e.sym; |
1098 | } |
1099 | } |
1100 | return null; |
1101 | } |
1102 | |
1103 | /** Does this symbol override `other' symbol, when both are seen as |
1104 | * members of class `origin'? It is assumed that _other is a member |
1105 | * of origin. |
1106 | * |
1107 | * It is assumed that both symbols have the same name. The static |
1108 | * modifier is ignored for this test. |
1109 | * |
1110 | * See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 |
1111 | */ |
1112 | public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) { |
1113 | if (isConstructor() || _other.kind != MTH) return false; |
1114 | |
1115 | if (this == _other) return true; |
1116 | MethodSymbol other = (MethodSymbol)_other; |
1117 | |
1118 | // check for a direct implementation |
1119 | if (other.isOverridableIn((TypeSymbol)owner) && |
1120 | types.asSuper(owner.type, other.owner) != null) { |
1121 | Type mt = types.memberType(owner.type, this); |
1122 | Type ot = types.memberType(owner.type, other); |
1123 | if (types.isSubSignature(mt, ot)) { |
1124 | if (!checkResult) |
1125 | return true; |
1126 | if (types.returnTypeSubstitutable(mt, ot)) |
1127 | return true; |
1128 | } |
1129 | } |
1130 | |
1131 | // check for an inherited implementation |
1132 | if ((flags() & ABSTRACT) != 0 || |
1133 | (other.flags() & ABSTRACT) == 0 || |
1134 | !other.isOverridableIn(origin) || |
1135 | !this.isMemberOf(origin, types)) |
1136 | return false; |
1137 | |
1138 | // assert types.asSuper(origin.type, other.owner) != null; |
1139 | Type mt = types.memberType(origin.type, this); |
1140 | Type ot = types.memberType(origin.type, other); |
1141 | return |
1142 | types.isSubSignature(mt, ot) && |
1143 | (!checkResult || types.resultSubtype(mt, ot, Warner.noWarnings)); |
1144 | } |
1145 | |
1146 | private boolean isOverridableIn(TypeSymbol origin) { |
1147 | // JLS3 8.4.6.1 |
1148 | switch ((int)(flags_field & Flags.AccessFlags)) { |
1149 | case Flags.PRIVATE: |
1150 | return false; |
1151 | case Flags.PUBLIC: |
1152 | return true; |
1153 | case Flags.PROTECTED: |
1154 | return (origin.flags() & INTERFACE) == 0; |
1155 | case 0: |
1156 | // for package private: can only override in the same |
1157 | // package |
1158 | return |
1159 | this.packge() == origin.packge() && |
1160 | (origin.flags() & INTERFACE) == 0; |
1161 | default: |
1162 | return false; |
1163 | } |
1164 | } |
1165 | |
1166 | /** The implementation of this (abstract) symbol in class origin; |
1167 | * null if none exists. Synthetic methods are not considered |
1168 | * as possible implementations. |
1169 | */ |
1170 | public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) { |
1171 | for (Type t = origin.type; t.tag == CLASS; t = types.supertype(t)) { |
1172 | TypeSymbol c = t.tsym; |
1173 | for (Scope.Entry e = c.members().lookup(name); |
1174 | e.scope != null; |
1175 | e = e.next()) { |
1176 | if (e.sym.kind == MTH) { |
1177 | MethodSymbol m = (MethodSymbol) e.sym; |
1178 | if (m.overrides(this, origin, types, checkResult) && |
1179 | (m.flags() & SYNTHETIC) == 0) |
1180 | return m; |
1181 | } |
1182 | } |
1183 | } |
1184 | // if origin is derived from a raw type, we might have missed |
1185 | // an implementation because we do not know enough about instantiations. |
1186 | // in this case continue with the supertype as origin. |
1187 | if (types.isDerivedRaw(origin.type)) |
1188 | return implementation(types.supertype(origin.type).tsym, types, checkResult); |
1189 | else |
1190 | return null; |
1191 | } |
1192 | |
1193 | public List<VarSymbol> params() { |
1194 | owner.complete(); |
1195 | if (params == null) { |
1196 | List<Name> names = savedParameterNames; |
1197 | savedParameterNames = null; |
1198 | if (names == null) { |
1199 | names = List.nil(); |
1200 | int i = 0; |
1201 | for (Type t : type.getParameterTypes()) |
1202 | names = names.prepend(name.table.fromString("arg" + i++)); |
1203 | names = names.reverse(); |
1204 | } |
1205 | ListBuffer<VarSymbol> buf = new ListBuffer<VarSymbol>(); |
1206 | for (Type t : type.getParameterTypes()) { |
1207 | buf.append(new VarSymbol(PARAMETER, names.head, t, this)); |
1208 | names = names.tail; |
1209 | } |
1210 | params = buf.toList(); |
1211 | } |
1212 | return params; |
1213 | } |
1214 | |
1215 | public Symbol asMemberOf(Type site, Types types) { |
1216 | return new MethodSymbol(flags_field, name, types.memberType(site, this), owner); |
1217 | } |
1218 | |
1219 | public ElementKind getKind() { |
1220 | if (name == name.table.init) |
1221 | return ElementKind.CONSTRUCTOR; |
1222 | else if (name == name.table.clinit) |
1223 | return ElementKind.STATIC_INIT; |
1224 | else |
1225 | return ElementKind.METHOD; |
1226 | } |
1227 | |
1228 | public Attribute getDefaultValue() { |
1229 | return defaultValue; |
1230 | } |
1231 | |
1232 | public List<VarSymbol> getParameters() { |
1233 | return params(); |
1234 | } |
1235 | |
1236 | public boolean isVarArgs() { |
1237 | return (flags() & VARARGS) != 0; |
1238 | } |
1239 | |
1240 | public <R, P> R accept(ElementVisitor<R, P> v, P p) { |
1241 | return v.visitExecutable(this, p); |
1242 | } |
1243 | |
1244 | public Type getReturnType() { |
1245 | return asType().getReturnType(); |
1246 | } |
1247 | |
1248 | public List<Type> getThrownTypes() { |
1249 | return asType().getThrownTypes(); |
1250 | } |
1251 | } |
1252 | |
1253 | /** A class for predefined operators. |
1254 | */ |
1255 | public static class OperatorSymbol extends MethodSymbol { |
1256 | |
1257 | public int opcode; |
1258 | |
1259 | public OperatorSymbol(Name name, Type type, int opcode, Symbol owner) { |
1260 | super(PUBLIC | STATIC, name, type, owner); |
1261 | this.opcode = opcode; |
1262 | } |
1263 | } |
1264 | |
1265 | /** Symbol completer interface. |
1266 | */ |
1267 | public static interface Completer { |
1268 | void complete(Symbol sym) throws CompletionFailure; |
1269 | } |
1270 | |
1271 | public static class CompletionFailure extends RuntimeException { |
1272 | private static final long serialVersionUID = 0; |
1273 | public Symbol sym; |
1274 | |
1275 | /** A localized string describing the failure. |
1276 | */ |
1277 | public String errmsg; |
1278 | |
1279 | public CompletionFailure(Symbol sym, String errmsg) { |
1280 | this.sym = sym; |
1281 | this.errmsg = errmsg; |
1282 | // this.printStackTrace();//DEBUG |
1283 | } |
1284 | |
1285 | public String getMessage() { |
1286 | return errmsg; |
1287 | } |
1288 | |
1289 | @Override |
1290 | public CompletionFailure initCause(Throwable cause) { |
1291 | super.initCause(cause); |
1292 | return this; |
1293 | } |
1294 | |
1295 | } |
1296 | } |