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