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