diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/transform/ModelTransformer.java b/smithy-model/src/main/java/software/amazon/smithy/model/transform/ModelTransformer.java index 445637e7fa0..ba67e2a2ba0 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/transform/ModelTransformer.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/transform/ModelTransformer.java @@ -18,17 +18,21 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.ServiceLoader; import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.Supplier; import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.loader.ModelAssembler; import software.amazon.smithy.model.neighbor.UnreferencedShapes; import software.amazon.smithy.model.neighbor.UnreferencedTraitDefinitions; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.shapes.ShapeIndex; import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.model.traits.TraitDefinition; @@ -132,6 +136,44 @@ public Model removeShapesIf(Model model, Predicate predicate) { return filterShapes(model, FunctionalUtils.not(predicate)); } + /** + * Renames shapes using ShapeId pairs while ensuring that the + * transformed model is in a consistent state. + * + *

This transformer ensures that when an aggregate shape is renamed, all + * members are updated in the model. + * + * @param model Model to transform. + * @param renamed Map of shapeIds + * @return Returns the transformed model.base. + */ + public Model renameShapes( + Model model, + Map renamed + ) { + return this.renameShapes(model, renamed, Model::assembler); + } + + /** + * Renames shapes using ShapeId pairs while ensuring that the + * transformed model is in a consistent state. + * + *

This transformer ensures that when an aggregate shape is renamed, all + * members are updated in the model. + * + * @param model Model to transform. + * @param renamed Map of shapeIds + * @param modelAssemblerSupplier Supplier used to create {@link ModelAssembler}s in each transform. + * @return Returns the transformed model. + */ + public Model renameShapes( + Model model, + Map renamed, + Supplier modelAssemblerSupplier + ) { + return new RenameShapes(renamed, modelAssemblerSupplier).transform(this, model); + } + /** * Filters shapes out of the model that do not match the given predicate. * @@ -141,7 +183,7 @@ public Model removeShapesIf(Model model, Predicate predicate) { * * @param model Model to transform. * @param predicate Predicate that filters shapes. - * @return Returns the transformed model.base. + * @return Returns the transformed model. */ public Model filterShapes(Model model, Predicate predicate) { return new FilterShapes(predicate).transform(this, model); diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/transform/RenameShapes.java b/smithy-model/src/main/java/software/amazon/smithy/model/transform/RenameShapes.java new file mode 100644 index 00000000000..565533b41b9 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/transform/RenameShapes.java @@ -0,0 +1,115 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. 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. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 software.amazon.smithy.model.transform; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.loader.ModelAssembler; +import software.amazon.smithy.model.node.ArrayNode; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.NodeVisitor; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.node.StringNode; +import software.amazon.smithy.model.shapes.ModelSerializer; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.utils.Pair; + +/** + * Renames shapes using ShapeId pairs while ensuring that the + * transformed model is in a consistent state. + * + *

Member shapes are updated when their containing shape is updated. + * + *

Trait references to ShapeId values are also updated. + */ +final class RenameShapes { + private final Map renamed; + private final ModelAssembler assembler; + + RenameShapes(Map renamed, Supplier modelAssemblerSupplier) { + this.renamed = new HashMap<>(renamed); + this.assembler = modelAssemblerSupplier.get(); + } + + Model transform(ModelTransformer transformer, Model model) { + // Remove any no-op pairs to avoid renaming shapes unnecessarily. + renamed.keySet().removeIf(fromId -> fromId.equals(renamed.get(fromId))); + if (renamed.isEmpty()) { + return model; + } + + // Creates a set that will be used for checking if a string value needs to be renamed or not. + Set toRename = renamed.keySet().stream() + .map(ShapeId::toString) + .collect(Collectors.toSet()); + + // This transformer converts the model into an ObjectNode. This approach was chosen because the + // JSON AST format includes fully qualified shape ID values, making it possible rename shapes across + // the model by only needing to compare and replace StringNode values. + ModelSerializer serializer = ModelSerializer.builder().build(); + ObjectNode node = serializer.serialize(model); + + // Use visitor to traverse node and rebuild model. + Node newModel = node.accept(new RenameShapeVisitor(toRename, renamed)); + + return assembler.addDocumentNode(newModel) + .assemble() + .unwrap(); + } + + private static final class RenameShapeVisitor extends NodeVisitor.Default { + + private final Set toRename; + private final Map shapeMapping; + + RenameShapeVisitor(Set toRename, Map shapeMapping) { + this.toRename = toRename; + this.shapeMapping = shapeMapping; + } + + @Override + protected Node getDefault(Node node) { + return node; + } + + @Override + public Node arrayNode(ArrayNode node) { + return node.getElements().stream() + .map(element -> element.accept(this)) + .collect(ArrayNode.collect()); + } + + @Override + public Node objectNode(ObjectNode node) { + return node.getMembers().entrySet().stream() + .map(entry -> Pair.of(entry.getKey().accept(this), entry.getValue().accept(this))) + .collect(ObjectNode.collect(pair -> pair.getLeft().expectStringNode(), Pair::getRight)); + } + + @Override + public Node stringNode(StringNode node) { + if (toRename.contains(node.getValue())) { + ShapeId nodeShapeId = node.expectShapeId(); + return new StringNode(shapeMapping.get(nodeShapeId).toString(), node.getSourceLocation()); + } + return node; + } + } +} diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/transform/RenameShapesTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/transform/RenameShapesTest.java new file mode 100644 index 00000000000..9697088f1c8 --- /dev/null +++ b/smithy-model/src/test/java/software/amazon/smithy/model/transform/RenameShapesTest.java @@ -0,0 +1,383 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. 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. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 software.amazon.smithy.model.transform; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.node.ArrayNode; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.node.StringNode; +import software.amazon.smithy.model.shapes.ListShape; +import software.amazon.smithy.model.shapes.MapShape; +import software.amazon.smithy.model.shapes.MemberShape; +import software.amazon.smithy.model.shapes.ResourceShape; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.shapes.SetShape; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.shapes.StringShape; +import software.amazon.smithy.model.shapes.StructureShape; +import software.amazon.smithy.model.shapes.UnionShape; +import software.amazon.smithy.model.traits.Trait; + +public class RenameShapesTest { + + @Test + public void returnsUnmodifiedModelIfGivenEmptyRenameMapping() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + StringShape fooTarget = StringShape.builder().id(stringId).build(); + Model model = Model.builder() + .addShapes(fooTarget) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + Map renamed = new HashMap<>(); + Model result = transformer.renameShapes(model, renamed); + + assertEquals(result.shapes().count(), 1); + assertEquals(result.getShape(stringId).get(), fooTarget); + } + + @Test + public void returnsUnmodifiedModelIfToAndFromAreEqual() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + StringShape target = StringShape.builder().id(stringId).build(); + Model model = Model.builder() + .addShapes(target) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + Map renamed = new HashMap<>(); + renamed.put(stringId, stringId ); + Model result = transformer.renameShapes(model, renamed); + + assertEquals(result.shapes().count(), 1); + assertEquals(result.getShape(stringId).get(), target); + } + + @Test + public void returnsModelWithRenamedStringShape() { + ShapeId fromStringId = ShapeId.from("ns.foo#String"); + ShapeId containerId = ShapeId.from("ns.foo#Container"); + ShapeId keyId = ShapeId.from("ns.foo#Container$key"); + ShapeId valueId = ShapeId.from("ns.foo#Container$value"); + + StringShape target = StringShape.builder().id(fromStringId).build(); + MemberShape keyMember = MemberShape.builder().id(keyId).target(fromStringId).build(); + MemberShape valueMember = MemberShape.builder().id(valueId).target(fromStringId).build(); + MapShape container = MapShape.builder().id(containerId).key(keyMember).value(valueMember).build(); + Model model = Model.builder() + .addShapes(target, keyMember, valueMember, container) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + + ShapeId toStringId = ShapeId.from("ns.bar#String"); + Map renamed = new HashMap<>(); + renamed.put(fromStringId, toStringId ); + Model result = transformer.renameShapes(model, renamed); + + assertTrue(result.getShape(toStringId).isPresent()); + assertFalse(result.getShape(fromStringId).isPresent()); + } + + @Test + public void updatesMetadataReferences() { + Model model = Model.assembler() + .addImport(IntegTest.class.getResource("rename-shape-test-model.json")) + .assemble() + .unwrap(); + + Map renamed = new HashMap<>(); + ShapeId fooUnreferenced = ShapeId.from("ns.foo#UnreferencedString"); + ShapeId barUnreferenced = ShapeId.from("ns.bar#UnreferencedString"); + renamed.put(fooUnreferenced, barUnreferenced); + ModelTransformer transformer = ModelTransformer.create(); + Model result = transformer.renameShapes(model, renamed); + ArrayNode suppressions = result.getMetadata().get("suppressions").asArrayNode().get(); + ObjectNode suppression = suppressions.getElements().get(0).asObjectNode().get(); + ArrayNode suppressionShapes = suppression.getStringMap().get("shapes").expectArrayNode(); + StringNode suppressionShape = suppressionShapes.getElements().get(0).asStringNode().get(); + + assertEquals(suppressionShape.getValue(), "ns.bar#UnreferencedString"); + assertTrue(result.getShape(barUnreferenced).isPresent()); + assertFalse(result.getShape(fooUnreferenced).isPresent()); + } + + @Test + public void updatesIdRefValues() { + Model model = Model.assembler() + .addImport(IntegTest.class.getResource("rename-shape-test-model.json")) + .assemble() + .unwrap(); + + Map renamed = new HashMap<>(); + ShapeId fromId = ShapeId.from("ns.foo#OldShape"); + ShapeId toId = ShapeId.from("ns.foo#NewShape"); + renamed.put(fromId, toId); + ModelTransformer transformer = ModelTransformer.create(); + Model result = transformer.renameShapes(model, renamed); + StringNode node = Node.from(toId.toShapeId().toString()); + + assertTrue(result.getShape(toId).isPresent()); + assertFalse(result.getShape(fromId).isPresent()); + Shape shape = result.expectShape(ShapeId.from("ns.foo#ValidShape")); + Trait trait = shape.findTrait("ns.foo#integerRef").get(); + assertEquals(trait.toNode(), node); + } + + @Test + public void updatesShapeNamesAndReferences() { + Model model = Model.assembler() + .addImport(IntegTest.class.getResource("rename-shape-test-model.json")) + .assemble() + .unwrap(); + Map renamed = new HashMap<>(); + + // Service + ShapeId fromService = ShapeId.from("ns.foo#MyService"); + ShapeId toService = ShapeId.from("ns.bar#MyNewService"); + renamed.put(fromService, toService); + + // Operation + ShapeId fromOperation = ShapeId.from("ns.foo#MyOperation"); + ShapeId toOperation = ShapeId.from("ns.baz#MyNewOperation"); + renamed.put(fromOperation, toOperation); + ShapeId fromOtherOperation = ShapeId.from("ns.foo#MyOtherOperation"); + ShapeId toOtherOperation = ShapeId.from("ns.fred#MyOtherNewOperation"); + renamed.put(fromOtherOperation, toOtherOperation); + + // Resource + ShapeId fromResource = ShapeId.from("ns.foo#MyResource"); + ShapeId toResource = ShapeId.from("ns.qux#MyNewResource"); + renamed.put(fromResource, toResource); + + // Structure + ShapeId fromStructure = ShapeId.from("ns.foo#MyStructure"); + ShapeId toStructure = ShapeId.from("ns.quux#MyNewStructure"); + renamed.put(fromStructure, toStructure); + + // List + ShapeId fromList = ShapeId.from("ns.foo#MyList"); + ShapeId toList = ShapeId.from("ns.quuz#MyNewList"); + renamed.put(fromList, toList); + + // Map + ShapeId fromMap = ShapeId.from("ns.foo#MyMap"); + ShapeId toMap = ShapeId.from("ns.corge#MyNewMap"); + renamed.put(fromMap, toMap); + + // Set + ShapeId fromSet = ShapeId.from("ns.foo#MySet"); + ShapeId toSet = ShapeId.from("ns.grault#MyNewSet"); + renamed.put(fromSet, toSet); + + // Union + ShapeId fromUnion = ShapeId.from("ns.foo#MyUnion"); + ShapeId toUnion = ShapeId.from("ns.garply#MyNewUnion"); + renamed.put(fromUnion, toUnion); + + // ID + ShapeId fromId = ShapeId.from("ns.foo#MyId"); + ShapeId toId = ShapeId.from("ns.waldo#MyNewId"); + renamed.put(fromId, toId); + + ModelTransformer transformer = ModelTransformer.create(); + Model result = transformer.renameShapes(model, renamed); + + // All new names are present. + assertTrue(result.getShape(toService).isPresent()); + assertTrue(result.getShape(toOperation).isPresent()); + assertTrue(result.getShape(toResource).isPresent()); + assertTrue(result.getShape(toStructure).isPresent()); + assertTrue(result.getShape(toList).isPresent()); + assertTrue(result.getShape(toMap).isPresent()); + assertTrue(result.getShape(toSet).isPresent()); + assertTrue(result.getShape(toUnion).isPresent()); + assertTrue(result.getShape(toId).isPresent()); + + // All new shapes are updated as references. + ServiceShape service = result.getShape(toService).get().asServiceShape().get(); + assertTrue(service.getOperations().contains(toOperation)); + assertTrue(service.getResources().contains(toResource)); + + ResourceShape resource = result.getShape(toResource).get().asResourceShape().get(); + assertEquals(resource.getIdentifiers().get("myId"), toId); + assertTrue(resource.getAllOperations().contains(toOtherOperation)); + + StructureShape operationInput = result.getShape(ShapeId.from("ns.foo#MyOperationInput")).get() + .asStructureShape().get(); + MemberShape struct = operationInput.getMember("struct").get(); + MemberShape list = operationInput.getMember("list").get(); + MemberShape map = operationInput.getMember("map").get(); + MemberShape set = operationInput.getMember("set").get(); + MemberShape union = operationInput.getMember("union").get(); + assertEquals(struct.getTarget(), toStructure); + assertEquals(list.getTarget(), toList); + assertEquals(map.getTarget(), toMap); + assertEquals(set.getTarget(), toSet); + assertEquals(union.getTarget(), toUnion); + + // All old names have been removed. + assertFalse(result.getShape(fromService).isPresent()); + assertFalse(result.getShape(fromOperation).isPresent()); + assertFalse(result.getShape(fromResource).isPresent()); + assertFalse(result.getShape(fromStructure).isPresent()); + assertFalse(result.getShape(fromList).isPresent()); + assertFalse(result.getShape(fromMap).isPresent()); + assertFalse(result.getShape(fromSet).isPresent()); + assertFalse(result.getShape(fromUnion).isPresent()); + assertFalse(result.getShape(fromId).isPresent()); + } + + @Test + public void updatesListMembersWhenContainerUpdated() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + ShapeId containerId = ShapeId.from("ns.foo#Container"); + ShapeId memberId = ShapeId.from("ns.foo#Container$member"); + + StringShape target = StringShape.builder().id(stringId).build(); + MemberShape member = MemberShape.builder().id(memberId).target(target).build(); + ListShape container = ListShape.builder().id(containerId).addMember(member).build(); + Model model = Model.builder() + .addShapes(target, member, container) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + ShapeId newContainerId = ShapeId.from("ns.bar#Baz"); + ShapeId newMemberId = ShapeId.from("ns.bar#Baz$member"); + Map renamed = new HashMap<>(); + renamed.put(containerId, newContainerId); + Model result = transformer.renameShapes(model, renamed); + + assertTrue(result.getShape(newContainerId).isPresent()); + ListShape newContainer = result.getShape(newContainerId).get().asListShape().get(); + assertEquals(newContainer.getMember().getId(), newMemberId); + assertFalse(result.getShape(containerId).isPresent()); + } + + @Test + public void updatesMapMembersWhenContainerUpdated() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + ShapeId containerId = ShapeId.from("ns.foo#Container"); + ShapeId keyId = ShapeId.from("ns.foo#Container$key"); + ShapeId valueId = ShapeId.from("ns.foo#Container$value"); + + StringShape target = StringShape.builder().id(stringId).build(); + MemberShape keyMember = MemberShape.builder().id(keyId).target(stringId).build(); + MemberShape valueMember = MemberShape.builder().id(valueId).target(stringId).build(); + MapShape container = MapShape.builder().id(containerId).key(keyMember).value(valueMember).build(); + Model model = Model.builder() + .addShapes(target, keyMember, valueMember, container) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + ShapeId newContainerId = ShapeId.from("ns.bar#Baz"); + ShapeId newKeyId = ShapeId.from("ns.bar#Baz$key"); + ShapeId newValueId = ShapeId.from("ns.bar#Baz$value"); + Map renamed = new HashMap<>(); + renamed.put(containerId, newContainerId); + Model result = transformer.renameShapes(model, renamed); + + assertTrue(result.getShape(newContainerId).isPresent()); + MapShape newContainer = result.getShape(newContainerId).get().asMapShape().get(); + assertEquals(newContainer.getKey().getId(), newKeyId); + assertEquals(newContainer.getValue().getId(), newValueId); + assertFalse(result.getShape(containerId).isPresent()); + } + + @Test + public void updatesSetMembersWhenContainerUpdated() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + ShapeId containerId = ShapeId.from("ns.foo#Container"); + ShapeId memberId = ShapeId.from("ns.foo#Container$member"); + + StringShape target = StringShape.builder().id(stringId).build(); + MemberShape member = MemberShape.builder().id(memberId).target(target).build(); + SetShape container = SetShape.builder().id(containerId).addMember(member).build(); + Model model = Model.builder() + .addShapes(target, member, container) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + ShapeId newContainerId = ShapeId.from("ns.bar#Baz"); + ShapeId newMemberId = ShapeId.from("ns.bar#Baz$member"); + Map renamed = new HashMap<>(); + renamed.put(containerId, newContainerId); + Model result = transformer.renameShapes(model, renamed); + + assertTrue(result.getShape(newContainerId).isPresent()); + SetShape newContainer = result.getShape(newContainerId).get().asSetShape().get(); + assertEquals(newContainer.getMember().getId(), newMemberId); + assertFalse(result.getShape(containerId).isPresent()); + } + + @Test + public void updatesStructureMembersWhenContainerUpdated() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + ShapeId containerId = ShapeId.from("ns.foo#Container"); + ShapeId memberId = ShapeId.from("ns.foo#Container$member"); + + StringShape target = StringShape.builder().id(stringId).build(); + MemberShape member = MemberShape.builder().id(memberId).target(target).build(); + StructureShape container = StructureShape.builder().id(containerId).addMember(member).build(); + Model model = Model.builder() + .addShapes(target, member, container) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + ShapeId newContainerId = ShapeId.from("ns.bar#Baz"); + ShapeId newMemberId = ShapeId.from("ns.bar#Baz$member"); + Map renamed = new HashMap<>(); + renamed.put(containerId, newContainerId); + Model result = transformer.renameShapes(model, renamed); + + assertTrue(result.getShape(newContainerId).isPresent()); + StructureShape newContainer = result.getShape(newContainerId).get().asStructureShape().get(); + newContainer.getMember("member").ifPresent(newMember -> { + assertEquals(newMember.getId(), newMemberId); + }); + assertFalse(result.getShape(containerId).isPresent()); + } + + @Test + public void updatesUnionMembersWhenContainerUpdated() { + ShapeId stringId = ShapeId.from("ns.foo#String"); + ShapeId containerId = ShapeId.from("ns.foo#Container"); + ShapeId memberId = ShapeId.from("ns.foo#Container$member"); + + StringShape target = StringShape.builder().id(stringId).build(); + MemberShape member = MemberShape.builder().id(memberId).target(target).build(); + UnionShape container = UnionShape.builder().id(containerId).addMember(member).build(); + Model model = Model.builder() + .addShapes(target, member, container) + .build(); + ModelTransformer transformer = ModelTransformer.create(); + ShapeId newContainerId = ShapeId.from("ns.bar#Baz"); + ShapeId newMemberId = ShapeId.from("ns.bar#Baz$member"); + Map renamed = new HashMap<>(); + renamed.put(containerId, newContainerId); + Model result = transformer.renameShapes(model, renamed); + + assertTrue(result.getShape(newContainerId).isPresent()); + UnionShape newContainer = result.getShape(newContainerId).get().asUnionShape().get(); + newContainer.getMember("member").ifPresent(newMember -> { + assertEquals(newMember.getId(), newMemberId); + }); + assertFalse(result.getShape(containerId).isPresent()); + } +} diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/transform/rename-shape-test-model.json b/smithy-model/src/test/resources/software/amazon/smithy/model/transform/rename-shape-test-model.json new file mode 100644 index 00000000000..2373aedc5ee --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/transform/rename-shape-test-model.json @@ -0,0 +1,179 @@ +{ + "smithy": "0.5.0", + "shapes": { + "ns.foo#MyService": { + "type": "service", + "version": "2017-01-17", + "operations": [ + { + "target": "ns.foo#MyOperation" + } + ], + "resources": [ + { + "target": "ns.foo#MyResource" + } + ], + "traits": { + "smithy.api#protocols": [ + { + "name": "foo" + } + ] + } + }, + "ns.foo#MyOperation": { + "type": "operation", + "input": { + "target": "ns.foo#MyOperationInput" + }, + "output": { + "target": "ns.foo#MyOperationOutput" + }, + "errors": [ + { + "target": "ns.foo#MyOperationError" + } + ], + "traits": { + "smithy.api#readonly": true + } + }, + "ns.foo#MyOperationInput": { + "type": "structure", + "members": { + "struct": { + "target": "ns.foo#MyStructure" + }, + "list": { + "target": "ns.foo#MyList" + }, + "map": { + "target": "ns.foo#MyMap" + }, + "set": { + "target": "ns.foo#MySet" + }, + "union": { + "target": "ns.foo#MyUnion" + } + } + }, + "ns.foo#MyStructure": { + "type": "structure" + }, + "ns.foo#MyList": { + "type": "list", + "member": { + "target": "smithy.api#String" + } + }, + "ns.foo#MyMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + } + }, + "ns.foo#MySet": { + "type": "set", + "member": { + "target": "smithy.api#String" + } + }, + "ns.foo#MyUnion": { + "type": "union", + "members": { + "a": { + "target": "smithy.api#String" + }, + "b": { + "target": "smithy.api#String", + "traits": { + "smithy.api#sensitive": true + } + } + } + }, + "ns.foo#MyOperationOutput": { + "type": "structure" + }, + "ns.foo#MyOperationError": { + "type": "structure", + "traits": { + "smithy.api#error": "client" + } + }, + "ns.foo#MyResource": { + "type": "resource", + "identifiers": { + "myId": { + "target": "ns.foo#MyId" + } + }, + "operations": [ + { + "target": "ns.foo#MyOtherOperation" + } + ] + }, + "ns.foo#MyId": { + "type": "string" + }, + "ns.foo#MyOtherOperation": { + "type": "operation", + "input": { + "target": "ns.foo#MyOtherInput" + }, + "output": { + "target": "ns.foo#MyStructure" + } + }, + "ns.foo#MyOtherInput": { + "type": "structure", + "members": { + "myId": { + "target": "ns.foo#MyId", + "traits": { + "smithy.api#required": true + } + } + } + + }, + "ns.foo#integerRef": { + "type": "string", + "traits": { + "smithy.api#trait": true, + "smithy.api#idRef": { + "failWhenMissing": true, + "selector": "integer" + } + } + }, + "ns.foo#ValidShape": { + "type": "string", + "traits": { + "ns.foo#integerRef": "ns.foo#OldShape", + "smithy.api#deprecated": {} + } + }, + "ns.foo#OldShape": { + "type": "integer" + }, + "ns.foo#UnreferencedString": { + "type": "string" + } + }, + "metadata": { + "suppressions": [ + { + "ids": ["UnreferencedShape"], + "shapes": ["ns.foo#UnreferencedString"], + "reason": "unreferenced shape" + } + ] + } +}