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