Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
38899 views
/*1* Copyright (c) 2000, 2016, 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.lang.reflect.Modifier;28import java.util.*;2930import javax.tools.JavaFileManager;3132import com.sun.javadoc.*;33import com.sun.source.util.JavacTask;34import com.sun.source.util.TreePath;35import com.sun.tools.doclint.DocLint;36import com.sun.tools.javac.api.BasicJavacTask;37import com.sun.tools.javac.code.*;38import com.sun.tools.javac.code.Symbol.*;39import com.sun.tools.javac.code.Type.ClassType;40import com.sun.tools.javac.comp.Check;41import com.sun.tools.javac.file.JavacFileManager;42import com.sun.tools.javac.tree.JCTree;43import com.sun.tools.javac.tree.JCTree.*;44import com.sun.tools.javac.util.Context;45import com.sun.tools.javac.util.Names;4647/**48* Holds the environment for a run of javadoc.49* Holds only the information needed throughout the50* run and not the compiler info that could be GC'ed51* or ported.52*53* <p><b>This is NOT part of any supported API.54* If you write code that depends on this, you do so at your own risk.55* This code and its internal interfaces are subject to change or56* deletion without notice.</b>57*58* @since 1.459* @author Robert Field60* @author Neal Gafter (rewrite)61* @author Scott Seligman (generics)62*/63public class DocEnv {64protected static final Context.Key<DocEnv> docEnvKey =65new Context.Key<DocEnv>();6667public static DocEnv instance(Context context) {68DocEnv instance = context.get(docEnvKey);69if (instance == null)70instance = new DocEnv(context);71return instance;72}7374private Messager messager;7576DocLocale doclocale;7778/** Predefined symbols known to the compiler. */79Symtab syms;8081/** Referenced directly in RootDocImpl. */82JavadocClassReader reader;8384/** Javadoc's own version of the compiler's enter phase. */85JavadocEnter enter;8687/** The name table. */88private final Names names;8990/** The encoding name. */91private String encoding;9293final Symbol externalizableSym;9495/** Access filter (public, protected, ...). */96protected ModifierFilter showAccess;9798/** True if we are using a sentence BreakIterator. */99boolean breakiterator;100101/**102* True if we do not want to print any notifications at all.103*/104boolean quiet = false;105106Check chk;107Types types;108JavaFileManager fileManager;109Context context;110DocLint doclint;111JavaScriptScanner javaScriptScanner;112113WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<JCTree, TreePath>();114115/** Allow documenting from class files? */116boolean docClasses = false;117118/** Does the doclet only expect pre-1.5 doclet API? */119protected boolean legacyDoclet = true;120121/**122* Set this to true if you would like to not emit any errors, warnings and123* notices.124*/125private boolean silent = false;126127/**128* The source language version.129*/130protected Source source;131132/**133* Constructor134*135* @param context Context for this javadoc instance.136*/137protected DocEnv(Context context) {138context.put(docEnvKey, this);139this.context = context;140141messager = Messager.instance0(context);142syms = Symtab.instance(context);143reader = JavadocClassReader.instance0(context);144enter = JavadocEnter.instance0(context);145names = Names.instance(context);146externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable"));147chk = Check.instance(context);148types = Types.instance(context);149fileManager = context.get(JavaFileManager.class);150if (fileManager instanceof JavacFileManager) {151((JavacFileManager)fileManager).setSymbolFileEnabled(false);152}153154// Default. Should normally be reset with setLocale.155this.doclocale = new DocLocale(this, "", breakiterator);156source = Source.instance(context);157}158159public void setSilent(boolean silent) {160this.silent = silent;161}162163/**164* Look up ClassDoc by qualified name.165*/166public ClassDocImpl lookupClass(String name) {167ClassSymbol c = getClassSymbol(name);168if (c != null) {169return getClassDoc(c);170} else {171return null;172}173}174175/**176* Load ClassDoc by qualified name.177*/178public ClassDocImpl loadClass(String name) {179try {180ClassSymbol c = reader.loadClass(names.fromString(name));181return getClassDoc(c);182} catch (CompletionFailure ex) {183chk.completionError(null, ex);184return null;185}186}187188/**189* Look up PackageDoc by qualified name.190*/191public PackageDocImpl lookupPackage(String name) {192//### Jing alleges that class check is needed193//### to avoid a compiler bug. Most likely194//### instead a dummy created for error recovery.195//### Should investigate this.196PackageSymbol p = syms.packages.get(names.fromString(name));197ClassSymbol c = getClassSymbol(name);198if (p != null && c == null) {199return getPackageDoc(p);200} else {201return null;202}203}204// where205/** Retrieve class symbol by fully-qualified name.206*/207ClassSymbol getClassSymbol(String name) {208// Name may contain nested class qualification.209// Generate candidate flatnames with successively shorter210// package qualifiers and longer nested class qualifiers.211int nameLen = name.length();212char[] nameChars = name.toCharArray();213int idx = name.length();214for (;;) {215ClassSymbol s = syms.classes.get(names.fromChars(nameChars, 0, nameLen));216if (s != null)217return s; // found it!218idx = name.substring(0, idx).lastIndexOf('.');219if (idx < 0) break;220nameChars[idx] = '$';221}222return null;223}224225/**226* Set the locale.227*/228public void setLocale(String localeName) {229// create locale specifics230doclocale = new DocLocale(this, localeName, breakiterator);231// update Messager if locale has changed.232messager.setLocale(doclocale.locale);233}234235/** Check whether this member should be documented. */236public boolean shouldDocument(VarSymbol sym) {237long mod = sym.flags();238239if ((mod & Flags.SYNTHETIC) != 0) {240return false;241}242243return showAccess.checkModifier(translateModifiers(mod));244}245246/** Check whether this member should be documented. */247public boolean shouldDocument(MethodSymbol sym) {248long mod = sym.flags();249250if ((mod & Flags.SYNTHETIC) != 0) {251return false;252}253254return showAccess.checkModifier(translateModifiers(mod));255}256257/** check whether this class should be documented. */258public boolean shouldDocument(ClassSymbol sym) {259return260(sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics261(docClasses || getClassDoc(sym).tree != null) &&262isVisible(sym);263}264265//### Comment below is inaccurate wrt modifier filter testing266/**267* Check the visibility if this is an nested class.268* if this is not a nested class, return true.269* if this is an static visible nested class,270* return true.271* if this is an visible nested class272* if the outer class is visible return true.273* else return false.274* IMPORTANT: This also allows, static nested classes275* to be defined inside an nested class, which is not276* allowed by the compiler. So such an test case will277* not reach upto this method itself, but if compiler278* allows it, then that will go through.279*/280protected boolean isVisible(ClassSymbol sym) {281long mod = sym.flags_field;282if (!showAccess.checkModifier(translateModifiers(mod))) {283return false;284}285ClassSymbol encl = sym.owner.enclClass();286return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl));287}288289//---------------- print forwarders ----------------//290291/**292* Print error message, increment error count.293*294* @param msg message to print.295*/296public void printError(String msg) {297if (silent)298return;299messager.printError(msg);300}301302/**303* Print error message, increment error count.304*305* @param key selects message from resource306*/307public void error(DocImpl doc, String key) {308if (silent)309return;310messager.error(doc==null ? null : doc.position(), key);311}312313/**314* Print error message, increment error count.315*316* @param key selects message from resource317*/318public void error(SourcePosition pos, String key) {319if (silent)320return;321messager.error(pos, key);322}323324/**325* Print error message, increment error count.326*327* @param msg message to print.328*/329public void printError(SourcePosition pos, String msg) {330if (silent)331return;332messager.printError(pos, msg);333}334335/**336* Print error message, increment error count.337*338* @param key selects message from resource339* @param a1 first argument340*/341public void error(DocImpl doc, String key, String a1) {342if (silent)343return;344messager.error(doc==null ? null : doc.position(), key, a1);345}346347/**348* Print error message, increment error count.349*350* @param key selects message from resource351* @param a1 first argument352* @param a2 second argument353*/354public void error(DocImpl doc, String key, String a1, String a2) {355if (silent)356return;357messager.error(doc==null ? null : doc.position(), key, a1, a2);358}359360/**361* Print error message, increment error count.362*363* @param key selects message from resource364* @param a1 first argument365* @param a2 second argument366* @param a3 third argument367*/368public void error(DocImpl doc, String key, String a1, String a2, String a3) {369if (silent)370return;371messager.error(doc==null ? null : doc.position(), key, a1, a2, a3);372}373374/**375* Print warning message, increment warning count.376*377* @param msg message to print.378*/379public void printWarning(String msg) {380if (silent)381return;382messager.printWarning(msg);383}384385/**386* Print warning message, increment warning count.387*388* @param key selects message from resource389*/390public void warning(DocImpl doc, String key) {391if (silent)392return;393messager.warning(doc==null ? null : doc.position(), key);394}395396/**397* Print warning message, increment warning count.398*399* @param msg message to print.400*/401public void printWarning(SourcePosition pos, String msg) {402if (silent)403return;404messager.printWarning(pos, msg);405}406407/**408* Print warning message, increment warning count.409*410* @param key selects message from resource411* @param a1 first argument412*/413public void warning(DocImpl doc, String key, String a1) {414if (silent)415return;416// suppress messages that have (probably) been covered by doclint417if (doclint != null && doc != null && key.startsWith("tag"))418return;419messager.warning(doc==null ? null : doc.position(), key, a1);420}421422/**423* Print warning message, increment warning count.424*425* @param key selects message from resource426* @param a1 first argument427* @param a2 second argument428*/429public void warning(DocImpl doc, String key, String a1, String a2) {430if (silent)431return;432messager.warning(doc==null ? null : doc.position(), key, a1, a2);433}434435/**436* Print warning message, increment warning count.437*438* @param key selects message from resource439* @param a1 first argument440* @param a2 second argument441* @param a3 third argument442*/443public void warning(DocImpl doc, String key, String a1, String a2, String a3) {444if (silent)445return;446messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3);447}448449/**450* Print warning message, increment warning count.451*452* @param key selects message from resource453* @param a1 first argument454* @param a2 second argument455* @param a3 third argument456*/457public void warning(DocImpl doc, String key, String a1, String a2, String a3,458String a4) {459if (silent)460return;461messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4);462}463464/**465* Print a message.466*467* @param msg message to print.468*/469public void printNotice(String msg) {470if (silent || quiet)471return;472messager.printNotice(msg);473}474475476/**477* Print a message.478*479* @param key selects message from resource480*/481public void notice(String key) {482if (silent || quiet)483return;484messager.notice(key);485}486487/**488* Print a message.489*490* @param msg message to print.491*/492public void printNotice(SourcePosition pos, String msg) {493if (silent || quiet)494return;495messager.printNotice(pos, msg);496}497498/**499* Print a message.500*501* @param key selects message from resource502* @param a1 first argument503*/504public void notice(String key, String a1) {505if (silent || quiet)506return;507messager.notice(key, a1);508}509510/**511* Print a message.512*513* @param key selects message from resource514* @param a1 first argument515* @param a2 second argument516*/517public void notice(String key, String a1, String a2) {518if (silent || quiet)519return;520messager.notice(key, a1, a2);521}522523/**524* Print a message.525*526* @param key selects message from resource527* @param a1 first argument528* @param a2 second argument529* @param a3 third argument530*/531public void notice(String key, String a1, String a2, String a3) {532if (silent || quiet)533return;534messager.notice(key, a1, a2, a3);535}536537/**538* Exit, reporting errors and warnings.539*/540public void exit() {541// Messager should be replaced by a more general542// compilation environment. This can probably543// subsume DocEnv as well.544messager.exit();545}546547protected Map<PackageSymbol, PackageDocImpl> packageMap =548new HashMap<PackageSymbol, PackageDocImpl>();549/**550* Return the PackageDoc of this package symbol.551*/552public PackageDocImpl getPackageDoc(PackageSymbol pack) {553PackageDocImpl result = packageMap.get(pack);554if (result != null) return result;555result = new PackageDocImpl(this, pack);556packageMap.put(pack, result);557return result;558}559560/**561* Create the PackageDoc (or a subtype) for a package symbol.562*/563void makePackageDoc(PackageSymbol pack, TreePath treePath) {564PackageDocImpl result = packageMap.get(pack);565if (result != null) {566if (treePath != null) result.setTreePath(treePath);567} else {568result = new PackageDocImpl(this, pack, treePath);569packageMap.put(pack, result);570}571}572573574protected Map<ClassSymbol, ClassDocImpl> classMap =575new HashMap<ClassSymbol, ClassDocImpl>();576/**577* Return the ClassDoc (or a subtype) of this class symbol.578*/579public ClassDocImpl getClassDoc(ClassSymbol clazz) {580ClassDocImpl result = classMap.get(clazz);581if (result != null) return result;582if (isAnnotationType(clazz)) {583result = new AnnotationTypeDocImpl(this, clazz);584} else {585result = new ClassDocImpl(this, clazz);586}587classMap.put(clazz, result);588return result;589}590591/**592* Create the ClassDoc (or a subtype) for a class symbol.593*/594protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) {595ClassDocImpl result = classMap.get(clazz);596if (result != null) {597if (treePath != null) result.setTreePath(treePath);598return;599}600if (isAnnotationType((JCClassDecl) treePath.getLeaf())) { // flags of clazz may not yet be set601result = new AnnotationTypeDocImpl(this, clazz, treePath);602} else {603result = new ClassDocImpl(this, clazz, treePath);604}605classMap.put(clazz, result);606}607608protected static boolean isAnnotationType(ClassSymbol clazz) {609return ClassDocImpl.isAnnotationType(clazz);610}611612protected static boolean isAnnotationType(JCClassDecl tree) {613return (tree.mods.flags & Flags.ANNOTATION) != 0;614}615616protected Map<VarSymbol, FieldDocImpl> fieldMap =617new HashMap<VarSymbol, FieldDocImpl>();618/**619* Return the FieldDoc of this var symbol.620*/621public FieldDocImpl getFieldDoc(VarSymbol var) {622FieldDocImpl result = fieldMap.get(var);623if (result != null) return result;624result = new FieldDocImpl(this, var);625fieldMap.put(var, result);626return result;627}628/**629* Create a FieldDoc for a var symbol.630*/631protected void makeFieldDoc(VarSymbol var, TreePath treePath) {632FieldDocImpl result = fieldMap.get(var);633if (result != null) {634if (treePath != null) result.setTreePath(treePath);635} else {636result = new FieldDocImpl(this, var, treePath);637fieldMap.put(var, result);638}639}640641protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap =642new HashMap<MethodSymbol, ExecutableMemberDocImpl>();643/**644* Create a MethodDoc for this MethodSymbol.645* Should be called only on symbols representing methods.646*/647protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) {648MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);649if (result != null) {650if (treePath != null) result.setTreePath(treePath);651} else {652result = new MethodDocImpl(this, meth, treePath);653methodMap.put(meth, result);654}655}656657/**658* Return the MethodDoc for a MethodSymbol.659* Should be called only on symbols representing methods.660*/661public MethodDocImpl getMethodDoc(MethodSymbol meth) {662assert !meth.isConstructor() : "not expecting a constructor symbol";663MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);664if (result != null) return result;665result = new MethodDocImpl(this, meth);666methodMap.put(meth, result);667return result;668}669670/**671* Create the ConstructorDoc for a MethodSymbol.672* Should be called only on symbols representing constructors.673*/674protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) {675ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);676if (result != null) {677if (treePath != null) result.setTreePath(treePath);678} else {679result = new ConstructorDocImpl(this, meth, treePath);680methodMap.put(meth, result);681}682}683684/**685* Return the ConstructorDoc for a MethodSymbol.686* Should be called only on symbols representing constructors.687*/688public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) {689assert meth.isConstructor() : "expecting a constructor symbol";690ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);691if (result != null) return result;692result = new ConstructorDocImpl(this, meth);693methodMap.put(meth, result);694return result;695}696697/**698* Create the AnnotationTypeElementDoc for a MethodSymbol.699* Should be called only on symbols representing annotation type elements.700*/701protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) {702AnnotationTypeElementDocImpl result =703(AnnotationTypeElementDocImpl)methodMap.get(meth);704if (result != null) {705if (treePath != null) result.setTreePath(treePath);706} else {707result =708new AnnotationTypeElementDocImpl(this, meth, treePath);709methodMap.put(meth, result);710}711}712713/**714* Return the AnnotationTypeElementDoc for a MethodSymbol.715* Should be called only on symbols representing annotation type elements.716*/717public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc(718MethodSymbol meth) {719720AnnotationTypeElementDocImpl result =721(AnnotationTypeElementDocImpl)methodMap.get(meth);722if (result != null) return result;723result = new AnnotationTypeElementDocImpl(this, meth);724methodMap.put(meth, result);725return result;726}727728// private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap =729// new HashMap<ClassType, ParameterizedTypeImpl>();730/**731* Return the ParameterizedType of this instantiation.732// * ### Could use Type.sameTypeAs() instead of equality matching in hashmap733// * ### to avoid some duplication.734*/735ParameterizedTypeImpl getParameterizedType(ClassType t) {736return new ParameterizedTypeImpl(this, t);737// ParameterizedTypeImpl result = parameterizedTypeMap.get(t);738// if (result != null) return result;739// result = new ParameterizedTypeImpl(this, t);740// parameterizedTypeMap.put(t, result);741// return result;742}743744TreePath getTreePath(JCCompilationUnit tree) {745TreePath p = treePaths.get(tree);746if (p == null)747treePaths.put(tree, p = new TreePath(tree));748return p;749}750751TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) {752TreePath p = treePaths.get(tree);753if (p == null)754treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));755return p;756}757758TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) {759return new TreePath(getTreePath(toplevel, cdecl), tree);760}761762/**763* Set the encoding.764*/765public void setEncoding(String encoding) {766this.encoding = encoding;767}768769/**770* Get the encoding.771*/772public String getEncoding() {773return encoding;774}775776/**777* Convert modifier bits from private coding used by778* the compiler to that of java.lang.reflect.Modifier.779*/780static int translateModifiers(long flags) {781int result = 0;782if ((flags & Flags.ABSTRACT) != 0)783result |= Modifier.ABSTRACT;784if ((flags & Flags.FINAL) != 0)785result |= Modifier.FINAL;786if ((flags & Flags.INTERFACE) != 0)787result |= Modifier.INTERFACE;788if ((flags & Flags.NATIVE) != 0)789result |= Modifier.NATIVE;790if ((flags & Flags.PRIVATE) != 0)791result |= Modifier.PRIVATE;792if ((flags & Flags.PROTECTED) != 0)793result |= Modifier.PROTECTED;794if ((flags & Flags.PUBLIC) != 0)795result |= Modifier.PUBLIC;796if ((flags & Flags.STATIC) != 0)797result |= Modifier.STATIC;798if ((flags & Flags.SYNCHRONIZED) != 0)799result |= Modifier.SYNCHRONIZED;800if ((flags & Flags.TRANSIENT) != 0)801result |= Modifier.TRANSIENT;802if ((flags & Flags.VOLATILE) != 0)803result |= Modifier.VOLATILE;804return result;805}806807void initDoclint(Collection<String> opts, Collection<String> customTagNames) {808ArrayList<String> doclintOpts = new ArrayList<String>();809810for (String opt: opts) {811doclintOpts.add(opt == null ? DocLint.XMSGS_OPTION : DocLint.XMSGS_CUSTOM_PREFIX + opt);812}813814if (doclintOpts.isEmpty()) {815doclintOpts.add(DocLint.XMSGS_OPTION);816} else if (doclintOpts.size() == 1817&& doclintOpts.get(0).equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) {818return;819}820821String sep = "";822StringBuilder customTags = new StringBuilder();823for (String customTag : customTagNames) {824customTags.append(sep);825customTags.append(customTag);826sep = DocLint.TAGS_SEPARATOR;827}828doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString());829830JavacTask t = BasicJavacTask.instance(context);831doclint = new DocLint();832// standard doclet normally generates H1, H2833doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");834doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);835}836837JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {838if (allowScriptInComments) {839javaScriptScanner = null;840} else {841javaScriptScanner = new JavaScriptScanner();842}843return javaScriptScanner;844}845846boolean showTagMessages() {847return (doclint == null);848}849}850851852