Thu, 25 Oct 2012 11:09:36 -0700
7200915: convert TypeTags from a series of small ints to an enum
Reviewed-by: jjg, mcimadamore
Contributed-by: vicente.romero@oracle.com
1 /*
2 * Copyright (c) 2000, 2012, 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.*;
30 import javax.tools.JavaFileManager;
32 import com.sun.javadoc.*;
34 import com.sun.tools.javac.code.*;
35 import com.sun.tools.javac.code.Symbol.*;
36 import com.sun.tools.javac.code.Type.ClassType;
37 import com.sun.tools.javac.comp.Check;
38 import com.sun.tools.javac.tree.JCTree.*;
39 import com.sun.tools.javac.util.Context;
40 import com.sun.tools.javac.util.Names;
41 import com.sun.tools.javac.util.Position;
43 /**
44 * Holds the environment for a run of javadoc.
45 * Holds only the information needed throughout the
46 * run and not the compiler info that could be GC'ed
47 * or ported.
48 *
49 * <p><b>This is NOT part of any supported API.
50 * If you write code that depends on this, you do so at your own risk.
51 * This code and its internal interfaces are subject to change or
52 * deletion without notice.</b>
53 *
54 * @since 1.4
55 * @author Robert Field
56 * @author Neal Gafter (rewrite)
57 * @author Scott Seligman (generics)
58 */
59 public class DocEnv {
60 protected static final Context.Key<DocEnv> docEnvKey =
61 new Context.Key<DocEnv>();
63 public static DocEnv instance(Context context) {
64 DocEnv instance = context.get(docEnvKey);
65 if (instance == null)
66 instance = new DocEnv(context);
67 return instance;
68 }
70 private Messager messager;
72 DocLocale doclocale;
74 /** Predefined symbols known to the compiler. */
75 Symtab syms;
77 /** Referenced directly in RootDocImpl. */
78 JavadocClassReader reader;
80 /** Javadoc's own version of the compiler's enter phase. */
81 JavadocEnter enter;
83 /** The name table. */
84 Names names;
86 /** The encoding name. */
87 private String encoding;
89 final Symbol externalizableSym;
91 /** Access filter (public, protected, ...). */
92 protected ModifierFilter showAccess;
94 /** True if we are using a sentence BreakIterator. */
95 boolean breakiterator;
97 /**
98 * True if we do not want to print any notifications at all.
99 */
100 boolean quiet = false;
102 Check chk;
103 Types types;
104 JavaFileManager fileManager;
106 /** Allow documenting from class files? */
107 boolean docClasses = false;
109 /** Does the doclet only expect pre-1.5 doclet API? */
110 protected boolean legacyDoclet = true;
112 /**
113 * Set this to true if you would like to not emit any errors, warnings and
114 * notices.
115 */
116 private boolean silent = false;
118 /**
119 * Constructor
120 *
121 * @param context Context for this javadoc instance.
122 */
123 protected DocEnv(Context context) {
124 context.put(docEnvKey, this);
126 messager = Messager.instance0(context);
127 syms = Symtab.instance(context);
128 reader = JavadocClassReader.instance0(context);
129 enter = JavadocEnter.instance0(context);
130 names = Names.instance(context);
131 externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable"));
132 chk = Check.instance(context);
133 types = Types.instance(context);
134 fileManager = context.get(JavaFileManager.class);
136 // Default. Should normally be reset with setLocale.
137 this.doclocale = new DocLocale(this, "", breakiterator);
138 }
140 public void setSilent(boolean silent) {
141 this.silent = silent;
142 }
144 /**
145 * Look up ClassDoc by qualified name.
146 */
147 public ClassDocImpl lookupClass(String name) {
148 ClassSymbol c = getClassSymbol(name);
149 if (c != null) {
150 return getClassDoc(c);
151 } else {
152 return null;
153 }
154 }
156 /**
157 * Load ClassDoc by qualified name.
158 */
159 public ClassDocImpl loadClass(String name) {
160 try {
161 ClassSymbol c = reader.loadClass(names.fromString(name));
162 return getClassDoc(c);
163 } catch (CompletionFailure ex) {
164 chk.completionError(null, ex);
165 return null;
166 }
167 }
169 /**
170 * Look up PackageDoc by qualified name.
171 */
172 public PackageDocImpl lookupPackage(String name) {
173 //### Jing alleges that class check is needed
174 //### to avoid a compiler bug. Most likely
175 //### instead a dummy created for error recovery.
176 //### Should investigate this.
177 PackageSymbol p = syms.packages.get(names.fromString(name));
178 ClassSymbol c = getClassSymbol(name);
179 if (p != null && c == null) {
180 return getPackageDoc(p);
181 } else {
182 return null;
183 }
184 }
185 // where
186 /** Retrieve class symbol by fully-qualified name.
187 */
188 ClassSymbol getClassSymbol(String name) {
189 // Name may contain nested class qualification.
190 // Generate candidate flatnames with successively shorter
191 // package qualifiers and longer nested class qualifiers.
192 int nameLen = name.length();
193 char[] nameChars = name.toCharArray();
194 int idx = name.length();
195 for (;;) {
196 ClassSymbol s = syms.classes.get(names.fromChars(nameChars, 0, nameLen));
197 if (s != null)
198 return s; // found it!
199 idx = name.substring(0, idx).lastIndexOf('.');
200 if (idx < 0) break;
201 nameChars[idx] = '$';
202 }
203 return null;
204 }
206 /**
207 * Set the locale.
208 */
209 public void setLocale(String localeName) {
210 // create locale specifics
211 doclocale = new DocLocale(this, localeName, breakiterator);
212 // reset Messager if locale has changed.
213 messager.reset();
214 }
216 /** Check whether this member should be documented. */
217 public boolean shouldDocument(VarSymbol sym) {
218 long mod = sym.flags();
220 if ((mod & Flags.SYNTHETIC) != 0) {
221 return false;
222 }
224 return showAccess.checkModifier(translateModifiers(mod));
225 }
227 /** Check whether this member should be documented. */
228 public boolean shouldDocument(MethodSymbol sym) {
229 long mod = sym.flags();
231 if ((mod & Flags.SYNTHETIC) != 0) {
232 return false;
233 }
235 return showAccess.checkModifier(translateModifiers(mod));
236 }
238 /** check whether this class should be documented. */
239 public boolean shouldDocument(ClassSymbol sym) {
240 return
241 (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics
242 (docClasses || getClassDoc(sym).tree != null) &&
243 isVisible(sym);
244 }
246 //### Comment below is inaccurate wrt modifier filter testing
247 /**
248 * Check the visibility if this is an nested class.
249 * if this is not a nested class, return true.
250 * if this is an static visible nested class,
251 * return true.
252 * if this is an visible nested class
253 * if the outer class is visible return true.
254 * else return false.
255 * IMPORTANT: This also allows, static nested classes
256 * to be defined inside an nested class, which is not
257 * allowed by the compiler. So such an test case will
258 * not reach upto this method itself, but if compiler
259 * allows it, then that will go through.
260 */
261 protected boolean isVisible(ClassSymbol sym) {
262 long mod = sym.flags_field;
263 if (!showAccess.checkModifier(translateModifiers(mod))) {
264 return false;
265 }
266 ClassSymbol encl = sym.owner.enclClass();
267 return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl));
268 }
270 //---------------- print forwarders ----------------//
272 /**
273 * Print error message, increment error count.
274 *
275 * @param msg message to print.
276 */
277 public void printError(String msg) {
278 if (silent)
279 return;
280 messager.printError(msg);
281 }
283 /**
284 * Print error message, increment error count.
285 *
286 * @param key selects message from resource
287 */
288 public void error(DocImpl doc, String key) {
289 if (silent)
290 return;
291 messager.error(doc==null ? null : doc.position(), key);
292 }
294 /**
295 * Print error message, increment error count.
296 *
297 * @param key selects message from resource
298 */
299 public void error(SourcePosition pos, String key) {
300 if (silent)
301 return;
302 messager.error(pos, key);
303 }
305 /**
306 * Print error message, increment error count.
307 *
308 * @param msg message to print.
309 */
310 public void printError(SourcePosition pos, String msg) {
311 if (silent)
312 return;
313 messager.printError(pos, msg);
314 }
316 /**
317 * Print error message, increment error count.
318 *
319 * @param key selects message from resource
320 * @param a1 first argument
321 */
322 public void error(DocImpl doc, String key, String a1) {
323 if (silent)
324 return;
325 messager.error(doc==null ? null : doc.position(), key, a1);
326 }
328 /**
329 * Print error message, increment error count.
330 *
331 * @param key selects message from resource
332 * @param a1 first argument
333 * @param a2 second argument
334 */
335 public void error(DocImpl doc, String key, String a1, String a2) {
336 if (silent)
337 return;
338 messager.error(doc==null ? null : doc.position(), key, a1, a2);
339 }
341 /**
342 * Print error message, increment error count.
343 *
344 * @param key selects message from resource
345 * @param a1 first argument
346 * @param a2 second argument
347 * @param a3 third argument
348 */
349 public void error(DocImpl doc, String key, String a1, String a2, String a3) {
350 if (silent)
351 return;
352 messager.error(doc==null ? null : doc.position(), key, a1, a2, a3);
353 }
355 /**
356 * Print warning message, increment warning count.
357 *
358 * @param msg message to print.
359 */
360 public void printWarning(String msg) {
361 if (silent)
362 return;
363 messager.printWarning(msg);
364 }
366 /**
367 * Print warning message, increment warning count.
368 *
369 * @param key selects message from resource
370 */
371 public void warning(DocImpl doc, String key) {
372 if (silent)
373 return;
374 messager.warning(doc==null ? null : doc.position(), key);
375 }
377 /**
378 * Print warning message, increment warning count.
379 *
380 * @param msg message to print.
381 */
382 public void printWarning(SourcePosition pos, String msg) {
383 if (silent)
384 return;
385 messager.printWarning(pos, msg);
386 }
388 /**
389 * Print warning message, increment warning count.
390 *
391 * @param key selects message from resource
392 * @param a1 first argument
393 */
394 public void warning(DocImpl doc, String key, String a1) {
395 if (silent)
396 return;
397 messager.warning(doc==null ? null : doc.position(), key, a1);
398 }
400 /**
401 * Print warning message, increment warning count.
402 *
403 * @param key selects message from resource
404 * @param a1 first argument
405 * @param a2 second argument
406 */
407 public void warning(DocImpl doc, String key, String a1, String a2) {
408 if (silent)
409 return;
410 messager.warning(doc==null ? null : doc.position(), key, a1, a2);
411 }
413 /**
414 * Print warning message, increment warning count.
415 *
416 * @param key selects message from resource
417 * @param a1 first argument
418 * @param a2 second argument
419 * @param a3 third argument
420 */
421 public void warning(DocImpl doc, String key, String a1, String a2, String a3) {
422 if (silent)
423 return;
424 messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3);
425 }
427 /**
428 * Print warning message, increment warning count.
429 *
430 * @param key selects message from resource
431 * @param a1 first argument
432 * @param a2 second argument
433 * @param a3 third argument
434 */
435 public void warning(DocImpl doc, String key, String a1, String a2, String a3,
436 String a4) {
437 if (silent)
438 return;
439 messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4);
440 }
442 /**
443 * Print a message.
444 *
445 * @param msg message to print.
446 */
447 public void printNotice(String msg) {
448 if (silent || quiet)
449 return;
450 messager.printNotice(msg);
451 }
454 /**
455 * Print a message.
456 *
457 * @param key selects message from resource
458 */
459 public void notice(String key) {
460 if (silent || quiet)
461 return;
462 messager.notice(key);
463 }
465 /**
466 * Print a message.
467 *
468 * @param msg message to print.
469 */
470 public void printNotice(SourcePosition pos, String msg) {
471 if (silent || quiet)
472 return;
473 messager.printNotice(pos, msg);
474 }
476 /**
477 * Print a message.
478 *
479 * @param key selects message from resource
480 * @param a1 first argument
481 */
482 public void notice(String key, String a1) {
483 if (silent || quiet)
484 return;
485 messager.notice(key, a1);
486 }
488 /**
489 * Print a message.
490 *
491 * @param key selects message from resource
492 * @param a1 first argument
493 * @param a2 second argument
494 */
495 public void notice(String key, String a1, String a2) {
496 if (silent || quiet)
497 return;
498 messager.notice(key, a1, a2);
499 }
501 /**
502 * Print a message.
503 *
504 * @param key selects message from resource
505 * @param a1 first argument
506 * @param a2 second argument
507 * @param a3 third argument
508 */
509 public void notice(String key, String a1, String a2, String a3) {
510 if (silent || quiet)
511 return;
512 messager.notice(key, a1, a2, a3);
513 }
515 /**
516 * Exit, reporting errors and warnings.
517 */
518 public void exit() {
519 // Messager should be replaced by a more general
520 // compilation environment. This can probably
521 // subsume DocEnv as well.
522 messager.exit();
523 }
525 protected Map<PackageSymbol, PackageDocImpl> packageMap =
526 new HashMap<PackageSymbol, PackageDocImpl>();
527 /**
528 * Return the PackageDoc of this package symbol.
529 */
530 public PackageDocImpl getPackageDoc(PackageSymbol pack) {
531 PackageDocImpl result = packageMap.get(pack);
532 if (result != null) return result;
533 result = new PackageDocImpl(this, pack);
534 packageMap.put(pack, result);
535 return result;
536 }
538 /**
539 * Create the PackageDoc (or a subtype) for a package symbol.
540 */
541 void makePackageDoc(PackageSymbol pack, String docComment, JCCompilationUnit tree) {
542 PackageDocImpl result = packageMap.get(pack);
543 if (result != null) {
544 if (docComment != null) result.setRawCommentText(docComment);
545 if (tree != null) result.setTree(tree);
546 } else {
547 result = new PackageDocImpl(this, pack, docComment, tree);
548 packageMap.put(pack, result);
549 }
550 }
553 protected Map<ClassSymbol, ClassDocImpl> classMap =
554 new HashMap<ClassSymbol, ClassDocImpl>();
555 /**
556 * Return the ClassDoc (or a subtype) of this class symbol.
557 */
558 public ClassDocImpl getClassDoc(ClassSymbol clazz) {
559 ClassDocImpl result = classMap.get(clazz);
560 if (result != null) return result;
561 if (isAnnotationType(clazz)) {
562 result = new AnnotationTypeDocImpl(this, clazz);
563 } else {
564 result = new ClassDocImpl(this, clazz);
565 }
566 classMap.put(clazz, result);
567 return result;
568 }
570 /**
571 * Create the ClassDoc (or a subtype) for a class symbol.
572 */
573 protected void makeClassDoc(ClassSymbol clazz, String docComment, JCClassDecl tree, Position.LineMap lineMap) {
574 ClassDocImpl result = classMap.get(clazz);
575 if (result != null) {
576 if (docComment != null) result.setRawCommentText(docComment);
577 if (tree != null) result.setTree(tree);
578 return;
579 }
580 if (isAnnotationType(tree)) { // flags of clazz may not yet be set
581 result = new AnnotationTypeDocImpl(this, clazz, docComment, tree, lineMap);
582 } else {
583 result = new ClassDocImpl(this, clazz, docComment, tree, lineMap);
584 }
585 classMap.put(clazz, result);
586 }
588 protected static boolean isAnnotationType(ClassSymbol clazz) {
589 return ClassDocImpl.isAnnotationType(clazz);
590 }
592 protected static boolean isAnnotationType(JCClassDecl tree) {
593 return (tree.mods.flags & Flags.ANNOTATION) != 0;
594 }
596 protected Map<VarSymbol, FieldDocImpl> fieldMap =
597 new HashMap<VarSymbol, FieldDocImpl>();
598 /**
599 * Return the FieldDoc of this var symbol.
600 */
601 public FieldDocImpl getFieldDoc(VarSymbol var) {
602 FieldDocImpl result = fieldMap.get(var);
603 if (result != null) return result;
604 result = new FieldDocImpl(this, var);
605 fieldMap.put(var, result);
606 return result;
607 }
608 /**
609 * Create a FieldDoc for a var symbol.
610 */
611 protected void makeFieldDoc(VarSymbol var, String docComment, JCVariableDecl tree, Position.LineMap lineMap) {
612 FieldDocImpl result = fieldMap.get(var);
613 if (result != null) {
614 if (docComment != null) result.setRawCommentText(docComment);
615 if (tree != null) result.setTree(tree);
616 } else {
617 result = new FieldDocImpl(this, var, docComment, tree, lineMap);
618 fieldMap.put(var, result);
619 }
620 }
622 protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap =
623 new HashMap<MethodSymbol, ExecutableMemberDocImpl>();
624 /**
625 * Create a MethodDoc for this MethodSymbol.
626 * Should be called only on symbols representing methods.
627 */
628 protected void makeMethodDoc(MethodSymbol meth, String docComment,
629 JCMethodDecl tree, Position.LineMap lineMap) {
630 MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
631 if (result != null) {
632 if (docComment != null) result.setRawCommentText(docComment);
633 if (tree != null) result.setTree(tree);
634 } else {
635 result = new MethodDocImpl(this, meth, docComment, tree, lineMap);
636 methodMap.put(meth, result);
637 }
638 }
640 /**
641 * Return the MethodDoc for a MethodSymbol.
642 * Should be called only on symbols representing methods.
643 */
644 public MethodDocImpl getMethodDoc(MethodSymbol meth) {
645 assert !meth.isConstructor() : "not expecting a constructor symbol";
646 MethodDocImpl result = (MethodDocImpl)methodMap.get(meth);
647 if (result != null) return result;
648 result = new MethodDocImpl(this, meth);
649 methodMap.put(meth, result);
650 return result;
651 }
653 /**
654 * Create the ConstructorDoc for a MethodSymbol.
655 * Should be called only on symbols representing constructors.
656 */
657 protected void makeConstructorDoc(MethodSymbol meth, String docComment,
658 JCMethodDecl tree, Position.LineMap lineMap) {
659 ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
660 if (result != null) {
661 if (docComment != null) result.setRawCommentText(docComment);
662 if (tree != null) result.setTree(tree);
663 } else {
664 result = new ConstructorDocImpl(this, meth, docComment, tree, lineMap);
665 methodMap.put(meth, result);
666 }
667 }
669 /**
670 * Return the ConstructorDoc for a MethodSymbol.
671 * Should be called only on symbols representing constructors.
672 */
673 public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) {
674 assert meth.isConstructor() : "expecting a constructor symbol";
675 ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth);
676 if (result != null) return result;
677 result = new ConstructorDocImpl(this, meth);
678 methodMap.put(meth, result);
679 return result;
680 }
682 /**
683 * Create the AnnotationTypeElementDoc for a MethodSymbol.
684 * Should be called only on symbols representing annotation type elements.
685 */
686 protected void makeAnnotationTypeElementDoc(MethodSymbol meth,
687 String docComment, JCMethodDecl tree, Position.LineMap lineMap) {
688 AnnotationTypeElementDocImpl result =
689 (AnnotationTypeElementDocImpl)methodMap.get(meth);
690 if (result != null) {
691 if (docComment != null) result.setRawCommentText(docComment);
692 if (tree != null) result.setTree(tree);
693 } else {
694 result =
695 new AnnotationTypeElementDocImpl(this, meth, docComment, tree, lineMap);
696 methodMap.put(meth, result);
697 }
698 }
700 /**
701 * Return the AnnotationTypeElementDoc for a MethodSymbol.
702 * Should be called only on symbols representing annotation type elements.
703 */
704 public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc(
705 MethodSymbol meth) {
707 AnnotationTypeElementDocImpl result =
708 (AnnotationTypeElementDocImpl)methodMap.get(meth);
709 if (result != null) return result;
710 result = new AnnotationTypeElementDocImpl(this, meth);
711 methodMap.put(meth, result);
712 return result;
713 }
715 // private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap =
716 // new HashMap<ClassType, ParameterizedTypeImpl>();
717 /**
718 * Return the ParameterizedType of this instantiation.
719 // * ### Could use Type.sameTypeAs() instead of equality matching in hashmap
720 // * ### to avoid some duplication.
721 */
722 ParameterizedTypeImpl getParameterizedType(ClassType t) {
723 return new ParameterizedTypeImpl(this, t);
724 // ParameterizedTypeImpl result = parameterizedTypeMap.get(t);
725 // if (result != null) return result;
726 // result = new ParameterizedTypeImpl(this, t);
727 // parameterizedTypeMap.put(t, result);
728 // return result;
729 }
731 /**
732 * Set the encoding.
733 */
734 public void setEncoding(String encoding) {
735 this.encoding = encoding;
736 }
738 /**
739 * Get the encoding.
740 */
741 public String getEncoding() {
742 return encoding;
743 }
745 /**
746 * Convert modifier bits from private coding used by
747 * the compiler to that of java.lang.reflect.Modifier.
748 */
749 static int translateModifiers(long flags) {
750 int result = 0;
751 if ((flags & Flags.ABSTRACT) != 0)
752 result |= Modifier.ABSTRACT;
753 if ((flags & Flags.FINAL) != 0)
754 result |= Modifier.FINAL;
755 if ((flags & Flags.INTERFACE) != 0)
756 result |= Modifier.INTERFACE;
757 if ((flags & Flags.NATIVE) != 0)
758 result |= Modifier.NATIVE;
759 if ((flags & Flags.PRIVATE) != 0)
760 result |= Modifier.PRIVATE;
761 if ((flags & Flags.PROTECTED) != 0)
762 result |= Modifier.PROTECTED;
763 if ((flags & Flags.PUBLIC) != 0)
764 result |= Modifier.PUBLIC;
765 if ((flags & Flags.STATIC) != 0)
766 result |= Modifier.STATIC;
767 if ((flags & Flags.SYNCHRONIZED) != 0)
768 result |= Modifier.SYNCHRONIZED;
769 if ((flags & Flags.TRANSIENT) != 0)
770 result |= Modifier.TRANSIENT;
771 if ((flags & Flags.VOLATILE) != 0)
772 result |= Modifier.VOLATILE;
773 return result;
774 }
775 }