Skip to content

Commit 6a12923

Browse files
committed
Fix JSON Schema pointer conflicts with trait definitions
This commit updates the DeconflictingStrategy to scrub trait definitions from the model used to pre-compute JSON Schema pointers. These shapes wouldn't have made their way into converted schemas anyways, and existing behavior for non-computed pointers is maintained.
1 parent 193a262 commit 6a12923

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

smithy-jsonschema/src/main/java/software/amazon/smithy/jsonschema/DeconflictingStrategy.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import software.amazon.smithy.model.shapes.SimpleShape;
3030
import software.amazon.smithy.model.traits.EnumTrait;
3131
import software.amazon.smithy.model.traits.PrivateTrait;
32+
import software.amazon.smithy.model.transform.ModelTransformer;
3233
import software.amazon.smithy.utils.FunctionalUtils;
3334
import software.amazon.smithy.utils.StringUtils;
3435

@@ -56,8 +57,14 @@ final class DeconflictingStrategy implements RefStrategy {
5657
this.delegate = delegate;
5758

5859
// Pre-compute a map of all converted shape refs. Sort the shapes
59-
// to make the result deterministic.
60-
model.shapes().filter(shapePredicate.and(FunctionalUtils.not(this::isIgnoredShape))).sorted().forEach(shape -> {
60+
// to make the result deterministic. Eliminate trait definitions
61+
// ahead of that computation to eliminate potential conflicts with
62+
// shapes that won't go into JSON Schema anyway.
63+
Model scrubbedModel = ModelTransformer.create().scrubTraitDefinitions(model);
64+
scrubbedModel.shapes()
65+
.filter(shapePredicate.and(FunctionalUtils.not(this::isIgnoredShape)))
66+
.sorted()
67+
.forEach(shape -> {
6168
String pointer = delegate.toPointer(shape.getId());
6269
if (!reversePointers.containsKey(pointer)) {
6370
pointers.put(shape.getId(), pointer);

smithy-jsonschema/src/test/java/software/amazon/smithy/jsonschema/DeconflictingStrategyTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import software.amazon.smithy.model.shapes.ShapeId;
1414
import software.amazon.smithy.model.shapes.StringShape;
1515
import software.amazon.smithy.model.shapes.StructureShape;
16+
import software.amazon.smithy.model.traits.PrivateTrait;
17+
import software.amazon.smithy.model.traits.TraitDefinition;
1618

1719
public class DeconflictingStrategyTest {
1820
@Test
@@ -97,4 +99,27 @@ public void excludesPrivatePreludeShapes() {
9799
.createDefaultStrategy(model, new JsonSchemaConfig(), propertyNamingStrategy, alwaysTrue());
98100
assertThat(strategy.toPointer(a.getId()), equalTo("#/definitions/Severity"));
99101
}
102+
103+
@Test
104+
public void excludesTraitDefinitions() {
105+
StringShape member = StringShape.builder().id("com.foo#String").build();
106+
StructureShape matcher = StructureShape.builder()
107+
.id("com.foo#Matcher")
108+
.addMember("member", member.getId())
109+
.build();
110+
StructureShape matcherForTrait = StructureShape.builder()
111+
.id("com.bar#Matcher")
112+
.addTrait(new PrivateTrait())
113+
.build();
114+
StructureShape trait = StructureShape.builder()
115+
.id("com.bar#Trait")
116+
.addTrait(TraitDefinition.builder().build())
117+
.addMember("matcher", matcherForTrait.toShapeId())
118+
.build();
119+
Model model = Model.assembler().addShapes(trait, matcherForTrait, matcher, member).assemble().unwrap();
120+
PropertyNamingStrategy propertyNamingStrategy = PropertyNamingStrategy.createDefaultStrategy();
121+
RefStrategy strategy = RefStrategy
122+
.createDefaultStrategy(model, new JsonSchemaConfig(), propertyNamingStrategy, alwaysTrue());
123+
assertThat(strategy.toPointer(matcher.getId()), equalTo("#/definitions/Matcher"));
124+
}
100125
}

0 commit comments

Comments
 (0)