-
Notifications
You must be signed in to change notification settings - Fork 218
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add transforms to remove deprecated shapes
- Loading branch information
Showing
18 changed files
with
542 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
...el/src/main/java/software/amazon/smithy/model/transform/FilterDeprecatedRelativeDate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package software.amazon.smithy.model.transform; | ||
|
||
import java.util.HashSet; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.logging.Logger; | ||
import java.util.regex.Pattern; | ||
import software.amazon.smithy.model.Model; | ||
import software.amazon.smithy.model.shapes.Shape; | ||
import software.amazon.smithy.model.traits.DeprecatedTrait; | ||
|
||
final class FilterDeprecatedRelativeDate { | ||
private static final Logger LOGGER = Logger.getLogger(FilterDeprecatedRelativeDate.class.getName()); | ||
// YYYY-MM-DD calendar date with optional hyphens. | ||
private static final Pattern ISO_8601_DATE_REGEX = Pattern.compile( | ||
"^([0-9]{4})-?(1[0-2]|0[1-9])-?(3[01]|0[1-9]|[12][0-9])$" | ||
); | ||
|
||
public final String relativeDate; | ||
|
||
FilterDeprecatedRelativeDate(String relativeDate) { | ||
if (relativeDate != null && !isIso8601Date(relativeDate)) { | ||
throw new IllegalArgumentException("Provided relativeDate: `" | ||
+ relativeDate | ||
+ "` does not match ISO8601 calendar date format (YYYY-MM-DD)." | ||
); | ||
} | ||
this.relativeDate = relativeDate != null ? relativeDate.replace("-", "") : null; | ||
} | ||
|
||
public Model transform(ModelTransformer transformer, Model model) { | ||
// If there is no filter. Exit without traversing shapes | ||
if (relativeDate == null) { | ||
return model; | ||
} | ||
|
||
Set<Shape> shapesToRemove = new HashSet<>(); | ||
for (Shape shape : model.getShapesWithTrait(DeprecatedTrait.class)) { | ||
if (shape.hasTrait(DeprecatedTrait.class)) { | ||
Optional<String> sinceOptional = shape.expectTrait(DeprecatedTrait.class).getSince(); | ||
if (!sinceOptional.isPresent()) { | ||
continue; | ||
} | ||
String since = sinceOptional.get(); | ||
|
||
if (isIso8601Date(since)) { | ||
// Compare lexicographical ordering without hyphens. | ||
if (relativeDate.compareTo(since.replace("-", "")) > 0) { | ||
LOGGER.fine("Filtering deprecated shape: `" | ||
+ shape + "`" | ||
+ ". Shape was deprecated as of: " + since | ||
); | ||
shapesToRemove.add(shape); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return transformer.removeShapes(model, shapesToRemove); | ||
} | ||
|
||
private static boolean isIso8601Date(String string) { | ||
return ISO_8601_DATE_REGEX.matcher(string).matches(); | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
...src/main/java/software/amazon/smithy/model/transform/FilterDeprecatedRelativeVersion.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package software.amazon.smithy.model.transform; | ||
|
||
import java.util.HashSet; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.logging.Logger; | ||
import java.util.regex.Pattern; | ||
import software.amazon.smithy.model.Model; | ||
import software.amazon.smithy.model.shapes.Shape; | ||
import software.amazon.smithy.model.traits.DeprecatedTrait; | ||
|
||
final class FilterDeprecatedRelativeVersion { | ||
private static final Logger LOGGER = Logger.getLogger(FilterDeprecatedRelativeVersion.class.getName()); | ||
|
||
/** | ||
* SemVer regex from semantic version spec. | ||
* @see <a href="https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string">SemVer</a> | ||
*/ | ||
private static final Pattern SEMVER_REGEX = Pattern.compile( | ||
"^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)" | ||
+ "(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" | ||
); | ||
|
||
public final String relativeVersion; | ||
|
||
FilterDeprecatedRelativeVersion(String relativeVersion) { | ||
if (relativeVersion != null && !isSemVer(relativeVersion)) { | ||
throw new IllegalArgumentException("Provided relativeDate: `" | ||
+ relativeVersion | ||
+ "` is not a valid ." | ||
); | ||
} | ||
this.relativeVersion = relativeVersion; | ||
} | ||
|
||
public Model transform(ModelTransformer transformer, Model model) { | ||
// If there are no filters. Exit without traversing shapes | ||
if (relativeVersion == null) { | ||
return model; | ||
} | ||
|
||
Set<Shape> shapesToRemove = new HashSet<>(); | ||
for (Shape shape : model.getShapesWithTrait(DeprecatedTrait.class)) { | ||
Optional<String> sinceOptional = shape.expectTrait(DeprecatedTrait.class).getSince(); | ||
|
||
if (!sinceOptional.isPresent()) { | ||
continue; | ||
} | ||
|
||
String since = sinceOptional.get(); | ||
// Remove any shapes that were deprecated before the specified version. | ||
if (isSemVer(since)) { | ||
if (compareSemVer(relativeVersion, since) > 0) { | ||
LOGGER.fine("Filtering deprecated shape: `" | ||
+ shape + "`" | ||
+ ". Shape was deprecated as of version: " + since | ||
); | ||
shapesToRemove.add(shape); | ||
} | ||
} | ||
} | ||
|
||
return transformer.removeShapes(model, shapesToRemove); | ||
} | ||
|
||
public static boolean isSemVer(String string) { | ||
return SEMVER_REGEX.matcher(string).matches(); | ||
} | ||
|
||
static int compareSemVer(String semVer1, String semVer2) { | ||
String[] versionComponents1 = semVer1.split("\\."); | ||
String[] versionComponents2 = semVer2.split("\\."); | ||
|
||
int maxLength = Math.max(versionComponents1.length, versionComponents2.length); | ||
for (int i = 0; i < maxLength; i++) { | ||
// Treat all implicit components as 0's | ||
String component1 = i >= versionComponents1.length ? "0" : versionComponents1[i]; | ||
String component2 = i >= versionComponents2.length ? "0" : versionComponents2[i]; | ||
int comparison = component1.compareTo(component2); | ||
if (comparison != 0) { | ||
return comparison; | ||
} | ||
} | ||
return 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...rc/test/java/software/amazon/smithy/model/transform/FilterDeprecatedRelativeDateTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package software.amazon.smithy.model.transform; | ||
|
||
import java.util.List; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.MethodSource; | ||
import software.amazon.smithy.model.Model; | ||
import software.amazon.smithy.model.node.Node; | ||
import software.amazon.smithy.model.shapes.ModelSerializer; | ||
import software.amazon.smithy.utils.ListUtils; | ||
|
||
public class FilterDeprecatedRelativeDateTest { | ||
|
||
public static List<String> fileSource() { | ||
return ListUtils.of("deprecated-shapes", "deprecated-members", "deprecated-traits"); | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("fileSource") | ||
void compareTransform(String prefix) { | ||
Model before = Model.assembler() | ||
.addImport(FilterDeprecatedRelativeDate.class.getResource("deprecated-date/" + prefix + "-before.smithy")) | ||
.assemble() | ||
.unwrap(); | ||
Model actualResult = ModelTransformer.create().filterDeprecatedRelativeDate(before, "2024-10-10"); | ||
Model expectedResult = Model.assembler() | ||
.addImport(FilterDeprecatedRelativeDate.class.getResource("deprecated-date/" + prefix + "-after.smithy")) | ||
.assemble() | ||
.unwrap(); | ||
|
||
Node actualNode = ModelSerializer.builder().build().serialize(actualResult); | ||
Node expectedNode = ModelSerializer.builder().build().serialize(expectedResult); | ||
Node.assertEquals(actualNode, expectedNode); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
...test/java/software/amazon/smithy/model/transform/FilterDeprecatedRelativeVersionTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package software.amazon.smithy.model.transform; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
import java.util.List; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.Arguments; | ||
import org.junit.jupiter.params.provider.MethodSource; | ||
import software.amazon.smithy.model.Model; | ||
import software.amazon.smithy.model.node.Node; | ||
import software.amazon.smithy.model.shapes.ModelSerializer; | ||
import software.amazon.smithy.utils.ListUtils; | ||
|
||
public class FilterDeprecatedRelativeVersionTest { | ||
static List<Arguments> semverSupplier() { | ||
return ListUtils.of( | ||
Arguments.of("1.0.0", "1.0.0", 0), | ||
Arguments.of("1.0.0", "1.0.1", -1), | ||
Arguments.of("1.1.0", "1.1.1", -1), | ||
Arguments.of("1.1.0", "1.0.1", 1), | ||
Arguments.of("1.1.1", "1.1.1.1", -1), | ||
Arguments.of("1.0.0.1", "1.0.0", 1), | ||
Arguments.of("1.0.0", "1.0", 0), | ||
Arguments.of("20.20.0.1", "20.20.1.0", -1), | ||
Arguments.of("20.20.1.0", "20.20.1.0-PATCH", -1) | ||
); | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("semverSupplier") | ||
void testSemverComparison(String semver1, String semver2, int expected) { | ||
int result = FilterDeprecatedRelativeVersion.compareSemVer(semver1, semver2); | ||
switch (expected) { | ||
case 0: | ||
assertEquals(result, 0); | ||
break; | ||
case -1: | ||
assertTrue(result < 0); | ||
break; | ||
case 1: | ||
assertTrue(result > 0); | ||
break; | ||
default: | ||
throw new IllegalStateException("Unexpected value: " + expected); | ||
} | ||
} | ||
|
||
public static List<String> fileSource() { | ||
return ListUtils.of("deprecated-shapes", "deprecated-members", "deprecated-traits"); | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("fileSource") | ||
void compareTransform(String prefix) { | ||
Model before = Model.assembler() | ||
.addImport(FilterDeprecatedRelativeDate.class.getResource("deprecated-version/" + prefix + "-before.smithy")) | ||
.assemble() | ||
.unwrap(); | ||
Model actualResult = ModelTransformer.create().filterDeprecatedRelativeVersion(before, "1.1.0"); | ||
Model expectedResult = Model.assembler() | ||
.addImport(FilterDeprecatedRelativeDate.class.getResource("deprecated-version/" + prefix + "-after.smithy")) | ||
.assemble() | ||
.unwrap(); | ||
|
||
Node actualNode = ModelSerializer.builder().build().serialize(actualResult); | ||
Node expectedNode = ModelSerializer.builder().build().serialize(expectedResult); | ||
Node.assertEquals(actualNode, expectedNode); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
...es/software/amazon/smithy/model/transform/deprecated-date/deprecated-members-after.smithy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
$version: "2" | ||
|
||
namespace smithy.example | ||
|
||
structure MyStruct { | ||
@deprecated(message: "Should NOT be filtered as it is deprecated at the same date as the filter", since: "2024-10-10") | ||
notFilteredEquals: String | ||
|
||
@deprecated(message: "Should NOT be filtered as it is deprecated after the filter date", since: "2024-10-11") | ||
notFilteredAfter: String | ||
} |
20 changes: 20 additions & 0 deletions
20
...s/software/amazon/smithy/model/transform/deprecated-date/deprecated-members-before.smithy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
$version: "2" | ||
|
||
namespace smithy.example | ||
|
||
structure MyStruct { | ||
@deprecated(message: "Should be filtered as it is deprecated before date", since: "2024-10-09") | ||
filteredBeforeHyphens: String | ||
|
||
@deprecated(message: "Should be filtered as it is deprecated before date", since: "20241009") | ||
filteredBeforeNoHyphens: String | ||
|
||
@deprecated(message: "Should be filtered as it is deprecated before date", since: "2024-1009") | ||
filteredBeforeMixedHyphens: String | ||
|
||
@deprecated(message: "Should NOT be filtered as it is deprecated at the same date as the filter", since: "2024-10-10") | ||
notFilteredEquals: String | ||
|
||
@deprecated(message: "Should NOT be filtered as it is deprecated after the filter date", since: "2024-10-11") | ||
notFilteredAfter: String | ||
} |
13 changes: 13 additions & 0 deletions
13
...ces/software/amazon/smithy/model/transform/deprecated-date/deprecated-shapes-after.smithy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
$version: "2" | ||
|
||
namespace smithy.example | ||
|
||
@deprecated(message: "Should NOT be filtered as it is deprecated at the same date as the filter", since: "2024-10-10") | ||
structure NotFilteredEquals { | ||
field: String | ||
} | ||
|
||
@deprecated(message: "Should NOT be filtered as it is deprecated after the filter date", since: "2024-10-11") | ||
structure NotFilteredAfter { | ||
field: String | ||
} |
Oops, something went wrong.