8237803: Reorganize impl of tool options

Reviewed-by: prappo
This commit is contained in:
Jonathan Gibbons 2020-01-27 13:42:57 -08:00
parent 99b9939318
commit 6b4223eec2
8 changed files with 1128 additions and 813 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@ -50,7 +50,7 @@ import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import jdk.javadoc.internal.tool.ToolOption;
import jdk.javadoc.internal.tool.ToolOptions;
/**
* Provides access to functionality specific to the JDK documentation tool,
@ -170,13 +170,7 @@ public class JavadocTool implements DocumentationTool {
public int isSupportedOption(String option) {
if (option == null)
throw new NullPointerException();
for (ToolOption o : ToolOption.values()) {
for (String name : o.names) {
if (name.equals(option))
return o.hasArg ? 1 : 0;
}
}
return -1;
return ToolOptions.isSupportedOption(option);
}
}

View File

@ -2023,10 +2023,8 @@ public class Utils {
return result;
}
if (hasParameters(e1) && hasParameters(e2)) {
@SuppressWarnings("unchecked")
List<VariableElement> parameters1 = (List<VariableElement>)((ExecutableElement)e1).getParameters();
@SuppressWarnings("unchecked")
List<VariableElement> parameters2 = (List<VariableElement>)((ExecutableElement)e2).getParameters();
List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
result = compareParameters(false, parameters1, parameters2);
if (result != 0) {
return result;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2020, 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
@ -164,7 +164,7 @@ public class ElementsTable {
private final JavaFileManager fm;
private final List<Location> locations;
private final Modules modules;
private final Map<ToolOption, Object> opts;
private final ToolOptions options;
private final Messager messager;
private final JavaCompiler compiler;
@ -201,15 +201,15 @@ public class ElementsTable {
* Creates the table to manage included and excluded elements.
*
* @param context the context to locate commonly used objects
* @param location the location used to locate source files
* @param options the tool options
*/
ElementsTable(Context context, Map<ToolOption, Object> opts) {
ElementsTable(Context context, ToolOptions options) {
this.toolEnv = ToolEnvironment.instance(context);
this.syms = Symtab.instance(context);
this.names = Names.instance(context);
this.fm = toolEnv.fileManager;
this.modules = Modules.instance(context);
this.opts = opts;
this.options = options;
this.messager = Messager.instance0(context);
this.compiler = JavaCompiler.instance(context);
Source source = Source.instance(context);
@ -229,9 +229,9 @@ public class ElementsTable {
getEntry("").excluded = false;
accessFilter = new ModifierFilter(opts);
xclasses = (boolean)opts.getOrDefault(ToolOption.XCLASSES, false);
expandRequires = (AccessKind)opts.get(ToolOption.EXPAND_REQUIRES);
accessFilter = new ModifierFilter(options);
xclasses = options.xclasses();
expandRequires = options.expandRequires();
}
/**
@ -318,9 +318,7 @@ public class ElementsTable {
*
* @param e the element in question
*
* @see getIncludedModuleElements
* @see getIncludedPackageElements
* @see getIncludedTypeElements
* @see #getIncludedElements()
*
* @return true if included
*/
@ -407,21 +405,19 @@ public class ElementsTable {
return null;
}
@SuppressWarnings("unchecked")
ElementsTable scanSpecifiedItems() throws ToolException {
// scan modules specified on the command line
List<String> moduleNames = (List<String>) opts.computeIfAbsent(ToolOption.MODULE,
s -> Collections.EMPTY_LIST);
List<String> modules = options.modules();
List<String> mlist = new ArrayList<>();
for (String m : moduleNames) {
for (String m : modules) {
List<Location> moduleLocations = getModuleLocation(locations, m);
if (moduleLocations.isEmpty()) {
String text = messager.getText("main.module_not_found", m);
throw new ToolException(CMDERR, text);
}
if (moduleLocations.contains(StandardLocation.SOURCE_PATH)) {
sanityCheckSourcePathModules(moduleNames);
sanityCheckSourcePathModules(modules);
}
mlist.add(m);
ModuleSymbol msym = syms.enterModule(names.fromString(m));
@ -436,8 +432,7 @@ public class ElementsTable {
});
// scan for modules with qualified subpackages
((List<String>)opts.computeIfAbsent(ToolOption.SUBPACKAGES, v -> Collections.EMPTY_LIST))
.stream()
options.subpackages().stream()
.map(ModulePackage::new)
.forEachOrdered((mpkg) -> {
subPackages.add(mpkg);
@ -448,8 +443,8 @@ public class ElementsTable {
// all the modules specified on the command line have been scraped
// init the module systems
modules.addExtraAddModules(mlist.toArray(new String[mlist.size()]));
modules.initModules(this.classTreeList);
this.modules.addExtraAddModules(mlist.toArray(new String[mlist.size()]));
this.modules.initModules(this.classTreeList);
return this;
}
@ -504,10 +499,8 @@ public class ElementsTable {
return result;
}
@SuppressWarnings("unchecked")
private void computeSubpackages() throws ToolException {
((List<String>) opts.computeIfAbsent(ToolOption.EXCLUDE, v -> Collections.EMPTY_LIST))
.stream()
options.excludes().stream()
.map(ModulePackage::new)
.forEachOrdered((mpkg) -> excludePackages.add(mpkg));
@ -830,7 +823,7 @@ public class ElementsTable {
/**
* Returns the set of source files for a package.
*
* @param packageName the specified package
* @param modpkg the specified package
* @return the set of file objects for the specified package
* @throws ToolException if an error occurs while accessing the files
*/
@ -1214,24 +1207,24 @@ public class ElementsTable {
/**
* Constructor - Specify a filter.
*
* @param accessSet an Access filter.
* @param options the tool options
*/
ModifierFilter(Map<ToolOption, Object> opts) {
ModifierFilter(ToolOptions options) {
AccessKind accessValue = null;
for (ElementKind kind : ALLOWED_KINDS) {
switch (kind) {
case METHOD:
accessValue = (AccessKind)opts.get(ToolOption.SHOW_MEMBERS);
accessValue = options.showMembersAccess();
break;
case CLASS:
accessValue = (AccessKind)opts.get(ToolOption.SHOW_TYPES);
accessValue = options.showTypesAccess();
break;
case PACKAGE:
accessValue = (AccessKind)opts.get(ToolOption.SHOW_PACKAGES);
accessValue = options.showPackagesAccess();
break;
case MODULE:
accessValue = (AccessKind)opts.get(ToolOption.SHOW_MODULE_CONTENTS);
accessValue = options.showModuleContents();
break;
default:
throw new AssertionError("unknown element: " + kind);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2020, 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
@ -32,7 +32,6 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.Element;
@ -121,18 +120,18 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
return new JavadocTool(context);
} catch (CompletionFailure ex) {
assert messager != null;
messager.error(Position.NOPOS, ex.getMessage());
return null;
}
}
public DocletEnvironment getEnvironment(Map<ToolOption,
Object> jdtoolOpts,
public DocletEnvironment getEnvironment(ToolOptions toolOptions,
List<String> javaNames,
Iterable<? extends JavaFileObject> fileObjects) throws ToolException {
toolEnv = ToolEnvironment.instance(context);
toolEnv.initialize(jdtoolOpts);
ElementsTable etable = new ElementsTable(context, jdtoolOpts);
toolEnv.initialize(toolOptions);
ElementsTable etable = new ElementsTable(context, toolOptions);
javadocFinder.sourceCompleter = etable.xclasses
? Completer.NULL_COMPLETER
: sourceCompleter;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, 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
@ -28,12 +28,10 @@ package jdk.javadoc.internal.tool;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.text.BreakIterator;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.IllformedLocaleException;
@ -44,12 +42,10 @@ import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.file.BaseFileManager;
@ -57,25 +53,20 @@ import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.Arguments;
import com.sun.tools.javac.main.CommandLine;
import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
import com.sun.tools.javac.platform.PlatformDescription;
import com.sun.tools.javac.platform.PlatformUtils;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.WriterKind;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.util.StringUtils;
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.Doclet.Option;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.StandardDoclet;
import jdk.javadoc.internal.tool.Main.Result;
import jdk.javadoc.internal.tool.ToolOptions.ToolOption;
import static javax.tools.DocumentationTool.Location.*;
import static com.sun.tools.javac.main.Option.*;
import static jdk.javadoc.internal.tool.Main.Result.*;
/**
@ -87,10 +78,8 @@ import static jdk.javadoc.internal.tool.Main.Result.*;
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Start extends ToolOption.Helper {
public class Start {
private static final Class<?> StdDoclet =
jdk.javadoc.doclet.StandardDoclet.class;
/** Context for this invocation. */
private final Context context;
@ -118,6 +107,8 @@ public class Start extends ToolOption.Helper {
private JavaFileManager fileManager;
private final ToolOptions options;
Start() {
this(null, null, null, null, null, null);
}
@ -138,6 +129,8 @@ public class Start extends ToolOption.Helper {
this.classLoader = classLoader;
this.docletClass = null;
this.locale = Locale.getDefault();
options = getToolOptions();
}
public Start(Context context) {
@ -147,48 +140,50 @@ public class Start extends ToolOption.Helper {
this.docletName = null;
this.classLoader = null;
this.locale = Locale.getDefault();
}
void initMessager() {
if (!apiMode)
return;
if (messager == null) {
Log log = context.get(Log.logKey);
if (log instanceof Messager) {
messager = (Messager) log;
} else {
PrintWriter out = context.get(Log.errKey);
messager = (out == null)
? new Messager(context, ProgramName)
: new Messager(context, ProgramName, out, out);
}
Log log = context.get(Log.logKey);
if (log instanceof Messager) {
messager = (Messager) log;
} else {
PrintWriter out = context.get(Log.errKey);
messager = (out == null)
? new Messager(context, ProgramName)
: new Messager(context, ProgramName, out, out);
}
options = getToolOptions();
}
/**
* Usage
*/
@Override
void usage() {
usage("main.usage", OptionKind.STANDARD, "main.usage.foot");
private ToolOptions getToolOptions() {
ToolOptions.ShowHelper helper = new ToolOptions.ShowHelper() {
@Override
public void usage() {
showUsage("main.usage", ToolOption.Kind.STANDARD, "main.usage.foot");
}
@Override
public void Xusage() {
showUsage("main.Xusage", ToolOption.Kind.EXTENDED, "main.Xusage.foot");
}
@Override
public void version() {
showVersion("javadoc.version", "release");
}
@Override
public void fullVersion() {
showVersion("javadoc.fullversion", "full");
}
};
return new ToolOptions(context, messager, helper);
}
@Override
void Xusage() {
usage("main.Xusage", OptionKind.EXTENDED, "main.Xusage.foot");
private void showUsage() {
showUsage("main.usage", ToolOption.Kind.STANDARD, "main.usage.foot");
}
@Override
void version() {
messager.notice("javadoc.version", messager.programName, version("release"));
}
@Override
void fullVersion() {
messager.notice("javadoc.fullversion", messager.programName, version("full"));
}
private void usage(String headerKey, OptionKind kind, String footerKey) {
private void showUsage(String headerKey, ToolOption.Kind kind, String footerKey) {
messager.notice(headerKey);
showToolOptions(kind);
@ -196,7 +191,7 @@ public class Start extends ToolOption.Helper {
if (docletClass != null) {
String name = doclet.getName();
messager.notice("main.doclet.usage.header", name);
showDocletOptions(kind == OptionKind.EXTENDED
showDocletOptions(kind == ToolOption.Kind.EXTENDED
? Option.Kind.EXTENDED
: Option.Kind.STANDARD);
}
@ -207,7 +202,11 @@ public class Start extends ToolOption.Helper {
private static final String versionRBName = "jdk.javadoc.internal.tool.resources.version";
private static ResourceBundle versionRB;
private static String version(String key) {
private void showVersion(String labelKey, String versionKey) {
messager.notice(labelKey, messager.programName, getVersion(versionKey));
}
private static String getVersion(String key) {
if (versionRB == null) {
try {
versionRB = ResourceBundle.getBundle(versionRBName);
@ -222,7 +221,7 @@ public class Start extends ToolOption.Helper {
}
}
void showToolOptions(OptionKind kind) {
private void showToolOptions(ToolOption.Kind kind) {
Comparator<ToolOption> comp = new Comparator<ToolOption>() {
final Collator collator = Collator.getInstance(Locale.US);
{ collator.setStrength(Collator.PRIMARY); }
@ -233,26 +232,27 @@ public class Start extends ToolOption.Helper {
}
};
Stream.of(ToolOption.values())
options.getSupportedOptions().stream()
.filter(opt -> opt.kind == kind)
.sorted(comp)
.forEach(this::showToolOption);
}
void showToolOption(ToolOption option) {
private void showToolOption(ToolOption option) {
List<String> names = option.getNames();
String primaryName = option.primaryName;
String parameters;
if (option.hasArg || option.primaryName.endsWith(":")) {
String sep = (option == ToolOption.J) || option.primaryName.endsWith(":") ? "" : " ";
if (option.hasArg || primaryName.endsWith(":")) {
String sep = primaryName.equals(ToolOptions.J) || primaryName.endsWith(":") ? "" : " ";
parameters = sep + option.getParameters(messager);
} else {
parameters = "";
}
String description = option.getDescription(messager);
showUsage(names, parameters, description);
showOption(names, parameters, description);
}
void showDocletOptions(Option.Kind kind) {
private void showDocletOptions(Option.Kind kind) {
Comparator<Doclet.Option> comp = new Comparator<Doclet.Option>() {
final Collator collator = Collator.getInstance(Locale.US);
{ collator.setStrength(Collator.PRIMARY); }
@ -269,18 +269,18 @@ public class Start extends ToolOption.Helper {
.forEach(this::showDocletOption);
}
void showDocletOption(Doclet.Option option) {
private void showDocletOption(Doclet.Option option) {
List<String> names = option.getNames();
String parameters;
String optname = names.get(0);
if (option.getArgumentCount() > 0 || optname.endsWith(":")) {
String sep = optname.endsWith(":") ? "" : " ";
String primaryName = names.get(0);
if (option.getArgumentCount() > 0 || primaryName.endsWith(":")) {
String sep = primaryName.endsWith(":") ? "" : " ";
parameters = sep + option.getParameters();
} else {
parameters = "";
}
String description = option.getDescription();
showUsage(names, parameters, description);
showOption(names, parameters, description);
}
// The following constants are intended to format the output to
@ -297,7 +297,7 @@ public class Start extends ToolOption.Helper {
/** The format for a single-line help entry. */
private static final String COMPACT_FORMAT = SMALL_INDENT + "%-" + DEFAULT_SYNOPSIS_WIDTH + "s %s";
void showUsage(List<String> names, String parameters, String description) {
void showOption(List<String> names, String parameters, String description) {
String synopses = names.stream()
.map(s -> s + parameters)
.collect(Collectors.joining(", "));
@ -358,7 +358,6 @@ public class Start extends ToolOption.Helper {
return begin(opts, fileObjects).isOK();
}
@SuppressWarnings("removal")
private Result begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
fileManager = context.get(JavaFileManager.class);
if (fileManager == null) {
@ -438,7 +437,7 @@ public class Start extends ToolOption.Helper {
} catch (IOException ignore) {}
}
boolean haveErrorWarnings = messager.hasErrors()
|| (rejectWarnings && messager.hasWarnings());
|| (this.options.rejectWarnings() && messager.hasWarnings());
if (!result.isOK() && !haveErrorWarnings) {
// the doclet failed, but nothing reported, flag it!.
error("main.unknown.error");
@ -462,7 +461,7 @@ public class Start extends ToolOption.Helper {
}
private void dumpStack(boolean enabled, Throwable t) {
if (t != null && (enabled || dumpOnError)) {
if (t != null && (enabled || options.dumpOnError())) {
t.printStackTrace(System.err);
}
}
@ -470,18 +469,15 @@ public class Start extends ToolOption.Helper {
/**
* Main program - internal
*/
@SuppressWarnings("unchecked")
private Result parseAndExecute(List<String> argList, Iterable<? extends JavaFileObject> fileObjects)
throws ToolException, OptionException, com.sun.tools.javac.main.Option.InvalidValueException {
long tm = System.currentTimeMillis();
List<String> javaNames = new ArrayList<>();
compOpts = Options.instance(context);
// Make sure no obsolete source/target messages are reported
try {
com.sun.tools.javac.main.Option.XLINT_CUSTOM.process(getOptionHelper(), "-Xlint:-options");
options.processCompilerOption(com.sun.tools.javac.main.Option.XLINT_CUSTOM, "-Xlint:-options");
} catch (com.sun.tools.javac.main.Option.InvalidValueException ignore) {
}
@ -511,22 +507,19 @@ public class Start extends ToolOption.Helper {
}
if (fileManager instanceof BaseFileManager) {
((BaseFileManager) fileManager).handleOptions(fileManagerOpts);
((BaseFileManager) fileManager).handleOptions(options.fileManagerOptions());
}
if (fileManager.isSupportedOption(MULTIRELEASE.primaryName) == 1) {
String mr = com.sun.tools.javac.main.Option.MULTIRELEASE.primaryName;
if (fileManager.isSupportedOption(mr) == 1) {
Target target = Target.instance(context);
List<String> list = List.of(target.multiReleaseValue());
fileManager.handleOption(MULTIRELEASE.primaryName, list.iterator());
fileManager.handleOption(mr, list.iterator());
}
compOpts.notifyListeners();
List<String> modules = (List<String>) jdtoolOpts.computeIfAbsent(ToolOption.MODULE,
s -> Collections.EMPTY_LIST);
options.compilerOptions().notifyListeners();
if (modules.isEmpty()) {
List<String> subpkgs = (List<String>) jdtoolOpts.computeIfAbsent(ToolOption.SUBPACKAGES,
s -> Collections.EMPTY_LIST);
if (subpkgs.isEmpty()) {
if (options.modules().isEmpty()) {
if (options.subpackages().isEmpty()) {
if (javaNames.isEmpty() && isEmpty(fileObjects)) {
String text = messager.getText("main.No_modules_packages_or_classes_specified");
throw new ToolException(CMDERR, text);
@ -537,14 +530,12 @@ public class Start extends ToolOption.Helper {
JavadocTool comp = JavadocTool.make0(context);
if (comp == null) return ABNORMAL;
DocletEnvironment docEnv = comp.getEnvironment(jdtoolOpts,
javaNames,
fileObjects);
DocletEnvironment docEnv = comp.getEnvironment(options, javaNames, fileObjects);
// release resources
comp = null;
if (breakiterator || !locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
if (options.breakIterator() || !locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
JavacTrees trees = JavacTrees.instance(context);
trees.setBreakIterator(BreakIterator.getSentenceInstance(locale));
}
@ -554,7 +545,7 @@ public class Start extends ToolOption.Helper {
: ERROR;
// We're done.
if (compOpts.get("-verbose") != null) {
if (options.verbose()) {
tm = System.currentTimeMillis() - tm;
messager.notice("main.done_in", Long.toString(tm));
}
@ -578,8 +569,8 @@ public class Start extends ToolOption.Helper {
return matches(option.getNames(), targ);
}
Set<? extends Doclet.Option> docletOptions = null;
int handleDocletOptions(int idx, List<String> args, boolean isToolOption)
private Set<? extends Doclet.Option> docletOptions = null;
int handleDocletOption(int idx, List<String> args, boolean isToolOption)
throws OptionException {
if (docletOptions == null) {
docletOptions = doclet.getSupportedOptions();
@ -601,18 +592,18 @@ public class Start extends ToolOption.Helper {
switch (opt.getArgumentCount()) {
case 0:
text = messager.getText("main.unnecessary_arg_provided", argBase);
throw new OptionException(ERROR, this::usage, text);
throw new OptionException(ERROR, this::showUsage, text);
case 1:
opt.process(arg, Arrays.asList(argVal));
break;
default:
text = messager.getText("main.only_one_argument_with_equals", argBase);
throw new OptionException(ERROR, this::usage, text);
throw new OptionException(ERROR, this::showUsage, text);
}
} else {
if (args.size() - idx -1 < opt.getArgumentCount()) {
text = messager.getText("main.requires_argument", arg);
throw new OptionException(ERROR, this::usage, text);
throw new OptionException(ERROR, this::showUsage, text);
}
opt.process(arg, args.subList(idx + 1, args.size()));
idx += opt.getArgumentCount();
@ -623,13 +614,13 @@ public class Start extends ToolOption.Helper {
// check if arg is accepted by the tool before emitting error
if (!isToolOption) {
text = messager.getText("main.invalid_flag", arg);
throw new OptionException(ERROR, this::usage, text);
throw new OptionException(ERROR, this::showUsage, text);
}
return idx;
}
private Doclet preprocess(JavaFileManager jfm,
List<String> argv) throws ToolException, OptionException {
private Doclet preprocess(JavaFileManager jfm, List<String> argv)
throws ToolException, OptionException {
// doclet specifying arguments
String userDocletPath = null;
String userDocletName = null;
@ -642,13 +633,13 @@ public class Start extends ToolOption.Helper {
// Step 1: loop through the args, set locale early on, if found.
for (int i = 0 ; i < argv.size() ; i++) {
String arg = argv.get(i);
if (arg.equals(ToolOption.DUMPONERROR.primaryName)) {
dumpOnError = true;
} else if (arg.equals(ToolOption.LOCALE.primaryName)) {
if (arg.equals(ToolOptions.DUMP_ON_ERROR)) {
options.setDumpOnError(true);
} else if (arg.equals(ToolOptions.LOCALE)) {
checkOneArg(argv, i++);
String lname = argv.get(i);
locale = getLocale(lname);
} else if (arg.equals(ToolOption.DOCLET.primaryName)) {
} else if (arg.equals(ToolOptions.DOCLET)) {
checkOneArg(argv, i++);
if (userDocletName != null) {
if (apiMode) {
@ -669,7 +660,7 @@ public class Start extends ToolOption.Helper {
throw new ToolException(CMDERR, text);
}
userDocletName = argv.get(i);
} else if (arg.equals(ToolOption.DOCLETPATH.primaryName)) {
} else if (arg.equals(ToolOptions.DOCLET_PATH)) {
checkOneArg(argv, i++);
if (userDocletPath == null) {
userDocletPath = argv.get(i);
@ -685,10 +676,9 @@ public class Start extends ToolOption.Helper {
}
}
// Step 3: doclet name specified ? if so find a ClassLoader,
// and load it.
if(docletClass == null) {
if (docletClass == null) {
if (userDocletName != null) {
ClassLoader cl = classLoader;
if (cl == null) {
@ -728,13 +718,11 @@ public class Start extends ToolOption.Helper {
} else if (docletName != null){
docletClass = loadDocletClass(docletName, getClass().getClassLoader());
} else {
docletClass = StdDoclet;
docletClass = StandardDoclet.class;
}
}
if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
// no need to dispatch to old, safe to init now
initMessager();
messager.setLocale(locale);
try {
Object o = docletClass.getConstructor().newInstance();
@ -769,22 +757,22 @@ public class Start extends ToolOption.Helper {
OptionException, com.sun.tools.javac.main.Option.InvalidValueException {
for (int i = 0 ; i < args.size() ; i++) {
String arg = args.get(i);
ToolOption o = ToolOption.get(arg);
ToolOption o = options.getOption(arg);
if (o != null) {
// handle a doclet argument that may be needed however
// don't increment the index, and allow the tool to consume args
handleDocletOptions(i, args, true);
handleDocletOption(i, args, true);
if (o.hasArg) {
if (arg.startsWith("--") && arg.contains("=")) {
o.process(this, arg.substring(arg.indexOf('=') + 1));
o.process(arg.substring(arg.indexOf('=') + 1));
} else {
checkOneArg(args, i++);
o.process(this, args.get(i));
o.process(args.get(i));
}
} else if (o.hasSuffix) {
o.process(this, arg);
o.process(arg);
} else {
o.process(this);
o.process();
}
} else if (arg.startsWith("-XD")) {
// hidden javac options
@ -792,9 +780,9 @@ public class Start extends ToolOption.Helper {
int eq = s.indexOf('=');
String key = (eq < 0) ? s : s.substring(0, eq);
String value = (eq < 0) ? s : s.substring(eq+1);
compOpts.put(key, value);
options.compilerOptions().put(key, value);
} else if (arg.startsWith("-")) {
i = handleDocletOptions(i, args, false);
i = handleDocletOption(i, args, false);
} else {
javaNames.add(arg);
}
@ -812,7 +800,7 @@ public class Start extends ToolOption.Helper {
private void checkOneArg(List<String> args, int index) throws OptionException {
if ((index + 1) >= args.size() || args.get(index + 1).startsWith("-d")) {
String text = messager.getText("main.requires_argument", args.get(index));
throw new OptionException(CMDERR, this::usage, text);
throw new OptionException(CMDERR, this::showUsage, text);
}
}
@ -859,34 +847,5 @@ public class Start extends ToolOption.Helper {
return null;
}
@Override
OptionHelper getOptionHelper() {
return new GrumpyHelper(messager) {
@Override
public String get(com.sun.tools.javac.main.Option option) {
return compOpts.get(option);
}
@Override
public void put(String name, String value) {
compOpts.put(name, value);
}
@Override
public void remove(String name) {
compOpts.remove(name);
}
@Override
public boolean handleFileManagerOption(com.sun.tools.javac.main.Option option, String value) {
fileManagerOpts.put(option, value);
return true;
}
};
}
@Override
String getLocalizedMessage(String msg, Object... args) {
return messager.getText(msg, args);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, 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
@ -158,9 +158,9 @@ public class ToolEnvironment {
elementToTreePath = new HashMap<>();
}
public void initialize(Map<ToolOption, Object> toolOpts) {
this.quiet = (boolean)toolOpts.getOrDefault(ToolOption.QUIET, false);
this.ignoreSourceErrors = (boolean)toolOpts.getOrDefault(ToolOption.IGNORE_SOURCE_ERRORS, false);
public void initialize(ToolOptions options) {
this.quiet = options.quiet();
this.ignoreSourceErrors = options.ignoreSourceErrors();
}
/**

View File

@ -1,618 +0,0 @@
/*
* Copyright (c) 2012, 2019, 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 jdk.javadoc.internal.tool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.ElementKind;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.main.Option.InvalidValueException;
import com.sun.tools.javac.main.Option.OptionKind;
import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.util.Options;
import static com.sun.tools.javac.main.Option.OptionKind.*;
import static jdk.javadoc.internal.tool.Main.Result.*;
/**
* javadoc tool options.
*
* <p><b>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.</b>
*/
public enum ToolOption {
// ----- options for underlying compiler -----
BOOTCLASSPATH("-bootclasspath", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.BOOT_CLASS_PATH.process(helper.getOptionHelper(), primaryName, arg);
}
},
CLASS_PATH("--class-path -classpath -cp", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.CLASS_PATH.process(helper.getOptionHelper(), primaryName, arg);
}
},
EXTDIRS("-extdirs", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.EXTDIRS.process(helper.getOptionHelper(), primaryName, arg);
}
},
SOURCE_PATH("--source-path -sourcepath", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.SOURCE_PATH.process(helper.getOptionHelper(), primaryName, arg);
}
},
MODULE_SOURCE_PATH("--module-source-path", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.MODULE_SOURCE_PATH.process(helper.getOptionHelper(), primaryName, arg);
}
},
UPGRADE_MODULE_PATH("--upgrade-module-path", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.UPGRADE_MODULE_PATH.process(helper.getOptionHelper(), primaryName, arg);
}
},
SYSTEM("--system", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.SYSTEM.process(helper.getOptionHelper(), primaryName, arg);
}
},
MODULE_PATH("--module-path -p", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.MODULE_PATH.process(helper.getOptionHelper(), primaryName, arg);
}
},
ADD_MODULES("--add-modules", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.ADD_MODULES.process(helper.getOptionHelper(), primaryName, arg);
}
},
LIMIT_MODULES("--limit-modules", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.LIMIT_MODULES.process(helper.getOptionHelper(), primaryName, arg);
}
},
MODULE("--module", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
helper.addToList(this, ",", arg);
}
},
ENCODING("-encoding", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.ENCODING.process(helper.getOptionHelper(), primaryName, arg);
}
},
RELEASE("--release", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.RELEASE.process(helper.getOptionHelper(), primaryName, arg);
}
},
SOURCE("--source -source", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.SOURCE.process(helper.getOptionHelper(), primaryName, arg);
Option.TARGET.process(helper.getOptionHelper(), Option.TARGET.primaryName, arg);
}
},
XMAXERRS("-Xmaxerrs", EXTENDED, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.XMAXERRS.process(helper.getOptionHelper(), primaryName, arg);
}
},
XMAXWARNS("-Xmaxwarns", EXTENDED, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.XMAXWARNS.process(helper.getOptionHelper(), primaryName, arg);
}
},
ADD_READS("--add-reads", EXTENDED, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.ADD_READS.process(helper.getOptionHelper(), primaryName, arg);
}
},
ADD_EXPORTS("--add-exports", EXTENDED, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.ADD_EXPORTS.process(helper.getOptionHelper(), primaryName, arg);
}
},
PATCH_MODULE("--patch-module", EXTENDED, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.PATCH_MODULE.process(helper.getOptionHelper(), primaryName, arg);
}
},
ADD_OPENS("--add-opens", HIDDEN, true) {
@Override
public void process(Helper helper, String arg) throws InvalidValueException {
Option.ADD_OPENS.process(helper.getOptionHelper(), primaryName, arg);
}
},
ENABLE_PREVIEW("--enable-preview", STANDARD) {
@Override
public void process(Helper helper) throws InvalidValueException {
Option.PREVIEW.process(helper.getOptionHelper(), primaryName);
}
},
// ----- doclet options -----
DOCLET("-doclet", STANDARD, true), // handled in setDocletInvoker
DOCLETPATH("-docletpath", STANDARD, true), // handled in setDocletInvoker
// ----- selection options -----
SUBPACKAGES("-subpackages", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
helper.addToList(this, ":", arg);
}
},
EXCLUDE("-exclude", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
helper.addToList(this, ":", arg);
}
},
// ----- filtering options -----
PACKAGE("-package", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("package");
}
},
PRIVATE("-private", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("private");
}
},
PROTECTED("-protected", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("protected");
}
},
PUBLIC("-public", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
helper.setSimpleFilter("public");
}
},
SHOW_MEMBERS("--show-members", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws OptionException {
helper.setFilter(this, arg);
}
},
SHOW_TYPES("--show-types", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws OptionException {
helper.setFilter(this, arg);
}
},
SHOW_PACKAGES("--show-packages", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws OptionException {
helper.setShowPackageAccess(SHOW_PACKAGES, arg);
}
},
SHOW_MODULE_CONTENTS("--show-module-contents", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws OptionException {
helper.setShowModuleContents(SHOW_MODULE_CONTENTS, arg);
}
},
EXPAND_REQUIRES("--expand-requires", STANDARD, true) {
@Override
public void process(Helper helper, String arg) throws OptionException {
helper.setExpandRequires(EXPAND_REQUIRES, arg);
}
},
// ----- output control options -----
QUIET("-quiet", STANDARD) {
@Override
public void process(Helper helper) {
helper.jdtoolOpts.put(QUIET, true);
}
},
VERBOSE("-verbose", STANDARD) {
@Override
public void process(Helper helper) {
helper.compOpts.put("-verbose", "");
}
},
XWERROR("-Xwerror", HIDDEN) {
@Override
public void process(Helper helper) {
helper.rejectWarnings = true;
}
},
// ----- other options -----
BREAKITERATOR("-breakiterator", STANDARD) {
@Override
public void process(Helper helper) {
helper.breakiterator = true;
}
},
LOCALE("-locale", STANDARD, true) {
@Override
public void process(Helper helper, String arg) {
helper.docLocale = arg;
}
},
XCLASSES("-Xclasses", HIDDEN) {
@Override
public void process(Helper helper) {
helper.jdtoolOpts.put(XCLASSES, true);
}
},
DUMPONERROR("--dump-on-error", HIDDEN) {
@Override
public void process(Helper helper) {
helper.dumpOnError = true;
}
},
IGNORE_SOURCE_ERRORS("--ignore-source-errors", HIDDEN) {
@Override
public void process(Helper helper) {
helper.jdtoolOpts.put(IGNORE_SOURCE_ERRORS, true);
}
},
// ----- help options -----
HELP("--help -help -? -h", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
throw new OptionException(OK, helper::usage);
}
},
HELP_EXTRA("--help-extra -X", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
throw new OptionException(OK, helper::Xusage);
}
},
// This option exists only for the purpose of documenting itself.
// It's actually implemented by the launcher.
J("-J", STANDARD, true) {
@Override
public void process(Helper helper) {
throw new AssertionError("the -J flag should be caught by the launcher.");
}
},
VERSION("--version", STANDARD) {
@Override
public void process(Helper helper) throws OptionException {
throw new OptionException(OK, helper::version);
}
},
FULLVERSION("--full-version", HIDDEN) {
@Override
public void process(Helper helper) throws OptionException {
throw new OptionException(OK, helper::fullVersion);
}
};
public final String primaryName;
public final List<String> names;
public final OptionKind kind;
public final boolean hasArg;
public final boolean hasSuffix; // ex: foo:bar or -foo=bar
ToolOption(String opt, OptionKind kind) {
this(opt, kind, false);
}
ToolOption(String names, OptionKind kind, boolean hasArg) {
this.names = Arrays.asList(names.split("\\s+"));
this.primaryName = this.names.get(0);
this.kind = kind;
this.hasArg = hasArg;
char lastChar = names.charAt(names.length() - 1);
this.hasSuffix = lastChar == ':' || lastChar == '=';
}
void process(Helper helper, String arg) throws OptionException, Option.InvalidValueException { }
void process(Helper helper) throws OptionException, Option.InvalidValueException { }
List<String> getNames() {
return names;
}
String getParameters(Messager messager) {
return (hasArg || primaryName.endsWith(":"))
? messager.getText(getKey(primaryName, ".arg"))
: null;
}
String getDescription(Messager messager) {
return messager.getText(getKey(primaryName, ".desc"));
}
private String getKey(String optionName, String suffix) {
return "main.opt."
+ optionName
.replaceAll("^-*", "") // remove leading '-'
.replaceAll("[^A-Za-z0-9]+$", "") // remove trailing non-alphanumeric
.replaceAll("[^A-Za-z0-9]", ".") // replace internal non-alphanumeric
+ suffix;
}
static ToolOption get(String name) {
String oname = name;
if (name.startsWith("--") && name.contains("=")) {
oname = name.substring(0, name.indexOf('='));
}
for (ToolOption o : values()) {
for (String n : o.names) {
if (oname.equals(n)) {
return o;
}
}
}
return null;
}
abstract static class Helper {
// File manager options
final Map<Option, String> fileManagerOpts = new LinkedHashMap<>();
/** javac options, set by various options. */
Options compOpts; // = Options.instance(context)
/** Javadoc tool options */
final Map<ToolOption, Object> jdtoolOpts = new EnumMap<>(ToolOption.class);
/** dump stack traces for debugging etc.*/
boolean dumpOnError = false;
/** Set by -breakiterator. */
boolean breakiterator = false;
/** Set by -Xwerror. */
boolean rejectWarnings = false;
/** Set by -prompt. */
boolean promptOnError;
/** Set by -locale. */
String docLocale = "";
Helper() {
populateDefaultAccessMap();
}
abstract void usage();
abstract void Xusage();
abstract void version();
abstract void fullVersion();
abstract String getLocalizedMessage(String msg, Object... args);
abstract OptionHelper getOptionHelper();
@SuppressWarnings("unchecked")
void addToList(ToolOption opt, String delimiter, String str) {
List<String> list = (List<String>) jdtoolOpts.computeIfAbsent(opt, v -> new ArrayList<>());
list.addAll(Arrays.asList(str.split(delimiter)));
jdtoolOpts.put(opt, list);
}
void setExpandRequires(ToolOption opt, String arg) throws OptionException {
switch (arg) {
case "transitive":
jdtoolOpts.put(opt, AccessKind.PUBLIC);
break;
case "all":
jdtoolOpts.put(opt, AccessKind.PRIVATE);
break;
default:
String text = getLocalizedMessage("main.illegal_option_value", arg);
throw new IllegalOptionValue(this::usage, text);
}
}
void setShowModuleContents(ToolOption opt, String arg) throws OptionException {
switch (arg) {
case "api":
jdtoolOpts.put(opt, AccessKind.PUBLIC);
break;
case "all":
jdtoolOpts.put(opt, AccessKind.PRIVATE);
break;
default:
String text = getLocalizedMessage("main.illegal_option_value", arg);
throw new IllegalOptionValue(this::usage, text);
}
}
void setShowPackageAccess(ToolOption opt, String arg) throws OptionException {
switch (arg) {
case "exported":
jdtoolOpts.put(opt, AccessKind.PUBLIC);
break;
case "all":
jdtoolOpts.put(opt, AccessKind.PRIVATE);
break;
default:
String text = getLocalizedMessage("main.illegal_option_value", arg);
throw new IllegalOptionValue(this::usage, text);
}
}
void setFilter(ToolOption opt, String arg) throws OptionException {
jdtoolOpts.put(opt, getAccessValue(arg));
}
void setSimpleFilter(String arg) throws OptionException {
handleSimpleOption(arg);
}
void setFileManagerOpt(Option opt, String arg) {
fileManagerOpts.put(opt, arg);
}
void handleSimpleOption(String arg) throws OptionException {
populateSimpleAccessMap(getAccessValue(arg));
}
/*
* This method handles both the simple options -package,
* -private, so on, in addition to the new ones such as
* --show-types:public and so on.
*/
private AccessKind getAccessValue(String arg) throws OptionException {
int colon = arg.indexOf(':');
String value = (colon > 0)
? arg.substring(colon + 1)
: arg;
switch (value) {
case "public":
return AccessKind.PUBLIC;
case "protected":
return AccessKind.PROTECTED;
case "package":
return AccessKind.PACKAGE;
case "private":
return AccessKind.PRIVATE;
default:
String text = getLocalizedMessage("main.illegal_option_value", value);
throw new IllegalOptionValue(this::usage, text);
}
}
/*
* Sets the entire kind map to PROTECTED this is the default.
*/
private void populateDefaultAccessMap() {
populateSimpleAccessMap(AccessKind.PROTECTED);
}
/*
* This sets access to all the allowed kinds in the
* access map.
*/
void populateSimpleAccessMap(AccessKind accessValue) {
for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) {
switch (kind) {
case METHOD:
jdtoolOpts.put(SHOW_MEMBERS, accessValue);
break;
case CLASS:
jdtoolOpts.put(SHOW_TYPES, accessValue);
break;
case PACKAGE:
jdtoolOpts.put(SHOW_PACKAGES, accessValue);
break;
case MODULE:
jdtoolOpts.put(SHOW_MODULE_CONTENTS, accessValue);
break;
default:
throw new AssertionError("unknown element kind:" + kind);
}
}
}
}
}

View File

@ -0,0 +1,990 @@
/*
* Copyright (c) 2012, 2020, 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 jdk.javadoc.internal.tool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.ElementKind;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.main.Option.InvalidValueException;
import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Options;
import static jdk.javadoc.internal.tool.Main.Result.OK;
import static jdk.javadoc.internal.tool.ToolOptions.ToolOption.Kind.*;
/**
* Storage and support for javadoc tool options, as distinct from
* the options supported by any doclet that may be in use.
* The tool options includes those options which are delegated
* to javac and/or the file manager, such as options to set
* the source level, and path options to locate the files to be
* documented.
*
* <p><b>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.</b>
*/
public class ToolOptions {
// The following are the names of options handled in the first pass of option decoding,
// in Start.preprocess.
static final String DOCLET = "-doclet";
static final String DOCLET_PATH = "-docletpath";
static final String DUMP_ON_ERROR = "--dump-on-error";
static final String J = "-J";
static final String LOCALE = "-locale";
/**
* Argument for command-line option {@code -breakiterator}.
*/
private boolean breakIterator = false;
/**
* Argument for command-line option {@code -locale}.
*/
private String docLocale = "";
/**
* Argument for command-line option {@code --dump-on-error}.
* Dump stack traces for debugging etc.
* Similar to javac {@code -doe}.
*/
private boolean dumpOnError = false;
/**
* Argument for command-line option {@code -exclude}.
*/
private List<String> excludes = new ArrayList<>();
/**
* Argument for command-line option {@code --expand-requires}.
*/
private AccessKind expandRequires;
/**
* Argument for command-line option {@code --ignore-source-errors}.
*/
private boolean ignoreSourceErrors;
/**
* Argument for command-line option {@code --module}.
*/
private List<String> modules = new ArrayList<>();
/**
* Argument for command-line option {@code -Xwerror}.
* Set by -Xwerror.
*/
private boolean rejectWarnings = false;
/**
* Argument for command-line option {@code --show-members}.
*/
private AccessKind showMembersAccess;
/**
* Argument for command-line option {@code --show-types}.
*/
private AccessKind showTypesAccess;
/**
* Argument for command-line option {@code --show-packages}.
*/
private AccessKind showPackagesAccess;
/**
* Argument for command-line option {@code --show-module-contents}.
*/
private AccessKind showModuleContents;
/**
* Argument for command-line option {@code -quiet}.
*/
private boolean quiet;
/**
* Argument for command-line option {@code -subpackages}.
*/
private List<String> subpackages = new ArrayList<>();
/**
* Argument for command-line option {@code -verbose}.
*/
private boolean verbose;
/**
* Argument for command-line option {@code -xclasses}.
* If true, names on the command line that would normally be
* treated as package names are treated as class names instead.
*/
private boolean xclasses = false;
/**
* Options to be given to the file manager, such as path options
* indicating where to find files to be documented.
*/
private final Map<Option, String> fileManagerOpts;
/**
* Options to be given to the underlying compiler front-end,
* such as options to indicate the source level to be used.
*/
private final Options compOpts;
/**
* The "helper" to be used when processing compiler options.
*/
private final OptionHelper compilerOptionHelper;
/**
* The messager to be used to report diagnostics..
*/
private final Messager messager;
/**
* The helper for help and version options
*/
private final ShowHelper showHelper;
/**
* Creates an object to handle tool options.
*
* @param context the context used to find other tool-related components
* @param messager the messager to be used to report diagnostics
*/
ToolOptions(Context context, Messager messager, ShowHelper showHelper) {
this.messager = messager;
this.showHelper = showHelper;
compOpts = Options.instance(context);
fileManagerOpts = new LinkedHashMap<>();
compilerOptionHelper = getOptionHelper();
setAccessDefault();
}
/**
* Creates a minimal object, just sufficient to check the names of the
* supported options.
*/
private ToolOptions() {
compOpts = null;
compilerOptionHelper = null;
fileManagerOpts = null;
messager = null;
showHelper = null;
}
/**
* Returns the set of options supported by the tool, excluding any options
* that are managed by the doclet that may be in use.
*
* @return the set of options
*/
public List<ToolOption> getSupportedOptions() {
return supportedOptions;
}
/**
* Determines if the given option is supported and if so, the
* number of arguments the option takes.
*
* @param option an option
* @return the number of arguments the given option takes or -1 if
* the option is not supported
* @see javax.tools.DocumentationTool#isSupportedOption(String)
*/
public static int isSupportedOption(String option) {
ToolOptions t = new ToolOptions();
for (ToolOption o : t.supportedOptions) {
for (String name : o.names) {
if (name.equals(option))
return o.hasArg ? 1 : 0;
}
}
return -1;
}
/**
* Returns the option to be used to process an argument such as may be found on
* the command line.
*
* @param arg the argument
* @return the option
*/
ToolOption getOption(String arg) {
String name = arg;
if (arg.startsWith("--") && arg.contains("=")) {
name = arg.substring(0, arg.indexOf('='));
}
for (ToolOption o : supportedOptions) {
for (String n : o.names) {
if (name.equals(n)) {
return o;
}
}
}
return null;
}
private List<ToolOption> supportedOptions = List.of(
// ----- options for underlying compiler -----
new ToolOption("-bootclasspath", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.BOOT_CLASS_PATH, primaryName, arg);
}
},
new ToolOption("--class-path -classpath -cp", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.CLASS_PATH, primaryName, arg);
}
},
new ToolOption("-extdirs", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.EXTDIRS, primaryName, arg);
}
},
new ToolOption("--source-path -sourcepath", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.SOURCE_PATH, primaryName, arg);
}
},
new ToolOption("--module-source-path", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.MODULE_SOURCE_PATH, primaryName, arg);
}
},
new ToolOption("--upgrade-module-path", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.UPGRADE_MODULE_PATH, primaryName, arg);
}
},
new ToolOption("--system", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.SYSTEM, primaryName, arg);
}
},
new ToolOption("--module-path -p", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.MODULE_PATH, primaryName, arg);
}
},
new ToolOption("--add-modules", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.ADD_MODULES, primaryName, arg);
}
},
new ToolOption("--limit-modules", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.LIMIT_MODULES, primaryName, arg);
}
},
new ToolOption("--module", STANDARD, true) {
@Override
public void process(String arg) {
modules.addAll(List.of(arg.split(",")));
}
},
new ToolOption("-encoding", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.ENCODING, primaryName, arg);
}
},
new ToolOption("--release", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.RELEASE, primaryName, arg);
}
},
new ToolOption("--source -source", STANDARD, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.SOURCE, primaryName, arg);
processCompilerOption(Option.TARGET, Option.TARGET.primaryName, arg);
}
},
new ToolOption("-Xmaxerrs", EXTENDED, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.XMAXERRS, primaryName, arg);
}
},
new ToolOption("-Xmaxwarns", EXTENDED, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.XMAXWARNS, primaryName, arg);
}
},
new ToolOption("--add-reads", EXTENDED, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.ADD_READS, primaryName, arg);
}
},
new ToolOption("--add-exports", EXTENDED, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.ADD_EXPORTS, primaryName, arg);
}
},
new ToolOption("--patch-module", EXTENDED, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.PATCH_MODULE, primaryName, arg);
}
},
new ToolOption("--add-opens", HIDDEN, true) {
@Override
public void process(String arg) throws InvalidValueException {
processCompilerOption(Option.ADD_OPENS, primaryName, arg);
}
},
new ToolOption("--enable-preview", STANDARD) {
@Override
public void process() throws InvalidValueException {
processCompilerOption(Option.PREVIEW, primaryName);
}
},
// ----- doclet options -----
new ToolOption(DOCLET, STANDARD, true), // handled in setDocletInvoker
new ToolOption(DOCLET_PATH, STANDARD, true), // handled in setDocletInvoker
// ----- selection options -----
new ToolOption("-subpackages", STANDARD, true) {
@Override
public void process(String arg) {
subpackages.addAll(List.of(arg.split(":")));
}
},
new ToolOption("-exclude", STANDARD, true) {
@Override
public void process(String arg) {
excludes.addAll(List.of(arg.split(":")));
}
},
// ----- filtering options -----
new ToolOption("-package", STANDARD) {
@Override
public void process() throws OptionException {
setSimpleFilter("package");
}
},
new ToolOption("-private", STANDARD) {
@Override
public void process() throws OptionException {
setSimpleFilter("private");
}
},
new ToolOption("-protected", STANDARD) {
@Override
public void process() throws OptionException {
setSimpleFilter("protected");
}
},
new ToolOption("-public", STANDARD) {
@Override
public void process() throws OptionException {
setSimpleFilter("public");
}
},
new ToolOption("--show-members", STANDARD, true) {
@Override
public void process(String arg) throws OptionException {
setShowMembersAccess(arg);
}
},
new ToolOption("--show-types", STANDARD, true) {
@Override
public void process(String arg) throws OptionException {
setShowTypesAccess(arg);
}
},
new ToolOption("--show-packages", STANDARD, true) {
@Override
public void process(String arg) throws OptionException {
setShowPackageAccess(arg);
}
},
new ToolOption("--show-module-contents", STANDARD, true) {
@Override
public void process(String arg) throws OptionException {
setShowModuleContents(arg);
}
},
new ToolOption("--expand-requires", STANDARD, true) {
@Override
public void process(String arg) throws OptionException {
setExpandRequires(arg);
}
},
// ----- output control options -----
new ToolOption("-quiet", STANDARD) {
@Override
public void process() {
quiet = true;
}
},
new ToolOption("-verbose", STANDARD) {
@Override
public void process() {
setVerbose();
}
},
new ToolOption("-Xwerror", HIDDEN) {
@Override
public void process() {
rejectWarnings = true;
}
},
// ----- other options -----
new ToolOption("-breakiterator", STANDARD) {
@Override
public void process() {
breakIterator = true;
}
},
new ToolOption(LOCALE, STANDARD, true) {
@Override
public void process(String arg) {
docLocale = arg;
}
},
new ToolOption("-Xclasses", HIDDEN) {
@Override
public void process() {
xclasses = true;
}
},
new ToolOption(DUMP_ON_ERROR, HIDDEN) {
@Override
public void process() {
dumpOnError = true;
}
},
new ToolOption("--ignore-source-errors", HIDDEN) {
@Override
public void process() {
ignoreSourceErrors = true;
}
},
// ----- help options -----
new ToolOption("--help -help -? -h", STANDARD) {
@Override
public void process() throws OptionException {
throw new OptionException(OK, showHelper::usage);
}
},
new ToolOption("--help-extra -X", STANDARD) {
@Override
public void process() throws OptionException {
throw new OptionException(OK, showHelper::Xusage);
}
},
// This option exists only for the purpose of documenting itself.
// It's actually implemented by the launcher.
new ToolOption(J, STANDARD, true) {
@Override
public void process() {
throw new AssertionError("the -J flag should be caught by the launcher.");
}
},
new ToolOption("--version", STANDARD) {
@Override
public void process() throws OptionException {
throw new OptionException(OK, showHelper::version);
}
},
new ToolOption("--full-version", HIDDEN) {
@Override
public void process() throws OptionException {
throw new OptionException(OK, showHelper::fullVersion);
}
});
/**
* Base class for all supported tool options.
*/
static class ToolOption {
enum Kind { STANDARD, EXTENDED, HIDDEN }
final String primaryName;
final List<String> names;
final Kind kind;
final boolean hasArg;
final boolean hasSuffix; // ex: foo:bar or -foo=bar
ToolOption(String opt, Kind kind) {
this(opt, kind, false);
}
ToolOption(String names, Kind kind, boolean hasArg) {
this.names = Arrays.asList(names.split("\\s+"));
this.primaryName = this.names.get(0);
this.kind = kind;
this.hasArg = hasArg;
char lastChar = names.charAt(names.length() - 1);
this.hasSuffix = lastChar == ':' || lastChar == '=';
}
void process(String arg) throws OptionException, Option.InvalidValueException { }
void process() throws OptionException, Option.InvalidValueException { }
List<String> getNames() {
return names;
}
String getParameters(Messager messager) {
return (hasArg || primaryName.endsWith(":"))
? messager.getText(getKey(primaryName, ".arg"))
: null;
}
String getDescription(Messager messager) {
return messager.getText(getKey(primaryName, ".desc"));
}
private String getKey(String optionName, String suffix) {
return "main.opt."
+ optionName
.replaceAll("^-*", "") // remove leading '-'
.replaceAll("[^A-Za-z0-9]+$", "") // remove trailing non-alphanumeric
.replaceAll("[^A-Za-z0-9]", ".") // replace internal non-alphanumeric
+ suffix;
}
}
interface ShowHelper {
/**
* Show command-line help for the standard options, as requested by
* the {@code --help} option and its aliases.
*/
void usage();
/**
* Show command-line help for the extended options, as requested by
* the {@code --help-extended} option and its aliases.
*/
void Xusage();
/**
* Show the basic version information, as requested by the {@code --version} option.
*/
void version();
/**
* Show the full version information, as requested by the {@code --full-version} option.
*/
void fullVersion();
}
//<editor-fold desc="accessor methods">
/**
* Argument for command-line option {@code -breakiterator}.
*/
boolean breakIterator() {
return breakIterator;
}
/**
* Argument for command-line option {@code -locale}.
*/
String locale() {
return docLocale;
}
/**
* Argument for command-line option {@code --dump-on-error}.
* Dump stack traces for debugging etc.
* Similar to javac {@code -doe}.
*/
boolean dumpOnError() {
return dumpOnError;
}
void setDumpOnError(boolean v) {
dumpOnError = true;
}
/**
* Argument for command-line option {@code -exclude}.
*/
List<String> excludes() {
return excludes;
}
/**
* Argument for command-line option {@code --expand-requires}.
*/
AccessKind expandRequires() {
return expandRequires;
}
/**
* Argument for command-line option {@code --ignore-source-errors}.
*/
boolean ignoreSourceErrors() {
return ignoreSourceErrors;
}
/**
* Argument for command-line option {@code --module}.
*/
List<String> modules() {
return modules;
}
/**
* Argument for command-line option {@code -Xwerror}.
* Set by -Xwerror.
*/
boolean rejectWarnings() {
return rejectWarnings;
}
/**
* Argument for command-line option {@code --show-members}.
*/
AccessKind showMembersAccess() {
return showMembersAccess;
}
/**
* Argument for command-line option {@code --show-types}.
*/
AccessKind showTypesAccess() {
return showTypesAccess;
}
/**
* Argument for command-line option {@code --show-packages}.
*/
AccessKind showPackagesAccess() {
return showPackagesAccess;
}
/**
* Argument for command-line option {@code --show-module-contents}.
*/
AccessKind showModuleContents() {
return showModuleContents;
}
/**
* Argument for command-line option {@code -quiet}.
*/
boolean quiet() {
return quiet;
}
/**
* Argument for command-line option {@code -subpackages}.
*/
List<String> subpackages() {
return subpackages;
}
/**
* Argument for command-line option {@code -verbose}.
*/
boolean verbose() {
return verbose;
}
/**
* Argument for command-line option {@code -xclasses}.
* If true, names on the command line that would normally be
* treated as package names are treated as class names instead.
*/
boolean xclasses() {
return xclasses;
}
/**
* Returns the set of options to be used for the instance of the
* underlying compiler front-end.
*
* @return the options
*/
Options compilerOptions() {
return compOpts;
}
/**
* Returns the set of options to be used for the file manager.
*
* @return the options
*/
Map<Option, String> fileManagerOptions() {
return fileManagerOpts;
}
//</editor-fold>
/**
* Returns an {@code IllegalOptionValue} exception.
*
* @param arg the arghument to include in the detail message
* @return the exception
*/
private IllegalOptionValue illegalOptionValue(String arg) {
return new IllegalOptionValue(showHelper::usage, messager.getText("main.illegal_option_value", arg));
}
/**
* Process a compiler option.
*
* @param option the option object to process the command-line option
* @param opt the command-line option
* @throws Option.InvalidValueException if the command-line option is invalid
*/
void processCompilerOption(Option option, String opt) throws Option.InvalidValueException {
option.process(compilerOptionHelper, opt);
}
/**
* Process a compiler option.
*
* @param option the option object to process the command-line option
* @param opt the command-line option
* @param arg the argument for the command-line option
* @throws Option.InvalidValueException if the command-line option is invalid
*/
private void processCompilerOption(Option option, String opt, String arg) throws Option.InvalidValueException {
option.process(compilerOptionHelper, opt, arg);
}
/**
* Returns a "helper" to be used when processing compiler options.
* @return the helper
*/
private OptionHelper getOptionHelper() {
return new OptionHelper.GrumpyHelper(messager) {
@Override
public String get(com.sun.tools.javac.main.Option option) {
return compOpts.get(option);
}
@Override
public void put(String name, String value) {
compOpts.put(name, value);
}
@Override
public void remove(String name) {
compOpts.remove(name);
}
@Override
public boolean handleFileManagerOption(com.sun.tools.javac.main.Option option, String value) {
fileManagerOpts.put(option, value);
return true;
}
};
}
private void setExpandRequires(String arg) throws OptionException {
switch (arg) {
case "transitive":
expandRequires = AccessKind.PUBLIC;
break;
case "all":
expandRequires = AccessKind.PRIVATE;
break;
default:
throw illegalOptionValue(arg);
}
}
private void setShowModuleContents(String arg) throws OptionException {
switch (arg) {
case "api":
showModuleContents = AccessKind.PUBLIC;
break;
case "all":
showModuleContents = AccessKind.PRIVATE;
break;
default:
throw illegalOptionValue(arg);
}
}
private void setShowPackageAccess(String arg) throws OptionException {
switch (arg) {
case "exported":
showPackagesAccess = AccessKind.PUBLIC;
break;
case "all":
showPackagesAccess = AccessKind.PRIVATE;
break;
default:
throw illegalOptionValue(arg);
}
}
private void setShowTypesAccess(String arg) throws OptionException {
showTypesAccess = getAccessValue(arg);
}
private void setShowMembersAccess(String arg) throws OptionException {
showMembersAccess = getAccessValue(arg);
}
private void setSimpleFilter(String arg) throws OptionException {
setSimpleAccessOption(arg);
}
private void setVerbose() {
compOpts.put("-verbose", "");
verbose = true;
}
private void setSimpleAccessOption(String arg) throws OptionException {
setAccess(getAccessValue(arg));
}
/*
* This method handles both the simple options -package,
* -private, so on, in addition to the new ones such as
* --show-types:public and so on.
*/
private AccessKind getAccessValue(String arg) throws OptionException {
int colon = arg.indexOf(':');
String value = (colon > 0)
? arg.substring(colon + 1)
: arg;
switch (value) {
case "public":
return AccessKind.PUBLIC;
case "protected":
return AccessKind.PROTECTED;
case "package":
return AccessKind.PACKAGE;
case "private":
return AccessKind.PRIVATE;
default:
throw illegalOptionValue(value);
}
}
/*
* Sets all access members to PROTECTED; this is the default.
*/
private void setAccessDefault() {
setAccess(AccessKind.PROTECTED);
}
/*
* This sets access to all the allowed kinds in the
* access members.
*/
private void setAccess(AccessKind accessValue) {
for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) {
switch (kind) {
case METHOD:
showMembersAccess = accessValue;
break;
case CLASS:
showTypesAccess = accessValue;
break;
case PACKAGE:
showPackagesAccess = accessValue;
break;
case MODULE:
showModuleContents = accessValue;
break;
default:
throw new AssertionError("unknown element kind:" + kind);
}
}
}
}