From 906affaad198871b19e0a5d132be0b9636f3a9ea Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Mon, 28 Aug 2023 15:40:03 -0400 Subject: [PATCH 1/3] feat: add ApiVersion parser and comparison --- .../com/google/docfx/doclet/ApiVersion.java | 100 ++++++++++++++++++ .../com/microsoft/util/ApiVersionTest.java | 66 ++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java create mode 100644 third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java diff --git a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java new file mode 100644 index 00000000..298ed75e --- /dev/null +++ b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java @@ -0,0 +1,100 @@ +package com.google.docfx.doclet; + +import com.google.common.base.MoreObjects; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + +public class ApiVersion implements Comparable { + public static ApiVersion NONE = new ApiVersion(0, 0, null, 0); + + private static final Pattern VALID_VERSION_REGEX = + Pattern.compile("^v(\\d+)p?(\\d+)?(alpha|beta)?(\\d+)?"); + + /** + * Creates an ApiVersion instance, if the given input matches the correct format. + * + *

Supported Format: + * + *

+   * v1p2beta3
+   *  │└┤└──┤│
+   *  │ │   ││
+   *  │ │   │└─── Optional: Prerelease major version
+   *  │ │   └──── Optional: Stability level. See AIP 181
+   *  │ └──────── Optional: Minor version
+   *  └────────── Required: Major version
+   * 
+ * + * @return Optional.empty() if the given input doesn't match the version pattern + */ + public static Optional parse(@Nullable String input) { + if (input != null) { + Matcher matcher = VALID_VERSION_REGEX.matcher(input); + if (matcher.matches()) { + return Optional.of( + new ApiVersion( + safeParseInt(matcher.group(1)), + safeParseInt(matcher.group(2)), + matcher.group(3), + safeParseInt(matcher.group(4)))); + } + } + return Optional.empty(); + } + + private static int safeParseInt(@Nullable String input) { + if (input == null) { + return 0; + } + return Integer.parseInt(input); + } + + private final int major; + private final int minor; + private final String stability; + private final int prerelease; + + private ApiVersion(int major, int minor, String stability, int prerelease) { + this.major = major; + this.minor = minor; + this.stability = stability; + this.prerelease = prerelease; + } + + public boolean isStable() { + return stability == null; + } + + @Override + public int compareTo(ApiVersion other) { + if (major != other.major) { + return major - other.major; + } + if (minor != other.minor) { + return minor - other.minor; + } + if (!Objects.equals(stability, other.stability)) { + if (stability == null) { + return 1; // Other is a prerelease version, but this is not. + } + if (other.stability == null) { + return -1; // This is a prerelease version, but the other is not. + } + return stability.compareTo(other.stability); // Based on alphabetical order + } + return prerelease - other.prerelease; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(ApiVersion.class) + .add("major", major) + .add("minor", minor) + .add("stability", stability) + .add("prerelease", prerelease) + .toString(); + } +} diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java new file mode 100644 index 00000000..21a16c74 --- /dev/null +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java @@ -0,0 +1,66 @@ +package com.microsoft.util; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.docfx.doclet.ApiVersion; +import org.junit.Test; + +public class ApiVersionTest { + + @Test + public void badFormat() { + assertFalse(ApiVersion.parse("badFormat").isPresent()); + assertFalse(ApiVersion.parse("1p1").isPresent()); + assertFalse(ApiVersion.parse("v1p2p3").isPresent()); + assertFalse(ApiVersion.parse("v1a").isPresent()); + assertFalse(ApiVersion.parse("v1beta2p3").isPresent()); + } + + @Test + public void goodFormat() { + assertTrue(ApiVersion.parse("v99").isPresent()); + assertTrue(ApiVersion.parse("v1p2").isPresent()); + assertTrue(ApiVersion.parse("v2alpha").isPresent()); + assertTrue(ApiVersion.parse("v3beta").isPresent()); + assertTrue(ApiVersion.parse("v3beta1").isPresent()); + assertTrue(ApiVersion.parse("v3beta1").isPresent()); + assertTrue(ApiVersion.parse("v3p1beta2").isPresent()); + } + + @Test + public void testAisGreaterThanB() { + String[][] comparisons = { + {"v3", "v2"}, + {"v1p1", "v1"}, + {"v1", "v1alpha"}, + {"v1", "v1beta"}, + {"v1beta", "v1alpha"}, + {"v1beta", "v1alpha2"}, + {"v1beta1", "v1alpha"}, + {"v1beta1", "v1beta"}, + {"v1beta2", "v1beta1"}, + {"v2p1alpha0", "v1p1alpha0"}, + }; + + for (String[] testcase : comparisons) { + ApiVersion a = parse(testcase[0]); + ApiVersion b = parse(testcase[1]); + assertThat(a).isGreaterThan(b); + } + } + + private ApiVersion parse(String s) { + return ApiVersion.parse(s).orElseThrow(() -> new IllegalStateException("Unable to parse " + s)); + } + + @Test + public void stability() { + assertTrue(ApiVersion.parse("v12").orElseThrow().isStable()); + assertTrue(ApiVersion.parse("v1p3").orElseThrow().isStable()); + + assertFalse(ApiVersion.parse("v1alpha").orElseThrow().isStable()); + assertFalse(ApiVersion.parse("v1p1beta1").orElseThrow().isStable()); + } +} From 59998127290b9efde23dc0bf50007282f836929e Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Mon, 28 Aug 2023 15:42:11 -0400 Subject: [PATCH 2/3] feat: add guava --- third_party/docfx-doclet-143274/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/third_party/docfx-doclet-143274/pom.xml b/third_party/docfx-doclet-143274/pom.xml index 505daa81..aa59d1b0 100644 --- a/third_party/docfx-doclet-143274/pom.xml +++ b/third_party/docfx-doclet-143274/pom.xml @@ -149,6 +149,11 @@ jsoup 1.16.1 + + com.google.guava + guava + 32.1.1-jre + From ebd1660c2ab19007b98e5e01e08e53b3899ceadf Mon Sep 17 00:00:00 2001 From: Burke Davison Date: Tue, 29 Aug 2023 09:10:06 -0400 Subject: [PATCH 3/3] chore: ApiVersion equals and hashCode --- .../com/google/docfx/doclet/ApiVersion.java | 20 ++++++++++++++++++ .../com/microsoft/util/ApiVersionTest.java | 21 ++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java index 298ed75e..c577cb22 100644 --- a/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java +++ b/third_party/docfx-doclet-143274/src/main/java/com/google/docfx/doclet/ApiVersion.java @@ -88,6 +88,26 @@ public int compareTo(ApiVersion other) { return prerelease - other.prerelease; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ApiVersion other = (ApiVersion) o; + return major == other.major + && minor == other.minor + && prerelease == other.prerelease + && Objects.equals(stability, other.stability); + } + + @Override + public int hashCode() { + return Objects.hash(major, minor, stability, prerelease); + } + @Override public String toString() { return MoreObjects.toStringHelper(ApiVersion.class) diff --git a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java index 21a16c74..aaa67c29 100644 --- a/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java +++ b/third_party/docfx-doclet-143274/src/test/java/com/microsoft/util/ApiVersionTest.java @@ -51,16 +51,23 @@ public void testAisGreaterThanB() { } } - private ApiVersion parse(String s) { - return ApiVersion.parse(s).orElseThrow(() -> new IllegalStateException("Unable to parse " + s)); + @Test + public void stability() { + assertTrue(parse("v12").isStable()); + assertTrue(parse("v1p3").isStable()); + + assertFalse(parse("v1alpha").isStable()); + assertFalse(parse("v1p1beta1").isStable()); } @Test - public void stability() { - assertTrue(ApiVersion.parse("v12").orElseThrow().isStable()); - assertTrue(ApiVersion.parse("v1p3").orElseThrow().isStable()); + public void equals() { + assertThat(parse("v1")).isEqualTo(parse("v1p0")); + assertThat(parse("v1p0")).isEqualTo(parse("v1")); + assertThat(parse("v2p1beta")).isEqualTo(parse("v2p1beta0")); + } - assertFalse(ApiVersion.parse("v1alpha").orElseThrow().isStable()); - assertFalse(ApiVersion.parse("v1p1beta1").orElseThrow().isStable()); + private ApiVersion parse(String s) { + return ApiVersion.parse(s).orElseThrow(() -> new IllegalStateException("Unable to parse " + s)); } }