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