Option.java revision 2973:0e8fa3249327
1/* 2 * Copyright (c) 2006, 2014, 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 26package com.sun.tools.javac.main; 27 28import java.io.File; 29import java.io.FileWriter; 30import java.io.PrintWriter; 31import java.util.Collections; 32import java.util.EnumSet; 33import java.util.LinkedHashMap; 34import java.util.Map; 35import java.util.ServiceLoader; 36import java.util.Set; 37import java.util.TreeSet; 38import java.util.stream.Collectors; 39import java.util.stream.StreamSupport; 40 41import javax.lang.model.SourceVersion; 42 43import com.sun.tools.doclint.DocLint; 44import com.sun.tools.javac.code.Lint; 45import com.sun.tools.javac.code.Lint.LintCategory; 46import com.sun.tools.javac.code.Source; 47import com.sun.tools.javac.code.Type; 48import com.sun.tools.javac.jvm.Profile; 49import com.sun.tools.javac.jvm.Target; 50import com.sun.tools.javac.platform.PlatformProvider; 51import com.sun.tools.javac.processing.JavacProcessingEnvironment; 52import com.sun.tools.javac.util.Log; 53import com.sun.tools.javac.util.Log.PrefixKind; 54import com.sun.tools.javac.util.Log.WriterKind; 55import com.sun.tools.javac.util.Options; 56import com.sun.tools.javac.util.StringUtils; 57 58import static com.sun.tools.javac.main.Option.ChoiceKind.*; 59import static com.sun.tools.javac.main.Option.OptionGroup.*; 60import static com.sun.tools.javac.main.Option.OptionKind.*; 61 62/** 63 * Options for javac. The specific Option to handle a command-line option 64 * is identified by searching the members of this enum in order, looking for 65 * the first {@link #matches match}. The action for an Option is performed 66 * by calling {@link #process process}, and by providing a suitable 67 * {@link OptionHelper} to provide access the compiler state. 68 * 69 * <p><b>This is NOT part of any supported API. 70 * If you write code that depends on this, you do so at your own 71 * risk. This code and its internal interfaces are subject to change 72 * or deletion without notice.</b></p> 73 */ 74public enum Option { 75 G("-g", "opt.g", STANDARD, BASIC), 76 77 G_NONE("-g:none", "opt.g.none", STANDARD, BASIC) { 78 @Override 79 public boolean process(OptionHelper helper, String option) { 80 helper.put("-g:", "none"); 81 return false; 82 } 83 }, 84 85 G_CUSTOM("-g:", "opt.g.lines.vars.source", 86 STANDARD, BASIC, ANYOF, "lines", "vars", "source"), 87 88 XLINT("-Xlint", "opt.Xlint", EXTENDED, BASIC), 89 90 XLINT_CUSTOM("-Xlint:", EXTENDED, BASIC, ANYOF, getXLintChoices()) { 91 private static final String LINT_KEY_FORMAT = " %-19s %s"; 92 @Override 93 void help(Log log, OptionKind kind) { 94 if (this.kind != kind) 95 return; 96 97 log.printRawLines(WriterKind.NOTICE, 98 String.format(HELP_LINE_FORMAT, 99 log.localize(PrefixKind.JAVAC, "opt.Xlint.subopts"), 100 log.localize(PrefixKind.JAVAC, "opt.Xlint.suboptlist"))); 101 log.printRawLines(WriterKind.NOTICE, 102 String.format(LINT_KEY_FORMAT, 103 "all", 104 log.localize(PrefixKind.JAVAC, "opt.Xlint.all"))); 105 for (LintCategory lc : LintCategory.values()) { 106 if (lc.hidden) continue; 107 log.printRawLines(WriterKind.NOTICE, 108 String.format(LINT_KEY_FORMAT, 109 lc.option, 110 log.localize(PrefixKind.JAVAC, 111 "opt.Xlint.desc." + lc.option))); 112 } 113 log.printRawLines(WriterKind.NOTICE, 114 String.format(LINT_KEY_FORMAT, 115 "none", 116 log.localize(PrefixKind.JAVAC, "opt.Xlint.none"))); 117 } 118 }, 119 120 XDOCLINT("-Xdoclint", "opt.Xdoclint", EXTENDED, BASIC), 121 122 XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) { 123 @Override 124 public boolean matches(String option) { 125 return DocLint.isValidOption( 126 option.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX)); 127 } 128 129 @Override 130 public boolean process(OptionHelper helper, String option) { 131 String prev = helper.get(XDOCLINT_CUSTOM); 132 String next = (prev == null) ? option : (prev + " " + option); 133 helper.put(XDOCLINT_CUSTOM.text, next); 134 return false; 135 } 136 }, 137 138 XDOCLINT_PACKAGE("-Xdoclint/package:", "opt.Xdoclint.package.args", "opt.Xdoclint.package.desc", EXTENDED, BASIC) { 139 @Override 140 public boolean matches(String option) { 141 return DocLint.isValidOption( 142 option.replace(XDOCLINT_PACKAGE.text, DocLint.XCHECK_PACKAGE)); 143 } 144 145 @Override 146 public boolean process(OptionHelper helper, String option) { 147 String prev = helper.get(XDOCLINT_PACKAGE); 148 String next = (prev == null) ? option : (prev + " " + option); 149 helper.put(XDOCLINT_PACKAGE.text, next); 150 return false; 151 } 152 }, 153 154 // -nowarn is retained for command-line backward compatibility 155 NOWARN("-nowarn", "opt.nowarn", STANDARD, BASIC) { 156 @Override 157 public boolean process(OptionHelper helper, String option) { 158 helper.put("-Xlint:none", option); 159 return false; 160 } 161 }, 162 163 VERBOSE("-verbose", "opt.verbose", STANDARD, BASIC), 164 165 // -deprecation is retained for command-line backward compatibility 166 DEPRECATION("-deprecation", "opt.deprecation", STANDARD, BASIC) { 167 @Override 168 public boolean process(OptionHelper helper, String option) { 169 helper.put("-Xlint:deprecation", option); 170 return false; 171 } 172 }, 173 174 CLASSPATH("-classpath", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER), 175 176 CP("-cp", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER) { 177 @Override 178 public boolean process(OptionHelper helper, String option, String arg) { 179 return super.process(helper, "-classpath", arg); 180 } 181 }, 182 183 SOURCEPATH("-sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER), 184 185 BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) { 186 @Override 187 public boolean process(OptionHelper helper, String option, String arg) { 188 helper.remove("-Xbootclasspath/p:"); 189 helper.remove("-Xbootclasspath/a:"); 190 return super.process(helper, option, arg); 191 } 192 }, 193 194 XBOOTCLASSPATH_PREPEND("-Xbootclasspath/p:", "opt.arg.path", "opt.Xbootclasspath.p", EXTENDED, FILEMANAGER), 195 196 XBOOTCLASSPATH_APPEND("-Xbootclasspath/a:", "opt.arg.path", "opt.Xbootclasspath.a", EXTENDED, FILEMANAGER), 197 198 XBOOTCLASSPATH("-Xbootclasspath:", "opt.arg.path", "opt.bootclasspath", EXTENDED, FILEMANAGER) { 199 @Override 200 public boolean process(OptionHelper helper, String option, String arg) { 201 helper.remove("-Xbootclasspath/p:"); 202 helper.remove("-Xbootclasspath/a:"); 203 return super.process(helper, "-bootclasspath", arg); 204 } 205 }, 206 207 EXTDIRS("-extdirs", "opt.arg.dirs", "opt.extdirs", STANDARD, FILEMANAGER), 208 209 DJAVA_EXT_DIRS("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs", EXTENDED, FILEMANAGER) { 210 @Override 211 public boolean process(OptionHelper helper, String option, String arg) { 212 return super.process(helper, "-extdirs", arg); 213 } 214 }, 215 216 ENDORSEDDIRS("-endorseddirs", "opt.arg.dirs", "opt.endorseddirs", STANDARD, FILEMANAGER), 217 218 DJAVA_ENDORSED_DIRS("-Djava.endorsed.dirs=", "opt.arg.dirs", "opt.endorseddirs", EXTENDED, FILEMANAGER) { 219 @Override 220 public boolean process(OptionHelper helper, String option, String arg) { 221 return super.process(helper, "-endorseddirs", arg); 222 } 223 }, 224 225 PROC("-proc:", "opt.proc.none.only", STANDARD, BASIC, ONEOF, "none", "only"), 226 227 PROCESSOR("-processor", "opt.arg.class.list", "opt.processor", STANDARD, BASIC), 228 229 PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER), 230 231 PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC), 232 233 D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER), 234 235 S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER), 236 237 H("-h", "opt.arg.directory", "opt.headerDest", STANDARD, FILEMANAGER), 238 239 IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"), 240 241 ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) { 242 @Override 243 public boolean process(OptionHelper helper, String option, String operand) { 244 return super.process(helper, option, operand); 245 } 246 247 }, 248 249 SOURCE("-source", "opt.arg.release", "opt.source", STANDARD, BASIC) { 250 @Override 251 public boolean process(OptionHelper helper, String option, String operand) { 252 Source source = Source.lookup(operand); 253 if (source == null) { 254 helper.error("err.invalid.source", operand); 255 return true; 256 } 257 return super.process(helper, option, operand); 258 } 259 }, 260 261 TARGET("-target", "opt.arg.release", "opt.target", STANDARD, BASIC) { 262 @Override 263 public boolean process(OptionHelper helper, String option, String operand) { 264 Target target = Target.lookup(operand); 265 if (target == null) { 266 helper.error("err.invalid.target", operand); 267 return true; 268 } 269 return super.process(helper, option, operand); 270 } 271 }, 272 273 RELEASE("-release", "opt.arg.release", "opt.release", STANDARD, BASIC) { 274 @Override 275 void help(Log log, OptionKind kind) { 276 if (this.kind != kind) 277 return; 278 279 Iterable<PlatformProvider> providers = 280 ServiceLoader.load(PlatformProvider.class, Arguments.class.getClassLoader()); 281 Set<String> platforms = StreamSupport.stream(providers.spliterator(), false) 282 .flatMap(provider -> StreamSupport.stream(provider.getSupportedPlatformNames() 283 .spliterator(), 284 false)) 285 .collect(Collectors.toCollection(TreeSet :: new)); 286 287 StringBuilder targets = new StringBuilder(); 288 String delim = ""; 289 for (String platform : platforms) { 290 targets.append(delim); 291 targets.append(platform); 292 delim = ", "; 293 } 294 295 log.printRawLines(WriterKind.NOTICE, 296 String.format(HELP_LINE_FORMAT, 297 super.helpSynopsis(log), 298 log.localize(PrefixKind.JAVAC, descrKey, targets.toString()))); 299 } 300 }, 301 302 PROFILE("-profile", "opt.arg.profile", "opt.profile", STANDARD, BASIC) { 303 @Override 304 public boolean process(OptionHelper helper, String option, String operand) { 305 Profile profile = Profile.lookup(operand); 306 if (profile == null) { 307 helper.error("err.invalid.profile", operand); 308 return true; 309 } 310 return super.process(helper, option, operand); 311 } 312 }, 313 314 VERSION("-version", "opt.version", STANDARD, INFO) { 315 @Override 316 public boolean process(OptionHelper helper, String option) { 317 Log log = helper.getLog(); 318 String ownName = helper.getOwnName(); 319 log.printLines(PrefixKind.JAVAC, "version", ownName, JavaCompiler.version()); 320 return super.process(helper, option); 321 } 322 }, 323 324 FULLVERSION("-fullversion", null, HIDDEN, INFO) { 325 @Override 326 public boolean process(OptionHelper helper, String option) { 327 Log log = helper.getLog(); 328 String ownName = helper.getOwnName(); 329 log.printLines(PrefixKind.JAVAC, "fullVersion", ownName, JavaCompiler.fullVersion()); 330 return super.process(helper, option); 331 } 332 }, 333 334 DIAGS("-XDdiags=", null, HIDDEN, INFO) { 335 @Override 336 public boolean process(OptionHelper helper, String option) { 337 option = option.substring(option.indexOf('=') + 1); 338 String diagsOption = option.contains("%") ? 339 "-XDdiagsFormat=" : 340 "-XDdiags="; 341 diagsOption += option; 342 if (XD.matches(diagsOption)) 343 return XD.process(helper, diagsOption); 344 else 345 return false; 346 } 347 }, 348 349 HELP("-help", "opt.help", STANDARD, INFO) { 350 @Override 351 public boolean process(OptionHelper helper, String option) { 352 Log log = helper.getLog(); 353 String ownName = helper.getOwnName(); 354 log.printLines(PrefixKind.JAVAC, "msg.usage.header", ownName); 355 for (Option o: getJavaCompilerOptions()) { 356 o.help(log, OptionKind.STANDARD); 357 } 358 log.printNewline(); 359 return super.process(helper, option); 360 } 361 }, 362 363 A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, true) { 364 @Override 365 public boolean matches(String arg) { 366 return arg.startsWith("-A"); 367 } 368 369 @Override 370 public boolean hasArg() { 371 return false; 372 } 373 // Mapping for processor options created in 374 // JavacProcessingEnvironment 375 @Override 376 public boolean process(OptionHelper helper, String option) { 377 int argLength = option.length(); 378 if (argLength == 2) { 379 helper.error("err.empty.A.argument"); 380 return true; 381 } 382 int sepIndex = option.indexOf('='); 383 String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); 384 if (!JavacProcessingEnvironment.isValidOptionName(key)) { 385 helper.error("err.invalid.A.key", option); 386 return true; 387 } 388 return process(helper, option, option); 389 } 390 }, 391 392 X("-X", "opt.X", STANDARD, INFO) { 393 @Override 394 public boolean process(OptionHelper helper, String option) { 395 Log log = helper.getLog(); 396 for (Option o: getJavaCompilerOptions()) { 397 o.help(log, OptionKind.EXTENDED); 398 } 399 log.printNewline(); 400 log.printLines(PrefixKind.JAVAC, "msg.usage.nonstandard.footer"); 401 return super.process(helper, option); 402 } 403 }, 404 405 // This option exists only for the purpose of documenting itself. 406 // It's actually implemented by the launcher. 407 J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, true) { 408 @Override 409 public boolean process(OptionHelper helper, String option) { 410 throw new AssertionError 411 ("the -J flag should be caught by the launcher."); 412 } 413 }, 414 415 MOREINFO("-moreinfo", null, HIDDEN, BASIC) { 416 @Override 417 public boolean process(OptionHelper helper, String option) { 418 Type.moreInfo = true; 419 return super.process(helper, option); 420 } 421 }, 422 423 // treat warnings as errors 424 WERROR("-Werror", "opt.Werror", STANDARD, BASIC), 425 426 // prompt after each error 427 // new Option("-prompt", "opt.prompt"), 428 PROMPT("-prompt", null, HIDDEN, BASIC), 429 430 // dump stack on error 431 DOE("-doe", null, HIDDEN, BASIC), 432 433 // output source after type erasure 434 PRINTSOURCE("-printsource", null, HIDDEN, BASIC), 435 436 // display warnings for generic unchecked operations 437 WARNUNCHECKED("-warnunchecked", null, HIDDEN, BASIC) { 438 @Override 439 public boolean process(OptionHelper helper, String option) { 440 helper.put("-Xlint:unchecked", option); 441 return false; 442 } 443 }, 444 445 XMAXERRS("-Xmaxerrs", "opt.arg.number", "opt.maxerrs", EXTENDED, BASIC), 446 447 XMAXWARNS("-Xmaxwarns", "opt.arg.number", "opt.maxwarns", EXTENDED, BASIC), 448 449 XSTDOUT("-Xstdout", "opt.arg.file", "opt.Xstdout", EXTENDED, INFO) { 450 @Override 451 public boolean process(OptionHelper helper, String option, String arg) { 452 try { 453 Log log = helper.getLog(); 454 log.setWriters(new PrintWriter(new FileWriter(arg), true)); 455 } catch (java.io.IOException e) { 456 helper.error("err.error.writing.file", arg, e); 457 return true; 458 } 459 return super.process(helper, option, arg); 460 } 461 }, 462 463 XPRINT("-Xprint", "opt.print", EXTENDED, BASIC), 464 465 XPRINTROUNDS("-XprintRounds", "opt.printRounds", EXTENDED, BASIC), 466 467 XPRINTPROCESSORINFO("-XprintProcessorInfo", "opt.printProcessorInfo", EXTENDED, BASIC), 468 469 XPREFER("-Xprefer:", "opt.prefer", EXTENDED, BASIC, ONEOF, "source", "newer"), 470 471 XXUSERPATHSFIRST("-XXuserPathsFirst", "opt.userpathsfirst", HIDDEN, BASIC), 472 473 // see enum PkgInfo 474 XPKGINFO("-Xpkginfo:", "opt.pkginfo", EXTENDED, BASIC, ONEOF, "always", "legacy", "nonempty"), 475 476 /* -O is a no-op, accepted for backward compatibility. */ 477 O("-O", null, HIDDEN, BASIC), 478 479 /* -Xjcov produces tables to support the code coverage tool jcov. */ 480 XJCOV("-Xjcov", null, HIDDEN, BASIC), 481 482 PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) { 483 @Override 484 public boolean process(OptionHelper helper, String option) { 485 String p = option.substring(option.indexOf(':') + 1); 486 String prev = helper.get(PLUGIN); 487 helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p.trim()); 488 return false; 489 } 490 }, 491 492 XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"), 493 494 /* This is a back door to the compiler's option table. 495 * -XDx=y sets the option x to the value y. 496 * -XDx sets the option x to the value x. 497 */ 498 XD("-XD", null, HIDDEN, BASIC) { 499 @Override 500 public boolean matches(String s) { 501 return s.startsWith(text); 502 } 503 @Override 504 public boolean process(OptionHelper helper, String option) { 505 option = option.substring(text.length()); 506 int eq = option.indexOf('='); 507 String key = (eq < 0) ? option : option.substring(0, eq); 508 String value = (eq < 0) ? option : option.substring(eq+1); 509 helper.put(key, value); 510 return false; 511 } 512 }, 513 514 // This option exists only for the purpose of documenting itself. 515 // It's actually implemented by the CommandLine class. 516 AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) { 517 @Override 518 public boolean process(OptionHelper helper, String option) { 519 throw new AssertionError("the @ flag should be caught by CommandLine."); 520 } 521 }, 522 523 /* 524 * TODO: With apt, the matches method accepts anything if 525 * -XclassAsDecls is used; code elsewhere does the lookup to 526 * see if the class name is both legal and found. 527 * 528 * In apt, the process method adds the candidate class file 529 * name to a separate list. 530 */ 531 SOURCEFILE("sourcefile", null, HIDDEN, INFO) { 532 @Override 533 public boolean matches(String s) { 534 return s.endsWith(".java") // Java source file 535 || SourceVersion.isName(s); // Legal type name 536 } 537 @Override 538 public boolean process(OptionHelper helper, String option) { 539 if (option.endsWith(".java") ) { 540 File f = new File(option); 541 if (!f.exists()) { 542 helper.error("err.file.not.found", f); 543 return true; 544 } 545 if (!f.isFile()) { 546 helper.error("err.file.not.file", f); 547 return true; 548 } 549 helper.addFile(f); 550 } else { 551 helper.addClassName(option); 552 } 553 return false; 554 } 555 }; 556 557 /** The kind of an Option. This is used by the -help and -X options. */ 558 public enum OptionKind { 559 /** A standard option, documented by -help. */ 560 STANDARD, 561 /** An extended option, documented by -X. */ 562 EXTENDED, 563 /** A hidden option, not documented. */ 564 HIDDEN, 565 } 566 567 /** The group for an Option. This determines the situations in which the 568 * option is applicable. */ 569 enum OptionGroup { 570 /** A basic option, available for use on the command line or via the 571 * Compiler API. */ 572 BASIC, 573 /** An option for javac's standard JavaFileManager. Other file managers 574 * may or may not support these options. */ 575 FILEMANAGER, 576 /** A command-line option that requests information, such as -help. */ 577 INFO, 578 /** A command-line "option" representing a file or class name. */ 579 OPERAND 580 } 581 582 /** The kind of choice for "choice" options. */ 583 enum ChoiceKind { 584 /** The expected value is exactly one of the set of choices. */ 585 ONEOF, 586 /** The expected value is one of more of the set of choices. */ 587 ANYOF 588 } 589 590 public final String text; 591 592 final OptionKind kind; 593 594 final OptionGroup group; 595 596 /** Documentation key for arguments. 597 */ 598 final String argsNameKey; 599 600 /** Documentation key for description. 601 */ 602 final String descrKey; 603 604 /** Suffix option (-foo=bar or -foo:bar) 605 */ 606 final boolean hasSuffix; 607 608 /** The kind of choices for this option, if any. 609 */ 610 final ChoiceKind choiceKind; 611 612 /** The choices for this option, if any, and whether or not the choices 613 * are hidden 614 */ 615 final Map<String,Boolean> choices; 616 617 618 Option(String text, String descrKey, 619 OptionKind kind, OptionGroup group) { 620 this(text, null, descrKey, kind, group, null, null, false); 621 } 622 623 Option(String text, String argsNameKey, String descrKey, 624 OptionKind kind, OptionGroup group) { 625 this(text, argsNameKey, descrKey, kind, group, null, null, false); 626 } 627 628 Option(String text, String argsNameKey, String descrKey, 629 OptionKind kind, OptionGroup group, boolean doHasSuffix) { 630 this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix); 631 } 632 633 Option(String text, OptionKind kind, OptionGroup group, 634 ChoiceKind choiceKind, Map<String,Boolean> choices) { 635 this(text, null, null, kind, group, choiceKind, choices, false); 636 } 637 638 Option(String text, String descrKey, 639 OptionKind kind, OptionGroup group, 640 ChoiceKind choiceKind, String... choices) { 641 this(text, null, descrKey, kind, group, choiceKind, 642 createChoices(choices), false); 643 } 644 // where 645 private static Map<String,Boolean> createChoices(String... choices) { 646 Map<String,Boolean> map = new LinkedHashMap<>(); 647 for (String c: choices) 648 map.put(c, false); 649 return map; 650 } 651 652 private Option(String text, String argsNameKey, String descrKey, 653 OptionKind kind, OptionGroup group, 654 ChoiceKind choiceKind, Map<String,Boolean> choices, 655 boolean doHasSuffix) { 656 this.text = text; 657 this.argsNameKey = argsNameKey; 658 this.descrKey = descrKey; 659 this.kind = kind; 660 this.group = group; 661 this.choiceKind = choiceKind; 662 this.choices = choices; 663 char lastChar = text.charAt(text.length()-1); 664 this.hasSuffix = doHasSuffix || lastChar == ':' || lastChar == '='; 665 } 666 667 public String getText() { 668 return text; 669 } 670 671 public OptionKind getKind() { 672 return kind; 673 } 674 675 public boolean hasArg() { 676 return argsNameKey != null && !hasSuffix; 677 } 678 679 public boolean matches(String option) { 680 if (!hasSuffix) 681 return option.equals(text); 682 683 if (!option.startsWith(text)) 684 return false; 685 686 if (choices != null) { 687 String arg = option.substring(text.length()); 688 if (choiceKind == ChoiceKind.ONEOF) 689 return choices.keySet().contains(arg); 690 else { 691 for (String a: arg.split(",+")) { 692 if (!choices.keySet().contains(a)) 693 return false; 694 } 695 } 696 } 697 698 return true; 699 } 700 701 public boolean process(OptionHelper helper, String option, String arg) { 702 if (choices != null) { 703 if (choiceKind == ChoiceKind.ONEOF) { 704 // some clients like to see just one of option+choice set 705 for (String s: choices.keySet()) 706 helper.remove(option + s); 707 String opt = option + arg; 708 helper.put(opt, opt); 709 // some clients like to see option (without trailing ":") 710 // set to arg 711 String nm = option.substring(0, option.length() - 1); 712 helper.put(nm, arg); 713 } else { 714 // set option+word for each word in arg 715 for (String a: arg.split(",+")) { 716 String opt = option + a; 717 helper.put(opt, opt); 718 } 719 } 720 } 721 helper.put(option, arg); 722 if (group == OptionGroup.FILEMANAGER) 723 helper.handleFileManagerOption(this, arg); 724 return false; 725 } 726 727 public boolean process(OptionHelper helper, String option) { 728 if (hasSuffix) 729 return process(helper, text, option.substring(text.length())); 730 else 731 return process(helper, option, option); 732 } 733 734 private static final String HELP_LINE_FORMAT = " %-26s %s"; 735 736 void help(Log log, OptionKind kind) { 737 if (this.kind != kind) 738 return; 739 740 log.printRawLines(WriterKind.NOTICE, 741 String.format(HELP_LINE_FORMAT, 742 helpSynopsis(log), 743 log.localize(PrefixKind.JAVAC, descrKey))); 744 745 } 746 747 private String helpSynopsis(Log log) { 748 StringBuilder sb = new StringBuilder(); 749 sb.append(text); 750 if (argsNameKey == null) { 751 if (choices != null) { 752 String sep = "{"; 753 for (Map.Entry<String,Boolean> e: choices.entrySet()) { 754 if (!e.getValue()) { 755 sb.append(sep); 756 sb.append(e.getKey()); 757 sep = ","; 758 } 759 } 760 sb.append("}"); 761 } 762 } else { 763 if (!hasSuffix) 764 sb.append(" "); 765 sb.append(log.localize(PrefixKind.JAVAC, argsNameKey)); 766 767 } 768 769 return sb.toString(); 770 } 771 772 // For -XpkgInfo:value 773 public enum PkgInfo { 774 /** 775 * Always generate package-info.class for every package-info.java file. 776 * The file may be empty if there annotations with a RetentionPolicy 777 * of CLASS or RUNTIME. This option may be useful in conjunction with 778 * build systems (such as Ant) that expect javac to generate at least 779 * one .class file for every .java file. 780 */ 781 ALWAYS, 782 /** 783 * Generate a package-info.class file if package-info.java contains 784 * annotations. The file may be empty if all the annotations have 785 * a RetentionPolicy of SOURCE. 786 * This value is just for backwards compatibility with earlier behavior. 787 * Either of the other two values are to be preferred to using this one. 788 */ 789 LEGACY, 790 /** 791 * Generate a package-info.class file if and only if there are annotations 792 * in package-info.java to be written into it. 793 */ 794 NONEMPTY; 795 796 public static PkgInfo get(Options options) { 797 String v = options.get(XPKGINFO); 798 return (v == null 799 ? PkgInfo.LEGACY 800 : PkgInfo.valueOf(StringUtils.toUpperCase(v))); 801 } 802 } 803 804 private static Map<String,Boolean> getXLintChoices() { 805 Map<String,Boolean> choices = new LinkedHashMap<>(); 806 choices.put("all", false); 807 for (Lint.LintCategory c : Lint.LintCategory.values()) 808 choices.put(c.option, c.hidden); 809 for (Lint.LintCategory c : Lint.LintCategory.values()) 810 choices.put("-" + c.option, c.hidden); 811 choices.put("none", false); 812 return choices; 813 } 814 815 static Set<Option> getJavaCompilerOptions() { 816 return EnumSet.allOf(Option.class); 817 } 818 819 public static Set<Option> getJavacFileManagerOptions() { 820 return getOptions(EnumSet.of(FILEMANAGER)); 821 } 822 823 public static Set<Option> getJavacToolOptions() { 824 return getOptions(EnumSet.of(BASIC)); 825 } 826 827 static Set<Option> getOptions(Set<OptionGroup> desired) { 828 Set<Option> options = EnumSet.noneOf(Option.class); 829 for (Option option : Option.values()) 830 if (desired.contains(option.group)) 831 options.add(option); 832 return Collections.unmodifiableSet(options); 833 } 834 835} 836