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