langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
changeset 37945 1e4ba9d1f15e
parent 37937 a75e084fe3f5
parent 37944 1153fab98d25
child 37946 e420b9f05aaf
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java	Thu May 12 15:15:05 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1329 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javadoc;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.net.URI;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-
-import com.sun.javadoc.*;
-import com.sun.source.util.TreePath;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.Kinds.KindSelector;
-import com.sun.tools.javac.code.Scope;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.comp.AttrContext;
-import com.sun.tools.javac.comp.Env;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.TreeInfo;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-import com.sun.tools.javac.util.Position;
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-import static com.sun.tools.javac.code.TypeTag.CLASS;
-import static com.sun.tools.javac.tree.JCTree.Tag.*;
-
-/**
- * Represents a java class and provides access to information
- * about the class, the class' comment and tags, and the
- * members of the class.  A ClassDocImpl only exists if it was
- * processed in this run of javadoc.  References to classes
- * which may or may not have been processed in this run are
- * referred to using Type (which can be converted to ClassDocImpl,
- * if possible).
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @see Type
- *
- * @since 1.2
- * @author Robert Field
- * @author Neal Gafter (rewrite)
- * @author Scott Seligman (generics, enums, annotations)
- */
-
-public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
-
-    public final ClassType type;        // protected->public for debugging
-    public final ClassSymbol tsym;
-
-    boolean isIncluded = false;         // Set in RootDocImpl
-
-    private SerializedForm serializedForm;
-
-    /**
-     * Constructor
-     */
-    public ClassDocImpl(DocEnv env, ClassSymbol sym) {
-        this(env, sym, null);
-    }
-
-    /**
-     * Constructor
-     */
-    public ClassDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {
-        super(env, sym, treePath);
-        this.type = (ClassType)sym.type;
-        this.tsym = sym;
-    }
-
-    public com.sun.javadoc.Type getElementType() {
-        return null;
-    }
-
-    /**
-     * Returns the flags in terms of javac's flags
-     */
-    protected long getFlags() {
-        return getFlags(tsym);
-    }
-
-    /**
-     * Returns the flags of a ClassSymbol in terms of javac's flags
-     */
-    static long getFlags(ClassSymbol clazz) {
-        try {
-            return clazz.flags();
-        } catch (CompletionFailure ex) {
-            /* Quietly ignore completion failures and try again - the type
-             * for which the CompletionFailure was thrown shouldn't be completed
-             * again by the completer that threw the CompletionFailure.
-             */
-            return getFlags(clazz);
-        }
-    }
-
-    /**
-     * Is a ClassSymbol an annotation type?
-     */
-    static boolean isAnnotationType(ClassSymbol clazz) {
-        return (getFlags(clazz) & Flags.ANNOTATION) != 0;
-    }
-
-    /**
-     * Identify the containing class
-     */
-    protected ClassSymbol getContainingClass() {
-        return tsym.owner.enclClass();
-    }
-
-    /**
-     * Return true if this is a class, not an interface.
-     */
-    @Override
-    public boolean isClass() {
-        return !Modifier.isInterface(getModifiers());
-    }
-
-    /**
-     * Return true if this is a ordinary class,
-     * not an enumeration, exception, an error, or an interface.
-     */
-    @Override
-    public boolean isOrdinaryClass() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.errorType.tsym ||
-                t.tsym == env.syms.exceptionType.tsym) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Return true if this is an enumeration.
-     * (For legacy doclets, return false.)
-     */
-    @Override
-    public boolean isEnum() {
-        return (getFlags() & Flags.ENUM) != 0
-               &&
-               !env.legacyDoclet;
-    }
-
-    /**
-     * Return true if this is an interface, but not an annotation type.
-     * Overridden by AnnotationTypeDocImpl.
-     */
-    @Override
-    public boolean isInterface() {
-        return Modifier.isInterface(getModifiers());
-    }
-
-    /**
-     * Return true if this is an exception class
-     */
-    @Override
-    public boolean isException() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.exceptionType.tsym) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if this is an error class
-     */
-    @Override
-    public boolean isError() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.errorType.tsym) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if this is a throwable class
-     */
-    public boolean isThrowable() {
-        if (isEnum() || isInterface() || isAnnotationType()) {
-            return false;
-        }
-        for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {
-            if (t.tsym == env.syms.throwableType.tsym) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true if this class is abstract
-     */
-    public boolean isAbstract() {
-        return Modifier.isAbstract(getModifiers());
-    }
-
-    /**
-     * Returns true if this class was synthesized by the compiler.
-     */
-    public boolean isSynthetic() {
-        return (getFlags() & Flags.SYNTHETIC) != 0;
-    }
-
-    /**
-     * Return true if this class is included in the active set.
-     * A ClassDoc is included iff either it is specified on the
-     * commandline, or if it's containing package is specified
-     * on the command line, or if it is a member class of an
-     * included class.
-     */
-
-    public boolean isIncluded() {
-        if (isIncluded) {
-            return true;
-        }
-        if (env.shouldDocument(tsym)) {
-            // Class is nameable from top-level and
-            // the class and all enclosing classes
-            // pass the modifier filter.
-            if (containingPackage().isIncluded()) {
-                return isIncluded=true;
-            }
-            ClassDoc outer = containingClass();
-            if (outer != null && outer.isIncluded()) {
-                return isIncluded=true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return the package that this class is contained in.
-     */
-    @Override
-    public PackageDoc containingPackage() {
-        PackageDocImpl p = env.getPackageDoc(tsym.packge());
-        if (p.setDocPath == false) {
-            FileObject docPath;
-            try {
-                Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                    ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
-
-                docPath = env.fileManager.getFileForInput(
-                        location, p.qualifiedName(), "package.html");
-            } catch (IOException e) {
-                docPath = null;
-            }
-
-            if (docPath == null) {
-                // fall back on older semantics of looking in same directory as
-                // source file for this class
-                SourcePosition po = position();
-                if (env.fileManager instanceof StandardJavaFileManager &&
-                        po instanceof SourcePositionImpl) {
-                    URI uri = ((SourcePositionImpl) po).filename.toUri();
-                    if ("file".equals(uri.getScheme())) {
-                        File f = new File(uri);
-                        File dir = f.getParentFile();
-                        if (dir != null) {
-                            File pf = new File(dir, "package.html");
-                            if (pf.exists()) {
-                                StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
-                                docPath = sfm.getJavaFileObjects(pf).iterator().next();
-                            }
-                        }
-
-                    }
-                }
-            }
-
-            p.setDocPath(docPath);
-        }
-        return p;
-    }
-
-    /**
-     * Return the class name without package qualifier - but with
-     * enclosing class qualifier - as a String.
-     * <pre>
-     * Examples:
-     *  for java.util.Hashtable
-     *  return Hashtable
-     *  for java.util.Map.Entry
-     *  return Map.Entry
-     * </pre>
-     */
-    public String name() {
-        if (name == null) {
-            name = getClassName(tsym, false);
-        }
-        return name;
-    }
-
-    private String name;
-
-    /**
-     * Return the qualified class name as a String.
-     * <pre>
-     * Example:
-     *  for java.util.Hashtable
-     *  return java.util.Hashtable
-     *  if no qualifier, just return flat name
-     * </pre>
-     */
-    public String qualifiedName() {
-        if (qualifiedName == null) {
-            qualifiedName = getClassName(tsym, true);
-        }
-        return qualifiedName;
-    }
-
-    private String qualifiedName;
-
-    /**
-     * Return unqualified name of type excluding any dimension information.
-     * <p>
-     * For example, a two dimensional array of String returns 'String'.
-     */
-    public String typeName() {
-        return name();
-    }
-
-    /**
-     * Return qualified name of type excluding any dimension information.
-     *<p>
-     * For example, a two dimensional array of String
-     * returns 'java.lang.String'.
-     */
-    public String qualifiedTypeName() {
-        return qualifiedName();
-    }
-
-    /**
-     * Return the simple name of this type.
-     */
-    public String simpleTypeName() {
-        if (simpleTypeName == null) {
-            simpleTypeName = tsym.name.toString();
-        }
-        return simpleTypeName;
-    }
-
-    private String simpleTypeName;
-
-    /**
-     * Return the qualified name and any type parameters.
-     * Each parameter is a type variable with optional bounds.
-     */
-    @Override
-    public String toString() {
-        return classToString(env, tsym, true);
-    }
-
-    /**
-     * Return the class name as a string.  If "full" is true the name is
-     * qualified, otherwise it is qualified by its enclosing class(es) only.
-     */
-    static String getClassName(ClassSymbol c, boolean full) {
-        if (full) {
-            return c.getQualifiedName().toString();
-        } else {
-            String n = "";
-            for ( ; c != null; c = c.owner.enclClass()) {
-                n = c.name + (n.equals("") ? "" : ".") + n;
-            }
-            return n;
-        }
-    }
-
-    /**
-     * Return the class name with any type parameters as a string.
-     * Each parameter is a type variable with optional bounds.
-     * If "full" is true all names are qualified, otherwise they are
-     * qualified by their enclosing class(es) only.
-     */
-    static String classToString(DocEnv env, ClassSymbol c, boolean full) {
-        StringBuilder s = new StringBuilder();
-        if (!c.isInner()) {             // if c is not an inner class
-            s.append(getClassName(c, full));
-        } else {
-            // c is an inner class, so include type params of outer.
-            ClassSymbol encl = c.owner.enclClass();
-            s.append(classToString(env, encl, full))
-             .append('.')
-             .append(c.name);
-        }
-        s.append(TypeMaker.typeParametersString(env, c, full));
-        return s.toString();
-    }
-
-    /**
-     * Is this class (or any enclosing class) generic?  That is, does
-     * it have type parameters?
-     */
-    static boolean isGeneric(ClassSymbol c) {
-        return c.type.allparams().nonEmpty();
-    }
-
-    /**
-     * Return the formal type parameters of this class or interface.
-     * Return an empty array if there are none.
-     */
-    public TypeVariable[] typeParameters() {
-        if (env.legacyDoclet) {
-            return new TypeVariable[0];
-        }
-        TypeVariable res[] = new TypeVariable[type.getTypeArguments().length()];
-        TypeMaker.getTypes(env, type.getTypeArguments(), res);
-        return res;
-    }
-
-    /**
-     * Return the type parameter tags of this class or interface.
-     */
-    public ParamTag[] typeParamTags() {
-        return (env.legacyDoclet)
-            ? new ParamTag[0]
-            : comment().typeParamTags();
-    }
-
-    /**
-     * Return the modifier string for this class. If it's an interface
-     * exclude 'abstract' keyword from the modifier string
-     */
-    @Override
-    public String modifiers() {
-        return Modifier.toString(modifierSpecifier());
-    }
-
-    @Override
-    public int modifierSpecifier() {
-        int modifiers = getModifiers();
-        return (isInterface() || isAnnotationType())
-                ? modifiers & ~Modifier.ABSTRACT
-                : modifiers;
-    }
-
-    /**
-     * Return the superclass of this class
-     *
-     * @return the ClassDocImpl for the superclass of this class, null
-     * if there is no superclass.
-     */
-    public ClassDoc superclass() {
-        if (isInterface() || isAnnotationType()) return null;
-        if (tsym == env.syms.objectType.tsym) return null;
-        ClassSymbol c = (ClassSymbol)env.types.supertype(type).tsym;
-        if (c == null || c == tsym) c = (ClassSymbol)env.syms.objectType.tsym;
-        return env.getClassDoc(c);
-    }
-
-    /**
-     * Return the superclass of this class.  Return null if this is an
-     * interface.  A superclass is represented by either a
-     * <code>ClassDoc</code> or a <code>ParameterizedType</code>.
-     */
-    public com.sun.javadoc.Type superclassType() {
-        if (isInterface() || isAnnotationType() ||
-                (tsym == env.syms.objectType.tsym))
-            return null;
-        Type sup = env.types.supertype(type);
-        return TypeMaker.getType(env,
-                                 (sup.hasTag(TypeTag.NONE)) ? env.syms.objectType : sup);
-    }
-
-    /**
-     * Test whether this class is a subclass of the specified class.
-     *
-     * @param cd the candidate superclass.
-     * @return true if cd is a superclass of this class.
-     */
-    public boolean subclassOf(ClassDoc cd) {
-        return tsym.isSubClass(((ClassDocImpl)cd).tsym, env.types);
-    }
-
-    /**
-     * Return interfaces implemented by this class or interfaces
-     * extended by this interface.
-     *
-     * @return An array of ClassDocImpl representing the interfaces.
-     * Return an empty array if there are no interfaces.
-     */
-    public ClassDoc[] interfaces() {
-        ListBuffer<ClassDocImpl> ta = new ListBuffer<>();
-        for (Type t : env.types.interfaces(type)) {
-            ta.append(env.getClassDoc((ClassSymbol)t.tsym));
-        }
-        //### Cache ta here?
-        return ta.toArray(new ClassDocImpl[ta.length()]);
-    }
-
-    /**
-     * Return interfaces implemented by this class or interfaces extended
-     * by this interface. Includes only directly-declared interfaces, not
-     * inherited interfaces.
-     * Return an empty array if there are no interfaces.
-     */
-    public com.sun.javadoc.Type[] interfaceTypes() {
-        //### Cache result here?
-        return TypeMaker.getTypes(env, env.types.interfaces(type));
-    }
-
-    /**
-     * Return fields in class.
-     * @param filter include only the included fields if filter==true
-     */
-    public FieldDoc[] fields(boolean filter) {
-        return fields(filter, false);
-    }
-
-    /**
-     * Return included fields in class.
-     */
-    public FieldDoc[] fields() {
-        return fields(true, false);
-    }
-
-    /**
-     * Return the enum constants if this is an enum type.
-     */
-    public FieldDoc[] enumConstants() {
-        return fields(false, true);
-    }
-
-    /**
-     * Return fields in class.
-     * @param filter  if true, return only the included fields
-     * @param enumConstants  if true, return the enum constants instead
-     */
-    private FieldDoc[] fields(boolean filter, boolean enumConstants) {
-        List<FieldDocImpl> fields = List.nil();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null && sym.kind == VAR) {
-                VarSymbol s = (VarSymbol)sym;
-                boolean isEnum = ((s.flags() & Flags.ENUM) != 0) &&
-                                 !env.legacyDoclet;
-                if (isEnum == enumConstants &&
-                        (!filter || env.shouldDocument(s))) {
-                    fields = fields.prepend(env.getFieldDoc(s));
-                }
-            }
-        }
-        return fields.toArray(new FieldDocImpl[fields.length()]);
-    }
-
-    /**
-     * Return methods in class.
-     * This method is overridden by AnnotationTypeDocImpl.
-     *
-     * @param filter include only the included methods if filter==true
-     * @return an array of MethodDocImpl for representing the visible
-     * methods in this class.  Does not include constructors.
-     */
-    public MethodDoc[] methods(boolean filter) {
-        Names names = tsym.name.table.names;
-        List<MethodDocImpl> methods = List.nil();
-        for (Symbol sym :tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null
-                && sym.kind == MTH
-                && sym.name != names.init
-                && sym.name != names.clinit) {
-                MethodSymbol s = (MethodSymbol)sym;
-                if (!filter || env.shouldDocument(s)) {
-                    methods = methods.prepend(env.getMethodDoc(s));
-                }
-            }
-        }
-        //### Cache methods here?
-        return methods.toArray(new MethodDocImpl[methods.length()]);
-    }
-
-    /**
-     * Return included methods in class.
-     *
-     * @return an array of MethodDocImpl for representing the visible
-     * methods in this class.  Does not include constructors.
-     */
-    public MethodDoc[] methods() {
-        return methods(true);
-    }
-
-    /**
-     * Return constructors in class.
-     *
-     * @param filter include only the included constructors if filter==true
-     * @return an array of ConstructorDocImpl for representing the visible
-     * constructors in this class.
-     */
-    public ConstructorDoc[] constructors(boolean filter) {
-        Names names = tsym.name.table.names;
-        List<ConstructorDocImpl> constructors = List.nil();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null &&
-                sym.kind == MTH && sym.name == names.init) {
-                MethodSymbol s = (MethodSymbol)sym;
-                if (!filter || env.shouldDocument(s)) {
-                    constructors = constructors.prepend(env.getConstructorDoc(s));
-                }
-            }
-        }
-        //### Cache constructors here?
-        return constructors.toArray(new ConstructorDocImpl[constructors.length()]);
-    }
-
-    /**
-     * Return included constructors in class.
-     *
-     * @return an array of ConstructorDocImpl for representing the visible
-     * constructors in this class.
-     */
-    public ConstructorDoc[] constructors() {
-        return constructors(true);
-    }
-
-    /**
-     * Adds all inner classes of this class, and their
-     * inner classes recursively, to the list l.
-     */
-    void addAllClasses(ListBuffer<ClassDocImpl> l, boolean filtered) {
-        try {
-            if (isSynthetic()) return;
-            // sometimes synthetic classes are not marked synthetic
-            if (!JavadocTool.isValidClassName(tsym.name.toString())) return;
-            if (filtered && !env.shouldDocument(tsym)) return;
-            if (l.contains(this)) return;
-            l.append(this);
-            List<ClassDocImpl> more = List.nil();
-            for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-                if (sym != null && sym.kind == TYP) {
-                    ClassSymbol s = (ClassSymbol)sym;
-                    ClassDocImpl c = env.getClassDoc(s);
-                    if (c.isSynthetic()) continue;
-                    if (c != null) more = more.prepend(c);
-                }
-            }
-            // this extra step preserves the ordering from oldjavadoc
-            for (; more.nonEmpty(); more=more.tail) {
-                more.head.addAllClasses(l, filtered);
-            }
-        } catch (CompletionFailure e) {
-            // quietly ignore completion failures
-        }
-    }
-
-    /**
-     * Return inner classes within this class.
-     *
-     * @param filter include only the included inner classes if filter==true.
-     * @return an array of ClassDocImpl for representing the visible
-     * classes defined in this class. Anonymous and local classes
-     * are not included.
-     */
-    public ClassDoc[] innerClasses(boolean filter) {
-        ListBuffer<ClassDocImpl> innerClasses = new ListBuffer<>();
-        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
-            if (sym != null && sym.kind == TYP) {
-                ClassSymbol s = (ClassSymbol)sym;
-                if ((s.flags_field & Flags.SYNTHETIC) != 0) continue;
-                if (!filter || env.isVisible(s)) {
-                    innerClasses.prepend(env.getClassDoc(s));
-                }
-            }
-        }
-        //### Cache classes here?
-        return innerClasses.toArray(new ClassDocImpl[innerClasses.length()]);
-    }
-
-    /**
-     * Return included inner classes within this class.
-     *
-     * @return an array of ClassDocImpl for representing the visible
-     * classes defined in this class. Anonymous and local classes
-     * are not included.
-     */
-    public ClassDoc[] innerClasses() {
-        return innerClasses(true);
-    }
-
-    /**
-     * Find a class within the context of this class.
-     * Search order: qualified name, in this class (inner),
-     * in this package, in the class imports, in the package
-     * imports.
-     * Return the ClassDocImpl if found, null if not found.
-     */
-    //### The specified search order is not the normal rule the
-    //### compiler would use.  Leave as specified or change it?
-    public ClassDoc findClass(String className) {
-        ClassDoc searchResult = searchClass(className);
-        if (searchResult == null) {
-            ClassDocImpl enclosingClass = (ClassDocImpl)containingClass();
-            //Expand search space to include enclosing class.
-            while (enclosingClass != null && enclosingClass.containingClass() != null) {
-                enclosingClass = (ClassDocImpl)enclosingClass.containingClass();
-            }
-            searchResult = enclosingClass == null ?
-                null : enclosingClass.searchClass(className);
-        }
-        return searchResult;
-    }
-
-    private ClassDoc searchClass(String className) {
-        Names names = tsym.name.table.names;
-
-        // search by qualified name first
-        ClassDoc cd = env.lookupClass(className);
-        if (cd != null) {
-            return cd;
-        }
-
-        // search inner classes
-        //### Add private entry point to avoid creating array?
-        //### Replicate code in innerClasses here to avoid consing?
-        for (ClassDoc icd : innerClasses()) {
-            if (icd.name().equals(className) ||
-                    //### This is from original javadoc but it looks suspicious to me...
-                    //### I believe it is attempting to compensate for the confused
-                    //### convention of including the nested class qualifiers in the
-                    //### 'name' of the inner class, rather than the true simple name.
-                    icd.name().endsWith("." + className)) {
-                return icd;
-            } else {
-                ClassDoc innercd = ((ClassDocImpl) icd).searchClass(className);
-                if (innercd != null) {
-                    return innercd;
-                }
-            }
-        }
-
-        // check in this package
-        cd = containingPackage().findClass(className);
-        if (cd != null) {
-            return cd;
-        }
-
-        // make sure that this symbol has been completed
-        tsym.complete();
-
-        // search imports
-
-        if (tsym.sourcefile != null) {
-
-            //### This information is available only for source classes.
-
-            Env<AttrContext> compenv = env.enter.getEnv(tsym);
-            if (compenv == null) return null;
-
-            Scope s = compenv.toplevel.namedImportScope;
-            for (Symbol sym : s.getSymbolsByName(names.fromString(className))) {
-                if (sym.kind == TYP) {
-                    ClassDoc c = env.getClassDoc((ClassSymbol)sym);
-                    return c;
-                }
-            }
-
-            s = compenv.toplevel.starImportScope;
-            for (Symbol sym : s.getSymbolsByName(names.fromString(className))) {
-                if (sym.kind == TYP) {
-                    ClassDoc c = env.getClassDoc((ClassSymbol)sym);
-                    return c;
-                }
-            }
-        }
-
-        return null; // not found
-    }
-
-
-    private boolean hasParameterTypes(MethodSymbol method, String[] argTypes) {
-
-        if (argTypes == null) {
-            // wildcard
-            return true;
-        }
-
-        int i = 0;
-        List<Type> types = method.type.getParameterTypes();
-
-        if (argTypes.length != types.length()) {
-            return false;
-        }
-
-        for (Type t : types) {
-            String argType = argTypes[i++];
-            // For vararg method, "T..." matches type T[].
-            if (i == argTypes.length) {
-                argType = argType.replace("...", "[]");
-            }
-            if (!hasTypeName(env.types.erasure(t), argType)) {  //###(gj)
-                return false;
-            }
-        }
-        return true;
-    }
-    // where
-    private boolean hasTypeName(Type t, String name) {
-        return
-            name.equals(TypeMaker.getTypeName(t, true))
-            ||
-            name.equals(TypeMaker.getTypeName(t, false))
-            ||
-            (qualifiedName() + "." + name).equals(TypeMaker.getTypeName(t, true));
-    }
-
-
-
-    /**
-     * Find a method in this class scope.
-     * Search order: this class, interfaces, superclasses, outerclasses.
-     * Note that this is not necessarily what the compiler would do!
-     *
-     * @param methodName the unqualified name to search for.
-     * @param paramTypes the array of Strings for method parameter types.
-     * @return the first MethodDocImpl which matches, null if not found.
-     */
-    public MethodDocImpl findMethod(String methodName, String[] paramTypes) {
-        // Use hash table 'searched' to avoid searching same class twice.
-        //### It is not clear how this could happen.
-        return searchMethod(methodName, paramTypes, new HashSet<ClassDocImpl>());
-    }
-
-    private MethodDocImpl searchMethod(String methodName,
-                                       String[] paramTypes, Set<ClassDocImpl> searched) {
-        //### Note that this search is not necessarily what the compiler would do!
-
-        Names names = tsym.name.table.names;
-        // do not match constructors
-        if (names.init.contentEquals(methodName)) {
-            return null;
-        }
-
-        ClassDocImpl cdi;
-        MethodDocImpl mdi;
-
-        if (searched.contains(this)) {
-            return null;
-        }
-        searched.add(this);
-
-        //DEBUG
-        /*---------------------------------*
-         System.out.print("searching " + this + " for " + methodName);
-         if (paramTypes == null) {
-         System.out.println("()");
-         } else {
-         System.out.print("(");
-         for (int k=0; k < paramTypes.length; k++) {
-         System.out.print(paramTypes[k]);
-         if ((k + 1) < paramTypes.length) {
-         System.out.print(", ");
-         }
-         }
-         System.out.println(")");
-         }
-         *---------------------------------*/
-
-        // search current class
-
-        //### Using modifier filter here isn't really correct,
-        //### but emulates the old behavior.  Instead, we should
-        //### apply the normal rules of visibility and inheritance.
-
-        if (paramTypes == null) {
-            // If no parameters specified, we are allowed to return
-            // any method with a matching name.  In practice, the old
-            // code returned the first method, which is now the last!
-            // In order to provide textually identical results, we
-            // attempt to emulate the old behavior.
-            MethodSymbol lastFound = null;
-            for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(methodName))) {
-                if (sym.kind == MTH) {
-                    //### Should intern methodName as Name.
-                    if (sym.name.toString().equals(methodName)) {
-                        lastFound = (MethodSymbol)sym;
-                    }
-                }
-            }
-            if (lastFound != null) {
-                return env.getMethodDoc(lastFound);
-            }
-        } else {
-            for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(methodName))) {
-                if (sym != null &&
-                    sym.kind == MTH) {
-                    //### Should intern methodName as Name.
-                    if (hasParameterTypes((MethodSymbol)sym, paramTypes)) {
-                        return env.getMethodDoc((MethodSymbol)sym);
-                    }
-                }
-            }
-        }
-
-        //### If we found a MethodDoc above, but which did not pass
-        //### the modifier filter, we should return failure here!
-
-        // search superclass
-        cdi = (ClassDocImpl)superclass();
-        if (cdi != null) {
-            mdi = cdi.searchMethod(methodName, paramTypes, searched);
-            if (mdi != null) {
-                return mdi;
-            }
-        }
-
-        // search interfaces
-        for (ClassDoc intf : interfaces()) {
-            cdi = (ClassDocImpl) intf;
-            mdi = cdi.searchMethod(methodName, paramTypes, searched);
-            if (mdi != null) {
-                return mdi;
-            }
-        }
-
-        // search enclosing class
-        cdi = (ClassDocImpl)containingClass();
-        if (cdi != null) {
-            mdi = cdi.searchMethod(methodName, paramTypes, searched);
-            if (mdi != null) {
-                return mdi;
-            }
-        }
-
-        //###(gj) As a temporary measure until type variables are better
-        //### handled, try again without the parameter types.
-        //### This should most often find the right method, and occassionally
-        //### find the wrong one.
-        //if (paramTypes != null) {
-        //    return findMethod(methodName, null);
-        //}
-
-        return null;
-    }
-
-    /**
-     * Find constructor in this class.
-     *
-     * @param constrName the unqualified name to search for.
-     * @param paramTypes the array of Strings for constructor parameters.
-     * @return the first ConstructorDocImpl which matches, null if not found.
-     */
-    public ConstructorDoc findConstructor(String constrName,
-                                          String[] paramTypes) {
-        Names names = tsym.name.table.names;
-        for (Symbol sym : tsym.members().getSymbolsByName(names.fromString("<init>"))) {
-            if (sym.kind == MTH) {
-                if (hasParameterTypes((MethodSymbol)sym, paramTypes)) {
-                    return env.getConstructorDoc((MethodSymbol)sym);
-                }
-            }
-        }
-
-        //###(gj) As a temporary measure until type variables are better
-        //### handled, try again without the parameter types.
-        //### This will often find the right constructor, and occassionally
-        //### find the wrong one.
-        //if (paramTypes != null) {
-        //    return findConstructor(constrName, null);
-        //}
-
-        return null;
-    }
-
-    /**
-     * Find a field in this class scope.
-     * Search order: this class, outerclasses, interfaces,
-     * superclasses. IMP: If see tag is defined in an inner class,
-     * which extends a super class and if outerclass and the super
-     * class have a visible field in common then Java compiler cribs
-     * about the ambiguity, but the following code will search in the
-     * above given search order.
-     *
-     * @param fieldName the unqualified name to search for.
-     * @return the first FieldDocImpl which matches, null if not found.
-     */
-    public FieldDoc findField(String fieldName) {
-        return searchField(fieldName, new HashSet<ClassDocImpl>());
-    }
-
-    private FieldDocImpl searchField(String fieldName, Set<ClassDocImpl> searched) {
-        Names names = tsym.name.table.names;
-        if (searched.contains(this)) {
-            return null;
-        }
-        searched.add(this);
-
-        for (Symbol sym : tsym.members().getSymbolsByName(names.fromString(fieldName))) {
-            if (sym.kind == VAR) {
-                //### Should intern fieldName as Name.
-                return env.getFieldDoc((VarSymbol)sym);
-            }
-        }
-
-        //### If we found a FieldDoc above, but which did not pass
-        //### the modifier filter, we should return failure here!
-
-        ClassDocImpl cdi = (ClassDocImpl)containingClass();
-        if (cdi != null) {
-            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
-            if (fdi != null) {
-                return fdi;
-            }
-        }
-
-        // search superclass
-        cdi = (ClassDocImpl)superclass();
-        if (cdi != null) {
-            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
-            if (fdi != null) {
-                return fdi;
-            }
-        }
-
-        // search interfaces
-        for (ClassDoc intf : interfaces()) {
-            cdi = (ClassDocImpl) intf;
-            FieldDocImpl fdi = cdi.searchField(fieldName, searched);
-            if (fdi != null) {
-                return fdi;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the list of classes declared as imported.
-     * These are called "single-type-import declarations" in the JLS.
-     * This method is deprecated in the ClassDoc interface.
-     *
-     * @return an array of ClassDocImpl representing the imported classes.
-     *
-     * @deprecated  Import declarations are implementation details that
-     *          should not be exposed here.  In addition, not all imported
-     *          classes are imported through single-type-import declarations.
-     */
-    @Deprecated
-    public ClassDoc[] importedClasses() {
-        // information is not available for binary classfiles
-        if (tsym.sourcefile == null) return new ClassDoc[0];
-
-        ListBuffer<ClassDocImpl> importedClasses = new ListBuffer<>();
-
-        Env<AttrContext> compenv = env.enter.getEnv(tsym);
-        if (compenv == null) return new ClassDocImpl[0];
-
-        Name asterisk = tsym.name.table.names.asterisk;
-        for (JCTree t : compenv.toplevel.defs) {
-            if (t.hasTag(IMPORT)) {
-                JCTree imp = ((JCImport) t).qualid;
-                if ((TreeInfo.name(imp) != asterisk) &&
-                    imp.type.tsym.kind.matches(KindSelector.TYP)) {
-                    importedClasses.append(
-                            env.getClassDoc((ClassSymbol)imp.type.tsym));
-                }
-            }
-        }
-
-        return importedClasses.toArray(new ClassDocImpl[importedClasses.length()]);
-    }
-
-    /**
-     * Get the list of packages declared as imported.
-     * These are called "type-import-on-demand declarations" in the JLS.
-     * This method is deprecated in the ClassDoc interface.
-     *
-     * @return an array of PackageDocImpl representing the imported packages.
-     *
-     * ###NOTE: the syntax supports importing all inner classes from a class as well.
-     * @deprecated  Import declarations are implementation details that
-     *          should not be exposed here.  In addition, this method's
-     *          return type does not allow for all type-import-on-demand
-     *          declarations to be returned.
-     */
-    @Deprecated
-    public PackageDoc[] importedPackages() {
-        // information is not available for binary classfiles
-        if (tsym.sourcefile == null) return new PackageDoc[0];
-
-        ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<>();
-
-        //### Add the implicit "import java.lang.*" to the result
-        Names names = tsym.name.table.names;
-        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(env.syms.java_base, names.java_lang)));
-
-        Env<AttrContext> compenv = env.enter.getEnv(tsym);
-        if (compenv == null) return new PackageDocImpl[0];
-
-        for (JCTree t : compenv.toplevel.defs) {
-            if (t.hasTag(IMPORT)) {
-                JCTree imp = ((JCImport) t).qualid;
-                if (TreeInfo.name(imp) == names.asterisk) {
-                    JCFieldAccess sel = (JCFieldAccess)imp;
-                    Symbol s = sel.selected.type.tsym;
-                    PackageDocImpl pdoc = env.getPackageDoc(s.packge());
-                    if (!importedPackages.contains(pdoc))
-                        importedPackages.append(pdoc);
-                }
-            }
-        }
-
-        return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);
-    }
-
-    /**
-     * Return the type's dimension information.
-     * Always return "", as this is not an array type.
-     */
-    public String dimension() {
-        return "";
-    }
-
-    /**
-     * Return this type as a class, which it already is.
-     */
-    public ClassDoc asClassDoc() {
-        return this;
-    }
-
-    /**
-     * Return null (unless overridden), as this is not an annotation type.
-     */
-    public AnnotationTypeDoc asAnnotationTypeDoc() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a class instantiation.
-     */
-    public ParameterizedType asParameterizedType() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a type variable.
-     */
-    public TypeVariable asTypeVariable() {
-        return null;
-    }
-
-    /**
-     * Return null, as this is not a wildcard type.
-     */
-    public WildcardType asWildcardType() {
-        return null;
-    }
-
-    /**
-     * Returns null, as this is not an annotated type.
-     */
-    public AnnotatedType asAnnotatedType() {
-        return null;
-    }
-
-    /**
-     * Return false, as this is not a primitive type.
-     */
-    public boolean isPrimitive() {
-        return false;
-    }
-
-    //--- Serialization ---
-
-    //### These methods ignore modifier filter.
-
-    /**
-     * Return true if this class implements <code>java.io.Serializable</code>.
-     *
-     * Since <code>java.io.Externalizable</code> extends
-     * <code>java.io.Serializable</code>,
-     * Externalizable objects are also Serializable.
-     */
-    public boolean isSerializable() {
-        try {
-            return env.types.isSubtype(type, env.syms.serializableType);
-        } catch (CompletionFailure ex) {
-            // quietly ignore completion failures
-            return false;
-        }
-    }
-
-    /**
-     * Return true if this class implements
-     * <code>java.io.Externalizable</code>.
-     */
-    public boolean isExternalizable() {
-        try {
-            return env.types.isSubtype(type, env.externalizableSym.type);
-        } catch (CompletionFailure ex) {
-            // quietly ignore completion failures
-            return false;
-        }
-    }
-
-    /**
-     * Return the serialization methods for this class.
-     *
-     * @return an array of <code>MethodDocImpl</code> that represents
-     * the serialization methods for this class.
-     */
-    public MethodDoc[] serializationMethods() {
-        if (serializedForm == null) {
-            serializedForm = new SerializedForm(env, tsym, this);
-        }
-        //### Clone this?
-        return serializedForm.methods();
-    }
-
-    /**
-     * Return the Serializable fields of class.<p>
-     *
-     * Return either a list of default fields documented by
-     * <code>serial</code> tag<br>
-     * or return a single <code>FieldDoc</code> for
-     * <code>serialPersistentField</code> member.
-     * There should be a <code>serialField</code> tag for
-     * each Serializable field defined by an <code>ObjectStreamField</code>
-     * array component of <code>serialPersistentField</code>.
-     *
-     * @return an array of {@code FieldDoc} for the Serializable fields
-     *         of this class.
-     *
-     * @see #definesSerializableFields()
-     * @see SerialFieldTagImpl
-     */
-    public FieldDoc[] serializableFields() {
-        if (serializedForm == null) {
-            serializedForm = new SerializedForm(env, tsym, this);
-        }
-        //### Clone this?
-        return serializedForm.fields();
-    }
-
-    /**
-     * Return true if Serializable fields are explicitly defined with
-     * the special class member <code>serialPersistentFields</code>.
-     *
-     * @see #serializableFields()
-     * @see SerialFieldTagImpl
-     */
-    public boolean definesSerializableFields() {
-        if (!isSerializable() || isExternalizable()) {
-            return false;
-        } else {
-            if (serializedForm == null) {
-                serializedForm = new SerializedForm(env, tsym, this);
-            }
-            //### Clone this?
-            return serializedForm.definesSerializableFields();
-        }
-    }
-
-    /**
-     * Determine if a class is a RuntimeException.
-     * <p>
-     * Used only by ThrowsTagImpl.
-     */
-    boolean isRuntimeException() {
-        return tsym.isSubClass(env.syms.runtimeExceptionType.tsym, env.types);
-    }
-
-    /**
-     * Return the source position of the entity, or null if
-     * no position is available.
-     */
-    @Override
-    public SourcePosition position() {
-        if (tsym.sourcefile == null) return null;
-        return SourcePositionImpl.make(tsym.sourcefile,
-                                       (tree==null) ? Position.NOPOS : tree.pos,
-                                       lineMap);
-    }
-}