diff options
Diffstat (limited to 'java/com/google/turbine/options')
4 files changed, 147 insertions, 31 deletions
diff --git a/java/com/google/turbine/options/LanguageVersion.java b/java/com/google/turbine/options/LanguageVersion.java new file mode 100644 index 0000000..e2b0ea7 --- /dev/null +++ b/java/com/google/turbine/options/LanguageVersion.java @@ -0,0 +1,136 @@ +/* + * Copyright 2021 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.turbine.options; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Ints; +import java.util.Iterator; +import java.util.OptionalInt; +import javax.lang.model.SourceVersion; + +/** + * The language version being compiled, corresponding to javac's {@code -source}, {@code -target}, + * and {@code --release} flags. + */ +@AutoValue +public abstract class LanguageVersion { + + /** The source version. */ + public abstract int source(); + + /** The target version. */ + public abstract int target(); + + /** + * The release version. + * + * <p>If set, system APIs will be resolved from the host JDK's ct.sym instead of using the + * provided {@code --bootclasspath}. + */ + public abstract OptionalInt release(); + + /** The class file major version corresponding to the {@link #target}. */ + public int majorVersion() { + return target() + 44; + } + + public SourceVersion sourceVersion() { + try { + return SourceVersion.valueOf("RELEASE_" + source()); + } catch (IllegalArgumentException unused) { + throw new IllegalArgumentException("invalid -source version: " + source()); + } + } + + private static LanguageVersion create(int source, int target, OptionalInt release) { + return new AutoValue_LanguageVersion(source, target, release); + } + + /** The default language version. Currently Java 8. */ + public static LanguageVersion createDefault() { + return create(DEFAULT, DEFAULT, OptionalInt.empty()); + } + + private static final int DEFAULT = 8; + + /** Returns the effective {@code LanguageVersion} for the given list of javac options. */ + public static LanguageVersion fromJavacopts(ImmutableList<String> javacopts) { + int sourceVersion = DEFAULT; + int targetVersion = DEFAULT; + OptionalInt release = OptionalInt.empty(); + Iterator<String> it = javacopts.iterator(); + while (it.hasNext()) { + String option = it.next(); + switch (option) { + case "-source": + case "--source": + if (!it.hasNext()) { + throw new IllegalArgumentException(option + " requires an argument"); + } + sourceVersion = parseVersion(it.next()); + release = OptionalInt.empty(); + break; + case "-target": + case "--target": + if (!it.hasNext()) { + throw new IllegalArgumentException(option + " requires an argument"); + } + targetVersion = parseVersion(it.next()); + release = OptionalInt.empty(); + break; + case "--release": + if (!it.hasNext()) { + throw new IllegalArgumentException(option + " requires an argument"); + } + String value = it.next(); + Integer n = Ints.tryParse(value); + if (n == null) { + throw new IllegalArgumentException("invalid --release version: " + value); + } + release = OptionalInt.of(n); + sourceVersion = n; + targetVersion = n; + break; + default: + break; + } + } + return create(sourceVersion, targetVersion, release); + } + + private static int parseVersion(String value) { + boolean hasPrefix = value.startsWith("1."); + Integer version = Ints.tryParse(hasPrefix ? value.substring("1.".length()) : value); + if (version == null || !isValidVersion(version, hasPrefix)) { + throw new IllegalArgumentException("invalid -source version: " + value); + } + return version; + } + + private static boolean isValidVersion(int version, boolean hasPrefix) { + if (version < 5) { + // the earliest source version supported by JDK 8 is Java 5 + return false; + } + if (hasPrefix && version > 10) { + // javac supports legacy `1.*` version numbers for source versions up to Java 10 + return false; + } + return true; + } +} diff --git a/java/com/google/turbine/options/TurbineOptions.java b/java/com/google/turbine/options/TurbineOptions.java index c104c54..5cd9a61 100644 --- a/java/com/google/turbine/options/TurbineOptions.java +++ b/java/com/google/turbine/options/TurbineOptions.java @@ -20,7 +20,7 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.Optional; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.jspecify.nullness.Nullable; /** Header compilation options. */ @AutoValue @@ -61,8 +61,8 @@ public abstract class TurbineOptions { /** Paths to compilation bootclasspath artifacts. */ public abstract ImmutableSet<String> bootClassPath(); - /** The target platform version. */ - public abstract Optional<String> release(); + /** The language version. */ + public abstract LanguageVersion languageVersion(); /** The target platform's system modules. */ public abstract Optional<String> system(); @@ -138,6 +138,7 @@ public abstract class TurbineOptions { .setDirectJars(ImmutableList.of()) .setDepsArtifacts(ImmutableList.of()) .addAllJavacOpts(ImmutableList.of()) + .setLanguageVersion(LanguageVersion.createDefault()) .setReducedClasspathMode(ReducedClasspathMode.NONE) .setHelp(false) .setFullClasspathLength(0) @@ -153,7 +154,7 @@ public abstract class TurbineOptions { public abstract Builder setBootClassPath(ImmutableList<String> bootClassPath); - public abstract Builder setRelease(String release); + public abstract Builder setLanguageVersion(LanguageVersion languageVersion); public abstract Builder setSystem(String system); diff --git a/java/com/google/turbine/options/TurbineOptionsParser.java b/java/com/google/turbine/options/TurbineOptionsParser.java index 4a8ff16..e68a546 100644 --- a/java/com/google/turbine/options/TurbineOptionsParser.java +++ b/java/com/google/turbine/options/TurbineOptionsParser.java @@ -17,7 +17,6 @@ package com.google.turbine.options; import static com.google.common.base.Preconditions.checkArgument; -import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; @@ -29,7 +28,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayDeque; import java.util.Deque; -import java.util.Iterator; /** A command line options parser for {@link TurbineOptions}. */ public final class TurbineOptionsParser { @@ -83,19 +81,14 @@ public final class TurbineOptionsParser { case "--bootclasspath": builder.setBootClassPath(readList(argumentDeque)); break; - case "--release": - builder.setRelease(readOne(next, argumentDeque)); - break; case "--system": builder.setSystem(readOne(next, argumentDeque)); break; case "--javacopts": - { - ImmutableList<String> javacopts = readJavacopts(argumentDeque); - setReleaseFromJavacopts(builder, javacopts); - builder.addAllJavacOpts(javacopts); - break; - } + ImmutableList<String> javacOpts = readJavacopts(argumentDeque); + builder.setLanguageVersion(LanguageVersion.fromJavacopts(javacOpts)); + builder.addAllJavacOpts(javacOpts); + break; case "--sources": builder.setSources(readList(argumentDeque)); break; @@ -193,8 +186,7 @@ public final class TurbineOptionsParser { if (!Files.exists(paramsPath)) { throw new AssertionError("params file does not exist: " + paramsPath); } - expandParamsFiles( - argumentDeque, ARG_SPLITTER.split(new String(Files.readAllBytes(paramsPath), UTF_8))); + expandParamsFiles(argumentDeque, ARG_SPLITTER.split(Files.readString(paramsPath))); } else { argumentDeque.addLast(arg); } @@ -237,19 +229,5 @@ public final class TurbineOptionsParser { throw new IllegalArgumentException("javacopts should be terminated by `--`"); } - /** - * Parses the given javacopts for {@code --release}, and if found sets turbine's {@code --release} - * flag. - */ - private static void setReleaseFromJavacopts( - TurbineOptions.Builder builder, ImmutableList<String> javacopts) { - Iterator<String> it = javacopts.iterator(); - while (it.hasNext()) { - if (it.next().equals("--release") && it.hasNext()) { - builder.setRelease(it.next()); - } - } - } - private TurbineOptionsParser() {} } diff --git a/java/com/google/turbine/options/package-info.java b/java/com/google/turbine/options/package-info.java index 9c12bf8..45bad5e 100644 --- a/java/com/google/turbine/options/package-info.java +++ b/java/com/google/turbine/options/package-info.java @@ -14,4 +14,5 @@ * limitations under the License. */ +@org.jspecify.nullness.NullMarked package com.google.turbine.options; |