| /* |
| * Copyright (c) 2012, 2017, 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", STANDARD, true) { |
| @Override |
| public void process(Helper helper, String arg) throws InvalidValueException { |
| Option.SOURCE.process(helper.getOptionHelper(), 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); |
| } |
| }, |
| |
| // ----- 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", 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."); |
| } |
| }, |
| |
| // This option exists only for the purpose of documenting itself. |
| // It's actually implemented ahead of the normal option decoding loop. |
| Xold("-Xold", EXTENDED) { |
| @Override |
| public void process(Helper helper) { |
| throw new AssertionError("the -Xold flag should be handled earlier."); |
| } |
| }; |
| |
| 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 { } |
| |
| 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; |
| } |
| |
| static abstract 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 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); |
| } |
| } |
| } |
| } |
| } |