src/share/classes/com/sun/tools/javadoc/JavadocTool.java

Thu, 04 Aug 2016 23:36:47 -0700

author
asaha
date
Thu, 04 Aug 2016 23:36:47 -0700
changeset 3270
8a30511b2ea4
parent 2367
1737ad9ac984
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8162511: 8u111 L10n resource file updates
Summary: 8u111 L10n resource file updates
Reviewed-by: coffeys
Contributed-by: li.jiang@oracle.com

     1 /*
     2  * Copyright (c) 2001, 2014, 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.io.File;
    29 import java.io.IOException;
    30 import java.util.Collection;
    31 import java.util.EnumSet;
    32 import java.util.HashMap;
    33 import java.util.HashSet;
    34 import java.util.Map;
    35 import java.util.Set;
    36 import javax.tools.JavaFileManager.Location;
    37 import javax.tools.JavaFileObject;
    38 import javax.tools.StandardJavaFileManager;
    39 import javax.tools.StandardLocation;
    41 import com.sun.tools.javac.code.Symbol.CompletionFailure;
    42 import com.sun.tools.javac.tree.JCTree;
    43 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
    44 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
    45 import com.sun.tools.javac.util.Abort;
    46 import com.sun.tools.javac.util.Context;
    47 import com.sun.tools.javac.util.List;
    48 import com.sun.tools.javac.util.ListBuffer;
    49 import com.sun.tools.javac.util.Position;
    52 /**
    53  *  This class could be the main entry point for Javadoc when Javadoc is used as a
    54  *  component in a larger software system. It provides operations to
    55  *  construct a new javadoc processor, and to run it on a set of source
    56  *  files.
    57  *
    58  *  <p><b>This is NOT part of any supported API.
    59  *  If you write code that depends on this, you do so at your own risk.
    60  *  This code and its internal interfaces are subject to change or
    61  *  deletion without notice.</b>
    62  *
    63  *  @author Neal Gafter
    64  */
    65 public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
    66     DocEnv docenv;
    68     final Messager messager;
    69     final JavadocClassReader javadocReader;
    70     final JavadocEnter javadocEnter;
    71     final Set<JavaFileObject> uniquefiles;
    73     /**
    74      * Construct a new JavaCompiler processor, using appropriately
    75      * extended phases of the underlying compiler.
    76      */
    77     protected JavadocTool(Context context) {
    78         super(context);
    79         messager = Messager.instance0(context);
    80         javadocReader = JavadocClassReader.instance0(context);
    81         javadocEnter = JavadocEnter.instance0(context);
    82         uniquefiles = new HashSet<>();
    83     }
    85     /**
    86      * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
    87      */
    88     protected boolean keepComments() {
    89         return true;
    90     }
    92     /**
    93      *  Construct a new javadoc tool.
    94      */
    95     public static JavadocTool make0(Context context) {
    96         Messager messager = null;
    97         try {
    98             // force the use of Javadoc's class reader
    99             JavadocClassReader.preRegister(context);
   101             // force the use of Javadoc's own enter phase
   102             JavadocEnter.preRegister(context);
   104             // force the use of Javadoc's own member enter phase
   105             JavadocMemberEnter.preRegister(context);
   107             // force the use of Javadoc's own todo phase
   108             JavadocTodo.preRegister(context);
   110             // force the use of Messager as a Log
   111             messager = Messager.instance0(context);
   113             return new JavadocTool(context);
   114         } catch (CompletionFailure ex) {
   115             messager.error(Position.NOPOS, ex.getMessage());
   116             return null;
   117         }
   118     }
   120     public RootDocImpl getRootDocImpl(String doclocale,
   121                                       String encoding,
   122                                       ModifierFilter filter,
   123                                       List<String> javaNames,
   124                                       List<String[]> options,
   125                                       Iterable<? extends JavaFileObject> fileObjects,
   126                                       boolean breakiterator,
   127                                       List<String> subPackages,
   128                                       List<String> excludedPackages,
   129                                       boolean docClasses,
   130                                       boolean legacyDoclet,
   131                       boolean quiet) throws IOException {
   132         docenv = DocEnv.instance(context);
   133         docenv.showAccess = filter;
   134         docenv.quiet = quiet;
   135         docenv.breakiterator = breakiterator;
   136         docenv.setLocale(doclocale);
   137         docenv.setEncoding(encoding);
   138         docenv.docClasses = docClasses;
   139         docenv.legacyDoclet = legacyDoclet;
   140         javadocReader.sourceCompleter = docClasses ? null : thisCompleter;
   142         ListBuffer<String> names = new ListBuffer<String>();
   143         ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<JCCompilationUnit>();
   144         ListBuffer<JCCompilationUnit> packTrees = new ListBuffer<JCCompilationUnit>();
   146         try {
   147             StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager
   148                     ? (StandardJavaFileManager) docenv.fileManager : null;
   149             for (List<String> it = javaNames; it.nonEmpty(); it = it.tail) {
   150                 String name = it.head;
   151                 if (!docClasses && fm != null && name.endsWith(".java") && new File(name).exists()) {
   152                     JavaFileObject fo = fm.getJavaFileObjects(name).iterator().next();
   153                     parse(fo, classTrees, true);
   154                 } else if (isValidPackageName(name)) {
   155                     names = names.append(name);
   156                 } else if (name.endsWith(".java")) {
   157                     if (fm == null)
   158                         throw new IllegalArgumentException();
   159                     else
   160                         docenv.error(null, "main.file_not_found", name);
   161                 } else {
   162                     docenv.error(null, "main.illegal_package_name", name);
   163                 }
   164             }
   165             for (JavaFileObject fo: fileObjects) {
   166                 parse(fo, classTrees, true);
   167             }
   169             if (!docClasses) {
   170                 // Recursively search given subpackages.  If any packages
   171                 //are found, add them to the list.
   172                 Map<String,List<JavaFileObject>> packageFiles =
   173                         searchSubPackages(subPackages, names, excludedPackages);
   175                 // Parse the packages
   176                 for (List<String> packs = names.toList(); packs.nonEmpty(); packs = packs.tail) {
   177                     // Parse sources ostensibly belonging to package.
   178                     String packageName = packs.head;
   179                     parsePackageClasses(packageName, packageFiles.get(packageName), packTrees, excludedPackages);
   180                 }
   182                 if (messager.nerrors() != 0) return null;
   184                 // Enter symbols for all files
   185                 docenv.notice("main.Building_tree");
   186                 javadocEnter.main(classTrees.toList().appendList(packTrees.toList()));
   187             }
   188         } catch (Abort ex) {}
   190         if (messager.nerrors() != 0)
   191             return null;
   193         if (docClasses)
   194             return new RootDocImpl(docenv, javaNames, options);
   195         else
   196             return new RootDocImpl(docenv, listClasses(classTrees.toList()), names.toList(), options);
   197     }
   199     /** Is the given string a valid package name? */
   200     boolean isValidPackageName(String s) {
   201         int index;
   202         while ((index = s.indexOf('.')) != -1) {
   203             if (!isValidClassName(s.substring(0, index))) return false;
   204             s = s.substring(index+1);
   205         }
   206         return isValidClassName(s);
   207     }
   209     /**
   210      * search all directories in path for subdirectory name. Add all
   211      * .java files found in such a directory to args.
   212      */
   213     private void parsePackageClasses(String name,
   214             List<JavaFileObject> files,
   215             ListBuffer<JCCompilationUnit> trees,
   216             List<String> excludedPackages)
   217             throws IOException {
   218         if (excludedPackages.contains(name)) {
   219             return;
   220         }
   222         docenv.notice("main.Loading_source_files_for_package", name);
   224         if (files == null) {
   225             Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
   226                     ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
   227             ListBuffer<JavaFileObject> lb = new ListBuffer<JavaFileObject>();
   228             for (JavaFileObject fo: docenv.fileManager.list(
   229                     location, name, EnumSet.of(JavaFileObject.Kind.SOURCE), false)) {
   230                 String binaryName = docenv.fileManager.inferBinaryName(location, fo);
   231                 String simpleName = getSimpleName(binaryName);
   232                 if (isValidClassName(simpleName)) {
   233                     lb.append(fo);
   234                 }
   235             }
   236             files = lb.toList();
   237         }
   238         if (files.nonEmpty()) {
   239             for (JavaFileObject fo : files) {
   240                 parse(fo, trees, false);
   241             }
   242         } else {
   243             messager.warning(Messager.NOPOS, "main.no_source_files_for_package",
   244                              name.replace(File.separatorChar, '.'));
   245         }
   246     }
   248     private void parse(JavaFileObject fo, ListBuffer<JCCompilationUnit> trees,
   249                        boolean trace) {
   250         if (uniquefiles.add(fo)) { // ignore duplicates
   251             if (trace)
   252                 docenv.notice("main.Loading_source_file", fo.getName());
   253             trees.append(parse(fo));
   254         }
   255     }
   257     /**
   258      * Recursively search all directories in path for subdirectory name.
   259      * Add all packages found in such a directory to packages list.
   260      */
   261     private Map<String,List<JavaFileObject>> searchSubPackages(
   262             List<String> subPackages,
   263             ListBuffer<String> packages,
   264             List<String> excludedPackages)
   265             throws IOException {
   266         Map<String,List<JavaFileObject>> packageFiles =
   267                 new HashMap<String,List<JavaFileObject>>();
   269         Map<String,Boolean> includedPackages = new HashMap<String,Boolean>();
   270         includedPackages.put("", true);
   271         for (String p: excludedPackages)
   272             includedPackages.put(p, false);
   274         StandardLocation path = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
   275                 ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
   277         searchSubPackages(subPackages,
   278                 includedPackages,
   279                 packages, packageFiles,
   280                 path,
   281                 EnumSet.of(JavaFileObject.Kind.SOURCE));
   283         return packageFiles;
   284     }
   286     private void searchSubPackages(List<String> subPackages,
   287             Map<String,Boolean> includedPackages,
   288             ListBuffer<String> packages,
   289             Map<String, List<JavaFileObject>> packageFiles,
   290             StandardLocation location, Set<JavaFileObject.Kind> kinds)
   291             throws IOException {
   292         for (String subPackage: subPackages) {
   293             if (!isIncluded(subPackage, includedPackages))
   294                 continue;
   296             for (JavaFileObject fo: docenv.fileManager.list(location, subPackage, kinds, true)) {
   297                 String binaryName = docenv.fileManager.inferBinaryName(location, fo);
   298                 String packageName = getPackageName(binaryName);
   299                 String simpleName = getSimpleName(binaryName);
   300                 if (isIncluded(packageName, includedPackages) && isValidClassName(simpleName)) {
   301                     List<JavaFileObject> list = packageFiles.get(packageName);
   302                     list = (list == null ? List.of(fo) : list.prepend(fo));
   303                     packageFiles.put(packageName, list);
   304                     if (!packages.contains(packageName))
   305                         packages.add(packageName);
   306                 }
   307             }
   308         }
   309     }
   311     private String getPackageName(String name) {
   312         int lastDot = name.lastIndexOf(".");
   313         return (lastDot == -1 ? "" : name.substring(0, lastDot));
   314     }
   316     private String getSimpleName(String name) {
   317         int lastDot = name.lastIndexOf(".");
   318         return (lastDot == -1 ? name : name.substring(lastDot + 1));
   319     }
   321     private boolean isIncluded(String packageName, Map<String,Boolean> includedPackages) {
   322         Boolean b = includedPackages.get(packageName);
   323         if (b == null) {
   324             b = isIncluded(getPackageName(packageName), includedPackages);
   325             includedPackages.put(packageName, b);
   326         }
   327         return b;
   328     }
   330     /**
   331      * Recursively search all directories in path for subdirectory name.
   332      * Add all packages found in such a directory to packages list.
   333      */
   334     private void searchSubPackage(String packageName,
   335                                   ListBuffer<String> packages,
   336                                   List<String> excludedPackages,
   337                                   Collection<File> pathnames) {
   338         if (excludedPackages.contains(packageName))
   339             return;
   341         String packageFilename = packageName.replace('.', File.separatorChar);
   342         boolean addedPackage = false;
   343         for (File pathname : pathnames) {
   344             File f = new File(pathname, packageFilename);
   345             String filenames[] = f.list();
   346             // if filenames not null, then found directory
   347             if (filenames != null) {
   348                 for (String filename : filenames) {
   349                     if (!addedPackage
   350                             && (isValidJavaSourceFile(filename) ||
   351                                 isValidJavaClassFile(filename))
   352                             && !packages.contains(packageName)) {
   353                         packages.append(packageName);
   354                         addedPackage = true;
   355                     } else if (isValidClassName(filename) &&
   356                                (new File(f, filename)).isDirectory()) {
   357                         searchSubPackage(packageName + "." + filename,
   358                                          packages, excludedPackages, pathnames);
   359                     }
   360                 }
   361             }
   362         }
   363     }
   365     /**
   366      * Return true if given file name is a valid class file name.
   367      * @param file the name of the file to check.
   368      * @return true if given file name is a valid class file name
   369      * and false otherwise.
   370      */
   371     private static boolean isValidJavaClassFile(String file) {
   372         if (!file.endsWith(".class")) return false;
   373         String clazzName = file.substring(0, file.length() - ".class".length());
   374         return isValidClassName(clazzName);
   375     }
   377     /**
   378      * Return true if given file name is a valid Java source file name.
   379      * @param file the name of the file to check.
   380      * @return true if given file name is a valid Java source file name
   381      * and false otherwise.
   382      */
   383     private static boolean isValidJavaSourceFile(String file) {
   384         if (!file.endsWith(".java")) return false;
   385         String clazzName = file.substring(0, file.length() - ".java".length());
   386         return isValidClassName(clazzName);
   387     }
   389     /** Are surrogates supported?
   390      */
   391     final static boolean surrogatesSupported = surrogatesSupported();
   392     private static boolean surrogatesSupported() {
   393         try {
   394             boolean b = Character.isHighSurrogate('a');
   395             return true;
   396         } catch (NoSuchMethodError ex) {
   397             return false;
   398         }
   399     }
   401     /**
   402      * Return true if given file name is a valid class name
   403      * (including "package-info").
   404      * @param s the name of the class to check.
   405      * @return true if given class name is a valid class name
   406      * and false otherwise.
   407      */
   408     public static boolean isValidClassName(String s) {
   409         if (s.length() < 1) return false;
   410         if (s.equals("package-info")) return true;
   411         if (surrogatesSupported) {
   412             int cp = s.codePointAt(0);
   413             if (!Character.isJavaIdentifierStart(cp))
   414                 return false;
   415             for (int j=Character.charCount(cp); j<s.length(); j+=Character.charCount(cp)) {
   416                 cp = s.codePointAt(j);
   417                 if (!Character.isJavaIdentifierPart(cp))
   418                     return false;
   419             }
   420         } else {
   421             if (!Character.isJavaIdentifierStart(s.charAt(0)))
   422                 return false;
   423             for (int j=1; j<s.length(); j++)
   424                 if (!Character.isJavaIdentifierPart(s.charAt(j)))
   425                     return false;
   426         }
   427         return true;
   428     }
   430     /**
   431      * From a list of top level trees, return the list of contained class definitions
   432      */
   433     List<JCClassDecl> listClasses(List<JCCompilationUnit> trees) {
   434         ListBuffer<JCClassDecl> result = new ListBuffer<JCClassDecl>();
   435         for (JCCompilationUnit t : trees) {
   436             for (JCTree def : t.defs) {
   437                 if (def.hasTag(JCTree.Tag.CLASSDEF))
   438                     result.append((JCClassDecl)def);
   439             }
   440         }
   441         return result.toList();
   442     }
   444 }

mercurial