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

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.doclint;
aoqi@0 27
aoqi@0 28 import java.io.File;
aoqi@0 29 import java.io.IOException;
aoqi@0 30 import java.io.PrintWriter;
aoqi@0 31 import java.util.ArrayList;
aoqi@0 32 import java.util.HashSet;
aoqi@0 33 import java.util.LinkedList;
aoqi@0 34 import java.util.List;
aoqi@0 35 import java.util.Queue;
aoqi@0 36 import java.util.Set;
aoqi@0 37
aoqi@0 38 import javax.lang.model.element.Name;
aoqi@0 39 import javax.tools.JavaFileObject;
aoqi@0 40 import javax.tools.StandardLocation;
aoqi@0 41
aoqi@0 42 import com.sun.source.doctree.DocCommentTree;
aoqi@0 43 import com.sun.source.tree.ClassTree;
aoqi@0 44 import com.sun.source.tree.CompilationUnitTree;
aoqi@0 45 import com.sun.source.tree.MethodTree;
aoqi@0 46 import com.sun.source.tree.Tree;
aoqi@0 47 import com.sun.source.tree.VariableTree;
aoqi@0 48 import com.sun.source.util.JavacTask;
aoqi@0 49 import com.sun.source.util.Plugin;
aoqi@0 50 import com.sun.source.util.TaskEvent;
aoqi@0 51 import com.sun.source.util.TaskListener;
aoqi@0 52 import com.sun.source.util.TreePath;
aoqi@0 53 import com.sun.source.util.TreePathScanner;
aoqi@0 54 import com.sun.tools.javac.api.JavacTaskImpl;
aoqi@0 55 import com.sun.tools.javac.api.JavacTool;
aoqi@0 56 import com.sun.tools.javac.file.JavacFileManager;
aoqi@0 57 import com.sun.tools.javac.main.JavaCompiler;
aoqi@0 58 import com.sun.tools.javac.util.Context;
aoqi@0 59
aoqi@0 60 /**
aoqi@0 61 * Multi-function entry point for the doc check utility.
aoqi@0 62 *
aoqi@0 63 * This class can be invoked in the following ways:
aoqi@0 64 * <ul>
aoqi@0 65 * <li>From the command line
aoqi@0 66 * <li>From javac, as a plugin
aoqi@0 67 * <li>Directly, via a simple API
aoqi@0 68 * </ul>
aoqi@0 69 *
aoqi@0 70 * <p><b>This is NOT part of any supported API.
aoqi@0 71 * If you write code that depends on this, you do so at your own
aoqi@0 72 * risk. This code and its internal interfaces are subject to change
aoqi@0 73 * or deletion without notice.</b></p>
aoqi@0 74 */
aoqi@0 75 public class DocLint implements Plugin {
aoqi@0 76
aoqi@0 77 public static final String XMSGS_OPTION = "-Xmsgs";
aoqi@0 78 public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";
aoqi@0 79 private static final String STATS = "-stats";
aoqi@0 80 public static final String XIMPLICIT_HEADERS = "-XimplicitHeaders:";
aoqi@0 81 public static final String XCUSTOM_TAGS_PREFIX = "-XcustomTags:";
aoqi@0 82 public static final String TAGS_SEPARATOR = ",";
aoqi@0 83
aoqi@0 84 // <editor-fold defaultstate="collapsed" desc="Command-line entry point">
aoqi@0 85 public static void main(String... args) {
aoqi@0 86 DocLint dl = new DocLint();
aoqi@0 87 try {
aoqi@0 88 dl.run(args);
aoqi@0 89 } catch (BadArgs e) {
aoqi@0 90 System.err.println(e.getMessage());
aoqi@0 91 System.exit(1);
aoqi@0 92 } catch (IOException e) {
aoqi@0 93 System.err.println(dl.localize("dc.main.ioerror", e.getLocalizedMessage()));
aoqi@0 94 System.exit(2);
aoqi@0 95 }
aoqi@0 96 }
aoqi@0 97
aoqi@0 98 // </editor-fold>
aoqi@0 99
aoqi@0 100 // <editor-fold defaultstate="collapsed" desc="Simple API">
aoqi@0 101
aoqi@0 102 public class BadArgs extends Exception {
aoqi@0 103 private static final long serialVersionUID = 0;
aoqi@0 104 BadArgs(String code, Object... args) {
aoqi@0 105 super(localize(code, args));
aoqi@0 106 this.code = code;
aoqi@0 107 this.args = args;
aoqi@0 108 }
aoqi@0 109
aoqi@0 110 final String code;
aoqi@0 111 final Object[] args;
aoqi@0 112 }
aoqi@0 113
aoqi@0 114 /**
aoqi@0 115 * Simple API entry point.
aoqi@0 116 */
aoqi@0 117 public void run(String... args) throws BadArgs, IOException {
aoqi@0 118 PrintWriter out = new PrintWriter(System.out);
aoqi@0 119 try {
aoqi@0 120 run(out, args);
aoqi@0 121 } finally {
aoqi@0 122 out.flush();
aoqi@0 123 }
aoqi@0 124 }
aoqi@0 125
aoqi@0 126 public void run(PrintWriter out, String... args) throws BadArgs, IOException {
aoqi@0 127 env = new Env();
aoqi@0 128 processArgs(args);
aoqi@0 129
aoqi@0 130 if (needHelp)
aoqi@0 131 showHelp(out);
aoqi@0 132
aoqi@0 133 if (javacFiles.isEmpty()) {
aoqi@0 134 if (!needHelp)
aoqi@0 135 out.println(localize("dc.main.no.files.given"));
aoqi@0 136 }
aoqi@0 137
aoqi@0 138 JavacTool tool = JavacTool.create();
aoqi@0 139
aoqi@0 140 JavacFileManager fm = new JavacFileManager(new Context(), false, null);
aoqi@0 141 fm.setSymbolFileEnabled(false);
aoqi@0 142 fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
aoqi@0 143 fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
aoqi@0 144 fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
aoqi@0 145
aoqi@0 146 JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
aoqi@0 147 fm.getJavaFileObjectsFromFiles(javacFiles));
aoqi@0 148 Iterable<? extends CompilationUnitTree> units = task.parse();
aoqi@0 149 ((JavacTaskImpl) task).enter();
aoqi@0 150
aoqi@0 151 env.init(task);
aoqi@0 152 checker = new Checker(env);
aoqi@0 153
aoqi@0 154 DeclScanner ds = new DeclScanner() {
aoqi@0 155 @Override
aoqi@0 156 void visitDecl(Tree tree, Name name) {
aoqi@0 157 TreePath p = getCurrentPath();
aoqi@0 158 DocCommentTree dc = env.trees.getDocCommentTree(p);
aoqi@0 159
aoqi@0 160 checker.scan(dc, p);
aoqi@0 161 }
aoqi@0 162 };
aoqi@0 163
aoqi@0 164 ds.scan(units, null);
aoqi@0 165
aoqi@0 166 reportStats(out);
aoqi@0 167
aoqi@0 168 Context ctx = ((JavacTaskImpl) task).getContext();
aoqi@0 169 JavaCompiler c = JavaCompiler.instance(ctx);
aoqi@0 170 c.printCount("error", c.errorCount());
aoqi@0 171 c.printCount("warn", c.warningCount());
aoqi@0 172 }
aoqi@0 173
aoqi@0 174 void processArgs(String... args) throws BadArgs {
aoqi@0 175 javacOpts = new ArrayList<>();
aoqi@0 176 javacFiles = new ArrayList<>();
aoqi@0 177
aoqi@0 178 if (args.length == 0)
aoqi@0 179 needHelp = true;
aoqi@0 180
aoqi@0 181 for (int i = 0; i < args.length; i++) {
aoqi@0 182 String arg = args[i];
aoqi@0 183 if (arg.matches("-Xmax(errs|warns)") && i + 1 < args.length) {
aoqi@0 184 if (args[++i].matches("[0-9]+")) {
aoqi@0 185 javacOpts.add(arg);
aoqi@0 186 javacOpts.add(args[i]);
aoqi@0 187 } else {
aoqi@0 188 throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
aoqi@0 189 }
aoqi@0 190 } else if (arg.equals(STATS)) {
aoqi@0 191 env.messages.setStatsEnabled(true);
aoqi@0 192 } else if (arg.equals("-bootclasspath") && i + 1 < args.length) {
aoqi@0 193 javacBootClassPath = splitPath(args[++i]);
aoqi@0 194 } else if (arg.equals("-classpath") && i + 1 < args.length) {
aoqi@0 195 javacClassPath = splitPath(args[++i]);
aoqi@0 196 } else if (arg.equals("-cp") && i + 1 < args.length) {
aoqi@0 197 javacClassPath = splitPath(args[++i]);
aoqi@0 198 } else if (arg.equals("-sourcepath") && i + 1 < args.length) {
aoqi@0 199 javacSourcePath = splitPath(args[++i]);
aoqi@0 200 } else if (arg.equals(XMSGS_OPTION)) {
aoqi@0 201 env.messages.setOptions(null);
aoqi@0 202 } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
aoqi@0 203 env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
aoqi@0 204 } else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
aoqi@0 205 env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
aoqi@0 206 } else if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")
aoqi@0 207 || arg.equals("-?") || arg.equals("-usage")) {
aoqi@0 208 needHelp = true;
aoqi@0 209 } else if (arg.startsWith("-")) {
aoqi@0 210 throw new BadArgs("dc.bad.option", arg);
aoqi@0 211 } else {
aoqi@0 212 while (i < args.length)
aoqi@0 213 javacFiles.add(new File(args[i++]));
aoqi@0 214 }
aoqi@0 215 }
aoqi@0 216 }
aoqi@0 217
aoqi@0 218 void showHelp(PrintWriter out) {
aoqi@0 219 String msg = localize("dc.main.usage");
aoqi@0 220 for (String line: msg.split("\n"))
aoqi@0 221 out.println(line);
aoqi@0 222 }
aoqi@0 223
aoqi@0 224 List<File> splitPath(String path) {
aoqi@0 225 List<File> files = new ArrayList<>();
aoqi@0 226 for (String f: path.split(File.pathSeparator)) {
aoqi@0 227 if (f.length() > 0)
aoqi@0 228 files.add(new File(f));
aoqi@0 229 }
aoqi@0 230 return files;
aoqi@0 231 }
aoqi@0 232
aoqi@0 233 List<File> javacBootClassPath;
aoqi@0 234 List<File> javacClassPath;
aoqi@0 235 List<File> javacSourcePath;
aoqi@0 236 List<String> javacOpts;
aoqi@0 237 List<File> javacFiles;
aoqi@0 238 boolean needHelp = false;
aoqi@0 239
aoqi@0 240 // </editor-fold>
aoqi@0 241
aoqi@0 242 // <editor-fold defaultstate="collapsed" desc="javac Plugin">
aoqi@0 243
aoqi@0 244 @Override
aoqi@0 245 public String getName() {
aoqi@0 246 return "doclint";
aoqi@0 247 }
aoqi@0 248
aoqi@0 249 @Override
aoqi@0 250 public void init(JavacTask task, String... args) {
aoqi@0 251 init(task, args, true);
aoqi@0 252 }
aoqi@0 253
aoqi@0 254 // </editor-fold>
aoqi@0 255
aoqi@0 256 // <editor-fold defaultstate="collapsed" desc="Embedding API">
aoqi@0 257
aoqi@0 258 public void init(JavacTask task, String[] args, boolean addTaskListener) {
aoqi@0 259 env = new Env();
aoqi@0 260 for (int i = 0; i < args.length; i++) {
aoqi@0 261 String arg = args[i];
aoqi@0 262 if (arg.equals(XMSGS_OPTION)) {
aoqi@0 263 env.messages.setOptions(null);
aoqi@0 264 } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
aoqi@0 265 env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
aoqi@0 266 } else if (arg.matches(XIMPLICIT_HEADERS + "[1-6]")) {
aoqi@0 267 char ch = arg.charAt(arg.length() - 1);
aoqi@0 268 env.setImplicitHeaders(Character.digit(ch, 10));
aoqi@0 269 } else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
aoqi@0 270 env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
aoqi@0 271 } else
aoqi@0 272 throw new IllegalArgumentException(arg);
aoqi@0 273 }
aoqi@0 274 env.init(task);
aoqi@0 275
aoqi@0 276 checker = new Checker(env);
aoqi@0 277
aoqi@0 278 if (addTaskListener) {
aoqi@0 279 final DeclScanner ds = new DeclScanner() {
aoqi@0 280 @Override
aoqi@0 281 void visitDecl(Tree tree, Name name) {
aoqi@0 282 TreePath p = getCurrentPath();
aoqi@0 283 DocCommentTree dc = env.trees.getDocCommentTree(p);
aoqi@0 284
aoqi@0 285 checker.scan(dc, p);
aoqi@0 286 }
aoqi@0 287 };
aoqi@0 288
aoqi@0 289 TaskListener tl = new TaskListener() {
aoqi@0 290 @Override
aoqi@0 291 public void started(TaskEvent e) {
aoqi@0 292 switch (e.getKind()) {
aoqi@0 293 case ANALYZE:
aoqi@0 294 CompilationUnitTree tree;
aoqi@0 295 while ((tree = todo.poll()) != null)
aoqi@0 296 ds.scan(tree, null);
aoqi@0 297 break;
aoqi@0 298 }
aoqi@0 299 }
aoqi@0 300
aoqi@0 301 @Override
aoqi@0 302 public void finished(TaskEvent e) {
aoqi@0 303 switch (e.getKind()) {
aoqi@0 304 case PARSE:
aoqi@0 305 todo.add(e.getCompilationUnit());
aoqi@0 306 break;
aoqi@0 307 }
aoqi@0 308 }
aoqi@0 309
aoqi@0 310 Queue<CompilationUnitTree> todo = new LinkedList<CompilationUnitTree>();
aoqi@0 311 };
aoqi@0 312
aoqi@0 313 task.addTaskListener(tl);
aoqi@0 314 }
aoqi@0 315 }
aoqi@0 316
aoqi@0 317 public void scan(TreePath p) {
aoqi@0 318 DocCommentTree dc = env.trees.getDocCommentTree(p);
aoqi@0 319 checker.scan(dc, p);
aoqi@0 320 }
aoqi@0 321
aoqi@0 322 public void reportStats(PrintWriter out) {
aoqi@0 323 env.messages.reportStats(out);
aoqi@0 324 }
aoqi@0 325
aoqi@0 326 // </editor-fold>
aoqi@0 327
aoqi@0 328 Env env;
aoqi@0 329 Checker checker;
aoqi@0 330
aoqi@0 331 public static boolean isValidOption(String opt) {
aoqi@0 332 if (opt.equals(XMSGS_OPTION))
aoqi@0 333 return true;
aoqi@0 334 if (opt.startsWith(XMSGS_CUSTOM_PREFIX))
aoqi@0 335 return Messages.Options.isValidOptions(opt.substring(XMSGS_CUSTOM_PREFIX.length()));
aoqi@0 336 return false;
aoqi@0 337 }
aoqi@0 338
aoqi@0 339 private String localize(String code, Object... args) {
aoqi@0 340 Messages m = (env != null) ? env.messages : new Messages(null);
aoqi@0 341 return m.localize(code, args);
aoqi@0 342 }
aoqi@0 343
aoqi@0 344 // <editor-fold defaultstate="collapsed" desc="DeclScanner">
aoqi@0 345
aoqi@0 346 static abstract class DeclScanner extends TreePathScanner<Void, Void> {
aoqi@0 347 abstract void visitDecl(Tree tree, Name name);
aoqi@0 348
aoqi@0 349 @Override
aoqi@0 350 public Void visitCompilationUnit(CompilationUnitTree tree, Void ignore) {
aoqi@0 351 if (tree.getPackageName() != null) {
aoqi@0 352 visitDecl(tree, null);
aoqi@0 353 }
aoqi@0 354 return super.visitCompilationUnit(tree, ignore);
aoqi@0 355 }
aoqi@0 356
aoqi@0 357 @Override
aoqi@0 358 public Void visitClass(ClassTree tree, Void ignore) {
aoqi@0 359 visitDecl(tree, tree.getSimpleName());
aoqi@0 360 return super.visitClass(tree, ignore);
aoqi@0 361 }
aoqi@0 362
aoqi@0 363 @Override
aoqi@0 364 public Void visitMethod(MethodTree tree, Void ignore) {
aoqi@0 365 visitDecl(tree, tree.getName());
aoqi@0 366 //return super.visitMethod(tree, ignore);
aoqi@0 367 return null;
aoqi@0 368 }
aoqi@0 369
aoqi@0 370 @Override
aoqi@0 371 public Void visitVariable(VariableTree tree, Void ignore) {
aoqi@0 372 visitDecl(tree, tree.getName());
aoqi@0 373 return super.visitVariable(tree, ignore);
aoqi@0 374 }
aoqi@0 375 }
aoqi@0 376
aoqi@0 377 // </editor-fold>
aoqi@0 378
aoqi@0 379 }

mercurial