src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 2113
7d266a2b31b2
child 2233
4a6f853f8721
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

duke@1 1 /*
jjg@1521 2 * Copyright (c) 1997, 2013, 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.javadoc;
duke@1 27
jjg@197 28 import java.io.File;
jjg@197 29 import java.io.IOException;
jjg@197 30 import java.lang.reflect.Modifier;
jjg@197 31 import java.net.URI;
jjg@197 32 import java.util.HashSet;
jjg@197 33 import java.util.Set;
jjg@1443 34
jjg@197 35 import javax.tools.FileObject;
jjg@197 36 import javax.tools.JavaFileManager.Location;
jjg@197 37 import javax.tools.StandardJavaFileManager;
jjg@197 38 import javax.tools.StandardLocation;
jjg@197 39
duke@1 40 import com.sun.javadoc.*;
jjg@1443 41 import com.sun.source.util.TreePath;
duke@1 42 import com.sun.tools.javac.code.Flags;
duke@1 43 import com.sun.tools.javac.code.Kinds;
duke@1 44 import com.sun.tools.javac.code.Scope;
duke@1 45 import com.sun.tools.javac.code.Symbol;
duke@1 46 import com.sun.tools.javac.code.Symbol.*;
jjg@197 47 import com.sun.tools.javac.code.Type;
jjg@197 48 import com.sun.tools.javac.code.Type.ClassType;
mcimadamore@1902 49 import com.sun.tools.javac.code.TypeTag;
duke@1 50 import com.sun.tools.javac.comp.AttrContext;
duke@1 51 import com.sun.tools.javac.comp.Env;
duke@1 52 import com.sun.tools.javac.tree.JCTree;
duke@1 53 import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
duke@1 54 import com.sun.tools.javac.tree.JCTree.JCImport;
duke@1 55 import com.sun.tools.javac.tree.TreeInfo;
jjg@197 56 import com.sun.tools.javac.util.List;
jjg@197 57 import com.sun.tools.javac.util.ListBuffer;
jjg@197 58 import com.sun.tools.javac.util.Name;
jjg@113 59 import com.sun.tools.javac.util.Names;
jjg@197 60 import com.sun.tools.javac.util.Position;
duke@1 61 import static com.sun.tools.javac.code.Kinds.*;
jjg@1374 62 import static com.sun.tools.javac.code.TypeTag.CLASS;
jjg@1127 63 import static com.sun.tools.javac.tree.JCTree.Tag.*;
duke@1 64
duke@1 65 /**
duke@1 66 * Represents a java class and provides access to information
duke@1 67 * about the class, the class' comment and tags, and the
duke@1 68 * members of the class. A ClassDocImpl only exists if it was
duke@1 69 * processed in this run of javadoc. References to classes
duke@1 70 * which may or may not have been processed in this run are
duke@1 71 * referred to using Type (which can be converted to ClassDocImpl,
duke@1 72 * if possible).
duke@1 73 *
jjg@1359 74 * <p><b>This is NOT part of any supported API.
jjg@1359 75 * If you write code that depends on this, you do so at your own risk.
jjg@1359 76 * This code and its internal interfaces are subject to change or
jjg@1359 77 * deletion without notice.</b>
jjg@1359 78 *
duke@1 79 * @see Type
duke@1 80 *
duke@1 81 * @since 1.2
duke@1 82 * @author Robert Field
duke@1 83 * @author Neal Gafter (rewrite)
duke@1 84 * @author Scott Seligman (generics, enums, annotations)
duke@1 85 */
duke@1 86
duke@1 87 public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
duke@1 88
duke@1 89 public final ClassType type; // protected->public for debugging
duke@1 90 protected final ClassSymbol tsym;
duke@1 91
duke@1 92 boolean isIncluded = false; // Set in RootDocImpl
duke@1 93
duke@1 94 private SerializedForm serializedForm;
duke@1 95
duke@1 96 /**
duke@1 97 * Constructor
duke@1 98 */
duke@1 99 public ClassDocImpl(DocEnv env, ClassSymbol sym) {
jjg@1443 100 this(env, sym, null);
duke@1 101 }
duke@1 102
duke@1 103 /**
duke@1 104 * Constructor
duke@1 105 */
jjg@1443 106 public ClassDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {
jjg@1443 107 super(env, sym, treePath);
duke@1 108 this.type = (ClassType)sym.type;
duke@1 109 this.tsym = sym;
duke@1 110 }
duke@1 111
bpatel@1691 112 public com.sun.javadoc.Type getElementType() {
bpatel@1691 113 return null;
bpatel@1691 114 }
bpatel@1691 115
duke@1 116 /**
duke@1 117 * Returns the flags in terms of javac's flags
duke@1 118 */
duke@1 119 protected long getFlags() {
duke@1 120 return getFlags(tsym);
duke@1 121 }
duke@1 122
duke@1 123 /**
duke@1 124 * Returns the flags of a ClassSymbol in terms of javac's flags
duke@1 125 */
duke@1 126 static long getFlags(ClassSymbol clazz) {
duke@1 127 while (true) {
duke@1 128 try {
duke@1 129 return clazz.flags();
duke@1 130 } catch (CompletionFailure ex) {
jjg@1987 131 /* Quietly ignore completion failures.
jjg@1987 132 * Note that a CompletionFailure can only
jjg@1987 133 * occur as a result of calling complete(),
jjg@1987 134 * which will always remove the current
jjg@1987 135 * completer, leaving it to be null or
jjg@1987 136 * follow-up completer. Thus the loop
jjg@1987 137 * is guaranteed to eventually terminate.
jjg@1987 138 */
duke@1 139 }
duke@1 140 }
duke@1 141 }
duke@1 142
duke@1 143 /**
duke@1 144 * Is a ClassSymbol an annotation type?
duke@1 145 */
duke@1 146 static boolean isAnnotationType(ClassSymbol clazz) {
duke@1 147 return (getFlags(clazz) & Flags.ANNOTATION) != 0;
duke@1 148 }
duke@1 149
duke@1 150 /**
duke@1 151 * Identify the containing class
duke@1 152 */
duke@1 153 protected ClassSymbol getContainingClass() {
duke@1 154 return tsym.owner.enclClass();
duke@1 155 }
duke@1 156
duke@1 157 /**
duke@1 158 * Return true if this is a class, not an interface.
duke@1 159 */
jjg@910 160 @Override
duke@1 161 public boolean isClass() {
duke@1 162 return !Modifier.isInterface(getModifiers());
duke@1 163 }
duke@1 164
duke@1 165 /**
duke@1 166 * Return true if this is a ordinary class,
duke@1 167 * not an enumeration, exception, an error, or an interface.
duke@1 168 */
jjg@910 169 @Override
duke@1 170 public boolean isOrdinaryClass() {
duke@1 171 if (isEnum() || isInterface() || isAnnotationType()) {
duke@1 172 return false;
duke@1 173 }
jjg@1374 174 for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
duke@1 175 if (t.tsym == env.syms.errorType.tsym ||
duke@1 176 t.tsym == env.syms.exceptionType.tsym) {
duke@1 177 return false;
duke@1 178 }
duke@1 179 }
duke@1 180 return true;
duke@1 181 }
duke@1 182
duke@1 183 /**
duke@1 184 * Return true if this is an enumeration.
duke@1 185 * (For legacy doclets, return false.)
duke@1 186 */
jjg@910 187 @Override
duke@1 188 public boolean isEnum() {
duke@1 189 return (getFlags() & Flags.ENUM) != 0
duke@1 190 &&
duke@1 191 !env.legacyDoclet;
duke@1 192 }
duke@1 193
duke@1 194 /**
duke@1 195 * Return true if this is an interface, but not an annotation type.
duke@1 196 * Overridden by AnnotationTypeDocImpl.
duke@1 197 */
jjg@910 198 @Override
duke@1 199 public boolean isInterface() {
duke@1 200 return Modifier.isInterface(getModifiers());
duke@1 201 }
duke@1 202
duke@1 203 /**
duke@1 204 * Return true if this is an exception class
duke@1 205 */
jjg@910 206 @Override
duke@1 207 public boolean isException() {
duke@1 208 if (isEnum() || isInterface() || isAnnotationType()) {
duke@1 209 return false;
duke@1 210 }
jjg@1374 211 for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
duke@1 212 if (t.tsym == env.syms.exceptionType.tsym) {
duke@1 213 return true;
duke@1 214 }
duke@1 215 }
duke@1 216 return false;
duke@1 217 }
duke@1 218
duke@1 219 /**
duke@1 220 * Return true if this is an error class
duke@1 221 */
jjg@910 222 @Override
duke@1 223 public boolean isError() {
duke@1 224 if (isEnum() || isInterface() || isAnnotationType()) {
duke@1 225 return false;
duke@1 226 }
jjg@1374 227 for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
duke@1 228 if (t.tsym == env.syms.errorType.tsym) {
duke@1 229 return true;
duke@1 230 }
duke@1 231 }
duke@1 232 return false;
duke@1 233 }
duke@1 234
duke@1 235 /**
duke@1 236 * Return true if this is a throwable class
duke@1 237 */
duke@1 238 public boolean isThrowable() {
duke@1 239 if (isEnum() || isInterface() || isAnnotationType()) {
duke@1 240 return false;
duke@1 241 }
jjg@1374 242 for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
duke@1 243 if (t.tsym == env.syms.throwableType.tsym) {
duke@1 244 return true;
duke@1 245 }
duke@1 246 }
duke@1 247 return false;
duke@1 248 }
duke@1 249
duke@1 250 /**
duke@1 251 * Return true if this class is abstract
duke@1 252 */
duke@1 253 public boolean isAbstract() {
duke@1 254 return Modifier.isAbstract(getModifiers());
duke@1 255 }
duke@1 256
duke@1 257 /**
duke@1 258 * Returns true if this class was synthesized by the compiler.
duke@1 259 */
duke@1 260 public boolean isSynthetic() {
duke@1 261 return (getFlags() & Flags.SYNTHETIC) != 0;
duke@1 262 }
duke@1 263
duke@1 264 /**
duke@1 265 * Return true if this class is included in the active set.
duke@1 266 * A ClassDoc is included iff either it is specified on the
duke@1 267 * commandline, or if it's containing package is specified
duke@1 268 * on the command line, or if it is a member class of an
duke@1 269 * included class.
duke@1 270 */
duke@1 271
duke@1 272 public boolean isIncluded() {
duke@1 273 if (isIncluded) {
duke@1 274 return true;
duke@1 275 }
duke@1 276 if (env.shouldDocument(tsym)) {
duke@1 277 // Class is nameable from top-level and
duke@1 278 // the class and all enclosing classes
duke@1 279 // pass the modifier filter.
duke@1 280 if (containingPackage().isIncluded()) {
duke@1 281 return isIncluded=true;
duke@1 282 }
duke@1 283 ClassDoc outer = containingClass();
duke@1 284 if (outer != null && outer.isIncluded()) {
duke@1 285 return isIncluded=true;
duke@1 286 }
duke@1 287 }
duke@1 288 return false;
duke@1 289 }
duke@1 290
vromero@1454 291 public boolean isFunctionalInterface() {
bpatel@1998 292 return env.types.isFunctionalInterface(tsym) && env.source.allowLambda();
vromero@1454 293 }
vromero@1454 294
duke@1 295 /**
duke@1 296 * Return the package that this class is contained in.
duke@1 297 */
jjg@910 298 @Override
duke@1 299 public PackageDoc containingPackage() {
duke@1 300 PackageDocImpl p = env.getPackageDoc(tsym.packge());
jjg@197 301 if (p.setDocPath == false) {
jjg@197 302 FileObject docPath;
jjg@197 303 try {
jjg@197 304 Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
jjg@197 305 ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
jjg@197 306
jjg@197 307 docPath = env.fileManager.getFileForInput(
jjg@197 308 location, p.qualifiedName(), "package.html");
jjg@197 309 } catch (IOException e) {
jjg@197 310 docPath = null;
duke@1 311 }
jjg@197 312
jjg@197 313 if (docPath == null) {
jjg@197 314 // fall back on older semantics of looking in same directory as
jjg@197 315 // source file for this class
jjg@197 316 SourcePosition po = position();
jjg@197 317 if (env.fileManager instanceof StandardJavaFileManager &&
jjg@197 318 po instanceof SourcePositionImpl) {
jjg@197 319 URI uri = ((SourcePositionImpl) po).filename.toUri();
jjg@197 320 if ("file".equals(uri.getScheme())) {
jjg@400 321 File f = new File(uri);
jjg@197 322 File dir = f.getParentFile();
jjg@197 323 if (dir != null) {
jjg@197 324 File pf = new File(dir, "package.html");
jjg@197 325 if (pf.exists()) {
jjg@197 326 StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
jjg@197 327 docPath = sfm.getJavaFileObjects(pf).iterator().next();
jjg@197 328 }
jjg@197 329 }
jjg@197 330
jjg@197 331 }
jjg@197 332 }
jjg@197 333 }
jjg@197 334
jjg@197 335 p.setDocPath(docPath);
duke@1 336 }
duke@1 337 return p;
duke@1 338 }
duke@1 339
duke@1 340 /**
duke@1 341 * Return the class name without package qualifier - but with
duke@1 342 * enclosing class qualifier - as a String.
duke@1 343 * <pre>
duke@1 344 * Examples:
duke@1 345 * for java.util.Hashtable
duke@1 346 * return Hashtable
duke@1 347 * for java.util.Map.Entry
duke@1 348 * return Map.Entry
duke@1 349 * </pre>
duke@1 350 */
duke@1 351 public String name() {
jjg@1706 352 if (name == null) {
jjg@1706 353 name = getClassName(tsym, false);
jjg@1706 354 }
jjg@1706 355 return name;
duke@1 356 }
duke@1 357
jjg@1706 358 private String name;
jjg@1706 359
duke@1 360 /**
duke@1 361 * Return the qualified class name as a String.
duke@1 362 * <pre>
duke@1 363 * Example:
duke@1 364 * for java.util.Hashtable
duke@1 365 * return java.util.Hashtable
duke@1 366 * if no qualifier, just return flat name
duke@1 367 * </pre>
duke@1 368 */
duke@1 369 public String qualifiedName() {
jjg@1706 370 if (qualifiedName == null) {
jjg@1706 371 qualifiedName = getClassName(tsym, true);
jjg@1706 372 }
jjg@1706 373 return qualifiedName;
duke@1 374 }
duke@1 375
jjg@1706 376 private String qualifiedName;
jjg@1706 377
duke@1 378 /**
duke@1 379 * Return unqualified name of type excluding any dimension information.
duke@1 380 * <p>
duke@1 381 * For example, a two dimensional array of String returns 'String'.
duke@1 382 */
duke@1 383 public String typeName() {
duke@1 384 return name();
duke@1 385 }
duke@1 386
duke@1 387 /**
duke@1 388 * Return qualified name of type excluding any dimension information.
duke@1 389 *<p>
duke@1 390 * For example, a two dimensional array of String
duke@1 391 * returns 'java.lang.String'.
duke@1 392 */
duke@1 393 public String qualifiedTypeName() {
duke@1 394 return qualifiedName();
duke@1 395 }
duke@1 396
duke@1 397 /**
duke@1 398 * Return the simple name of this type.
duke@1 399 */
duke@1 400 public String simpleTypeName() {
jjg@1706 401 if (simpleTypeName == null) {
jjg@1706 402 simpleTypeName = tsym.name.toString();
jjg@1706 403 }
jjg@1706 404 return simpleTypeName;
duke@1 405 }
duke@1 406
jjg@1706 407 private String simpleTypeName;
jjg@1706 408
duke@1 409 /**
duke@1 410 * Return the qualified name and any type parameters.
duke@1 411 * Each parameter is a type variable with optional bounds.
duke@1 412 */
jjg@910 413 @Override
duke@1 414 public String toString() {
duke@1 415 return classToString(env, tsym, true);
duke@1 416 }
duke@1 417
duke@1 418 /**
duke@1 419 * Return the class name as a string. If "full" is true the name is
duke@1 420 * qualified, otherwise it is qualified by its enclosing class(es) only.
duke@1 421 */
duke@1 422 static String getClassName(ClassSymbol c, boolean full) {
duke@1 423 if (full) {
duke@1 424 return c.getQualifiedName().toString();
duke@1 425 } else {
duke@1 426 String n = "";
duke@1 427 for ( ; c != null; c = c.owner.enclClass()) {
duke@1 428 n = c.name + (n.equals("") ? "" : ".") + n;
duke@1 429 }
duke@1 430 return n;
duke@1 431 }
duke@1 432 }
duke@1 433
duke@1 434 /**
duke@1 435 * Return the class name with any type parameters as a string.
duke@1 436 * Each parameter is a type variable with optional bounds.
duke@1 437 * If "full" is true all names are qualified, otherwise they are
duke@1 438 * qualified by their enclosing class(es) only.
duke@1 439 */
duke@1 440 static String classToString(DocEnv env, ClassSymbol c, boolean full) {
jjg@910 441 StringBuilder s = new StringBuilder();
duke@1 442 if (!c.isInner()) { // if c is not an inner class
duke@1 443 s.append(getClassName(c, full));
duke@1 444 } else {
duke@1 445 // c is an inner class, so include type params of outer.
duke@1 446 ClassSymbol encl = c.owner.enclClass();
duke@1 447 s.append(classToString(env, encl, full))
duke@1 448 .append('.')
duke@1 449 .append(c.name);
duke@1 450 }
duke@1 451 s.append(TypeMaker.typeParametersString(env, c, full));
duke@1 452 return s.toString();
duke@1 453 }
duke@1 454
duke@1 455 /**
duke@1 456 * Is this class (or any enclosing class) generic? That is, does
duke@1 457 * it have type parameters?
duke@1 458 */
duke@1 459 static boolean isGeneric(ClassSymbol c) {
duke@1 460 return c.type.allparams().nonEmpty();
duke@1 461 }
duke@1 462
duke@1 463 /**
duke@1 464 * Return the formal type parameters of this class or interface.
duke@1 465 * Return an empty array if there are none.
duke@1 466 */
duke@1 467 public TypeVariable[] typeParameters() {
duke@1 468 if (env.legacyDoclet) {
duke@1 469 return new TypeVariable[0];
duke@1 470 }
duke@1 471 TypeVariable res[] = new TypeVariable[type.getTypeArguments().length()];
duke@1 472 TypeMaker.getTypes(env, type.getTypeArguments(), res);
duke@1 473 return res;
duke@1 474 }
duke@1 475
duke@1 476 /**
duke@1 477 * Return the type parameter tags of this class or interface.
duke@1 478 */
duke@1 479 public ParamTag[] typeParamTags() {
duke@1 480 return (env.legacyDoclet)
duke@1 481 ? new ParamTag[0]
duke@1 482 : comment().typeParamTags();
duke@1 483 }
duke@1 484
duke@1 485 /**
duke@1 486 * Return the modifier string for this class. If it's an interface
duke@1 487 * exclude 'abstract' keyword from the modifier string
duke@1 488 */
jjg@910 489 @Override
duke@1 490 public String modifiers() {
duke@1 491 return Modifier.toString(modifierSpecifier());
duke@1 492 }
duke@1 493
jjg@910 494 @Override
duke@1 495 public int modifierSpecifier() {
duke@1 496 int modifiers = getModifiers();
duke@1 497 return (isInterface() || isAnnotationType())
duke@1 498 ? modifiers & ~Modifier.ABSTRACT
duke@1 499 : modifiers;
duke@1 500 }
duke@1 501
duke@1 502 /**
duke@1 503 * Return the superclass of this class
duke@1 504 *
duke@1 505 * @return the ClassDocImpl for the superclass of this class, null
duke@1 506 * if there is no superclass.
duke@1 507 */
duke@1 508 public ClassDoc superclass() {
duke@1 509 if (isInterface() || isAnnotationType()) return null;
duke@1 510 if (tsym == env.syms.objectType.tsym) return null;
duke@1 511 ClassSymbol c = (ClassSymbol)env.types.supertype(type).tsym;
duke@1 512 if (c == null || c == tsym) c = (ClassSymbol)env.syms.objectType.tsym;
duke@1 513 return env.getClassDoc(c);
duke@1 514 }
duke@1 515
duke@1 516 /**
duke@1 517 * Return the superclass of this class. Return null if this is an
duke@1 518 * interface. A superclass is represented by either a
duke@1 519 * <code>ClassDoc</code> or a <code>ParameterizedType</code>.
duke@1 520 */
duke@1 521 public com.sun.javadoc.Type superclassType() {
duke@1 522 if (isInterface() || isAnnotationType() ||
duke@1 523 (tsym == env.syms.objectType.tsym))
duke@1 524 return null;
duke@1 525 Type sup = env.types.supertype(type);
duke@1 526 return TypeMaker.getType(env,
mcimadamore@1902 527 (sup.hasTag(TypeTag.NONE)) ? env.syms.objectType : sup);
duke@1 528 }
duke@1 529
duke@1 530 /**
duke@1 531 * Test whether this class is a subclass of the specified class.
duke@1 532 *
duke@1 533 * @param cd the candidate superclass.
duke@1 534 * @return true if cd is a superclass of this class.
duke@1 535 */
duke@1 536 public boolean subclassOf(ClassDoc cd) {
duke@1 537 return tsym.isSubClass(((ClassDocImpl)cd).tsym, env.types);
duke@1 538 }
duke@1 539
duke@1 540 /**
duke@1 541 * Return interfaces implemented by this class or interfaces
duke@1 542 * extended by this interface.
duke@1 543 *
duke@1 544 * @return An array of ClassDocImpl representing the interfaces.
duke@1 545 * Return an empty array if there are no interfaces.
duke@1 546 */
duke@1 547 public ClassDoc[] interfaces() {
duke@1 548 ListBuffer<ClassDocImpl> ta = new ListBuffer<ClassDocImpl>();
duke@1 549 for (Type t : env.types.interfaces(type)) {
duke@1 550 ta.append(env.getClassDoc((ClassSymbol)t.tsym));
duke@1 551 }
duke@1 552 //### Cache ta here?
duke@1 553 return ta.toArray(new ClassDocImpl[ta.length()]);
duke@1 554 }
duke@1 555
duke@1 556 /**
duke@1 557 * Return interfaces implemented by this class or interfaces extended
duke@1 558 * by this interface. Includes only directly-declared interfaces, not
duke@1 559 * inherited interfaces.
duke@1 560 * Return an empty array if there are no interfaces.
duke@1 561 */
duke@1 562 public com.sun.javadoc.Type[] interfaceTypes() {
duke@1 563 //### Cache result here?
duke@1 564 return TypeMaker.getTypes(env, env.types.interfaces(type));
duke@1 565 }
duke@1 566
duke@1 567 /**
duke@1 568 * Return fields in class.
duke@1 569 * @param filter include only the included fields if filter==true
duke@1 570 */
duke@1 571 public FieldDoc[] fields(boolean filter) {
duke@1 572 return fields(filter, false);
duke@1 573 }
duke@1 574
duke@1 575 /**
duke@1 576 * Return included fields in class.
duke@1 577 */
duke@1 578 public FieldDoc[] fields() {
duke@1 579 return fields(true, false);
duke@1 580 }
duke@1 581
duke@1 582 /**
duke@1 583 * Return the enum constants if this is an enum type.
duke@1 584 */
duke@1 585 public FieldDoc[] enumConstants() {
duke@1 586 return fields(false, true);
duke@1 587 }
duke@1 588
duke@1 589 /**
duke@1 590 * Return fields in class.
duke@1 591 * @param filter if true, return only the included fields
duke@1 592 * @param enumConstants if true, return the enum constants instead
duke@1 593 */
duke@1 594 private FieldDoc[] fields(boolean filter, boolean enumConstants) {
duke@1 595 List<FieldDocImpl> fields = List.nil();
duke@1 596 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
duke@1 597 if (e.sym != null && e.sym.kind == VAR) {
duke@1 598 VarSymbol s = (VarSymbol)e.sym;
duke@1 599 boolean isEnum = ((s.flags() & Flags.ENUM) != 0) &&
duke@1 600 !env.legacyDoclet;
duke@1 601 if (isEnum == enumConstants &&
duke@1 602 (!filter || env.shouldDocument(s))) {
duke@1 603 fields = fields.prepend(env.getFieldDoc(s));
duke@1 604 }
duke@1 605 }
duke@1 606 }
duke@1 607 return fields.toArray(new FieldDocImpl[fields.length()]);
duke@1 608 }
duke@1 609
duke@1 610 /**
duke@1 611 * Return methods in class.
duke@1 612 * This method is overridden by AnnotationTypeDocImpl.
duke@1 613 *
duke@1 614 * @param filter include only the included methods if filter==true
duke@1 615 * @return an array of MethodDocImpl for representing the visible
duke@1 616 * methods in this class. Does not include constructors.
duke@1 617 */
duke@1 618 public MethodDoc[] methods(boolean filter) {
jjg@113 619 Names names = tsym.name.table.names;
duke@1 620 List<MethodDocImpl> methods = List.nil();
duke@1 621 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
jjg@2113 622 if (e.sym != null
jjg@2113 623 && e.sym.kind == Kinds.MTH
jjg@2113 624 && e.sym.name != names.init
jjg@2113 625 && e.sym.name != names.clinit) {
duke@1 626 MethodSymbol s = (MethodSymbol)e.sym;
duke@1 627 if (!filter || env.shouldDocument(s)) {
duke@1 628 methods = methods.prepend(env.getMethodDoc(s));
duke@1 629 }
duke@1 630 }
duke@1 631 }
duke@1 632 //### Cache methods here?
duke@1 633 return methods.toArray(new MethodDocImpl[methods.length()]);
duke@1 634 }
duke@1 635
duke@1 636 /**
duke@1 637 * Return included methods in class.
duke@1 638 *
duke@1 639 * @return an array of MethodDocImpl for representing the visible
duke@1 640 * methods in this class. Does not include constructors.
duke@1 641 */
duke@1 642 public MethodDoc[] methods() {
duke@1 643 return methods(true);
duke@1 644 }
duke@1 645
duke@1 646 /**
duke@1 647 * Return constructors in class.
duke@1 648 *
duke@1 649 * @param filter include only the included constructors if filter==true
duke@1 650 * @return an array of ConstructorDocImpl for representing the visible
duke@1 651 * constructors in this class.
duke@1 652 */
duke@1 653 public ConstructorDoc[] constructors(boolean filter) {
jjg@113 654 Names names = tsym.name.table.names;
duke@1 655 List<ConstructorDocImpl> constructors = List.nil();
duke@1 656 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
duke@1 657 if (e.sym != null &&
duke@1 658 e.sym.kind == Kinds.MTH && e.sym.name == names.init) {
duke@1 659 MethodSymbol s = (MethodSymbol)e.sym;
duke@1 660 if (!filter || env.shouldDocument(s)) {
duke@1 661 constructors = constructors.prepend(env.getConstructorDoc(s));
duke@1 662 }
duke@1 663 }
duke@1 664 }
duke@1 665 //### Cache constructors here?
duke@1 666 return constructors.toArray(new ConstructorDocImpl[constructors.length()]);
duke@1 667 }
duke@1 668
duke@1 669 /**
duke@1 670 * Return included constructors in class.
duke@1 671 *
duke@1 672 * @return an array of ConstructorDocImpl for representing the visible
duke@1 673 * constructors in this class.
duke@1 674 */
duke@1 675 public ConstructorDoc[] constructors() {
duke@1 676 return constructors(true);
duke@1 677 }
duke@1 678
duke@1 679 /**
duke@1 680 * Adds all inner classes of this class, and their
duke@1 681 * inner classes recursively, to the list l.
duke@1 682 */
duke@1 683 void addAllClasses(ListBuffer<ClassDocImpl> l, boolean filtered) {
duke@1 684 try {
duke@1 685 if (isSynthetic()) return;
duke@1 686 // sometimes synthetic classes are not marked synthetic
duke@1 687 if (!JavadocTool.isValidClassName(tsym.name.toString())) return;
duke@1 688 if (filtered && !env.shouldDocument(tsym)) return;
duke@1 689 if (l.contains(this)) return;
duke@1 690 l.append(this);
duke@1 691 List<ClassDocImpl> more = List.nil();
duke@1 692 for (Scope.Entry e = tsym.members().elems; e != null;
duke@1 693 e = e.sibling) {
duke@1 694 if (e.sym != null && e.sym.kind == Kinds.TYP) {
duke@1 695 ClassSymbol s = (ClassSymbol)e.sym;
duke@1 696 ClassDocImpl c = env.getClassDoc(s);
duke@1 697 if (c.isSynthetic()) continue;
duke@1 698 if (c != null) more = more.prepend(c);
duke@1 699 }
duke@1 700 }
duke@1 701 // this extra step preserves the ordering from oldjavadoc
duke@1 702 for (; more.nonEmpty(); more=more.tail) {
duke@1 703 more.head.addAllClasses(l, filtered);
duke@1 704 }
duke@1 705 } catch (CompletionFailure e) {
duke@1 706 // quietly ignore completion failures
duke@1 707 }
duke@1 708 }
duke@1 709
duke@1 710 /**
duke@1 711 * Return inner classes within this class.
duke@1 712 *
duke@1 713 * @param filter include only the included inner classes if filter==true.
duke@1 714 * @return an array of ClassDocImpl for representing the visible
duke@1 715 * classes defined in this class. Anonymous and local classes
duke@1 716 * are not included.
duke@1 717 */
duke@1 718 public ClassDoc[] innerClasses(boolean filter) {
duke@1 719 ListBuffer<ClassDocImpl> innerClasses = new ListBuffer<ClassDocImpl>();
duke@1 720 for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
duke@1 721 if (e.sym != null && e.sym.kind == Kinds.TYP) {
duke@1 722 ClassSymbol s = (ClassSymbol)e.sym;
duke@1 723 if ((s.flags_field & Flags.SYNTHETIC) != 0) continue;
duke@1 724 if (!filter || env.isVisible(s)) {
duke@1 725 innerClasses.prepend(env.getClassDoc(s));
duke@1 726 }
duke@1 727 }
duke@1 728 }
duke@1 729 //### Cache classes here?
duke@1 730 return innerClasses.toArray(new ClassDocImpl[innerClasses.length()]);
duke@1 731 }
duke@1 732
duke@1 733 /**
duke@1 734 * Return included inner classes within this class.
duke@1 735 *
duke@1 736 * @return an array of ClassDocImpl for representing the visible
duke@1 737 * classes defined in this class. Anonymous and local classes
duke@1 738 * are not included.
duke@1 739 */
duke@1 740 public ClassDoc[] innerClasses() {
duke@1 741 return innerClasses(true);
duke@1 742 }
duke@1 743
duke@1 744 /**
duke@1 745 * Find a class within the context of this class.
duke@1 746 * Search order: qualified name, in this class (inner),
duke@1 747 * in this package, in the class imports, in the package
duke@1 748 * imports.
duke@1 749 * Return the ClassDocImpl if found, null if not found.
duke@1 750 */
duke@1 751 //### The specified search order is not the normal rule the
duke@1 752 //### compiler would use. Leave as specified or change it?
duke@1 753 public ClassDoc findClass(String className) {
duke@1 754 ClassDoc searchResult = searchClass(className);
duke@1 755 if (searchResult == null) {
duke@1 756 ClassDocImpl enclosingClass = (ClassDocImpl)containingClass();
duke@1 757 //Expand search space to include enclosing class.
duke@1 758 while (enclosingClass != null && enclosingClass.containingClass() != null) {
duke@1 759 enclosingClass = (ClassDocImpl)enclosingClass.containingClass();
duke@1 760 }
duke@1 761 searchResult = enclosingClass == null ?
duke@1 762 null : enclosingClass.searchClass(className);
duke@1 763 }
duke@1 764 return searchResult;
duke@1 765 }
duke@1 766
duke@1 767 private ClassDoc searchClass(String className) {
jjg@113 768 Names names = tsym.name.table.names;
duke@1 769
duke@1 770 // search by qualified name first
duke@1 771 ClassDoc cd = env.lookupClass(className);
duke@1 772 if (cd != null) {
duke@1 773 return cd;
duke@1 774 }
duke@1 775
duke@1 776 // search inner classes
duke@1 777 //### Add private entry point to avoid creating array?
duke@1 778 //### Replicate code in innerClasses here to avoid consing?
ksrini@1065 779 for (ClassDoc icd : innerClasses()) {
ksrini@1065 780 if (icd.name().equals(className) ||
ksrini@1065 781 //### This is from original javadoc but it looks suspicious to me...
ksrini@1065 782 //### I believe it is attempting to compensate for the confused
ksrini@1065 783 //### convention of including the nested class qualifiers in the
ksrini@1065 784 //### 'name' of the inner class, rather than the true simple name.
ksrini@1065 785 icd.name().endsWith("." + className)) {
ksrini@1065 786 return icd;
duke@1 787 } else {
ksrini@1065 788 ClassDoc innercd = ((ClassDocImpl) icd).searchClass(className);
duke@1 789 if (innercd != null) {
duke@1 790 return innercd;
duke@1 791 }
duke@1 792 }
duke@1 793 }
duke@1 794
duke@1 795 // check in this package
duke@1 796 cd = containingPackage().findClass(className);
duke@1 797 if (cd != null) {
duke@1 798 return cd;
duke@1 799 }
duke@1 800
duke@1 801 // make sure that this symbol has been completed
duke@1 802 if (tsym.completer != null) {
duke@1 803 tsym.complete();
duke@1 804 }
duke@1 805
duke@1 806 // search imports
duke@1 807
duke@1 808 if (tsym.sourcefile != null) {
duke@1 809
duke@1 810 //### This information is available only for source classes.
duke@1 811
duke@1 812 Env<AttrContext> compenv = env.enter.getEnv(tsym);
duke@1 813 if (compenv == null) return null;
duke@1 814
duke@1 815 Scope s = compenv.toplevel.namedImportScope;
duke@1 816 for (Scope.Entry e = s.lookup(names.fromString(className)); e.scope != null; e = e.next()) {
duke@1 817 if (e.sym.kind == Kinds.TYP) {
duke@1 818 ClassDoc c = env.getClassDoc((ClassSymbol)e.sym);
duke@1 819 return c;
duke@1 820 }
duke@1 821 }
duke@1 822
duke@1 823 s = compenv.toplevel.starImportScope;
duke@1 824 for (Scope.Entry e = s.lookup(names.fromString(className)); e.scope != null; e = e.next()) {
duke@1 825 if (e.sym.kind == Kinds.TYP) {
duke@1 826 ClassDoc c = env.getClassDoc((ClassSymbol)e.sym);
duke@1 827 return c;
duke@1 828 }
duke@1 829 }
duke@1 830 }
duke@1 831
duke@1 832 return null; // not found
duke@1 833 }
duke@1 834
duke@1 835
duke@1 836 private boolean hasParameterTypes(MethodSymbol method, String[] argTypes) {
duke@1 837
duke@1 838 if (argTypes == null) {
duke@1 839 // wildcard
duke@1 840 return true;
duke@1 841 }
duke@1 842
duke@1 843 int i = 0;
duke@1 844 List<Type> types = method.type.getParameterTypes();
duke@1 845
duke@1 846 if (argTypes.length != types.length()) {
duke@1 847 return false;
duke@1 848 }
duke@1 849
duke@1 850 for (Type t : types) {
duke@1 851 String argType = argTypes[i++];
duke@1 852 // For vararg method, "T..." matches type T[].
duke@1 853 if (i == argTypes.length) {
duke@1 854 argType = argType.replace("...", "[]");
duke@1 855 }
duke@1 856 if (!hasTypeName(env.types.erasure(t), argType)) { //###(gj)
duke@1 857 return false;
duke@1 858 }
duke@1 859 }
duke@1 860 return true;
duke@1 861 }
duke@1 862 // where
duke@1 863 private boolean hasTypeName(Type t, String name) {
duke@1 864 return
duke@1 865 name.equals(TypeMaker.getTypeName(t, true))
duke@1 866 ||
duke@1 867 name.equals(TypeMaker.getTypeName(t, false))
duke@1 868 ||
duke@1 869 (qualifiedName() + "." + name).equals(TypeMaker.getTypeName(t, true));
duke@1 870 }
duke@1 871
duke@1 872
duke@1 873
duke@1 874 /**
duke@1 875 * Find a method in this class scope.
duke@1 876 * Search order: this class, interfaces, superclasses, outerclasses.
duke@1 877 * Note that this is not necessarily what the compiler would do!
duke@1 878 *
duke@1 879 * @param methodName the unqualified name to search for.
jjg@1358 880 * @param paramTypes the array of Strings for method parameter types.
duke@1 881 * @return the first MethodDocImpl which matches, null if not found.
duke@1 882 */
duke@1 883 public MethodDocImpl findMethod(String methodName, String[] paramTypes) {
duke@1 884 // Use hash table 'searched' to avoid searching same class twice.
duke@1 885 //### It is not clear how this could happen.
duke@1 886 return searchMethod(methodName, paramTypes, new HashSet<ClassDocImpl>());
duke@1 887 }
duke@1 888
duke@1 889 private MethodDocImpl searchMethod(String methodName,
duke@1 890 String[] paramTypes, Set<ClassDocImpl> searched) {
duke@1 891 //### Note that this search is not necessarily what the compiler would do!
duke@1 892
sundar@721 893 Names names = tsym.name.table.names;
sundar@721 894 // do not match constructors
sundar@721 895 if (names.init.contentEquals(methodName)) {
sundar@721 896 return null;
sundar@721 897 }
sundar@721 898
duke@1 899 ClassDocImpl cdi;
duke@1 900 MethodDocImpl mdi;
duke@1 901
duke@1 902 if (searched.contains(this)) {
duke@1 903 return null;
duke@1 904 }
duke@1 905 searched.add(this);
duke@1 906
duke@1 907 //DEBUG
duke@1 908 /*---------------------------------*
duke@1 909 System.out.print("searching " + this + " for " + methodName);
duke@1 910 if (paramTypes == null) {
duke@1 911 System.out.println("()");
duke@1 912 } else {
duke@1 913 System.out.print("(");
duke@1 914 for (int k=0; k < paramTypes.length; k++) {
duke@1 915 System.out.print(paramTypes[k]);
duke@1 916 if ((k + 1) < paramTypes.length) {
duke@1 917 System.out.print(", ");
duke@1 918 }
duke@1 919 }
duke@1 920 System.out.println(")");
duke@1 921 }
duke@1 922 *---------------------------------*/
duke@1 923
duke@1 924 // search current class
duke@1 925 Scope.Entry e = tsym.members().lookup(names.fromString(methodName));
duke@1 926
duke@1 927 //### Using modifier filter here isn't really correct,
duke@1 928 //### but emulates the old behavior. Instead, we should
duke@1 929 //### apply the normal rules of visibility and inheritance.
duke@1 930
duke@1 931 if (paramTypes == null) {
duke@1 932 // If no parameters specified, we are allowed to return
duke@1 933 // any method with a matching name. In practice, the old
duke@1 934 // code returned the first method, which is now the last!
duke@1 935 // In order to provide textually identical results, we
duke@1 936 // attempt to emulate the old behavior.
duke@1 937 MethodSymbol lastFound = null;
duke@1 938 for (; e.scope != null; e = e.next()) {
duke@1 939 if (e.sym.kind == Kinds.MTH) {
duke@1 940 //### Should intern methodName as Name.
duke@1 941 if (e.sym.name.toString().equals(methodName)) {
duke@1 942 lastFound = (MethodSymbol)e.sym;
duke@1 943 }
duke@1 944 }
duke@1 945 }
duke@1 946 if (lastFound != null) {
duke@1 947 return env.getMethodDoc(lastFound);
duke@1 948 }
duke@1 949 } else {
duke@1 950 for (; e.scope != null; e = e.next()) {
duke@1 951 if (e.sym != null &&
duke@1 952 e.sym.kind == Kinds.MTH) {
duke@1 953 //### Should intern methodName as Name.
duke@1 954 if (hasParameterTypes((MethodSymbol)e.sym, paramTypes)) {
duke@1 955 return env.getMethodDoc((MethodSymbol)e.sym);
duke@1 956 }
duke@1 957 }
duke@1 958 }
duke@1 959 }
duke@1 960
duke@1 961 //### If we found a MethodDoc above, but which did not pass
duke@1 962 //### the modifier filter, we should return failure here!
duke@1 963
duke@1 964 // search superclass
duke@1 965 cdi = (ClassDocImpl)superclass();
duke@1 966 if (cdi != null) {
duke@1 967 mdi = cdi.searchMethod(methodName, paramTypes, searched);
duke@1 968 if (mdi != null) {
duke@1 969 return mdi;
duke@1 970 }
duke@1 971 }
duke@1 972
duke@1 973 // search interfaces
duke@1 974 ClassDoc intf[] = interfaces();
duke@1 975 for (int i = 0; i < intf.length; i++) {
duke@1 976 cdi = (ClassDocImpl)intf[i];
duke@1 977 mdi = cdi.searchMethod(methodName, paramTypes, searched);
duke@1 978 if (mdi != null) {
duke@1 979 return mdi;
duke@1 980 }
duke@1 981 }
duke@1 982
duke@1 983 // search enclosing class
duke@1 984 cdi = (ClassDocImpl)containingClass();
duke@1 985 if (cdi != null) {
duke@1 986 mdi = cdi.searchMethod(methodName, paramTypes, searched);
duke@1 987 if (mdi != null) {
duke@1 988 return mdi;
duke@1 989 }
duke@1 990 }
duke@1 991
duke@1 992 //###(gj) As a temporary measure until type variables are better
duke@1 993 //### handled, try again without the parameter types.
duke@1 994 //### This should most often find the right method, and occassionally
duke@1 995 //### find the wrong one.
duke@1 996 //if (paramTypes != null) {
duke@1 997 // return findMethod(methodName, null);
duke@1 998 //}
duke@1 999
duke@1 1000 return null;
duke@1 1001 }
duke@1 1002
duke@1 1003 /**
duke@1 1004 * Find constructor in this class.
duke@1 1005 *
duke@1 1006 * @param constrName the unqualified name to search for.
jjg@1358 1007 * @param paramTypes the array of Strings for constructor parameters.
duke@1 1008 * @return the first ConstructorDocImpl which matches, null if not found.
duke@1 1009 */
duke@1 1010 public ConstructorDoc findConstructor(String constrName,
duke@1 1011 String[] paramTypes) {
jjg@113 1012 Names names = tsym.name.table.names;
duke@1 1013 for (Scope.Entry e = tsym.members().lookup(names.fromString("<init>")); e.scope != null; e = e.next()) {
duke@1 1014 if (e.sym.kind == Kinds.MTH) {
duke@1 1015 if (hasParameterTypes((MethodSymbol)e.sym, paramTypes)) {
duke@1 1016 return env.getConstructorDoc((MethodSymbol)e.sym);
duke@1 1017 }
duke@1 1018 }
duke@1 1019 }
duke@1 1020
duke@1 1021 //###(gj) As a temporary measure until type variables are better
duke@1 1022 //### handled, try again without the parameter types.
duke@1 1023 //### This will often find the right constructor, and occassionally
duke@1 1024 //### find the wrong one.
duke@1 1025 //if (paramTypes != null) {
duke@1 1026 // return findConstructor(constrName, null);
duke@1 1027 //}
duke@1 1028
duke@1 1029 return null;
duke@1 1030 }
duke@1 1031
duke@1 1032 /**
duke@1 1033 * Find a field in this class scope.
duke@1 1034 * Search order: this class, outerclasses, interfaces,
duke@1 1035 * superclasses. IMP: If see tag is defined in an inner class,
duke@1 1036 * which extends a super class and if outerclass and the super
duke@1 1037 * class have a visible field in common then Java compiler cribs
duke@1 1038 * about the ambiguity, but the following code will search in the
duke@1 1039 * above given search order.
duke@1 1040 *
duke@1 1041 * @param fieldName the unqualified name to search for.
duke@1 1042 * @return the first FieldDocImpl which matches, null if not found.
duke@1 1043 */
duke@1 1044 public FieldDoc findField(String fieldName) {
duke@1 1045 return searchField(fieldName, new HashSet<ClassDocImpl>());
duke@1 1046 }
duke@1 1047
duke@1 1048 private FieldDocImpl searchField(String fieldName, Set<ClassDocImpl> searched) {
jjg@113 1049 Names names = tsym.name.table.names;
duke@1 1050 if (searched.contains(this)) {
duke@1 1051 return null;
duke@1 1052 }
duke@1 1053 searched.add(this);
duke@1 1054
duke@1 1055 for (Scope.Entry e = tsym.members().lookup(names.fromString(fieldName)); e.scope != null; e = e.next()) {
duke@1 1056 if (e.sym.kind == Kinds.VAR) {
duke@1 1057 //### Should intern fieldName as Name.
duke@1 1058 return env.getFieldDoc((VarSymbol)e.sym);
duke@1 1059 }
duke@1 1060 }
duke@1 1061
duke@1 1062 //### If we found a FieldDoc above, but which did not pass
duke@1 1063 //### the modifier filter, we should return failure here!
duke@1 1064
duke@1 1065 ClassDocImpl cdi = (ClassDocImpl)containingClass();
duke@1 1066 if (cdi != null) {
duke@1 1067 FieldDocImpl fdi = cdi.searchField(fieldName, searched);
duke@1 1068 if (fdi != null) {
duke@1 1069 return fdi;
duke@1 1070 }
duke@1 1071 }
duke@1 1072
duke@1 1073 // search superclass
duke@1 1074 cdi = (ClassDocImpl)superclass();
duke@1 1075 if (cdi != null) {
duke@1 1076 FieldDocImpl fdi = cdi.searchField(fieldName, searched);
duke@1 1077 if (fdi != null) {
duke@1 1078 return fdi;
duke@1 1079 }
duke@1 1080 }
duke@1 1081
duke@1 1082 // search interfaces
duke@1 1083 ClassDoc intf[] = interfaces();
duke@1 1084 for (int i = 0; i < intf.length; i++) {
duke@1 1085 cdi = (ClassDocImpl)intf[i];
duke@1 1086 FieldDocImpl fdi = cdi.searchField(fieldName, searched);
duke@1 1087 if (fdi != null) {
duke@1 1088 return fdi;
duke@1 1089 }
duke@1 1090 }
duke@1 1091
duke@1 1092 return null;
duke@1 1093 }
duke@1 1094
duke@1 1095 /**
duke@1 1096 * Get the list of classes declared as imported.
duke@1 1097 * These are called "single-type-import declarations" in the JLS.
duke@1 1098 * This method is deprecated in the ClassDoc interface.
duke@1 1099 *
duke@1 1100 * @return an array of ClassDocImpl representing the imported classes.
duke@1 1101 *
duke@1 1102 * @deprecated Import declarations are implementation details that
duke@1 1103 * should not be exposed here. In addition, not all imported
duke@1 1104 * classes are imported through single-type-import declarations.
duke@1 1105 */
duke@1 1106 @Deprecated
duke@1 1107 public ClassDoc[] importedClasses() {
duke@1 1108 // information is not available for binary classfiles
duke@1 1109 if (tsym.sourcefile == null) return new ClassDoc[0];
duke@1 1110
duke@1 1111 ListBuffer<ClassDocImpl> importedClasses = new ListBuffer<ClassDocImpl>();
duke@1 1112
duke@1 1113 Env<AttrContext> compenv = env.enter.getEnv(tsym);
duke@1 1114 if (compenv == null) return new ClassDocImpl[0];
duke@1 1115
jjg@113 1116 Name asterisk = tsym.name.table.names.asterisk;
duke@1 1117 for (JCTree t : compenv.toplevel.defs) {
jjg@1127 1118 if (t.hasTag(IMPORT)) {
duke@1 1119 JCTree imp = ((JCImport) t).qualid;
duke@1 1120 if ((TreeInfo.name(imp) != asterisk) &&
duke@1 1121 (imp.type.tsym.kind & Kinds.TYP) != 0) {
duke@1 1122 importedClasses.append(
duke@1 1123 env.getClassDoc((ClassSymbol)imp.type.tsym));
duke@1 1124 }
duke@1 1125 }
duke@1 1126 }
duke@1 1127
duke@1 1128 return importedClasses.toArray(new ClassDocImpl[importedClasses.length()]);
duke@1 1129 }
duke@1 1130
duke@1 1131 /**
duke@1 1132 * Get the list of packages declared as imported.
duke@1 1133 * These are called "type-import-on-demand declarations" in the JLS.
duke@1 1134 * This method is deprecated in the ClassDoc interface.
duke@1 1135 *
duke@1 1136 * @return an array of PackageDocImpl representing the imported packages.
duke@1 1137 *
duke@1 1138 * ###NOTE: the syntax supports importing all inner classes from a class as well.
duke@1 1139 * @deprecated Import declarations are implementation details that
duke@1 1140 * should not be exposed here. In addition, this method's
duke@1 1141 * return type does not allow for all type-import-on-demand
duke@1 1142 * declarations to be returned.
duke@1 1143 */
duke@1 1144 @Deprecated
duke@1 1145 public PackageDoc[] importedPackages() {
duke@1 1146 // information is not available for binary classfiles
duke@1 1147 if (tsym.sourcefile == null) return new PackageDoc[0];
duke@1 1148
duke@1 1149 ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<PackageDocImpl>();
duke@1 1150
duke@1 1151 //### Add the implicit "import java.lang.*" to the result
jjg@113 1152 Names names = tsym.name.table.names;
duke@1 1153 importedPackages.append(env.getPackageDoc(env.reader.enterPackage(names.java_lang)));
duke@1 1154
duke@1 1155 Env<AttrContext> compenv = env.enter.getEnv(tsym);
duke@1 1156 if (compenv == null) return new PackageDocImpl[0];
duke@1 1157
duke@1 1158 for (JCTree t : compenv.toplevel.defs) {
jjg@1127 1159 if (t.hasTag(IMPORT)) {
duke@1 1160 JCTree imp = ((JCImport) t).qualid;
duke@1 1161 if (TreeInfo.name(imp) == names.asterisk) {
duke@1 1162 JCFieldAccess sel = (JCFieldAccess)imp;
duke@1 1163 Symbol s = sel.selected.type.tsym;
duke@1 1164 PackageDocImpl pdoc = env.getPackageDoc(s.packge());
duke@1 1165 if (!importedPackages.contains(pdoc))
duke@1 1166 importedPackages.append(pdoc);
duke@1 1167 }
duke@1 1168 }
duke@1 1169 }
duke@1 1170
duke@1 1171 return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);
duke@1 1172 }
duke@1 1173
duke@1 1174 /**
duke@1 1175 * Return the type's dimension information.
duke@1 1176 * Always return "", as this is not an array type.
duke@1 1177 */
duke@1 1178 public String dimension() {
duke@1 1179 return "";
duke@1 1180 }
duke@1 1181
duke@1 1182 /**
duke@1 1183 * Return this type as a class, which it already is.
duke@1 1184 */
duke@1 1185 public ClassDoc asClassDoc() {
duke@1 1186 return this;
duke@1 1187 }
duke@1 1188
duke@1 1189 /**
duke@1 1190 * Return null (unless overridden), as this is not an annotation type.
duke@1 1191 */
duke@1 1192 public AnnotationTypeDoc asAnnotationTypeDoc() {
duke@1 1193 return null;
duke@1 1194 }
duke@1 1195
duke@1 1196 /**
duke@1 1197 * Return null, as this is not a class instantiation.
duke@1 1198 */
duke@1 1199 public ParameterizedType asParameterizedType() {
duke@1 1200 return null;
duke@1 1201 }
duke@1 1202
duke@1 1203 /**
duke@1 1204 * Return null, as this is not a type variable.
duke@1 1205 */
duke@1 1206 public TypeVariable asTypeVariable() {
duke@1 1207 return null;
duke@1 1208 }
duke@1 1209
duke@1 1210 /**
duke@1 1211 * Return null, as this is not a wildcard type.
duke@1 1212 */
duke@1 1213 public WildcardType asWildcardType() {
duke@1 1214 return null;
duke@1 1215 }
duke@1 1216
duke@1 1217 /**
jjg@1521 1218 * Returns null, as this is not an annotated type.
jjg@1521 1219 */
jjg@1521 1220 public AnnotatedType asAnnotatedType() {
jjg@1521 1221 return null;
jjg@1521 1222 }
jjg@1521 1223
jjg@1521 1224 /**
duke@1 1225 * Return false, as this is not a primitive type.
duke@1 1226 */
duke@1 1227 public boolean isPrimitive() {
duke@1 1228 return false;
duke@1 1229 }
duke@1 1230
duke@1 1231 //--- Serialization ---
duke@1 1232
duke@1 1233 //### These methods ignore modifier filter.
duke@1 1234
duke@1 1235 /**
duke@1 1236 * Return true if this class implements <code>java.io.Serializable</code>.
duke@1 1237 *
duke@1 1238 * Since <code>java.io.Externalizable</code> extends
duke@1 1239 * <code>java.io.Serializable</code>,
duke@1 1240 * Externalizable objects are also Serializable.
duke@1 1241 */
duke@1 1242 public boolean isSerializable() {
duke@1 1243 try {
duke@1 1244 return env.types.isSubtype(type, env.syms.serializableType);
duke@1 1245 } catch (CompletionFailure ex) {
duke@1 1246 // quietly ignore completion failures
duke@1 1247 return false;
duke@1 1248 }
duke@1 1249 }
duke@1 1250
duke@1 1251 /**
duke@1 1252 * Return true if this class implements
duke@1 1253 * <code>java.io.Externalizable</code>.
duke@1 1254 */
duke@1 1255 public boolean isExternalizable() {
duke@1 1256 try {
duke@1 1257 return env.types.isSubtype(type, env.externalizableSym.type);
duke@1 1258 } catch (CompletionFailure ex) {
duke@1 1259 // quietly ignore completion failures
duke@1 1260 return false;
duke@1 1261 }
duke@1 1262 }
duke@1 1263
duke@1 1264 /**
duke@1 1265 * Return the serialization methods for this class.
duke@1 1266 *
duke@1 1267 * @return an array of <code>MethodDocImpl</code> that represents
duke@1 1268 * the serialization methods for this class.
duke@1 1269 */
duke@1 1270 public MethodDoc[] serializationMethods() {
duke@1 1271 if (serializedForm == null) {
duke@1 1272 serializedForm = new SerializedForm(env, tsym, this);
duke@1 1273 }
duke@1 1274 //### Clone this?
duke@1 1275 return serializedForm.methods();
duke@1 1276 }
duke@1 1277
duke@1 1278 /**
duke@1 1279 * Return the Serializable fields of class.<p>
duke@1 1280 *
duke@1 1281 * Return either a list of default fields documented by
duke@1 1282 * <code>serial</code> tag<br>
duke@1 1283 * or return a single <code>FieldDoc</code> for
duke@1 1284 * <code>serialPersistentField</code> member.
duke@1 1285 * There should be a <code>serialField</code> tag for
duke@1 1286 * each Serializable field defined by an <code>ObjectStreamField</code>
duke@1 1287 * array component of <code>serialPersistentField</code>.
duke@1 1288 *
duke@1 1289 * @returns an array of <code>FieldDoc</code> for the Serializable fields
duke@1 1290 * of this class.
duke@1 1291 *
duke@1 1292 * @see #definesSerializableFields()
duke@1 1293 * @see SerialFieldTagImpl
duke@1 1294 */
duke@1 1295 public FieldDoc[] serializableFields() {
duke@1 1296 if (serializedForm == null) {
duke@1 1297 serializedForm = new SerializedForm(env, tsym, this);
duke@1 1298 }
duke@1 1299 //### Clone this?
duke@1 1300 return serializedForm.fields();
duke@1 1301 }
duke@1 1302
duke@1 1303 /**
duke@1 1304 * Return true if Serializable fields are explicitly defined with
duke@1 1305 * the special class member <code>serialPersistentFields</code>.
duke@1 1306 *
duke@1 1307 * @see #serializableFields()
duke@1 1308 * @see SerialFieldTagImpl
duke@1 1309 */
duke@1 1310 public boolean definesSerializableFields() {
duke@1 1311 if (!isSerializable() || isExternalizable()) {
duke@1 1312 return false;
duke@1 1313 } else {
duke@1 1314 if (serializedForm == null) {
duke@1 1315 serializedForm = new SerializedForm(env, tsym, this);
duke@1 1316 }
duke@1 1317 //### Clone this?
duke@1 1318 return serializedForm.definesSerializableFields();
duke@1 1319 }
duke@1 1320 }
duke@1 1321
duke@1 1322 /**
duke@1 1323 * Determine if a class is a RuntimeException.
duke@1 1324 * <p>
duke@1 1325 * Used only by ThrowsTagImpl.
duke@1 1326 */
duke@1 1327 boolean isRuntimeException() {
duke@1 1328 return tsym.isSubClass(env.syms.runtimeExceptionType.tsym, env.types);
duke@1 1329 }
duke@1 1330
duke@1 1331 /**
duke@1 1332 * Return the source position of the entity, or null if
duke@1 1333 * no position is available.
duke@1 1334 */
jjg@910 1335 @Override
duke@1 1336 public SourcePosition position() {
duke@1 1337 if (tsym.sourcefile == null) return null;
jjg@197 1338 return SourcePositionImpl.make(tsym.sourcefile,
duke@1 1339 (tree==null) ? Position.NOPOS : tree.pos,
duke@1 1340 lineMap);
duke@1 1341 }
duke@1 1342 }

mercurial