1 | /* |
2 | * Copyright 2006 Sun Microsystems, Inc. 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. Sun designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
23 | * have any questions. |
24 | */ |
25 | |
26 | package com.sun.tools.javac.main; |
27 | |
28 | import com.sun.tools.javac.code.Source; |
29 | import com.sun.tools.javac.code.Type; |
30 | import com.sun.tools.javac.jvm.Target; |
31 | import com.sun.tools.javac.main.JavacOption.HiddenOption; |
32 | import com.sun.tools.javac.main.JavacOption.Option; |
33 | import com.sun.tools.javac.main.JavacOption.XOption; |
34 | import com.sun.tools.javac.util.List; |
35 | import com.sun.tools.javac.util.ListBuffer; |
36 | import com.sun.tools.javac.util.Log; |
37 | import com.sun.tools.javac.util.Options; |
38 | import com.sun.tools.javac.processing.JavacProcessingEnvironment; |
39 | import java.io.File; |
40 | import java.io.FileWriter; |
41 | import java.io.PrintWriter; |
42 | import java.util.EnumSet; |
43 | import java.util.Set; |
44 | import java.util.StringTokenizer; |
45 | import javax.lang.model.SourceVersion; |
46 | |
47 | import static com.sun.tools.javac.main.OptionName.*; |
48 | |
49 | /** |
50 | * TODO: describe com.sun.tools.javac.main.RecognizedOptions |
51 | * |
52 | * <p><b>This is NOT part of any API supported by Sun Microsystems. |
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 { |
58 | |
59 | private RecognizedOptions() {} |
60 | |
61 | public interface OptionHelper { |
62 | |
63 | void setOut(PrintWriter out); |
64 | |
65 | void error(String key, Object... args); |
66 | |
67 | void printVersion(); |
68 | |
69 | void printFullVersion(); |
70 | |
71 | void printHelp(); |
72 | |
73 | void printXhelp(); |
74 | |
75 | void addFile(File f); |
76 | |
77 | void addClassName(String s); |
78 | |
79 | } |
80 | |
81 | public static class GrumpyHelper implements OptionHelper { |
82 | |
83 | public void setOut(PrintWriter out) { |
84 | throw new IllegalArgumentException(); |
85 | } |
86 | |
87 | public void error(String key, Object... args) { |
88 | throw new IllegalArgumentException(Main.getLocalizedString(key, args)); |
89 | } |
90 | |
91 | public void printVersion() { |
92 | throw new IllegalArgumentException(); |
93 | } |
94 | |
95 | public void printFullVersion() { |
96 | throw new IllegalArgumentException(); |
97 | } |
98 | |
99 | public void printHelp() { |
100 | throw new IllegalArgumentException(); |
101 | } |
102 | |
103 | public void printXhelp() { |
104 | throw new IllegalArgumentException(); |
105 | } |
106 | |
107 | public void addFile(File f) { |
108 | throw new IllegalArgumentException(f.getPath()); |
109 | } |
110 | |
111 | public void addClassName(String s) { |
112 | throw new IllegalArgumentException(s); |
113 | } |
114 | |
115 | } |
116 | |
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_CUSTOM, |
138 | PROCESSOR, |
139 | PROCESSORPATH, |
140 | D, |
141 | S, |
142 | IMPLICIT, |
143 | ENCODING, |
144 | SOURCE, |
145 | TARGET, |
146 | VERSION, |
147 | FULLVERSION, |
148 | HELP, |
149 | A, |
150 | X, |
151 | J, |
152 | MOREINFO, |
153 | WERROR, |
154 | // COMPLEXINFERENCE, |
155 | PROMPT, |
156 | DOE, |
157 | PRINTSOURCE, |
158 | WARNUNCHECKED, |
159 | XMAXERRS, |
160 | XMAXWARNS, |
161 | XSTDOUT, |
162 | XPRINT, |
163 | XPRINTROUNDS, |
164 | XPRINTPROCESSORINFO, |
165 | XPREFER, |
166 | O, |
167 | XJCOV, |
168 | XD, |
169 | SOURCEFILE); |
170 | |
171 | static Set<OptionName> javacFileManagerOptions = EnumSet.of( |
172 | CLASSPATH, |
173 | CP, |
174 | SOURCEPATH, |
175 | BOOTCLASSPATH, |
176 | XBOOTCLASSPATH_PREPEND, |
177 | XBOOTCLASSPATH_APPEND, |
178 | XBOOTCLASSPATH, |
179 | EXTDIRS, |
180 | DJAVA_EXT_DIRS, |
181 | ENDORSEDDIRS, |
182 | DJAVA_ENDORSED_DIRS, |
183 | PROCESSORPATH, |
184 | D, |
185 | S, |
186 | ENCODING, |
187 | SOURCE); |
188 | |
189 | static Set<OptionName> javacToolOptions = EnumSet.of( |
190 | G, |
191 | G_NONE, |
192 | G_CUSTOM, |
193 | XLINT, |
194 | XLINT_CUSTOM, |
195 | NOWARN, |
196 | VERBOSE, |
197 | DEPRECATION, |
198 | PROC_CUSTOM, |
199 | PROCESSOR, |
200 | IMPLICIT, |
201 | SOURCE, |
202 | TARGET, |
203 | // VERSION, |
204 | // FULLVERSION, |
205 | // HELP, |
206 | A, |
207 | // X, |
208 | // J, |
209 | MOREINFO, |
210 | WERROR, |
211 | // COMPLEXINFERENCE, |
212 | PROMPT, |
213 | DOE, |
214 | PRINTSOURCE, |
215 | WARNUNCHECKED, |
216 | XMAXERRS, |
217 | XMAXWARNS, |
218 | // XSTDOUT, |
219 | XPRINT, |
220 | XPRINTROUNDS, |
221 | XPRINTPROCESSORINFO, |
222 | XPREFER, |
223 | O, |
224 | XJCOV, |
225 | XD); |
226 | |
227 | static Option[] getJavaCompilerOptions(OptionHelper helper) { |
228 | return getOptions(helper, javacOptions); |
229 | } |
230 | |
231 | public static Option[] getJavacFileManagerOptions(OptionHelper helper) { |
232 | return getOptions(helper, javacFileManagerOptions); |
233 | } |
234 | |
235 | public static Option[] getJavacToolOptions(OptionHelper helper) { |
236 | return getOptions(helper, javacToolOptions); |
237 | } |
238 | |
239 | static Option[] getOptions(OptionHelper helper, Set<OptionName> desired) { |
240 | ListBuffer<Option> options = new ListBuffer<Option>(); |
241 | for (Option option : getAll(helper)) |
242 | if (desired.contains(option.getName())) |
243 | options.append(option); |
244 | return options.toArray(new Option[options.length()]); |
245 | } |
246 | |
247 | /** |
248 | * @param out the writer to use for diagnostic output |
249 | */ |
250 | public static Option[] getAll(final OptionHelper helper) { |
251 | return new Option[]{ |
252 | new Option(G, "opt.g"), |
253 | new Option(G_NONE, "opt.g.none") { |
254 | public boolean process(Options options, String option) { |
255 | options.put("-g:", "none"); |
256 | return false; |
257 | } |
258 | }, |
259 | |
260 | new Option(G_CUSTOM, "opt.g.lines.vars.source") { |
261 | public boolean matches(String s) { |
262 | return s.startsWith("-g:"); |
263 | } |
264 | public boolean process(Options options, String option) { |
265 | String suboptions = option.substring(3); |
266 | options.put("-g:", suboptions); |
267 | // enter all the -g suboptions as "-g:suboption" |
268 | for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) { |
269 | String tok = t.nextToken(); |
270 | String opt = "-g:" + tok; |
271 | options.put(opt, opt); |
272 | } |
273 | return false; |
274 | } |
275 | }, |
276 | |
277 | new XOption(XLINT, "opt.Xlint"), |
278 | new XOption(XLINT_CUSTOM, "opt.Xlint.suboptlist") { |
279 | public boolean matches(String s) { |
280 | return s.startsWith("-Xlint:"); |
281 | } |
282 | public boolean process(Options options, String option) { |
283 | String suboptions = option.substring(7); |
284 | options.put("-Xlint:", suboptions); |
285 | // enter all the -Xlint suboptions as "-Xlint:suboption" |
286 | for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) { |
287 | String tok = t.nextToken(); |
288 | String opt = "-Xlint:" + tok; |
289 | options.put(opt, opt); |
290 | } |
291 | return false; |
292 | } |
293 | }, |
294 | |
295 | // -nowarn is retained for command-line backward compatibility |
296 | new Option(NOWARN, "opt.nowarn") { |
297 | public boolean process(Options options, String option) { |
298 | options.put("-Xlint:none", option); |
299 | return false; |
300 | } |
301 | }, |
302 | |
303 | new Option(VERBOSE, "opt.verbose"), |
304 | |
305 | // -deprecation is retained for command-line backward compatibility |
306 | new Option(DEPRECATION, "opt.deprecation") { |
307 | public boolean process(Options options, String option) { |
308 | options.put("-Xlint:deprecation", option); |
309 | return false; |
310 | } |
311 | }, |
312 | |
313 | new Option(CLASSPATH, "opt.arg.path", "opt.classpath"), |
314 | new Option(CP, "opt.arg.path", "opt.classpath") { |
315 | public boolean process(Options options, String option, String arg) { |
316 | return super.process(options, "-classpath", arg); |
317 | } |
318 | }, |
319 | new Option(SOURCEPATH, "opt.arg.path", "opt.sourcepath"), |
320 | new Option(BOOTCLASSPATH, "opt.arg.path", "opt.bootclasspath") { |
321 | public boolean process(Options options, String option, String arg) { |
322 | options.remove("-Xbootclasspath/p:"); |
323 | options.remove("-Xbootclasspath/a:"); |
324 | return super.process(options, option, arg); |
325 | } |
326 | }, |
327 | new XOption(XBOOTCLASSPATH_PREPEND,"opt.arg.path", "opt.Xbootclasspath.p"), |
328 | new XOption(XBOOTCLASSPATH_APPEND, "opt.arg.path", "opt.Xbootclasspath.a"), |
329 | new XOption(XBOOTCLASSPATH, "opt.arg.path", "opt.bootclasspath") { |
330 | public boolean process(Options options, String option, String arg) { |
331 | options.remove("-Xbootclasspath/p:"); |
332 | options.remove("-Xbootclasspath/a:"); |
333 | return super.process(options, "-bootclasspath", arg); |
334 | } |
335 | }, |
336 | new Option(EXTDIRS, "opt.arg.dirs", "opt.extdirs"), |
337 | new XOption(DJAVA_EXT_DIRS, "opt.arg.dirs", "opt.extdirs") { |
338 | public boolean process(Options options, String option, String arg) { |
339 | return super.process(options, "-extdirs", arg); |
340 | } |
341 | }, |
342 | new Option(ENDORSEDDIRS, "opt.arg.dirs", "opt.endorseddirs"), |
343 | new XOption(DJAVA_ENDORSED_DIRS, "opt.arg.dirs", "opt.endorseddirs") { |
344 | public boolean process(Options options, String option, String arg) { |
345 | return super.process(options, "-endorseddirs", arg); |
346 | } |
347 | }, |
348 | new Option(PROC_CUSTOM, "opt.proc.none.only") { |
349 | public boolean matches(String s) { |
350 | return s.equals("-proc:none") || s.equals("-proc:only"); |
351 | } |
352 | |
353 | public boolean process(Options options, String option) { |
354 | if (option.equals("-proc:none")) { |
355 | options.remove("-proc:only"); |
356 | } else { |
357 | options.remove("-proc:none"); |
358 | } |
359 | options.put(option, option); |
360 | return false; |
361 | } |
362 | }, |
363 | new Option(PROCESSOR, "opt.arg.class.list", "opt.processor"), |
364 | new Option(PROCESSORPATH, "opt.arg.path", "opt.processorpath"), |
365 | new Option(D, "opt.arg.directory", "opt.d"), |
366 | new Option(S, "opt.arg.directory", "opt.sourceDest"), |
367 | new Option(IMPLICIT, "opt.implicit") { |
368 | public boolean matches(String s) { |
369 | return s.equals("-implicit:none") || s.equals("-implicit:class"); |
370 | } |
371 | public boolean process(Options options, String option, String operand) { |
372 | int sep = option.indexOf(":"); |
373 | options.put(option.substring(0, sep), option.substring(sep+1)); |
374 | options.put(option,option); |
375 | return false; |
376 | } |
377 | }, |
378 | new Option(ENCODING, "opt.arg.encoding", "opt.encoding"), |
379 | new Option(SOURCE, "opt.arg.release", "opt.source") { |
380 | public boolean process(Options options, String option, String operand) { |
381 | Source source = Source.lookup(operand); |
382 | if (source == null) { |
383 | helper.error("err.invalid.source", operand); |
384 | return true; |
385 | } |
386 | return super.process(options, option, operand); |
387 | } |
388 | }, |
389 | new Option(TARGET, "opt.arg.release", "opt.target") { |
390 | public boolean process(Options options, String option, String operand) { |
391 | Target target = Target.lookup(operand); |
392 | if (target == null) { |
393 | helper.error("err.invalid.target", operand); |
394 | return true; |
395 | } |
396 | return super.process(options, option, operand); |
397 | } |
398 | }, |
399 | new Option(VERSION, "opt.version") { |
400 | public boolean process(Options options, String option) { |
401 | helper.printVersion(); |
402 | return super.process(options, option); |
403 | } |
404 | }, |
405 | new HiddenOption(FULLVERSION) { |
406 | public boolean process(Options options, String option) { |
407 | helper.printFullVersion(); |
408 | return super.process(options, option); |
409 | } |
410 | }, |
411 | new Option(HELP, "opt.help") { |
412 | public boolean process(Options options, String option) { |
413 | helper.printHelp(); |
414 | return super.process(options, option); |
415 | } |
416 | }, |
417 | new Option(A, "opt.arg.key.equals.value","opt.A") { |
418 | String helpSynopsis() { |
419 | hasSuffix = true; |
420 | return super.helpSynopsis(); |
421 | } |
422 | |
423 | public boolean matches(String arg) { |
424 | return arg.startsWith("-A"); |
425 | } |
426 | |
427 | public boolean hasArg() { |
428 | return false; |
429 | } |
430 | // Mapping for processor options created in |
431 | // JavacProcessingEnvironment |
432 | public boolean process(Options options, String option) { |
433 | int argLength = option.length(); |
434 | if (argLength == 2) { |
435 | helper.error("err.empty.A.argument"); |
436 | return true; |
437 | } |
438 | int sepIndex = option.indexOf('='); |
439 | String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); |
440 | if (!JavacProcessingEnvironment.isValidOptionName(key)) { |
441 | helper.error("err.invalid.A.key", option); |
442 | return true; |
443 | } |
444 | return process(options, option, option); |
445 | } |
446 | }, |
447 | new Option(X, "opt.X") { |
448 | public boolean process(Options options, String option) { |
449 | helper.printXhelp(); |
450 | return super.process(options, option); |
451 | } |
452 | }, |
453 | |
454 | // This option exists only for the purpose of documenting itself. |
455 | // It's actually implemented by the launcher. |
456 | new Option(J, "opt.arg.flag", "opt.J") { |
457 | String helpSynopsis() { |
458 | hasSuffix = true; |
459 | return super.helpSynopsis(); |
460 | } |
461 | public boolean process(Options options, String option) { |
462 | throw new AssertionError |
463 | ("the -J flag should be caught by the launcher."); |
464 | } |
465 | }, |
466 | |
467 | // stop after parsing and attributing. |
468 | // new HiddenOption("-attrparseonly"), |
469 | |
470 | // new Option("-moreinfo", "opt.moreinfo") { |
471 | new HiddenOption(MOREINFO) { |
472 | public boolean process(Options options, String option) { |
473 | Type.moreInfo = true; |
474 | return super.process(options, option); |
475 | } |
476 | }, |
477 | |
478 | // treat warnings as errors |
479 | new HiddenOption(WERROR), |
480 | |
481 | // use complex inference from context in the position of a method call argument |
482 | new HiddenOption(COMPLEXINFERENCE), |
483 | |
484 | // generare source stubs |
485 | // new HiddenOption("-stubs"), |
486 | |
487 | // relax some constraints to allow compiling from stubs |
488 | // new HiddenOption("-relax"), |
489 | |
490 | // output source after translating away inner classes |
491 | // new Option("-printflat", "opt.printflat"), |
492 | // new HiddenOption("-printflat"), |
493 | |
494 | // display scope search details |
495 | // new Option("-printsearch", "opt.printsearch"), |
496 | // new HiddenOption("-printsearch"), |
497 | |
498 | // prompt after each error |
499 | // new Option("-prompt", "opt.prompt"), |
500 | new HiddenOption(PROMPT), |
501 | |
502 | // dump stack on error |
503 | new HiddenOption(DOE), |
504 | |
505 | // output source after type erasure |
506 | // new Option("-s", "opt.s"), |
507 | new HiddenOption(PRINTSOURCE), |
508 | |
509 | // output shrouded class files |
510 | // new Option("-scramble", "opt.scramble"), |
511 | // new Option("-scrambleall", "opt.scrambleall"), |
512 | |
513 | // display warnings for generic unchecked operations |
514 | new HiddenOption(WARNUNCHECKED) { |
515 | public boolean process(Options options, String option) { |
516 | options.put("-Xlint:unchecked", option); |
517 | return false; |
518 | } |
519 | }, |
520 | |
521 | new XOption(XMAXERRS, "opt.arg.number", "opt.maxerrs"), |
522 | new XOption(XMAXWARNS, "opt.arg.number", "opt.maxwarns"), |
523 | new XOption(XSTDOUT, "opt.arg.file", "opt.Xstdout") { |
524 | public boolean process(Options options, String option, String arg) { |
525 | try { |
526 | helper.setOut(new PrintWriter(new FileWriter(arg), true)); |
527 | } catch (java.io.IOException e) { |
528 | helper.error("err.error.writing.file", arg, e); |
529 | return true; |
530 | } |
531 | return super.process(options, option, arg); |
532 | } |
533 | }, |
534 | |
535 | new XOption(XPRINT, "opt.print"), |
536 | |
537 | new XOption(XPRINTROUNDS, "opt.printRounds"), |
538 | |
539 | new XOption(XPRINTPROCESSORINFO, "opt.printProcessorInfo"), |
540 | |
541 | new XOption(XPREFER, "opt.prefer") { |
542 | public boolean matches(String s) { |
543 | return s.equals("-Xprefer:source") || s.equals("-Xprefer:newer"); |
544 | } |
545 | public boolean process(Options options, String option, String operand) { |
546 | int sep = option.indexOf(":"); |
547 | options.put(option.substring(0, sep), option.substring(sep+1)); |
548 | options.put(option,option); |
549 | return false; |
550 | } |
551 | }, |
552 | |
553 | /* -O is a no-op, accepted for backward compatibility. */ |
554 | new HiddenOption(O), |
555 | |
556 | /* -Xjcov produces tables to support the code coverage tool jcov. */ |
557 | new HiddenOption(XJCOV), |
558 | |
559 | /* This is a back door to the compiler's option table. |
560 | * -XDx=y sets the option x to the value y. |
561 | * -XDx sets the option x to the value x. |
562 | */ |
563 | new HiddenOption(XD) { |
564 | String s; |
565 | public boolean matches(String s) { |
566 | this.s = s; |
567 | return s.startsWith(name.optionName); |
568 | } |
569 | public boolean process(Options options, String option) { |
570 | s = s.substring(name.optionName.length()); |
571 | int eq = s.indexOf('='); |
572 | String key = (eq < 0) ? s : s.substring(0, eq); |
573 | String value = (eq < 0) ? s : s.substring(eq+1); |
574 | options.put(key, value); |
575 | return false; |
576 | } |
577 | }, |
578 | |
579 | /* |
580 | * TODO: With apt, the matches method accepts anything if |
581 | * -XclassAsDecls is used; code elsewhere does the lookup to |
582 | * see if the class name is both legal and found. |
583 | * |
584 | * In apt, the process method adds the candiate class file |
585 | * name to a separate list. |
586 | */ |
587 | new HiddenOption(SOURCEFILE) { |
588 | String s; |
589 | public boolean matches(String s) { |
590 | this.s = s; |
591 | return s.endsWith(".java") // Java source file |
592 | || SourceVersion.isName(s); // Legal type name |
593 | } |
594 | public boolean process(Options options, String option) { |
595 | if (s.endsWith(".java") ) { |
596 | File f = new File(s); |
597 | if (!f.exists()) { |
598 | helper.error("err.file.not.found", f); |
599 | return true; |
600 | } |
601 | if (!f.isFile()) { |
602 | helper.error("err.file.not.file", f); |
603 | return true; |
604 | } |
605 | helper.addFile(f); |
606 | } |
607 | else |
608 | helper.addClassName(s); |
609 | return false; |
610 | } |
611 | }, |
612 | }; |
613 | } |
614 | |
615 | } |