Report unsupported based on desugared library version.
Bug: 158645207
Change-Id: Iaf8ead86c709492e42c29fd55a812d78fbf5ac41
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
index a1af388..d687d19 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.SemanticVersion;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@@ -22,14 +23,7 @@
public class DesugaredLibraryConfigurationParser {
public static final int MAX_SUPPORTED_VERSION = 4;
-
- private static final String MIN_DESUGARED_LIBRARY_WITH_COMMON_FLAGS = "1.0.9";
-
- private static final String UNSUPPORTED_MESSAGE =
- "Unsupported desugared library version, please upgrade the"
- + " desugared library to at least version "
- + MIN_DESUGARED_LIBRARY_WITH_COMMON_FLAGS
- + ".";
+ public static final SemanticVersion MIN_SUPPORTED_VERSION = new SemanticVersion(1, 0, 9);
static final String CONFIGURATION_FORMAT_VERSION_KEY = "configuration_format_version";
static final String VERSION_KEY = "version";
@@ -73,15 +67,11 @@
}
private JsonElement required(JsonObject json, String key) {
- return required(
- json,
- key,
- "Invalid desugared library configuration. " + "Expected required key '" + key + "'");
- }
-
- private JsonElement required(JsonObject json, String key, String message) {
if (!json.has(key)) {
- throw reporter.fatalError(new StringDiagnostic(message, origin));
+ throw reporter.fatalError(
+ new StringDiagnostic(
+ "Invalid desugared library configuration. Expected required key '" + key + "'",
+ origin));
}
return json.get(key);
}
@@ -115,6 +105,18 @@
}
String version = required(jsonConfig, VERSION_KEY).getAsString();
+ SemanticVersion semanticVersion = SemanticVersion.parse(version);
+ if (!semanticVersion.isNewerOrEqual(MIN_SUPPORTED_VERSION)) {
+ throw reporter.fatalError(
+ new StringDiagnostic(
+ "Unsupported desugared library version: "
+ + version
+ + ", please upgrade the desugared library to at least version "
+ + MIN_SUPPORTED_VERSION
+ + ".",
+ origin));
+ }
+
String groupID = required(jsonConfig, GROUP_ID_KEY).getAsString();
String artifactID = required(jsonConfig, ARTIFACT_ID_KEY).getAsString();
String identifier = String.join(":", groupID, artifactID, version);
@@ -126,7 +128,7 @@
required(jsonConfig, REQUIRED_COMPILATION_API_LEVEL_KEY).getAsInt();
configurationBuilder.setRequiredCompilationAPILevel(
AndroidApiLevel.getAndroidApiLevel(required_compilation_api_level));
- JsonElement commonFlags = required(jsonConfig, COMMON_FLAGS_KEY, UNSUPPORTED_MESSAGE);
+ JsonElement commonFlags = required(jsonConfig, COMMON_FLAGS_KEY);
JsonElement libraryFlags = required(jsonConfig, LIBRARY_FLAGS_KEY);
JsonElement programFlags = required(jsonConfig, PROGRAM_FLAGS_KEY);
parseFlagsList(commonFlags.getAsJsonArray());
diff --git a/src/main/java/com/android/tools/r8/utils/SemanticVersion.java b/src/main/java/com/android/tools/r8/utils/SemanticVersion.java
new file mode 100644
index 0000000..977073d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/SemanticVersion.java
@@ -0,0 +1,84 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils;
+
+import java.util.Objects;
+
+public class SemanticVersion {
+
+ public static SemanticVersion parse(String version) {
+ int majorEnd = version.indexOf('.');
+ if (majorEnd <= 0) {
+ throw new IllegalArgumentException("Invalid semantic version: " + version);
+ }
+ int minorEnd = version.indexOf('.', majorEnd + 1);
+ if (minorEnd <= majorEnd) {
+ throw new IllegalArgumentException("Invalid semantic version: " + version);
+ }
+ // No current support for extensions.
+ int patchEnd = version.length();
+ int major;
+ int minor;
+ int patch;
+ try {
+ major = Integer.parseInt(version.substring(0, majorEnd));
+ minor = Integer.parseInt(version.substring(majorEnd + 1, minorEnd));
+ patch = Integer.parseInt(version.substring(minorEnd + 1, patchEnd));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid semantic version: " + version, e);
+ }
+ return new SemanticVersion(major, minor, patch);
+ }
+
+ private final int major;
+ private final int minor;
+ private final int patch;
+
+ public SemanticVersion(int major, int minor, int patch) {
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ }
+
+ public int getMajor() {
+ return major;
+ }
+
+ public int getMinor() {
+ return minor;
+ }
+
+ public int getPatch() {
+ return patch;
+ }
+
+ public boolean isNewerOrEqual(SemanticVersion other) {
+ if (major != other.major) {
+ return major > other.major;
+ }
+ if (minor != other.minor) {
+ return minor > other.minor;
+ }
+ return patch >= other.patch;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SemanticVersion)) {
+ return false;
+ }
+ SemanticVersion other = (SemanticVersion) obj;
+ return major == other.major && minor == other.minor && patch == other.patch;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(major, minor, patch);
+ }
+
+ @Override
+ public String toString() {
+ return "" + major + "." + minor + "." + patch;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
index 92fc7be..07c0703 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
@@ -28,6 +28,7 @@
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.SemanticVersion;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.google.common.collect.ImmutableList;
@@ -73,7 +74,7 @@
DesugaredLibraryConfigurationParser.MAX_SUPPORTED_VERSION)
.put("group_id", "com.tools.android")
.put("artifact_id", "desugar_jdk_libs")
- .put("version", "0.0.0")
+ .put("version", DesugaredLibraryConfigurationParser.MIN_SUPPORTED_VERSION.toString())
.put("required_compilation_api_level", 1)
.put("synthesized_library_classes_package_prefix", "j$.")
.put("common_flags", Collections.emptyList())
@@ -141,6 +142,7 @@
"version",
"required_compilation_api_level",
"synthesized_library_classes_package_prefix",
+ "common_flags",
"program_flags",
"library_flags");
for (String key : requiredKeys) {
@@ -158,9 +160,13 @@
}
@Test
- public void testUnsupportedFormatMissingFlags() {
+ public void testUnsupportedVersion() {
LinkedHashMap<String, Object> data = template();
- data.remove("common_flags");
+ SemanticVersion minVersion = DesugaredLibraryConfigurationParser.MIN_SUPPORTED_VERSION;
+ data.put(
+ "version",
+ new SemanticVersion(minVersion.getMajor(), minVersion.getMinor(), minVersion.getPatch() - 1)
+ .toString());
runFailing(
toJson(data),
diagnostics ->
diff --git a/src/test/java/com/android/tools/r8/utils/SemanticVersionTests.java b/src/test/java/com/android/tools/r8/utils/SemanticVersionTests.java
new file mode 100644
index 0000000..8f0dd61
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/SemanticVersionTests.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils;
+
+import static com.android.tools.r8.utils.SemanticVersion.parse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class SemanticVersionTests extends TestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public SemanticVersionTests(TestParameters parameters) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ }
+
+ @Test
+ public void test() throws Exception {
+ assertTrue(parse("1.0.1").isNewerOrEqual(parse("1.0.0")));
+ assertFalse(parse("1.0.1").isNewerOrEqual(parse("1.1.0")));
+ assertTrue(parse("1.1.0").isNewerOrEqual(parse("1.0.1")));
+ assertFalse(parse("1.1.1").isNewerOrEqual(parse("2.0.0")));
+
+ assertTrue(parse("2.0.0").isNewerOrEqual(parse("1.1.1")));
+ assertTrue(parse("42.42.42").isNewerOrEqual(parse("9.9.9")));
+ assertTrue(parse("9.42.42").isNewerOrEqual(parse("9.9.9")));
+ assertTrue(parse("9.9.42").isNewerOrEqual(parse("9.9.9")));
+
+ assertFalse(parse("1.1.1").isNewerOrEqual(parse("2.0.0")));
+ assertFalse(parse("9.9.9").isNewerOrEqual(parse("42.42.42")));
+ assertFalse(parse("9.9.9").isNewerOrEqual(parse("9.42.42")));
+ assertFalse(parse("9.9.9").isNewerOrEqual(parse("9.9.42")));
+ }
+}