Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
38899 views
/*1* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javadoc;2627import java.io.File;28import java.io.IOException;29import java.lang.reflect.Modifier;30import java.net.URI;31import java.util.HashSet;32import java.util.Set;3334import javax.tools.FileObject;35import javax.tools.JavaFileManager.Location;36import javax.tools.StandardJavaFileManager;37import javax.tools.StandardLocation;3839import com.sun.javadoc.*;40import com.sun.source.util.TreePath;41import com.sun.tools.javac.code.Flags;42import com.sun.tools.javac.code.Kinds;43import com.sun.tools.javac.code.Scope;44import com.sun.tools.javac.code.Symbol;45import com.sun.tools.javac.code.Symbol.*;46import com.sun.tools.javac.code.Type;47import com.sun.tools.javac.code.Type.ClassType;48import com.sun.tools.javac.code.TypeTag;49import com.sun.tools.javac.comp.AttrContext;50import com.sun.tools.javac.comp.Env;51import com.sun.tools.javac.tree.JCTree;52import com.sun.tools.javac.tree.JCTree.JCFieldAccess;53import com.sun.tools.javac.tree.JCTree.JCImport;54import com.sun.tools.javac.tree.TreeInfo;55import com.sun.tools.javac.util.List;56import com.sun.tools.javac.util.ListBuffer;57import com.sun.tools.javac.util.Name;58import com.sun.tools.javac.util.Names;59import com.sun.tools.javac.util.Position;60import static com.sun.tools.javac.code.Kinds.*;61import static com.sun.tools.javac.code.TypeTag.CLASS;62import static com.sun.tools.javac.tree.JCTree.Tag.*;6364/**65* Represents a java class and provides access to information66* about the class, the class' comment and tags, and the67* members of the class. A ClassDocImpl only exists if it was68* processed in this run of javadoc. References to classes69* which may or may not have been processed in this run are70* referred to using Type (which can be converted to ClassDocImpl,71* if possible).72*73* <p><b>This is NOT part of any supported API.74* If you write code that depends on this, you do so at your own risk.75* This code and its internal interfaces are subject to change or76* deletion without notice.</b>77*78* @see Type79*80* @since 1.281* @author Robert Field82* @author Neal Gafter (rewrite)83* @author Scott Seligman (generics, enums, annotations)84*/8586public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {8788public final ClassType type; // protected->public for debugging89protected final ClassSymbol tsym;9091boolean isIncluded = false; // Set in RootDocImpl9293private SerializedForm serializedForm;9495/**96* Constructor97*/98public ClassDocImpl(DocEnv env, ClassSymbol sym) {99this(env, sym, null);100}101102/**103* Constructor104*/105public ClassDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) {106super(env, sym, treePath);107this.type = (ClassType)sym.type;108this.tsym = sym;109}110111public com.sun.javadoc.Type getElementType() {112return null;113}114115/**116* Returns the flags in terms of javac's flags117*/118protected long getFlags() {119return getFlags(tsym);120}121122/**123* Returns the flags of a ClassSymbol in terms of javac's flags124*/125static long getFlags(ClassSymbol clazz) {126try {127return clazz.flags();128} catch (CompletionFailure ex) {129/* Quietly ignore completion failures and try again - the type130* for which the CompletionFailure was thrown shouldn't be completed131* again by the completer that threw the CompletionFailure.132*/133return getFlags(clazz);134}135}136137/**138* Is a ClassSymbol an annotation type?139*/140static boolean isAnnotationType(ClassSymbol clazz) {141return (getFlags(clazz) & Flags.ANNOTATION) != 0;142}143144/**145* Identify the containing class146*/147protected ClassSymbol getContainingClass() {148return tsym.owner.enclClass();149}150151/**152* Return true if this is a class, not an interface.153*/154@Override155public boolean isClass() {156return !Modifier.isInterface(getModifiers());157}158159/**160* Return true if this is a ordinary class,161* not an enumeration, exception, an error, or an interface.162*/163@Override164public boolean isOrdinaryClass() {165if (isEnum() || isInterface() || isAnnotationType()) {166return false;167}168for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {169if (t.tsym == env.syms.errorType.tsym ||170t.tsym == env.syms.exceptionType.tsym) {171return false;172}173}174return true;175}176177/**178* Return true if this is an enumeration.179* (For legacy doclets, return false.)180*/181@Override182public boolean isEnum() {183return (getFlags() & Flags.ENUM) != 0184&&185!env.legacyDoclet;186}187188/**189* Return true if this is an interface, but not an annotation type.190* Overridden by AnnotationTypeDocImpl.191*/192@Override193public boolean isInterface() {194return Modifier.isInterface(getModifiers());195}196197/**198* Return true if this is an exception class199*/200@Override201public boolean isException() {202if (isEnum() || isInterface() || isAnnotationType()) {203return false;204}205for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {206if (t.tsym == env.syms.exceptionType.tsym) {207return true;208}209}210return false;211}212213/**214* Return true if this is an error class215*/216@Override217public boolean isError() {218if (isEnum() || isInterface() || isAnnotationType()) {219return false;220}221for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {222if (t.tsym == env.syms.errorType.tsym) {223return true;224}225}226return false;227}228229/**230* Return true if this is a throwable class231*/232public boolean isThrowable() {233if (isEnum() || isInterface() || isAnnotationType()) {234return false;235}236for (Type t = type; t.hasTag(CLASS); t = env.types.supertype(t)) {237if (t.tsym == env.syms.throwableType.tsym) {238return true;239}240}241return false;242}243244/**245* Return true if this class is abstract246*/247public boolean isAbstract() {248return Modifier.isAbstract(getModifiers());249}250251/**252* Returns true if this class was synthesized by the compiler.253*/254public boolean isSynthetic() {255return (getFlags() & Flags.SYNTHETIC) != 0;256}257258/**259* Return true if this class is included in the active set.260* A ClassDoc is included iff either it is specified on the261* commandline, or if it's containing package is specified262* on the command line, or if it is a member class of an263* included class.264*/265266public boolean isIncluded() {267if (isIncluded) {268return true;269}270if (env.shouldDocument(tsym)) {271// Class is nameable from top-level and272// the class and all enclosing classes273// pass the modifier filter.274if (containingPackage().isIncluded()) {275return isIncluded=true;276}277ClassDoc outer = containingClass();278if (outer != null && outer.isIncluded()) {279return isIncluded=true;280}281}282return false;283}284285/**286* Return the package that this class is contained in.287*/288@Override289public PackageDoc containingPackage() {290PackageDocImpl p = env.getPackageDoc(tsym.packge());291if (p.setDocPath == false) {292FileObject docPath;293try {294Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)295? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;296297docPath = env.fileManager.getFileForInput(298location, p.qualifiedName(), "package.html");299} catch (IOException e) {300docPath = null;301}302303if (docPath == null) {304// fall back on older semantics of looking in same directory as305// source file for this class306SourcePosition po = position();307if (env.fileManager instanceof StandardJavaFileManager &&308po instanceof SourcePositionImpl) {309URI uri = ((SourcePositionImpl) po).filename.toUri();310if ("file".equals(uri.getScheme())) {311File f = new File(uri);312File dir = f.getParentFile();313if (dir != null) {314File pf = new File(dir, "package.html");315if (pf.exists()) {316StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;317docPath = sfm.getJavaFileObjects(pf).iterator().next();318}319}320321}322}323}324325p.setDocPath(docPath);326}327return p;328}329330/**331* Return the class name without package qualifier - but with332* enclosing class qualifier - as a String.333* <pre>334* Examples:335* for java.util.Hashtable336* return Hashtable337* for java.util.Map.Entry338* return Map.Entry339* </pre>340*/341public String name() {342if (name == null) {343name = getClassName(tsym, false);344}345return name;346}347348private String name;349350/**351* Return the qualified class name as a String.352* <pre>353* Example:354* for java.util.Hashtable355* return java.util.Hashtable356* if no qualifier, just return flat name357* </pre>358*/359public String qualifiedName() {360if (qualifiedName == null) {361qualifiedName = getClassName(tsym, true);362}363return qualifiedName;364}365366private String qualifiedName;367368/**369* Return unqualified name of type excluding any dimension information.370* <p>371* For example, a two dimensional array of String returns 'String'.372*/373public String typeName() {374return name();375}376377/**378* Return qualified name of type excluding any dimension information.379*<p>380* For example, a two dimensional array of String381* returns 'java.lang.String'.382*/383public String qualifiedTypeName() {384return qualifiedName();385}386387/**388* Return the simple name of this type.389*/390public String simpleTypeName() {391if (simpleTypeName == null) {392simpleTypeName = tsym.name.toString();393}394return simpleTypeName;395}396397private String simpleTypeName;398399/**400* Return the qualified name and any type parameters.401* Each parameter is a type variable with optional bounds.402*/403@Override404public String toString() {405return classToString(env, tsym, true);406}407408/**409* Return the class name as a string. If "full" is true the name is410* qualified, otherwise it is qualified by its enclosing class(es) only.411*/412static String getClassName(ClassSymbol c, boolean full) {413if (full) {414return c.getQualifiedName().toString();415} else {416String n = "";417for ( ; c != null; c = c.owner.enclClass()) {418n = c.name + (n.equals("") ? "" : ".") + n;419}420return n;421}422}423424/**425* Return the class name with any type parameters as a string.426* Each parameter is a type variable with optional bounds.427* If "full" is true all names are qualified, otherwise they are428* qualified by their enclosing class(es) only.429*/430static String classToString(DocEnv env, ClassSymbol c, boolean full) {431StringBuilder s = new StringBuilder();432if (!c.isInner()) { // if c is not an inner class433s.append(getClassName(c, full));434} else {435// c is an inner class, so include type params of outer.436ClassSymbol encl = c.owner.enclClass();437s.append(classToString(env, encl, full))438.append('.')439.append(c.name);440}441s.append(TypeMaker.typeParametersString(env, c, full));442return s.toString();443}444445/**446* Is this class (or any enclosing class) generic? That is, does447* it have type parameters?448*/449static boolean isGeneric(ClassSymbol c) {450return c.type.allparams().nonEmpty();451}452453/**454* Return the formal type parameters of this class or interface.455* Return an empty array if there are none.456*/457public TypeVariable[] typeParameters() {458if (env.legacyDoclet) {459return new TypeVariable[0];460}461TypeVariable res[] = new TypeVariable[type.getTypeArguments().length()];462TypeMaker.getTypes(env, type.getTypeArguments(), res);463return res;464}465466/**467* Return the type parameter tags of this class or interface.468*/469public ParamTag[] typeParamTags() {470return (env.legacyDoclet)471? new ParamTag[0]472: comment().typeParamTags();473}474475/**476* Return the modifier string for this class. If it's an interface477* exclude 'abstract' keyword from the modifier string478*/479@Override480public String modifiers() {481return Modifier.toString(modifierSpecifier());482}483484@Override485public int modifierSpecifier() {486int modifiers = getModifiers();487return (isInterface() || isAnnotationType())488? modifiers & ~Modifier.ABSTRACT489: modifiers;490}491492/**493* Return the superclass of this class494*495* @return the ClassDocImpl for the superclass of this class, null496* if there is no superclass.497*/498public ClassDoc superclass() {499if (isInterface() || isAnnotationType()) return null;500if (tsym == env.syms.objectType.tsym) return null;501ClassSymbol c = (ClassSymbol)env.types.supertype(type).tsym;502if (c == null || c == tsym) c = (ClassSymbol)env.syms.objectType.tsym;503return env.getClassDoc(c);504}505506/**507* Return the superclass of this class. Return null if this is an508* interface. A superclass is represented by either a509* <code>ClassDoc</code> or a <code>ParameterizedType</code>.510*/511public com.sun.javadoc.Type superclassType() {512if (isInterface() || isAnnotationType() ||513(tsym == env.syms.objectType.tsym))514return null;515Type sup = env.types.supertype(type);516return TypeMaker.getType(env,517(sup.hasTag(TypeTag.NONE)) ? env.syms.objectType : sup);518}519520/**521* Test whether this class is a subclass of the specified class.522*523* @param cd the candidate superclass.524* @return true if cd is a superclass of this class.525*/526public boolean subclassOf(ClassDoc cd) {527return tsym.isSubClass(((ClassDocImpl)cd).tsym, env.types);528}529530/**531* Return interfaces implemented by this class or interfaces532* extended by this interface.533*534* @return An array of ClassDocImpl representing the interfaces.535* Return an empty array if there are no interfaces.536*/537public ClassDoc[] interfaces() {538ListBuffer<ClassDocImpl> ta = new ListBuffer<ClassDocImpl>();539for (Type t : env.types.interfaces(type)) {540ta.append(env.getClassDoc((ClassSymbol)t.tsym));541}542//### Cache ta here?543return ta.toArray(new ClassDocImpl[ta.length()]);544}545546/**547* Return interfaces implemented by this class or interfaces extended548* by this interface. Includes only directly-declared interfaces, not549* inherited interfaces.550* Return an empty array if there are no interfaces.551*/552public com.sun.javadoc.Type[] interfaceTypes() {553//### Cache result here?554return TypeMaker.getTypes(env, env.types.interfaces(type));555}556557/**558* Return fields in class.559* @param filter include only the included fields if filter==true560*/561public FieldDoc[] fields(boolean filter) {562return fields(filter, false);563}564565/**566* Return included fields in class.567*/568public FieldDoc[] fields() {569return fields(true, false);570}571572/**573* Return the enum constants if this is an enum type.574*/575public FieldDoc[] enumConstants() {576return fields(false, true);577}578579/**580* Return fields in class.581* @param filter if true, return only the included fields582* @param enumConstants if true, return the enum constants instead583*/584private FieldDoc[] fields(boolean filter, boolean enumConstants) {585List<FieldDocImpl> fields = List.nil();586for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {587if (e.sym != null && e.sym.kind == VAR) {588VarSymbol s = (VarSymbol)e.sym;589boolean isEnum = ((s.flags() & Flags.ENUM) != 0) &&590!env.legacyDoclet;591if (isEnum == enumConstants &&592(!filter || env.shouldDocument(s))) {593fields = fields.prepend(env.getFieldDoc(s));594}595}596}597return fields.toArray(new FieldDocImpl[fields.length()]);598}599600/**601* Return methods in class.602* This method is overridden by AnnotationTypeDocImpl.603*604* @param filter include only the included methods if filter==true605* @return an array of MethodDocImpl for representing the visible606* methods in this class. Does not include constructors.607*/608public MethodDoc[] methods(boolean filter) {609Names names = tsym.name.table.names;610List<MethodDocImpl> methods = List.nil();611for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {612if (e.sym != null613&& e.sym.kind == Kinds.MTH614&& e.sym.name != names.init615&& e.sym.name != names.clinit) {616MethodSymbol s = (MethodSymbol)e.sym;617if (!filter || env.shouldDocument(s)) {618methods = methods.prepend(env.getMethodDoc(s));619}620}621}622//### Cache methods here?623return methods.toArray(new MethodDocImpl[methods.length()]);624}625626/**627* Return included methods in class.628*629* @return an array of MethodDocImpl for representing the visible630* methods in this class. Does not include constructors.631*/632public MethodDoc[] methods() {633return methods(true);634}635636/**637* Return constructors in class.638*639* @param filter include only the included constructors if filter==true640* @return an array of ConstructorDocImpl for representing the visible641* constructors in this class.642*/643public ConstructorDoc[] constructors(boolean filter) {644Names names = tsym.name.table.names;645List<ConstructorDocImpl> constructors = List.nil();646for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {647if (e.sym != null &&648e.sym.kind == Kinds.MTH && e.sym.name == names.init) {649MethodSymbol s = (MethodSymbol)e.sym;650if (!filter || env.shouldDocument(s)) {651constructors = constructors.prepend(env.getConstructorDoc(s));652}653}654}655//### Cache constructors here?656return constructors.toArray(new ConstructorDocImpl[constructors.length()]);657}658659/**660* Return included constructors in class.661*662* @return an array of ConstructorDocImpl for representing the visible663* constructors in this class.664*/665public ConstructorDoc[] constructors() {666return constructors(true);667}668669/**670* Adds all inner classes of this class, and their671* inner classes recursively, to the list l.672*/673void addAllClasses(ListBuffer<ClassDocImpl> l, boolean filtered) {674try {675if (isSynthetic()) return;676// sometimes synthetic classes are not marked synthetic677if (!JavadocTool.isValidClassName(tsym.name.toString())) return;678if (filtered && !env.shouldDocument(tsym)) return;679if (l.contains(this)) return;680l.append(this);681List<ClassDocImpl> more = List.nil();682for (Scope.Entry e = tsym.members().elems; e != null;683e = e.sibling) {684if (e.sym != null && e.sym.kind == Kinds.TYP) {685ClassSymbol s = (ClassSymbol)e.sym;686ClassDocImpl c = env.getClassDoc(s);687if (c.isSynthetic()) continue;688if (c != null) more = more.prepend(c);689}690}691// this extra step preserves the ordering from oldjavadoc692for (; more.nonEmpty(); more=more.tail) {693more.head.addAllClasses(l, filtered);694}695} catch (CompletionFailure e) {696// quietly ignore completion failures697}698}699700/**701* Return inner classes within this class.702*703* @param filter include only the included inner classes if filter==true.704* @return an array of ClassDocImpl for representing the visible705* classes defined in this class. Anonymous and local classes706* are not included.707*/708public ClassDoc[] innerClasses(boolean filter) {709ListBuffer<ClassDocImpl> innerClasses = new ListBuffer<ClassDocImpl>();710for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {711if (e.sym != null && e.sym.kind == Kinds.TYP) {712ClassSymbol s = (ClassSymbol)e.sym;713if ((s.flags_field & Flags.SYNTHETIC) != 0) continue;714if (!filter || env.isVisible(s)) {715innerClasses.prepend(env.getClassDoc(s));716}717}718}719//### Cache classes here?720return innerClasses.toArray(new ClassDocImpl[innerClasses.length()]);721}722723/**724* Return included inner classes within this class.725*726* @return an array of ClassDocImpl for representing the visible727* classes defined in this class. Anonymous and local classes728* are not included.729*/730public ClassDoc[] innerClasses() {731return innerClasses(true);732}733734/**735* Find a class within the context of this class.736* Search order: qualified name, in this class (inner),737* in this package, in the class imports, in the package738* imports.739* Return the ClassDocImpl if found, null if not found.740*/741//### The specified search order is not the normal rule the742//### compiler would use. Leave as specified or change it?743public ClassDoc findClass(String className) {744ClassDoc searchResult = searchClass(className);745if (searchResult == null) {746ClassDocImpl enclosingClass = (ClassDocImpl)containingClass();747//Expand search space to include enclosing class.748while (enclosingClass != null && enclosingClass.containingClass() != null) {749enclosingClass = (ClassDocImpl)enclosingClass.containingClass();750}751searchResult = enclosingClass == null ?752null : enclosingClass.searchClass(className);753}754return searchResult;755}756757private ClassDoc searchClass(String className) {758Names names = tsym.name.table.names;759760// search by qualified name first761ClassDoc cd = env.lookupClass(className);762if (cd != null) {763return cd;764}765766// search inner classes767//### Add private entry point to avoid creating array?768//### Replicate code in innerClasses here to avoid consing?769for (ClassDoc icd : innerClasses()) {770if (icd.name().equals(className) ||771//### This is from original javadoc but it looks suspicious to me...772//### I believe it is attempting to compensate for the confused773//### convention of including the nested class qualifiers in the774//### 'name' of the inner class, rather than the true simple name.775icd.name().endsWith("." + className)) {776return icd;777} else {778ClassDoc innercd = ((ClassDocImpl) icd).searchClass(className);779if (innercd != null) {780return innercd;781}782}783}784785// check in this package786cd = containingPackage().findClass(className);787if (cd != null) {788return cd;789}790791// make sure that this symbol has been completed792if (tsym.completer != null) {793tsym.complete();794}795796// search imports797798if (tsym.sourcefile != null) {799800//### This information is available only for source classes.801802Env<AttrContext> compenv = env.enter.getEnv(tsym);803if (compenv == null) return null;804805Scope s = compenv.toplevel.namedImportScope;806for (Scope.Entry e = s.lookup(names.fromString(className)); e.scope != null; e = e.next()) {807if (e.sym.kind == Kinds.TYP) {808ClassDoc c = env.getClassDoc((ClassSymbol)e.sym);809return c;810}811}812813s = compenv.toplevel.starImportScope;814for (Scope.Entry e = s.lookup(names.fromString(className)); e.scope != null; e = e.next()) {815if (e.sym.kind == Kinds.TYP) {816ClassDoc c = env.getClassDoc((ClassSymbol)e.sym);817return c;818}819}820}821822return null; // not found823}824825826private boolean hasParameterTypes(MethodSymbol method, String[] argTypes) {827828if (argTypes == null) {829// wildcard830return true;831}832833int i = 0;834List<Type> types = method.type.getParameterTypes();835836if (argTypes.length != types.length()) {837return false;838}839840for (Type t : types) {841String argType = argTypes[i++];842// For vararg method, "T..." matches type T[].843if (i == argTypes.length) {844argType = argType.replace("...", "[]");845}846if (!hasTypeName(env.types.erasure(t), argType)) { //###(gj)847return false;848}849}850return true;851}852// where853private boolean hasTypeName(Type t, String name) {854return855name.equals(TypeMaker.getTypeName(t, true))856||857name.equals(TypeMaker.getTypeName(t, false))858||859(qualifiedName() + "." + name).equals(TypeMaker.getTypeName(t, true));860}861862863864/**865* Find a method in this class scope.866* Search order: this class, interfaces, superclasses, outerclasses.867* Note that this is not necessarily what the compiler would do!868*869* @param methodName the unqualified name to search for.870* @param paramTypes the array of Strings for method parameter types.871* @return the first MethodDocImpl which matches, null if not found.872*/873public MethodDocImpl findMethod(String methodName, String[] paramTypes) {874// Use hash table 'searched' to avoid searching same class twice.875//### It is not clear how this could happen.876return searchMethod(methodName, paramTypes, new HashSet<ClassDocImpl>());877}878879private MethodDocImpl searchMethod(String methodName,880String[] paramTypes, Set<ClassDocImpl> searched) {881//### Note that this search is not necessarily what the compiler would do!882883Names names = tsym.name.table.names;884// do not match constructors885if (names.init.contentEquals(methodName)) {886return null;887}888889ClassDocImpl cdi;890MethodDocImpl mdi;891892if (searched.contains(this)) {893return null;894}895searched.add(this);896897//DEBUG898/*---------------------------------*899System.out.print("searching " + this + " for " + methodName);900if (paramTypes == null) {901System.out.println("()");902} else {903System.out.print("(");904for (int k=0; k < paramTypes.length; k++) {905System.out.print(paramTypes[k]);906if ((k + 1) < paramTypes.length) {907System.out.print(", ");908}909}910System.out.println(")");911}912*---------------------------------*/913914// search current class915Scope.Entry e = tsym.members().lookup(names.fromString(methodName));916917//### Using modifier filter here isn't really correct,918//### but emulates the old behavior. Instead, we should919//### apply the normal rules of visibility and inheritance.920921if (paramTypes == null) {922// If no parameters specified, we are allowed to return923// any method with a matching name. In practice, the old924// code returned the first method, which is now the last!925// In order to provide textually identical results, we926// attempt to emulate the old behavior.927MethodSymbol lastFound = null;928for (; e.scope != null; e = e.next()) {929if (e.sym.kind == Kinds.MTH) {930//### Should intern methodName as Name.931if (e.sym.name.toString().equals(methodName)) {932lastFound = (MethodSymbol)e.sym;933}934}935}936if (lastFound != null) {937return env.getMethodDoc(lastFound);938}939} else {940for (; e.scope != null; e = e.next()) {941if (e.sym != null &&942e.sym.kind == Kinds.MTH) {943//### Should intern methodName as Name.944if (hasParameterTypes((MethodSymbol)e.sym, paramTypes)) {945return env.getMethodDoc((MethodSymbol)e.sym);946}947}948}949}950951//### If we found a MethodDoc above, but which did not pass952//### the modifier filter, we should return failure here!953954// search superclass955cdi = (ClassDocImpl)superclass();956if (cdi != null) {957mdi = cdi.searchMethod(methodName, paramTypes, searched);958if (mdi != null) {959return mdi;960}961}962963// search interfaces964ClassDoc intf[] = interfaces();965for (int i = 0; i < intf.length; i++) {966cdi = (ClassDocImpl)intf[i];967mdi = cdi.searchMethod(methodName, paramTypes, searched);968if (mdi != null) {969return mdi;970}971}972973// search enclosing class974cdi = (ClassDocImpl)containingClass();975if (cdi != null) {976mdi = cdi.searchMethod(methodName, paramTypes, searched);977if (mdi != null) {978return mdi;979}980}981982//###(gj) As a temporary measure until type variables are better983//### handled, try again without the parameter types.984//### This should most often find the right method, and occassionally985//### find the wrong one.986//if (paramTypes != null) {987// return findMethod(methodName, null);988//}989990return null;991}992993/**994* Find constructor in this class.995*996* @param constrName the unqualified name to search for.997* @param paramTypes the array of Strings for constructor parameters.998* @return the first ConstructorDocImpl which matches, null if not found.999*/1000public ConstructorDoc findConstructor(String constrName,1001String[] paramTypes) {1002Names names = tsym.name.table.names;1003for (Scope.Entry e = tsym.members().lookup(names.fromString("<init>")); e.scope != null; e = e.next()) {1004if (e.sym.kind == Kinds.MTH) {1005if (hasParameterTypes((MethodSymbol)e.sym, paramTypes)) {1006return env.getConstructorDoc((MethodSymbol)e.sym);1007}1008}1009}10101011//###(gj) As a temporary measure until type variables are better1012//### handled, try again without the parameter types.1013//### This will often find the right constructor, and occassionally1014//### find the wrong one.1015//if (paramTypes != null) {1016// return findConstructor(constrName, null);1017//}10181019return null;1020}10211022/**1023* Find a field in this class scope.1024* Search order: this class, outerclasses, interfaces,1025* superclasses. IMP: If see tag is defined in an inner class,1026* which extends a super class and if outerclass and the super1027* class have a visible field in common then Java compiler cribs1028* about the ambiguity, but the following code will search in the1029* above given search order.1030*1031* @param fieldName the unqualified name to search for.1032* @return the first FieldDocImpl which matches, null if not found.1033*/1034public FieldDoc findField(String fieldName) {1035return searchField(fieldName, new HashSet<ClassDocImpl>());1036}10371038private FieldDocImpl searchField(String fieldName, Set<ClassDocImpl> searched) {1039Names names = tsym.name.table.names;1040if (searched.contains(this)) {1041return null;1042}1043searched.add(this);10441045for (Scope.Entry e = tsym.members().lookup(names.fromString(fieldName)); e.scope != null; e = e.next()) {1046if (e.sym.kind == Kinds.VAR) {1047//### Should intern fieldName as Name.1048return env.getFieldDoc((VarSymbol)e.sym);1049}1050}10511052//### If we found a FieldDoc above, but which did not pass1053//### the modifier filter, we should return failure here!10541055ClassDocImpl cdi = (ClassDocImpl)containingClass();1056if (cdi != null) {1057FieldDocImpl fdi = cdi.searchField(fieldName, searched);1058if (fdi != null) {1059return fdi;1060}1061}10621063// search superclass1064cdi = (ClassDocImpl)superclass();1065if (cdi != null) {1066FieldDocImpl fdi = cdi.searchField(fieldName, searched);1067if (fdi != null) {1068return fdi;1069}1070}10711072// search interfaces1073ClassDoc intf[] = interfaces();1074for (int i = 0; i < intf.length; i++) {1075cdi = (ClassDocImpl)intf[i];1076FieldDocImpl fdi = cdi.searchField(fieldName, searched);1077if (fdi != null) {1078return fdi;1079}1080}10811082return null;1083}10841085/**1086* Get the list of classes declared as imported.1087* These are called "single-type-import declarations" in the JLS.1088* This method is deprecated in the ClassDoc interface.1089*1090* @return an array of ClassDocImpl representing the imported classes.1091*1092* @deprecated Import declarations are implementation details that1093* should not be exposed here. In addition, not all imported1094* classes are imported through single-type-import declarations.1095*/1096@Deprecated1097public ClassDoc[] importedClasses() {1098// information is not available for binary classfiles1099if (tsym.sourcefile == null) return new ClassDoc[0];11001101ListBuffer<ClassDocImpl> importedClasses = new ListBuffer<ClassDocImpl>();11021103Env<AttrContext> compenv = env.enter.getEnv(tsym);1104if (compenv == null) return new ClassDocImpl[0];11051106Name asterisk = tsym.name.table.names.asterisk;1107for (JCTree t : compenv.toplevel.defs) {1108if (t.hasTag(IMPORT)) {1109JCTree imp = ((JCImport) t).qualid;1110if ((TreeInfo.name(imp) != asterisk) &&1111(imp.type.tsym.kind & Kinds.TYP) != 0) {1112importedClasses.append(1113env.getClassDoc((ClassSymbol)imp.type.tsym));1114}1115}1116}11171118return importedClasses.toArray(new ClassDocImpl[importedClasses.length()]);1119}11201121/**1122* Get the list of packages declared as imported.1123* These are called "type-import-on-demand declarations" in the JLS.1124* This method is deprecated in the ClassDoc interface.1125*1126* @return an array of PackageDocImpl representing the imported packages.1127*1128* ###NOTE: the syntax supports importing all inner classes from a class as well.1129* @deprecated Import declarations are implementation details that1130* should not be exposed here. In addition, this method's1131* return type does not allow for all type-import-on-demand1132* declarations to be returned.1133*/1134@Deprecated1135public PackageDoc[] importedPackages() {1136// information is not available for binary classfiles1137if (tsym.sourcefile == null) return new PackageDoc[0];11381139ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<PackageDocImpl>();11401141//### Add the implicit "import java.lang.*" to the result1142Names names = tsym.name.table.names;1143importedPackages.append(env.getPackageDoc(env.reader.enterPackage(names.java_lang)));11441145Env<AttrContext> compenv = env.enter.getEnv(tsym);1146if (compenv == null) return new PackageDocImpl[0];11471148for (JCTree t : compenv.toplevel.defs) {1149if (t.hasTag(IMPORT)) {1150JCTree imp = ((JCImport) t).qualid;1151if (TreeInfo.name(imp) == names.asterisk) {1152JCFieldAccess sel = (JCFieldAccess)imp;1153Symbol s = sel.selected.type.tsym;1154PackageDocImpl pdoc = env.getPackageDoc(s.packge());1155if (!importedPackages.contains(pdoc))1156importedPackages.append(pdoc);1157}1158}1159}11601161return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);1162}11631164/**1165* Return the type's dimension information.1166* Always return "", as this is not an array type.1167*/1168public String dimension() {1169return "";1170}11711172/**1173* Return this type as a class, which it already is.1174*/1175public ClassDoc asClassDoc() {1176return this;1177}11781179/**1180* Return null (unless overridden), as this is not an annotation type.1181*/1182public AnnotationTypeDoc asAnnotationTypeDoc() {1183return null;1184}11851186/**1187* Return null, as this is not a class instantiation.1188*/1189public ParameterizedType asParameterizedType() {1190return null;1191}11921193/**1194* Return null, as this is not a type variable.1195*/1196public TypeVariable asTypeVariable() {1197return null;1198}11991200/**1201* Return null, as this is not a wildcard type.1202*/1203public WildcardType asWildcardType() {1204return null;1205}12061207/**1208* Returns null, as this is not an annotated type.1209*/1210public AnnotatedType asAnnotatedType() {1211return null;1212}12131214/**1215* Return false, as this is not a primitive type.1216*/1217public boolean isPrimitive() {1218return false;1219}12201221//--- Serialization ---12221223//### These methods ignore modifier filter.12241225/**1226* Return true if this class implements <code>java.io.Serializable</code>.1227*1228* Since <code>java.io.Externalizable</code> extends1229* <code>java.io.Serializable</code>,1230* Externalizable objects are also Serializable.1231*/1232public boolean isSerializable() {1233try {1234return env.types.isSubtype(type, env.syms.serializableType);1235} catch (CompletionFailure ex) {1236// quietly ignore completion failures1237return false;1238}1239}12401241/**1242* Return true if this class implements1243* <code>java.io.Externalizable</code>.1244*/1245public boolean isExternalizable() {1246try {1247return env.types.isSubtype(type, env.externalizableSym.type);1248} catch (CompletionFailure ex) {1249// quietly ignore completion failures1250return false;1251}1252}12531254/**1255* Return the serialization methods for this class.1256*1257* @return an array of <code>MethodDocImpl</code> that represents1258* the serialization methods for this class.1259*/1260public MethodDoc[] serializationMethods() {1261if (serializedForm == null) {1262serializedForm = new SerializedForm(env, tsym, this);1263}1264//### Clone this?1265return serializedForm.methods();1266}12671268/**1269* Return the Serializable fields of class.<p>1270*1271* Return either a list of default fields documented by1272* <code>serial</code> tag<br>1273* or return a single <code>FieldDoc</code> for1274* <code>serialPersistentField</code> member.1275* There should be a <code>serialField</code> tag for1276* each Serializable field defined by an <code>ObjectStreamField</code>1277* array component of <code>serialPersistentField</code>.1278*1279* @returns an array of <code>FieldDoc</code> for the Serializable fields1280* of this class.1281*1282* @see #definesSerializableFields()1283* @see SerialFieldTagImpl1284*/1285public FieldDoc[] serializableFields() {1286if (serializedForm == null) {1287serializedForm = new SerializedForm(env, tsym, this);1288}1289//### Clone this?1290return serializedForm.fields();1291}12921293/**1294* Return true if Serializable fields are explicitly defined with1295* the special class member <code>serialPersistentFields</code>.1296*1297* @see #serializableFields()1298* @see SerialFieldTagImpl1299*/1300public boolean definesSerializableFields() {1301if (!isSerializable() || isExternalizable()) {1302return false;1303} else {1304if (serializedForm == null) {1305serializedForm = new SerializedForm(env, tsym, this);1306}1307//### Clone this?1308return serializedForm.definesSerializableFields();1309}1310}13111312/**1313* Determine if a class is a RuntimeException.1314* <p>1315* Used only by ThrowsTagImpl.1316*/1317boolean isRuntimeException() {1318return tsym.isSubClass(env.syms.runtimeExceptionType.tsym, env.types);1319}13201321/**1322* Return the source position of the entity, or null if1323* no position is available.1324*/1325@Override1326public SourcePosition position() {1327if (tsym.sourcefile == null) return null;1328return SourcePositionImpl.make(tsym.sourcefile,1329(tree==null) ? Position.NOPOS : tree.pos,1330lineMap);1331}1332}133313341335