
org.jdrupes.mdoclet.internal.doclint.DocLint Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of doclet Show documentation
Show all versions of doclet Show documentation
A doclet for processing javadoc comments written with Markup
/*
* Copyright (c) 2012, 2022, 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 org.jdrupes.mdoclet.internal.doclint;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import javax.lang.model.element.Name;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.StandardLocation;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.ModuleTree;
import com.sun.source.tree.PackageTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.DocTrees;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
/**
* Multi-function entry point for the doc check utility.
*
* This class can be invoked in the following ways:
*
* - From the command line
*
- From javac, as a plugin
*
- Directly, via a simple API
*
*/
public class DocLint extends com.sun.tools.doclint.DocLint {
public static final String XMSGS_OPTION = "-Xmsgs";
public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";
private static final String STATS = "-stats";
public static final String XCUSTOM_TAGS_PREFIX = "-XcustomTags:";
public static final String XCHECK_PACKAGE = "-XcheckPackage:";
public static final String SEPARATOR = ",";
//
public static void main(String... args) {
DocLint dl = new DocLint();
try {
dl.run(args);
} catch (BadArgs e) {
System.err.println(e.getMessage());
System.exit(1);
} catch (IOException e) {
System.err.println(
dl.localize("dc.main.ioerror", e.getLocalizedMessage()));
System.exit(2);
}
}
//
//
public class BadArgs extends Exception {
private static final long serialVersionUID = 0;
BadArgs(String code, Object... args) {
super(localize(code, args));
this.code = code;
this.args = args;
}
final String code;
final transient Object[] args;
}
/**
* Simple API entry point.
* @param args Options and operands for doclint
* @throws BadArgs if an error is detected in any args
* @throws IOException if there are problems with any of the file arguments
*/
public void run(String... args) throws BadArgs, IOException {
PrintWriter out = new PrintWriter(System.out);
try {
run(out, args);
} finally {
out.flush();
}
}
public void run(PrintWriter out, String... args)
throws BadArgs, IOException {
env = new Env();
processArgs(args);
boolean noFiles = javacFiles.isEmpty();
if (needHelp) {
showHelp(out);
if (noFiles)
return;
} else if (noFiles) {
out.println(localize("dc.main.no.files.given"));
return;
}
JavacTool tool = JavacTool.create();
JavacFileManager fm = new JavacFileManager(new Context(), false, null);
fm.setSymbolFileEnabled(false);
if (javacBootClassPath != null) {
fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH,
javacBootClassPath);
}
if (javacClassPath != null) {
fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
}
if (javacSourcePath != null) {
fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
}
JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
fm.getJavaFileObjectsFromFiles(javacFiles));
Iterable extends CompilationUnitTree> units = task.parse();
((JavacTaskImpl) task).enter();
env.init(task);
checker = new Checker(env);
DeclScanner ds = new DeclScanner(env) {
@Override
void visitDecl(Tree tree, Name name) {
TreePath p = getCurrentPath();
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);
}
};
ds.scan(units, null);
reportStats(out);
Context ctx = ((JavacTaskImpl) task).getContext();
JavaCompiler c = JavaCompiler.instance(ctx);
c.printCount("error", c.errorCount());
c.printCount("warn", c.warningCount());
}
void processArgs(String... args) throws BadArgs {
javacOpts = new ArrayList<>();
javacFiles = new ArrayList<>();
if (args.length == 0)
needHelp = true;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.matches("-Xmax(errs|warns)") && i + 1 < args.length) {
if (args[++i].matches("[0-9]+")) {
javacOpts.add(arg);
javacOpts.add(args[i]);
} else {
throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
}
} else if ((arg.equals("-target") || arg.equals("-source"))
&& i + 1 < args.length) {
javacOpts.add(arg);
javacOpts.add(args[++i]);
} else if (arg.equals(STATS)) {
env.messages.setStatsEnabled(true);
} else if (arg.equals("-bootclasspath") && i + 1 < args.length) {
javacBootClassPath = splitPath(args[++i]);
} else if (arg.equals("-classpath") && i + 1 < args.length) {
javacClassPath = splitPath(args[++i]);
} else if (arg.equals("-cp") && i + 1 < args.length) {
javacClassPath = splitPath(args[++i]);
} else if (arg.equals("-sourcepath") && i + 1 < args.length) {
javacSourcePath = splitPath(args[++i]);
} else if (arg.equals(XMSGS_OPTION)) {
env.messages.setOptions(null);
} else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
} else if (arg.equals("-h") || arg.equals("-help")
|| arg.equals("--help")
|| arg.equals("-?") || arg.equals("-usage")) {
needHelp = true;
} else if (arg.startsWith("-")) {
throw new BadArgs("dc.bad.option", arg);
} else {
while (i < args.length)
javacFiles.add(new File(args[i++]));
}
}
}
void showHelp(PrintWriter out) {
String msg = localize("dc.main.usage");
for (String line : msg.split("\n"))
out.println(line);
}
List splitPath(String path) {
List files = new ArrayList<>();
for (String f : path.split(File.pathSeparator)) {
if (f.length() > 0)
files.add(new File(f));
}
return files;
}
List javacBootClassPath;
List javacClassPath;
List javacSourcePath;
List javacOpts;
List javacFiles;
boolean needHelp = false;
//
//
@Override
@DefinedBy(Api.COMPILER_TREE)
public String getName() {
return "doclint";
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public void init(JavacTask task, String... args) {
init(task, args, true);
}
//
//
/**
* Initialize DocLint for use with a {@code JavacTask}.
* {@link Env#strictReferenceChecks Strict reference checks} are not enabled by default.
*
* @param task the task
* @param args arguments to configure DocLint
* @param addTaskListener whether or not to register a {@code TaskListener} to invoke DocLint
*/
public void init(JavacTask task, String[] args, boolean addTaskListener) {
env = new Env();
env.init(task);
processArgs(env, args);
checker = new Checker(env);
if (addTaskListener) {
final DeclScanner ds = new DeclScanner(env) {
@Override
void visitDecl(Tree tree, Name name) {
TreePath p = getCurrentPath();
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);
}
};
TaskListener tl = new TaskListener() {
@Override
@DefinedBy(Api.COMPILER_TREE)
public void started(TaskEvent e) {
switch (e.getKind()) {
case ANALYZE:
CompilationUnitTree tree;
while ((tree = todo.poll()) != null)
ds.scan(tree, null);
break;
}
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public void finished(TaskEvent e) {
switch (e.getKind()) {
case PARSE:
todo.add(e.getCompilationUnit());
break;
}
}
Queue todo = new LinkedList<>();
};
task.addTaskListener(tl);
}
}
/**
* Initialize DocLint with the given utility objects and arguments.
* {@link Env#strictReferenceChecks Strict reference checks} are enabled by default.
*
* @param trees the {@code DocTrees} utility class
* @param elements the {@code Elements} utility class
* @param types the {@code Types} utility class
* @param args arguments to configure DocLint
*/
public void init(DocTrees trees, Elements elements, Types types,
String... args) {
env = new Env();
env.init(trees, elements, types);
env.strictReferenceChecks = true;
processArgs(env, args);
checker = new Checker(env);
}
private void processArgs(Env env, String... args) {
for (String arg : args) {
if (arg.equals(XMSGS_OPTION)) {
env.messages.setOptions(null);
} else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
} else if (arg.startsWith(XCHECK_PACKAGE)) {
env.setCheckPackages(arg.substring(arg.indexOf(":") + 1));
} else
throw new IllegalArgumentException(arg);
}
}
public void scan(TreePath p) {
DocCommentTree dc = env.trees.getDocCommentTree(p);
checker.scan(dc, p);
}
public boolean shouldCheck(CompilationUnitTree unit) {
return env.shouldCheck(unit);
}
public void reportStats(PrintWriter out) {
env.messages.reportStats(out);
}
//
Env env;
Checker checker;
public boolean isValidOption(String opt) {
if (opt.equals(XMSGS_OPTION))
return true;
if (opt.startsWith(XMSGS_CUSTOM_PREFIX))
return Messages.Options
.isValidOptions(opt.substring(XMSGS_CUSTOM_PREFIX.length()));
if (opt.startsWith(XCHECK_PACKAGE)) {
return Env.validatePackages(opt.substring(opt.indexOf(":") + 1));
}
return false;
}
public boolean isGroupEnabled(Messages.Group group,
Env.AccessKind accessKind) {
return env.messages.isEnabled(group, accessKind);
}
private String localize(String code, Object... args) {
Messages m = (env != null) ? env.messages : new Messages(null);
return m.localize(code, args);
}
//
abstract static class DeclScanner extends TreePathScanner {
final Env env;
public DeclScanner(Env env) {
this.env = env;
}
abstract void visitDecl(Tree tree, Name name);
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitPackage(PackageTree tree, Void ignore) {
visitDecl(tree, null);
return super.visitPackage(tree, ignore);
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitClass(ClassTree tree, Void ignore) {
visitDecl(tree, tree.getSimpleName());
return super.visitClass(tree, ignore);
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitMethod(MethodTree tree, Void ignore) {
visitDecl(tree, tree.getName());
return null;
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitModule(ModuleTree tree, Void ignore) {
visitDecl(tree, null);
return super.visitModule(tree, ignore);
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitVariable(VariableTree tree, Void ignore) {
visitDecl(tree, tree.getName());
return super.visitVariable(tree, ignore);
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitCompilationUnit(CompilationUnitTree node, Void p) {
if (!env.shouldCheck(node)) {
return null;
}
return super.visitCompilationUnit(node, p);
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitBlock(BlockTree tree, Void ignore) {
return null;
}
@Override
@DefinedBy(Api.COMPILER_TREE)
public Void visitLambdaExpression(LambdaExpressionTree tree,
Void ignore) {
return null;
}
}
//
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy