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 
instance(Context context)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      */
DocEnv(Context context)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 
setSilent(boolean silent)172     public void setSilent(boolean silent) {
173         this.silent = silent;
174     }
175 
176     /**
177      * Look up ClassDoc by qualified name.
178      */
lookupClass(String name)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      */
loadClass(String name)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      */
lookupPackage(String name)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          */
getClassSymbol(String name)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      */
setLocale(String localeName)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. */
shouldDocument(VarSymbol sym)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. */
shouldDocument(MethodSymbol sym)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. */
shouldDocument(ClassSymbol sym)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      */
isVisible(ClassSymbol sym)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      */
printError(String msg)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      */
error(DocImpl doc, String key)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      */
error(SourcePosition pos, String key)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      */
printError(SourcePosition pos, String msg)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      */
error(DocImpl doc, String key, String a1)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      */
error(DocImpl doc, String key, String a1, String a2)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      */
error(DocImpl doc, String key, String a1, String a2, String a3)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      */
printWarning(String msg)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      */
warning(DocImpl doc, String key)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      */
printWarning(SourcePosition pos, String msg)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      */
warning(DocImpl doc, String key, String a1)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      */
warning(DocImpl doc, String key, String a1, String a2)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      */
warning(DocImpl doc, String key, String a1, String a2, String a3)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      */
warning(DocImpl doc, String key, String a1, String a2, String a3, String a4)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      */
printNotice(String msg)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      */
notice(String key)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      */
printNotice(SourcePosition pos, String msg)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      */
notice(String key, String a1)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      */
notice(String key, String a1, String a2)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      */
notice(String key, String a1, String a2, String a3)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      */
exit()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      */
getPackageDoc(PackageSymbol pack)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      */
makePackageDoc(PackageSymbol pack, TreePath treePath)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      */
getClassDoc(ClassSymbol clazz)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      */
makeClassDoc(ClassSymbol clazz, TreePath treePath)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 
isAnnotationType(ClassSymbol clazz)625     protected static boolean isAnnotationType(ClassSymbol clazz) {
626         return ClassDocImpl.isAnnotationType(clazz);
627     }
628 
isAnnotationType(JCClassDecl tree)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      */
getFieldDoc(VarSymbol var)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      */
makeFieldDoc(VarSymbol var, TreePath treePath)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      */
makeMethodDoc(MethodSymbol meth, TreePath treePath)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      */
getMethodDoc(MethodSymbol meth)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      */
makeConstructorDoc(MethodSymbol meth, TreePath treePath)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      */
getConstructorDoc(MethodSymbol meth)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      */
makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath)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      */
getAnnotationTypeElementDoc( MethodSymbol meth)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      */
getParameterizedType(ClassType t)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 
getTreePath(JCCompilationUnit tree)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 
getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree)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 
getTreePath(JCCompilationUnit toplevel, JCClassDecl tree)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 
getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree)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      */
setEncoding(String encoding)787     public void setEncoding(String encoding) {
788         this.encoding = encoding;
789     }
790 
791     /**
792      * Get the encoding.
793      */
getEncoding()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      */
translateModifiers(long flags)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 
initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion)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 
initJavaScriptScanner(boolean allowScriptInComments)863     JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
864         if (allowScriptInComments) {
865             javaScriptScanner = null;
866         } else {
867             javaScriptScanner = new JavaScriptScanner();
868         }
869         return javaScriptScanner;
870     }
871 
showTagMessages()872     boolean showTagMessages() {
873         return (doclint == null);
874     }
875 
876     Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
877 
shouldCheck(CompilationUnitTree unit)878     boolean shouldCheck(CompilationUnitTree unit) {
879         return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck);
880     }
881 }
882