src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/DocEnv.java
branchniosocketimpl-branch
changeset 57208 7a45c67e73d0
parent 57207 30695f27d7ea
parent 53902 7a6fd71449e7
child 57210 a67ea4f53e56
equal deleted inserted replaced
57207:30695f27d7ea 57208:7a45c67e73d0
     1 /*
       
     2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.tools.javadoc.main;
       
    27 
       
    28 import java.lang.reflect.Modifier;
       
    29 import java.util.*;
       
    30 
       
    31 import javax.tools.JavaFileManager;
       
    32 
       
    33 import com.sun.javadoc.*;
       
    34 import com.sun.source.tree.CompilationUnitTree;
       
    35 import com.sun.source.util.JavacTask;
       
    36 import com.sun.source.util.TreePath;
       
    37 import com.sun.tools.doclint.DocLint;
       
    38 import com.sun.tools.javac.api.BasicJavacTask;
       
    39 import com.sun.tools.javac.code.*;
       
    40 import com.sun.tools.javac.code.Symbol.*;
       
    41 import com.sun.tools.javac.code.Symbol.ClassSymbol;
       
    42 import com.sun.tools.javac.code.Symbol.CompletionFailure;
       
    43 import com.sun.tools.javac.code.Symbol.MethodSymbol;
       
    44 import com.sun.tools.javac.code.Symbol.PackageSymbol;
       
    45 import com.sun.tools.javac.code.Symbol.VarSymbol;
       
    46 import com.sun.tools.javac.code.Type.ClassType;
       
    47 import com.sun.tools.javac.comp.Check;
       
    48 import com.sun.tools.javac.comp.Enter;
       
    49 import com.sun.tools.javac.file.JavacFileManager;
       
    50 import com.sun.tools.javac.tree.JCTree;
       
    51 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
       
    52 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
       
    53 import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
       
    54 import com.sun.tools.javac.util.Context;
       
    55 import com.sun.tools.javac.util.Convert;
       
    56 import com.sun.tools.javac.util.Name;
       
    57 import com.sun.tools.javac.util.Names;
       
    58 
       
    59 /**
       
    60  * Holds the environment for a run of javadoc.
       
    61  * Holds only the information needed throughout the
       
    62  * run and not the compiler info that could be GC'ed
       
    63  * or ported.
       
    64  *
       
    65  *  <p><b>This is NOT part of any supported API.
       
    66  *  If you write code that depends on this, you do so at your own risk.
       
    67  *  This code and its internal interfaces are subject to change or
       
    68  *  deletion without notice.</b>
       
    69  *
       
    70  * @since 1.4
       
    71  * @author Robert Field
       
    72  * @author Neal Gafter (rewrite)
       
    73  * @author Scott Seligman (generics)
       
    74  */
       
    75 @Deprecated(since="9", forRemoval=true)
       
    76 @SuppressWarnings("removal")
       
    77 public class DocEnv {
       
    78     protected static final Context.Key<DocEnv> docEnvKey = new Context.Key<>();
       
    79 
       
    80     public static DocEnv instance(Context context) {
       
    81         DocEnv instance = context.get(docEnvKey);
       
    82         if (instance == null)
       
    83             instance = new DocEnv(context);
       
    84         return instance;
       
    85     }
       
    86 
       
    87     DocLocale doclocale;
       
    88 
       
    89     private final Messager messager;
       
    90 
       
    91     /** Predefined symbols known to the compiler. */
       
    92     final Symtab syms;
       
    93 
       
    94     /** Referenced directly in RootDocImpl. */
       
    95     private final ClassFinder finder;
       
    96 
       
    97     /** Javadoc's own version of the compiler's enter phase. */
       
    98     final Enter enter;
       
    99 
       
   100     /** The name table. */
       
   101     private final Names names;
       
   102 
       
   103     /** The encoding name. */
       
   104     private String encoding;
       
   105 
       
   106     final Symbol externalizableSym;
       
   107 
       
   108     /** Access filter (public, protected, ...).  */
       
   109     protected ModifierFilter showAccess;
       
   110 
       
   111     /** True if we are using a sentence BreakIterator. */
       
   112     boolean breakiterator;
       
   113 
       
   114     /**
       
   115      * True if we do not want to print any notifications at all.
       
   116      */
       
   117     boolean quiet = false;
       
   118 
       
   119     Check chk;
       
   120     Types types;
       
   121     JavaFileManager fileManager;
       
   122     Context context;
       
   123     DocLint doclint;
       
   124     JavaScriptScanner javaScriptScanner;
       
   125 
       
   126     WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<>();
       
   127 
       
   128     /** Allow documenting from class files? */
       
   129     boolean docClasses = false;
       
   130 
       
   131     /** Does the doclet only expect pre-1.5 doclet API? */
       
   132     protected boolean legacyDoclet = true;
       
   133 
       
   134     /**
       
   135      * Set this to true if you would like to not emit any errors, warnings and
       
   136      * notices.
       
   137      */
       
   138     private boolean silent = false;
       
   139 
       
   140     /**
       
   141      * The source language version.
       
   142      */
       
   143     protected Source source;
       
   144 
       
   145     /**
       
   146      * Constructor
       
   147      *
       
   148      * @param context      Context for this javadoc instance.
       
   149      */
       
   150     protected DocEnv(Context context) {
       
   151         context.put(docEnvKey, this);
       
   152         this.context = context;
       
   153 
       
   154         messager = Messager.instance0(context);
       
   155         syms = Symtab.instance(context);
       
   156         finder = JavadocClassFinder.instance(context);
       
   157         enter = JavadocEnter.instance(context);
       
   158         names = Names.instance(context);
       
   159         externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
       
   160         chk = Check.instance(context);
       
   161         types = Types.instance(context);
       
   162         fileManager = context.get(JavaFileManager.class);
       
   163         if (fileManager instanceof JavacFileManager) {
       
   164             ((JavacFileManager)fileManager).setSymbolFileEnabled(false);
       
   165         }
       
   166 
       
   167         // Default.  Should normally be reset with setLocale.
       
   168         this.doclocale = new DocLocale(this, "", breakiterator);
       
   169         source = Source.instance(context);
       
   170     }
       
   171 
       
   172     public void setSilent(boolean silent) {
       
   173         this.silent = silent;
       
   174     }
       
   175 
       
   176     /**
       
   177      * Look up ClassDoc by qualified name.
       
   178      */
       
   179     public ClassDocImpl lookupClass(String name) {
       
   180         ClassSymbol c = getClassSymbol(name);
       
   181         if (c != null) {
       
   182             return getClassDoc(c);
       
   183         } else {
       
   184             return null;
       
   185         }
       
   186     }
       
   187 
       
   188     /**
       
   189      * Load ClassDoc by qualified name.
       
   190      */
       
   191     public ClassDocImpl loadClass(String name) {
       
   192         try {
       
   193             Name nameImpl = names.fromString(name);
       
   194             ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
       
   195             ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
       
   196             return getClassDoc(c);
       
   197         } catch (CompletionFailure ex) {
       
   198             chk.completionError(null, ex);
       
   199             return null;
       
   200         }
       
   201     }
       
   202 
       
   203     /**
       
   204      * Look up PackageDoc by qualified name.
       
   205      */
       
   206     public PackageDocImpl lookupPackage(String name) {
       
   207         //### Jing alleges that class check is needed
       
   208         //### to avoid a compiler bug.  Most likely
       
   209         //### instead a dummy created for error recovery.
       
   210         //### Should investigate this.
       
   211         Name nameImpl = names.fromString(name);
       
   212         ModuleSymbol mod = syms.inferModule(nameImpl);
       
   213         PackageSymbol p = mod != null ? syms.getPackage(mod, nameImpl) : null;
       
   214         ClassSymbol c = getClassSymbol(name);
       
   215         if (p != null && c == null) {
       
   216             return getPackageDoc(p);
       
   217         } else {
       
   218             return null;
       
   219         }
       
   220     }
       
   221         // where
       
   222         /** Retrieve class symbol by fully-qualified name.
       
   223          */
       
   224         ClassSymbol getClassSymbol(String name) {
       
   225             // Name may contain nested class qualification.
       
   226             // Generate candidate flatnames with successively shorter
       
   227             // package qualifiers and longer nested class qualifiers.
       
   228             int nameLen = name.length();
       
   229             char[] nameChars = name.toCharArray();
       
   230             int idx = name.length();
       
   231             for (;;) {
       
   232                 Name nameImpl = names.fromChars(nameChars, 0, nameLen);
       
   233                 ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
       
   234                 ClassSymbol s = mod != null ? syms.getClass(mod, nameImpl) : null;
       
   235                 if (s != null)
       
   236                     return s; // found it!
       
   237                 idx = name.substring(0, idx).lastIndexOf('.');
       
   238                 if (idx < 0) break;
       
   239                 nameChars[idx] = '$';
       
   240             }
       
   241             return null;
       
   242         }
       
   243 
       
   244     /**
       
   245      * Set the locale.
       
   246      */
       
   247     public void setLocale(String localeName) {
       
   248         // create locale specifics
       
   249         doclocale = new DocLocale(this, localeName, breakiterator);
       
   250         // update Messager if locale has changed.
       
   251         messager.setLocale(doclocale.locale);
       
   252     }
       
   253 
       
   254     /** Check whether this member should be documented. */
       
   255     public boolean shouldDocument(VarSymbol sym) {
       
   256         long mod = sym.flags();
       
   257 
       
   258         if ((mod & Flags.SYNTHETIC) != 0) {
       
   259             return false;
       
   260         }
       
   261 
       
   262         return showAccess.checkModifier(translateModifiers(mod));
       
   263     }
       
   264 
       
   265     /** Check whether this member should be documented. */
       
   266     public boolean shouldDocument(MethodSymbol sym) {
       
   267         long mod = sym.flags();
       
   268 
       
   269         if ((mod & Flags.SYNTHETIC) != 0) {
       
   270             return false;
       
   271         }
       
   272 
       
   273         return showAccess.checkModifier(translateModifiers(mod));
       
   274     }
       
   275 
       
   276     /** check whether this class should be documented. */
       
   277     public boolean shouldDocument(ClassSymbol sym) {
       
   278         return
       
   279             (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics
       
   280             (docClasses || getClassDoc(sym).tree != null) &&
       
   281             isVisible(sym);
       
   282     }
       
   283 
       
   284     //### Comment below is inaccurate wrt modifier filter testing
       
   285     /**
       
   286      * Check the visibility if this is an nested class.
       
   287      * if this is not a nested class, return true.
       
   288      * if this is an static visible nested class,
       
   289      *    return true.
       
   290      * if this is an visible nested class
       
   291      *    if the outer class is visible return true.
       
   292      *    else return false.
       
   293      * IMPORTANT: This also allows, static nested classes
       
   294      * to be defined inside an nested class, which is not
       
   295      * allowed by the compiler. So such an test case will
       
   296      * not reach upto this method itself, but if compiler
       
   297      * allows it, then that will go through.
       
   298      */
       
   299     protected boolean isVisible(ClassSymbol sym) {
       
   300         long mod = sym.flags_field;
       
   301         if (!showAccess.checkModifier(translateModifiers(mod))) {
       
   302             return false;
       
   303         }
       
   304         ClassSymbol encl = sym.owner.enclClass();
       
   305         return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl));
       
   306     }
       
   307 
       
   308     //---------------- print forwarders ----------------//
       
   309 
       
   310     /**
       
   311      * Print error message, increment error count.
       
   312      *
       
   313      * @param msg message to print.
       
   314      */
       
   315     public void printError(String msg) {
       
   316         if (silent)
       
   317             return;
       
   318         messager.printError(msg);
       
   319     }
       
   320 
       
   321     /**
       
   322      * Print error message, increment error count.
       
   323      *
       
   324      * @param key selects message from resource
       
   325      */
       
   326     public void error(DocImpl doc, String key) {
       
   327         if (silent)
       
   328             return;
       
   329         messager.error(doc==null ? null : doc.position(), key);
       
   330     }
       
   331 
       
   332     /**
       
   333      * Print error message, increment error count.
       
   334      *
       
   335      * @param key selects message from resource
       
   336      */
       
   337     public void error(SourcePosition pos, String key) {
       
   338         if (silent)
       
   339             return;
       
   340         messager.error(pos, key);
       
   341     }
       
   342 
       
   343     /**
       
   344      * Print error message, increment error count.
       
   345      *
       
   346      * @param msg message to print.
       
   347      */
       
   348     public void printError(SourcePosition pos, String msg) {
       
   349         if (silent)
       
   350             return;
       
   351         messager.printError(pos, msg);
       
   352     }
       
   353 
       
   354     /**
       
   355      * Print error message, increment error count.
       
   356      *
       
   357      * @param key selects message from resource
       
   358      * @param a1 first argument
       
   359      */
       
   360     public void error(DocImpl doc, String key, String a1) {
       
   361         if (silent)
       
   362             return;
       
   363         messager.error(doc==null ? null : doc.position(), key, a1);
       
   364     }
       
   365 
       
   366     /**
       
   367      * Print error message, increment error count.
       
   368      *
       
   369      * @param key selects message from resource
       
   370      * @param a1 first argument
       
   371      * @param a2 second argument
       
   372      */
       
   373     public void error(DocImpl doc, String key, String a1, String a2) {
       
   374         if (silent)
       
   375             return;
       
   376         messager.error(doc==null ? null : doc.position(), key, a1, a2);
       
   377     }
       
   378 
       
   379     /**
       
   380      * Print error message, increment error count.
       
   381      *
       
   382      * @param key selects message from resource
       
   383      * @param a1 first argument
       
   384      * @param a2 second argument
       
   385      * @param a3 third argument
       
   386      */
       
   387     public void error(DocImpl doc, String key, String a1, String a2, String a3) {
       
   388         if (silent)
       
   389             return;
       
   390         messager.error(doc==null ? null : doc.position(), key, a1, a2, a3);
       
   391     }
       
   392 
       
   393     /**
       
   394      * Print warning message, increment warning count.
       
   395      *
       
   396      * @param msg message to print.
       
   397      */
       
   398     public void printWarning(String msg) {
       
   399         if (silent)
       
   400             return;
       
   401         messager.printWarning(msg);
       
   402     }
       
   403 
       
   404     /**
       
   405      * Print warning message, increment warning count.
       
   406      *
       
   407      * @param key selects message from resource
       
   408      */
       
   409     public void warning(DocImpl doc, String key) {
       
   410         if (silent)
       
   411             return;
       
   412         messager.warning(doc==null ? null : doc.position(), key);
       
   413     }
       
   414 
       
   415     /**
       
   416      * Print warning message, increment warning count.
       
   417      *
       
   418      * @param msg message to print.
       
   419      */
       
   420     public void printWarning(SourcePosition pos, String msg) {
       
   421         if (silent)
       
   422             return;
       
   423         messager.printWarning(pos, msg);
       
   424     }
       
   425 
       
   426     /**
       
   427      * Print warning message, increment warning count.
       
   428      *
       
   429      * @param key selects message from resource
       
   430      * @param a1 first argument
       
   431      */
       
   432     public void warning(DocImpl doc, String key, String a1) {
       
   433         if (silent)
       
   434             return;
       
   435         // suppress messages that have (probably) been covered by doclint
       
   436         if (doclint != null && doc != null && key.startsWith("tag"))
       
   437             return;
       
   438         messager.warning(doc==null ? null : doc.position(), key, a1);
       
   439     }
       
   440 
       
   441     /**
       
   442      * Print warning message, increment warning count.
       
   443      *
       
   444      * @param key selects message from resource
       
   445      * @param a1 first argument
       
   446      * @param a2 second argument
       
   447      */
       
   448     public void warning(DocImpl doc, String key, String a1, String a2) {
       
   449         if (silent)
       
   450             return;
       
   451         messager.warning(doc==null ? null : doc.position(), key, a1, a2);
       
   452     }
       
   453 
       
   454     /**
       
   455      * Print warning message, increment warning count.
       
   456      *
       
   457      * @param key selects message from resource
       
   458      * @param a1 first argument
       
   459      * @param a2 second argument
       
   460      * @param a3 third argument
       
   461      */
       
   462     public void warning(DocImpl doc, String key, String a1, String a2, String a3) {
       
   463         if (silent)
       
   464             return;
       
   465         messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3);
       
   466     }
       
   467 
       
   468     /**
       
   469      * Print warning message, increment warning count.
       
   470      *
       
   471      * @param key selects message from resource
       
   472      * @param a1 first argument
       
   473      * @param a2 second argument
       
   474      * @param a3 third argument
       
   475      */
       
   476     public void warning(DocImpl doc, String key, String a1, String a2, String a3,
       
   477                         String a4) {
       
   478         if (silent)
       
   479             return;
       
   480         messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4);
       
   481     }
       
   482 
       
   483     /**
       
   484      * Print a message.
       
   485      *
       
   486      * @param msg message to print.
       
   487      */
       
   488     public void printNotice(String msg) {
       
   489         if (silent || quiet)
       
   490             return;
       
   491         messager.printNotice(msg);
       
   492     }
       
   493 
       
   494 
       
   495     /**
       
   496      * Print a message.
       
   497      *
       
   498      * @param key selects message from resource
       
   499      */
       
   500     public void notice(String key) {
       
   501         if (silent || quiet)
       
   502             return;
       
   503         messager.notice(key);
       
   504     }
       
   505 
       
   506     /**
       
   507      * Print a message.
       
   508      *
       
   509      * @param msg message to print.
       
   510      */
       
   511     public void printNotice(SourcePosition pos, String msg) {
       
   512         if (silent || quiet)
       
   513             return;
       
   514         messager.printNotice(pos, msg);
       
   515     }
       
   516 
       
   517     /**
       
   518      * Print a message.
       
   519      *
       
   520      * @param key selects message from resource
       
   521      * @param a1 first argument
       
   522      */
       
   523     public void notice(String key, String a1) {
       
   524         if (silent || quiet)
       
   525             return;
       
   526         messager.notice(key, a1);
       
   527     }
       
   528 
       
   529     /**
       
   530      * Print a message.
       
   531      *
       
   532      * @param key selects message from resource
       
   533      * @param a1 first argument
       
   534      * @param a2 second argument
       
   535      */
       
   536     public void notice(String key, String a1, String a2) {
       
   537         if (silent || quiet)
       
   538             return;
       
   539         messager.notice(key, a1, a2);
       
   540     }
       
   541 
       
   542     /**
       
   543      * Print a message.
       
   544      *
       
   545      * @param key selects message from resource
       
   546      * @param a1 first argument
       
   547      * @param a2 second argument
       
   548      * @param a3 third argument
       
   549      */
       
   550     public void notice(String key, String a1, String a2, String a3) {
       
   551         if (silent || quiet)
       
   552             return;
       
   553         messager.notice(key, a1, a2, a3);
       
   554     }
       
   555 
       
   556     /**
       
   557      * Exit, reporting errors and warnings.
       
   558      */
       
   559     public void exit() {
       
   560         // Messager should be replaced by a more general
       
   561         // compilation environment.  This can probably
       
   562         // subsume DocEnv as well.
       
   563         messager.exit();
       
   564     }
       
   565 
       
   566     protected Map<PackageSymbol, PackageDocImpl> packageMap = new HashMap<>();
       
   567     /**
       
   568      * Return the PackageDoc of this package symbol.
       
   569      */
       
   570     public PackageDocImpl getPackageDoc(PackageSymbol pack) {
       
   571         PackageDocImpl result = packageMap.get(pack);
       
   572         if (result != null) return result;
       
   573         result = new PackageDocImpl(this, pack);
       
   574         packageMap.put(pack, result);
       
   575         return result;
       
   576     }
       
   577 
       
   578     /**
       
   579      * Create the PackageDoc (or a subtype) for a package symbol.
       
   580      */
       
   581     void makePackageDoc(PackageSymbol pack, TreePath treePath) {
       
   582         PackageDocImpl result = packageMap.get(pack);
       
   583         if (result != null) {
       
   584             if (treePath != null) result.setTreePath(treePath);
       
   585         } else {
       
   586             result = new PackageDocImpl(this, pack, treePath);
       
   587             packageMap.put(pack, result);
       
   588         }
       
   589     }
       
   590 
       
   591 
       
   592     protected Map<ClassSymbol, ClassDocImpl> classMap = new HashMap<>();
       
   593     /**
       
   594      * Return the ClassDoc (or a subtype) of this class symbol.
       
   595      */
       
   596     public ClassDocImpl getClassDoc(ClassSymbol clazz) {
       
   597         ClassDocImpl result = classMap.get(clazz);
       
   598         if (result != null) return result;
       
   599         if (isAnnotationType(clazz)) {
       
   600             result = new AnnotationTypeDocImpl(this, clazz);
       
   601         } else {
       
   602             result = new ClassDocImpl(this, clazz);
       
   603         }
       
   604         classMap.put(clazz, result);
       
   605         return result;
       
   606     }
       
   607 
       
   608     /**
       
   609      * Create the ClassDoc (or a subtype) for a class symbol.
       
   610      */
       
   611     protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) {
       
   612         ClassDocImpl result = classMap.get(clazz);
       
   613         if (result != null) {
       
   614             if (treePath != null) result.setTreePath(treePath);
       
   615             return;
       
   616         }
       
   617         if (isAnnotationType((JCClassDecl) treePath.getLeaf())) {   // flags of clazz may not yet be set
       
   618             result = new AnnotationTypeDocImpl(this, clazz, treePath);
       
   619         } else {
       
   620             result = new ClassDocImpl(this, clazz, treePath);
       
   621         }
       
   622         classMap.put(clazz, result);
       
   623     }
       
   624 
       
   625     protected static boolean isAnnotationType(ClassSymbol clazz) {
       
   626         return ClassDocImpl.isAnnotationType(clazz);
       
   627     }
       
   628 
       
   629     protected static boolean isAnnotationType(JCClassDecl tree) {
       
   630         return (tree.mods.flags & Flags.ANNOTATION) != 0;
       
   631     }
       
   632 
       
   633     protected Map<VarSymbol, FieldDocImpl> fieldMap = new HashMap<>();
       
   634     /**
       
   635      * Return the FieldDoc of this var symbol.
       
   636      */
       
   637     public FieldDocImpl getFieldDoc(VarSymbol var) {
       
   638         FieldDocImpl result = fieldMap.get(var);
       
   639         if (result != null) return result;
       
   640         result = new FieldDocImpl(this, var);
       
   641         fieldMap.put(var, result);
       
   642         return result;
       
   643     }
       
   644     /**
       
   645      * Create a FieldDoc for a var symbol.
       
   646      */
       
   647     protected void makeFieldDoc(VarSymbol var, TreePath treePath) {
       
   648         FieldDocImpl result = fieldMap.get(var);
       
   649         if (result != null) {
       
   650             if (treePath != null) result.setTreePath(treePath);
       
   651         } else {
       
   652             result = new FieldDocImpl(this, var, treePath);
       
   653             fieldMap.put(var, result);
       
   654         }
       
   655     }
       
   656 
       
   657     protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap = new HashMap<>();
       
   658     /**
       
   659      * Create a MethodDoc for this MethodSymbol.
       
   660      * Should be called only on symbols representing methods.
       
   661      */
       
   662     protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) {
       
   663         MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
       
   664         if (result != null) {
       
   665             if (treePath != null) result.setTreePath(treePath);
       
   666         } else {
       
   667             result = new MethodDocImpl(this, meth, treePath);
       
   668             methodMap.put(meth, result);
       
   669         }
       
   670     }
       
   671 
       
   672     /**
       
   673      * Return the MethodDoc for a MethodSymbol.
       
   674      * Should be called only on symbols representing methods.
       
   675      */
       
   676     public MethodDocImpl getMethodDoc(MethodSymbol meth) {
       
   677         assert !meth.isConstructor() : "not expecting a constructor symbol";
       
   678         MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
       
   679         if (result != null) return result;
       
   680         result = new MethodDocImpl(this, meth);
       
   681         methodMap.put(meth, result);
       
   682         return result;
       
   683     }
       
   684 
       
   685     /**
       
   686      * Create the ConstructorDoc for a MethodSymbol.
       
   687      * Should be called only on symbols representing constructors.
       
   688      */
       
   689     protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) {
       
   690         ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
       
   691         if (result != null) {
       
   692             if (treePath != null) result.setTreePath(treePath);
       
   693         } else {
       
   694             result = new ConstructorDocImpl(this, meth, treePath);
       
   695             methodMap.put(meth, result);
       
   696         }
       
   697     }
       
   698 
       
   699     /**
       
   700      * Return the ConstructorDoc for a MethodSymbol.
       
   701      * Should be called only on symbols representing constructors.
       
   702      */
       
   703     public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) {
       
   704         assert meth.isConstructor() : "expecting a constructor symbol";
       
   705         ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
       
   706         if (result != null) return result;
       
   707         result = new ConstructorDocImpl(this, meth);
       
   708         methodMap.put(meth, result);
       
   709         return result;
       
   710     }
       
   711 
       
   712     /**
       
   713      * Create the AnnotationTypeElementDoc for a MethodSymbol.
       
   714      * Should be called only on symbols representing annotation type elements.
       
   715      */
       
   716     protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) {
       
   717         AnnotationTypeElementDocImpl result =
       
   718             (AnnotationTypeElementDocImpl)methodMap.get(meth);
       
   719         if (result != null) {
       
   720             if (treePath != null) result.setTreePath(treePath);
       
   721         } else {
       
   722             result =
       
   723                 new AnnotationTypeElementDocImpl(this, meth, treePath);
       
   724             methodMap.put(meth, result);
       
   725         }
       
   726     }
       
   727 
       
   728     /**
       
   729      * Return the AnnotationTypeElementDoc for a MethodSymbol.
       
   730      * Should be called only on symbols representing annotation type elements.
       
   731      */
       
   732     public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc(
       
   733             MethodSymbol meth) {
       
   734 
       
   735         AnnotationTypeElementDocImpl result =
       
   736             (AnnotationTypeElementDocImpl)methodMap.get(meth);
       
   737         if (result != null) return result;
       
   738         result = new AnnotationTypeElementDocImpl(this, meth);
       
   739         methodMap.put(meth, result);
       
   740         return result;
       
   741     }
       
   742 
       
   743 //  private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap =
       
   744 //          new HashMap<ClassType, ParameterizedTypeImpl>();
       
   745     /**
       
   746      * Return the ParameterizedType of this instantiation.
       
   747 //   * ### Could use Type.sameTypeAs() instead of equality matching in hashmap
       
   748 //   * ### to avoid some duplication.
       
   749      */
       
   750     ParameterizedTypeImpl getParameterizedType(ClassType t) {
       
   751         return new ParameterizedTypeImpl(this, t);
       
   752 //      ParameterizedTypeImpl result = parameterizedTypeMap.get(t);
       
   753 //      if (result != null) return result;
       
   754 //      result = new ParameterizedTypeImpl(this, t);
       
   755 //      parameterizedTypeMap.put(t, result);
       
   756 //      return result;
       
   757     }
       
   758 
       
   759     TreePath getTreePath(JCCompilationUnit tree) {
       
   760         TreePath p = treePaths.get(tree);
       
   761         if (p == null)
       
   762             treePaths.put(tree, p = new TreePath(tree));
       
   763         return p;
       
   764     }
       
   765 
       
   766     TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) {
       
   767         TreePath p = treePaths.get(tree);
       
   768         if (p == null)
       
   769             treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
       
   770         return p;
       
   771     }
       
   772 
       
   773     TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) {
       
   774         TreePath p = treePaths.get(tree);
       
   775         if (p == null)
       
   776             treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
       
   777         return p;
       
   778     }
       
   779 
       
   780     TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) {
       
   781         return new TreePath(getTreePath(toplevel, cdecl), tree);
       
   782     }
       
   783 
       
   784     /**
       
   785      * Set the encoding.
       
   786      */
       
   787     public void setEncoding(String encoding) {
       
   788         this.encoding = encoding;
       
   789     }
       
   790 
       
   791     /**
       
   792      * Get the encoding.
       
   793      */
       
   794     public String getEncoding() {
       
   795         return encoding;
       
   796     }
       
   797 
       
   798     /**
       
   799      * Convert modifier bits from private coding used by
       
   800      * the compiler to that of java.lang.reflect.Modifier.
       
   801      */
       
   802     static int translateModifiers(long flags) {
       
   803         int result = 0;
       
   804         if ((flags & Flags.ABSTRACT) != 0)
       
   805             result |= Modifier.ABSTRACT;
       
   806         if ((flags & Flags.FINAL) != 0)
       
   807             result |= Modifier.FINAL;
       
   808         if ((flags & Flags.INTERFACE) != 0)
       
   809             result |= Modifier.INTERFACE;
       
   810         if ((flags & Flags.NATIVE) != 0)
       
   811             result |= Modifier.NATIVE;
       
   812         if ((flags & Flags.PRIVATE) != 0)
       
   813             result |= Modifier.PRIVATE;
       
   814         if ((flags & Flags.PROTECTED) != 0)
       
   815             result |= Modifier.PROTECTED;
       
   816         if ((flags & Flags.PUBLIC) != 0)
       
   817             result |= Modifier.PUBLIC;
       
   818         if ((flags & Flags.STATIC) != 0)
       
   819             result |= Modifier.STATIC;
       
   820         if ((flags & Flags.SYNCHRONIZED) != 0)
       
   821             result |= Modifier.SYNCHRONIZED;
       
   822         if ((flags & Flags.TRANSIENT) != 0)
       
   823             result |= Modifier.TRANSIENT;
       
   824         if ((flags & Flags.VOLATILE) != 0)
       
   825             result |= Modifier.VOLATILE;
       
   826         return result;
       
   827     }
       
   828 
       
   829     void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) {
       
   830         ArrayList<String> doclintOpts = new ArrayList<>();
       
   831         boolean msgOptionSeen = false;
       
   832 
       
   833         for (String opt : opts) {
       
   834             if (opt.startsWith(DocLint.XMSGS_OPTION)) {
       
   835                 if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))
       
   836                     return;
       
   837                 msgOptionSeen = true;
       
   838             }
       
   839             doclintOpts.add(opt);
       
   840         }
       
   841 
       
   842         if (!msgOptionSeen) {
       
   843             doclintOpts.add(DocLint.XMSGS_OPTION);
       
   844         }
       
   845 
       
   846         String sep = "";
       
   847         StringBuilder customTags = new StringBuilder();
       
   848         for (String customTag : customTagNames) {
       
   849             customTags.append(sep);
       
   850             customTags.append(customTag);
       
   851             sep = DocLint.SEPARATOR;
       
   852         }
       
   853         doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString());
       
   854         doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + htmlVersion);
       
   855 
       
   856         JavacTask t = BasicJavacTask.instance(context);
       
   857         doclint = new DocLint();
       
   858         // standard doclet normally generates H1, H2
       
   859         doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
       
   860         doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
       
   861     }
       
   862 
       
   863     JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
       
   864         if (allowScriptInComments) {
       
   865             javaScriptScanner = null;
       
   866         } else {
       
   867             javaScriptScanner = new JavaScriptScanner();
       
   868         }
       
   869         return javaScriptScanner;
       
   870     }
       
   871 
       
   872     boolean showTagMessages() {
       
   873         return (doclint == null);
       
   874     }
       
   875 
       
   876     Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
       
   877 
       
   878     boolean shouldCheck(CompilationUnitTree unit) {
       
   879         return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck);
       
   880     }
       
   881 }