1 /* 2 * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 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", 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 // ----- doclet options ----- 193 194 DOCLET("-doclet", STANDARD, true), // handled in setDocletInvoker 195 196 DOCLETPATH("-docletpath", STANDARD, true), // handled in setDocletInvoker 197 198 // ----- selection options ----- 199 200 SUBPACKAGES("-subpackages", STANDARD, true) { 201 @Override 202 public void process(Helper helper, String arg) { 203 helper.addToList(this, ":", arg); 204 } 205 }, 206 207 EXCLUDE("-exclude", STANDARD, true) { 208 @Override 209 public void process(Helper helper, String arg) { 210 helper.addToList(this, ":", arg); 211 } 212 }, 213 214 // ----- filtering options ----- 215 216 PACKAGE("-package", STANDARD) { 217 @Override 218 public void process(Helper helper) throws OptionException { 219 helper.setSimpleFilter("package"); 220 } 221 }, 222 223 PRIVATE("-private", STANDARD) { 224 @Override 225 public void process(Helper helper) throws OptionException { 226 helper.setSimpleFilter("private"); 227 } 228 }, 229 230 PROTECTED("-protected", STANDARD) { 231 @Override 232 public void process(Helper helper) throws OptionException { 233 helper.setSimpleFilter("protected"); 234 } 235 }, 236 237 PUBLIC("-public", STANDARD) { 238 @Override 239 public void process(Helper helper) throws OptionException { 240 helper.setSimpleFilter("public"); 241 } 242 }, 243 244 SHOW_MEMBERS("--show-members", STANDARD, true) { 245 @Override 246 public void process(Helper helper, String arg) throws OptionException { 247 helper.setFilter(this, arg); 248 } 249 }, 250 251 SHOW_TYPES("--show-types", STANDARD, true) { 252 @Override 253 public void process(Helper helper, String arg) throws OptionException { 254 helper.setFilter(this, arg); 255 } 256 }, 257 258 SHOW_PACKAGES("--show-packages", STANDARD, true) { 259 @Override 260 public void process(Helper helper, String arg) throws OptionException { 261 helper.setShowPackageAccess(SHOW_PACKAGES, arg); 262 } 263 }, 264 265 SHOW_MODULE_CONTENTS("--show-module-contents", STANDARD, true) { 266 @Override 267 public void process(Helper helper, String arg) throws OptionException { 268 helper.setShowModuleContents(SHOW_MODULE_CONTENTS, arg); 269 } 270 }, 271 272 EXPAND_REQUIRES("--expand-requires", STANDARD, true) { 273 @Override 274 public void process(Helper helper, String arg) throws OptionException { 275 helper.setExpandRequires(EXPAND_REQUIRES, arg); 276 } 277 }, 278 279 // ----- output control options ----- 280 281 QUIET("-quiet", STANDARD) { 282 @Override 283 public void process(Helper helper) { 284 helper.jdtoolOpts.put(QUIET, true); 285 } 286 }, 287 288 VERBOSE("-verbose", STANDARD) { 289 @Override 290 public void process(Helper helper) { 291 helper.compOpts.put("-verbose", ""); 292 } 293 }, 294 295 XWERROR("-Xwerror", HIDDEN) { 296 @Override 297 public void process(Helper helper) { 298 helper.rejectWarnings = true; 299 300 } 301 }, 302 303 // ----- other options ----- 304 305 BREAKITERATOR("-breakiterator", STANDARD) { 306 @Override 307 public void process(Helper helper) { 308 helper.breakiterator = true; 309 } 310 }, 311 312 LOCALE("-locale", STANDARD, true) { 313 @Override 314 public void process(Helper helper, String arg) { 315 helper.docLocale = arg; 316 } 317 }, 318 319 XCLASSES("-Xclasses", HIDDEN) { 320 @Override 321 public void process(Helper helper) { 322 helper.jdtoolOpts.put(XCLASSES, true); 323 } 324 }, 325 326 DUMPONERROR("--dump-on-error", HIDDEN) { 327 @Override 328 public void process(Helper helper) { 329 helper.dumpOnError = true; 330 } 331 }, 332 333 IGNORE_SOURCE_ERRORS("--ignore-source-errors", HIDDEN) { 334 @Override 335 public void process(Helper helper) { 336 helper.jdtoolOpts.put(IGNORE_SOURCE_ERRORS, true); 337 } 338 }, 339 340 // ----- help options ----- 341 342 HELP("--help -help", STANDARD) { 343 @Override 344 public void process(Helper helper) throws OptionException { 345 throw new OptionException(OK, helper::usage); 346 } 347 }, 348 349 HELP_EXTRA("--help-extra -X", STANDARD) { 350 @Override 351 public void process(Helper helper) throws OptionException { 352 throw new OptionException(OK, helper::Xusage); 353 } 354 }, 355 356 // This option exists only for the purpose of documenting itself. 357 // It's actually implemented by the launcher. 358 J("-J", STANDARD, true) { 359 @Override 360 public void process(Helper helper) { 361 throw new AssertionError("the -J flag should be caught by the launcher."); 362 } 363 }, 364 365 VERSION("--version", STANDARD) { 366 @Override 367 public void process(Helper helper) throws OptionException { 368 throw new OptionException(OK, helper::version); 369 } 370 }, 371 372 FULLVERSION("--full-version", HIDDEN) { 373 @Override 374 public void process(Helper helper) throws OptionException { 375 throw new OptionException(OK, helper::fullVersion); 376 } 377 }; 378 379 public final String primaryName; 380 public final List<String> names; 381 public final OptionKind kind; 382 public final boolean hasArg; 383 public final boolean hasSuffix; // ex: foo:bar or -foo=bar 384 385 ToolOption(String opt, OptionKind kind) { 386 this(opt, kind, false); 387 } 388 389 ToolOption(String names, OptionKind kind, boolean hasArg) { 390 this.names = Arrays.asList(names.split("\\s+")); 391 this.primaryName = this.names.get(0); 392 this.kind = kind; 393 this.hasArg = hasArg; 394 char lastChar = names.charAt(names.length() - 1); 395 this.hasSuffix = lastChar == ':' || lastChar == '='; 396 } 397 398 void process(Helper helper, String arg) throws OptionException, Option.InvalidValueException { } 399 400 void process(Helper helper) throws OptionException { } 401 402 List<String> getNames() { 403 return names; 404 } 405 406 String getParameters(Messager messager) { 407 return (hasArg || primaryName.endsWith(":")) 408 ? messager.getText(getKey(primaryName, ".arg")) 409 : null; 410 } 411 412 String getDescription(Messager messager) { 413 return messager.getText(getKey(primaryName, ".desc")); 414 } 415 416 private String getKey(String optionName, String suffix) { 417 return "main.opt." 418 + optionName 419 .replaceAll("^-*", "") // remove leading '-' 420 .replaceAll("[^A-Za-z0-9]+$", "") // remove trailing non-alphanumeric 421 .replaceAll("[^A-Za-z0-9]", ".") // replace internal non-alphanumeric 422 + suffix; 423 } 424 425 426 static ToolOption get(String name) { 427 String oname = name; 428 if (name.startsWith("--") && name.contains("=")) { 429 oname = name.substring(0, name.indexOf('=')); 430 } 431 for (ToolOption o : values()) { 432 for (String n : o.names) { 433 if (oname.equals(n)) { 434 return o; 435 } 436 } 437 } 438 return null; 439 } 440 441 static abstract class Helper { 442 443 // File manager options 444 final Map<Option, String> fileManagerOpts = new LinkedHashMap<>(); 445 446 /** javac options, set by various options. */ 447 Options compOpts; // = Options.instance(context) 448 449 /** Javadoc tool options */ 450 final Map<ToolOption, Object> jdtoolOpts = new EnumMap<>(ToolOption.class); 451 452 /** dump stack traces for debugging etc.*/ 453 boolean dumpOnError = false; 454 455 /** Set by -breakiterator. */ 456 boolean breakiterator = false; 457 458 /** Set by -Xwerror. */ 459 boolean rejectWarnings = false; 460 461 /** Set by -prompt. */ 462 boolean promptOnError; 463 464 /** Set by -locale. */ 465 String docLocale = ""; 466 467 Helper() { 468 populateDefaultAccessMap(); 469 } 470 471 abstract void usage(); 472 abstract void Xusage(); 473 474 abstract void version(); 475 abstract void fullVersion(); 476 477 abstract String getLocalizedMessage(String msg, Object... args); 478 479 abstract OptionHelper getOptionHelper(); 480 481 @SuppressWarnings("unchecked") 482 void addToList(ToolOption opt, String delimiter, String str) { 483 List<String> list = (List<String>) jdtoolOpts.computeIfAbsent(opt, v -> new ArrayList<>()); 484 list.addAll(Arrays.asList(str.split(delimiter))); 485 jdtoolOpts.put(opt, list); 486 } 487 488 void setExpandRequires(ToolOption opt, String arg) throws OptionException { 489 switch (arg) { 490 case "transitive": 491 jdtoolOpts.put(opt, AccessKind.PUBLIC); 492 break; 493 case "all": 494 jdtoolOpts.put(opt, AccessKind.PRIVATE); 495 break; 496 default: 497 String text = getLocalizedMessage("main.illegal_option_value", arg); 498 throw new IllegalOptionValue(this::usage, text); 499 } 500 } 501 502 void setShowModuleContents(ToolOption opt, String arg) throws OptionException { 503 switch (arg) { 504 case "api": 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 setShowPackageAccess(ToolOption opt, String arg) throws OptionException { 517 switch (arg) { 518 case "exported": 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 531 void setFilter(ToolOption opt, String arg) throws OptionException { 532 jdtoolOpts.put(opt, getAccessValue(arg)); 533 } 534 535 void setSimpleFilter(String arg) throws OptionException { 536 handleSimpleOption(arg); 537 } 538 539 void setFileManagerOpt(Option opt, String arg) { 540 fileManagerOpts.put(opt, arg); 541 } 542 543 void handleSimpleOption(String arg) throws OptionException { 544 populateSimpleAccessMap(getAccessValue(arg)); 545 } 546 547 /* 548 * This method handles both the simple options -package, 549 * -private, so on, in addition to the new ones such as 550 * --show-types:public and so on. 551 */ 552 private AccessKind getAccessValue(String arg) throws OptionException { 553 int colon = arg.indexOf(':'); 554 String value = (colon > 0) 555 ? arg.substring(colon + 1) 556 : arg; 557 switch (value) { 558 case "public": 559 return AccessKind.PUBLIC; 560 case "protected": 561 return AccessKind.PROTECTED; 562 case "package": 563 return AccessKind.PACKAGE; 564 case "private": 565 return AccessKind.PRIVATE; 566 default: 567 String text = getLocalizedMessage("main.illegal_option_value", value); 568 throw new IllegalOptionValue(this::usage, text); 569 } 570 } 571 572 /* 573 * Sets the entire kind map to PROTECTED this is the default. 574 */ 575 private void populateDefaultAccessMap() { 576 populateSimpleAccessMap(AccessKind.PROTECTED); 577 } 578 579 /* 580 * This sets access to all the allowed kinds in the 581 * access map. 582 */ 583 void populateSimpleAccessMap(AccessKind accessValue) { 584 for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) { 585 switch (kind) { 586 case METHOD: 587 jdtoolOpts.put(SHOW_MEMBERS, accessValue); 588 break; 589 case CLASS: 590 jdtoolOpts.put(SHOW_TYPES, accessValue); 591 break; 592 case PACKAGE: 593 jdtoolOpts.put(SHOW_PACKAGES, accessValue); 594 break; 595 case MODULE: 596 jdtoolOpts.put(SHOW_MODULE_CONTENTS, accessValue); 597 break; 598 default: 599 throw new AssertionError("unknown element kind:" + kind); 600 } 601 } 602 } 603 } 604 }