ToolOption.java revision 3976:8be741555fa6
1/*
2 * Copyright (c) 2012, 2016, 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 jdk.javadoc.internal.tool;
27
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.EnumMap;
31import java.util.LinkedHashMap;
32import java.util.List;
33import java.util.Map;
34
35import javax.lang.model.element.ElementKind;
36
37import com.sun.tools.javac.main.Option;
38import com.sun.tools.javac.main.Option.InvalidValueException;
39import com.sun.tools.javac.main.Option.OptionKind;
40import com.sun.tools.javac.main.OptionHelper;
41import com.sun.tools.javac.util.Options;
42
43import static com.sun.tools.javac.main.Option.OptionKind.*;
44import 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 */
54public 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    // ----- help options -----
333
334    HELP("--help -help", STANDARD) {
335        @Override
336        public void process(Helper helper) throws OptionException {
337            throw new OptionException(OK, helper::usage);
338        }
339    },
340
341    X("-X", STANDARD) {
342        @Override
343        public void process(Helper helper) throws OptionException {
344           throw new OptionException(OK, helper::Xusage);
345        }
346    },
347
348    // This option exists only for the purpose of documenting itself.
349    // It's actually implemented by the launcher.
350    J("-J", STANDARD, true) {
351        @Override
352        public void process(Helper helper) {
353            throw new AssertionError("the -J flag should be caught by the launcher.");
354        }
355    },
356
357    // This option exists only for the purpose of documenting itself.
358    // It's actually implemented ahead of the normal option decoding loop.
359    Xold("-Xold", EXTENDED) {
360        @Override
361        public void process(Helper helper) {
362            throw new AssertionError("the -Xold flag should be handled earlier.");
363        }
364    };
365
366    public final String primaryName;
367    public final List<String> names;
368    public final OptionKind kind;
369    public final boolean hasArg;
370    public final boolean hasSuffix; // ex: foo:bar or -foo=bar
371
372    ToolOption(String opt, OptionKind kind) {
373        this(opt, kind, false);
374    }
375
376    ToolOption(String names, OptionKind kind, boolean hasArg) {
377        this.names = Arrays.asList(names.split("\\s+"));
378        this.primaryName = this.names.get(0);
379        this.kind = kind;
380        this.hasArg = hasArg;
381        char lastChar = names.charAt(names.length() - 1);
382        this.hasSuffix = lastChar == ':' || lastChar == '=';
383    }
384
385    void process(Helper helper, String arg) throws OptionException, Option.InvalidValueException { }
386
387    void process(Helper helper) throws OptionException { }
388
389    List<String> getNames() {
390        return names;
391    }
392
393    String getParameters(Messager messager) {
394        return (hasArg || primaryName.endsWith(":"))
395                ? messager.getText(getKey(primaryName, ".arg"))
396                : null;
397    }
398
399    String getDescription(Messager messager) {
400        return messager.getText(getKey(primaryName, ".desc"));
401    }
402
403    private String getKey(String optionName, String suffix) {
404        return "main.opt."
405                + optionName
406                .replaceAll("^-*", "")              // remove leading '-'
407                .replaceAll("[^A-Za-z0-9]+$", "")   // remove trailing non-alphanumeric
408                .replaceAll("[^A-Za-z0-9]", ".")    // replace internal non-alphanumeric
409                + suffix;
410    }
411
412
413    static ToolOption get(String name) {
414        String oname = name;
415        if (name.contains(":")) {
416            oname = name.substring(0, name.indexOf(':') + 1);
417        } else if (name.contains("=")) {
418            oname = name.substring(0, name.indexOf('='));
419        }
420        for (ToolOption o : values()) {
421            for (String n : o.names) {
422                if (oname.equals(n)) {
423                    return o;
424                }
425            }
426        }
427        return null;
428    }
429
430    static abstract class Helper {
431
432        // File manager options
433        final Map<Option, String> fileManagerOpts = new LinkedHashMap<>();
434
435        /** javac options, set by various options. */
436        Options compOpts; // = Options.instance(context)
437
438        /** Javadoc tool options */
439        final Map<ToolOption, Object> jdtoolOpts = new EnumMap<>(ToolOption.class);
440
441        /** dump stack traces for debugging etc.*/
442        boolean dumpOnError = false;
443
444        /** Set by -breakiterator. */
445        boolean breakiterator = false;
446
447        /** Set by -Xwerror. */
448        boolean rejectWarnings = false;
449
450        /** Set by -prompt. */
451        boolean promptOnError;
452
453        /** Set by -locale. */
454        String docLocale = "";
455
456        Helper() {
457            populateDefaultAccessMap();
458        }
459
460        abstract void usage();
461        abstract void Xusage();
462
463        abstract String getLocalizedMessage(String msg, Object... args);
464
465        abstract OptionHelper getOptionHelper();
466
467        @SuppressWarnings("unchecked")
468        void addToList(ToolOption opt, String delimiter, String str) {
469            List<String> list = (List<String>) jdtoolOpts.computeIfAbsent(opt, v -> new ArrayList<>());
470            list.addAll(Arrays.asList(str.split(delimiter)));
471            jdtoolOpts.put(opt, list);
472        }
473
474        void setExpandRequires(ToolOption opt, String arg) throws OptionException {
475            switch (arg) {
476                case "transitive":
477                    jdtoolOpts.put(opt, AccessKind.PUBLIC);
478                    break;
479                case "all":
480                    jdtoolOpts.put(opt, AccessKind.PRIVATE);
481                    break;
482                default:
483                    String text = getLocalizedMessage("main.illegal_option_value", arg);
484                    throw new IllegalOptionValue(this::usage, text);
485            }
486        }
487
488        void setShowModuleContents(ToolOption opt, String arg) throws OptionException {
489            switch (arg) {
490                case "api":
491                    jdtoolOpts.put(opt, AccessKind.PUBLIC);
492                    break;
493                case "all":
494                    jdtoolOpts.put(opt, AccessKind.PRIVATE);
495                    break;
496                default:
497                    String text = getLocalizedMessage("main.illegal_option_value", arg);
498                    throw new IllegalOptionValue(this::usage, text);
499            }
500        }
501
502        void setShowPackageAccess(ToolOption opt, String arg) throws OptionException {
503            switch (arg) {
504                case "exported":
505                    jdtoolOpts.put(opt, AccessKind.PUBLIC);
506                    break;
507                case "all":
508                    jdtoolOpts.put(opt, AccessKind.PRIVATE);
509                    break;
510                default:
511                    String text = getLocalizedMessage("main.illegal_option_value", arg);
512                    throw new IllegalOptionValue(this::usage, text);
513            }
514        }
515
516
517        void setFilter(ToolOption opt, String arg) throws OptionException {
518            jdtoolOpts.put(opt, getAccessValue(arg));
519        }
520
521        void setSimpleFilter(String arg) throws OptionException {
522            handleSimpleOption(arg);
523        }
524
525        void setFileManagerOpt(Option opt, String arg) {
526            fileManagerOpts.put(opt, arg);
527        }
528
529        void handleSimpleOption(String arg) throws OptionException {
530            populateSimpleAccessMap(getAccessValue(arg));
531        }
532
533        /*
534         * This method handles both the simple options -package,
535         * -private, so on, in addition to the new ones such as
536         * --show-types:public and so on.
537         */
538        private AccessKind getAccessValue(String arg) throws OptionException {
539            int colon = arg.indexOf(':');
540            String value = (colon > 0)
541                    ? arg.substring(colon + 1)
542                    : arg;
543            switch (value) {
544                case "public":
545                    return AccessKind.PUBLIC;
546                case "protected":
547                    return AccessKind.PROTECTED;
548                case "package":
549                    return AccessKind.PACKAGE;
550                case "private":
551                    return AccessKind.PRIVATE;
552                default:
553                    String text = getLocalizedMessage("main.illegal_option_value", value);
554                    throw new IllegalOptionValue(this::usage, text);
555            }
556        }
557
558        /*
559         * Sets the entire kind map to PROTECTED this is the default.
560         */
561        private void populateDefaultAccessMap() {
562            populateSimpleAccessMap(AccessKind.PROTECTED);
563        }
564
565        /*
566         * This sets access to all the allowed kinds in the
567         * access map.
568         */
569        void populateSimpleAccessMap(AccessKind accessValue) {
570            for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) {
571                switch (kind) {
572                    case METHOD:
573                        jdtoolOpts.put(SHOW_MEMBERS, accessValue);
574                        break;
575                    case CLASS:
576                        jdtoolOpts.put(SHOW_TYPES, accessValue);
577                        break;
578                    case PACKAGE:
579                        jdtoolOpts.put(SHOW_PACKAGES, accessValue);
580                        break;
581                    case MODULE:
582                        jdtoolOpts.put(SHOW_MODULE_CONTENTS, accessValue);
583                        break;
584                    default:
585                        throw new AssertionError("unknown element kind:" + kind);
586                }
587            }
588        }
589    }
590}
591