All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.tools.oldlets.javadoc.main.DocEnv Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
/*
 * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.oldlets.javadoc.main;

import com.sun.javadoc.SourcePosition;
import java.lang.reflect.Modifier;
import java.util.*;

import javax.tools.JavaFileManager;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreePath;
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;

/**
 * Holds the environment for a run of javadoc.
 * Holds only the information needed throughout the
 * run and not the compiler info that could be GC'ed
 * or ported.
 *
 *  

This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice. * * @since 1.4 * @author Robert Field * @author Neal Gafter (rewrite) * @author Scott Seligman (generics) */ public class DocEnv { protected static final Context.Key docEnvKey = new Context.Key<>(); public static DocEnv instance(Context context) { DocEnv instance = context.get(docEnvKey); if (instance == null) instance = new DocEnv(context); return instance; } DocLocale doclocale; private final Messager messager; /** Predefined symbols known to the compiler. */ final Symtab syms; /** Referenced directly in RootDocImpl. */ public final JavadocClassFinder finder; /** Javadoc's own version of the compiler's enter phase. */ final Enter enter; /** The name table. */ private final Names names; /** The encoding name. */ private String encoding; final Symbol externalizableSym; /** Access filter (public, protected, ...). */ protected ModifierFilter showAccess; /** True if we are using a sentence BreakIterator. */ boolean breakiterator; /** * True if we do not want to print any notifications at all. */ boolean quiet = false; Check chk; Types types; JavaFileManager fileManager; Context context; DocLint doclint; JavaScriptScanner javaScriptScanner; WeakHashMap treePaths = new WeakHashMap<>(); /** Allow documenting from class files? */ boolean docClasses = false; /** Does the doclet only expect pre-1.5 doclet API? */ protected boolean legacyDoclet = true; /** * Set this to true if you would like to not emit any errors, warnings and * notices. */ private boolean silent = false; /** * The source language version. */ protected Source source; /** * Constructor * * @param context Context for this javadoc instance. */ protected DocEnv(Context context) { context.put(docEnvKey, this); this.context = context; messager = Messager.instance0(context); syms = Symtab.instance(context); finder = JavadocClassFinder.instance(context); enter = JavadocEnter.instance(context); names = Names.instance(context); externalizableSym = SymbolKind.enterClass(this, syms, names.fromString("java.io.Externalizable")); chk = Check.instance(context); types = Types.instance(context); fileManager = context.get(JavaFileManager.class); if (fileManager instanceof JavacFileManager) { ((JavacFileManager)fileManager).setSymbolFileEnabled(false); } // Default. Should normally be reset with setLocale. this.doclocale = new DocLocale(this, "", breakiterator); source = Source.instance(context); } public void setSilent(boolean silent) { this.silent = silent; } /** * Look up ClassDoc by qualified name. */ public ClassDocImpl lookupClass(String name) { ClassSymbol c = getClassSymbol(name); if (c != null) { return getClassDoc(c); } else { return null; } } /** * Load ClassDoc by qualified name. */ public ClassDocImpl loadClass(String name) { try { ClassSymbol c = SymbolKind.loadClass(this, syms, names.fromString(name)); return getClassDoc(c); } catch (CompletionFailure ex) { chk.completionError(null, ex); return null; } } /** * Look up PackageDoc by qualified name. */ public PackageDocImpl lookupPackage(String name) { //### Jing alleges that class check is needed //### to avoid a compiler bug. Most likely //### instead a dummy created for error recovery. //### Should investigate this. PackageSymbol p = SymbolKind.lookupPackage(syms, names.fromString(name)); ClassSymbol c = getClassSymbol(name); if (p != null && c == null) { return getPackageDoc(p); } else { return null; } } // where /** Retrieve class symbol by fully-qualified name. */ ClassSymbol getClassSymbol(String name) { // Name may contain nested class qualification. // Generate candidate flatnames with successively shorter // package qualifiers and longer nested class qualifiers. int nameLen = name.length(); char[] nameChars = name.toCharArray(); int idx = name.length(); for (;;) { final Name n = names.fromChars(nameChars, 0, nameLen); ClassSymbol s = SymbolKind.getClass(syms, n); if (s != null) return s; // found it! idx = name.substring(0, idx).lastIndexOf('.'); if (idx < 0) break; nameChars[idx] = '$'; } return null; } /** * Set the locale. */ public void setLocale(String localeName) { // create locale specifics doclocale = new DocLocale(this, localeName, breakiterator); // update Messager if locale has changed. messager.setLocale(doclocale.locale); } /** Check whether this member should be documented. */ public boolean shouldDocument(VarSymbol sym) { long mod = sym.flags(); if ((mod & Flags.SYNTHETIC) != 0) { return false; } return showAccess.checkModifier(translateModifiers(mod)); } /** Check whether this member should be documented. */ public boolean shouldDocument(MethodSymbol sym) { long mod = sym.flags(); if ((mod & Flags.SYNTHETIC) != 0) { return false; } return showAccess.checkModifier(translateModifiers(mod)); } /** check whether this class should be documented. */ public boolean shouldDocument(ClassSymbol sym) { return (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics (docClasses || getClassDoc(sym).tree != null) && isVisible(sym); } //### Comment below is inaccurate wrt modifier filter testing /** * Check the visibility if this is an nested class. * if this is not a nested class, return true. * if this is an static visible nested class, * return true. * if this is an visible nested class * if the outer class is visible return true. * else return false. * IMPORTANT: This also allows, static nested classes * to be defined inside an nested class, which is not * allowed by the compiler. So such an test case will * not reach upto this method itself, but if compiler * allows it, then that will go through. */ protected boolean isVisible(ClassSymbol sym) { long mod = sym.flags_field; if (!showAccess.checkModifier(translateModifiers(mod))) { return false; } ClassSymbol encl = sym.owner.enclClass(); return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl)); } //---------------- print forwarders ----------------// /** * Print error message, increment error count. * * @param msg message to print. */ public void printError(String msg) { if (silent) return; messager.printError(msg); } /** * Print error message, increment error count. * * @param key selects message from resource */ public void error(DocImpl doc, String key) { if (silent) return; messager.error(doc==null ? null : doc.position(), key); } /** * Print error message, increment error count. * * @param key selects message from resource */ public void error(SourcePosition pos, String key) { if (silent) return; messager.error(pos, key); } /** * Print error message, increment error count. * * @param msg message to print. */ public void printError(SourcePosition pos, String msg) { if (silent) return; messager.printError(pos, msg); } /** * Print error message, increment error count. * * @param key selects message from resource * @param a1 first argument */ public void error(DocImpl doc, String key, String a1) { if (silent) return; messager.error(doc==null ? null : doc.position(), key, a1); } /** * Print error message, increment error count. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument */ public void error(DocImpl doc, String key, String a1, String a2) { if (silent) return; messager.error(doc==null ? null : doc.position(), key, a1, a2); } /** * Print error message, increment error count. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument * @param a3 third argument */ public void error(DocImpl doc, String key, String a1, String a2, String a3) { if (silent) return; messager.error(doc==null ? null : doc.position(), key, a1, a2, a3); } /** * Print warning message, increment warning count. * * @param msg message to print. */ public void printWarning(String msg) { if (silent) return; messager.printWarning(msg); } /** * Print warning message, increment warning count. * * @param key selects message from resource */ public void warning(DocImpl doc, String key) { if (silent) return; messager.warning(doc==null ? null : doc.position(), key); } /** * Print warning message, increment warning count. * * @param msg message to print. */ public void printWarning(SourcePosition pos, String msg) { if (silent) return; messager.printWarning(pos, msg); } /** * Print warning message, increment warning count. * * @param key selects message from resource * @param a1 first argument */ public void warning(DocImpl doc, String key, String a1) { if (silent) return; // suppress messages that have (probably) been covered by doclint if (doclint != null && doc != null && key.startsWith("tag")) return; messager.warning(doc==null ? null : doc.position(), key, a1); } /** * Print warning message, increment warning count. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument */ public void warning(DocImpl doc, String key, String a1, String a2) { if (silent) return; messager.warning(doc==null ? null : doc.position(), key, a1, a2); } /** * Print warning message, increment warning count. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument * @param a3 third argument */ public void warning(DocImpl doc, String key, String a1, String a2, String a3) { if (silent) return; messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3); } /** * Print warning message, increment warning count. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument * @param a3 third argument */ public void warning(DocImpl doc, String key, String a1, String a2, String a3, String a4) { if (silent) return; messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4); } /** * Print a message. * * @param msg message to print. */ public void printNotice(String msg) { if (silent || quiet) return; messager.printNotice(msg); } /** * Print a message. * * @param key selects message from resource */ public void notice(String key) { if (silent || quiet) return; messager.notice(key); } /** * Print a message. * * @param msg message to print. */ public void printNotice(SourcePosition pos, String msg) { if (silent || quiet) return; messager.printNotice(pos, msg); } /** * Print a message. * * @param key selects message from resource * @param a1 first argument */ public void notice(String key, String a1) { if (silent || quiet) return; messager.notice(key, a1); } /** * Print a message. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument */ public void notice(String key, String a1, String a2) { if (silent || quiet) return; messager.notice(key, a1, a2); } /** * Print a message. * * @param key selects message from resource * @param a1 first argument * @param a2 second argument * @param a3 third argument */ public void notice(String key, String a1, String a2, String a3) { if (silent || quiet) return; messager.notice(key, a1, a2, a3); } /** * Exit, reporting errors and warnings. */ public void exit() { // Messager should be replaced by a more general // compilation environment. This can probably // subsume DocEnv as well. messager.exit(); } protected Map packageMap = new HashMap<>(); /** * Return the PackageDoc of this package symbol. */ public PackageDocImpl getPackageDoc(PackageSymbol pack) { PackageDocImpl result = packageMap.get(pack); if (result != null) return result; result = new PackageDocImpl(this, pack); packageMap.put(pack, result); return result; } /** * Create the PackageDoc (or a subtype) for a package symbol. */ void makePackageDoc(PackageSymbol pack, TreePath treePath) { PackageDocImpl result = packageMap.get(pack); if (result != null) { if (treePath != null) result.setTreePath(treePath); } else { result = new PackageDocImpl(this, pack, treePath); packageMap.put(pack, result); } } protected Map classMap = new HashMap<>(); /** * Return the ClassDoc (or a subtype) of this class symbol. */ public ClassDocImpl getClassDoc(ClassSymbol clazz) { ClassDocImpl result = classMap.get(clazz); if (result != null) return result; if (isAnnotationType(clazz)) { result = new AnnotationTypeDocImpl(this, clazz); } else { result = new ClassDocImpl(this, clazz); } classMap.put(clazz, result); return result; } /** * Create the ClassDoc (or a subtype) for a class symbol. */ protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) { ClassDocImpl result = classMap.get(clazz); if (result != null) { if (treePath != null) result.setTreePath(treePath); return; } if (isAnnotationType((JCClassDecl) treePath.getLeaf())) { // flags of clazz may not yet be set result = new AnnotationTypeDocImpl(this, clazz, treePath); } else { result = new ClassDocImpl(this, clazz, treePath); } classMap.put(clazz, result); } protected static boolean isAnnotationType(ClassSymbol clazz) { return ClassDocImpl.isAnnotationType(clazz); } protected static boolean isAnnotationType(JCClassDecl tree) { return (tree.mods.flags & Flags.ANNOTATION) != 0; } protected Map fieldMap = new HashMap<>(); /** * Return the FieldDoc of this var symbol. */ public FieldDocImpl getFieldDoc(VarSymbol var) { FieldDocImpl result = fieldMap.get(var); if (result != null) return result; result = new FieldDocImpl(this, var); fieldMap.put(var, result); return result; } /** * Create a FieldDoc for a var symbol. */ protected void makeFieldDoc(VarSymbol var, TreePath treePath) { FieldDocImpl result = fieldMap.get(var); if (result != null) { if (treePath != null) result.setTreePath(treePath); } else { result = new FieldDocImpl(this, var, treePath); fieldMap.put(var, result); } } protected Map methodMap = new HashMap<>(); /** * Create a MethodDoc for this MethodSymbol. * Should be called only on symbols representing methods. */ protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) { MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); if (result != null) { if (treePath != null) result.setTreePath(treePath); } else { result = new MethodDocImpl(this, meth, treePath); methodMap.put(meth, result); } } /** * Return the MethodDoc for a MethodSymbol. * Should be called only on symbols representing methods. */ public MethodDocImpl getMethodDoc(MethodSymbol meth) { assert !meth.isConstructor() : "not expecting a constructor symbol"; MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); if (result != null) return result; result = new MethodDocImpl(this, meth); methodMap.put(meth, result); return result; } /** * Create the ConstructorDoc for a MethodSymbol. * Should be called only on symbols representing constructors. */ protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) { ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); if (result != null) { if (treePath != null) result.setTreePath(treePath); } else { result = new ConstructorDocImpl(this, meth, treePath); methodMap.put(meth, result); } } /** * Return the ConstructorDoc for a MethodSymbol. * Should be called only on symbols representing constructors. */ public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) { assert meth.isConstructor() : "expecting a constructor symbol"; ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); if (result != null) return result; result = new ConstructorDocImpl(this, meth); methodMap.put(meth, result); return result; } /** * Create the AnnotationTypeElementDoc for a MethodSymbol. * Should be called only on symbols representing annotation type elements. */ protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) { AnnotationTypeElementDocImpl result = (AnnotationTypeElementDocImpl)methodMap.get(meth); if (result != null) { if (treePath != null) result.setTreePath(treePath); } else { result = new AnnotationTypeElementDocImpl(this, meth, treePath); methodMap.put(meth, result); } } /** * Return the AnnotationTypeElementDoc for a MethodSymbol. * Should be called only on symbols representing annotation type elements. */ public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc( MethodSymbol meth) { AnnotationTypeElementDocImpl result = (AnnotationTypeElementDocImpl)methodMap.get(meth); if (result != null) return result; result = new AnnotationTypeElementDocImpl(this, meth); methodMap.put(meth, result); return result; } // private Map parameterizedTypeMap = // new HashMap(); /** * Return the ParameterizedType of this instantiation. // * ### Could use Type.sameTypeAs() instead of equality matching in hashmap // * ### to avoid some duplication. */ ParameterizedTypeImpl getParameterizedType(ClassType t) { return new ParameterizedTypeImpl(this, t); // ParameterizedTypeImpl result = parameterizedTypeMap.get(t); // if (result != null) return result; // result = new ParameterizedTypeImpl(this, t); // parameterizedTypeMap.put(t, result); // return result; } TreePath getTreePath(JCCompilationUnit tree) { TreePath p = treePaths.get(tree); if (p == null) treePaths.put(tree, p = new TreePath(tree)); return p; } TreePath getTreePathForPkg(JCCompilationUnit toplevel, JCTree tree) { TreePath p = treePaths.get(tree); if (p == null) treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); return p; } TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) { TreePath p = treePaths.get(tree); if (p == null) treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); return p; } TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) { return new TreePath(getTreePath(toplevel, cdecl), tree); } /** * Set the encoding. */ public void setEncoding(String encoding) { this.encoding = encoding; } /** * Get the encoding. */ public String getEncoding() { return encoding; } /** * Convert modifier bits from private coding used by * the compiler to that of java.lang.reflect.Modifier. */ static int translateModifiers(long flags) { int result = 0; if ((flags & Flags.ABSTRACT) != 0) result |= Modifier.ABSTRACT; if ((flags & Flags.FINAL) != 0) result |= Modifier.FINAL; if ((flags & Flags.INTERFACE) != 0) result |= Modifier.INTERFACE; if ((flags & Flags.NATIVE) != 0) result |= Modifier.NATIVE; if ((flags & Flags.PRIVATE) != 0) result |= Modifier.PRIVATE; if ((flags & Flags.PROTECTED) != 0) result |= Modifier.PROTECTED; if ((flags & Flags.PUBLIC) != 0) result |= Modifier.PUBLIC; if ((flags & Flags.STATIC) != 0) result |= Modifier.STATIC; if ((flags & Flags.SYNCHRONIZED) != 0) result |= Modifier.SYNCHRONIZED; if ((flags & Flags.TRANSIENT) != 0) result |= Modifier.TRANSIENT; if ((flags & Flags.VOLATILE) != 0) result |= Modifier.VOLATILE; return result; } void initDoclint(Collection opts, Collection customTagNames, String htmlVersion) { ArrayList doclintOpts = new ArrayList<>(); boolean msgOptionSeen = false; for (String opt : opts) { if (opt.startsWith(DocLint.XMSGS_OPTION)) { if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) return; msgOptionSeen = true; } doclintOpts.add(opt); } if (!msgOptionSeen) { doclintOpts.add(DocLint.XMSGS_OPTION); } String sep = ""; StringBuilder customTags = new StringBuilder(); for (String customTag : customTagNames) { customTags.append(sep); customTags.append(customTag); sep = ","; } doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString()); doclintOpts.add("-XhtmlVersion:" + htmlVersion); JavacTask t = BasicJavacTask.instance(context); doclint = new DocLint(); doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false); } JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) { if (allowScriptInComments) { javaScriptScanner = null; } else { javaScriptScanner = new JavaScriptScanner(); } return javaScriptScanner; } boolean showTagMessages() { return (doclint == null); } Map shouldCheck = new HashMap<>(); boolean shouldCheck(CompilationUnitTree unit) { return shouldCheck.computeIfAbsent(unit, (__) -> { Boolean op; try { op = (Boolean) DocLint.class.getMethod("shouldCheck").invoke(doclint); } catch (ReflectiveOperationException ex) { op = true; } return op; }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy