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