< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java

Print this page




  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.FileWriter;
  29 import java.io.PrintWriter;
  30 import java.nio.file.Files;
  31 import java.nio.file.Path;
  32 import java.nio.file.Paths;
  33 import java.text.Collator;
  34 import java.util.Arrays;
  35 import java.util.Collections;
  36 import java.util.Comparator;
  37 import java.util.EnumSet;
  38 import java.util.HashSet;
  39 import java.util.Iterator;
  40 import java.util.LinkedHashMap;
  41 import java.util.LinkedHashSet;
  42 import java.util.Locale;
  43 import java.util.Map;
  44 import java.util.ServiceLoader;
  45 import java.util.Set;
  46 import java.util.TreeSet;
  47 import java.util.regex.Matcher;
  48 import java.util.regex.Pattern;
  49 import java.util.stream.Collectors;
  50 import java.util.stream.StreamSupport;
  51 
  52 import javax.lang.model.SourceVersion;
  53 
  54 import com.sun.tools.doclint.DocLint;
  55 import com.sun.tools.javac.code.Lint;
  56 import com.sun.tools.javac.code.Lint.LintCategory;
  57 import com.sun.tools.javac.code.Source;
  58 import com.sun.tools.javac.code.Type;
  59 import com.sun.tools.javac.jvm.Profile;
  60 import com.sun.tools.javac.jvm.Target;
  61 import com.sun.tools.javac.platform.PlatformProvider;
  62 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
  63 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  64 import com.sun.tools.javac.util.Assert;
  65 import com.sun.tools.javac.util.JDK9Wrappers;
  66 import com.sun.tools.javac.util.Log;
  67 import com.sun.tools.javac.util.Log.PrefixKind;
  68 import com.sun.tools.javac.util.Log.WriterKind;
  69 import com.sun.tools.javac.util.Options;
  70 import com.sun.tools.javac.util.StringUtils;
  71 
  72 import static com.sun.tools.javac.main.Option.ChoiceKind.*;
  73 import static com.sun.tools.javac.main.Option.OptionGroup.*;
  74 import static com.sun.tools.javac.main.Option.OptionKind.*;
  75 
  76 /**
  77  * Options for javac.
  78  * The specific Option to handle a command-line option can be found by calling
  79  * {@link #lookup}, which search some or all of the members of this enum in order,
  80  * looking for the first {@link #matches match}.
  81  * The action for an Option is performed {@link #handleOption}, which determines
  82  * whether an argument is needed and where to find it;
  83  * {@code handleOption} then calls {@link #process process} providing a suitable


 617     },
 618 
 619     LIMIT_MODULES("--limit-modules", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC) {
 620         @Override
 621         public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
 622             if (arg.isEmpty()) {
 623                 throw helper.newInvalidValueException("err.no.value.for.option", option);
 624             } else if (getPattern().matcher(arg).matches()) {
 625                 helper.put(LIMIT_MODULES.primaryName, arg); // last one wins
 626             } else {
 627                 throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
 628             }
 629         }
 630 
 631         @Override
 632         public Pattern getPattern() {
 633             return Pattern.compile(",*[^,].*");
 634         }
 635     },
 636 



























 637     // This option exists only for the purpose of documenting itself.
 638     // It's actually implemented by the CommandLine class.
 639     AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, ArgKind.ADJACENT) {
 640         @Override
 641         public void process(OptionHelper helper, String option) {
 642             throw new AssertionError("the @ flag should be caught by CommandLine.");
 643         }
 644     },
 645 
 646     // Standalone positional argument: source file or type name.
 647     SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
 648         @Override
 649         public boolean matches(String s) {
 650             if (s.endsWith(".java"))  // Java source file
 651                 return true;
 652             int sep = s.indexOf('/');
 653             if (sep != -1) {
 654                 return SourceVersion.isName(s.substring(0, sep))
 655                         && SourceVersion.isName(s.substring(sep + 1));
 656             } else {


 664                 if (!Files.exists(p)) {
 665                     throw helper.newInvalidValueException("err.file.not.found", p);
 666                 }
 667                 if (!Files.isRegularFile(p)) {
 668                     throw helper.newInvalidValueException("err.file.not.file", p);
 669                 }
 670                 helper.addFile(p);
 671             } else {
 672                 helper.addClassName(option);
 673             }
 674         }
 675     },
 676 
 677     MULTIRELEASE("--multi-release", "opt.arg.multi-release", "opt.multi-release", HIDDEN, FILEMANAGER),
 678 
 679     INHERIT_RUNTIME_ENVIRONMENT("--inherit-runtime-environment", "opt.inherit_runtime_environment",
 680             EXTENDED, BASIC) {
 681         @Override
 682         public void process(OptionHelper helper, String option) throws InvalidValueException {
 683             try {
 684                 Class.forName(JDK9Wrappers.VMHelper.VM_CLASSNAME);
 685                 String[] runtimeArgs = JDK9Wrappers.VMHelper.getRuntimeArguments();
 686                 for (String arg : runtimeArgs) {
 687                     // Handle any supported runtime options; ignore all others.
 688                     // The runtime arguments always use the single token form, e.g. "--name=value".
 689                     for (Option o : getSupportedRuntimeOptions()) {
 690                         if (o.matches(arg)) {
 691                             switch (o) {
 692                                 case ADD_MODULES:
 693                                     int eq = arg.indexOf('=');
 694                                     Assert.check(eq > 0, () -> ("invalid runtime option:" + arg));
 695                                     // --add-modules=ALL-DEFAULT is not supported at compile-time
 696                                     // so remove it from list, and only process the rest
 697                                     // if the set is non-empty.
 698                                     // Note that --add-modules=ALL-DEFAULT is automatically added
 699                                     // by the standard javac launcher.
 700                                     String mods = Arrays.stream(arg.substring(eq + 1).split(","))
 701                                             .filter(s -> !s.isEmpty() && !s.equals("ALL-DEFAULT"))
 702                                             .collect(Collectors.joining(","));
 703                                     if (!mods.isEmpty()) {
 704                                         String updatedArg = arg.substring(0, eq + 1) + mods;


1018             else {
1019                 for (String a: arg.split(",+")) {
1020                     if (!choices.contains(a))
1021                         return false;
1022                 }
1023             }
1024         }
1025 
1026         return true;
1027     }
1028 
1029     /**
1030      * Handles an option.
1031      * If an argument for the option is required, depending on spec of the option, it will be found
1032      * as part of the current arg (following ':' or '=') or in the following argument.
1033      * This is the recommended way to handle an option directly, instead of calling the underlying
1034      * {@link #process process} methods.
1035      * @param helper a helper to provide access to the environment
1036      * @param arg the arg string that identified this option
1037      * @param rest the remaining strings to be analysed
1038      * @return true if the operation was successful, and false otherwise
1039      * @implNote The return value is the opposite of that used by {@link #process}.
1040      */
1041     public void handleOption(OptionHelper helper, String arg, Iterator<String> rest) throws InvalidValueException {
1042         if (hasArg()) {
1043             String option;
1044             String operand;
1045             int sep = findSeparator(arg);
1046             if (getArgKind() == Option.ArgKind.ADJACENT) {
1047                 option = primaryName; // aliases not supported
1048                 operand = arg.substring(primaryName.length());
1049             } else if (sep > 0) {
1050                 option = arg.substring(0, sep);
1051                 operand = arg.substring(sep + 1);
1052             } else {
1053                 if (!rest.hasNext()) {
1054                     throw helper.newInvalidValueException("err.req.arg", arg);
1055                 }
1056                 option = arg;
1057                 operand = rest.next();
1058             }


1067      * or which contains an argument within it, following a separator.
1068      * @param helper a helper to provide access to the environment
1069      * @param option the option to be processed
1070      * @throws InvalidValueException if an error occurred
1071      */
1072     public void process(OptionHelper helper, String option) throws InvalidValueException {
1073         if (argKind == ArgKind.NONE) {
1074             process(helper, primaryName, option);
1075         } else {
1076             int sep = findSeparator(option);
1077             process(helper, primaryName, option.substring(sep + 1));
1078         }
1079     }
1080 
1081     /**
1082      * Processes an option by updating the environment via a helper object.
1083      * @param helper a helper to provide access to the environment
1084      * @param option the option to be processed
1085      * @param arg the value to associate with the option, or a default value
1086      *  to be used if the option does not otherwise take an argument.

1087      */
1088     public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
1089         if (choices != null) {
1090             if (choiceKind == ChoiceKind.ONEOF) {
1091                 // some clients like to see just one of option+choice set
1092                 for (String s : choices)
1093                     helper.remove(primaryName + s);
1094                 String opt = primaryName + arg;
1095                 helper.put(opt, opt);
1096                 // some clients like to see option (without trailing ":")
1097                 // set to arg
1098                 String nm = primaryName.substring(0, primaryName.length() - 1);
1099                 helper.put(nm, arg);
1100             } else {
1101                 // set option+word for each word in arg
1102                 for (String a: arg.split(",+")) {
1103                     String opt = primaryName + a;
1104                     helper.put(opt, opt);
1105                 }
1106             }




  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.FileWriter;
  29 import java.io.PrintWriter;
  30 import java.nio.file.Files;
  31 import java.nio.file.Path;
  32 import java.nio.file.Paths;
  33 import java.text.Collator;
  34 import java.util.Arrays;
  35 import java.util.Collections;
  36 import java.util.Comparator;
  37 import java.util.EnumSet;

  38 import java.util.Iterator;

  39 import java.util.LinkedHashSet;
  40 import java.util.Locale;

  41 import java.util.ServiceLoader;
  42 import java.util.Set;
  43 import java.util.TreeSet;

  44 import java.util.regex.Pattern;
  45 import java.util.stream.Collectors;
  46 import java.util.stream.StreamSupport;
  47 
  48 import javax.lang.model.SourceVersion;
  49 
  50 import com.sun.tools.doclint.DocLint;
  51 import com.sun.tools.javac.code.Lint;
  52 import com.sun.tools.javac.code.Lint.LintCategory;
  53 import com.sun.tools.javac.code.Source;
  54 import com.sun.tools.javac.code.Type;
  55 import com.sun.tools.javac.jvm.Profile;
  56 import com.sun.tools.javac.jvm.Target;
  57 import com.sun.tools.javac.platform.PlatformProvider;
  58 import com.sun.tools.javac.processing.JavacProcessingEnvironment;

  59 import com.sun.tools.javac.util.Assert;
  60 import com.sun.tools.javac.util.JDK9Wrappers;
  61 import com.sun.tools.javac.util.Log;
  62 import com.sun.tools.javac.util.Log.PrefixKind;
  63 import com.sun.tools.javac.util.Log.WriterKind;
  64 import com.sun.tools.javac.util.Options;
  65 import com.sun.tools.javac.util.StringUtils;
  66 
  67 import static com.sun.tools.javac.main.Option.ChoiceKind.*;
  68 import static com.sun.tools.javac.main.Option.OptionGroup.*;
  69 import static com.sun.tools.javac.main.Option.OptionKind.*;
  70 
  71 /**
  72  * Options for javac.
  73  * The specific Option to handle a command-line option can be found by calling
  74  * {@link #lookup}, which search some or all of the members of this enum in order,
  75  * looking for the first {@link #matches match}.
  76  * The action for an Option is performed {@link #handleOption}, which determines
  77  * whether an argument is needed and where to find it;
  78  * {@code handleOption} then calls {@link #process process} providing a suitable


 612     },
 613 
 614     LIMIT_MODULES("--limit-modules", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC) {
 615         @Override
 616         public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
 617             if (arg.isEmpty()) {
 618                 throw helper.newInvalidValueException("err.no.value.for.option", option);
 619             } else if (getPattern().matcher(arg).matches()) {
 620                 helper.put(LIMIT_MODULES.primaryName, arg); // last one wins
 621             } else {
 622                 throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
 623             }
 624         }
 625 
 626         @Override
 627         public Pattern getPattern() {
 628             return Pattern.compile(",*[^,].*");
 629         }
 630     },
 631 
 632     MODULE_VERSION("--module-version", "opt.arg.module.version", "opt.module.version", STANDARD, BASIC) {
 633         @Override
 634         public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
 635             if (arg.isEmpty()) {
 636                 throw helper.newInvalidValueException("err.no.value.for.option", option);
 637             } else {
 638                 try {
 639                     Class.forName(JDK9Wrappers.ModuleDescriptor.Version.CLASSNAME);
 640                     // use official parser if available
 641                     try {
 642                         JDK9Wrappers.ModuleDescriptor.Version.parse(arg);
 643                     } catch (IllegalArgumentException e) {
 644                         throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
 645                     }
 646                 } catch (ClassNotFoundException ex) {
 647                     // fall-back to simplistic rules when running on older platform
 648                     if (!(arg.charAt(0) >= '0' && arg.charAt(0) <= '9') ||
 649                         arg.endsWith("-") ||
 650                         arg.endsWith("+")) {
 651                         throw helper.newInvalidValueException("err.bad.value.for.option", option, arg);
 652                     }
 653                 }
 654             }
 655             super.process(helper, option, arg);
 656         }
 657     },
 658 
 659     // This option exists only for the purpose of documenting itself.
 660     // It's actually implemented by the CommandLine class.
 661     AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, ArgKind.ADJACENT) {
 662         @Override
 663         public void process(OptionHelper helper, String option) {
 664             throw new AssertionError("the @ flag should be caught by CommandLine.");
 665         }
 666     },
 667 
 668     // Standalone positional argument: source file or type name.
 669     SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
 670         @Override
 671         public boolean matches(String s) {
 672             if (s.endsWith(".java"))  // Java source file
 673                 return true;
 674             int sep = s.indexOf('/');
 675             if (sep != -1) {
 676                 return SourceVersion.isName(s.substring(0, sep))
 677                         && SourceVersion.isName(s.substring(sep + 1));
 678             } else {


 686                 if (!Files.exists(p)) {
 687                     throw helper.newInvalidValueException("err.file.not.found", p);
 688                 }
 689                 if (!Files.isRegularFile(p)) {
 690                     throw helper.newInvalidValueException("err.file.not.file", p);
 691                 }
 692                 helper.addFile(p);
 693             } else {
 694                 helper.addClassName(option);
 695             }
 696         }
 697     },
 698 
 699     MULTIRELEASE("--multi-release", "opt.arg.multi-release", "opt.multi-release", HIDDEN, FILEMANAGER),
 700 
 701     INHERIT_RUNTIME_ENVIRONMENT("--inherit-runtime-environment", "opt.inherit_runtime_environment",
 702             EXTENDED, BASIC) {
 703         @Override
 704         public void process(OptionHelper helper, String option) throws InvalidValueException {
 705             try {
 706                 Class.forName(JDK9Wrappers.VMHelper.CLASSNAME);
 707                 String[] runtimeArgs = JDK9Wrappers.VMHelper.getRuntimeArguments();
 708                 for (String arg : runtimeArgs) {
 709                     // Handle any supported runtime options; ignore all others.
 710                     // The runtime arguments always use the single token form, e.g. "--name=value".
 711                     for (Option o : getSupportedRuntimeOptions()) {
 712                         if (o.matches(arg)) {
 713                             switch (o) {
 714                                 case ADD_MODULES:
 715                                     int eq = arg.indexOf('=');
 716                                     Assert.check(eq > 0, () -> ("invalid runtime option:" + arg));
 717                                     // --add-modules=ALL-DEFAULT is not supported at compile-time
 718                                     // so remove it from list, and only process the rest
 719                                     // if the set is non-empty.
 720                                     // Note that --add-modules=ALL-DEFAULT is automatically added
 721                                     // by the standard javac launcher.
 722                                     String mods = Arrays.stream(arg.substring(eq + 1).split(","))
 723                                             .filter(s -> !s.isEmpty() && !s.equals("ALL-DEFAULT"))
 724                                             .collect(Collectors.joining(","));
 725                                     if (!mods.isEmpty()) {
 726                                         String updatedArg = arg.substring(0, eq + 1) + mods;


1040             else {
1041                 for (String a: arg.split(",+")) {
1042                     if (!choices.contains(a))
1043                         return false;
1044                 }
1045             }
1046         }
1047 
1048         return true;
1049     }
1050 
1051     /**
1052      * Handles an option.
1053      * If an argument for the option is required, depending on spec of the option, it will be found
1054      * as part of the current arg (following ':' or '=') or in the following argument.
1055      * This is the recommended way to handle an option directly, instead of calling the underlying
1056      * {@link #process process} methods.
1057      * @param helper a helper to provide access to the environment
1058      * @param arg the arg string that identified this option
1059      * @param rest the remaining strings to be analysed
1060      * @throws InvalidValueException if the value of the option was invalid
1061      * @implNote The return value is the opposite of that used by {@link #process}.
1062      */
1063     public void handleOption(OptionHelper helper, String arg, Iterator<String> rest) throws InvalidValueException {
1064         if (hasArg()) {
1065             String option;
1066             String operand;
1067             int sep = findSeparator(arg);
1068             if (getArgKind() == Option.ArgKind.ADJACENT) {
1069                 option = primaryName; // aliases not supported
1070                 operand = arg.substring(primaryName.length());
1071             } else if (sep > 0) {
1072                 option = arg.substring(0, sep);
1073                 operand = arg.substring(sep + 1);
1074             } else {
1075                 if (!rest.hasNext()) {
1076                     throw helper.newInvalidValueException("err.req.arg", arg);
1077                 }
1078                 option = arg;
1079                 operand = rest.next();
1080             }


1089      * or which contains an argument within it, following a separator.
1090      * @param helper a helper to provide access to the environment
1091      * @param option the option to be processed
1092      * @throws InvalidValueException if an error occurred
1093      */
1094     public void process(OptionHelper helper, String option) throws InvalidValueException {
1095         if (argKind == ArgKind.NONE) {
1096             process(helper, primaryName, option);
1097         } else {
1098             int sep = findSeparator(option);
1099             process(helper, primaryName, option.substring(sep + 1));
1100         }
1101     }
1102 
1103     /**
1104      * Processes an option by updating the environment via a helper object.
1105      * @param helper a helper to provide access to the environment
1106      * @param option the option to be processed
1107      * @param arg the value to associate with the option, or a default value
1108      *  to be used if the option does not otherwise take an argument.
1109      * @throws InvalidValueException if an error occurred
1110      */
1111     public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
1112         if (choices != null) {
1113             if (choiceKind == ChoiceKind.ONEOF) {
1114                 // some clients like to see just one of option+choice set
1115                 for (String s : choices)
1116                     helper.remove(primaryName + s);
1117                 String opt = primaryName + arg;
1118                 helper.put(opt, opt);
1119                 // some clients like to see option (without trailing ":")
1120                 // set to arg
1121                 String nm = primaryName.substring(0, primaryName.length() - 1);
1122                 helper.put(nm, arg);
1123             } else {
1124                 // set option+word for each word in arg
1125                 for (String a: arg.split(",+")) {
1126                     String opt = primaryName + a;
1127                     helper.put(opt, opt);
1128                 }
1129             }


< prev index next >