10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.javadoc.internal.tool; 27 28 import java.util.ArrayList; 29 import java.util.Arrays; 30 import java.util.EnumMap; 31 import java.util.LinkedHashMap; 32 import java.util.List; 33 import java.util.Map; 34 35 import javax.lang.model.element.ElementKind; 36 37 import com.sun.tools.javac.main.Option; 38 import com.sun.tools.javac.main.Option.InvalidValueException; 39 import com.sun.tools.javac.main.Option.OptionKind; 40 import com.sun.tools.javac.main.OptionHelper; 41 import com.sun.tools.javac.util.Options; 42 43 import static com.sun.tools.javac.main.Option.OptionKind.*; 44 import static jdk.javadoc.internal.tool.Main.Result.*; 45 46 /** 47 * javadoc tool options. 48 * 49 * <p><b>This is NOT part of any supported API. 50 * If you write code that depends on this, you do so at your own risk. 51 * This code and its internal interfaces are subject to change or 52 * deletion without notice.</b> 53 */ 54 public enum ToolOption { 55 56 // ----- options for underlying compiler ----- 57 58 BOOTCLASSPATH("-bootclasspath", STANDARD, true) { 59 @Override 60 public void process(Helper helper, String arg) throws InvalidValueException { 61 Option.BOOT_CLASS_PATH.process(helper.getOptionHelper(), primaryName, arg); 62 } 63 }, 64 65 CLASS_PATH("--class-path -classpath -cp", STANDARD, true) { 66 @Override 67 public void process(Helper helper, String arg) throws InvalidValueException { 68 Option.CLASS_PATH.process(helper.getOptionHelper(), primaryName, arg); 69 } 70 }, 71 72 EXTDIRS("-extdirs", STANDARD, true) { 73 @Override 74 public void process(Helper helper, String arg) throws InvalidValueException { 75 Option.EXTDIRS.process(helper.getOptionHelper(), primaryName, arg); 76 } 77 }, 78 79 SOURCE_PATH("--source-path -sourcepath", STANDARD, true) { 80 @Override 81 public void process(Helper helper, String arg) throws InvalidValueException { 82 Option.SOURCE_PATH.process(helper.getOptionHelper(), primaryName, arg); 83 } 84 }, 85 86 MODULE_SOURCE_PATH("--module-source-path", STANDARD, true) { 87 @Override 88 public void process(Helper helper, String arg) throws InvalidValueException { 89 Option.MODULE_SOURCE_PATH.process(helper.getOptionHelper(), primaryName, arg); 90 } 91 }, 92 93 UPGRADE_MODULE_PATH("--upgrade-module-path", STANDARD, true) { 94 @Override 95 public void process(Helper helper, String arg) throws InvalidValueException { 96 Option.UPGRADE_MODULE_PATH.process(helper.getOptionHelper(), primaryName, arg); 97 } 98 }, 99 100 SYSTEM("--system", STANDARD, true) { 101 @Override 102 public void process(Helper helper, String arg) throws InvalidValueException { 103 Option.SYSTEM.process(helper.getOptionHelper(), primaryName, arg); 104 } 105 }, 106 107 MODULE_PATH("--module-path -p", STANDARD, true) { 108 @Override 109 public void process(Helper helper, String arg) throws InvalidValueException { 110 Option.MODULE_PATH.process(helper.getOptionHelper(), primaryName, arg); 111 } 112 }, 113 114 ADD_MODULES("--add-modules", STANDARD, true) { 115 @Override 116 public void process(Helper helper, String arg) throws InvalidValueException { 117 Option.ADD_MODULES.process(helper.getOptionHelper(), primaryName, arg); 118 } 119 }, 120 121 LIMIT_MODULES("--limit-modules", STANDARD, true) { 122 @Override 123 public void process(Helper helper, String arg) throws InvalidValueException { 124 Option.LIMIT_MODULES.process(helper.getOptionHelper(), primaryName, arg); 125 } 126 }, 127 128 MODULE("--module", STANDARD, true) { 129 @Override 130 public void process(Helper helper, String arg) { 131 helper.addToList(this, ",", arg); 132 } 133 }, 134 135 ENCODING("-encoding", STANDARD, true) { 136 @Override 137 public void process(Helper helper, String arg) throws InvalidValueException { 138 Option.ENCODING.process(helper.getOptionHelper(), primaryName, arg); 139 } 140 }, 141 142 RELEASE("--release", STANDARD, true) { 143 @Override 144 public void process(Helper helper, String arg) throws InvalidValueException { 145 Option.RELEASE.process(helper.getOptionHelper(), primaryName, arg); 146 } 147 }, 148 149 SOURCE("--source -source", STANDARD, true) { 150 @Override 151 public void process(Helper helper, String arg) throws InvalidValueException { 152 Option.SOURCE.process(helper.getOptionHelper(), primaryName, arg); 153 Option.TARGET.process(helper.getOptionHelper(), Option.TARGET.primaryName, arg); 154 } 155 }, 156 157 XMAXERRS("-Xmaxerrs", EXTENDED, true) { 158 @Override 159 public void process(Helper helper, String arg) throws InvalidValueException { 160 Option.XMAXERRS.process(helper.getOptionHelper(), primaryName, arg); 161 } 162 }, 163 164 XMAXWARNS("-Xmaxwarns", EXTENDED, true) { 165 @Override 166 public void process(Helper helper, String arg) throws InvalidValueException { 167 Option.XMAXWARNS.process(helper.getOptionHelper(), primaryName, arg); 168 } 169 }, 170 171 ADD_READS("--add-reads", EXTENDED, true) { 172 @Override 173 public void process(Helper helper, String arg) throws InvalidValueException { 174 Option.ADD_READS.process(helper.getOptionHelper(), primaryName, arg); 175 } 176 }, 177 178 ADD_EXPORTS("--add-exports", EXTENDED, true) { 179 @Override 180 public void process(Helper helper, String arg) throws InvalidValueException { 181 Option.ADD_EXPORTS.process(helper.getOptionHelper(), primaryName, arg); 182 } 183 }, 184 185 PATCH_MODULE("--patch-module", EXTENDED, true) { 186 @Override 187 public void process(Helper helper, String arg) throws InvalidValueException { 188 Option.PATCH_MODULE.process(helper.getOptionHelper(), primaryName, arg); 189 } 190 }, 191 192 ADD_OPENS("--add-opens", HIDDEN, true) { 193 @Override 194 public void process(Helper helper, String arg) throws InvalidValueException { 195 Option.ADD_OPENS.process(helper.getOptionHelper(), primaryName, arg); 196 } 197 }, 198 199 ENABLE_PREVIEW("--enable-preview", STANDARD) { 200 @Override 201 public void process(Helper helper) throws InvalidValueException { 202 Option.PREVIEW.process(helper.getOptionHelper(), primaryName); 203 } 204 }, 205 206 // ----- doclet options ----- 207 208 DOCLET("-doclet", STANDARD, true), // handled in setDocletInvoker 209 210 DOCLETPATH("-docletpath", STANDARD, true), // handled in setDocletInvoker 211 212 // ----- selection options ----- 213 214 SUBPACKAGES("-subpackages", STANDARD, true) { 215 @Override 216 public void process(Helper helper, String arg) { 217 helper.addToList(this, ":", arg); 218 } 219 }, 220 221 EXCLUDE("-exclude", STANDARD, true) { 222 @Override 223 public void process(Helper helper, String arg) { 224 helper.addToList(this, ":", arg); 225 } 226 }, 227 228 // ----- filtering options ----- 229 230 PACKAGE("-package", STANDARD) { 231 @Override 232 public void process(Helper helper) throws OptionException { 233 helper.setSimpleFilter("package"); 234 } 235 }, 236 237 PRIVATE("-private", STANDARD) { 238 @Override 239 public void process(Helper helper) throws OptionException { 240 helper.setSimpleFilter("private"); 241 } 242 }, 243 244 PROTECTED("-protected", STANDARD) { 245 @Override 246 public void process(Helper helper) throws OptionException { 247 helper.setSimpleFilter("protected"); 248 } 249 }, 250 251 PUBLIC("-public", STANDARD) { 252 @Override 253 public void process(Helper helper) throws OptionException { 254 helper.setSimpleFilter("public"); 255 } 256 }, 257 258 SHOW_MEMBERS("--show-members", STANDARD, true) { 259 @Override 260 public void process(Helper helper, String arg) throws OptionException { 261 helper.setFilter(this, arg); 262 } 263 }, 264 265 SHOW_TYPES("--show-types", STANDARD, true) { 266 @Override 267 public void process(Helper helper, String arg) throws OptionException { 268 helper.setFilter(this, arg); 269 } 270 }, 271 272 SHOW_PACKAGES("--show-packages", STANDARD, true) { 273 @Override 274 public void process(Helper helper, String arg) throws OptionException { 275 helper.setShowPackageAccess(SHOW_PACKAGES, arg); 276 } 277 }, 278 279 SHOW_MODULE_CONTENTS("--show-module-contents", STANDARD, true) { 280 @Override 281 public void process(Helper helper, String arg) throws OptionException { 282 helper.setShowModuleContents(SHOW_MODULE_CONTENTS, arg); 283 } 284 }, 285 286 EXPAND_REQUIRES("--expand-requires", STANDARD, true) { 287 @Override 288 public void process(Helper helper, String arg) throws OptionException { 289 helper.setExpandRequires(EXPAND_REQUIRES, arg); 290 } 291 }, 292 293 // ----- output control options ----- 294 295 QUIET("-quiet", STANDARD) { 296 @Override 297 public void process(Helper helper) { 298 helper.jdtoolOpts.put(QUIET, true); 299 } 300 }, 301 302 VERBOSE("-verbose", STANDARD) { 303 @Override 304 public void process(Helper helper) { 305 helper.compOpts.put("-verbose", ""); 306 } 307 }, 308 309 XWERROR("-Xwerror", HIDDEN) { 310 @Override 311 public void process(Helper helper) { 312 helper.rejectWarnings = true; 313 314 } 315 }, 316 317 // ----- other options ----- 318 319 BREAKITERATOR("-breakiterator", STANDARD) { 320 @Override 321 public void process(Helper helper) { 322 helper.breakiterator = true; 323 } 324 }, 325 326 LOCALE("-locale", STANDARD, true) { 327 @Override 328 public void process(Helper helper, String arg) { 329 helper.docLocale = arg; 330 } 331 }, 332 333 XCLASSES("-Xclasses", HIDDEN) { 334 @Override 335 public void process(Helper helper) { 336 helper.jdtoolOpts.put(XCLASSES, true); 337 } 338 }, 339 340 DUMPONERROR("--dump-on-error", HIDDEN) { 341 @Override 342 public void process(Helper helper) { 343 helper.dumpOnError = true; 344 } 345 }, 346 347 IGNORE_SOURCE_ERRORS("--ignore-source-errors", HIDDEN) { 348 @Override 349 public void process(Helper helper) { 350 helper.jdtoolOpts.put(IGNORE_SOURCE_ERRORS, true); 351 } 352 }, 353 354 // ----- help options ----- 355 356 HELP("--help -help -? -h", STANDARD) { 357 @Override 358 public void process(Helper helper) throws OptionException { 359 throw new OptionException(OK, helper::usage); 360 } 361 }, 362 363 HELP_EXTRA("--help-extra -X", STANDARD) { 364 @Override 365 public void process(Helper helper) throws OptionException { 366 throw new OptionException(OK, helper::Xusage); 367 } 368 }, 369 370 // This option exists only for the purpose of documenting itself. 371 // It's actually implemented by the launcher. 372 J("-J", STANDARD, true) { 373 @Override 374 public void process(Helper helper) { 375 throw new AssertionError("the -J flag should be caught by the launcher."); 376 } 377 }, 378 379 VERSION("--version", STANDARD) { 380 @Override 381 public void process(Helper helper) throws OptionException { 382 throw new OptionException(OK, helper::version); 383 } 384 }, 385 386 FULLVERSION("--full-version", HIDDEN) { 387 @Override 388 public void process(Helper helper) throws OptionException { 389 throw new OptionException(OK, helper::fullVersion); 390 } 391 }; 392 393 public final String primaryName; 394 public final List<String> names; 395 public final OptionKind kind; 396 public final boolean hasArg; 397 public final boolean hasSuffix; // ex: foo:bar or -foo=bar 398 399 ToolOption(String opt, OptionKind kind) { 400 this(opt, kind, false); 401 } 402 403 ToolOption(String names, OptionKind kind, boolean hasArg) { 404 this.names = Arrays.asList(names.split("\\s+")); 405 this.primaryName = this.names.get(0); 406 this.kind = kind; 407 this.hasArg = hasArg; 408 char lastChar = names.charAt(names.length() - 1); 409 this.hasSuffix = lastChar == ':' || lastChar == '='; 410 } 411 412 void process(Helper helper, String arg) throws OptionException, Option.InvalidValueException { } 413 414 void process(Helper helper) throws OptionException, Option.InvalidValueException { } 415 416 List<String> getNames() { 417 return names; 418 } 419 420 String getParameters(Messager messager) { 421 return (hasArg || primaryName.endsWith(":")) 422 ? messager.getText(getKey(primaryName, ".arg")) 423 : null; 424 } 425 426 String getDescription(Messager messager) { 427 return messager.getText(getKey(primaryName, ".desc")); 428 } 429 430 private String getKey(String optionName, String suffix) { 431 return "main.opt." 432 + optionName 433 .replaceAll("^-*", "") // remove leading '-' 434 .replaceAll("[^A-Za-z0-9]+$", "") // remove trailing non-alphanumeric 435 .replaceAll("[^A-Za-z0-9]", ".") // replace internal non-alphanumeric 436 + suffix; 437 } 438 439 440 static ToolOption get(String name) { 441 String oname = name; 442 if (name.startsWith("--") && name.contains("=")) { 443 oname = name.substring(0, name.indexOf('=')); 444 } 445 for (ToolOption o : values()) { 446 for (String n : o.names) { 447 if (oname.equals(n)) { 448 return o; 449 } 450 } 451 } 452 return null; 453 } 454 455 abstract static class Helper { 456 457 // File manager options 458 final Map<Option, String> fileManagerOpts = new LinkedHashMap<>(); 459 460 /** javac options, set by various options. */ 461 Options compOpts; // = Options.instance(context) 462 463 /** Javadoc tool options */ 464 final Map<ToolOption, Object> jdtoolOpts = new EnumMap<>(ToolOption.class); 465 466 /** dump stack traces for debugging etc.*/ 467 boolean dumpOnError = false; 468 469 /** Set by -breakiterator. */ 470 boolean breakiterator = false; 471 472 /** Set by -Xwerror. */ 473 boolean rejectWarnings = false; 474 475 /** Set by -prompt. */ 476 boolean promptOnError; 477 478 /** Set by -locale. */ 479 String docLocale = ""; 480 481 Helper() { 482 populateDefaultAccessMap(); 483 } 484 485 abstract void usage(); 486 abstract void Xusage(); 487 488 abstract void version(); 489 abstract void fullVersion(); 490 491 abstract String getLocalizedMessage(String msg, Object... args); 492 493 abstract OptionHelper getOptionHelper(); 494 495 @SuppressWarnings("unchecked") 496 void addToList(ToolOption opt, String delimiter, String str) { 497 List<String> list = (List<String>) jdtoolOpts.computeIfAbsent(opt, v -> new ArrayList<>()); 498 list.addAll(Arrays.asList(str.split(delimiter))); 499 jdtoolOpts.put(opt, list); 500 } 501 502 void setExpandRequires(ToolOption opt, String arg) throws OptionException { 503 switch (arg) { 504 case "transitive": 505 jdtoolOpts.put(opt, AccessKind.PUBLIC); 506 break; 507 case "all": 508 jdtoolOpts.put(opt, AccessKind.PRIVATE); 509 break; 510 default: 511 String text = getLocalizedMessage("main.illegal_option_value", arg); 512 throw new IllegalOptionValue(this::usage, text); 513 } 514 } 515 516 void setShowModuleContents(ToolOption opt, String arg) throws OptionException { 517 switch (arg) { 518 case "api": 519 jdtoolOpts.put(opt, AccessKind.PUBLIC); 520 break; 521 case "all": 522 jdtoolOpts.put(opt, AccessKind.PRIVATE); 523 break; 524 default: 525 String text = getLocalizedMessage("main.illegal_option_value", arg); 526 throw new IllegalOptionValue(this::usage, text); 527 } 528 } 529 530 void setShowPackageAccess(ToolOption opt, String arg) throws OptionException { 531 switch (arg) { 532 case "exported": 533 jdtoolOpts.put(opt, AccessKind.PUBLIC); 534 break; 535 case "all": 536 jdtoolOpts.put(opt, AccessKind.PRIVATE); 537 break; 538 default: 539 String text = getLocalizedMessage("main.illegal_option_value", arg); 540 throw new IllegalOptionValue(this::usage, text); 541 } 542 } 543 544 545 void setFilter(ToolOption opt, String arg) throws OptionException { 546 jdtoolOpts.put(opt, getAccessValue(arg)); 547 } 548 549 void setSimpleFilter(String arg) throws OptionException { 550 handleSimpleOption(arg); 551 } 552 553 void setFileManagerOpt(Option opt, String arg) { 554 fileManagerOpts.put(opt, arg); 555 } 556 557 void handleSimpleOption(String arg) throws OptionException { 558 populateSimpleAccessMap(getAccessValue(arg)); 559 } 560 561 /* 562 * This method handles both the simple options -package, 563 * -private, so on, in addition to the new ones such as 564 * --show-types:public and so on. 565 */ 566 private AccessKind getAccessValue(String arg) throws OptionException { 567 int colon = arg.indexOf(':'); 568 String value = (colon > 0) 569 ? arg.substring(colon + 1) 570 : arg; 571 switch (value) { 572 case "public": 573 return AccessKind.PUBLIC; 574 case "protected": 575 return AccessKind.PROTECTED; 576 case "package": 577 return AccessKind.PACKAGE; 578 case "private": 579 return AccessKind.PRIVATE; 580 default: 581 String text = getLocalizedMessage("main.illegal_option_value", value); 582 throw new IllegalOptionValue(this::usage, text); 583 } 584 } 585 586 /* 587 * Sets the entire kind map to PROTECTED this is the default. 588 */ 589 private void populateDefaultAccessMap() { 590 populateSimpleAccessMap(AccessKind.PROTECTED); 591 } 592 593 /* 594 * This sets access to all the allowed kinds in the 595 * access map. 596 */ 597 void populateSimpleAccessMap(AccessKind accessValue) { 598 for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) { 599 switch (kind) { 600 case METHOD: 601 jdtoolOpts.put(SHOW_MEMBERS, accessValue); 602 break; 603 case CLASS: 604 jdtoolOpts.put(SHOW_TYPES, accessValue); 605 break; 606 case PACKAGE: 607 jdtoolOpts.put(SHOW_PACKAGES, accessValue); 608 break; 609 case MODULE: 610 jdtoolOpts.put(SHOW_MODULE_CONTENTS, accessValue); 611 break; 612 default: 613 throw new AssertionError("unknown element kind:" + kind); 614 } 615 } 616 } 617 } 618 } | 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.javadoc.internal.tool; 27 28 import java.util.ArrayList; 29 import java.util.Arrays; 30 import java.util.LinkedHashMap; 31 import java.util.List; 32 import java.util.Map; 33 import javax.lang.model.element.ElementKind; 34 35 import com.sun.tools.javac.main.Option; 36 import com.sun.tools.javac.main.Option.InvalidValueException; 37 import com.sun.tools.javac.main.OptionHelper; 38 import com.sun.tools.javac.util.Context; 39 import com.sun.tools.javac.util.Options; 40 41 import static jdk.javadoc.internal.tool.Main.Result.OK; 42 import static jdk.javadoc.internal.tool.ToolOptions.ToolOption.Kind.*; 43 44 /** 45 * Storage and support for javadoc tool options, as distinct from 46 * the options supported by any doclet that may be in use. 47 * The tool options includes those options which are delegated 48 * to javac and/or the file manager, such as options to set 49 * the source level, and path options to locate the files to be 50 * documented. 51 * 52 * <p><b>This is NOT part of any supported API. 53 * If you write code that depends on this, you do so at your own risk. 54 * This code and its internal interfaces are subject to change or 55 * deletion without notice.</b> 56 */ 57 public class ToolOptions { 58 // The following are the names of options handled in the first pass of option decoding, 59 // in Start.preprocess. 60 static final String DOCLET = "-doclet"; 61 static final String DOCLET_PATH = "-docletpath"; 62 static final String DUMP_ON_ERROR = "--dump-on-error"; 63 static final String J = "-J"; 64 static final String LOCALE = "-locale"; 65 66 /** 67 * Argument for command-line option {@code -breakiterator}. 68 */ 69 private boolean breakIterator = false; 70 71 /** 72 * Argument for command-line option {@code -locale}. 73 */ 74 private String docLocale = ""; 75 76 /** 77 * Argument for command-line option {@code --dump-on-error}. 78 * Dump stack traces for debugging etc. 79 * Similar to javac {@code -doe}. 80 */ 81 private boolean dumpOnError = false; 82 83 /** 84 * Argument for command-line option {@code -exclude}. 85 */ 86 private List<String> excludes = new ArrayList<>(); 87 88 /** 89 * Argument for command-line option {@code --expand-requires}. 90 */ 91 private AccessKind expandRequires; 92 93 /** 94 * Argument for command-line option {@code --ignore-source-errors}. 95 */ 96 private boolean ignoreSourceErrors; 97 98 /** 99 * Argument for command-line option {@code --module}. 100 */ 101 private List<String> modules = new ArrayList<>(); 102 103 /** 104 * Argument for command-line option {@code -Xwerror}. 105 * Set by -Xwerror. 106 */ 107 private boolean rejectWarnings = false; 108 109 /** 110 * Argument for command-line option {@code --show-members}. 111 */ 112 private AccessKind showMembersAccess; 113 114 /** 115 * Argument for command-line option {@code --show-types}. 116 */ 117 private AccessKind showTypesAccess; 118 119 /** 120 * Argument for command-line option {@code --show-packages}. 121 */ 122 private AccessKind showPackagesAccess; 123 124 /** 125 * Argument for command-line option {@code --show-module-contents}. 126 */ 127 private AccessKind showModuleContents; 128 129 /** 130 * Argument for command-line option {@code -quiet}. 131 */ 132 private boolean quiet; 133 134 /** 135 * Argument for command-line option {@code -subpackages}. 136 */ 137 private List<String> subpackages = new ArrayList<>(); 138 139 /** 140 * Argument for command-line option {@code -verbose}. 141 */ 142 private boolean verbose; 143 144 /** 145 * Argument for command-line option {@code -xclasses}. 146 * If true, names on the command line that would normally be 147 * treated as package names are treated as class names instead. 148 */ 149 private boolean xclasses = false; 150 151 /** 152 * Options to be given to the file manager, such as path options 153 * indicating where to find files to be documented. 154 */ 155 private final Map<Option, String> fileManagerOpts; 156 157 /** 158 * Options to be given to the underlying compiler front-end, 159 * such as options to indicate the source level to be used. 160 */ 161 private final Options compOpts; 162 163 /** 164 * The "helper" to be used when processing compiler options. 165 */ 166 private final OptionHelper compilerOptionHelper; 167 168 /** 169 * The messager to be used to report diagnostics.. 170 */ 171 private final Messager messager; 172 173 /** 174 * The helper for help and version options 175 */ 176 private final ShowHelper showHelper; 177 178 /** 179 * Creates an object to handle tool options. 180 * 181 * @param context the context used to find other tool-related components 182 * @param messager the messager to be used to report diagnostics 183 */ 184 ToolOptions(Context context, Messager messager, ShowHelper showHelper) { 185 this.messager = messager; 186 this.showHelper = showHelper; 187 compOpts = Options.instance(context); 188 fileManagerOpts = new LinkedHashMap<>(); 189 compilerOptionHelper = getOptionHelper(); 190 setAccessDefault(); 191 } 192 193 /** 194 * Creates a minimal object, just sufficient to check the names of the 195 * supported options. 196 */ 197 private ToolOptions() { 198 compOpts = null; 199 compilerOptionHelper = null; 200 fileManagerOpts = null; 201 messager = null; 202 showHelper = null; 203 } 204 205 /** 206 * Returns the set of options supported by the tool, excluding any options 207 * that are managed by the doclet that may be in use. 208 * 209 * @return the set of options 210 */ 211 public List<ToolOption> getSupportedOptions() { 212 return supportedOptions; 213 } 214 215 /** 216 * Determines if the given option is supported and if so, the 217 * number of arguments the option takes. 218 * 219 * @param option an option 220 * @return the number of arguments the given option takes or -1 if 221 * the option is not supported 222 * @see javax.tools.DocumentationTool#isSupportedOption(String) 223 */ 224 public static int isSupportedOption(String option) { 225 ToolOptions t = new ToolOptions(); 226 for (ToolOption o : t.supportedOptions) { 227 for (String name : o.names) { 228 if (name.equals(option)) 229 return o.hasArg ? 1 : 0; 230 } 231 } 232 return -1; 233 } 234 235 /** 236 * Returns the option to be used to process an argument such as may be found on 237 * the command line. 238 * 239 * @param arg the argument 240 * @return the option 241 */ 242 ToolOption getOption(String arg) { 243 String name = arg; 244 if (arg.startsWith("--") && arg.contains("=")) { 245 name = arg.substring(0, arg.indexOf('=')); 246 } 247 for (ToolOption o : supportedOptions) { 248 for (String n : o.names) { 249 if (name.equals(n)) { 250 return o; 251 } 252 } 253 } 254 return null; 255 } 256 257 private List<ToolOption> supportedOptions = List.of( 258 // ----- options for underlying compiler ----- 259 260 new ToolOption("-bootclasspath", STANDARD, true) { 261 @Override 262 public void process(String arg) throws InvalidValueException { 263 processCompilerOption(Option.BOOT_CLASS_PATH, primaryName, arg); 264 } 265 }, 266 267 new ToolOption("--class-path -classpath -cp", STANDARD, true) { 268 @Override 269 public void process(String arg) throws InvalidValueException { 270 processCompilerOption(Option.CLASS_PATH, primaryName, arg); 271 } 272 }, 273 274 new ToolOption("-extdirs", STANDARD, true) { 275 @Override 276 public void process(String arg) throws InvalidValueException { 277 processCompilerOption(Option.EXTDIRS, primaryName, arg); 278 } 279 }, 280 281 new ToolOption("--source-path -sourcepath", STANDARD, true) { 282 @Override 283 public void process(String arg) throws InvalidValueException { 284 processCompilerOption(Option.SOURCE_PATH, primaryName, arg); 285 } 286 }, 287 288 new ToolOption("--module-source-path", STANDARD, true) { 289 @Override 290 public void process(String arg) throws InvalidValueException { 291 processCompilerOption(Option.MODULE_SOURCE_PATH, primaryName, arg); 292 } 293 }, 294 295 new ToolOption("--upgrade-module-path", STANDARD, true) { 296 @Override 297 public void process(String arg) throws InvalidValueException { 298 processCompilerOption(Option.UPGRADE_MODULE_PATH, primaryName, arg); 299 } 300 }, 301 302 new ToolOption("--system", STANDARD, true) { 303 @Override 304 public void process(String arg) throws InvalidValueException { 305 processCompilerOption(Option.SYSTEM, primaryName, arg); 306 } 307 }, 308 309 new ToolOption("--module-path -p", STANDARD, true) { 310 @Override 311 public void process(String arg) throws InvalidValueException { 312 processCompilerOption(Option.MODULE_PATH, primaryName, arg); 313 } 314 }, 315 316 new ToolOption("--add-modules", STANDARD, true) { 317 @Override 318 public void process(String arg) throws InvalidValueException { 319 processCompilerOption(Option.ADD_MODULES, primaryName, arg); 320 } 321 }, 322 323 new ToolOption("--limit-modules", STANDARD, true) { 324 @Override 325 public void process(String arg) throws InvalidValueException { 326 processCompilerOption(Option.LIMIT_MODULES, primaryName, arg); 327 } 328 }, 329 330 new ToolOption("--module", STANDARD, true) { 331 @Override 332 public void process(String arg) { 333 modules.addAll(List.of(arg.split(","))); 334 } 335 }, 336 337 new ToolOption("-encoding", STANDARD, true) { 338 @Override 339 public void process(String arg) throws InvalidValueException { 340 processCompilerOption(Option.ENCODING, primaryName, arg); 341 } 342 }, 343 344 new ToolOption("--release", STANDARD, true) { 345 @Override 346 public void process(String arg) throws InvalidValueException { 347 processCompilerOption(Option.RELEASE, primaryName, arg); 348 } 349 }, 350 351 new ToolOption("--source -source", STANDARD, true) { 352 @Override 353 public void process(String arg) throws InvalidValueException { 354 processCompilerOption(Option.SOURCE, primaryName, arg); 355 processCompilerOption(Option.TARGET, Option.TARGET.primaryName, arg); 356 } 357 }, 358 359 new ToolOption("-Xmaxerrs", EXTENDED, true) { 360 @Override 361 public void process(String arg) throws InvalidValueException { 362 processCompilerOption(Option.XMAXERRS, primaryName, arg); 363 } 364 }, 365 366 new ToolOption("-Xmaxwarns", EXTENDED, true) { 367 @Override 368 public void process(String arg) throws InvalidValueException { 369 processCompilerOption(Option.XMAXWARNS, primaryName, arg); 370 } 371 }, 372 373 new ToolOption("--add-reads", EXTENDED, true) { 374 @Override 375 public void process(String arg) throws InvalidValueException { 376 processCompilerOption(Option.ADD_READS, primaryName, arg); 377 } 378 }, 379 380 new ToolOption("--add-exports", EXTENDED, true) { 381 @Override 382 public void process(String arg) throws InvalidValueException { 383 processCompilerOption(Option.ADD_EXPORTS, primaryName, arg); 384 } 385 }, 386 387 new ToolOption("--patch-module", EXTENDED, true) { 388 @Override 389 public void process(String arg) throws InvalidValueException { 390 processCompilerOption(Option.PATCH_MODULE, primaryName, arg); 391 } 392 }, 393 394 new ToolOption("--add-opens", HIDDEN, true) { 395 @Override 396 public void process(String arg) throws InvalidValueException { 397 processCompilerOption(Option.ADD_OPENS, primaryName, arg); 398 } 399 }, 400 401 new ToolOption("--enable-preview", STANDARD) { 402 @Override 403 public void process() throws InvalidValueException { 404 processCompilerOption(Option.PREVIEW, primaryName); 405 } 406 }, 407 408 // ----- doclet options ----- 409 410 new ToolOption(DOCLET, STANDARD, true), // handled in setDocletInvoker 411 412 new ToolOption(DOCLET_PATH, STANDARD, true), // handled in setDocletInvoker 413 414 // ----- selection options ----- 415 416 new ToolOption("-subpackages", STANDARD, true) { 417 @Override 418 public void process(String arg) { 419 subpackages.addAll(List.of(arg.split(":"))); 420 } 421 }, 422 423 new ToolOption("-exclude", STANDARD, true) { 424 @Override 425 public void process(String arg) { 426 excludes.addAll(List.of(arg.split(":"))); 427 } 428 }, 429 430 // ----- filtering options ----- 431 432 new ToolOption("-package", STANDARD) { 433 @Override 434 public void process() throws OptionException { 435 setSimpleFilter("package"); 436 } 437 }, 438 439 new ToolOption("-private", STANDARD) { 440 @Override 441 public void process() throws OptionException { 442 setSimpleFilter("private"); 443 } 444 }, 445 446 new ToolOption("-protected", STANDARD) { 447 @Override 448 public void process() throws OptionException { 449 setSimpleFilter("protected"); 450 } 451 }, 452 453 new ToolOption("-public", STANDARD) { 454 @Override 455 public void process() throws OptionException { 456 setSimpleFilter("public"); 457 } 458 }, 459 460 new ToolOption("--show-members", STANDARD, true) { 461 @Override 462 public void process(String arg) throws OptionException { 463 setShowMembersAccess(arg); 464 } 465 }, 466 467 new ToolOption("--show-types", STANDARD, true) { 468 @Override 469 public void process(String arg) throws OptionException { 470 setShowTypesAccess(arg); 471 } 472 }, 473 474 new ToolOption("--show-packages", STANDARD, true) { 475 @Override 476 public void process(String arg) throws OptionException { 477 setShowPackageAccess(arg); 478 } 479 }, 480 481 new ToolOption("--show-module-contents", STANDARD, true) { 482 @Override 483 public void process(String arg) throws OptionException { 484 setShowModuleContents(arg); 485 } 486 }, 487 488 new ToolOption("--expand-requires", STANDARD, true) { 489 @Override 490 public void process(String arg) throws OptionException { 491 setExpandRequires(arg); 492 } 493 }, 494 495 // ----- output control options ----- 496 497 new ToolOption("-quiet", STANDARD) { 498 @Override 499 public void process() { 500 quiet = true; 501 } 502 }, 503 504 new ToolOption("-verbose", STANDARD) { 505 @Override 506 public void process() { 507 setVerbose(); 508 } 509 }, 510 511 new ToolOption("-Xwerror", HIDDEN) { 512 @Override 513 public void process() { 514 rejectWarnings = true; 515 } 516 }, 517 518 // ----- other options ----- 519 520 new ToolOption("-breakiterator", STANDARD) { 521 @Override 522 public void process() { 523 breakIterator = true; 524 } 525 }, 526 527 new ToolOption(LOCALE, STANDARD, true) { 528 @Override 529 public void process(String arg) { 530 docLocale = arg; 531 } 532 }, 533 534 new ToolOption("-Xclasses", HIDDEN) { 535 @Override 536 public void process() { 537 xclasses = true; 538 } 539 }, 540 541 new ToolOption(DUMP_ON_ERROR, HIDDEN) { 542 @Override 543 public void process() { 544 dumpOnError = true; 545 } 546 }, 547 548 new ToolOption("--ignore-source-errors", HIDDEN) { 549 @Override 550 public void process() { 551 ignoreSourceErrors = true; 552 } 553 }, 554 555 // ----- help options ----- 556 557 new ToolOption("--help -help -? -h", STANDARD) { 558 @Override 559 public void process() throws OptionException { 560 throw new OptionException(OK, showHelper::usage); 561 } 562 }, 563 564 new ToolOption("--help-extra -X", STANDARD) { 565 @Override 566 public void process() throws OptionException { 567 throw new OptionException(OK, showHelper::Xusage); 568 } 569 }, 570 571 // This option exists only for the purpose of documenting itself. 572 // It's actually implemented by the launcher. 573 new ToolOption(J, STANDARD, true) { 574 @Override 575 public void process() { 576 throw new AssertionError("the -J flag should be caught by the launcher."); 577 } 578 }, 579 580 new ToolOption("--version", STANDARD) { 581 @Override 582 public void process() throws OptionException { 583 throw new OptionException(OK, showHelper::version); 584 } 585 }, 586 587 new ToolOption("--full-version", HIDDEN) { 588 @Override 589 public void process() throws OptionException { 590 throw new OptionException(OK, showHelper::fullVersion); 591 } 592 }); 593 594 /** 595 * Base class for all supported tool options. 596 */ 597 static class ToolOption { 598 enum Kind { STANDARD, EXTENDED, HIDDEN } 599 600 final String primaryName; 601 final List<String> names; 602 final Kind kind; 603 final boolean hasArg; 604 final boolean hasSuffix; // ex: foo:bar or -foo=bar 605 606 ToolOption(String opt, Kind kind) { 607 this(opt, kind, false); 608 } 609 610 ToolOption(String names, Kind kind, boolean hasArg) { 611 this.names = Arrays.asList(names.split("\\s+")); 612 this.primaryName = this.names.get(0); 613 this.kind = kind; 614 this.hasArg = hasArg; 615 char lastChar = names.charAt(names.length() - 1); 616 this.hasSuffix = lastChar == ':' || lastChar == '='; 617 } 618 619 void process(String arg) throws OptionException, Option.InvalidValueException { } 620 621 void process() throws OptionException, Option.InvalidValueException { } 622 623 List<String> getNames() { 624 return names; 625 } 626 627 String getParameters(Messager messager) { 628 return (hasArg || primaryName.endsWith(":")) 629 ? messager.getText(getKey(primaryName, ".arg")) 630 : null; 631 } 632 633 String getDescription(Messager messager) { 634 return messager.getText(getKey(primaryName, ".desc")); 635 } 636 637 private String getKey(String optionName, String suffix) { 638 return "main.opt." 639 + optionName 640 .replaceAll("^-*", "") // remove leading '-' 641 .replaceAll("[^A-Za-z0-9]+$", "") // remove trailing non-alphanumeric 642 .replaceAll("[^A-Za-z0-9]", ".") // replace internal non-alphanumeric 643 + suffix; 644 } 645 } 646 647 interface ShowHelper { 648 /** 649 * Show command-line help for the standard options, as requested by 650 * the {@code --help} option and its aliases. 651 */ 652 void usage(); 653 654 /** 655 * Show command-line help for the extended options, as requested by 656 * the {@code --help-extended} option and its aliases. 657 */ 658 void Xusage(); 659 660 /** 661 * Show the basic version information, as requested by the {@code --version} option. 662 */ 663 void version(); 664 665 /** 666 * Show the full version information, as requested by the {@code --full-version} option. 667 */ 668 void fullVersion(); 669 } 670 671 //<editor-fold desc="accessor methods"> 672 /** 673 * Argument for command-line option {@code -breakiterator}. 674 */ 675 boolean breakIterator() { 676 return breakIterator; 677 } 678 679 /** 680 * Argument for command-line option {@code -locale}. 681 */ 682 String locale() { 683 return docLocale; 684 } 685 686 /** 687 * Argument for command-line option {@code --dump-on-error}. 688 * Dump stack traces for debugging etc. 689 * Similar to javac {@code -doe}. 690 */ 691 boolean dumpOnError() { 692 return dumpOnError; 693 } 694 695 void setDumpOnError(boolean v) { 696 dumpOnError = true; 697 } 698 699 /** 700 * Argument for command-line option {@code -exclude}. 701 */ 702 List<String> excludes() { 703 return excludes; 704 } 705 706 /** 707 * Argument for command-line option {@code --expand-requires}. 708 */ 709 AccessKind expandRequires() { 710 return expandRequires; 711 } 712 713 /** 714 * Argument for command-line option {@code --ignore-source-errors}. 715 */ 716 boolean ignoreSourceErrors() { 717 return ignoreSourceErrors; 718 } 719 720 /** 721 * Argument for command-line option {@code --module}. 722 */ 723 List<String> modules() { 724 return modules; 725 } 726 727 /** 728 * Argument for command-line option {@code -Xwerror}. 729 * Set by -Xwerror. 730 */ 731 boolean rejectWarnings() { 732 return rejectWarnings; 733 } 734 735 /** 736 * Argument for command-line option {@code --show-members}. 737 */ 738 AccessKind showMembersAccess() { 739 return showMembersAccess; 740 } 741 742 /** 743 * Argument for command-line option {@code --show-types}. 744 */ 745 AccessKind showTypesAccess() { 746 return showTypesAccess; 747 } 748 749 /** 750 * Argument for command-line option {@code --show-packages}. 751 */ 752 AccessKind showPackagesAccess() { 753 return showPackagesAccess; 754 } 755 756 /** 757 * Argument for command-line option {@code --show-module-contents}. 758 */ 759 AccessKind showModuleContents() { 760 return showModuleContents; 761 } 762 763 /** 764 * Argument for command-line option {@code -quiet}. 765 */ 766 boolean quiet() { 767 return quiet; 768 } 769 770 /** 771 * Argument for command-line option {@code -subpackages}. 772 */ 773 List<String> subpackages() { 774 return subpackages; 775 } 776 777 /** 778 * Argument for command-line option {@code -verbose}. 779 */ 780 boolean verbose() { 781 return verbose; 782 } 783 784 /** 785 * Argument for command-line option {@code -xclasses}. 786 * If true, names on the command line that would normally be 787 * treated as package names are treated as class names instead. 788 */ 789 boolean xclasses() { 790 return xclasses; 791 } 792 793 /** 794 * Returns the set of options to be used for the instance of the 795 * underlying compiler front-end. 796 * 797 * @return the options 798 */ 799 Options compilerOptions() { 800 return compOpts; 801 } 802 803 /** 804 * Returns the set of options to be used for the file manager. 805 * 806 * @return the options 807 */ 808 Map<Option, String> fileManagerOptions() { 809 return fileManagerOpts; 810 } 811 //</editor-fold> 812 813 /** 814 * Returns an {@code IllegalOptionValue} exception. 815 * 816 * @param arg the arghument to include in the detail message 817 * @return the exception 818 */ 819 private IllegalOptionValue illegalOptionValue(String arg) { 820 return new IllegalOptionValue(showHelper::usage, messager.getText("main.illegal_option_value", arg)); 821 } 822 823 /** 824 * Process a compiler option. 825 * 826 * @param option the option object to process the command-line option 827 * @param opt the command-line option 828 * @throws Option.InvalidValueException if the command-line option is invalid 829 */ 830 void processCompilerOption(Option option, String opt) throws Option.InvalidValueException { 831 option.process(compilerOptionHelper, opt); 832 } 833 834 /** 835 * Process a compiler option. 836 * 837 * @param option the option object to process the command-line option 838 * @param opt the command-line option 839 * @param arg the argument for the command-line option 840 * @throws Option.InvalidValueException if the command-line option is invalid 841 */ 842 private void processCompilerOption(Option option, String opt, String arg) throws Option.InvalidValueException { 843 option.process(compilerOptionHelper, opt, arg); 844 } 845 846 /** 847 * Returns a "helper" to be used when processing compiler options. 848 * @return the helper 849 */ 850 private OptionHelper getOptionHelper() { 851 return new OptionHelper.GrumpyHelper(messager) { 852 @Override 853 public String get(com.sun.tools.javac.main.Option option) { 854 return compOpts.get(option); 855 } 856 857 @Override 858 public void put(String name, String value) { 859 compOpts.put(name, value); 860 } 861 862 @Override 863 public void remove(String name) { 864 compOpts.remove(name); 865 } 866 867 @Override 868 public boolean handleFileManagerOption(com.sun.tools.javac.main.Option option, String value) { 869 fileManagerOpts.put(option, value); 870 return true; 871 } 872 }; 873 } 874 875 private void setExpandRequires(String arg) throws OptionException { 876 switch (arg) { 877 case "transitive": 878 expandRequires = AccessKind.PUBLIC; 879 break; 880 case "all": 881 expandRequires = AccessKind.PRIVATE; 882 break; 883 default: 884 throw illegalOptionValue(arg); 885 } 886 } 887 888 private void setShowModuleContents(String arg) throws OptionException { 889 switch (arg) { 890 case "api": 891 showModuleContents = AccessKind.PUBLIC; 892 break; 893 case "all": 894 showModuleContents = AccessKind.PRIVATE; 895 break; 896 default: 897 throw illegalOptionValue(arg); 898 } 899 } 900 901 private void setShowPackageAccess(String arg) throws OptionException { 902 switch (arg) { 903 case "exported": 904 showPackagesAccess = AccessKind.PUBLIC; 905 break; 906 case "all": 907 showPackagesAccess = AccessKind.PRIVATE; 908 break; 909 default: 910 throw illegalOptionValue(arg); 911 } 912 } 913 914 private void setShowTypesAccess(String arg) throws OptionException { 915 showTypesAccess = getAccessValue(arg); 916 } 917 918 private void setShowMembersAccess(String arg) throws OptionException { 919 showMembersAccess = getAccessValue(arg); 920 } 921 922 private void setSimpleFilter(String arg) throws OptionException { 923 setSimpleAccessOption(arg); 924 } 925 926 private void setVerbose() { 927 compOpts.put("-verbose", ""); 928 verbose = true; 929 } 930 931 private void setSimpleAccessOption(String arg) throws OptionException { 932 setAccess(getAccessValue(arg)); 933 } 934 935 /* 936 * This method handles both the simple options -package, 937 * -private, so on, in addition to the new ones such as 938 * --show-types:public and so on. 939 */ 940 private AccessKind getAccessValue(String arg) throws OptionException { 941 int colon = arg.indexOf(':'); 942 String value = (colon > 0) 943 ? arg.substring(colon + 1) 944 : arg; 945 switch (value) { 946 case "public": 947 return AccessKind.PUBLIC; 948 case "protected": 949 return AccessKind.PROTECTED; 950 case "package": 951 return AccessKind.PACKAGE; 952 case "private": 953 return AccessKind.PRIVATE; 954 default: 955 throw illegalOptionValue(value); 956 } 957 } 958 959 /* 960 * Sets all access members to PROTECTED; this is the default. 961 */ 962 private void setAccessDefault() { 963 setAccess(AccessKind.PROTECTED); 964 } 965 966 /* 967 * This sets access to all the allowed kinds in the 968 * access members. 969 */ 970 private void setAccess(AccessKind accessValue) { 971 for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) { 972 switch (kind) { 973 case METHOD: 974 showMembersAccess = accessValue; 975 break; 976 case CLASS: 977 showTypesAccess = accessValue; 978 break; 979 case PACKAGE: 980 showPackagesAccess = accessValue; 981 break; 982 case MODULE: 983 showModuleContents = accessValue; 984 break; 985 default: 986 throw new AssertionError("unknown element kind:" + kind); 987 } 988 } 989 } 990 } |