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

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

There is a newer version: 1.0
Show newest version
/*
 * Copyright (c) 2001, 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.tools.javac.code.Scope;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;

import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.comp.Enter;
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.Abort;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;


/**
 *  This class could be the main entry point for Javadoc when Javadoc is used as a
 *  component in a larger software system. It provides operations to
 *  construct a new javadoc processor, and to run it on a set of source
 *  files.
 *
 *  

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. * * @author Neal Gafter */ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { DocEnv docenv; final Messager messager; final JavadocClassFinder javadocFinder; final Enter javadocEnter; final Set uniquefiles; /** * Construct a new JavaCompiler processor, using appropriately * extended phases of the underlying compiler. */ protected JavadocTool(Context context) { super(context); messager = Messager.instance0(context); javadocFinder = JavadocClassFinder.instance(context); javadocEnter = JavadocEnter.instance(context); uniquefiles = new HashSet<>(); } /** * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler. */ @Override protected boolean keepComments() { return true; } /** * Construct a new javadoc tool. */ public static JavadocTool make0(Context context) { // force the use of Javadoc's class finder JavadocClassFinder.preRegister(context); // force the use of Javadoc's own enter phase JavadocEnter.preRegister(context); // force the use of Javadoc's own member enter phase JavadocMemberEnter.preRegister(context); // force the use of Javadoc's own todo phase JavadocTodo.preRegister(context); // force the use of Messager as a Log Messager.instance0(context); return new JavadocTool(context); } public RootDocImpl getRootDocImpl(String doclocale, String encoding, ModifierFilter filter, List args, List options, Iterable fileObjects, boolean breakiterator, List subPackages, List excludedPackages, boolean docClasses, boolean legacyDoclet, boolean quiet) throws IOException { docenv = DocEnv.instance(context); docenv.showAccess = filter; docenv.quiet = quiet; docenv.breakiterator = breakiterator; docenv.setLocale(doclocale); docenv.setEncoding(encoding); docenv.docClasses = docClasses; docenv.legacyDoclet = legacyDoclet; Object sc; if (docClasses) { sc = SymbolKind.getStaticOrElse(Completer.class, "NULL_COMPLETER", null); } else { sc = SymbolKind.getOrElse(docenv.finder.getClass().getSuperclass(), docenv.finder, "sourceCompleter", null); } if (sc != null) { SymbolKind.setOrNothing(javadocFinder, "sourceCompleter", sc); } if (docClasses) { // If -Xclasses is set, the args should be a series of class names for (String arg: args) { if (!isValidPackageName(arg)) // checks docenv.error(null, "main.illegal_class_name", arg); } if (messager.nerrors() != 0) { return null; } return new RootDocImpl(docenv, args, options); } ListBuffer classTrees = new ListBuffer<>(); Set includedPackages = new LinkedHashSet<>(); try { StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager ? (StandardJavaFileManager) docenv.fileManager : null; Set packageNames = new LinkedHashSet<>(); // Normally, the args should be a series of package names or file names. // Parse the files and collect the package names. for (String arg: args) { if (fm != null && arg.endsWith(".java") && new File(arg).exists()) { if (new File(arg).getName().equals("module-info.java")) { docenv.warning(null, "main.file_ignored", arg); } else { parse(fm.getJavaFileObjects(arg), classTrees, true); } } else if (isValidPackageName(arg)) { packageNames.add(arg); } else if (arg.endsWith(".java")) { if (fm == null) throw new IllegalArgumentException(); else docenv.error(null, "main.file_not_found", arg); } else { docenv.error(null, "main.illegal_package_name", arg); } } // Parse file objects provide via the DocumentationTool API parse(fileObjects, classTrees, true); Object m = modules(); boolean multiModuleMode = false; if (m != null) { SymbolKind.invokeOrNull(m, "initModules", classTrees.toList()); multiModuleMode = SymbolKind.getOrElse(null, m, "multiModuleMode", false); } // Build up the complete list of any packages to be documented Location location = multiModuleMode ? StandardLocation.valueOf("MODULE_SOURCE_PATH") : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; PackageTable t = new PackageTable(docenv.fileManager, location) .packages(packageNames) .subpackages(subPackages, excludedPackages); includedPackages = t.getIncludedPackages(); // Parse the files in the packages to be documented ListBuffer allTrees = new ListBuffer<>(); for (String packageName: includedPackages) { List files = t.getFiles(packageName); docenv.notice("main.Loading_source_files_for_package", packageName); if (files.isEmpty()) messager.warning(Messager.NOPOS, "main.no_source_files_for_package", packageName); allTrees.addAll(classTrees); parse(files, allTrees, false); } if (m != null) { SymbolKind.invokeOrNull(m, "newRound"); SymbolKind.invokeOrNull(m, "initModules", allTrees.toList()); } if (messager.nerrors() != 0) { return null; } // Enter symbols for all files docenv.notice("main.Building_tree"); javadocEnter.main(classTrees.toList().appendList(allTrees.toList())); } catch (Abort ex) {} if (messager.nerrors() != 0) return null; return new RootDocImpl(docenv, listClasses(classTrees.toList()), List.from(includedPackages), options); } private Object modules() { try { Class Modules = Class.forName("com.sun.tools.javac.comp.Modules"); return SymbolKind.invokeStaticOrNull(Modules, "instance", context); } catch (ClassNotFoundException ex) { return null; } } /** Is the given string a valid package name? */ boolean isValidPackageName(String s) { int index; while ((index = s.indexOf('.')) != -1) { if (!isValidClassName(s.substring(0, index))) return false; s = s.substring(index+1); } return isValidClassName(s); } private void parse(Iterable files, ListBuffer trees, boolean trace) { for (JavaFileObject fo: files) { if (uniquefiles.add(fo)) { // ignore duplicates if (trace) docenv.notice("main.Loading_source_file", fo.getName()); trees.append(parse(fo)); } } } /** Are surrogates supported? */ final static boolean surrogatesSupported = surrogatesSupported(); private static boolean surrogatesSupported() { try { boolean b = Character.isHighSurrogate('a'); return true; } catch (NoSuchMethodError ex) { return false; } } /** * Return true if given file name is a valid class name * (including "package-info"). * @param s the name of the class to check. * @return true if given class name is a valid class name * and false otherwise. */ public static boolean isValidClassName(String s) { if (s.length() < 1) return false; if (s.equals("package-info")) return true; if (surrogatesSupported) { int cp = s.codePointAt(0); if (!Character.isJavaIdentifierStart(cp)) return false; for (int j=Character.charCount(cp); j listClasses(List trees) { ListBuffer result = new ListBuffer<>(); for (JCCompilationUnit t : trees) { for (JCTree def : t.defs) { if (def.hasTag(JCTree.Tag.CLASSDEF)) result.append((JCClassDecl)def); } } return result.toList(); } /** * A table to manage included and excluded packages. */ class PackageTable { private final Map entries = new LinkedHashMap<>(); private final Set includedPackages = new LinkedHashSet<>(); private final JavaFileManager fm; private final Location location; private final Set sourceKinds = EnumSet.of(JavaFileObject.Kind.SOURCE); /** * Creates a table to manage included and excluded packages. * @param fm The file manager used to locate source files * @param locn the location used to locate source files */ PackageTable(JavaFileManager fm, Location locn) { this.fm = fm; this.location = locn; getEntry("").excluded = false; } PackageTable packages(Collection packageNames) { includedPackages.addAll(packageNames); return this; } PackageTable subpackages(Collection packageNames, Collection excludePackageNames) throws IOException { for (String p: excludePackageNames) { getEntry(p).excluded = true; } for (String packageName: packageNames) { Location packageLocn = getLocation(packageName); for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, true)) { String binaryName = fm.inferBinaryName(packageLocn, fo); String pn = getPackageName(binaryName); String simpleName = getSimpleName(binaryName); Entry e = getEntry(pn); if (!e.isExcluded() && isValidClassName(simpleName)) { includedPackages.add(pn); e.files = (e.files == null ? List.of(fo) : e.files.prepend(fo)); } } } return this; } /** * Returns the aggregate set of included packages. * @return the aggregate set of included packages */ Set getIncludedPackages() { return includedPackages; } /** * Returns the set of source files for a package. * @param packageName the specified package * @return the set of file objects for the specified package * @throws IOException if an error occurs while accessing the files */ List getFiles(String packageName) throws IOException { Entry e = getEntry(packageName); // The files may have been found as a side effect of searching for subpackages if (e.files != null) return e.files; ListBuffer lb = new ListBuffer<>(); Location packageLocn = getLocation(packageName); for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) { String binaryName = fm.inferBinaryName(packageLocn, fo); String simpleName = getSimpleName(binaryName); if (isValidClassName(simpleName)) { lb.append(fo); } } return lb.toList(); } private Location getLocation(String packageName) throws IOException { if (location.toString().equals("MODULE_SOURCE_PATH")) { // TODO: handle invalid results Name pack = names.fromString(packageName); final List all = SymbolKind.invokeOrNull(modules(), "allModules"); for (Object msym : all) { PackageSymbol p = SymbolKind.invokeOrNull(syms, "getPackage", pack); if (p != null) { Scope members = SymbolKind.invokeOrNull(p, "members"); boolean empty = SymbolKind.invokeOrNull(members, "isEmpty"); if (!empty) { final String name = SymbolKind.getOrElse(null, msym, "name", null).toString(); return SymbolKind.invokeOrNull(fm, "getLocationForModule", location, name); } } } return null; } else { return location; } } private Entry getEntry(String name) { Entry e = entries.get(name); if (e == null) entries.put(name, e = new Entry(name)); return e; } private String getPackageName(String name) { int lastDot = name.lastIndexOf("."); return (lastDot == -1 ? "" : name.substring(0, lastDot)); } private String getSimpleName(String name) { int lastDot = name.lastIndexOf("."); return (lastDot == -1 ? name : name.substring(lastDot + 1)); } class Entry { final String name; Boolean excluded; List files; Entry(String name) { this.name = name; } boolean isExcluded() { if (excluded == null) excluded = getEntry(getPackageName(name)).isExcluded(); return excluded; } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy