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

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 2233
4a6f853f8721
parent 0
959103a6100f
child 3295
859dc787b52b
permissions
-rw-r--r--

merge

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

mercurial