src/share/classes/com/sun/tools/doclint/DocLint.java

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 2169
667843bd2193
parent 0
959103a6100f
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2012, 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.doclint;
    28 import java.io.File;
    29 import java.io.IOException;
    30 import java.io.PrintWriter;
    31 import java.util.ArrayList;
    32 import java.util.HashSet;
    33 import java.util.LinkedList;
    34 import java.util.List;
    35 import java.util.Queue;
    36 import java.util.Set;
    38 import javax.lang.model.element.Name;
    39 import javax.tools.JavaFileObject;
    40 import javax.tools.StandardLocation;
    42 import com.sun.source.doctree.DocCommentTree;
    43 import com.sun.source.tree.ClassTree;
    44 import com.sun.source.tree.CompilationUnitTree;
    45 import com.sun.source.tree.MethodTree;
    46 import com.sun.source.tree.Tree;
    47 import com.sun.source.tree.VariableTree;
    48 import com.sun.source.util.JavacTask;
    49 import com.sun.source.util.Plugin;
    50 import com.sun.source.util.TaskEvent;
    51 import com.sun.source.util.TaskListener;
    52 import com.sun.source.util.TreePath;
    53 import com.sun.source.util.TreePathScanner;
    54 import com.sun.tools.javac.api.JavacTaskImpl;
    55 import com.sun.tools.javac.api.JavacTool;
    56 import com.sun.tools.javac.file.JavacFileManager;
    57 import com.sun.tools.javac.main.JavaCompiler;
    58 import com.sun.tools.javac.util.Context;
    60 /**
    61  * Multi-function entry point for the doc check utility.
    62  *
    63  * This class can be invoked in the following ways:
    64  * <ul>
    65  * <li>From the command line
    66  * <li>From javac, as a plugin
    67  * <li>Directly, via a simple API
    68  * </ul>
    69  *
    70  * <p><b>This is NOT part of any supported API.
    71  * If you write code that depends on this, you do so at your own
    72  * risk.  This code and its internal interfaces are subject to change
    73  * or deletion without notice.</b></p>
    74  */
    75 public class DocLint implements Plugin {
    77     public static final String XMSGS_OPTION = "-Xmsgs";
    78     public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";
    79     private static final String STATS = "-stats";
    80     public static final String XIMPLICIT_HEADERS = "-XimplicitHeaders:";
    81     public static final String XCUSTOM_TAGS_PREFIX = "-XcustomTags:";
    82     public static final String TAGS_SEPARATOR = ",";
    84     // <editor-fold defaultstate="collapsed" desc="Command-line entry point">
    85     public static void main(String... args) {
    86         DocLint dl = new DocLint();
    87         try {
    88             dl.run(args);
    89         } catch (BadArgs e) {
    90             System.err.println(e.getMessage());
    91             System.exit(1);
    92         } catch (IOException e) {
    93             System.err.println(dl.localize("dc.main.ioerror", e.getLocalizedMessage()));
    94             System.exit(2);
    95         }
    96     }
    98     // </editor-fold>
   100     // <editor-fold defaultstate="collapsed" desc="Simple API">
   102     public class BadArgs extends Exception {
   103         private static final long serialVersionUID = 0;
   104         BadArgs(String code, Object... args) {
   105             super(localize(code, args));
   106             this.code = code;
   107             this.args = args;
   108         }
   110         final String code;
   111         final Object[] args;
   112     }
   114     /**
   115      * Simple API entry point.
   116      */
   117     public void run(String... args) throws BadArgs, IOException {
   118         PrintWriter out = new PrintWriter(System.out);
   119         try {
   120             run(out, args);
   121         } finally {
   122             out.flush();
   123         }
   124     }
   126     public void run(PrintWriter out, String... args) throws BadArgs, IOException {
   127         env = new Env();
   128         processArgs(args);
   130         if (needHelp)
   131             showHelp(out);
   133         if (javacFiles.isEmpty()) {
   134             if (!needHelp)
   135                 out.println(localize("dc.main.no.files.given"));
   136         }
   138         JavacTool tool = JavacTool.create();
   140         JavacFileManager fm = new JavacFileManager(new Context(), false, null);
   141         fm.setSymbolFileEnabled(false);
   142         fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
   143         fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
   144         fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
   146         JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
   147                 fm.getJavaFileObjectsFromFiles(javacFiles));
   148         Iterable<? extends CompilationUnitTree> units = task.parse();
   149         ((JavacTaskImpl) task).enter();
   151         env.init(task);
   152         checker = new Checker(env);
   154         DeclScanner ds = new DeclScanner() {
   155             @Override
   156             void visitDecl(Tree tree, Name name) {
   157                 TreePath p = getCurrentPath();
   158                 DocCommentTree dc = env.trees.getDocCommentTree(p);
   160                 checker.scan(dc, p);
   161             }
   162         };
   164         ds.scan(units, null);
   166         reportStats(out);
   168         Context ctx = ((JavacTaskImpl) task).getContext();
   169         JavaCompiler c = JavaCompiler.instance(ctx);
   170         c.printCount("error", c.errorCount());
   171         c.printCount("warn", c.warningCount());
   172     }
   174     void processArgs(String... args) throws BadArgs {
   175         javacOpts = new ArrayList<>();
   176         javacFiles = new ArrayList<>();
   178         if (args.length == 0)
   179             needHelp = true;
   181         for (int i = 0; i < args.length; i++) {
   182             String arg = args[i];
   183             if (arg.matches("-Xmax(errs|warns)") && i + 1 < args.length) {
   184                 if (args[++i].matches("[0-9]+")) {
   185                     javacOpts.add(arg);
   186                     javacOpts.add(args[i]);
   187                 } else {
   188                     throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
   189                 }
   190             } else if (arg.equals(STATS)) {
   191                 env.messages.setStatsEnabled(true);
   192             } else if (arg.equals("-bootclasspath") && i + 1 < args.length) {
   193                 javacBootClassPath = splitPath(args[++i]);
   194             } else if (arg.equals("-classpath") && i + 1 < args.length) {
   195                 javacClassPath = splitPath(args[++i]);
   196             } else if (arg.equals("-cp") && i + 1 < args.length) {
   197                 javacClassPath = splitPath(args[++i]);
   198             } else if (arg.equals("-sourcepath") && i + 1 < args.length) {
   199                 javacSourcePath = splitPath(args[++i]);
   200             } else if (arg.equals(XMSGS_OPTION)) {
   201                 env.messages.setOptions(null);
   202             } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
   203                 env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
   204             } else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
   205                 env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
   206             } else if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")
   207                     || arg.equals("-?") || arg.equals("-usage")) {
   208                 needHelp = true;
   209             } else if (arg.startsWith("-")) {
   210                 throw new BadArgs("dc.bad.option", arg);
   211             } else {
   212                 while (i < args.length)
   213                     javacFiles.add(new File(args[i++]));
   214             }
   215         }
   216     }
   218     void showHelp(PrintWriter out) {
   219         String msg = localize("dc.main.usage");
   220         for (String line: msg.split("\n"))
   221             out.println(line);
   222     }
   224     List<File> splitPath(String path) {
   225         List<File> files = new ArrayList<>();
   226         for (String f: path.split(File.pathSeparator)) {
   227             if (f.length() > 0)
   228                 files.add(new File(f));
   229         }
   230         return files;
   231     }
   233     List<File> javacBootClassPath;
   234     List<File> javacClassPath;
   235     List<File> javacSourcePath;
   236     List<String> javacOpts;
   237     List<File> javacFiles;
   238     boolean needHelp = false;
   240     // </editor-fold>
   242     // <editor-fold defaultstate="collapsed" desc="javac Plugin">
   244     @Override
   245     public String getName() {
   246         return "doclint";
   247     }
   249     @Override
   250     public void init(JavacTask task, String... args) {
   251         init(task, args, true);
   252     }
   254     // </editor-fold>
   256     // <editor-fold defaultstate="collapsed" desc="Embedding API">
   258     public void init(JavacTask task, String[] args, boolean addTaskListener) {
   259         env = new Env();
   260         for (int i = 0; i < args.length; i++) {
   261             String arg = args[i];
   262             if (arg.equals(XMSGS_OPTION)) {
   263                 env.messages.setOptions(null);
   264             } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
   265                 env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
   266             } else if (arg.matches(XIMPLICIT_HEADERS + "[1-6]")) {
   267                 char ch = arg.charAt(arg.length() - 1);
   268                 env.setImplicitHeaders(Character.digit(ch, 10));
   269             } else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
   270                 env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
   271             } else
   272                 throw new IllegalArgumentException(arg);
   273         }
   274         env.init(task);
   276         checker = new Checker(env);
   278         if (addTaskListener) {
   279             final DeclScanner ds = new DeclScanner() {
   280                 @Override
   281                 void visitDecl(Tree tree, Name name) {
   282                     TreePath p = getCurrentPath();
   283                     DocCommentTree dc = env.trees.getDocCommentTree(p);
   285                     checker.scan(dc, p);
   286                 }
   287             };
   289             TaskListener tl = new TaskListener() {
   290                 @Override
   291                 public void started(TaskEvent e) {
   292                     switch (e.getKind()) {
   293                         case ANALYZE:
   294                             CompilationUnitTree tree;
   295                             while ((tree = todo.poll()) != null)
   296                                 ds.scan(tree, null);
   297                             break;
   298                     }
   299                 }
   301                 @Override
   302                 public void finished(TaskEvent e) {
   303                     switch (e.getKind()) {
   304                         case PARSE:
   305                             todo.add(e.getCompilationUnit());
   306                             break;
   307                     }
   308                 }
   310                 Queue<CompilationUnitTree> todo = new LinkedList<CompilationUnitTree>();
   311             };
   313             task.addTaskListener(tl);
   314         }
   315     }
   317     public void scan(TreePath p) {
   318         DocCommentTree dc = env.trees.getDocCommentTree(p);
   319         checker.scan(dc, p);
   320     }
   322     public void reportStats(PrintWriter out) {
   323         env.messages.reportStats(out);
   324     }
   326     // </editor-fold>
   328     Env env;
   329     Checker checker;
   331     public static boolean isValidOption(String opt) {
   332         if (opt.equals(XMSGS_OPTION))
   333            return true;
   334         if (opt.startsWith(XMSGS_CUSTOM_PREFIX))
   335            return Messages.Options.isValidOptions(opt.substring(XMSGS_CUSTOM_PREFIX.length()));
   336         return false;
   337     }
   339     private String localize(String code, Object... args) {
   340         Messages m = (env != null) ? env.messages : new Messages(null);
   341         return m.localize(code, args);
   342     }
   344     // <editor-fold defaultstate="collapsed" desc="DeclScanner">
   346     static abstract class DeclScanner extends TreePathScanner<Void, Void> {
   347         abstract void visitDecl(Tree tree, Name name);
   349         @Override
   350         public Void visitCompilationUnit(CompilationUnitTree tree, Void ignore) {
   351             if (tree.getPackageName() != null) {
   352                 visitDecl(tree, null);
   353             }
   354             return super.visitCompilationUnit(tree, ignore);
   355         }
   357         @Override
   358         public Void visitClass(ClassTree tree, Void ignore) {
   359             visitDecl(tree, tree.getSimpleName());
   360             return super.visitClass(tree, ignore);
   361         }
   363         @Override
   364         public Void visitMethod(MethodTree tree, Void ignore) {
   365             visitDecl(tree, tree.getName());
   366             //return super.visitMethod(tree, ignore);
   367             return null;
   368         }
   370         @Override
   371         public Void visitVariable(VariableTree tree, Void ignore) {
   372             visitDecl(tree, tree.getName());
   373             return super.visitVariable(tree, ignore);
   374         }
   375     }
   377     // </editor-fold>
   379 }

mercurial