Mon, 07 Mar 2011 13:45:06 -0800
6980021: javac should document @file command line option
Reviewed-by: mcimadamore
1 /*
2 * Copyright (c) 2006, 2010, 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 */
26 package com.sun.tools.javac.main;
28 import com.sun.tools.javac.code.Lint;
29 import com.sun.tools.javac.code.Source;
30 import com.sun.tools.javac.code.Type;
31 import com.sun.tools.javac.jvm.Target;
32 import com.sun.tools.javac.main.JavacOption.HiddenOption;
33 import com.sun.tools.javac.main.JavacOption.Option;
34 import com.sun.tools.javac.main.JavacOption.XOption;
35 import com.sun.tools.javac.util.ListBuffer;
36 import com.sun.tools.javac.util.Options;
37 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
38 import java.io.File;
39 import java.io.FileWriter;
40 import java.io.PrintWriter;
41 import java.util.EnumSet;
42 import java.util.LinkedHashMap;
43 import java.util.Map;
44 import java.util.Set;
45 import javax.lang.model.SourceVersion;
47 import static com.sun.tools.javac.main.OptionName.*;
49 /**
50 * TODO: describe com.sun.tools.javac.main.RecognizedOptions
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
54 * risk. This code and its internal interfaces are subject to change
55 * or deletion without notice.</b></p>
56 */
57 public class RecognizedOptions {
59 private RecognizedOptions() {}
61 public interface OptionHelper {
63 void setOut(PrintWriter out);
65 void error(String key, Object... args);
67 void printVersion();
69 void printFullVersion();
71 void printHelp();
73 void printXhelp();
75 void addFile(File f);
77 void addClassName(String s);
79 }
81 public static class GrumpyHelper implements OptionHelper {
83 public void setOut(PrintWriter out) {
84 throw new IllegalArgumentException();
85 }
87 public void error(String key, Object... args) {
88 throw new IllegalArgumentException(Main.getLocalizedString(key, args));
89 }
91 public void printVersion() {
92 throw new IllegalArgumentException();
93 }
95 public void printFullVersion() {
96 throw new IllegalArgumentException();
97 }
99 public void printHelp() {
100 throw new IllegalArgumentException();
101 }
103 public void printXhelp() {
104 throw new IllegalArgumentException();
105 }
107 public void addFile(File f) {
108 throw new IllegalArgumentException(f.getPath());
109 }
111 public void addClassName(String s) {
112 throw new IllegalArgumentException(s);
113 }
115 }
117 static Set<OptionName> javacOptions = EnumSet.of(
118 G,
119 G_NONE,
120 G_CUSTOM,
121 XLINT,
122 XLINT_CUSTOM,
123 NOWARN,
124 VERBOSE,
125 DEPRECATION,
126 CLASSPATH,
127 CP,
128 SOURCEPATH,
129 BOOTCLASSPATH,
130 XBOOTCLASSPATH_PREPEND,
131 XBOOTCLASSPATH_APPEND,
132 XBOOTCLASSPATH,
133 EXTDIRS,
134 DJAVA_EXT_DIRS,
135 ENDORSEDDIRS,
136 DJAVA_ENDORSED_DIRS,
137 PROC,
138 PROCESSOR,
139 PROCESSORPATH,
140 D,
141 S,
142 IMPLICIT,
143 ENCODING,
144 SOURCE,
145 TARGET,
146 VERSION,
147 FULLVERSION,
148 DIAGS,
149 HELP,
150 A,
151 X,
152 J,
153 MOREINFO,
154 WERROR,
155 // COMPLEXINFERENCE,
156 PROMPT,
157 DOE,
158 PRINTSOURCE,
159 WARNUNCHECKED,
160 XMAXERRS,
161 XMAXWARNS,
162 XSTDOUT,
163 XPKGINFO,
164 XPRINT,
165 XPRINTROUNDS,
166 XPRINTPROCESSORINFO,
167 XPREFER,
168 O,
169 XJCOV,
170 XD,
171 AT,
172 SOURCEFILE);
174 static Set<OptionName> javacFileManagerOptions = EnumSet.of(
175 CLASSPATH,
176 CP,
177 SOURCEPATH,
178 BOOTCLASSPATH,
179 XBOOTCLASSPATH_PREPEND,
180 XBOOTCLASSPATH_APPEND,
181 XBOOTCLASSPATH,
182 EXTDIRS,
183 DJAVA_EXT_DIRS,
184 ENDORSEDDIRS,
185 DJAVA_ENDORSED_DIRS,
186 PROCESSORPATH,
187 D,
188 S,
189 ENCODING,
190 SOURCE);
192 static Set<OptionName> javacToolOptions = EnumSet.of(
193 G,
194 G_NONE,
195 G_CUSTOM,
196 XLINT,
197 XLINT_CUSTOM,
198 NOWARN,
199 VERBOSE,
200 DEPRECATION,
201 PROC,
202 PROCESSOR,
203 IMPLICIT,
204 SOURCE,
205 TARGET,
206 // VERSION,
207 // FULLVERSION,
208 // HELP,
209 A,
210 // X,
211 // J,
212 MOREINFO,
213 WERROR,
214 // COMPLEXINFERENCE,
215 PROMPT,
216 DOE,
217 PRINTSOURCE,
218 WARNUNCHECKED,
219 XMAXERRS,
220 XMAXWARNS,
221 // XSTDOUT,
222 XPKGINFO,
223 XPRINT,
224 XPRINTROUNDS,
225 XPRINTPROCESSORINFO,
226 XPREFER,
227 O,
228 XJCOV,
229 XD);
231 static Option[] getJavaCompilerOptions(OptionHelper helper) {
232 return getOptions(helper, javacOptions);
233 }
235 public static Option[] getJavacFileManagerOptions(OptionHelper helper) {
236 return getOptions(helper, javacFileManagerOptions);
237 }
239 public static Option[] getJavacToolOptions(OptionHelper helper) {
240 return getOptions(helper, javacToolOptions);
241 }
243 static Option[] getOptions(OptionHelper helper, Set<OptionName> desired) {
244 ListBuffer<Option> options = new ListBuffer<Option>();
245 for (Option option : getAll(helper))
246 if (desired.contains(option.getName()))
247 options.append(option);
248 return options.toArray(new Option[options.length()]);
249 }
251 /**
252 * Get all the recognized options.
253 * @param helper an {@code OptionHelper} to help when processing options
254 * @return an array of options
255 */
256 public static Option[] getAll(final OptionHelper helper) {
257 return new Option[] {
258 new Option(G, "opt.g"),
259 new Option(G_NONE, "opt.g.none") {
260 @Override
261 public boolean process(Options options, String option) {
262 options.put("-g:", "none");
263 return false;
264 }
265 },
267 new Option(G_CUSTOM, "opt.g.lines.vars.source",
268 Option.ChoiceKind.ANYOF, "lines", "vars", "source"),
270 new XOption(XLINT, "opt.Xlint"),
271 new XOption(XLINT_CUSTOM, "opt.Xlint.suboptlist",
272 Option.ChoiceKind.ANYOF, getXLintChoices()),
274 // -nowarn is retained for command-line backward compatibility
275 new Option(NOWARN, "opt.nowarn") {
276 @Override
277 public boolean process(Options options, String option) {
278 options.put("-Xlint:none", option);
279 return false;
280 }
281 },
283 new Option(VERBOSE, "opt.verbose"),
285 // -deprecation is retained for command-line backward compatibility
286 new Option(DEPRECATION, "opt.deprecation") {
287 @Override
288 public boolean process(Options options, String option) {
289 options.put("-Xlint:deprecation", option);
290 return false;
291 }
292 },
294 new Option(CLASSPATH, "opt.arg.path", "opt.classpath"),
295 new Option(CP, "opt.arg.path", "opt.classpath") {
296 @Override
297 public boolean process(Options options, String option, String arg) {
298 return super.process(options, "-classpath", arg);
299 }
300 },
301 new Option(SOURCEPATH, "opt.arg.path", "opt.sourcepath"),
302 new Option(BOOTCLASSPATH, "opt.arg.path", "opt.bootclasspath") {
303 @Override
304 public boolean process(Options options, String option, String arg) {
305 options.remove("-Xbootclasspath/p:");
306 options.remove("-Xbootclasspath/a:");
307 return super.process(options, option, arg);
308 }
309 },
310 new XOption(XBOOTCLASSPATH_PREPEND,"opt.arg.path", "opt.Xbootclasspath.p"),
311 new XOption(XBOOTCLASSPATH_APPEND, "opt.arg.path", "opt.Xbootclasspath.a"),
312 new XOption(XBOOTCLASSPATH, "opt.arg.path", "opt.bootclasspath") {
313 @Override
314 public boolean process(Options options, String option, String arg) {
315 options.remove("-Xbootclasspath/p:");
316 options.remove("-Xbootclasspath/a:");
317 return super.process(options, "-bootclasspath", arg);
318 }
319 },
320 new Option(EXTDIRS, "opt.arg.dirs", "opt.extdirs"),
321 new XOption(DJAVA_EXT_DIRS, "opt.arg.dirs", "opt.extdirs") {
322 @Override
323 public boolean process(Options options, String option, String arg) {
324 return super.process(options, "-extdirs", arg);
325 }
326 },
327 new Option(ENDORSEDDIRS, "opt.arg.dirs", "opt.endorseddirs"),
328 new XOption(DJAVA_ENDORSED_DIRS, "opt.arg.dirs", "opt.endorseddirs") {
329 @Override
330 public boolean process(Options options, String option, String arg) {
331 return super.process(options, "-endorseddirs", arg);
332 }
333 },
334 new Option(PROC, "opt.proc.none.only",
335 Option.ChoiceKind.ONEOF, "none", "only"),
336 new Option(PROCESSOR, "opt.arg.class.list", "opt.processor"),
337 new Option(PROCESSORPATH, "opt.arg.path", "opt.processorpath"),
338 new Option(D, "opt.arg.directory", "opt.d"),
339 new Option(S, "opt.arg.directory", "opt.sourceDest"),
340 new Option(IMPLICIT, "opt.implicit",
341 Option.ChoiceKind.ONEOF, "none", "class"),
342 new Option(ENCODING, "opt.arg.encoding", "opt.encoding"),
343 new Option(SOURCE, "opt.arg.release", "opt.source") {
344 @Override
345 public boolean process(Options options, String option, String operand) {
346 Source source = Source.lookup(operand);
347 if (source == null) {
348 helper.error("err.invalid.source", operand);
349 return true;
350 }
351 return super.process(options, option, operand);
352 }
353 },
354 new Option(TARGET, "opt.arg.release", "opt.target") {
355 @Override
356 public boolean process(Options options, String option, String operand) {
357 Target target = Target.lookup(operand);
358 if (target == null) {
359 helper.error("err.invalid.target", operand);
360 return true;
361 }
362 return super.process(options, option, operand);
363 }
364 },
365 new Option(VERSION, "opt.version") {
366 @Override
367 public boolean process(Options options, String option) {
368 helper.printVersion();
369 return super.process(options, option);
370 }
371 },
372 new HiddenOption(FULLVERSION) {
373 @Override
374 public boolean process(Options options, String option) {
375 helper.printFullVersion();
376 return super.process(options, option);
377 }
378 },
379 new HiddenOption(DIAGS) {
380 @Override
381 public boolean process(Options options, String option) {
382 Option xd = getOptions(helper, EnumSet.of(XD))[0];
383 option = option.substring(option.indexOf('=') + 1);
384 String diagsOption = option.contains("%") ?
385 "-XDdiagsFormat=" :
386 "-XDdiags=";
387 diagsOption += option;
388 if (xd.matches(diagsOption))
389 return xd.process(options, diagsOption);
390 else
391 return false;
392 }
393 },
394 new Option(HELP, "opt.help") {
395 @Override
396 public boolean process(Options options, String option) {
397 helper.printHelp();
398 return super.process(options, option);
399 }
400 },
401 new Option(A, "opt.arg.key.equals.value","opt.A") {
402 @Override
403 String helpSynopsis() {
404 hasSuffix = true;
405 return super.helpSynopsis();
406 }
408 @Override
409 public boolean matches(String arg) {
410 return arg.startsWith("-A");
411 }
413 @Override
414 public boolean hasArg() {
415 return false;
416 }
417 // Mapping for processor options created in
418 // JavacProcessingEnvironment
419 @Override
420 public boolean process(Options options, String option) {
421 int argLength = option.length();
422 if (argLength == 2) {
423 helper.error("err.empty.A.argument");
424 return true;
425 }
426 int sepIndex = option.indexOf('=');
427 String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) );
428 if (!JavacProcessingEnvironment.isValidOptionName(key)) {
429 helper.error("err.invalid.A.key", option);
430 return true;
431 }
432 return process(options, option, option);
433 }
434 },
435 new Option(X, "opt.X") {
436 @Override
437 public boolean process(Options options, String option) {
438 helper.printXhelp();
439 return super.process(options, option);
440 }
441 },
443 // This option exists only for the purpose of documenting itself.
444 // It's actually implemented by the launcher.
445 new Option(J, "opt.arg.flag", "opt.J") {
446 @Override
447 String helpSynopsis() {
448 hasSuffix = true;
449 return super.helpSynopsis();
450 }
451 @Override
452 public boolean process(Options options, String option) {
453 throw new AssertionError
454 ("the -J flag should be caught by the launcher.");
455 }
456 },
458 // stop after parsing and attributing.
459 // new HiddenOption("-attrparseonly"),
461 // new Option("-moreinfo", "opt.moreinfo") {
462 new HiddenOption(MOREINFO) {
463 @Override
464 public boolean process(Options options, String option) {
465 Type.moreInfo = true;
466 return super.process(options, option);
467 }
468 },
470 // treat warnings as errors
471 new Option(WERROR, "opt.Werror"),
473 // use complex inference from context in the position of a method call argument
474 new HiddenOption(COMPLEXINFERENCE),
476 // generare source stubs
477 // new HiddenOption("-stubs"),
479 // relax some constraints to allow compiling from stubs
480 // new HiddenOption("-relax"),
482 // output source after translating away inner classes
483 // new Option("-printflat", "opt.printflat"),
484 // new HiddenOption("-printflat"),
486 // display scope search details
487 // new Option("-printsearch", "opt.printsearch"),
488 // new HiddenOption("-printsearch"),
490 // prompt after each error
491 // new Option("-prompt", "opt.prompt"),
492 new HiddenOption(PROMPT),
494 // dump stack on error
495 new HiddenOption(DOE),
497 // output source after type erasure
498 // new Option("-s", "opt.s"),
499 new HiddenOption(PRINTSOURCE),
501 // output shrouded class files
502 // new Option("-scramble", "opt.scramble"),
503 // new Option("-scrambleall", "opt.scrambleall"),
505 // display warnings for generic unchecked operations
506 new HiddenOption(WARNUNCHECKED) {
507 @Override
508 public boolean process(Options options, String option) {
509 options.put("-Xlint:unchecked", option);
510 return false;
511 }
512 },
514 new XOption(XMAXERRS, "opt.arg.number", "opt.maxerrs"),
515 new XOption(XMAXWARNS, "opt.arg.number", "opt.maxwarns"),
516 new XOption(XSTDOUT, "opt.arg.file", "opt.Xstdout") {
517 @Override
518 public boolean process(Options options, String option, String arg) {
519 try {
520 helper.setOut(new PrintWriter(new FileWriter(arg), true));
521 } catch (java.io.IOException e) {
522 helper.error("err.error.writing.file", arg, e);
523 return true;
524 }
525 return super.process(options, option, arg);
526 }
527 },
529 new XOption(XPRINT, "opt.print"),
531 new XOption(XPRINTROUNDS, "opt.printRounds"),
533 new XOption(XPRINTPROCESSORINFO, "opt.printProcessorInfo"),
535 new XOption(XPREFER, "opt.prefer",
536 Option.ChoiceKind.ONEOF, "source", "newer"),
538 new XOption(XPKGINFO, "opt.pkginfo",
539 Option.ChoiceKind.ONEOF, "always", "legacy", "nonempty"),
541 /* -O is a no-op, accepted for backward compatibility. */
542 new HiddenOption(O),
544 /* -Xjcov produces tables to support the code coverage tool jcov. */
545 new HiddenOption(XJCOV),
547 /* This is a back door to the compiler's option table.
548 * -XDx=y sets the option x to the value y.
549 * -XDx sets the option x to the value x.
550 */
551 new HiddenOption(XD) {
552 String s;
553 @Override
554 public boolean matches(String s) {
555 this.s = s;
556 return s.startsWith(name.optionName);
557 }
558 @Override
559 public boolean process(Options options, String option) {
560 s = s.substring(name.optionName.length());
561 int eq = s.indexOf('=');
562 String key = (eq < 0) ? s : s.substring(0, eq);
563 String value = (eq < 0) ? s : s.substring(eq+1);
564 options.put(key, value);
565 return false;
566 }
567 },
569 // This option exists only for the purpose of documenting itself.
570 // It's actually implemented by the CommandLine class.
571 new Option(AT, "opt.arg.file", "opt.AT") {
572 @Override
573 String helpSynopsis() {
574 hasSuffix = true;
575 return super.helpSynopsis();
576 }
577 @Override
578 public boolean process(Options options, String option) {
579 throw new AssertionError
580 ("the @ flag should be caught by CommandLine.");
581 }
582 },
584 /*
585 * TODO: With apt, the matches method accepts anything if
586 * -XclassAsDecls is used; code elsewhere does the lookup to
587 * see if the class name is both legal and found.
588 *
589 * In apt, the process method adds the candidate class file
590 * name to a separate list.
591 */
592 new HiddenOption(SOURCEFILE) {
593 String s;
594 @Override
595 public boolean matches(String s) {
596 this.s = s;
597 return s.endsWith(".java") // Java source file
598 || SourceVersion.isName(s); // Legal type name
599 }
600 @Override
601 public boolean process(Options options, String option) {
602 if (s.endsWith(".java") ) {
603 File f = new File(s);
604 if (!f.exists()) {
605 helper.error("err.file.not.found", f);
606 return true;
607 }
608 if (!f.isFile()) {
609 helper.error("err.file.not.file", f);
610 return true;
611 }
612 helper.addFile(f);
613 }
614 else
615 helper.addClassName(s);
616 return false;
617 }
618 },
619 };
620 }
622 public enum PkgInfo {
623 ALWAYS, LEGACY, NONEMPTY;
624 public static PkgInfo get(Options options) {
625 String v = options.get(XPKGINFO);
626 return (v == null
627 ? PkgInfo.LEGACY
628 : PkgInfo.valueOf(v.toUpperCase()));
629 }
630 }
632 private static Map<String,Boolean> getXLintChoices() {
633 Map<String,Boolean> choices = new LinkedHashMap<String,Boolean>();
634 choices.put("all", false);
635 for (Lint.LintCategory c : Lint.LintCategory.values())
636 choices.put(c.option, c.hidden);
637 for (Lint.LintCategory c : Lint.LintCategory.values())
638 choices.put("-" + c.option, c.hidden);
639 choices.put("none", false);
640 return choices;
641 }
643 }