From 379b055cc7132d93e8e749fad8b05ff644f8b924 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Wed, 3 Jun 2026 15:02:30 -0700 Subject: [PATCH 01/23] Change ShapeRef to MemberShape --- gems/smithy-cbor/lib/smithy-cbor/builder.rb | 18 ++--- gems/smithy-cbor/lib/smithy-cbor/codec.rb | 4 +- gems/smithy-cbor/lib/smithy-cbor/parser.rb | 22 +++--- gems/smithy-cbor/sig/smithy-cbor/codec.rbs | 4 +- .../spec/smithy-cbor/builder_spec.rb | 4 +- .../lib/smithy-client/default_params.rb | 10 +-- .../lib/smithy-client/log_param_filter.rb | 18 ++--- .../lib/smithy-client/param_converter.rb | 16 ++--- .../lib/smithy-client/param_validator.rb | 26 +++---- .../lib/smithy-client/plugins/host_prefix.rb | 2 +- .../plugins/idempotency_token.rb | 2 +- .../plugins/request_compression.rb | 6 +- .../plugins/transfer_encoding.rb | 6 +- .../rpc_v2_cbor/error_handler.rb | 4 +- .../lib/smithy-client/rpc_v2_cbor/handler.rb | 6 +- .../smithy-client/stubbing/data_applicator.rb | 10 +-- .../lib/smithy-client/stubbing/empty_stub.rb | 8 +-- .../smithy-client/log_param_filter_spec.rb | 4 +- .../smithy-client/param_converter_spec.rb | 4 +- .../plugins/transfer_encoding_spec.rb | 4 +- gems/smithy-json/lib/smithy-json/builder.rb | 18 ++--- gems/smithy-json/lib/smithy-json/codec.rb | 4 +- gems/smithy-json/lib/smithy-json/parser.rb | 22 +++--- gems/smithy-json/sig/smithy-json/codec.rbs | 4 +- .../spec/smithy-json/builder_spec.rb | 4 +- .../document_utils/deserializer.rb | 20 +++--- .../document_utils/serializer.rb | 18 ++--- .../smithy-schema/lib/smithy-schema/shapes.rb | 46 ++++++------- .../sig/smithy-schema/shapes.rbs | 44 ++++++------ .../spec/smithy-schema/shapes_spec.rb | 68 +++++++++---------- gems/smithy-xml/lib/smithy-xml/builder.rb | 30 ++++---- gems/smithy-xml/lib/smithy-xml/codec.rb | 4 +- gems/smithy-xml/lib/smithy-xml/parser.rb | 4 +- .../smithy-xml/lib/smithy-xml/parser/frame.rb | 22 +++--- gems/smithy-xml/sig/smithy-xml/codec.rbs | 4 +- .../spec/smithy-xml/builder_spec.rb | 6 +- .../smithy/templates/client/errors_rbs.erb | 2 +- .../lib/smithy/templates/client/schema.erb | 2 +- gems/smithy/lib/smithy/views/client/schema.rb | 28 ++++---- .../spec/interfaces/rename_shapes_spec.rb | 4 +- .../interfaces/synthetic_input_output_spec.rb | 12 ++-- .../spec/support/examples/schema_examples.rb | 24 +++---- 42 files changed, 284 insertions(+), 284 deletions(-) diff --git a/gems/smithy-cbor/lib/smithy-cbor/builder.rb b/gems/smithy-cbor/lib/smithy-cbor/builder.rb index 076e718dd..7eb4bab2b 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/builder.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/builder.rb @@ -13,8 +13,8 @@ def initialize(options = {}) end def build(shape, data) - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) - return if ref.shape == Prelude::Unit + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) + return if ref.target == Prelude::Unit Cbor.encode(shape(ref, data)) end @@ -22,7 +22,7 @@ def build(shape, data) private def shape(ref, value) - case ref.shape + case ref.target when BlobShape then blob(value) when ListShape then list(ref, value) when MapShape then map(ref, value) @@ -39,7 +39,7 @@ def blob(value) def list(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.collect do |value| shape(shape.member, value) end @@ -48,7 +48,7 @@ def list(ref, values) def map(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.each.with_object({}) do |(key, value), data| data[key] = shape(shape.value, value) end @@ -57,7 +57,7 @@ def map(ref, values) def structure(ref, values) return if values.nil? - ref.shape.members.each_with_object({}) do |(member_name, member_ref), data| + ref.target.members.each_with_object({}) do |(member_name, member_ref), data| value = values[member_name] next if value.nil? @@ -70,12 +70,12 @@ def union(ref, values) # rubocop:disable Metrics/AbcSize data = {} if values.is_a?(Schema::Union) - _name, member_ref = ref.shape.member_by_type(values.class) + _name, member_ref = ref.target.member_by_type(values.class) data[member_ref.location_name] = shape(member_ref, values.value) else key, value = values.first - if ref.shape.member?(key) - member_ref = ref.shape.member(key) + if ref.target.member?(key) + member_ref = ref.target.member(key) data[member_ref.location_name] = shape(member_ref, value) end end diff --git a/gems/smithy-cbor/lib/smithy-cbor/codec.rb b/gems/smithy-cbor/lib/smithy-cbor/codec.rb index 72e5cb451..1931e6c64 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/codec.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/codec.rb @@ -9,14 +9,14 @@ def initialize(options = {}) @options = options end - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [Object] data # @return [String, nil] def build(shape, data) Builder.new(@options).build(shape, data) end - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [String] bytes # @param [Object, nil] target (nil) # @return [Object, nil] diff --git a/gems/smithy-cbor/lib/smithy-cbor/parser.rb b/gems/smithy-cbor/lib/smithy-cbor/parser.rb index 18b1fcb96..2d580df76 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/parser.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/parser.rb @@ -15,7 +15,7 @@ def initialize(options = {}) def parse(shape, bytes, target = nil) return {} if bytes.empty? - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) shape(ref, Cbor.decode(bytes), target) end @@ -24,7 +24,7 @@ def parse(shape, bytes, target = nil) def shape(ref, value, target = nil) return nil if value.nil? - case ref.shape + case ref.target when ListShape then list(ref, value, target) when MapShape then map(ref, value, target) when StructureShape then structure(ref, value, target) @@ -36,9 +36,9 @@ def shape(ref, value, target = nil) def list(ref, values, target = nil) target = [] if target.nil? values.each do |value| - next if value.nil? && !sparse?(ref.shape) + next if value.nil? && !sparse?(ref.target) - target << shape(ref.shape.member, value) + target << shape(ref.target.member, value) end target end @@ -46,16 +46,16 @@ def list(ref, values, target = nil) def map(ref, values, target = nil) target = {} if target.nil? values.each do |key, value| - next if value.nil? && !sparse?(ref.shape) + next if value.nil? && !sparse?(ref.target) - target[key] = shape(ref.shape.value, value) + target[key] = shape(ref.target.value, value) end target end def structure(ref, values, target = nil) - target = ref.shape.type.new if target.nil? - ref.shape.members.each do |member_name, member_ref| + target = ref.target.type.new if target.nil? + ref.target.members.each do |member_name, member_ref| value = values[member_ref.location_name] target[member_name] = shape(member_ref, value) unless value.nil? end @@ -63,17 +63,17 @@ def structure(ref, values, target = nil) end def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize - ref.shape.members.each do |member_name, member_ref| + ref.target.members.each do |member_name, member_ref| value = values[member_ref.location_name] next if value.nil? - target = ref.shape.member_type(member_name) if target.nil? + target = ref.target.member_type(member_name) if target.nil? return target.new(member_name => shape(member_ref, value)) end values.delete('__type') key, value = values.first - ref.shape.member_type(:unknown).new(unknown: { key => value }) + ref.target.member_type(:unknown).new(unknown: { key => value }) end def sparse?(shape) diff --git a/gems/smithy-cbor/sig/smithy-cbor/codec.rbs b/gems/smithy-cbor/sig/smithy-cbor/codec.rbs index 6febd3a71..2b6341287 100644 --- a/gems/smithy-cbor/sig/smithy-cbor/codec.rbs +++ b/gems/smithy-cbor/sig/smithy-cbor/codec.rbs @@ -2,8 +2,8 @@ module Smithy module Cbor module Codec def initialize: (?Hash[Symbol, untyped] options) -> void - def build: (Schema::Shapes::Shape | Schema::Shapes::ShapeRef shape, Object data) -> (nil | String) - def parse: (Schema::Shapes::Shape | Schema::Shapes::ShapeRef shape, String bytes, ?Object ?target) -> Object? + def build: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, Object data) -> (nil | String) + def parse: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, String bytes, ?Object ?target) -> Object? end end end \ No newline at end of file diff --git a/gems/smithy-cbor/spec/smithy-cbor/builder_spec.rb b/gems/smithy-cbor/spec/smithy-cbor/builder_spec.rb index 72f363b0f..4ebead47d 100644 --- a/gems/smithy-cbor/spec/smithy-cbor/builder_spec.rb +++ b/gems/smithy-cbor/spec/smithy-cbor/builder_spec.rb @@ -77,7 +77,7 @@ module Cbor context 'unions' do it 'builds unions as a type' do - union = structure_shape.member(:union).shape.member_type(:string).new(string: 'string') + union = structure_shape.member(:union).target.member_type(:string).new(string: 'string') type = structure_shape.type.new(union: union) bytes = subject.build(structure_shape, type) expect(Cbor.decode(bytes)).to eq({ 'union' => { 'string' => 'string' } }) @@ -90,7 +90,7 @@ module Cbor end it 'builds union unit members as a type' do - union = structure_shape.member(:union).shape.member_type(:unit).new(unit: Schema::EmptyStructure.new) + union = structure_shape.member(:union).target.member_type(:unit).new(unit: Schema::EmptyStructure.new) type = structure_shape.type.new(union: union) bytes = subject.build(structure_shape, type) expect(Cbor.decode(bytes)).to eq('union' => { 'unit' => {} }) diff --git a/gems/smithy-client/lib/smithy-client/default_params.rb b/gems/smithy-client/lib/smithy-client/default_params.rb index db3401bcf..8d879527b 100644 --- a/gems/smithy-client/lib/smithy-client/default_params.rb +++ b/gems/smithy-client/lib/smithy-client/default_params.rb @@ -22,7 +22,7 @@ def apply(params) private def shape(ref, value) - case ref.shape + case ref.target when ListShape then list(ref, value) when MapShape then map(ref, value) when StructureShape then structure(ref, value) @@ -33,7 +33,7 @@ def shape(ref, value) def list(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.each do |value| shape(shape.member, value) end @@ -43,7 +43,7 @@ def list(ref, values) def map(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.each_pair do |_key, value| shape(shape.value, value) end @@ -53,7 +53,7 @@ def map(ref, values) def structure(ref, values) return if values.nil? - ref.shape.members.each do |member_name, member_ref| + ref.target.members.each do |member_name, member_ref| value = values[member_name] value ||= default(member_ref) if default?(ref, member_ref.traits) next if value.nil? && !default?(ref, member_ref.traits) # default can have nil values @@ -72,7 +72,7 @@ def default?(ref, traits) def default(ref) default = ref.traits['smithy.api#default'] - case ref.shape + case ref.target when BlobShape then Base64.strict_decode64(default) when TimestampShape then timestamp_default(default) else default diff --git a/gems/smithy-client/lib/smithy-client/log_param_filter.rb b/gems/smithy-client/lib/smithy-client/log_param_filter.rb index ebd00af84..551c9e849 100644 --- a/gems/smithy-client/lib/smithy-client/log_param_filter.rb +++ b/gems/smithy-client/lib/smithy-client/log_param_filter.rb @@ -11,7 +11,7 @@ def initialize(options = {}) end def filter(ref, values) - case ref.shape + case ref.target when ListShape then list(ref, values) when MapShape then map(ref, values) when StructureShape then structure(ref, values) @@ -23,7 +23,7 @@ def filter(ref, values) private def list(ref, values) - shape = ref.shape + shape = ref.target return '[FILTERED]' if sensitive?(shape) member_ref = shape.member @@ -31,7 +31,7 @@ def list(ref, values) end def map(ref, values) - shape = ref.shape + shape = ref.target return '[FILTERED]' if sensitive?(shape) filtered = {} @@ -43,13 +43,13 @@ def map(ref, values) end def scalar(ref, value) - return '[FILTERED]' if sensitive?(ref.shape) + return '[FILTERED]' if sensitive?(ref.target) value end def structure(ref, values) - shape = ref.shape + shape = ref.target return '[FILTERED]' if sensitive?(shape) filtered = {} @@ -63,17 +63,17 @@ def structure(ref, values) end def union(ref, values) # rubocop:disable Metrics/AbcSize - shape = ref.shape + shape = ref.target return '[FILTERED]' if sensitive?(shape) filtered = {} if values.is_a?(Schema::Union) - name, member_ref = ref.shape.member_by_type(values.class) + name, member_ref = ref.target.member_by_type(values.class) filtered[name] = filter(member_ref, values.value) else key, value = values.first - if ref.shape.member?(key) - member_ref = ref.shape.member(key) + if ref.target.member?(key) + member_ref = ref.target.member(key) filtered[key] = filter(member_ref, value) end end diff --git a/gems/smithy-client/lib/smithy-client/param_converter.rb b/gems/smithy-client/lib/smithy-client/param_converter.rb index f89eb0237..a28633225 100644 --- a/gems/smithy-client/lib/smithy-client/param_converter.rb +++ b/gems/smithy-client/lib/smithy-client/param_converter.rb @@ -36,11 +36,11 @@ def close_opened_files private def c(ref, value) - self.class.c(ref.shape.class, value, self) + self.class.c(ref.target.class, value, self) end def shape(ref, value) - case ref.shape + case ref.target when ListShape then list(ref, value) when MapShape then map(ref, value) when StructureShape then structure(ref, value) @@ -53,7 +53,7 @@ def list(ref, values) values = c(ref, values) return values unless values.is_a?(Array) - values.collect { |v| shape(ref.shape.member, v) } + values.collect { |v| shape(ref.target.member, v) } end def map(ref, values) @@ -61,7 +61,7 @@ def map(ref, values) return values unless values.is_a?(Hash) values.each.with_object({}) do |(key, value), hash| - hash[shape(ref.shape.key, key)] = shape(ref.shape.value, value) + hash[shape(ref.target.key, key)] = shape(ref.target.value, value) end end @@ -71,9 +71,9 @@ def structure(ref, values) values.each_pair do |k, v| next if v.nil? - next unless ref.shape.member?(k) + next unless ref.target.member?(k) - values[k] = shape(ref.shape.member(k), v) + values[k] = shape(ref.target.member(k), v) end values end @@ -82,11 +82,11 @@ def union(ref, values) values = c(ref, values) if values.is_a?(Schema::Union) - _name, member_ref = ref.shape.member_by_type(values.class) + _name, member_ref = ref.target.member_by_type(values.class) values = shape(member_ref, values) elsif values.is_a?(Hash) key, value = values.first - values[key] = shape(ref.shape.member(key), value) + values[key] = shape(ref.target.member(key), value) end values end diff --git a/gems/smithy-client/lib/smithy-client/param_validator.rb b/gems/smithy-client/lib/smithy-client/param_validator.rb index 6959ebbc1..1bede2ab9 100644 --- a/gems/smithy-client/lib/smithy-client/param_validator.rb +++ b/gems/smithy-client/lib/smithy-client/param_validator.rb @@ -29,7 +29,7 @@ def validate!(params, context: 'params') # rubocop:disable Metrics def shape(ref, value, errors, context) - case ref.shape + case ref.target when StructureShape then structure(ref, value, errors, context) when ListShape then list(ref, value, errors, context) when MapShape then map(ref, value, errors, context) @@ -96,7 +96,7 @@ def list(ref, values, errors, context) values.each.with_index do |value, index| next unless value - shape(ref.shape.member, value, errors, context + "[#{index}]") + shape(ref.target.member, value, errors, context + "[#{index}]") end end @@ -107,16 +107,16 @@ def map(ref, values, errors, context) end values.each do |key, value| - shape(ref.shape.key, key, errors, "#{context} #{key.inspect} key") + shape(ref.target.key, key, errors, "#{context} #{key.inspect} key") next unless value - shape(ref.shape.value, value, errors, context + "[#{key.inspect}]") + shape(ref.target.value, value, errors, context + "[#{key.inspect}]") end end def member(ref, name, value, errors, context) - if ref.shape.member?(name) - member_ref = ref.shape.member(name) + if ref.target.member?(name) + member_ref = ref.target.member(name) shape(member_ref, value, errors, context + "[#{name.inspect}]") else errors << "unexpected value at #{context}[#{name.inspect}]" @@ -124,7 +124,7 @@ def member(ref, name, value, errors, context) end def structure(ref, values, errors, context) - return if ref.shape == Prelude::Unit + return if ref.target == Prelude::Unit return unless valid_structure?(ref, values, errors, context) validate_required_members(ref, values, errors, context) if @validate_required @@ -136,7 +136,7 @@ def structure(ref, values, errors, context) end def valid_structure?(ref, values, errors, context) - if !values.is_a?(Hash) && !values.is_a?(ref.shape.type) + if !values.is_a?(Hash) && !values.is_a?(ref.target.type) errors << expected_got(context, 'a Hash', values) return false end @@ -148,7 +148,7 @@ def union(ref, values, errors, context) return unless valid_union?(ref, values, errors, context) if values.is_a?(Schema::Union) - _name, member_ref = ref.shape.member_by_type(values.class) + _name, member_ref = ref.target.member_by_type(values.class) shape(member_ref, values.value, errors, context) elsif values.is_a?(Hash) values.each_pair do |name, value| @@ -160,7 +160,7 @@ def union(ref, values, errors, context) end def valid_union?(ref, values, errors, context) - return true if values.is_a?(ref.shape.type) + return true if values.is_a?(ref.target.type) unless values.is_a?(Hash) errors << expected_got(context, 'a Hash', values) @@ -168,14 +168,14 @@ def valid_union?(ref, values, errors, context) end return true if values.size <= 1 - union_members = ref.shape.members.keys.join(', ') + union_members = ref.target.members.keys.join(', ') error = "expected #{context} to be a Hash with one of #{union_members}, got #{values.size} keys instead." errors << error false end def validate_required_members(ref, values, errors, context) - ref.shape.members.each do |name, member_ref| + ref.target.members.each do |name, member_ref| traits = member_ref.traits next unless traits.key?('smithy.api#required') && !traits.key?('smithy.api#clientOptional') @@ -187,7 +187,7 @@ def validate_required_members(ref, values, errors, context) end def streaming_input?(ref) - ref.shape.traits.key?('smithy.api#streaming') + ref.target.traits.key?('smithy.api#streaming') end def io_like?(value, require_size: false) diff --git a/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb b/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb index 0e174bd3e..769cae103 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb @@ -51,7 +51,7 @@ def apply_host_prefix(context, host_prefix) def label_value(input, label, params) name = nil - input.shape.members.each do |member_name, member_ref| + input.target.members.each do |member_name, member_ref| next unless member_ref.traits.key?('smithy.api#hostLabel') next unless member_ref.location_name == label diff --git a/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb b/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb index 88505e12e..bd57b084b 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb @@ -21,7 +21,7 @@ def call(context) private def apply_idempotency_token(input, params) - input.shape.members.each do |member_name, member_ref| + input.target.members.each do |member_name, member_ref| next unless member_ref.traits.key?('smithy.api#idempotencyToken') params[member_name] ||= SecureRandom.uuid diff --git a/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb b/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb index 953f3d57f..44ff7e27a 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb @@ -92,9 +92,9 @@ def request_encoding_selection(context) end def streaming?(input) - input.shape.members.any? do |_, member_ref| - member_ref.shape.traits.key?('smithy.api#streaming') && - !member_ref.shape.traits.key?('smithy.api#requiresLength') + input.target.members.any? do |_, member_ref| + member_ref.target.traits.key?('smithy.api#streaming') && + !member_ref.target.traits.key?('smithy.api#requiresLength') end end diff --git a/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb b/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb index 13fef8c0e..823bcdca8 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb @@ -13,7 +13,7 @@ class Handler < Client::Handler def call(context) payload_ref = streaming_member_ref(context) # Proceed with TE header logic IFF there's a streaming payload. - apply_transfer_encoding(context, payload_ref.shape) if payload_ref + apply_transfer_encoding(context, payload_ref.target) if payload_ref @handler.call(context) end @@ -29,8 +29,8 @@ def apply_transfer_encoding(context, payload) end def streaming_member_ref(context) - context.operation.input.shape.members.detect do |_, ref| - ref.shape.traits.key?('smithy.api#streaming') + context.operation.input.target.members.detect do |_, ref| + ref.target.traits.key?('smithy.api#streaming') end&.last end diff --git a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb index c693784bb..1da335e68 100644 --- a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb +++ b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb @@ -48,9 +48,9 @@ def extract_error(body, context) def parse_error_data(context, body, code) data = Schema::EmptyStructure.new context.operation.errors.each do |ref| - next unless ref.shape.name == code + next unless ref.target.name == code - data = Cbor::Parser.new.parse(ref, body, ref.shape.type.new) + data = Cbor::Parser.new.parse(ref, body, ref.target.type.new) end data end diff --git a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb index cf5a58065..8f0f1a49c 100644 --- a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb +++ b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb @@ -36,7 +36,7 @@ def apply_content_type_header(context) content_type = if event_stream?(input) 'application/vnd.amazon.eventstream' - elsif input.shape != Schema::Shapes::Prelude::Unit + elsif input.target != Schema::Shapes::Prelude::Unit 'application/cbor' end @@ -65,8 +65,8 @@ def apply_url_path(context) end def event_stream?(ref) - ref.shape.members.each_value do |member_ref| - shape = member_ref.shape + ref.target.members.each_value do |member_ref| + shape = member_ref.target return true if shape.traits.key?('smithy.api#streaming') && shape.is_a?(Schema::Shapes::UnionShape) end false diff --git a/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb b/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb index 402ac33c5..2ea15052c 100644 --- a/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb +++ b/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb @@ -19,7 +19,7 @@ def apply(data, stub) private def shape(ref, value, stub = nil) - case ref.shape + case ref.target when StructureShape then structure(ref, value, stub) when ListShape then list(ref, value) when MapShape then map(ref, value) @@ -30,7 +30,7 @@ def shape(ref, value, stub = nil) def list(ref, value) return if value.nil? - shape = ref.shape + shape = ref.target value.each_with_object([]) do |v, list| list << shape(shape.member, v) end @@ -39,7 +39,7 @@ def list(ref, value) def map(ref, value) return if value.nil? - shape = ref.shape + shape = ref.target value.each_with_object({}) do |(k, v), map| map[k.to_s] = shape(shape.value, v) end @@ -48,8 +48,8 @@ def map(ref, value) def structure(ref, data, stub) return if data.nil? - stub = ref.shape.type.new if stub.nil? - shape = ref.shape + stub = ref.target.type.new if stub.nil? + shape = ref.target data.each_pair do |key, value| stub[key] = shape(shape.member(key), value) end diff --git a/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb b/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb index ef18755f5..ed1de27d0 100644 --- a/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb +++ b/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb @@ -22,7 +22,7 @@ def stub private def shape(ref, visited) - shape = ref.shape + shape = ref.target return nil if visited.include?(shape) visited += [shape] @@ -37,14 +37,14 @@ def shape(ref, visited) end def structure(ref, visited) - shape = ref.shape + shape = ref.target shape.members.each_with_object(shape.type.new) do |(member_name, member_ref), struct| struct[member_name] = shape(member_ref, visited) end end def union(ref, visited) - shape = ref.shape + shape = ref.target member_name, member_ref = shape.members.first return unless member_name @@ -54,7 +54,7 @@ def union(ref, visited) end def scalar(ref) - case ref.shape + case ref.target when BigDecimalShape then BigDecimal(0) when BlobShape, EnumShape, StringShape then ref.location_name when BooleanShape then false diff --git a/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb b/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb index e7892b72e..c18d2b3c3 100644 --- a/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb +++ b/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb @@ -35,7 +35,7 @@ module Client 'target' => 'smithy.ruby.tests#SensitiveStructure' } - sensitive_structure = input.shape.member(:sensitive_structure).shape.type + sensitive_structure = input.target.member(:sensitive_structure).target.type filtered = subject.filter(input, { sensitive_structure: sensitive_structure.new(string: 'sensitive') }) expect(filtered).to eq(sensitive_structure: '[FILTERED]') end @@ -120,7 +120,7 @@ module Client it 'filters sensitive unions as a type' do shapes['smithy.ruby.tests#Union']['traits'] = { 'smithy.api#sensitive' => {} } - union = input.shape.member(:union).shape.member_type(:string) + union = input.target.member(:union).target.member_type(:string) filtered = subject.filter(input, { union: union.new(string: 'sensitive') }) expect(filtered).to eq(union: '[FILTERED]') end diff --git a/gems/smithy-client/spec/smithy-client/param_converter_spec.rb b/gems/smithy-client/spec/smithy-client/param_converter_spec.rb index 1f525e1e8..87d7dc9f8 100644 --- a/gems/smithy-client/spec/smithy-client/param_converter_spec.rb +++ b/gems/smithy-client/spec/smithy-client/param_converter_spec.rb @@ -49,8 +49,8 @@ module Client end it 'performs a deeply nested conversion of values when using types' do - structure_type = input.shape.type - union_type = input.shape.member(:union).shape.member_type(:structure) + structure_type = input.target.type + union_type = input.target.member(:union).target.member_type(:structure) params = structure_type.new( structure: structure_type.new(boolean: 'true'), map: 'not a map', diff --git a/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb index 215f660d8..664420d2b 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb @@ -25,8 +25,8 @@ module Plugins let(:streaming_body_plugin) do handler_class = Class.new(Client::Handler) do def call(context) - context.operation.input.shape.members.each do |name, ref| - if ref.shape.traits.key?('smithy.api#streaming') && context.params[name.to_sym] + context.operation.input.target.members.each do |name, ref| + if ref.target.traits.key?('smithy.api#streaming') && context.params[name.to_sym] context.http_request.body = context.params[name.to_sym] break end diff --git a/gems/smithy-json/lib/smithy-json/builder.rb b/gems/smithy-json/lib/smithy-json/builder.rb index c55cf456d..1d7b846c9 100644 --- a/gems/smithy-json/lib/smithy-json/builder.rb +++ b/gems/smithy-json/lib/smithy-json/builder.rb @@ -13,14 +13,14 @@ def initialize(options = {}) end def build(shape, data) - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) Smithy::Json.dump(shape(ref, data)) end private def shape(ref, value) # rubocop:disable Metrics/CyclomaticComplexity - case ref.shape + case ref.target when BlobShape then blob(value) when FloatShape then float(value) when ListShape then list(ref, value) @@ -51,7 +51,7 @@ def float(value) def list(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.collect do |value| shape(shape.member, value) end @@ -60,7 +60,7 @@ def list(ref, values) def map(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.each.with_object({}) do |(key, value), data| data[key] = shape(shape.value, value) end @@ -69,7 +69,7 @@ def map(ref, values) def structure(ref, values) return if values.nil? - ref.shape.members.each_with_object({}) do |(member_name, member_ref), data| + ref.target.members.each_with_object({}) do |(member_name, member_ref), data| value = values[member_name] data[location_name(member_ref)] = shape(member_ref, value) unless value.nil? end @@ -77,7 +77,7 @@ def structure(ref, values) def timestamp(ref, value) trait = 'smithy.api#timestampFormat' - case ref.traits[trait] || ref.shape.traits[trait] + case ref.traits[trait] || ref.target.traits[trait] when 'date-time' then value.utc.iso8601 when 'http-date' then value.utc.httpdate else @@ -91,12 +91,12 @@ def union(ref, values) # rubocop:disable Metrics/AbcSize data = {} if values.is_a?(Schema::Union) - _name, member_ref = ref.shape.member_by_type(values.class) + _name, member_ref = ref.target.member_by_type(values.class) data[location_name(member_ref)] = shape(member_ref, values.value) else key, value = values.first - if ref.shape.member?(key) - member_ref = ref.shape.member(key) + if ref.target.member?(key) + member_ref = ref.target.member(key) data[location_name(member_ref)] = shape(member_ref, value) end end diff --git a/gems/smithy-json/lib/smithy-json/codec.rb b/gems/smithy-json/lib/smithy-json/codec.rb index 82e8abd25..c808dfc4a 100644 --- a/gems/smithy-json/lib/smithy-json/codec.rb +++ b/gems/smithy-json/lib/smithy-json/codec.rb @@ -9,14 +9,14 @@ def initialize(options = {}) @options = options end - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [Object] data # @return [String, nil] def build(shape, data) Builder.new(@options).build(shape, data) end - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [String] bytes # @param [Object, nil] target (nil) # @return [Object, nil] diff --git a/gems/smithy-json/lib/smithy-json/parser.rb b/gems/smithy-json/lib/smithy-json/parser.rb index e21c05c6a..a99e8d0b4 100644 --- a/gems/smithy-json/lib/smithy-json/parser.rb +++ b/gems/smithy-json/lib/smithy-json/parser.rb @@ -15,14 +15,14 @@ def initialize(options = {}) def parse(shape, bytes, target = nil) return {} if bytes.empty? - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) shape(ref, Smithy::Json.load(bytes), target) end private def shape(ref, value, target = nil) # rubocop:disable Metrics/CyclomaticComplexity - case ref.shape + case ref.target when BlobShape then Base64.decode64(value) when FloatShape then float(value) when ListShape then list(ref, value, target) @@ -48,9 +48,9 @@ def list(ref, values, target = nil) target = [] if target.nil? values.each do |value| - next if value.nil? && !sparse?(ref.shape) + next if value.nil? && !sparse?(ref.target) - target << shape(ref.shape.member, value) + target << shape(ref.target.member, value) end target end @@ -58,9 +58,9 @@ def list(ref, values, target = nil) def map(ref, values, target = nil) target = {} if target.nil? values.each do |key, value| - next if value.nil? && !sparse?(ref.shape) + next if value.nil? && !sparse?(ref.target) - target[key] = shape(ref.shape.value, value) + target[key] = shape(ref.target.value, value) end target end @@ -68,8 +68,8 @@ def map(ref, values, target = nil) def structure(ref, values, target = nil) return if values.nil? - target = ref.shape.type.new if target.nil? - ref.shape.members.each do |member_name, member_ref| + target = ref.target.type.new if target.nil? + ref.target.members.each do |member_name, member_ref| value = values[location_name(member_ref)] target[member_name] = shape(member_ref, value) unless value.nil? end @@ -90,17 +90,17 @@ def timestamp(value) end def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize - ref.shape.members.each do |member_name, member_ref| + ref.target.members.each do |member_name, member_ref| value = values[location_name(member_ref)] next if value.nil? - target = ref.shape.member_type(member_name) if target.nil? + target = ref.target.member_type(member_name) if target.nil? return target.new(member_name => shape(member_ref, value)) end values.delete('__type') key, value = values.first - ref.shape.member_type(:unknown).new(unknown: { key => value }) + ref.target.member_type(:unknown).new(unknown: { key => value }) end def location_name(ref) diff --git a/gems/smithy-json/sig/smithy-json/codec.rbs b/gems/smithy-json/sig/smithy-json/codec.rbs index 0c5b60994..5d55bff0f 100644 --- a/gems/smithy-json/sig/smithy-json/codec.rbs +++ b/gems/smithy-json/sig/smithy-json/codec.rbs @@ -2,8 +2,8 @@ module Smithy module Json class Codec def initialize: (?Hash[Symbol, untyped] options) -> void - def build: (Schema::Shapes::Shape | Schema::Shapes::ShapeRef shape, Object data) -> (nil | String) - def parse: (Schema::Shapes::Shape | Schema::Shapes::ShapeRef shape, String bytes, ?Object ?target) -> Object? + def build: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, Object data) -> (nil | String) + def parse: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, String bytes, ?Object ?target) -> Object? end end end \ No newline at end of file diff --git a/gems/smithy-json/spec/smithy-json/builder_spec.rb b/gems/smithy-json/spec/smithy-json/builder_spec.rb index 821a656c1..08f286eb3 100644 --- a/gems/smithy-json/spec/smithy-json/builder_spec.rb +++ b/gems/smithy-json/spec/smithy-json/builder_spec.rb @@ -90,7 +90,7 @@ module Json context 'unions' do it 'builds unions as a type' do - union = structure_shape.member(:union).shape.member_type(:string).new(string: 'string') + union = structure_shape.member(:union).target.member_type(:string).new(string: 'string') type = structure_shape.type.new(union: union) bytes = subject.build(structure_shape, type) expect(Json.load(bytes)).to eq({ 'union' => { 'string' => 'string' } }) @@ -103,7 +103,7 @@ module Json end it 'builds union unit members as a type' do - union = structure_shape.member(:union).shape.member_type(:unit).new(unit: Schema::EmptyStructure.new) + union = structure_shape.member(:union).target.member_type(:unit).new(unit: Schema::EmptyStructure.new) type = structure_shape.type.new(union: union) bytes = subject.build(structure_shape, type) expect(Json.load(bytes)).to eq('union' => { 'unit' => {} }) diff --git a/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb b/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb index 7104a1f34..d4b5635fd 100644 --- a/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb +++ b/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb @@ -13,14 +13,14 @@ def initialize(options = {}) end def deserialize(data, shape, target) - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) shape(ref, data, target) end private def shape(ref, value, target = nil) # rubocop:disable Metrics/CyclomaticComplexity - case ref.shape + case ref.target when BlobShape then Base64.strict_decode64(value) when DocumentShape then document(value) when FloatShape then float(value) @@ -39,7 +39,7 @@ def document(values) msg = 'invalid document - document discriminator not found in type registry' raise ArgumentError, msg unless @type_registry.key?(values['__type']) - shape(ShapeRef.new(shape: @type_registry[values['__type']]), values) + shape(MemberShape.new(target: @type_registry[values['__type']]), values) end def float(value) @@ -57,7 +57,7 @@ def list(ref, values, target = nil) target = [] if target.nil? values.each do |value| - target << shape(ref.shape.member, value) unless value.nil? + target << shape(ref.target.member, value) unless value.nil? end target end @@ -67,7 +67,7 @@ def map(ref, values, target = nil) target = {} if target.nil? values.each do |key, value| - target[key] = shape(ref.shape.value, value) unless value.nil? + target[key] = shape(ref.target.value, value) unless value.nil? end target end @@ -75,8 +75,8 @@ def map(ref, values, target = nil) def structure(ref, values, target = nil) return if values.nil? - target = ref.shape.type.new if target.nil? - ref.shape.members.each do |member_name, member_ref| + target = ref.target.type.new if target.nil? + ref.target.members.each do |member_name, member_ref| value = values[location_name(member_ref)] target[member_name] = shape(member_ref, value) unless value.nil? end @@ -101,17 +101,17 @@ def timestamp(value) end def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize - ref.shape.members.each do |member_name, member_ref| + ref.target.members.each do |member_name, member_ref| value = values[location_name(member_ref)] next if value.nil? - target = ref.shape.member_type(member_name) if target.nil? + target = ref.target.member_type(member_name) if target.nil? return target.new(member_name => shape(member_ref, value)) end values.delete('__type') key, value = values.first - ref.shape.member_type(:unknown).new(key, value) + ref.target.member_type(:unknown).new(key, value) end def location_name(ref) diff --git a/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb b/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb index 3f98dfe21..7be3e0edf 100644 --- a/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb +++ b/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb @@ -19,7 +19,7 @@ def initialize(options = {}) end def format_document_data(shape, data) - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) document_data = shape(ref, data) document_data['__type'] = shape.id document_data @@ -42,7 +42,7 @@ def serialize_untyped(values) private def shape(ref, values) # rubocop:disable Metrics/CyclomaticComplexity - case ref.shape + case ref.target when BlobShape then blob(values) when DocumentShape then document(values) when FloatShape then float(values) @@ -92,7 +92,7 @@ def float(value) def list(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.collect do |value| shape(shape.member, value) end @@ -101,7 +101,7 @@ def list(ref, values) def map(ref, values) return if values.nil? - shape = ref.shape + shape = ref.target values.each.with_object({}) do |(key, value), data| data[key.to_s] = shape(shape.value, value) end @@ -110,7 +110,7 @@ def map(ref, values) def structure(ref, values) return if values.nil? - ref.shape.members.each_with_object({}) do |(member_name, member_ref), data| + ref.target.members.each_with_object({}) do |(member_name, member_ref), data| value = resolve_value(member_name, member_ref, values.to_h) data[location_name(member_ref)] = shape(member_ref, value) unless value.nil? end @@ -121,7 +121,7 @@ def timestamp(ref, value) return value.to_i unless @timestamp_format trait = 'smithy.api#timestampFormat' - case ref.traits[trait] || ref.shape.traits[trait] + case ref.traits[trait] || ref.target.traits[trait] when 'date-time' then value.utc.iso8601 when 'http-date' then value.utc.httpdate else @@ -135,7 +135,7 @@ def union(ref, values) data = {} if values.is_a?(Union) - _name, member_ref = ref.shape.member_by_type(values.class) + _name, member_ref = ref.target.member_by_type(values.class) data[location_name(member_ref)] = shape(member_ref, values) else key, value = values.first @@ -161,9 +161,9 @@ def normalize_timestamp_value(value) end def resolve_member_ref(ref, name) - return ref.shape.member(name) if ref.shape.member?(name) + return ref.target.member(name) if ref.target.member?(name) - ref.shape.members.values.find do |member_ref| + ref.target.members.values.find do |member_ref| member_ref.traits['smithy.api#jsonName'] == name || member_ref.location_name == name end end diff --git a/gems/smithy-schema/lib/smithy-schema/shapes.rb b/gems/smithy-schema/lib/smithy-schema/shapes.rb index caa8e94ba..d78c517dc 100644 --- a/gems/smithy-schema/lib/smithy-schema/shapes.rb +++ b/gems/smithy-schema/lib/smithy-schema/shapes.rb @@ -35,16 +35,16 @@ def []=(key, value) end # A reference to a shape. - class ShapeRef + class MemberShape def initialize(options = {}) - @shape = options[:shape] + @target = options[:target] @location_name = options[:location_name] @traits = options[:traits] || {} @metadata = {} end # @return [Shape] - attr_accessor :shape + attr_accessor :target # @return [String, nil] attr_accessor :location_name @@ -123,13 +123,13 @@ def initialize(options = {}) # @return [String] attr_accessor :name - # @return [ShapeRef] + # @return [MemberShape] attr_accessor :input - # @return [ShapeRef] + # @return [MemberShape] attr_accessor :output - # @return [Array] + # @return [Array] attr_accessor :errors end @@ -152,10 +152,10 @@ def initialize(options = {}) @members = {} end - # @return [Hash] + # @return [Hash] attr_accessor :members - # @return [ShapeRef] + # @return [MemberShape] def add_member(name, shape_ref) @members[name] = shape_ref end @@ -167,7 +167,7 @@ def member?(name) end # @param [Symbol] name - # @return [ShapeRef, nil] + # @return [MemberShape, nil] def member(name) @members[name] end @@ -186,10 +186,10 @@ def initialize(options = {}) @members = {} end - # @return [Hash] + # @return [Hash] attr_accessor :members - # @return [ShapeRef] + # @return [MemberShape] def add_member(name, shape_ref) @members[name] = shape_ref end @@ -201,7 +201,7 @@ def member?(name) end # @param [Symbol] name - # @return [ShapeRef, nil] + # @return [MemberShape, nil] def member(name) @members[name] end @@ -209,16 +209,16 @@ def member(name) # Represents a List shape. class ListShape < Shape - # @return [ShapeRef] + # @return [MemberShape] attr_accessor :member end # Represents a Map shape. class MapShape < Shape - # @return [ShapeRef] + # @return [MemberShape] attr_accessor :key - # @return [ShapeRef] + # @return [MemberShape] attr_accessor :value end @@ -232,13 +232,13 @@ def initialize(options = {}) @members = {} end - # @return [Hash] + # @return [Hash] attr_accessor :members # @return [Class] attr_accessor :type - # @return [ShapeRef] + # @return [MemberShape] def add_member(name, shape_ref) @members[name] = shape_ref end @@ -250,7 +250,7 @@ def member?(name) end # @param [Symbol] name - # @return [ShapeRef, nil] + # @return [MemberShape, nil] def member(name) @members[name] end @@ -268,19 +268,19 @@ def initialize(options = {}) @members_by_type = {} end - # @return [Hash] + # @return [Hash] attr_accessor :members # @return [Hash] attr_accessor :member_types - # @return [Hash] + # @return [Hash] attr_accessor :members_by_type # @return [Class] attr_accessor :type - # @return [ShapeRef] + # @return [MemberShape] def add_member(name, type, shape_ref) @member_types[name] = type @members_by_type[type] = [name, shape_ref] @@ -294,7 +294,7 @@ def member?(name) end # @param [Symbol] name - # @return [ShapeRef, nil] + # @return [MemberShape, nil] def member(name) @members[name] end @@ -318,7 +318,7 @@ def member_by_type?(type) end # @param [Class] type - # @return [ShapeRef, nil] + # @return [MemberShape, nil] def member_by_type(type) @members_by_type[type] end diff --git a/gems/smithy-schema/sig/smithy-schema/shapes.rbs b/gems/smithy-schema/sig/smithy-schema/shapes.rbs index b21661af6..d1fe31fc9 100644 --- a/gems/smithy-schema/sig/smithy-schema/shapes.rbs +++ b/gems/smithy-schema/sig/smithy-schema/shapes.rbs @@ -11,10 +11,10 @@ module Smithy def []=: (Symbol, Object) -> void end - class ShapeRef + class MemberShape def initialize: (?Hash[Symbol, untyped]) -> void - attr_accessor shape: Shape + attr_accessor target: Shape attr_accessor location_name: String? attr_accessor traits: Hash[String, untyped] def []: (Symbol) -> Object @@ -33,9 +33,9 @@ module Smithy class OperationShape < Shape attr_accessor name: String - attr_accessor input: ShapeRef - attr_accessor output: ShapeRef - attr_accessor errors: Array[ShapeRef] + attr_accessor input: MemberShape + attr_accessor output: MemberShape + attr_accessor errors: Array[MemberShape] end class BigDecimalShape < Shape @@ -51,60 +51,60 @@ module Smithy end class EnumShape < Shape - attr_accessor members: Hash[Symbol, ShapeRef] - def add_member: (Symbol, ShapeRef) -> ShapeRef + attr_accessor members: Hash[Symbol, MemberShape] + def add_member: (Symbol, MemberShape) -> MemberShape def member?: (Symbol?) -> bool - def member: (Symbol) -> ShapeRef? + def member: (Symbol) -> MemberShape? end class IntegerShape < Shape end class IntEnumShape < Shape - attr_accessor members: Hash[Symbol, ShapeRef] - def add_member: (Symbol, ShapeRef) -> ShapeRef + attr_accessor members: Hash[Symbol, MemberShape] + def add_member: (Symbol, MemberShape) -> MemberShape def member?: (Symbol?) -> bool - def member: (Symbol) -> ShapeRef? + def member: (Symbol) -> MemberShape? end class FloatShape < Shape end class ListShape < Shape - attr_accessor member: ShapeRef + attr_accessor member: MemberShape end class MapShape < Shape - attr_accessor key: ShapeRef - attr_accessor value: ShapeRef + attr_accessor key: MemberShape + attr_accessor value: MemberShape end class StringShape < Shape end class StructureShape < Shape - attr_accessor members: Hash[Symbol, ShapeRef] + attr_accessor members: Hash[Symbol, MemberShape] attr_accessor type: Class | Struct[untyped] - def add_member: (Symbol, ShapeRef) -> ShapeRef + def add_member: (Symbol, MemberShape) -> MemberShape def member?: (Symbol?) -> bool - def member: (Symbol) -> ShapeRef? + def member: (Symbol) -> MemberShape? end class TimestampShape < Shape end class UnionShape < Shape - attr_accessor members: Hash[Symbol, ShapeRef] + attr_accessor members: Hash[Symbol, MemberShape] attr_accessor member_types: Hash[Symbol, Class] - attr_accessor members_by_type: Hash[Class, [Symbol, ShapeRef]] + attr_accessor members_by_type: Hash[Class, [Symbol, MemberShape]] attr_accessor type: Class | Struct[untyped] - def add_member: (Symbol, Class, ShapeRef) -> ShapeRef + def add_member: (Symbol, Class, MemberShape) -> MemberShape def member?: (Symbol?) -> bool - def member: (Symbol) -> ShapeRef? + def member: (Symbol) -> MemberShape? def member_type?: (Symbol) -> bool def member_type: (Symbol) -> Class? def member_by_type?: (Class) -> bool - def member_by_type: (Class) -> [Symbol, ShapeRef]? + def member_by_type: (Class) -> [Symbol, MemberShape]? end module Prelude diff --git a/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb b/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb index 9ac332fa2..feffeb7c3 100644 --- a/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb +++ b/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb @@ -40,17 +40,17 @@ module Shapes end end - describe ShapeRef do - subject { ShapeRef.new } + describe MemberShape do + subject { MemberShape.new } it 'defaults shape to nil' do - expect(subject.shape).to be_nil + expect(subject.target).to be_nil end it 'can reference a shape' do shape = Shape.new - subject = ShapeRef.new(shape: shape) - expect(subject.shape).to be(shape) + subject = MemberShape.new(target: shape) + expect(subject.target).to be(shape) end it 'defaults a location name to nil' do @@ -58,7 +58,7 @@ module Shapes end it 'stores a location name' do - subject = ShapeRef.new(location_name: 'foo') + subject = MemberShape.new(location_name: 'foo') expect(subject.location_name).to eq('foo') end @@ -67,7 +67,7 @@ module Shapes end it 'can get and set metadata' do - subject = ShapeRef.new + subject = MemberShape.new subject[:foo] = 'bar' expect(subject[:foo]).to eq('bar') end @@ -152,7 +152,7 @@ module Shapes describe OperationShape do subject { OperationShape.new } - let(:shape_ref) { ShapeRef.new(shape: StructureShape.new) } + let(:shape_ref) { MemberShape.new(target: StructureShape.new) } it 'is a subclass of Shape' do expect(subject).to be_kind_of(Shape) @@ -244,15 +244,15 @@ module Shapes describe '#add_member' do it 'adds a member reference' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) - expect(subject.members[:foo]).to be_kind_of(ShapeRef) + expect(subject.members[:foo]).to be_kind_of(MemberShape) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) expect(subject.member?(:foo)).to be(true) end @@ -260,9 +260,9 @@ module Shapes describe '#member' do it 'returns the member' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) - expect(subject.member(:foo)).to be_kind_of(ShapeRef) + expect(subject.member(:foo)).to be_kind_of(MemberShape) end end end @@ -288,15 +288,15 @@ module Shapes describe '#add_member' do it 'adds a member reference' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) - expect(subject.members[:foo]).to be_kind_of(ShapeRef) + expect(subject.members[:foo]).to be_kind_of(MemberShape) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) expect(subject.member?(:foo)).to be(true) end @@ -304,9 +304,9 @@ module Shapes describe '#member' do it 'returns the member' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) - expect(subject.member(:foo)).to be_kind_of(ShapeRef) + expect(subject.member(:foo)).to be_kind_of(MemberShape) end end end @@ -334,7 +334,7 @@ module Shapes describe '#member accessor' do it 'gets and sets a member' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.member = shape_ref expect(subject.member).to eq(shape_ref) end @@ -360,7 +360,7 @@ module Shapes describe '#key accessor' do it 'gets and sets a key' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.key = shape_ref expect(subject.key).to eq(shape_ref) end @@ -368,7 +368,7 @@ module Shapes describe '#value accessor' do it 'gets and sets a value' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.value = shape_ref expect(subject.value).to eq(shape_ref) end @@ -403,15 +403,15 @@ module Shapes describe '#add_member' do it 'adds a member reference' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) - expect(subject.members[:foo]).to be_kind_of(ShapeRef) + expect(subject.members[:foo]).to be_kind_of(MemberShape) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) expect(subject.member?(:foo)).to be(true) end @@ -419,9 +419,9 @@ module Shapes describe '#member' do it 'returns the member' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, shape_ref) - expect(subject.member(:foo)).to be_kind_of(ShapeRef) + expect(subject.member(:foo)).to be_kind_of(MemberShape) end end end @@ -464,7 +464,7 @@ module Shapes describe '#add_member' do it 'adds a member with its type' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) expect(subject.members[:foo]).to be(shape_ref) expect(subject.member_types[:foo]).to be(union_type) @@ -474,7 +474,7 @@ module Shapes describe '#member?' do it 'returns true if member exists' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) expect(subject.member?(:foo)).to be(true) end @@ -482,15 +482,15 @@ module Shapes describe '#member' do it 'returns the member' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) - expect(subject.member(:foo)).to be_kind_of(ShapeRef) + expect(subject.member(:foo)).to be_kind_of(MemberShape) end end describe '#member_type?' do it 'returns true if member type exists' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) expect(subject.member_type?(:foo)).to be(true) end @@ -498,7 +498,7 @@ module Shapes describe '#member_type' do it 'returns the member type' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) expect(subject.member_type(:foo)).to eq(union_type) end @@ -506,7 +506,7 @@ module Shapes describe '#member_by_type?' do it 'returns true if member by type exists' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) expect(subject.member_by_type?(union_type)).to be(true) end @@ -514,7 +514,7 @@ module Shapes describe '#member_by_type' do it 'returns the member by type' do - shape_ref = ShapeRef.new(shape: StringShape.new) + shape_ref = MemberShape.new(target: StringShape.new) subject.add_member(:foo, union_type, shape_ref) expect(subject.member_by_type(union_type)).to eq([:foo, shape_ref]) end diff --git a/gems/smithy-xml/lib/smithy-xml/builder.rb b/gems/smithy-xml/lib/smithy-xml/builder.rb index 3ef193a17..c6935ad17 100644 --- a/gems/smithy-xml/lib/smithy-xml/builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/builder.rb @@ -14,17 +14,17 @@ def initialize(options = {}) end def build(shape, data, target = nil) - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) target ||= [] @builder = DocBuilder.new(target: target, indent: @indent, pad: @pad) - structure(ref.location_name || ref.shape.traits['smithy.api#xmlName'] || ref.shape.name, ref, data) + structure(ref.location_name || ref.target.traits['smithy.api#xmlName'] || ref.target.name, ref, data) target.join end private def shape(name, ref, value) - case ref.shape + case ref.target when BlobShape then node(name, ref, blob(value)) when ListShape then list(name, ref, value) when MapShape then map(name, ref, value) @@ -40,7 +40,7 @@ def blob(value) end def list(name, ref, values) - member_ref = ref.shape.member + member_ref = ref.target.member if flat?(ref) values.each do |value| shape(name, member_ref, value) @@ -48,15 +48,15 @@ def list(name, ref, values) else node(name, ref) do values.each do |value| - shape(location_name(member_ref, 'member'), ref.shape.member, value) + shape(location_name(member_ref, 'member'), ref.target.member, value) end end end end def map(name, ref, values) # rubocop:disable Metrics/AbcSize - key_ref = ref.shape.key - value_ref = ref.shape.value + key_ref = ref.target.key + value_ref = ref.target.value if flat?(ref) values.each do |key, value| node(name, ref) do @@ -67,7 +67,7 @@ def map(name, ref, values) # rubocop:disable Metrics/AbcSize else node(name, ref) do values.each do |key, value| - node('entry', ShapeRef.new(shape: MapShape.new)) do + node('entry', MemberShape.new(target: MapShape.new)) do shape(location_name(key_ref, 'key'), key_ref, key) shape(location_name(value_ref, 'value'), value_ref, value) end @@ -80,7 +80,7 @@ def structure(name, ref, values) return node(name, ref) if values.empty? node(name, ref, structure_attrs(ref, values)) do - ref.shape.members.each do |member_name, member_ref| + ref.target.members.each do |member_name, member_ref| next if values[member_name].nil? next if xml_attribute?(member_ref) @@ -90,7 +90,7 @@ def structure(name, ref, values) end def structure_attrs(ref, values) - ref.shape.members.each_with_object({}) do |(member_name, member_ref), attrs| + ref.target.members.each_with_object({}) do |(member_name, member_ref), attrs| if xml_attribute?(member_ref) && values.key?(member_name) attrs[location_name(member_ref, member_ref.location_name)] = values[member_name] end @@ -99,7 +99,7 @@ def structure_attrs(ref, values) def timestamp(ref, value) trait = 'smithy.api#timestampFormat' - case ref.traits[trait] || ref.shape.traits[trait] + case ref.traits[trait] || ref.target.traits[trait] when 'epoch-seconds' then value.to_i.to_s when 'http-date' then value.utc.httpdate else @@ -113,12 +113,12 @@ def union(name, ref, values) # rubocop:disable Metrics/AbcSize node(name, ref, structure_attrs(ref, values)) do if values.is_a?(Schema::Union) - _name, member_ref = ref.shape.member_by_type(values.class) + _name, member_ref = ref.target.member_by_type(values.class) shape(location_name(member_ref, member_ref.location_name), member_ref, values.value) else key, value = values.first - if ref.shape.member?(key) - member_ref = ref.shape.member(key) + if ref.target.member?(key) + member_ref = ref.target.member(key) shape(location_name(member_ref, member_ref.location_name), member_ref, value) end end @@ -156,7 +156,7 @@ def node(name, ref, *args, &) def shape_attrs(ref) trait = 'smithy.api#xmlNamespace' - xmlns = ref.traits[trait] || ref.shape.traits[trait] + xmlns = ref.traits[trait] || ref.target.traits[trait] return {} unless xmlns if (prefix = xmlns['prefix']) diff --git a/gems/smithy-xml/lib/smithy-xml/codec.rb b/gems/smithy-xml/lib/smithy-xml/codec.rb index 821199ba7..aede627ed 100644 --- a/gems/smithy-xml/lib/smithy-xml/codec.rb +++ b/gems/smithy-xml/lib/smithy-xml/codec.rb @@ -9,7 +9,7 @@ def initialize(options = {}) @options = options end - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [Object] data # @param [String, nil] target (nil) # @return [String, nil] @@ -17,7 +17,7 @@ def build(shape, data, target = nil) Builder.new(@options).build(shape, data, target) end - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [String] bytes # @param [Object, nil] target (nil) # @return [Object, nil] diff --git a/gems/smithy-xml/lib/smithy-xml/parser.rb b/gems/smithy-xml/lib/smithy-xml/parser.rb index 9f54726a4..a48ddbc8f 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser.rb @@ -22,12 +22,12 @@ def initialize(options = {}) # The purpose of the unhandled callback block is to allow callers to access values # such as a request ID that are part of the XML body but not part of modeling. # - # @param [ShapeRef, Shape] shape + # @param [MemberShape, Shape] shape # @param [String] bytes # @param [Object, nil] target (nil) # @return [Object] def parse(shape, bytes, target = nil, &) - ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape) + ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) bytes = '' if bytes.nil? || bytes.empty? stack = Stack.new(ref, target, &) @engine.new(stack).parse(bytes.to_s) diff --git a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb index 161464e49..da8d4dd18 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb @@ -25,7 +25,7 @@ def new(path, parent, ref, result = nil) private def frame_class(ref) - klass = FRAME_CLASSES[ref.shape.class] + klass = FRAME_CLASSES[ref.target.class] if klass == ListFrame && ref.traits.key?('smithy.api#xmlFlattened') FlatListFrame elsif klass == MapFrame && ref.traits.key?('smithy.api#xmlFlattened') @@ -103,7 +103,7 @@ def result class FlatListFrame < Frame def initialize(xml_name, *args) super - @member = Frame.new(xml_name, self, @ref.shape.member) + @member = Frame.new(xml_name, self, @ref.target.member) end def result @@ -147,7 +147,7 @@ class ListFrame < Frame def initialize(*args) super @result = [] - @member_xml_name = @ref.shape.member.traits['smithy.api#xmlName'] || 'member' + @member_xml_name = @ref.target.member.traits['smithy.api#xmlName'] || 'member' end def child_frame(xml_name) @@ -155,7 +155,7 @@ def child_frame(xml_name) raise NotImplementedError, "Expected XML name '#{@member_xml_name}' for ListFrame, got '#{xml_name}'" end - Frame.new(xml_name, self, @ref.shape.member) + Frame.new(xml_name, self, @ref.target.member) end def consume_child_frame(child) @@ -167,10 +167,10 @@ def consume_child_frame(child) class MapEntryFrame < Frame def initialize(xml_name, *args) super - @key_name = @ref.shape.key.traits['smithy.api#xmlName'] || 'key' - @key = Frame.new(xml_name, self, @ref.shape.key) - @value_name = @ref.shape.value.traits['smithy.api#xmlName'] || 'value' - @value = Frame.new(xml_name, self, @ref.shape.value) + @key_name = @ref.target.key.traits['smithy.api#xmlName'] || 'key' + @key = Frame.new(xml_name, self, @ref.target.key) + @value_name = @ref.target.value.traits['smithy.api#xmlName'] || 'value' + @value = Frame.new(xml_name, self, @ref.target.value) end # @return [StringFrame] @@ -234,16 +234,16 @@ class StructureFrame < Frame def initialize(xml_name, parent, ref, result = nil) super @members = {} - ref.shape.members.each do |member_name, member_ref| + ref.target.members.each do |member_name, member_ref| @members[xml_name(member_ref)] = { name: member_name, ref: member_ref } end - @result ||= ref.shape.type.new + @result ||= ref.target.type.new end def child_frame(xml_name) if (@member = @members[xml_name]) Frame.new(xml_name, self, @member[:ref]) - elsif @ref.shape.is_a?(UnionShape) + elsif @ref.target.is_a?(UnionShape) UnknownMemberFrame.new(xml_name, self, nil, @result) else NullFrame.new(xml_name, self) diff --git a/gems/smithy-xml/sig/smithy-xml/codec.rbs b/gems/smithy-xml/sig/smithy-xml/codec.rbs index 43bbbff0b..5768e40d6 100644 --- a/gems/smithy-xml/sig/smithy-xml/codec.rbs +++ b/gems/smithy-xml/sig/smithy-xml/codec.rbs @@ -1,8 +1,8 @@ module Smithy module Xml class Codec - def build: (Schema::Shapes::Shape | Schema::Shapes::ShapeRef shape, Object data) -> (nil | String) - def parse: (Schema::Shapes::Shape | Schema::Shapes::ShapeRef shape, String bytes, ?Object ?target) -> Object? + def build: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, Object data) -> (nil | String) + def parse: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, String bytes, ?Object ?target) -> Object? end end end \ No newline at end of file diff --git a/gems/smithy-xml/spec/smithy-xml/builder_spec.rb b/gems/smithy-xml/spec/smithy-xml/builder_spec.rb index ff78c8bdd..bcbec1641 100644 --- a/gems/smithy-xml/spec/smithy-xml/builder_spec.rb +++ b/gems/smithy-xml/spec/smithy-xml/builder_spec.rb @@ -16,7 +16,7 @@ def inline(xml) end it 'returns an empty frame when given a unit shape' do - ref = Schema::Shapes::ShapeRef.new(shape: Schema::Shapes::Prelude::Unit) + ref = Schema::Shapes::MemberShape.new(target: Schema::Shapes::Prelude::Unit) expect(subject.build(ref, '')).to eq('') end @@ -166,7 +166,7 @@ def inline(xml) context 'unions' do it 'builds unions as a type' do - union = structure_shape.member(:union).shape.member_type(:string).new(string: 'string') + union = structure_shape.member(:union).target.member_type(:string).new(string: 'string') type = structure_shape.type.new(union: union) bytes = subject.build(structure_shape, type) expect(bytes).to include('string') @@ -179,7 +179,7 @@ def inline(xml) end it 'builds union unit members as a type' do - union = structure_shape.member(:union).shape.member_type(:unit).new(unit: Schema::EmptyStructure.new) + union = structure_shape.member(:union).target.member_type(:unit).new(unit: Schema::EmptyStructure.new) type = structure_shape.type.new(union: union) bytes = subject.build(structure_shape, type) expect(bytes).to include('') diff --git a/gems/smithy/lib/smithy/templates/client/errors_rbs.erb b/gems/smithy/lib/smithy/templates/client/errors_rbs.erb index 002ea6564..fa54effba 100644 --- a/gems/smithy/lib/smithy/templates/client/errors_rbs.erb +++ b/gems/smithy/lib/smithy/templates/client/errors_rbs.erb @@ -3,7 +3,7 @@ module <%= module_name %> <% errors.each do |error| -%> class <%= error.name %> < Smithy::Client::ServiceError <% error.members.each do |member| -%> - def <%= member.name %>: () -> <%= Model::RBS.type(model, member.shape['target'], Model.shape(model, member.shape['target'])) %>? + def <%= member.name %>: () -> <%= Model::RBS.type(model, member.target['target'], Model.shape(model, member.target['target'])) %>? <% end -%> <% if error.retryable? -%> def retryable?: () -> true diff --git a/gems/smithy/lib/smithy/templates/client/schema.erb b/gems/smithy/lib/smithy/templates/client/schema.erb index 0a3afda6c..b4f51b6a0 100644 --- a/gems/smithy/lib/smithy/templates/client/schema.erb +++ b/gems/smithy/lib/smithy/templates/client/schema.erb @@ -34,7 +34,7 @@ module <%= module_name %> <% shape.members.each do |member| -%> <%= shape.name %>.add_member(:<%= member.name %>, <%= shape.union_type(member) %>, <%= member.initializer %>) <% end -%> - <%= shape.name %>.add_member(:unknown, Types::<%= shape.name %>::Unknown, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Unit)) + <%= shape.name %>.add_member(:unknown, Types::<%= shape.name %>::Unknown, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit)) <%= shape.name %>.type = <%= shape.type_class %> <% end -%> <% end -%> diff --git a/gems/smithy/lib/smithy/views/client/schema.rb b/gems/smithy/lib/smithy/views/client/schema.rb index 6df4f9b95..36f44b20f 100644 --- a/gems/smithy/lib/smithy/views/client/schema.rb +++ b/gems/smithy/lib/smithy/views/client/schema.rb @@ -115,16 +115,16 @@ def paginator private def build_input(input) - ShapeRef.new(@service, nil, input) + MemberShape.new(@service, nil, input) end def build_output(output) - ShapeRef.new(@service, nil, output) + MemberShape.new(@service, nil, output) end def build_errors(errors) errors = Set.new(@service.fetch('errors', [])).merge(errors) - errors.map { |error| ShapeRef.new(@service, nil, error) } + errors.map { |error| MemberShape.new(@service, nil, error) } end end @@ -205,7 +205,7 @@ def http_payload private def build_shape_refs(members) - members.map { |name, member| ShapeRef.new(@service, name, member) } + members.map { |name, member| MemberShape.new(@service, name, member) } end end @@ -221,7 +221,7 @@ def initialize(service, id, shape) private def build_shape_refs(members) - members.map { |name, shape_ref| ShapeRef.new(@service, name, shape_ref) } + members.map { |name, shape_ref| MemberShape.new(@service, name, shape_ref) } end end @@ -237,7 +237,7 @@ def initialize(service, id, shape) private def build_shape_refs(members) - members.map { |name, member| ShapeRef.new(@service, name, member) } + members.map { |name, member| MemberShape.new(@service, name, member) } end end @@ -245,7 +245,7 @@ def build_shape_refs(members) class ListShape < Shape def initialize(service, id, shape) super - @member = ShapeRef.new(@service, nil, shape['member']) + @member = MemberShape.new(@service, nil, shape['member']) end attr_reader :member @@ -255,8 +255,8 @@ def initialize(service, id, shape) class MapShape < Shape def initialize(service, id, shape) super - @key = ShapeRef.new(@service, nil, shape['key']) - @value = ShapeRef.new(@service, nil, shape['value']) + @key = MemberShape.new(@service, nil, shape['key']) + @value = MemberShape.new(@service, nil, shape['value']) end attr_reader :key, :value @@ -282,12 +282,12 @@ def union_type(shape_ref) private def build_shape_refs(members) - members.map { |name, member| ShapeRef.new(@service, name, member) } + members.map { |name, member| MemberShape.new(@service, name, member) } end end # @api private - class ShapeRef + class MemberShape OMITTED_TRAITS = %w[ smithy.api#documentation ].freeze @@ -320,17 +320,17 @@ def initialize(service, location_name, shape_ref) @service = service @name = location_name.underscore if location_name @location_name = location_name - @shape = shape(shape_ref['target']) + @target = shape(shape_ref['target']) @traits = shape_ref.fetch('traits', {}).except(*OMITTED_TRAITS) end attr_reader :name, :location_name def initializer - options_str = "shape: #{@shape}" + options_str = "target: #{@target}" options_str += ", location_name: \"#{@location_name}\"" if @location_name options_str += ", traits: #{@traits}" unless @traits.empty? - "::Smithy::Schema::Shapes::ShapeRef.new(#{options_str})" + "::Smithy::Schema::Shapes::MemberShape.new(#{options_str})" end def shape(id) diff --git a/gems/smithy/spec/interfaces/rename_shapes_spec.rb b/gems/smithy/spec/interfaces/rename_shapes_spec.rb index ae32e1bb7..a52bea17c 100644 --- a/gems/smithy/spec/interfaces/rename_shapes_spec.rb +++ b/gems/smithy/spec/interfaces/rename_shapes_spec.rb @@ -37,8 +37,8 @@ it 'assigns renamed shapes to operation inputs and outputs' do client = RenameShapes::Client.new operation = client.config.service.operation(:operation) - expect(operation.input.shape.type).to eq(RenameShapes::Types::RenamedOperationInput) - expect(operation.output.shape.type).to eq(RenameShapes::Types::RenamedOperationOutput) + expect(operation.input.target.type).to eq(RenameShapes::Types::RenamedOperationInput) + expect(operation.output.target.type).to eq(RenameShapes::Types::RenamedOperationOutput) end end end diff --git a/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb b/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb index 9e7886cb1..b7de49521 100644 --- a/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb +++ b/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb @@ -37,25 +37,25 @@ it 'assigns synthetic input and output shapes to the operation' do client = SyntheticInputOutput::Client.new operation = client.config.service.operation(:operation) - expect(operation.input.shape.type).to eq(SyntheticInputOutput::Types::OperationInput) - expect(operation.output.shape.type).to eq(SyntheticInputOutput::Types::OperationOutput) + expect(operation.input.target.type).to eq(SyntheticInputOutput::Types::OperationInput) + expect(operation.output.target.type).to eq(SyntheticInputOutput::Types::OperationOutput) end it 'preserves input and output shapes on the operation with the input and output trait' do client = SyntheticInputOutput::Client.new operation = client.config.service.operation(:operation_with_input_and_output_traits) - expect(operation.input.shape.type) + expect(operation.input.target.type) .to eq(SyntheticInputOutput::Types::OperationWithInputAndOutputTraitsInput) - expect(operation.output.shape.type) + expect(operation.output.target.type) .to eq(SyntheticInputOutput::Types::OperationWithInputAndOutputTraitsOutput) end it 'handles naming conflicts by inserting Operation between the operation name and the suffix' do client = SyntheticInputOutput::Client.new operation = client.config.service.operation(:operation_with_naming_conflict) - expect(operation.input.shape.type) + expect(operation.input.target.type) .to eq(SyntheticInputOutput::Types::OperationWithNamingConflictOperationInput) - expect(operation.output.shape.type) + expect(operation.output.target.type) .to eq(SyntheticInputOutput::Types::OperationWithNamingConflictOperationOutput) end end diff --git a/gems/smithy/spec/support/examples/schema_examples.rb b/gems/smithy/spec/support/examples/schema_examples.rb index 58cbd0f9d..68e320ac4 100644 --- a/gems/smithy/spec/support/examples/schema_examples.rb +++ b/gems/smithy/spec/support/examples/schema_examples.rb @@ -190,9 +190,9 @@ def expect_generated_shape(subject, shape_class, shape_hash) it 'has members' do expect(subject.members.keys).to eq(%i[foo]) - expect(subject.members[:foo].shape).to be_a(Smithy::Schema::Shapes::StructureShape) + expect(subject.members[:foo].target).to be_a(Smithy::Schema::Shapes::StructureShape) expect(subject.members[:foo].traits).to eq(expected_member['traits']) - expect(subject.members[:foo].shape.id).to eq(expected_member['target']) + expect(subject.members[:foo].target.id).to eq(expected_member['target']) end it 'has a member with traits' do @@ -217,9 +217,9 @@ def expect_generated_shape(subject, shape_class, shape_hash) it 'has members' do expect(subject.members.keys).to eq(%i[baz]) - expect(subject.members[:baz].shape).to be_a(Smithy::Schema::Shapes::StructureShape) + expect(subject.members[:baz].target).to be_a(Smithy::Schema::Shapes::StructureShape) expect(subject.members[:baz].traits).to eq(expected_member['traits']) - expect(subject.members[:baz].shape.id).to eq(expected_member['target']) + expect(subject.members[:baz].target.id).to eq(expected_member['target']) end it 'has a member with traits' do @@ -243,8 +243,8 @@ def expect_generated_shape(subject, shape_class, shape_hash) end it 'has a member' do - expect(subject.member.shape).to be_a(Smithy::Schema::Shapes::StringShape) - expect(subject.member.shape.id).to eq(expected_member['target']) + expect(subject.member.target).to be_a(Smithy::Schema::Shapes::StringShape) + expect(subject.member.target.id).to eq(expected_member['target']) end it 'has a member with traits' do @@ -268,10 +268,10 @@ def expect_generated_shape(subject, shape_class, shape_hash) end it 'has key and value members' do - expect(subject.key.shape).to be_a(Smithy::Schema::Shapes::StringShape) - expect(subject.key.shape.id).to eq(expected_shape['key']['target']) - expect(subject.value.shape).to be_a(Smithy::Schema::Shapes::StringShape) - expect(subject.value.shape.id).to eq(expected_shape['value']['target']) + expect(subject.key.target).to be_a(Smithy::Schema::Shapes::StringShape) + expect(subject.key.target.id).to eq(expected_shape['key']['target']) + expect(subject.value.target).to be_a(Smithy::Schema::Shapes::StringShape) + expect(subject.value.target.id).to eq(expected_shape['value']['target']) end it 'has keys and values with traits' do @@ -315,12 +315,12 @@ def expect_generated_shape(subject, shape_class, shape_hash) end it 'supports unit types' do - expect(subject.member(:unit).shape).to eq(Smithy::Schema::Shapes::Prelude::Unit) + expect(subject.member(:unit).target).to eq(Smithy::Schema::Shapes::Prelude::Unit) expect(subject.member_type(:unit)).to eq(ShapeService::Types::Union::Unit) end it 'has an unknown member' do - expect(subject.member(:unknown).shape).to eq(Smithy::Schema::Shapes::Prelude::Unit) + expect(subject.member(:unknown).target).to eq(Smithy::Schema::Shapes::Prelude::Unit) expect(subject.member_type(:unknown)).to eq(ShapeService::Types::Union::Unknown) end end From c16b2c2641034d2497aadb7e64beb462848a5d4b Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Wed, 3 Jun 2026 17:20:22 -0700 Subject: [PATCH 02/23] Fix unintended rename in errors --- gems/smithy/lib/smithy/templates/client/errors_rbs.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/smithy/lib/smithy/templates/client/errors_rbs.erb b/gems/smithy/lib/smithy/templates/client/errors_rbs.erb index fa54effba..002ea6564 100644 --- a/gems/smithy/lib/smithy/templates/client/errors_rbs.erb +++ b/gems/smithy/lib/smithy/templates/client/errors_rbs.erb @@ -3,7 +3,7 @@ module <%= module_name %> <% errors.each do |error| -%> class <%= error.name %> < Smithy::Client::ServiceError <% error.members.each do |member| -%> - def <%= member.name %>: () -> <%= Model::RBS.type(model, member.target['target'], Model.shape(model, member.target['target'])) %>? + def <%= member.name %>: () -> <%= Model::RBS.type(model, member.shape['target'], Model.shape(model, member.shape['target'])) %>? <% end -%> <% if error.retryable? -%> def retryable?: () -> true From acd5268e21d5f7a6f34c1499c7ff5d5007b591da Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Wed, 3 Jun 2026 17:24:35 -0700 Subject: [PATCH 03/23] Introduce target reference --- gems/smithy-schema/lib/smithy-schema/shapes.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gems/smithy-schema/lib/smithy-schema/shapes.rb b/gems/smithy-schema/lib/smithy-schema/shapes.rb index d78c517dc..5431260f3 100644 --- a/gems/smithy-schema/lib/smithy-schema/shapes.rb +++ b/gems/smithy-schema/lib/smithy-schema/shapes.rb @@ -11,8 +11,11 @@ def initialize(options = {}) @name = options[:name] @traits = options[:traits] || {} @metadata = {} + @target = self end + attr_reader :target + # @return [String] Absolute shape ID from model attr_accessor :id From 20ed88599849c3ab61a9a24aff99e3e93ab810ed Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Wed, 3 Jun 2026 17:24:51 -0700 Subject: [PATCH 04/23] Update projections --- projections/shapes/lib/shapes/client.rb | 2 + projections/shapes/lib/shapes/schema.rb | 100 +++++++++++----------- projections/weather/lib/weather/client.rb | 2 + projections/weather/lib/weather/schema.rb | 50 +++++------ 4 files changed, 79 insertions(+), 75 deletions(-) diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 43823faab..34b0ad788 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -20,6 +20,7 @@ require 'smithy-client/plugins/retry_errors' require 'smithy-client/plugins/sign_requests' require 'smithy-client/plugins/stub_responses' +require 'smithy-client/plugins/transfer_encoding' require 'smithy-client/plugins/user_agent' module ShapeService @@ -49,6 +50,7 @@ class Client < Smithy::Client::Base add_plugin(Smithy::Client::Plugins::RetryErrors) add_plugin(Smithy::Client::Plugins::SignRequests) add_plugin(Smithy::Client::Plugins::StubResponses) + add_plugin(Smithy::Client::Plugins::TransferEncoding) add_plugin(Smithy::Client::Plugins::UserAgent) # @param options [Hash] Client options diff --git a/projections/shapes/lib/shapes/schema.rb b/projections/shapes/lib/shapes/schema.rb index 40e8988f8..61a8da789 100644 --- a/projections/shapes/lib/shapes/schema.rb +++ b/projections/shapes/lib/shapes/schema.rb @@ -28,57 +28,57 @@ module Schema Timestamp = ::Smithy::Schema::Shapes::TimestampShape.new(id: "smithy.ruby.tests#Timestamp", name: "Timestamp", traits: {"smithy.ruby.tests#shape" => {}}) Union = ::Smithy::Schema::Shapes::UnionShape.new(id: "smithy.ruby.tests#Union", name: "Union", traits: {"smithy.ruby.tests#shape" => {}}) - Enum.add_member(:foo, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Unit, location_name: "FOO", traits: {"smithy.api#enumValue" => "bar"})) - IntEnum.add_member(:baz, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Unit, location_name: "BAZ", traits: {"smithy.api#enumValue" => 1})) - List.member = ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) - Map.key = ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) - Map.value = ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) - OperationInput.add_member(:blob, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Blob, location_name: "blob")) - OperationInput.add_member(:boolean, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Boolean, location_name: "boolean")) - OperationInput.add_member(:string, ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: "string")) - OperationInput.add_member(:byte, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Byte, location_name: "byte")) - OperationInput.add_member(:short, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Short, location_name: "short")) - OperationInput.add_member(:integer, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Integer, location_name: "integer")) - OperationInput.add_member(:long, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Long, location_name: "long")) - OperationInput.add_member(:float, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Float, location_name: "float")) - OperationInput.add_member(:double, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Double, location_name: "double")) - OperationInput.add_member(:big_integer, ::Smithy::Schema::Shapes::ShapeRef.new(shape: BigInteger, location_name: "bigInteger")) - OperationInput.add_member(:big_decimal, ::Smithy::Schema::Shapes::ShapeRef.new(shape: BigDecimal, location_name: "bigDecimal")) - OperationInput.add_member(:timestamp, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Timestamp, location_name: "timestamp")) - OperationInput.add_member(:document, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Document, location_name: "document")) - OperationInput.add_member(:enum, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Enum, location_name: "enum")) - OperationInput.add_member(:int_enum, ::Smithy::Schema::Shapes::ShapeRef.new(shape: IntEnum, location_name: "intEnum")) - OperationInput.add_member(:list, ::Smithy::Schema::Shapes::ShapeRef.new(shape: List, location_name: "list")) - OperationInput.add_member(:map, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Map, location_name: "map")) - OperationInput.add_member(:structure, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, location_name: "structure")) - OperationInput.add_member(:union, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Union, location_name: "union")) + Enum.add_member(:foo, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit, location_name: "FOO", traits: {"smithy.api#enumValue" => "bar"})) + IntEnum.add_member(:baz, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit, location_name: "BAZ", traits: {"smithy.api#enumValue" => 1})) + List.member = ::Smithy::Schema::Shapes::MemberShape.new(target: String, traits: {"smithy.ruby.tests#shape" => {}}) + Map.key = ::Smithy::Schema::Shapes::MemberShape.new(target: String, traits: {"smithy.ruby.tests#shape" => {}}) + Map.value = ::Smithy::Schema::Shapes::MemberShape.new(target: String, traits: {"smithy.ruby.tests#shape" => {}}) + OperationInput.add_member(:blob, ::Smithy::Schema::Shapes::MemberShape.new(target: Blob, location_name: "blob")) + OperationInput.add_member(:boolean, ::Smithy::Schema::Shapes::MemberShape.new(target: Boolean, location_name: "boolean")) + OperationInput.add_member(:string, ::Smithy::Schema::Shapes::MemberShape.new(target: String, location_name: "string")) + OperationInput.add_member(:byte, ::Smithy::Schema::Shapes::MemberShape.new(target: Byte, location_name: "byte")) + OperationInput.add_member(:short, ::Smithy::Schema::Shapes::MemberShape.new(target: Short, location_name: "short")) + OperationInput.add_member(:integer, ::Smithy::Schema::Shapes::MemberShape.new(target: Integer, location_name: "integer")) + OperationInput.add_member(:long, ::Smithy::Schema::Shapes::MemberShape.new(target: Long, location_name: "long")) + OperationInput.add_member(:float, ::Smithy::Schema::Shapes::MemberShape.new(target: Float, location_name: "float")) + OperationInput.add_member(:double, ::Smithy::Schema::Shapes::MemberShape.new(target: Double, location_name: "double")) + OperationInput.add_member(:big_integer, ::Smithy::Schema::Shapes::MemberShape.new(target: BigInteger, location_name: "bigInteger")) + OperationInput.add_member(:big_decimal, ::Smithy::Schema::Shapes::MemberShape.new(target: BigDecimal, location_name: "bigDecimal")) + OperationInput.add_member(:timestamp, ::Smithy::Schema::Shapes::MemberShape.new(target: Timestamp, location_name: "timestamp")) + OperationInput.add_member(:document, ::Smithy::Schema::Shapes::MemberShape.new(target: Document, location_name: "document")) + OperationInput.add_member(:enum, ::Smithy::Schema::Shapes::MemberShape.new(target: Enum, location_name: "enum")) + OperationInput.add_member(:int_enum, ::Smithy::Schema::Shapes::MemberShape.new(target: IntEnum, location_name: "intEnum")) + OperationInput.add_member(:list, ::Smithy::Schema::Shapes::MemberShape.new(target: List, location_name: "list")) + OperationInput.add_member(:map, ::Smithy::Schema::Shapes::MemberShape.new(target: Map, location_name: "map")) + OperationInput.add_member(:structure, ::Smithy::Schema::Shapes::MemberShape.new(target: Structure, location_name: "structure")) + OperationInput.add_member(:union, ::Smithy::Schema::Shapes::MemberShape.new(target: Union, location_name: "union")) OperationInput.type = Types::OperationInput - OperationOutput.add_member(:blob, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Blob, location_name: "blob")) - OperationOutput.add_member(:boolean, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Boolean, location_name: "boolean")) - OperationOutput.add_member(:string, ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: "string")) - OperationOutput.add_member(:byte, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Byte, location_name: "byte")) - OperationOutput.add_member(:short, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Short, location_name: "short")) - OperationOutput.add_member(:integer, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Integer, location_name: "integer")) - OperationOutput.add_member(:long, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Long, location_name: "long")) - OperationOutput.add_member(:float, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Float, location_name: "float")) - OperationOutput.add_member(:double, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Double, location_name: "double")) - OperationOutput.add_member(:big_integer, ::Smithy::Schema::Shapes::ShapeRef.new(shape: BigInteger, location_name: "bigInteger")) - OperationOutput.add_member(:big_decimal, ::Smithy::Schema::Shapes::ShapeRef.new(shape: BigDecimal, location_name: "bigDecimal")) - OperationOutput.add_member(:timestamp, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Timestamp, location_name: "timestamp")) - OperationOutput.add_member(:document, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Document, location_name: "document")) - OperationOutput.add_member(:enum, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Enum, location_name: "enum")) - OperationOutput.add_member(:int_enum, ::Smithy::Schema::Shapes::ShapeRef.new(shape: IntEnum, location_name: "intEnum")) - OperationOutput.add_member(:list, ::Smithy::Schema::Shapes::ShapeRef.new(shape: List, location_name: "list")) - OperationOutput.add_member(:map, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Map, location_name: "map")) - OperationOutput.add_member(:structure, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, location_name: "structure")) - OperationOutput.add_member(:union, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Union, location_name: "union")) + OperationOutput.add_member(:blob, ::Smithy::Schema::Shapes::MemberShape.new(target: Blob, location_name: "blob")) + OperationOutput.add_member(:boolean, ::Smithy::Schema::Shapes::MemberShape.new(target: Boolean, location_name: "boolean")) + OperationOutput.add_member(:string, ::Smithy::Schema::Shapes::MemberShape.new(target: String, location_name: "string")) + OperationOutput.add_member(:byte, ::Smithy::Schema::Shapes::MemberShape.new(target: Byte, location_name: "byte")) + OperationOutput.add_member(:short, ::Smithy::Schema::Shapes::MemberShape.new(target: Short, location_name: "short")) + OperationOutput.add_member(:integer, ::Smithy::Schema::Shapes::MemberShape.new(target: Integer, location_name: "integer")) + OperationOutput.add_member(:long, ::Smithy::Schema::Shapes::MemberShape.new(target: Long, location_name: "long")) + OperationOutput.add_member(:float, ::Smithy::Schema::Shapes::MemberShape.new(target: Float, location_name: "float")) + OperationOutput.add_member(:double, ::Smithy::Schema::Shapes::MemberShape.new(target: Double, location_name: "double")) + OperationOutput.add_member(:big_integer, ::Smithy::Schema::Shapes::MemberShape.new(target: BigInteger, location_name: "bigInteger")) + OperationOutput.add_member(:big_decimal, ::Smithy::Schema::Shapes::MemberShape.new(target: BigDecimal, location_name: "bigDecimal")) + OperationOutput.add_member(:timestamp, ::Smithy::Schema::Shapes::MemberShape.new(target: Timestamp, location_name: "timestamp")) + OperationOutput.add_member(:document, ::Smithy::Schema::Shapes::MemberShape.new(target: Document, location_name: "document")) + OperationOutput.add_member(:enum, ::Smithy::Schema::Shapes::MemberShape.new(target: Enum, location_name: "enum")) + OperationOutput.add_member(:int_enum, ::Smithy::Schema::Shapes::MemberShape.new(target: IntEnum, location_name: "intEnum")) + OperationOutput.add_member(:list, ::Smithy::Schema::Shapes::MemberShape.new(target: List, location_name: "list")) + OperationOutput.add_member(:map, ::Smithy::Schema::Shapes::MemberShape.new(target: Map, location_name: "map")) + OperationOutput.add_member(:structure, ::Smithy::Schema::Shapes::MemberShape.new(target: Structure, location_name: "structure")) + OperationOutput.add_member(:union, ::Smithy::Schema::Shapes::MemberShape.new(target: Union, location_name: "union")) OperationOutput.type = Types::OperationOutput - Structure.add_member(:member, ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: "member", traits: {"smithy.ruby.tests#shape" => {}})) + Structure.add_member(:member, ::Smithy::Schema::Shapes::MemberShape.new(target: String, location_name: "member", traits: {"smithy.ruby.tests#shape" => {}})) Structure.type = Types::Structure - Union.add_member(:string, Types::Union::String, ::Smithy::Schema::Shapes::ShapeRef.new(shape: String, location_name: "string", traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:structure, Types::Union::Structure, ::Smithy::Schema::Shapes::ShapeRef.new(shape: Structure, location_name: "structure", traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:unit, Types::Union::Unit, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Unit, location_name: "unit", traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:unknown, Types::Union::Unknown, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Unit)) + Union.add_member(:string, Types::Union::String, ::Smithy::Schema::Shapes::MemberShape.new(target: String, location_name: "string", traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:structure, Types::Union::Structure, ::Smithy::Schema::Shapes::MemberShape.new(target: Structure, location_name: "structure", traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:unit, Types::Union::Unit, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit, location_name: "unit", traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:unknown, Types::Union::Unknown, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit)) Union.type = Types::Union ShapeService = ::Smithy::Schema::Shapes::ServiceShape.new do |service| @@ -89,8 +89,8 @@ module Schema service.add_operation(:operation, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "smithy.ruby.tests#Operation" operation.name = "Operation" - operation.input = ::Smithy::Schema::Shapes::ShapeRef.new(shape: OperationInput) - operation.output = ::Smithy::Schema::Shapes::ShapeRef.new(shape: OperationOutput) + operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: OperationInput) + operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: OperationOutput) operation.traits = {"smithy.ruby.tests#shape" => {}} end) end diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 80efaf90b..c4e47eb3b 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -20,6 +20,7 @@ require 'smithy-client/plugins/retry_errors' require 'smithy-client/plugins/sign_requests' require 'smithy-client/plugins/stub_responses' +require 'smithy-client/plugins/transfer_encoding' require 'smithy-client/plugins/user_agent' module Weather @@ -49,6 +50,7 @@ class Client < Smithy::Client::Base add_plugin(Smithy::Client::Plugins::RetryErrors) add_plugin(Smithy::Client::Plugins::SignRequests) add_plugin(Smithy::Client::Plugins::StubResponses) + add_plugin(Smithy::Client::Plugins::TransferEncoding) add_plugin(Smithy::Client::Plugins::UserAgent) # @param options [Hash] Client options diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index ddcc30a94..a63e42308 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -19,31 +19,31 @@ module Schema ListCitiesOutput = ::Smithy::Schema::Shapes::StructureShape.new(id: "example.weather#ListCitiesOutput", name: "ListCitiesOutput") NoSuchResource = ::Smithy::Schema::Shapes::StructureShape.new(id: "example.weather#NoSuchResource", name: "NoSuchResource", traits: {"smithy.api#error" => "client"}) - CityCoordinates.add_member(:latitude, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Float, location_name: "latitude", traits: {"smithy.api#required" => {}})) - CityCoordinates.add_member(:longitude, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Float, location_name: "longitude", traits: {"smithy.api#required" => {}})) + CityCoordinates.add_member(:latitude, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Float, location_name: "latitude", traits: {"smithy.api#required" => {}})) + CityCoordinates.add_member(:longitude, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Float, location_name: "longitude", traits: {"smithy.api#required" => {}})) CityCoordinates.type = Types::CityCoordinates - CitySummaries.member = ::Smithy::Schema::Shapes::ShapeRef.new(shape: CitySummary) - CitySummary.add_member(:city_id, ::Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, location_name: "cityId", traits: {"smithy.api#required" => {}})) - CitySummary.add_member(:name, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::String, location_name: "name", traits: {"smithy.api#required" => {}})) + CitySummaries.member = ::Smithy::Schema::Shapes::MemberShape.new(target: CitySummary) + CitySummary.add_member(:city_id, ::Smithy::Schema::Shapes::MemberShape.new(target: CityId, location_name: "cityId", traits: {"smithy.api#required" => {}})) + CitySummary.add_member(:name, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::String, location_name: "name", traits: {"smithy.api#required" => {}})) CitySummary.type = Types::CitySummary - GetCityInput.add_member(:city_id, ::Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, location_name: "cityId", traits: {"smithy.api#required" => {}})) + GetCityInput.add_member(:city_id, ::Smithy::Schema::Shapes::MemberShape.new(target: CityId, location_name: "cityId", traits: {"smithy.api#required" => {}})) GetCityInput.type = Types::GetCityInput - GetCityOutput.add_member(:name, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::String, location_name: "name", traits: {"smithy.api#notProperty" => {}, "smithy.api#required" => {}})) - GetCityOutput.add_member(:coordinates, ::Smithy::Schema::Shapes::ShapeRef.new(shape: CityCoordinates, location_name: "coordinates", traits: {"smithy.api#required" => {}})) + GetCityOutput.add_member(:name, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::String, location_name: "name", traits: {"smithy.api#notProperty" => {}, "smithy.api#required" => {}})) + GetCityOutput.add_member(:coordinates, ::Smithy::Schema::Shapes::MemberShape.new(target: CityCoordinates, location_name: "coordinates", traits: {"smithy.api#required" => {}})) GetCityOutput.type = Types::GetCityOutput - GetCurrentTimeOutput.add_member(:time, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Timestamp, location_name: "time", traits: {"smithy.api#required" => {}})) + GetCurrentTimeOutput.add_member(:time, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Timestamp, location_name: "time", traits: {"smithy.api#required" => {}})) GetCurrentTimeOutput.type = Types::GetCurrentTimeOutput - GetForecastInput.add_member(:city_id, ::Smithy::Schema::Shapes::ShapeRef.new(shape: CityId, location_name: "cityId", traits: {"smithy.api#required" => {}})) + GetForecastInput.add_member(:city_id, ::Smithy::Schema::Shapes::MemberShape.new(target: CityId, location_name: "cityId", traits: {"smithy.api#required" => {}})) GetForecastInput.type = Types::GetForecastInput - GetForecastOutput.add_member(:chance_of_rain, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Float, location_name: "chanceOfRain")) + GetForecastOutput.add_member(:chance_of_rain, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Float, location_name: "chanceOfRain")) GetForecastOutput.type = Types::GetForecastOutput - ListCitiesInput.add_member(:next_token, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::String, location_name: "nextToken")) - ListCitiesInput.add_member(:page_size, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Integer, location_name: "pageSize")) + ListCitiesInput.add_member(:next_token, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::String, location_name: "nextToken")) + ListCitiesInput.add_member(:page_size, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Integer, location_name: "pageSize")) ListCitiesInput.type = Types::ListCitiesInput - ListCitiesOutput.add_member(:next_token, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::String, location_name: "nextToken")) - ListCitiesOutput.add_member(:items, ::Smithy::Schema::Shapes::ShapeRef.new(shape: CitySummaries, location_name: "items", traits: {"smithy.api#required" => {}})) + ListCitiesOutput.add_member(:next_token, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::String, location_name: "nextToken")) + ListCitiesOutput.add_member(:items, ::Smithy::Schema::Shapes::MemberShape.new(target: CitySummaries, location_name: "items", traits: {"smithy.api#required" => {}})) ListCitiesOutput.type = Types::ListCitiesOutput - NoSuchResource.add_member(:resource_type, ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::String, location_name: "resourceType", traits: {"smithy.api#required" => {}})) + NoSuchResource.add_member(:resource_type, ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::String, location_name: "resourceType", traits: {"smithy.api#required" => {}})) NoSuchResource.type = Types::NoSuchResource Weather = ::Smithy::Schema::Shapes::ServiceShape.new do |service| @@ -54,30 +54,30 @@ module Schema service.add_operation(:get_city, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#GetCity" operation.name = "GetCity" - operation.input = ::Smithy::Schema::Shapes::ShapeRef.new(shape: GetCityInput) - operation.output = ::Smithy::Schema::Shapes::ShapeRef.new(shape: GetCityOutput) - operation.errors << ::Smithy::Schema::Shapes::ShapeRef.new(shape: NoSuchResource) + operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: GetCityInput) + operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: GetCityOutput) + operation.errors << ::Smithy::Schema::Shapes::MemberShape.new(target: NoSuchResource) operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_current_time, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#GetCurrentTime" operation.name = "GetCurrentTime" - operation.input = ::Smithy::Schema::Shapes::ShapeRef.new(shape: ::Smithy::Schema::Shapes::Prelude::Unit) - operation.output = ::Smithy::Schema::Shapes::ShapeRef.new(shape: GetCurrentTimeOutput) + operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit) + operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: GetCurrentTimeOutput) operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_forecast, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#GetForecast" operation.name = "GetForecast" - operation.input = ::Smithy::Schema::Shapes::ShapeRef.new(shape: GetForecastInput) - operation.output = ::Smithy::Schema::Shapes::ShapeRef.new(shape: GetForecastOutput) + operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: GetForecastInput) + operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: GetForecastOutput) operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:list_cities, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#ListCities" operation.name = "ListCities" - operation.input = ::Smithy::Schema::Shapes::ShapeRef.new(shape: ListCitiesInput) - operation.output = ::Smithy::Schema::Shapes::ShapeRef.new(shape: ListCitiesOutput) + operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: ListCitiesInput) + operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: ListCitiesOutput) operation.traits = {"smithy.api#readonly" => {}} operation[:paginator] = Paginators::ListCities.new end) From 969094b64425673e5d70d30c0e3f4d646ff66429 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 09:06:21 -0700 Subject: [PATCH 05/23] Update Json codec with SERDE --- gems/smithy-json/lib/smithy-json/builder.rb | 55 ++++++++--------- gems/smithy-json/lib/smithy-json/parser.rb | 67 ++++++++++----------- 2 files changed, 59 insertions(+), 63 deletions(-) diff --git a/gems/smithy-json/lib/smithy-json/builder.rb b/gems/smithy-json/lib/smithy-json/builder.rb index 1d7b846c9..9095fe04f 100644 --- a/gems/smithy-json/lib/smithy-json/builder.rb +++ b/gems/smithy-json/lib/smithy-json/builder.rb @@ -13,21 +13,20 @@ def initialize(options = {}) end def build(shape, data) - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - Smithy::Json.dump(shape(ref, data)) + Smithy::Json.dump(serialize_shape(shape, data)) end private - def shape(ref, value) # rubocop:disable Metrics/CyclomaticComplexity - case ref.target + def serialize_shape(shape, value) # rubocop:disable Metrics/CyclomaticComplexity + case shape.target when BlobShape then blob(value) when FloatShape then float(value) - when ListShape then list(ref, value) - when MapShape then map(ref, value) - when StructureShape then structure(ref, value) - when TimestampShape then timestamp(ref, value) - when UnionShape then union(ref, value) + when ListShape then list(shape, value) + when MapShape then map(shape, value) + when StructureShape then structure(shape, value) + when TimestampShape then timestamp(shape, value) + when UnionShape then union(shape, value) else value end end @@ -48,36 +47,34 @@ def float(value) end end - def list(ref, values) + def list(shape, values) return if values.nil? - shape = ref.target values.collect do |value| - shape(shape.member, value) + serialize_shape(shape.target.member, value) end end - def map(ref, values) + def map(shape, values) return if values.nil? - shape = ref.target values.each.with_object({}) do |(key, value), data| - data[key] = shape(shape.value, value) + data[key] = serialize_shape(shape.target.value, value) end end - def structure(ref, values) + def structure(shape, values) return if values.nil? - ref.target.members.each_with_object({}) do |(member_name, member_ref), data| + shape.target.members.each_with_object({}) do |(member_name, member_shape), data| value = values[member_name] - data[location_name(member_ref)] = shape(member_ref, value) unless value.nil? + data[location_name(member_shape)] = serialize_shape(member_shape, value) unless value.nil? end end - def timestamp(ref, value) + def timestamp(shape, value) trait = 'smithy.api#timestampFormat' - case ref.traits[trait] || ref.target.traits[trait] + case shape.traits[trait] || shape.target.traits[trait] when 'date-time' then value.utc.iso8601 when 'http-date' then value.utc.httpdate else @@ -86,27 +83,27 @@ def timestamp(ref, value) end end - def union(ref, values) # rubocop:disable Metrics/AbcSize + def union(shape, values) # rubocop:disable Metrics/AbcSize return if values.nil? data = {} if values.is_a?(Schema::Union) - _name, member_ref = ref.target.member_by_type(values.class) - data[location_name(member_ref)] = shape(member_ref, values.value) + _name, member_ref = shape.target.member_by_type(values.class) + data[location_name(member_ref)] = serialize_shape(member_ref, values.value) else key, value = values.first - if ref.target.member?(key) - member_ref = ref.target.member(key) - data[location_name(member_ref)] = shape(member_ref, value) + if shape.target.member?(key) + member_ref = shape.target.member(key) + data[location_name(member_ref)] = serialize_shape(member_ref, value) end end data end - def location_name(ref) - return ref.location_name unless @json_name + def location_name(member) + return member.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.location_name + member.traits['smithy.api#jsonName'] || member.location_name end end end diff --git a/gems/smithy-json/lib/smithy-json/parser.rb b/gems/smithy-json/lib/smithy-json/parser.rb index a99e8d0b4..5aa5b893c 100644 --- a/gems/smithy-json/lib/smithy-json/parser.rb +++ b/gems/smithy-json/lib/smithy-json/parser.rb @@ -12,24 +12,23 @@ def initialize(options = {}) @json_name = options[:json_name] || false end - def parse(shape, bytes, target = nil) + def parse(shape, bytes, result = nil) return {} if bytes.empty? - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - shape(ref, Smithy::Json.load(bytes), target) + deserialize_shape(shape, Smithy::Json.load(bytes), result) end private - def shape(ref, value, target = nil) # rubocop:disable Metrics/CyclomaticComplexity - case ref.target + def deserialize_shape(shape, value, result = nil) # rubocop:disable Metrics/CyclomaticComplexity + case shape.target when BlobShape then Base64.decode64(value) when FloatShape then float(value) - when ListShape then list(ref, value, target) - when MapShape then map(ref, value, target) - when StructureShape then structure(ref, value, target) + when ListShape then list(shape, value, result) + when MapShape then map(shape, value, result) + when StructureShape then structure(shape, value, result) when TimestampShape then timestamp(value) - when UnionShape then union(ref, value, target) + when UnionShape then union(shape, value, result) else value end end @@ -43,37 +42,37 @@ def float(value) end end - def list(ref, values, target = nil) + def list(shape, values, result = nil) return if values.nil? - target = [] if target.nil? + result = [] if result.nil? values.each do |value| - next if value.nil? && !sparse?(ref.target) + next if value.nil? && !sparse?(shape.target) - target << shape(ref.target.member, value) + result << deserialize_shape(shape.target.member, value) end - target + result end - def map(ref, values, target = nil) - target = {} if target.nil? + def map(shape, values, result = nil) + result = {} if result.nil? values.each do |key, value| - next if value.nil? && !sparse?(ref.target) + next if value.nil? && !sparse?(shape.target) - target[key] = shape(ref.target.value, value) + result[key] = deserialize_shape(shape.target.value, value) end - target + result end - def structure(ref, values, target = nil) + def structure(shape, values, result = nil) return if values.nil? - target = ref.target.type.new if target.nil? - ref.target.members.each do |member_name, member_ref| - value = values[location_name(member_ref)] - target[member_name] = shape(member_ref, value) unless value.nil? + result = shape.target.type.new if result.nil? + shape.target.members.each do |member_name, member_shape| + value = values[location_name(member_shape)] + result[member_name] = deserialize_shape(member_shape, value) unless value.nil? end - target + result end def timestamp(value) @@ -89,24 +88,24 @@ def timestamp(value) end end - def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize - ref.target.members.each do |member_name, member_ref| - value = values[location_name(member_ref)] + def union(shape, values, result = nil) # rubocop:disable Metrics/AbcSize + shape.target.members.each do |member_name, member_shape| + value = values[location_name(member_shape)] next if value.nil? - target = ref.target.member_type(member_name) if target.nil? - return target.new(member_name => shape(member_ref, value)) + result = shape.target.member_type(member_name) if result.nil? + return result.new(member_name => deserialize_shape(member_shape, value)) end values.delete('__type') key, value = values.first - ref.target.member_type(:unknown).new(unknown: { key => value }) + shape.target.member_type(:unknown).new(unknown: { key => value }) end - def location_name(ref) - return ref.location_name unless @json_name + def location_name(member) + return member.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.location_name + member.traits['smithy.api#jsonName'] || member.location_name end def sparse?(shape) From f64addf74f860e3c0556dbe84ebd7c91caf0b922 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 12:47:13 -0700 Subject: [PATCH 06/23] Remove MemberShape wrapper from operation input/output --- .../lib/smithy/templates/client/schema.erb | 4 +- gems/smithy/lib/smithy/views/client/schema.rb | 140 +++++++++--------- .../spec/interfaces/rename_shapes_spec.rb | 4 +- .../interfaces/synthetic_input_output_spec.rb | 12 +- 4 files changed, 81 insertions(+), 79 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/schema.erb b/gems/smithy/lib/smithy/templates/client/schema.erb index b4f51b6a0..e4dd12b03 100644 --- a/gems/smithy/lib/smithy/templates/client/schema.erb +++ b/gems/smithy/lib/smithy/templates/client/schema.erb @@ -50,8 +50,8 @@ module <%= module_name %> service.add_operation(:<%= shape.name.underscore %>, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "<%= shape.id %>" operation.name = "<%= shape.name %>" - operation.input = <%= shape.input.initializer %> - operation.output = <%= shape.output.initializer %> + operation.input = <%= shape.input %> + operation.output = <%= shape.output %> <% shape.errors.each do |error| -%> operation.errors << <%= error.initializer %> <% end -%> diff --git a/gems/smithy/lib/smithy/views/client/schema.rb b/gems/smithy/lib/smithy/views/client/schema.rb index 36f44b20f..2c20265a1 100644 --- a/gems/smithy/lib/smithy/views/client/schema.rb +++ b/gems/smithy/lib/smithy/views/client/schema.rb @@ -54,6 +54,58 @@ def build_shape(id, shape) end end + # Shared resolution logic for the schema view classes. Mixed into the + # shape views ({Shape} and its subclasses), {OperationShape}, and + # {MemberShape} — every class that needs to turn an absolute shape ID + # into the Ruby constant the generated schema references. Relies on the + # including class exposing the unwrapped service hash as +@service+. + # @api private + module SchemaHelper + # Maps Smithy prelude shape IDs to their generated +Prelude::*+ + # constant names. Prelude shapes are shared built-ins and are never + # emitted per-service, so they resolve to a fixed constant rather than + # a service-local one. + PRELUDE_SHAPES_MAP = { + 'smithy.api#BigInteger' => 'Prelude::BigInteger', + 'smithy.api#BigDecimal' => 'Prelude::BigDecimal', + 'smithy.api#Blob' => 'Prelude::Blob', + 'smithy.api#Boolean' => 'Prelude::Boolean', + 'smithy.api#Byte' => 'Prelude::Byte', + 'smithy.api#Document' => 'Prelude::Document', + 'smithy.api#Double' => 'Prelude::Double', + 'smithy.api#Float' => 'Prelude::Float', + 'smithy.api#Integer' => 'Prelude::Integer', + 'smithy.api#Long' => 'Prelude::Long', + 'smithy.api#PrimitiveBoolean' => 'Prelude::PrimitiveBoolean', + 'smithy.api#PrimitiveByte' => 'Prelude::PrimitiveByte', + 'smithy.api#PrimitiveDouble' => 'Prelude::PrimitiveDouble', + 'smithy.api#PrimitiveFloat' => 'Prelude::PrimitiveFloat', + 'smithy.api#PrimitiveInteger' => 'Prelude::PrimitiveInteger', + 'smithy.api#PrimitiveLong' => 'Prelude::PrimitiveLong', + 'smithy.api#PrimitiveShort' => 'Prelude::PrimitiveShort', + 'smithy.api#Short' => 'Prelude::Short', + 'smithy.api#String' => 'Prelude::String', + 'smithy.api#Timestamp' => 'Prelude::Timestamp', + 'smithy.api#Unit' => 'Prelude::Unit' + }.freeze + + # Resolves an absolute shape ID to the Ruby constant the generated + # schema references for it. + # + # - Prelude shapes resolve to their fully-qualified + # +::Smithy::Schema::Shapes::Prelude::*+ constant. + # - All other shapes resolve to a service-local constant name, + # honoring the service's +rename+ map when present. + # + # @param [String] id Absolute shape ID (e.g. +"example.weather#GetCityInput"+). + # @return [String] The constant reference as a string (e.g. +"GetCityInput"+). + def shape_name_from_id(id) + return "::Smithy::Schema::Shapes::#{PRELUDE_SHAPES_MAP[id]}" if PRELUDE_SHAPES_MAP.key?(id) + + (@service.dig('rename', id) || Model::Shape.name(id)).camelize + end + end + # @api private class ServiceShape OMITTED_TRAITS = %w[ @@ -78,6 +130,8 @@ def name # @api private class OperationShape + include SchemaHelper + OMITTED_TRAITS = %w[ smithy.api#documentation smithy.api#examples @@ -92,8 +146,8 @@ def initialize(service, id, shape) _, @service = service.first @id = id @name = (@service.dig('rename', @id) || Model::Shape.name(@id)).camelize - @input = build_input(shape['input']) - @output = build_output(shape['output']) + @input = shape_name_from_id(shape['input']['target']) + @output = shape_name_from_id(shape['output']['target']) @errors = build_errors(shape.fetch('errors', [])) @traits = shape.fetch('traits', {}) end @@ -114,14 +168,6 @@ def paginator private - def build_input(input) - MemberShape.new(@service, nil, input) - end - - def build_output(output) - MemberShape.new(@service, nil, output) - end - def build_errors(errors) errors = Set.new(@service.fetch('errors', [])).merge(errors) errors.map { |error| MemberShape.new(@service, nil, error) } @@ -130,6 +176,8 @@ def build_errors(errors) # @api private class Shape + include SchemaHelper + OMITTED_TRAITS = %w[ smithy.api#documentation ].freeze @@ -172,6 +220,12 @@ def initializer options_str += ", traits: #{@traits}" unless @traits.empty? "::Smithy::Schema::Shapes::#{SHAPE_CLASS_MAP[@type]}.new(#{options_str})" end + + private + + def build_members(members) + members.map { |name, member| MemberShape.new(@service, name, member) } + end end # @api private @@ -184,7 +238,7 @@ class StructureShape < Shape def initialize(service, id, shape) super - @members = build_shape_refs(shape['members']) + @members = build_members(shape['members']) @traits = shape.fetch('traits', {}).except(*OMITTED_TRAITS) end @@ -201,44 +255,26 @@ def http_payload? def http_payload @members.find(&:http_payload).http_payload end - - private - - def build_shape_refs(members) - members.map { |name, member| MemberShape.new(@service, name, member) } - end end # @api private class EnumShape < Shape def initialize(service, id, shape) super - @members = build_shape_refs(shape['members']) + @members = build_members(shape['members']) end attr_reader :members - - private - - def build_shape_refs(members) - members.map { |name, shape_ref| MemberShape.new(@service, name, shape_ref) } - end end # @api private class IntEnumShape < Shape def initialize(service, id, shape) super - @members = build_shape_refs(shape['members']) + @members = build_members(shape['members']) end attr_reader :members - - private - - def build_shape_refs(members) - members.map { |name, member| MemberShape.new(@service, name, member) } - end end # @api private @@ -266,7 +302,7 @@ def initialize(service, id, shape) class UnionShape < Shape def initialize(service, id, shape) super - @members = build_shape_refs(shape['members']) + @members = build_members(shape['members']) end attr_reader :members @@ -278,49 +314,21 @@ def type_class def union_type(shape_ref) "#{type_class}::#{shape_ref.location_name.camelize}" end - - private - - def build_shape_refs(members) - members.map { |name, member| MemberShape.new(@service, name, member) } - end end # @api private class MemberShape + include SchemaHelper + OMITTED_TRAITS = %w[ smithy.api#documentation ].freeze - PRELUDE_SHAPES_MAP = { - 'smithy.api#BigInteger' => 'Prelude::BigInteger', - 'smithy.api#BigDecimal' => 'Prelude::BigDecimal', - 'smithy.api#Blob' => 'Prelude::Blob', - 'smithy.api#Boolean' => 'Prelude::Boolean', - 'smithy.api#Byte' => 'Prelude::Byte', - 'smithy.api#Document' => 'Prelude::Document', - 'smithy.api#Double' => 'Prelude::Double', - 'smithy.api#Float' => 'Prelude::Float', - 'smithy.api#Integer' => 'Prelude::Integer', - 'smithy.api#Long' => 'Prelude::Long', - 'smithy.api#PrimitiveBoolean' => 'Prelude::PrimitiveBoolean', - 'smithy.api#PrimitiveByte' => 'Prelude::PrimitiveByte', - 'smithy.api#PrimitiveDouble' => 'Prelude::PrimitiveDouble', - 'smithy.api#PrimitiveFloat' => 'Prelude::PrimitiveFloat', - 'smithy.api#PrimitiveInteger' => 'Prelude::PrimitiveInteger', - 'smithy.api#PrimitiveLong' => 'Prelude::PrimitiveLong', - 'smithy.api#PrimitiveShort' => 'Prelude::PrimitiveShort', - 'smithy.api#Short' => 'Prelude::Short', - 'smithy.api#String' => 'Prelude::String', - 'smithy.api#Timestamp' => 'Prelude::Timestamp', - 'smithy.api#Unit' => 'Prelude::Unit' - }.freeze - def initialize(service, location_name, shape_ref) @service = service @name = location_name.underscore if location_name @location_name = location_name - @target = shape(shape_ref['target']) + @target = shape_name_from_id(shape_ref['target']) @traits = shape_ref.fetch('traits', {}).except(*OMITTED_TRAITS) end @@ -333,12 +341,6 @@ def initializer "::Smithy::Schema::Shapes::MemberShape.new(#{options_str})" end - def shape(id) - return "::Smithy::Schema::Shapes::#{PRELUDE_SHAPES_MAP[id]}" if PRELUDE_SHAPES_MAP.key?(id) - - (@service.dig('rename', id) || Model::Shape.name(id)).camelize - end - def http_payload? @traits.key?('smithy.api#httpPayload') end diff --git a/gems/smithy/spec/interfaces/rename_shapes_spec.rb b/gems/smithy/spec/interfaces/rename_shapes_spec.rb index a52bea17c..863561eed 100644 --- a/gems/smithy/spec/interfaces/rename_shapes_spec.rb +++ b/gems/smithy/spec/interfaces/rename_shapes_spec.rb @@ -37,8 +37,8 @@ it 'assigns renamed shapes to operation inputs and outputs' do client = RenameShapes::Client.new operation = client.config.service.operation(:operation) - expect(operation.input.target.type).to eq(RenameShapes::Types::RenamedOperationInput) - expect(operation.output.target.type).to eq(RenameShapes::Types::RenamedOperationOutput) + expect(operation.input.type).to eq(RenameShapes::Types::RenamedOperationInput) + expect(operation.output.type).to eq(RenameShapes::Types::RenamedOperationOutput) end end end diff --git a/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb b/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb index b7de49521..f37ea33f4 100644 --- a/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb +++ b/gems/smithy/spec/interfaces/synthetic_input_output_spec.rb @@ -37,25 +37,25 @@ it 'assigns synthetic input and output shapes to the operation' do client = SyntheticInputOutput::Client.new operation = client.config.service.operation(:operation) - expect(operation.input.target.type).to eq(SyntheticInputOutput::Types::OperationInput) - expect(operation.output.target.type).to eq(SyntheticInputOutput::Types::OperationOutput) + expect(operation.input.type).to eq(SyntheticInputOutput::Types::OperationInput) + expect(operation.output.type).to eq(SyntheticInputOutput::Types::OperationOutput) end it 'preserves input and output shapes on the operation with the input and output trait' do client = SyntheticInputOutput::Client.new operation = client.config.service.operation(:operation_with_input_and_output_traits) - expect(operation.input.target.type) + expect(operation.input.type) .to eq(SyntheticInputOutput::Types::OperationWithInputAndOutputTraitsInput) - expect(operation.output.target.type) + expect(operation.output.type) .to eq(SyntheticInputOutput::Types::OperationWithInputAndOutputTraitsOutput) end it 'handles naming conflicts by inserting Operation between the operation name and the suffix' do client = SyntheticInputOutput::Client.new operation = client.config.service.operation(:operation_with_naming_conflict) - expect(operation.input.target.type) + expect(operation.input.type) .to eq(SyntheticInputOutput::Types::OperationWithNamingConflictOperationInput) - expect(operation.output.target.type) + expect(operation.output.type) .to eq(SyntheticInputOutput::Types::OperationWithNamingConflictOperationOutput) end end From adec0fbc02cc59cbb9f4c475131fb7ec59eb4c82 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 12:47:28 -0700 Subject: [PATCH 07/23] Update projections --- projections/shapes/lib/shapes/schema.rb | 4 ++-- projections/weather/lib/weather/schema.rb | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/projections/shapes/lib/shapes/schema.rb b/projections/shapes/lib/shapes/schema.rb index 61a8da789..f4dfa0810 100644 --- a/projections/shapes/lib/shapes/schema.rb +++ b/projections/shapes/lib/shapes/schema.rb @@ -89,8 +89,8 @@ module Schema service.add_operation(:operation, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "smithy.ruby.tests#Operation" operation.name = "Operation" - operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: OperationInput) - operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: OperationOutput) + operation.input = OperationInput + operation.output = OperationOutput operation.traits = {"smithy.ruby.tests#shape" => {}} end) end diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index a63e42308..7eff0acd0 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -54,30 +54,30 @@ module Schema service.add_operation(:get_city, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#GetCity" operation.name = "GetCity" - operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: GetCityInput) - operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: GetCityOutput) + operation.input = GetCityInput + operation.output = GetCityOutput operation.errors << ::Smithy::Schema::Shapes::MemberShape.new(target: NoSuchResource) operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_current_time, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#GetCurrentTime" operation.name = "GetCurrentTime" - operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: ::Smithy::Schema::Shapes::Prelude::Unit) - operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: GetCurrentTimeOutput) + operation.input = ::Smithy::Schema::Shapes::Prelude::Unit + operation.output = GetCurrentTimeOutput operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_forecast, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#GetForecast" operation.name = "GetForecast" - operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: GetForecastInput) - operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: GetForecastOutput) + operation.input = GetForecastInput + operation.output = GetForecastOutput operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:list_cities, ::Smithy::Schema::Shapes::OperationShape.new do |operation| operation.id = "example.weather#ListCities" operation.name = "ListCities" - operation.input = ::Smithy::Schema::Shapes::MemberShape.new(target: ListCitiesInput) - operation.output = ::Smithy::Schema::Shapes::MemberShape.new(target: ListCitiesOutput) + operation.input = ListCitiesInput + operation.output = ListCitiesOutput operation.traits = {"smithy.api#readonly" => {}} operation[:paginator] = Paginators::ListCities.new end) From 1b9b8c7488f2ce440701dc7fdb50393177f6e3da Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 12:54:58 -0700 Subject: [PATCH 08/23] Remove shape refs --- gems/smithy/lib/smithy/views/client/schema.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gems/smithy/lib/smithy/views/client/schema.rb b/gems/smithy/lib/smithy/views/client/schema.rb index 2c20265a1..56ff386d4 100644 --- a/gems/smithy/lib/smithy/views/client/schema.rb +++ b/gems/smithy/lib/smithy/views/client/schema.rb @@ -311,8 +311,8 @@ def type_class "Types::#{(@service.dig('rename', @id) || Model::Shape.name(@id)).camelize}" end - def union_type(shape_ref) - "#{type_class}::#{shape_ref.location_name.camelize}" + def union_type(member) + "#{type_class}::#{member.location_name.camelize}" end end @@ -324,12 +324,12 @@ class MemberShape smithy.api#documentation ].freeze - def initialize(service, location_name, shape_ref) + def initialize(service, location_name, member_def) @service = service @name = location_name.underscore if location_name @location_name = location_name - @target = shape_name_from_id(shape_ref['target']) - @traits = shape_ref.fetch('traits', {}).except(*OMITTED_TRAITS) + @target = shape_name_from_id(member_def['target']) + @traits = member_def.fetch('traits', {}).except(*OMITTED_TRAITS) end attr_reader :name, :location_name From 6108a77232557c358fb3fbb3be2684fbb742b322 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 13:03:55 -0700 Subject: [PATCH 09/23] Refacor CBOR codec to new standards --- gems/smithy-cbor/lib/smithy-cbor/builder.rb | 45 +++++++-------- gems/smithy-cbor/lib/smithy-cbor/parser.rb | 61 ++++++++++----------- 2 files changed, 51 insertions(+), 55 deletions(-) diff --git a/gems/smithy-cbor/lib/smithy-cbor/builder.rb b/gems/smithy-cbor/lib/smithy-cbor/builder.rb index 7eb4bab2b..e2b9b46b1 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/builder.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/builder.rb @@ -13,21 +13,20 @@ def initialize(options = {}) end def build(shape, data) - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - return if ref.target == Prelude::Unit + return if shape.target == Prelude::Unit - Cbor.encode(shape(ref, data)) + Cbor.encode(serialize_shape(shape, data)) end private - def shape(ref, value) - case ref.target + def serialize_shape(shape, value) + case shape.target when BlobShape then blob(value) - when ListShape then list(ref, value) - when MapShape then map(ref, value) - when StructureShape then structure(ref, value) - when UnionShape then union(ref, value) + when ListShape then list(shape, value) + when MapShape then map(shape, value) + when StructureShape then structure(shape, value) + when UnionShape then union(shape, value) else value end end @@ -36,47 +35,45 @@ def blob(value) value.respond_to?(:read) ? value.read : value end - def list(ref, values) + def list(shape, values) return if values.nil? - shape = ref.target values.collect do |value| - shape(shape.member, value) + serialize_shape(shape.target.member, value) end end - def map(ref, values) + def map(shape, values) return if values.nil? - shape = ref.target values.each.with_object({}) do |(key, value), data| - data[key] = shape(shape.value, value) + data[key] = serialize_shape(shape.target.value, value) end end - def structure(ref, values) + def structure(shape, values) return if values.nil? - ref.target.members.each_with_object({}) do |(member_name, member_ref), data| + shape.target.members.each_with_object({}) do |(member_name, member_shape), data| value = values[member_name] next if value.nil? - data[member_ref.location_name] = shape(member_ref, value) + data[member_shape.location_name] = serialize_shape(member_shape, value) end end - def union(ref, values) # rubocop:disable Metrics/AbcSize + def union(shape, values) # rubocop:disable Metrics/AbcSize return if values.nil? data = {} if values.is_a?(Schema::Union) - _name, member_ref = ref.target.member_by_type(values.class) - data[member_ref.location_name] = shape(member_ref, values.value) + _name, member_shape = shape.target.member_by_type(values.class) + data[member_shape.location_name] = serialize_shape(member_shape, values.value) else key, value = values.first - if ref.target.member?(key) - member_ref = ref.target.member(key) - data[member_ref.location_name] = shape(member_ref, value) + if shape.target.member?(key) + member_shape = shape.target.member(key) + data[member_shape.location_name] = serialize_shape(member_shape, value) end end data diff --git a/gems/smithy-cbor/lib/smithy-cbor/parser.rb b/gems/smithy-cbor/lib/smithy-cbor/parser.rb index 2d580df76..1342df72a 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/parser.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/parser.rb @@ -12,68 +12,67 @@ def initialize(options = {}) @options = options end - def parse(shape, bytes, target = nil) + def parse(shape, bytes, result = nil) return {} if bytes.empty? - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - shape(ref, Cbor.decode(bytes), target) + deserialize_shape(shape, Cbor.decode(bytes), result) end private - def shape(ref, value, target = nil) + def deserialize_shape(shape, value, result = nil) return nil if value.nil? - case ref.target - when ListShape then list(ref, value, target) - when MapShape then map(ref, value, target) - when StructureShape then structure(ref, value, target) - when UnionShape then union(ref, value, target) + case shape.target + when ListShape then list(shape, value, result) + when MapShape then map(shape, value, result) + when StructureShape then structure(shape, value, result) + when UnionShape then union(shape, value, result) else value end end - def list(ref, values, target = nil) - target = [] if target.nil? + def list(shape, values, result = nil) + result = [] if result.nil? values.each do |value| - next if value.nil? && !sparse?(ref.target) + next if value.nil? && !sparse?(shape.target) - target << shape(ref.target.member, value) + result << deserialize_shape(shape.target.member, value) end - target + result end - def map(ref, values, target = nil) - target = {} if target.nil? + def map(shape, values, result = nil) + result = {} if result.nil? values.each do |key, value| - next if value.nil? && !sparse?(ref.target) + next if value.nil? && !sparse?(shape.target) - target[key] = shape(ref.target.value, value) + result[key] = deserialize_shape(shape.target.value, value) end - target + result end - def structure(ref, values, target = nil) - target = ref.target.type.new if target.nil? - ref.target.members.each do |member_name, member_ref| - value = values[member_ref.location_name] - target[member_name] = shape(member_ref, value) unless value.nil? + def structure(shape, values, result = nil) + result = shape.target.type.new if result.nil? + shape.target.members.each do |member_name, member_shape| + value = values[member_shape.location_name] + result[member_name] = deserialize_shape(member_shape, value) unless value.nil? end - target + result end - def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize - ref.target.members.each do |member_name, member_ref| - value = values[member_ref.location_name] + def union(shape, values, result = nil) # rubocop:disable Metrics/AbcSize + shape.target.members.each do |member_name, member_shape| + value = values[member_shape.location_name] next if value.nil? - target = ref.target.member_type(member_name) if target.nil? - return target.new(member_name => shape(member_ref, value)) + result = shape.target.member_type(member_name) if result.nil? + return result.new(member_name => deserialize_shape(member_shape, value)) end values.delete('__type') key, value = values.first - ref.target.member_type(:unknown).new(unknown: { key => value }) + shape.target.member_type(:unknown).new(unknown: { key => value }) end def sparse?(shape) From 68715943be277ec9ad4e5513eb9678c598c1703f Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 13:56:21 -0700 Subject: [PATCH 10/23] Refactor XML codec --- gems/smithy-xml/lib/smithy-xml/builder.rb | 131 +++++++++--------- gems/smithy-xml/lib/smithy-xml/doc_builder.rb | 20 +-- gems/smithy-xml/lib/smithy-xml/parser.rb | 9 +- .../smithy-xml/lib/smithy-xml/parser/frame.rb | 48 +++---- .../smithy-xml/lib/smithy-xml/parser/stack.rb | 6 +- 5 files changed, 108 insertions(+), 106 deletions(-) diff --git a/gems/smithy-xml/lib/smithy-xml/builder.rb b/gems/smithy-xml/lib/smithy-xml/builder.rb index c6935ad17..60de2b659 100644 --- a/gems/smithy-xml/lib/smithy-xml/builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/builder.rb @@ -13,25 +13,24 @@ def initialize(options = {}) @pad = options.fetch(:pad, '') end - def build(shape, data, target = nil) - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - target ||= [] - @builder = DocBuilder.new(target: target, indent: @indent, pad: @pad) - structure(ref.location_name || ref.target.traits['smithy.api#xmlName'] || ref.target.name, ref, data) - target.join + def build(shape, data, output = nil) + output ||= [] + @builder = DocBuilder.new(output: output, indent: @indent, pad: @pad) + structure(shape.target.traits['smithy.api#xmlName'] || shape.target.name, shape, data) + output.join end private - def shape(name, ref, value) - case ref.target - when BlobShape then node(name, ref, blob(value)) - when ListShape then list(name, ref, value) - when MapShape then map(name, ref, value) - when StructureShape then structure(name, ref, value) - when TimestampShape then node(name, ref, timestamp(ref, value)) - when UnionShape then union(name, ref, value) - else node(name, ref, value.to_s) + def serialize_shape(name, shape, value) + case shape.target + when BlobShape then node(name, shape, blob(value)) + when ListShape then list(name, shape, value) + when MapShape then map(name, shape, value) + when StructureShape then structure(name, shape, value) + when TimestampShape then node(name, shape, timestamp(shape, value)) + when UnionShape then union(name, shape, value) + else node(name, shape, value.to_s) end end @@ -39,67 +38,71 @@ def blob(value) Base64.strict_encode64(value.respond_to?(:read) ? value.read : value) end - def list(name, ref, values) - member_ref = ref.target.member - if flat?(ref) + def list(name, shape, values) + member_shape = shape.target.member + if flat?(shape) values.each do |value| - shape(name, member_ref, value) + serialize_shape(name, member_shape, value) end else - node(name, ref) do + node(name, shape) do values.each do |value| - shape(location_name(member_ref, 'member'), ref.target.member, value) + serialize_shape(location_name(member_shape, 'member'), shape.target.member, value) end end end end - def map(name, ref, values) # rubocop:disable Metrics/AbcSize - key_ref = ref.target.key - value_ref = ref.target.value - if flat?(ref) - values.each do |key, value| - node(name, ref) do - shape(location_name(key_ref, 'key'), key_ref, key) - shape(location_name(value_ref, 'value'), value_ref, value) - end - end + def map(name, shape, values) + key_ref = shape.target.key + value_ref = shape.target.value + if flat?(shape) + resolve_flat(name, shape, values, key_ref, value_ref) else - node(name, ref) do + node(name, shape) do values.each do |key, value| node('entry', MemberShape.new(target: MapShape.new)) do - shape(location_name(key_ref, 'key'), key_ref, key) - shape(location_name(value_ref, 'value'), value_ref, value) + serialize_shape(location_name(key_ref, 'key'), key_ref, key) + serialize_shape(location_name(value_ref, 'value'), value_ref, value) end end end end end - def structure(name, ref, values) - return node(name, ref) if values.empty? + def resolve_flat(name, shape, values, key_ref, value_ref) + values.each do |key, value| + node(name, shape) do + serialize_shape(location_name(key_ref, 'key'), key_ref, key) + serialize_shape(location_name(value_ref, 'value'), value_ref, value) + end + end + end + + def structure(name, shape, values) + return node(name, shape) if values.empty? - node(name, ref, structure_attrs(ref, values)) do - ref.target.members.each do |member_name, member_ref| + node(name, shape, structure_attrs(shape, values)) do + shape.target.members.each do |member_name, member_shape| next if values[member_name].nil? - next if xml_attribute?(member_ref) + next if xml_attribute?(member_shape) - shape(location_name(member_ref, member_ref.location_name), member_ref, values[member_name]) + serialize_shape(location_name(member_shape, member_shape.location_name), member_shape, values[member_name]) end end end - def structure_attrs(ref, values) - ref.target.members.each_with_object({}) do |(member_name, member_ref), attrs| - if xml_attribute?(member_ref) && values.key?(member_name) - attrs[location_name(member_ref, member_ref.location_name)] = values[member_name] + def structure_attrs(shape, values) + shape.target.members.each_with_object({}) do |(member_name, member_shape), attrs| + if xml_attribute?(member_shape) && values.key?(member_name) + attrs[location_name(member_shape, member_shape.location_name)] = values[member_name] end end end - def timestamp(ref, value) + def timestamp(shape, value) trait = 'smithy.api#timestampFormat' - case ref.traits[trait] || ref.target.traits[trait] + case shape.traits[trait] || shape.target.traits[trait] when 'epoch-seconds' then value.to_i.to_s when 'http-date' then value.utc.httpdate else @@ -108,33 +111,33 @@ def timestamp(ref, value) end end - def union(name, ref, values) # rubocop:disable Metrics/AbcSize - return node(name, ref) if values.empty? + def union(name, shape, values) # rubocop:disable Metrics/AbcSize + return node(name, shape) if values.empty? - node(name, ref, structure_attrs(ref, values)) do + node(name, shape, structure_attrs(shape, values)) do if values.is_a?(Schema::Union) - _name, member_ref = ref.target.member_by_type(values.class) - shape(location_name(member_ref, member_ref.location_name), member_ref, values.value) + _name, member_shape = shape.target.member_by_type(values.class) + serialize_shape(location_name(member_shape, member_shape.location_name), member_shape, values.value) else key, value = values.first - if ref.target.member?(key) - member_ref = ref.target.member(key) - shape(location_name(member_ref, member_ref.location_name), member_ref, value) + if shape.target.member?(key) + member_shape = shape.target.member(key) + serialize_shape(location_name(member_shape, member_shape.location_name), member_shape, value) end end end end - def location_name(ref, default = nil) - ref.traits['smithy.api#xmlName'] || default + def location_name(shape, default = nil) + shape.traits['smithy.api#xmlName'] || default end - def flat?(ref) - ref.traits.key?('smithy.api#xmlFlattened') + def flat?(shape) + shape.traits.key?('smithy.api#xmlFlattened') end - def xml_attribute?(ref) - ref.traits.key?('smithy.api#xmlAttribute') + def xml_attribute?(shape) + shape.traits.key?('smithy.api#xmlAttribute') end # The `args` list may contain: @@ -147,16 +150,16 @@ def xml_attribute?(ref) # Pass a block if you want to nest XML nodes inside. When doing this, # you may *not* pass a value to the `args` list. # - def node(name, ref, *args, &) + def node(name, shape, *args, &) attrs = args.last.is_a?(Hash) ? args.pop : {} - attrs = shape_attrs(ref).merge(attrs) + attrs = shape_attrs(shape).merge(attrs) args << attrs @builder.node(name, *args, &) end - def shape_attrs(ref) + def shape_attrs(shape) trait = 'smithy.api#xmlNamespace' - xmlns = ref.traits[trait] || ref.target.traits[trait] + xmlns = shape.traits[trait] || shape.target.traits[trait] return {} unless xmlns if (prefix = xmlns['prefix']) diff --git a/gems/smithy-xml/lib/smithy-xml/doc_builder.rb b/gems/smithy-xml/lib/smithy-xml/doc_builder.rb index 0431dad29..e527a65db 100644 --- a/gems/smithy-xml/lib/smithy-xml/doc_builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/doc_builder.rb @@ -4,18 +4,18 @@ module Smithy module Xml # @api private class DocBuilder - # @option options [#<<] :target ('') + # @option options [#<<] :output ('') # @option options [String] :pad ('') # @option options [String] :indent ('') def initialize(options = {}) - # The String has to be mutable because @target implements `<<` method. - @target = options[:target] || String.new + # The String has to be mutable because @output implements `<<` method. + @output = options[:output] || String.new @indent = options[:indent] || '' @pad = options[:pad] || '' @end_of_line = @indent == '' ? '' : "\n" end - attr_reader :target + attr_reader :output # @overload node(name, attributes = {}) # Adds a self closing element without any content. @@ -33,15 +33,15 @@ def initialize(options = {}) def node(name, *args, &) # rubocop:disable Metrics/AbcSize attrs = args.last.is_a?(Hash) ? args.pop : {} if block_given? - @target << open_el(name, attrs) - @target << @end_of_line + @output << open_el(name, attrs) + @output << @end_of_line increase_pad(&) - @target << @pad - @target << close_el(name) + @output << @pad + @output << close_el(name) elsif args.empty? - @target << empty_element(name, attrs) + @output << empty_element(name, attrs) else - @target << inline_element(name, args.first, attrs) + @output << inline_element(name, args.first, attrs) end end diff --git a/gems/smithy-xml/lib/smithy-xml/parser.rb b/gems/smithy-xml/lib/smithy-xml/parser.rb index a48ddbc8f..1ad19893b 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser.rb @@ -22,14 +22,13 @@ def initialize(options = {}) # The purpose of the unhandled callback block is to allow callers to access values # such as a request ID that are part of the XML body but not part of modeling. # - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [String] bytes - # @param [Object, nil] target (nil) + # @param [Object, nil] result (nil) # @return [Object] - def parse(shape, bytes, target = nil, &) - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) + def parse(shape, bytes, result = nil, &) bytes = '' if bytes.nil? || bytes.empty? - stack = Stack.new(ref, target, &) + stack = Stack.new(shape, result, &) @engine.new(stack).parse(bytes.to_s) stack.result end diff --git a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb index da8d4dd18..b2a3709fe 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb @@ -12,10 +12,10 @@ class Frame include Smithy::Schema::Shapes class << self - def new(path, parent, ref, result = nil) + def new(path, parent, shape, result = nil) if self == Frame - frame = frame_class(ref).allocate - frame.send(:initialize, path, parent, ref, result) + frame = frame_class(shape).allocate + frame.send(:initialize, path, parent, shape, result) frame else super @@ -24,11 +24,11 @@ def new(path, parent, ref, result = nil) private - def frame_class(ref) - klass = FRAME_CLASSES[ref.target.class] - if klass == ListFrame && ref.traits.key?('smithy.api#xmlFlattened') + def frame_class(shape) + klass = FRAME_CLASSES[shape.target.class] + if klass == ListFrame && shape.traits.key?('smithy.api#xmlFlattened') FlatListFrame - elsif klass == MapFrame && ref.traits.key?('smithy.api#xmlFlattened') + elsif klass == MapFrame && shape.traits.key?('smithy.api#xmlFlattened') MapEntryFrame else klass @@ -36,15 +36,15 @@ def frame_class(ref) end end - def initialize(path, parent, ref, result) + def initialize(path, parent, shape, result) @path = path @parent = parent - @ref = ref + @shape = shape @result = result @text = [] end - attr_reader :parent, :ref, :result + attr_reader :parent, :shape, :result def append_text(value) @text << value @@ -103,7 +103,7 @@ def result class FlatListFrame < Frame def initialize(xml_name, *args) super - @member = Frame.new(xml_name, self, @ref.target.member) + @member = Frame.new(xml_name, self, @shape.target.member) end def result @@ -147,7 +147,7 @@ class ListFrame < Frame def initialize(*args) super @result = [] - @member_xml_name = @ref.target.member.traits['smithy.api#xmlName'] || 'member' + @member_xml_name = @shape.target.member.traits['smithy.api#xmlName'] || 'member' end def child_frame(xml_name) @@ -155,7 +155,7 @@ def child_frame(xml_name) raise NotImplementedError, "Expected XML name '#{@member_xml_name}' for ListFrame, got '#{xml_name}'" end - Frame.new(xml_name, self, @ref.target.member) + Frame.new(xml_name, self, @shape.target.member) end def consume_child_frame(child) @@ -167,10 +167,10 @@ def consume_child_frame(child) class MapEntryFrame < Frame def initialize(xml_name, *args) super - @key_name = @ref.target.key.traits['smithy.api#xmlName'] || 'key' - @key = Frame.new(xml_name, self, @ref.target.key) - @value_name = @ref.target.value.traits['smithy.api#xmlName'] || 'value' - @value = Frame.new(xml_name, self, @ref.target.value) + @key_name = @shape.target.key.traits['smithy.api#xmlName'] || 'key' + @key = Frame.new(xml_name, self, @shape.target.key) + @value_name = @shape.target.value.traits['smithy.api#xmlName'] || 'value' + @value = Frame.new(xml_name, self, @shape.target.value) end # @return [StringFrame] @@ -202,7 +202,7 @@ def child_frame(xml_name) raise NotImplementedError, "Expected XML name 'entry' for MapFrame, got '#{xml_name}'" end - MapEntryFrame.new(xml_name, self, @ref) + MapEntryFrame.new(xml_name, self, @shape) end def consume_child_frame(child) @@ -231,19 +231,19 @@ def result # @api private class StructureFrame < Frame - def initialize(xml_name, parent, ref, result = nil) + def initialize(xml_name, parent, shape, result = nil) super @members = {} - ref.target.members.each do |member_name, member_ref| + shape.target.members.each do |member_name, member_ref| @members[xml_name(member_ref)] = { name: member_name, ref: member_ref } end - @result ||= ref.target.type.new + @result ||= shape.target.type.new end def child_frame(xml_name) if (@member = @members[xml_name]) Frame.new(xml_name, self, @member[:ref]) - elsif @ref.target.is_a?(UnionShape) + elsif @shape.target.is_a?(UnionShape) UnknownMemberFrame.new(xml_name, self, nil, @result) else NullFrame.new(xml_name, self) @@ -267,8 +267,8 @@ def consume_child_frame(child) # rubocop:disable Metrics/AbcSize private - def xml_name(ref) - ref.traits['smithy.api#xmlName'] || ref.location_name + def xml_name(shape) + shape.traits['smithy.api#xmlName'] || shape.location_name end end diff --git a/gems/smithy-xml/lib/smithy-xml/parser/stack.rb b/gems/smithy-xml/lib/smithy-xml/parser/stack.rb index 00d1a8601..97f45614b 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/stack.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/stack.rb @@ -7,8 +7,8 @@ module Xml class Parser # @api private class Stack - def initialize(ref, result = nil, &unhandled_callback) - @ref = ref + def initialize(shape, result = nil, &unhandled_callback) + @shape = shape @result = result @unhandled_callback = unhandled_callback @frame = self @@ -51,7 +51,7 @@ def error(msg, line = nil, column = nil) end def child_frame(name) - Frame.new(name, self, @ref, @result) + Frame.new(name, self, @shape, @result) end def consume_child_frame(frame) From 1433a9316993242e8d2ab97f047b184ea0b25d41 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 16:59:00 -0700 Subject: [PATCH 11/23] Follow-up fixes --- gems/smithy-schema/lib/smithy-schema/shapes.rb | 6 ++++-- gems/smithy-xml/lib/smithy-xml/parser/frame.rb | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/gems/smithy-schema/lib/smithy-schema/shapes.rb b/gems/smithy-schema/lib/smithy-schema/shapes.rb index 5431260f3..8c3a11c4c 100644 --- a/gems/smithy-schema/lib/smithy-schema/shapes.rb +++ b/gems/smithy-schema/lib/smithy-schema/shapes.rb @@ -14,6 +14,8 @@ def initialize(options = {}) @target = self end + # @return [Shape] Returns self, so a bare shape can be traversed + # uniformly with a {MemberShape} via +#target+. attr_reader :target # @return [String] Absolute shape ID from model @@ -126,10 +128,10 @@ def initialize(options = {}) # @return [String] attr_accessor :name - # @return [MemberShape] + # @return [Shape] attr_accessor :input - # @return [MemberShape] + # @return [Shape] attr_accessor :output # @return [Array] diff --git a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb index b2a3709fe..20ce64a74 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/frame.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/frame.rb @@ -234,15 +234,15 @@ class StructureFrame < Frame def initialize(xml_name, parent, shape, result = nil) super @members = {} - shape.target.members.each do |member_name, member_ref| - @members[xml_name(member_ref)] = { name: member_name, ref: member_ref } + shape.target.members.each do |member_name, member_shape| + @members[xml_name(member_shape)] = { name: member_name, shape: member_shape } end @result ||= shape.target.type.new end def child_frame(xml_name) if (@member = @members[xml_name]) - Frame.new(xml_name, self, @member[:ref]) + Frame.new(xml_name, self, @member[:shape]) elsif @shape.target.is_a?(UnionShape) UnknownMemberFrame.new(xml_name, self, nil, @result) else From 80d31005d4dd851b87f6d292c2867c856410fc8c Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 17:01:51 -0700 Subject: [PATCH 12/23] Fix RBS --- gems/smithy-schema/sig/smithy-schema/shapes.rbs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gems/smithy-schema/sig/smithy-schema/shapes.rbs b/gems/smithy-schema/sig/smithy-schema/shapes.rbs index d1fe31fc9..f28c3b7e9 100644 --- a/gems/smithy-schema/sig/smithy-schema/shapes.rbs +++ b/gems/smithy-schema/sig/smithy-schema/shapes.rbs @@ -4,6 +4,7 @@ module Smithy class Shape def initialize: (?Hash[Symbol, untyped]) ?{ (self) -> void } -> void + attr_reader target: Shape attr_accessor id: String attr_accessor name: String attr_accessor traits: Hash[String, untyped] @@ -33,8 +34,8 @@ module Smithy class OperationShape < Shape attr_accessor name: String - attr_accessor input: MemberShape - attr_accessor output: MemberShape + attr_accessor input: Shape + attr_accessor output: Shape attr_accessor errors: Array[MemberShape] end From a64909f515da7092dd3393cd578225d6c160cee7 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 17:33:12 -0700 Subject: [PATCH 13/23] Rename codec dispatch methods --- gems/smithy-cbor/lib/smithy-cbor/builder.rb | 14 +++++++------- gems/smithy-cbor/lib/smithy-cbor/parser.rb | 12 ++++++------ gems/smithy-json/lib/smithy-json/builder.rb | 14 +++++++------- gems/smithy-json/lib/smithy-json/parser.rb | 12 ++++++------ gems/smithy-xml/lib/smithy-xml/builder.rb | 20 ++++++++++---------- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/gems/smithy-cbor/lib/smithy-cbor/builder.rb b/gems/smithy-cbor/lib/smithy-cbor/builder.rb index e2b9b46b1..08c427d87 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/builder.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/builder.rb @@ -15,12 +15,12 @@ def initialize(options = {}) def build(shape, data) return if shape.target == Prelude::Unit - Cbor.encode(serialize_shape(shape, data)) + Cbor.encode(build_shape(shape, data)) end private - def serialize_shape(shape, value) + def build_shape(shape, value) case shape.target when BlobShape then blob(value) when ListShape then list(shape, value) @@ -39,7 +39,7 @@ def list(shape, values) return if values.nil? values.collect do |value| - serialize_shape(shape.target.member, value) + build_shape(shape.target.member, value) end end @@ -47,7 +47,7 @@ def map(shape, values) return if values.nil? values.each.with_object({}) do |(key, value), data| - data[key] = serialize_shape(shape.target.value, value) + data[key] = build_shape(shape.target.value, value) end end @@ -58,7 +58,7 @@ def structure(shape, values) value = values[member_name] next if value.nil? - data[member_shape.location_name] = serialize_shape(member_shape, value) + data[member_shape.location_name] = build_shape(member_shape, value) end end @@ -68,12 +68,12 @@ def union(shape, values) # rubocop:disable Metrics/AbcSize data = {} if values.is_a?(Schema::Union) _name, member_shape = shape.target.member_by_type(values.class) - data[member_shape.location_name] = serialize_shape(member_shape, values.value) + data[member_shape.location_name] = build_shape(member_shape, values.value) else key, value = values.first if shape.target.member?(key) member_shape = shape.target.member(key) - data[member_shape.location_name] = serialize_shape(member_shape, value) + data[member_shape.location_name] = build_shape(member_shape, value) end end data diff --git a/gems/smithy-cbor/lib/smithy-cbor/parser.rb b/gems/smithy-cbor/lib/smithy-cbor/parser.rb index 1342df72a..35d4fc78e 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/parser.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/parser.rb @@ -15,12 +15,12 @@ def initialize(options = {}) def parse(shape, bytes, result = nil) return {} if bytes.empty? - deserialize_shape(shape, Cbor.decode(bytes), result) + parse_shape(shape, Cbor.decode(bytes), result) end private - def deserialize_shape(shape, value, result = nil) + def parse_shape(shape, value, result = nil) return nil if value.nil? case shape.target @@ -37,7 +37,7 @@ def list(shape, values, result = nil) values.each do |value| next if value.nil? && !sparse?(shape.target) - result << deserialize_shape(shape.target.member, value) + result << parse_shape(shape.target.member, value) end result end @@ -47,7 +47,7 @@ def map(shape, values, result = nil) values.each do |key, value| next if value.nil? && !sparse?(shape.target) - result[key] = deserialize_shape(shape.target.value, value) + result[key] = parse_shape(shape.target.value, value) end result end @@ -56,7 +56,7 @@ def structure(shape, values, result = nil) result = shape.target.type.new if result.nil? shape.target.members.each do |member_name, member_shape| value = values[member_shape.location_name] - result[member_name] = deserialize_shape(member_shape, value) unless value.nil? + result[member_name] = parse_shape(member_shape, value) unless value.nil? end result end @@ -67,7 +67,7 @@ def union(shape, values, result = nil) # rubocop:disable Metrics/AbcSize next if value.nil? result = shape.target.member_type(member_name) if result.nil? - return result.new(member_name => deserialize_shape(member_shape, value)) + return result.new(member_name => parse_shape(member_shape, value)) end values.delete('__type') diff --git a/gems/smithy-json/lib/smithy-json/builder.rb b/gems/smithy-json/lib/smithy-json/builder.rb index 9095fe04f..7edf9677a 100644 --- a/gems/smithy-json/lib/smithy-json/builder.rb +++ b/gems/smithy-json/lib/smithy-json/builder.rb @@ -13,12 +13,12 @@ def initialize(options = {}) end def build(shape, data) - Smithy::Json.dump(serialize_shape(shape, data)) + Smithy::Json.dump(build_shape(shape, data)) end private - def serialize_shape(shape, value) # rubocop:disable Metrics/CyclomaticComplexity + def build_shape(shape, value) # rubocop:disable Metrics/CyclomaticComplexity case shape.target when BlobShape then blob(value) when FloatShape then float(value) @@ -51,7 +51,7 @@ def list(shape, values) return if values.nil? values.collect do |value| - serialize_shape(shape.target.member, value) + build_shape(shape.target.member, value) end end @@ -59,7 +59,7 @@ def map(shape, values) return if values.nil? values.each.with_object({}) do |(key, value), data| - data[key] = serialize_shape(shape.target.value, value) + data[key] = build_shape(shape.target.value, value) end end @@ -68,7 +68,7 @@ def structure(shape, values) shape.target.members.each_with_object({}) do |(member_name, member_shape), data| value = values[member_name] - data[location_name(member_shape)] = serialize_shape(member_shape, value) unless value.nil? + data[location_name(member_shape)] = build_shape(member_shape, value) unless value.nil? end end @@ -89,12 +89,12 @@ def union(shape, values) # rubocop:disable Metrics/AbcSize data = {} if values.is_a?(Schema::Union) _name, member_ref = shape.target.member_by_type(values.class) - data[location_name(member_ref)] = serialize_shape(member_ref, values.value) + data[location_name(member_ref)] = build_shape(member_ref, values.value) else key, value = values.first if shape.target.member?(key) member_ref = shape.target.member(key) - data[location_name(member_ref)] = serialize_shape(member_ref, value) + data[location_name(member_ref)] = build_shape(member_ref, value) end end data diff --git a/gems/smithy-json/lib/smithy-json/parser.rb b/gems/smithy-json/lib/smithy-json/parser.rb index 5aa5b893c..e2a251610 100644 --- a/gems/smithy-json/lib/smithy-json/parser.rb +++ b/gems/smithy-json/lib/smithy-json/parser.rb @@ -15,12 +15,12 @@ def initialize(options = {}) def parse(shape, bytes, result = nil) return {} if bytes.empty? - deserialize_shape(shape, Smithy::Json.load(bytes), result) + parse_shape(shape, Smithy::Json.load(bytes), result) end private - def deserialize_shape(shape, value, result = nil) # rubocop:disable Metrics/CyclomaticComplexity + def parse_shape(shape, value, result = nil) # rubocop:disable Metrics/CyclomaticComplexity case shape.target when BlobShape then Base64.decode64(value) when FloatShape then float(value) @@ -49,7 +49,7 @@ def list(shape, values, result = nil) values.each do |value| next if value.nil? && !sparse?(shape.target) - result << deserialize_shape(shape.target.member, value) + result << parse_shape(shape.target.member, value) end result end @@ -59,7 +59,7 @@ def map(shape, values, result = nil) values.each do |key, value| next if value.nil? && !sparse?(shape.target) - result[key] = deserialize_shape(shape.target.value, value) + result[key] = parse_shape(shape.target.value, value) end result end @@ -70,7 +70,7 @@ def structure(shape, values, result = nil) result = shape.target.type.new if result.nil? shape.target.members.each do |member_name, member_shape| value = values[location_name(member_shape)] - result[member_name] = deserialize_shape(member_shape, value) unless value.nil? + result[member_name] = parse_shape(member_shape, value) unless value.nil? end result end @@ -94,7 +94,7 @@ def union(shape, values, result = nil) # rubocop:disable Metrics/AbcSize next if value.nil? result = shape.target.member_type(member_name) if result.nil? - return result.new(member_name => deserialize_shape(member_shape, value)) + return result.new(member_name => parse_shape(member_shape, value)) end values.delete('__type') diff --git a/gems/smithy-xml/lib/smithy-xml/builder.rb b/gems/smithy-xml/lib/smithy-xml/builder.rb index 60de2b659..83d1f87a4 100644 --- a/gems/smithy-xml/lib/smithy-xml/builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/builder.rb @@ -22,7 +22,7 @@ def build(shape, data, output = nil) private - def serialize_shape(name, shape, value) + def build_shape(name, shape, value) case shape.target when BlobShape then node(name, shape, blob(value)) when ListShape then list(name, shape, value) @@ -42,12 +42,12 @@ def list(name, shape, values) member_shape = shape.target.member if flat?(shape) values.each do |value| - serialize_shape(name, member_shape, value) + build_shape(name, member_shape, value) end else node(name, shape) do values.each do |value| - serialize_shape(location_name(member_shape, 'member'), shape.target.member, value) + build_shape(location_name(member_shape, 'member'), shape.target.member, value) end end end @@ -62,8 +62,8 @@ def map(name, shape, values) node(name, shape) do values.each do |key, value| node('entry', MemberShape.new(target: MapShape.new)) do - serialize_shape(location_name(key_ref, 'key'), key_ref, key) - serialize_shape(location_name(value_ref, 'value'), value_ref, value) + build_shape(location_name(key_ref, 'key'), key_ref, key) + build_shape(location_name(value_ref, 'value'), value_ref, value) end end end @@ -73,8 +73,8 @@ def map(name, shape, values) def resolve_flat(name, shape, values, key_ref, value_ref) values.each do |key, value| node(name, shape) do - serialize_shape(location_name(key_ref, 'key'), key_ref, key) - serialize_shape(location_name(value_ref, 'value'), value_ref, value) + build_shape(location_name(key_ref, 'key'), key_ref, key) + build_shape(location_name(value_ref, 'value'), value_ref, value) end end end @@ -87,7 +87,7 @@ def structure(name, shape, values) next if values[member_name].nil? next if xml_attribute?(member_shape) - serialize_shape(location_name(member_shape, member_shape.location_name), member_shape, values[member_name]) + build_shape(location_name(member_shape, member_shape.location_name), member_shape, values[member_name]) end end end @@ -117,12 +117,12 @@ def union(name, shape, values) # rubocop:disable Metrics/AbcSize node(name, shape, structure_attrs(shape, values)) do if values.is_a?(Schema::Union) _name, member_shape = shape.target.member_by_type(values.class) - serialize_shape(location_name(member_shape, member_shape.location_name), member_shape, values.value) + build_shape(location_name(member_shape, member_shape.location_name), member_shape, values.value) else key, value = values.first if shape.target.member?(key) member_shape = shape.target.member(key) - serialize_shape(location_name(member_shape, member_shape.location_name), member_shape, value) + build_shape(location_name(member_shape, member_shape.location_name), member_shape, value) end end end From cab41be43ce18b8c866c3f9d170262518d5f3a4f Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 17:33:18 -0700 Subject: [PATCH 14/23] Update codec documentation --- gems/smithy-cbor/lib/smithy-cbor/codec.rb | 10 +++++----- gems/smithy-json/lib/smithy-json/codec.rb | 10 +++++----- gems/smithy-xml/lib/smithy-xml/codec.rb | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/gems/smithy-cbor/lib/smithy-cbor/codec.rb b/gems/smithy-cbor/lib/smithy-cbor/codec.rb index 1931e6c64..2c95508e0 100644 --- a/gems/smithy-cbor/lib/smithy-cbor/codec.rb +++ b/gems/smithy-cbor/lib/smithy-cbor/codec.rb @@ -9,19 +9,19 @@ def initialize(options = {}) @options = options end - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [Object] data # @return [String, nil] def build(shape, data) Builder.new(@options).build(shape, data) end - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [String] bytes - # @param [Object, nil] target (nil) + # @param [Object, nil] result (nil) # @return [Object, nil] - def parse(shape, bytes, target = nil) - Parser.new(@options).parse(shape, bytes, target) + def parse(shape, bytes, result = nil) + Parser.new(@options).parse(shape, bytes, result) end end end diff --git a/gems/smithy-json/lib/smithy-json/codec.rb b/gems/smithy-json/lib/smithy-json/codec.rb index c808dfc4a..0ad2c6d3c 100644 --- a/gems/smithy-json/lib/smithy-json/codec.rb +++ b/gems/smithy-json/lib/smithy-json/codec.rb @@ -9,19 +9,19 @@ def initialize(options = {}) @options = options end - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [Object] data # @return [String, nil] def build(shape, data) Builder.new(@options).build(shape, data) end - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [String] bytes - # @param [Object, nil] target (nil) + # @param [Object, nil] result (nil) # @return [Object, nil] - def parse(shape, bytes, target = nil) - Parser.new(@options).parse(shape, bytes, target) + def parse(shape, bytes, result = nil) + Parser.new(@options).parse(shape, bytes, result) end end end diff --git a/gems/smithy-xml/lib/smithy-xml/codec.rb b/gems/smithy-xml/lib/smithy-xml/codec.rb index aede627ed..23ae8d86e 100644 --- a/gems/smithy-xml/lib/smithy-xml/codec.rb +++ b/gems/smithy-xml/lib/smithy-xml/codec.rb @@ -9,20 +9,20 @@ def initialize(options = {}) @options = options end - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [Object] data - # @param [String, nil] target (nil) + # @param [Array, nil] output (nil) # @return [String, nil] - def build(shape, data, target = nil) - Builder.new(@options).build(shape, data, target) + def build(shape, data, output = nil) + Builder.new(@options).build(shape, data, output) end - # @param [MemberShape, Shape] shape + # @param [Shape] shape # @param [String] bytes - # @param [Object, nil] target (nil) + # @param [Object, nil] result (nil) # @return [Object, nil] - def parse(shape, bytes, target = nil) - Parser.new(@options).parse(shape, bytes, target) + def parse(shape, bytes, result = nil) + Parser.new(@options).parse(shape, bytes, result) end end end From 74ee26dd7409be1d045a1bb0d3bc1efed4c08d3d Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 17:33:34 -0700 Subject: [PATCH 15/23] Unwrap operation errors --- .../lib/smithy-client/plugins/transfer_encoding.rb | 2 +- .../lib/smithy-client/rpc_v2_cbor/error_handler.rb | 8 ++++---- gems/smithy/lib/smithy/templates/client/schema.erb | 2 +- gems/smithy/lib/smithy/views/client/schema.rb | 2 +- projections/weather/lib/weather/schema.rb | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb b/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb index 823bcdca8..389ec9486 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb @@ -29,7 +29,7 @@ def apply_transfer_encoding(context, payload) end def streaming_member_ref(context) - context.operation.input.target.members.detect do |_, ref| + context.operation.input.members.detect do |_, ref| ref.target.traits.key?('smithy.api#streaming') end&.last end diff --git a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb index 1da335e68..af1ceda03 100644 --- a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb +++ b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/error_handler.rb @@ -41,16 +41,16 @@ def extract_error(body, context) code = error_code(context, data) data = parse_error_data(context, body, code) [code, data] - rescue Cbor::Error + rescue Cbor::ParseError [http_status_error_code(context), Schema::EmptyStructure.new] end def parse_error_data(context, body, code) data = Schema::EmptyStructure.new - context.operation.errors.each do |ref| - next unless ref.target.name == code + context.operation.errors.each do |err_shape| + next unless err_shape.name == code - data = Cbor::Parser.new.parse(ref, body, ref.target.type.new) + data = Cbor::Parser.new.parse(err_shape, body, err_shape.type.new) end data end diff --git a/gems/smithy/lib/smithy/templates/client/schema.erb b/gems/smithy/lib/smithy/templates/client/schema.erb index e4dd12b03..d58a65ea3 100644 --- a/gems/smithy/lib/smithy/templates/client/schema.erb +++ b/gems/smithy/lib/smithy/templates/client/schema.erb @@ -53,7 +53,7 @@ module <%= module_name %> operation.input = <%= shape.input %> operation.output = <%= shape.output %> <% shape.errors.each do |error| -%> - operation.errors << <%= error.initializer %> + operation.errors << <%= error %> <% end -%> operation.traits = <%= shape.traits %> <% if !schema_gem? && shape.paginated? -%> diff --git a/gems/smithy/lib/smithy/views/client/schema.rb b/gems/smithy/lib/smithy/views/client/schema.rb index 56ff386d4..2e286949f 100644 --- a/gems/smithy/lib/smithy/views/client/schema.rb +++ b/gems/smithy/lib/smithy/views/client/schema.rb @@ -170,7 +170,7 @@ def paginator def build_errors(errors) errors = Set.new(@service.fetch('errors', [])).merge(errors) - errors.map { |error| MemberShape.new(@service, nil, error) } + errors.map { |error| shape_name_from_id(error['target']) } end end diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index 7eff0acd0..2c0934b1f 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -56,7 +56,7 @@ module Schema operation.name = "GetCity" operation.input = GetCityInput operation.output = GetCityOutput - operation.errors << ::Smithy::Schema::Shapes::MemberShape.new(target: NoSuchResource) + operation.errors << NoSuchResource operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_current_time, ::Smithy::Schema::Shapes::OperationShape.new do |operation| From de790970fa03a0345d550c6cb9bd99c5dd183811 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Thu, 4 Jun 2026 17:33:42 -0700 Subject: [PATCH 16/23] Update RBS for unwrapped shapes --- gems/smithy-schema/lib/smithy-schema/shapes.rb | 2 +- gems/smithy-schema/sig/smithy-schema/shapes.rbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gems/smithy-schema/lib/smithy-schema/shapes.rb b/gems/smithy-schema/lib/smithy-schema/shapes.rb index 8c3a11c4c..9b832132c 100644 --- a/gems/smithy-schema/lib/smithy-schema/shapes.rb +++ b/gems/smithy-schema/lib/smithy-schema/shapes.rb @@ -134,7 +134,7 @@ def initialize(options = {}) # @return [Shape] attr_accessor :output - # @return [Array] + # @return [Array] attr_accessor :errors end diff --git a/gems/smithy-schema/sig/smithy-schema/shapes.rbs b/gems/smithy-schema/sig/smithy-schema/shapes.rbs index f28c3b7e9..ea7a332a4 100644 --- a/gems/smithy-schema/sig/smithy-schema/shapes.rbs +++ b/gems/smithy-schema/sig/smithy-schema/shapes.rbs @@ -36,7 +36,7 @@ module Smithy attr_accessor name: String attr_accessor input: Shape attr_accessor output: Shape - attr_accessor errors: Array[MemberShape] + attr_accessor errors: Array[Shape] end class BigDecimalShape < Shape From b2fee547c12ba0fb5f3ee4e64699cc5cb82004ce Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Fri, 5 Jun 2026 08:16:58 -0700 Subject: [PATCH 17/23] Clean up codec RBS --- gems/smithy-cbor/sig/smithy-cbor/codec.rbs | 4 ++-- gems/smithy-json/sig/smithy-json/codec.rbs | 4 ++-- gems/smithy-xml/sig/smithy-xml/codec.rbs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gems/smithy-cbor/sig/smithy-cbor/codec.rbs b/gems/smithy-cbor/sig/smithy-cbor/codec.rbs index 2b6341287..261cc3410 100644 --- a/gems/smithy-cbor/sig/smithy-cbor/codec.rbs +++ b/gems/smithy-cbor/sig/smithy-cbor/codec.rbs @@ -2,8 +2,8 @@ module Smithy module Cbor module Codec def initialize: (?Hash[Symbol, untyped] options) -> void - def build: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, Object data) -> (nil | String) - def parse: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, String bytes, ?Object ?target) -> Object? + def build: (Schema::Shapes::Shape shape, Object data) -> (nil | String) + def parse: (Schema::Shapes::Shape shape, String bytes, ?Object ?result) -> Object? end end end \ No newline at end of file diff --git a/gems/smithy-json/sig/smithy-json/codec.rbs b/gems/smithy-json/sig/smithy-json/codec.rbs index 5d55bff0f..9a6249ca7 100644 --- a/gems/smithy-json/sig/smithy-json/codec.rbs +++ b/gems/smithy-json/sig/smithy-json/codec.rbs @@ -2,8 +2,8 @@ module Smithy module Json class Codec def initialize: (?Hash[Symbol, untyped] options) -> void - def build: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, Object data) -> (nil | String) - def parse: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, String bytes, ?Object ?target) -> Object? + def build: (Schema::Shapes::Shape shape, Object data) -> (nil | String) + def parse: (Schema::Shapes::Shape shape, String bytes, ?Object ?result) -> Object? end end end \ No newline at end of file diff --git a/gems/smithy-xml/sig/smithy-xml/codec.rbs b/gems/smithy-xml/sig/smithy-xml/codec.rbs index 5768e40d6..638f8bbca 100644 --- a/gems/smithy-xml/sig/smithy-xml/codec.rbs +++ b/gems/smithy-xml/sig/smithy-xml/codec.rbs @@ -1,8 +1,8 @@ module Smithy module Xml class Codec - def build: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, Object data) -> (nil | String) - def parse: (Schema::Shapes::Shape | Schema::Shapes::MemberShape shape, String bytes, ?Object ?target) -> Object? + def build: (Schema::Shapes::Shape shape, Object data, ?Array? output) -> (nil | String) + def parse: (Schema::Shapes::Shape shape, String bytes, ?Object ?result) -> Object? end end end \ No newline at end of file From bfc5302710e929b2d19d56bc2959647ab37bf418 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Fri, 5 Jun 2026 08:49:59 -0700 Subject: [PATCH 18/23] Update plugin and handler shape references --- .../lib/smithy-client/plugins/host_prefix.rb | 6 +-- .../plugins/idempotency_token.rb | 4 +- .../plugins/request_compression.rb | 6 +-- .../plugins/transfer_encoding.rb | 18 ++++---- .../lib/smithy-client/rpc_v2_cbor/handler.rb | 8 ++-- .../smithy-client/stubbing/data_applicator.rb | 36 +++++++-------- .../lib/smithy-client/stubbing/empty_stub.rb | 44 +++++++++---------- .../plugins/transfer_encoding_spec.rb | 4 +- .../spec/smithy-xml/builder_spec.rb | 4 +- 9 files changed, 65 insertions(+), 65 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb b/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb index 769cae103..536f5932d 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/host_prefix.rb @@ -51,9 +51,9 @@ def apply_host_prefix(context, host_prefix) def label_value(input, label, params) name = nil - input.target.members.each do |member_name, member_ref| - next unless member_ref.traits.key?('smithy.api#hostLabel') - next unless member_ref.location_name == label + input.members.each do |member_name, member_shape| + next unless member_shape.traits.key?('smithy.api#hostLabel') + next unless member_shape.location_name == label name = member_name end diff --git a/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb b/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb index bd57b084b..1fc7989f7 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/idempotency_token.rb @@ -21,8 +21,8 @@ def call(context) private def apply_idempotency_token(input, params) - input.target.members.each do |member_name, member_ref| - next unless member_ref.traits.key?('smithy.api#idempotencyToken') + input.members.each do |member_name, member_shape| + next unless member_shape.traits.key?('smithy.api#idempotencyToken') params[member_name] ||= SecureRandom.uuid end diff --git a/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb b/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb index 44ff7e27a..6e4d23573 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/request_compression.rb @@ -92,9 +92,9 @@ def request_encoding_selection(context) end def streaming?(input) - input.target.members.any? do |_, member_ref| - member_ref.target.traits.key?('smithy.api#streaming') && - !member_ref.target.traits.key?('smithy.api#requiresLength') + input.members.any? do |_, member_shape| + member_shape.target.traits.key?('smithy.api#streaming') && + !member_shape.target.traits.key?('smithy.api#requiresLength') end end diff --git a/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb b/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb index 389ec9486..7c34ba8ee 100644 --- a/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb +++ b/gems/smithy-client/lib/smithy-client/plugins/transfer_encoding.rb @@ -11,31 +11,31 @@ class TransferEncoding < Plugin # @api private class Handler < Client::Handler def call(context) - payload_ref = streaming_member_ref(context) + payload_member = streaming_member(context) # Proceed with TE header logic IFF there's a streaming payload. - apply_transfer_encoding(context, payload_ref.target) if payload_ref + apply_transfer_encoding(context, payload_member.target) if payload_member @handler.call(context) end private - def apply_transfer_encoding(context, payload) + def apply_transfer_encoding(context, payload_shape) return if context.http_request.body.respond_to?(:size) - if requires_length?(payload) + if requires_length?(payload_shape) raise Smithy::Client::Errors::MissingContentLength elsif unsigned_payload?(context) context.http_request.headers['Transfer-Encoding'] = 'chunked' end end - def streaming_member_ref(context) - context.operation.input.members.detect do |_, ref| - ref.target.traits.key?('smithy.api#streaming') + def streaming_member(context) + context.operation.input.members.detect do |_, member_shape| + member_shape.target.traits.key?('smithy.api#streaming') end&.last end - def requires_length?(payload) - payload.traits.key?('smithy.api#requiresLength') + def requires_length?(shape) + shape.traits.key?('smithy.api#requiresLength') end def unsigned_payload?(context) diff --git a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb index 8f0f1a49c..8fc724807 100644 --- a/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb +++ b/gems/smithy-client/lib/smithy-client/rpc_v2_cbor/handler.rb @@ -36,7 +36,7 @@ def apply_content_type_header(context) content_type = if event_stream?(input) 'application/vnd.amazon.eventstream' - elsif input.target != Schema::Shapes::Prelude::Unit + elsif input != Schema::Shapes::Prelude::Unit 'application/cbor' end @@ -64,9 +64,9 @@ def apply_url_path(context) base.path += "/service/#{service_name}/operation/#{context.operation.name}" end - def event_stream?(ref) - ref.target.members.each_value do |member_ref| - shape = member_ref.target + def event_stream?(input_shape) + input_shape.members.each_value do |member_shape| + shape = member_shape.target return true if shape.traits.key?('smithy.api#streaming') && shape.is_a?(Schema::Shapes::UnionShape) end false diff --git a/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb b/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb index 2ea15052c..62916a900 100644 --- a/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb +++ b/gems/smithy-client/lib/smithy-client/stubbing/data_applicator.rb @@ -8,50 +8,50 @@ module Stubbing class DataApplicator include Smithy::Schema::Shapes - def initialize(ref) - @ref = ref + def initialize(shape) + @shape = shape end def apply(data, stub) - structure(@ref, data, stub) + structure(@shape, data, stub) end private - def shape(ref, value, stub = nil) - case ref.target - when StructureShape then structure(ref, value, stub) - when ListShape then list(ref, value) - when MapShape then map(ref, value) + def apply_shape(shape, value, stub = nil) + case shape.target + when StructureShape then structure(shape, value, stub) + when ListShape then list(shape, value) + when MapShape then map(shape, value) else value end end - def list(ref, value) + def list(shape, value) return if value.nil? - shape = ref.target + shape = shape.target value.each_with_object([]) do |v, list| - list << shape(shape.member, v) + list << apply_shape(shape.member, v) end end - def map(ref, value) + def map(shape, value) return if value.nil? - shape = ref.target + shape = shape.target value.each_with_object({}) do |(k, v), map| - map[k.to_s] = shape(shape.value, v) + map[k.to_s] = apply_shape(shape.value, v) end end - def structure(ref, data, stub) + def structure(shape, data, stub) return if data.nil? - stub = ref.target.type.new if stub.nil? - shape = ref.target + stub = shape.target.type.new if stub.nil? + shape = shape.target data.each_pair do |key, value| - stub[key] = shape(shape.member(key), value) + stub[key] = apply_shape(shape.member(key), value) end stub end diff --git a/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb b/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb index ed1de27d0..d463ee7a6 100644 --- a/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb +++ b/gems/smithy-client/lib/smithy-client/stubbing/empty_stub.rb @@ -10,53 +10,53 @@ module Stubbing class EmptyStub include Smithy::Schema::Shapes - def initialize(ref) - @ref = ref + def initialize(shape) + @shape = shape end # @return [Schema::Structure, Schema::EmptyStructure] def stub - structure(@ref, []) + structure(@shape, []) end private - def shape(ref, visited) - shape = ref.target - return nil if visited.include?(shape) + def stub_shape(shape, visited) + resolved_shape = shape.target + return nil if visited.include?(resolved_shape) - visited += [shape] + visited += [resolved_shape] - case shape + case resolved_shape when ListShape then [] when MapShape then {} - when StructureShape then structure(ref, visited) - when UnionShape then union(ref, visited) - else scalar(ref) + when StructureShape then structure(shape, visited) + when UnionShape then union(shape, visited) + else scalar(shape) end end - def structure(ref, visited) - shape = ref.target - shape.members.each_with_object(shape.type.new) do |(member_name, member_ref), struct| - struct[member_name] = shape(member_ref, visited) + def structure(shape, visited) + shape = shape.target + shape.members.each_with_object(shape.type.new) do |(member_name, member_shape), struct| + struct[member_name] = stub_shape(member_shape, visited) end end - def union(ref, visited) - shape = ref.target - member_name, member_ref = shape.members.first + def union(shape, visited) + shape = shape.target + member_name, member_shape = shape.members.first return unless member_name - value = shape(member_ref, visited) + value = stub_shape(member_shape, visited) klass = shape.member_type(member_name) klass.new(member_name => value) end - def scalar(ref) - case ref.target + def scalar(shape) + case shape.target when BigDecimalShape then BigDecimal(0) - when BlobShape, EnumShape, StringShape then ref.location_name + when BlobShape, EnumShape, StringShape then shape.location_name when BooleanShape then false when IntegerShape, IntEnumShape then 0 when FloatShape then 0.0 diff --git a/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb b/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb index 664420d2b..15570a688 100644 --- a/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb +++ b/gems/smithy-client/spec/smithy-client/plugins/transfer_encoding_spec.rb @@ -25,8 +25,8 @@ module Plugins let(:streaming_body_plugin) do handler_class = Class.new(Client::Handler) do def call(context) - context.operation.input.target.members.each do |name, ref| - if ref.target.traits.key?('smithy.api#streaming') && context.params[name.to_sym] + context.operation.input.members.each do |name, shape| + if shape.target.traits.key?('smithy.api#streaming') && context.params[name.to_sym] context.http_request.body = context.params[name.to_sym] break end diff --git a/gems/smithy-xml/spec/smithy-xml/builder_spec.rb b/gems/smithy-xml/spec/smithy-xml/builder_spec.rb index bcbec1641..e1f696655 100644 --- a/gems/smithy-xml/spec/smithy-xml/builder_spec.rb +++ b/gems/smithy-xml/spec/smithy-xml/builder_spec.rb @@ -16,8 +16,8 @@ def inline(xml) end it 'returns an empty frame when given a unit shape' do - ref = Schema::Shapes::MemberShape.new(target: Schema::Shapes::Prelude::Unit) - expect(subject.build(ref, '')).to eq('') + shape = Schema::Shapes::MemberShape.new(target: Schema::Shapes::Prelude::Unit) + expect(subject.build(shape, '')).to eq('') end context 'structures' do From d5b50311b348b8eca111724dbf9db8d1c028e246 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Fri, 5 Jun 2026 08:50:19 -0700 Subject: [PATCH 19/23] Update param helpers shape references --- .../lib/smithy-client/default_params.rb | 48 +++++------ .../lib/smithy-client/log_param_filter.rb | 66 +++++++-------- .../lib/smithy-client/param_converter.rb | 54 ++++++------- .../lib/smithy-client/param_validator.rb | 80 +++++++++---------- .../smithy-client/log_param_filter_spec.rb | 4 +- .../smithy-client/param_converter_spec.rb | 4 +- 6 files changed, 128 insertions(+), 128 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/default_params.rb b/gems/smithy-client/lib/smithy-client/default_params.rb index 8d879527b..ea4105b32 100644 --- a/gems/smithy-client/lib/smithy-client/default_params.rb +++ b/gems/smithy-client/lib/smithy-client/default_params.rb @@ -9,70 +9,70 @@ module Client class DefaultParams include Schema::Shapes - def initialize(ref) - @ref = ref + def initialize(shape) + @shape = shape end # @param [Hash] params # @return [Hash] def apply(params) - structure(@ref, params) + structure(@shape, params) end private - def shape(ref, value) - case ref.target - when ListShape then list(ref, value) - when MapShape then map(ref, value) - when StructureShape then structure(ref, value) + def apply_shape(shape, value) + case shape.target + when ListShape then list(shape, value) + when MapShape then map(shape, value) + when StructureShape then structure(shape, value) else value end end - def list(ref, values) + def list(shape, values) return if values.nil? - shape = ref.target + member = shape.target.member values.each do |value| - shape(shape.member, value) + apply_shape(member, value) end values end - def map(ref, values) + def map(shape, values) return if values.nil? - shape = ref.target + value_shape = shape.target.value values.each_pair do |_key, value| - shape(shape.value, value) + apply_shape(value_shape, value) end values end - def structure(ref, values) + def structure(shape, values) return if values.nil? - ref.target.members.each do |member_name, member_ref| + shape.target.members.each do |member_name, member_shape| value = values[member_name] - value ||= default(member_ref) if default?(ref, member_ref.traits) - next if value.nil? && !default?(ref, member_ref.traits) # default can have nil values + value ||= default(member_shape) if default?(shape, member_shape.traits) + next if value.nil? && !default?(shape, member_shape.traits) # default can have nil values - values[member_name] = shape(member_ref, value) + values[member_name] = apply_shape(member_shape, value) end values end - def default?(ref, traits) + def default?(shape, traits) # skip defaults for top level members - return false if ref == @ref + return false if shape == @shape traits.include?('smithy.api#default') && !traits.include?('smithy.api#clientOptional') end - def default(ref) - default = ref.traits['smithy.api#default'] - case ref.target + def default(member_shape) + default = member_shape.traits['smithy.api#default'] + case member_shape.target when BlobShape then Base64.strict_decode64(default) when TimestampShape then timestamp_default(default) else default diff --git a/gems/smithy-client/lib/smithy-client/log_param_filter.rb b/gems/smithy-client/lib/smithy-client/log_param_filter.rb index 551c9e849..d5b0697dc 100644 --- a/gems/smithy-client/lib/smithy-client/log_param_filter.rb +++ b/gems/smithy-client/lib/smithy-client/log_param_filter.rb @@ -10,71 +10,71 @@ def initialize(options = {}) @filter_sensitive_params = options.fetch(:filter_sensitive_params, true) end - def filter(ref, values) - case ref.target - when ListShape then list(ref, values) - when MapShape then map(ref, values) - when StructureShape then structure(ref, values) - when UnionShape then union(ref, values) - else scalar(ref, values) + def filter(shape, values) + case shape.target + when ListShape then list(shape, values) + when MapShape then map(shape, values) + when StructureShape then structure(shape, values) + when UnionShape then union(shape, values) + else scalar(shape, values) end end private - def list(ref, values) - shape = ref.target - return '[FILTERED]' if sensitive?(shape) + def list(shape, values) + target = shape.target + return '[FILTERED]' if sensitive?(target) - member_ref = shape.member - values.collect { |value| filter(member_ref, value) } + member = target.member + values.collect { |value| filter(member, value) } end - def map(ref, values) - shape = ref.target - return '[FILTERED]' if sensitive?(shape) + def map(shape, values) + target = shape.target + return '[FILTERED]' if sensitive?(target) filtered = {} - value_ref = shape.value + value_shape = target.value values.each_pair do |key, value| - filtered[key] = filter(value_ref, value) + filtered[key] = filter(value_shape, value) end filtered end - def scalar(ref, value) - return '[FILTERED]' if sensitive?(ref.target) + def scalar(shape, value) + return '[FILTERED]' if sensitive?(shape.target) value end - def structure(ref, values) - shape = ref.target - return '[FILTERED]' if sensitive?(shape) + def structure(shape, values) + target = shape.target + return '[FILTERED]' if sensitive?(target) filtered = {} values.each_pair do |key, value| - next unless shape.member?(key) + next unless target.member?(key) - member_ref = shape.member(key) - filtered[key] = filter(member_ref, value) + member_shape = target.member(key) + filtered[key] = filter(member_shape, value) end filtered end - def union(ref, values) # rubocop:disable Metrics/AbcSize - shape = ref.target - return '[FILTERED]' if sensitive?(shape) + def union(shape, values) + target = shape.target + return '[FILTERED]' if sensitive?(target) filtered = {} if values.is_a?(Schema::Union) - name, member_ref = ref.target.member_by_type(values.class) - filtered[name] = filter(member_ref, values.value) + name, member_shape = target.member_by_type(values.class) + filtered[name] = filter(member_shape, values.value) else key, value = values.first - if ref.target.member?(key) - member_ref = ref.target.member(key) - filtered[key] = filter(member_ref, value) + if target.member?(key) + member_shape = target.member(key) + filtered[key] = filter(member_shape, value) end end filtered diff --git a/gems/smithy-client/lib/smithy-client/param_converter.rb b/gems/smithy-client/lib/smithy-client/param_converter.rb index a28633225..ea2d71cb3 100644 --- a/gems/smithy-client/lib/smithy-client/param_converter.rb +++ b/gems/smithy-client/lib/smithy-client/param_converter.rb @@ -15,8 +15,8 @@ class ParamConverter @mutex = Mutex.new @converters = Hash.new { |h, k| h[k] = {} } - def initialize(ref) - @ref = ref + def initialize(shape) + @shape = shape @opened_files = [] end @@ -25,7 +25,7 @@ def initialize(ref) # @param [Hash] params # @return [Hash] def convert(params) - structure(@ref, params) + structure(@shape, params) end def close_opened_files @@ -35,58 +35,58 @@ def close_opened_files private - def c(ref, value) - self.class.c(ref.target.class, value, self) + def c(shape, value) + self.class.c(shape.target.class, value, self) end - def shape(ref, value) - case ref.target - when ListShape then list(ref, value) - when MapShape then map(ref, value) - when StructureShape then structure(ref, value) - when UnionShape then union(ref, value) - else c(ref, value) + def convert_shape(shape, value) + case shape.target + when ListShape then list(shape, value) + when MapShape then map(shape, value) + when StructureShape then structure(shape, value) + when UnionShape then union(shape, value) + else c(shape, value) end end - def list(ref, values) - values = c(ref, values) + def list(shape, values) + values = c(shape, values) return values unless values.is_a?(Array) - values.collect { |v| shape(ref.target.member, v) } + values.collect { |v| convert_shape(shape.target.member, v) } end - def map(ref, values) - values = c(ref, values) + def map(shape, values) + values = c(shape, values) return values unless values.is_a?(Hash) values.each.with_object({}) do |(key, value), hash| - hash[shape(ref.target.key, key)] = shape(ref.target.value, value) + hash[convert_shape(shape.target.key, key)] = convert_shape(shape.target.value, value) end end - def structure(ref, values) - values = c(ref, values) + def structure(shape, values) + values = c(shape, values) return values unless values.respond_to?(:each_pair) values.each_pair do |k, v| next if v.nil? - next unless ref.target.member?(k) + next unless shape.target.member?(k) - values[k] = shape(ref.target.member(k), v) + values[k] = convert_shape(shape.target.member(k), v) end values end - def union(ref, values) - values = c(ref, values) + def union(shape, values) + values = c(shape, values) if values.is_a?(Schema::Union) - _name, member_ref = ref.target.member_by_type(values.class) - values = shape(member_ref, values) + _name, member_shape = shape.target.member_by_type(values.class) + values = convert_shape(member_shape, values) elsif values.is_a?(Hash) key, value = values.first - values[key] = shape(ref.target.member(key), value) + values[key] = convert_shape(shape.target.member(key), value) end values end diff --git a/gems/smithy-client/lib/smithy-client/param_validator.rb b/gems/smithy-client/lib/smithy-client/param_validator.rb index 1bede2ab9..b27cb7753 100644 --- a/gems/smithy-client/lib/smithy-client/param_validator.rb +++ b/gems/smithy-client/lib/smithy-client/param_validator.rb @@ -10,8 +10,8 @@ class ParamValidator EXPECTED_GOT = 'expected %s to be %s, got class %s instead.' - def initialize(ref, validate_required: true) - @ref = ref + def initialize(shape, validate_required: true) + @shape = shape @validate_required = validate_required end @@ -21,20 +21,20 @@ def initialize(ref, validate_required: true) # @raise [ArgumentError] if the params are invalid def validate!(params, context: 'params') errors = [] - structure(@ref, params, errors, context) + structure(@shape, params, errors, context) raise ArgumentError, error_messages(errors) unless errors.empty? end private # rubocop:disable Metrics - def shape(ref, value, errors, context) - case ref.target - when StructureShape then structure(ref, value, errors, context) - when ListShape then list(ref, value, errors, context) - when MapShape then map(ref, value, errors, context) - when DocumentShape then document(ref, value, errors, context) - when UnionShape then union(ref, value, errors, context) + def validate_shape(shape, value, errors, context) + case shape.target + when StructureShape then structure(shape, value, errors, context) + when ListShape then list(shape, value, errors, context) + when MapShape then map(shape, value, errors, context) + when DocumentShape then document(shape, value, errors, context) + when UnionShape then union(shape, value, errors, context) when StringShape, EnumShape errors << expected_got(context, 'a String', value) unless value.is_a?(String) when IntegerShape, IntEnumShape @@ -49,7 +49,7 @@ def shape(ref, value, errors, context) errors << expected_got(context, 'true or false', value) unless [true, false].include?(value) when BlobShape unless value.is_a?(String) - if streaming_input?(ref) + if streaming_input?(shape) unless io_like?(value) errors << expected_got( context, @@ -87,7 +87,7 @@ def document(shape, value, errors, context) end end - def list(ref, values, errors, context) + def list(shape, values, errors, context) unless values.is_a?(Array) errors << expected_got(context, 'an Array', values) return @@ -96,47 +96,47 @@ def list(ref, values, errors, context) values.each.with_index do |value, index| next unless value - shape(ref.target.member, value, errors, context + "[#{index}]") + validate_shape(shape.target.member, value, errors, context + "[#{index}]") end end - def map(ref, values, errors, context) + def map(shape, values, errors, context) unless values.is_a?(Hash) errors << expected_got(context, 'a Hash', values) return end values.each do |key, value| - shape(ref.target.key, key, errors, "#{context} #{key.inspect} key") + validate_shape(shape.target.key, key, errors, "#{context} #{key.inspect} key") next unless value - shape(ref.target.value, value, errors, context + "[#{key.inspect}]") + validate_shape(shape.target.value, value, errors, context + "[#{key.inspect}]") end end - def member(ref, name, value, errors, context) - if ref.target.member?(name) - member_ref = ref.target.member(name) - shape(member_ref, value, errors, context + "[#{name.inspect}]") + def member(shape, name, value, errors, context) + if shape.target.member?(name) + member_shape = shape.target.member(name) + validate_shape(member_shape, value, errors, context + "[#{name.inspect}]") else errors << "unexpected value at #{context}[#{name.inspect}]" end end - def structure(ref, values, errors, context) - return if ref.target == Prelude::Unit - return unless valid_structure?(ref, values, errors, context) + def structure(shape, values, errors, context) + return if shape.target == Prelude::Unit + return unless valid_structure?(shape, values, errors, context) - validate_required_members(ref, values, errors, context) if @validate_required + validate_required_members(shape, values, errors, context) if @validate_required values.each_pair do |name, value| next if value.nil? - member(ref, name, value, errors, context) + member(shape, name, value, errors, context) end end - def valid_structure?(ref, values, errors, context) - if !values.is_a?(Hash) && !values.is_a?(ref.target.type) + def valid_structure?(shape, values, errors, context) + if !values.is_a?(Hash) && !values.is_a?(shape.target.type) errors << expected_got(context, 'a Hash', values) return false end @@ -144,23 +144,23 @@ def valid_structure?(ref, values, errors, context) true end - def union(ref, values, errors, context) - return unless valid_union?(ref, values, errors, context) + def union(shape, values, errors, context) + return unless valid_union?(shape, values, errors, context) if values.is_a?(Schema::Union) - _name, member_ref = ref.target.member_by_type(values.class) - shape(member_ref, values.value, errors, context) + _name, member_shape = shape.target.member_by_type(values.class) + validate_shape(member_shape, values.value, errors, context) elsif values.is_a?(Hash) values.each_pair do |name, value| next if value.nil? - member(ref, name, value, errors, context) + member(shape, name, value, errors, context) end end end - def valid_union?(ref, values, errors, context) - return true if values.is_a?(ref.target.type) + def valid_union?(shape, values, errors, context) + return true if values.is_a?(shape.target.type) unless values.is_a?(Hash) errors << expected_got(context, 'a Hash', values) @@ -168,15 +168,15 @@ def valid_union?(ref, values, errors, context) end return true if values.size <= 1 - union_members = ref.target.members.keys.join(', ') + union_members = shape.target.members.keys.join(', ') error = "expected #{context} to be a Hash with one of #{union_members}, got #{values.size} keys instead." errors << error false end - def validate_required_members(ref, values, errors, context) - ref.target.members.each do |name, member_ref| - traits = member_ref.traits + def validate_required_members(shape, values, errors, context) + shape.target.members.each do |name, member_shape| + traits = member_shape.traits next unless traits.key?('smithy.api#required') && !traits.key?('smithy.api#clientOptional') if values[name].nil? @@ -186,8 +186,8 @@ def validate_required_members(ref, values, errors, context) end end - def streaming_input?(ref) - ref.target.traits.key?('smithy.api#streaming') + def streaming_input?(shape) + shape.target.traits.key?('smithy.api#streaming') end def io_like?(value, require_size: false) diff --git a/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb b/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb index c18d2b3c3..882fb7760 100644 --- a/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb +++ b/gems/smithy-client/spec/smithy-client/log_param_filter_spec.rb @@ -35,7 +35,7 @@ module Client 'target' => 'smithy.ruby.tests#SensitiveStructure' } - sensitive_structure = input.target.member(:sensitive_structure).target.type + sensitive_structure = input.member(:sensitive_structure).target.type filtered = subject.filter(input, { sensitive_structure: sensitive_structure.new(string: 'sensitive') }) expect(filtered).to eq(sensitive_structure: '[FILTERED]') end @@ -120,7 +120,7 @@ module Client it 'filters sensitive unions as a type' do shapes['smithy.ruby.tests#Union']['traits'] = { 'smithy.api#sensitive' => {} } - union = input.target.member(:union).target.member_type(:string) + union = input.member(:union).target.member_type(:string) filtered = subject.filter(input, { union: union.new(string: 'sensitive') }) expect(filtered).to eq(union: '[FILTERED]') end diff --git a/gems/smithy-client/spec/smithy-client/param_converter_spec.rb b/gems/smithy-client/spec/smithy-client/param_converter_spec.rb index 87d7dc9f8..30b19da24 100644 --- a/gems/smithy-client/spec/smithy-client/param_converter_spec.rb +++ b/gems/smithy-client/spec/smithy-client/param_converter_spec.rb @@ -49,8 +49,8 @@ module Client end it 'performs a deeply nested conversion of values when using types' do - structure_type = input.target.type - union_type = input.target.member(:union).target.member_type(:structure) + structure_type = input.type + union_type = input.member(:union).target.member_type(:structure) params = structure_type.new( structure: structure_type.new(boolean: 'true'), map: 'not a map', From e36db8b51b77c4b55abcb8e4ce2a852cc959a04c Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Fri, 5 Jun 2026 08:50:42 -0700 Subject: [PATCH 20/23] Update document_utils shape references --- .../document_utils/deserializer.rb | 65 +++++++++-------- .../document_utils/serializer.rb | 71 +++++++++---------- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb b/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb index d4b5635fd..ad044d082 100644 --- a/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb +++ b/gems/smithy-schema/lib/smithy-schema/document_utils/deserializer.rb @@ -12,23 +12,22 @@ def initialize(options = {}) @type_registry = options[:type_registry] end - def deserialize(data, shape, target) - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - shape(ref, data, target) + def deserialize(data, shape, result) + deserialize_shape(shape, data, result) end private - def shape(ref, value, target = nil) # rubocop:disable Metrics/CyclomaticComplexity - case ref.target + def deserialize_shape(shape, value, result = nil) # rubocop:disable Metrics/CyclomaticComplexity + case shape.target when BlobShape then Base64.strict_decode64(value) when DocumentShape then document(value) when FloatShape then float(value) - when ListShape then list(ref, value, target) - when MapShape then map(ref, value, target) - when StructureShape then structure(ref, value, target) + when ListShape then list(shape, value, result) + when MapShape then map(shape, value, result) + when StructureShape then structure(shape, value, result) when TimestampShape then timestamp(value) - when UnionShape then union(ref, value, target) + when UnionShape then union(shape, value, result) else value end end @@ -39,7 +38,7 @@ def document(values) msg = 'invalid document - document discriminator not found in type registry' raise ArgumentError, msg unless @type_registry.key?(values['__type']) - shape(MemberShape.new(target: @type_registry[values['__type']]), values) + deserialize_shape(@type_registry[values['__type']], values) end def float(value) @@ -52,35 +51,35 @@ def float(value) end end - def list(ref, values, target = nil) + def list(shape, values, result = nil) return if values.nil? - target = [] if target.nil? + result = [] if result.nil? values.each do |value| - target << shape(ref.target.member, value) unless value.nil? + result << deserialize_shape(shape.target.member, value) unless value.nil? end - target + result end - def map(ref, values, target = nil) + def map(shape, values, result = nil) return if values.nil? - target = {} if target.nil? + result = {} if result.nil? values.each do |key, value| - target[key] = shape(ref.target.value, value) unless value.nil? + result[key] = deserialize_shape(shape.target.value, value) unless value.nil? end - target + result end - def structure(ref, values, target = nil) + def structure(shape, values, result = nil) return if values.nil? - target = ref.target.type.new if target.nil? - ref.target.members.each do |member_name, member_ref| - value = values[location_name(member_ref)] - target[member_name] = shape(member_ref, value) unless value.nil? + result = shape.target.type.new if result.nil? + shape.target.members.each do |member_name, member_shape| + value = values[location_name(member_shape)] + result[member_name] = deserialize_shape(member_shape, value) unless value.nil? end - target + result end def timestamp(value) @@ -100,24 +99,24 @@ def timestamp(value) end end - def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize - ref.target.members.each do |member_name, member_ref| - value = values[location_name(member_ref)] + def union(shape, values, result = nil) # rubocop:disable Metrics/AbcSize + shape.target.members.each do |member_name, member_shape| + value = values[location_name(member_shape)] next if value.nil? - target = ref.target.member_type(member_name) if target.nil? - return target.new(member_name => shape(member_ref, value)) + result = shape.target.member_type(member_name) if result.nil? + return result.new(member_name => deserialize_shape(member_shape, value)) end values.delete('__type') key, value = values.first - ref.target.member_type(:unknown).new(key, value) + shape.target.member_type(:unknown).new(key, value) end - def location_name(ref) - return ref.location_name unless @json_name + def location_name(member_shape) + return member_shape.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.location_name + member_shape.traits['smithy.api#jsonName'] || member_shape.location_name end end end diff --git a/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb b/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb index 7be3e0edf..b65a04fe2 100644 --- a/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb +++ b/gems/smithy-schema/lib/smithy-schema/document_utils/serializer.rb @@ -19,8 +19,7 @@ def initialize(options = {}) end def format_document_data(shape, data) - ref = shape.is_a?(MemberShape) ? shape : MemberShape.new(target: shape) - document_data = shape(ref, data) + document_data = serialize_shape(shape, data) document_data['__type'] = shape.id document_data end @@ -41,16 +40,16 @@ def serialize_untyped(values) private - def shape(ref, values) # rubocop:disable Metrics/CyclomaticComplexity - case ref.target + def serialize_shape(shape, values) # rubocop:disable Metrics/CyclomaticComplexity + case shape.target when BlobShape then blob(values) when DocumentShape then document(values) when FloatShape then float(values) - when ListShape then list(ref, values) - when MapShape then map(ref, values) - when StructureShape then structure(ref, values) - when TimestampShape then timestamp(ref, values) - when UnionShape then union(ref, values) + when ListShape then list(shape, values) + when MapShape then map(shape, values) + when StructureShape then structure(shape, values) + when TimestampShape then timestamp(shape, values) + when UnionShape then union(shape, values) else values end end @@ -89,39 +88,39 @@ def float(value) end end - def list(ref, values) + def list(shape, values) return if values.nil? - shape = ref.target + member = shape.target.member values.collect do |value| - shape(shape.member, value) + serialize_shape(member, value) end end - def map(ref, values) + def map(shape, values) return if values.nil? - shape = ref.target + value_shape = shape.target.value values.each.with_object({}) do |(key, value), data| - data[key.to_s] = shape(shape.value, value) + data[key.to_s] = serialize_shape(value_shape, value) end end - def structure(ref, values) + def structure(shape, values) return if values.nil? - ref.target.members.each_with_object({}) do |(member_name, member_ref), data| - value = resolve_value(member_name, member_ref, values.to_h) - data[location_name(member_ref)] = shape(member_ref, value) unless value.nil? + shape.target.members.each_with_object({}) do |(member_name, member_shape), data| + value = resolve_value(member_name, member_shape, values.to_h) + data[location_name(member_shape)] = serialize_shape(member_shape, value) unless value.nil? end end - def timestamp(ref, value) + def timestamp(shape, value) value = normalize_timestamp_value(value) return value.to_i unless @timestamp_format trait = 'smithy.api#timestampFormat' - case ref.traits[trait] || ref.target.traits[trait] + case shape.traits[trait] || shape.target.traits[trait] when 'date-time' then value.utc.iso8601 when 'http-date' then value.utc.httpdate else @@ -130,26 +129,26 @@ def timestamp(ref, value) end end - def union(ref, values) + def union(shape, values) return if values.nil? data = {} if values.is_a?(Union) - _name, member_ref = ref.target.member_by_type(values.class) - data[location_name(member_ref)] = shape(member_ref, values) + _name, member_shape = shape.target.member_by_type(values.class) + data[location_name(member_shape)] = serialize_shape(member_shape, values) else key, value = values.first - if (member_ref = resolve_member_ref(ref, key)) - data[location_name(member_ref)] = shape(member_ref, value) + if (member_shape = resolve_member_shape(shape, key)) + data[location_name(member_shape)] = serialize_shape(member_shape, value) end end data end - def location_name(ref) - return ref.location_name unless @json_name + def location_name(member_shape) + return member_shape.location_name unless @json_name - ref.traits['smithy.api#jsonName'] || ref.location_name + member_shape.traits['smithy.api#jsonName'] || member_shape.location_name end def normalize_timestamp_value(value) @@ -160,20 +159,20 @@ def normalize_timestamp_value(value) end end - def resolve_member_ref(ref, name) - return ref.target.member(name) if ref.target.member?(name) + def resolve_member_shape(shape, name) + return shape.target.member(name) if shape.target.member?(name) - ref.target.members.values.find do |member_ref| - member_ref.traits['smithy.api#jsonName'] == name || member_ref.location_name == name + shape.target.members.values.find do |member_shape| + member_shape.traits['smithy.api#jsonName'] == name || member_shape.location_name == name end end - def resolve_value(member_name, member_ref, values) - if (json_name = member_ref.traits['smithy.api#jsonName']) + def resolve_value(member_name, member_shape, values) + if (json_name = member_shape.traits['smithy.api#jsonName']) value = values[json_name] return value unless value.nil? end - values[member_name] || values[member_ref.location_name] + values[member_name] || values[member_shape.location_name] end end end From 1c580798f5111ab416924675acfeae19de4e6e5d Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Fri, 5 Jun 2026 09:00:02 -0700 Subject: [PATCH 21/23] Clean up remaining shape ref references --- gems/smithy-json/lib/smithy-json/builder.rb | 8 +- .../smithy-schema/lib/smithy-schema/shapes.rb | 18 ++-- .../spec/smithy-schema/shapes_spec.rb | 102 +++++++++--------- gems/smithy-xml/lib/smithy-xml/builder.rb | 16 +-- .../smithy-xml/lib/smithy-xml/parser/stack.rb | 2 +- 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/gems/smithy-json/lib/smithy-json/builder.rb b/gems/smithy-json/lib/smithy-json/builder.rb index 7edf9677a..3aa7b5bfe 100644 --- a/gems/smithy-json/lib/smithy-json/builder.rb +++ b/gems/smithy-json/lib/smithy-json/builder.rb @@ -88,13 +88,13 @@ def union(shape, values) # rubocop:disable Metrics/AbcSize data = {} if values.is_a?(Schema::Union) - _name, member_ref = shape.target.member_by_type(values.class) - data[location_name(member_ref)] = build_shape(member_ref, values.value) + _name, member_shape = shape.target.member_by_type(values.class) + data[location_name(member_shape)] = build_shape(member_shape, values.value) else key, value = values.first if shape.target.member?(key) - member_ref = shape.target.member(key) - data[location_name(member_ref)] = build_shape(member_ref, value) + member_shape = shape.target.member(key) + data[location_name(member_shape)] = build_shape(member_shape, value) end end data diff --git a/gems/smithy-schema/lib/smithy-schema/shapes.rb b/gems/smithy-schema/lib/smithy-schema/shapes.rb index 9b832132c..271d6d1d2 100644 --- a/gems/smithy-schema/lib/smithy-schema/shapes.rb +++ b/gems/smithy-schema/lib/smithy-schema/shapes.rb @@ -161,8 +161,8 @@ def initialize(options = {}) attr_accessor :members # @return [MemberShape] - def add_member(name, shape_ref) - @members[name] = shape_ref + def add_member(name, member_shape) + @members[name] = member_shape end # @param [Symbol] name @@ -195,8 +195,8 @@ def initialize(options = {}) attr_accessor :members # @return [MemberShape] - def add_member(name, shape_ref) - @members[name] = shape_ref + def add_member(name, member_shape) + @members[name] = member_shape end # @param [Symbol] name @@ -244,8 +244,8 @@ def initialize(options = {}) attr_accessor :type # @return [MemberShape] - def add_member(name, shape_ref) - @members[name] = shape_ref + def add_member(name, member_shape) + @members[name] = member_shape end # @param [Symbol] name @@ -286,10 +286,10 @@ def initialize(options = {}) attr_accessor :type # @return [MemberShape] - def add_member(name, type, shape_ref) + def add_member(name, type, member_shape) @member_types[name] = type - @members_by_type[type] = [name, shape_ref] - @members[name] = shape_ref + @members_by_type[type] = [name, member_shape] + @members[name] = member_shape end # @param [Symbol] name diff --git a/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb b/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb index feffeb7c3..72a036cb0 100644 --- a/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb +++ b/gems/smithy-schema/spec/smithy-schema/shapes_spec.rb @@ -152,7 +152,7 @@ module Shapes describe OperationShape do subject { OperationShape.new } - let(:shape_ref) { MemberShape.new(target: StructureShape.new) } + let(:member_shape) { MemberShape.new(target: StructureShape.new) } it 'is a subclass of Shape' do expect(subject).to be_kind_of(Shape) @@ -179,22 +179,22 @@ module Shapes context '#input' do it 'can get the input' do - subject = OperationShape.new(input: shape_ref) - expect(subject.input).to be(shape_ref) + subject = OperationShape.new(input: member_shape) + expect(subject.input).to be(member_shape) end end context '#output' do it 'can get the output' do - subject = OperationShape.new(output: shape_ref) - expect(subject.output).to be(shape_ref) + subject = OperationShape.new(output: member_shape) + expect(subject.output).to be(member_shape) end end context '#errors' do it 'can get a list of errors' do - subject = OperationShape.new(errors: [shape_ref]) - expect(subject.errors).to eq([shape_ref]) + subject = OperationShape.new(errors: [member_shape]) + expect(subject.errors).to eq([member_shape]) end end end @@ -244,24 +244,24 @@ module Shapes describe '#add_member' do it 'adds a member reference' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.members[:foo]).to be_kind_of(MemberShape) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.member?(:foo)).to be(true) end end describe '#member' do it 'returns the member' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.member(:foo)).to be_kind_of(MemberShape) end end @@ -288,24 +288,24 @@ module Shapes describe '#add_member' do it 'adds a member reference' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.members[:foo]).to be_kind_of(MemberShape) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.member?(:foo)).to be(true) end end describe '#member' do it 'returns the member' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.member(:foo)).to be_kind_of(MemberShape) end end @@ -334,9 +334,9 @@ module Shapes describe '#member accessor' do it 'gets and sets a member' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.member = shape_ref - expect(subject.member).to eq(shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.member = member_shape + expect(subject.member).to eq(member_shape) end end end @@ -360,17 +360,17 @@ module Shapes describe '#key accessor' do it 'gets and sets a key' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.key = shape_ref - expect(subject.key).to eq(shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.key = member_shape + expect(subject.key).to eq(member_shape) end end describe '#value accessor' do it 'gets and sets a value' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.value = shape_ref - expect(subject.value).to eq(shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.value = member_shape + expect(subject.value).to eq(member_shape) end end end @@ -403,24 +403,24 @@ module Shapes describe '#add_member' do it 'adds a member reference' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.members[:foo]).to be_kind_of(MemberShape) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.member?(:foo)).to be(true) end end describe '#member' do it 'returns the member' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, member_shape) expect(subject.member(:foo)).to be_kind_of(MemberShape) end end @@ -464,59 +464,59 @@ module Shapes describe '#add_member' do it 'adds a member with its type' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) - expect(subject.members[:foo]).to be(shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) + expect(subject.members[:foo]).to be(member_shape) expect(subject.member_types[:foo]).to be(union_type) - expect(subject.members_by_type[union_type]).to eq([:foo, shape_ref]) + expect(subject.members_by_type[union_type]).to eq([:foo, member_shape]) end end describe '#member?' do it 'returns true if member exists' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) expect(subject.member?(:foo)).to be(true) end end describe '#member' do it 'returns the member' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) expect(subject.member(:foo)).to be_kind_of(MemberShape) end end describe '#member_type?' do it 'returns true if member type exists' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) expect(subject.member_type?(:foo)).to be(true) end end describe '#member_type' do it 'returns the member type' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) expect(subject.member_type(:foo)).to eq(union_type) end end describe '#member_by_type?' do it 'returns true if member by type exists' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) expect(subject.member_by_type?(union_type)).to be(true) end end describe '#member_by_type' do it 'returns the member by type' do - shape_ref = MemberShape.new(target: StringShape.new) - subject.add_member(:foo, union_type, shape_ref) - expect(subject.member_by_type(union_type)).to eq([:foo, shape_ref]) + member_shape = MemberShape.new(target: StringShape.new) + subject.add_member(:foo, union_type, member_shape) + expect(subject.member_by_type(union_type)).to eq([:foo, member_shape]) end end end diff --git a/gems/smithy-xml/lib/smithy-xml/builder.rb b/gems/smithy-xml/lib/smithy-xml/builder.rb index 83d1f87a4..c012f818e 100644 --- a/gems/smithy-xml/lib/smithy-xml/builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/builder.rb @@ -54,27 +54,27 @@ def list(name, shape, values) end def map(name, shape, values) - key_ref = shape.target.key - value_ref = shape.target.value + key_shape = shape.target.key + value_shape = shape.target.value if flat?(shape) - resolve_flat(name, shape, values, key_ref, value_ref) + resolve_flat(name, shape, values, key_shape, value_shape) else node(name, shape) do values.each do |key, value| node('entry', MemberShape.new(target: MapShape.new)) do - build_shape(location_name(key_ref, 'key'), key_ref, key) - build_shape(location_name(value_ref, 'value'), value_ref, value) + build_shape(location_name(key_shape, 'key'), key_shape, key) + build_shape(location_name(value_shape, 'value'), value_shape, value) end end end end end - def resolve_flat(name, shape, values, key_ref, value_ref) + def resolve_flat(name, shape, values, key_shape, value_shape) values.each do |key, value| node(name, shape) do - build_shape(location_name(key_ref, 'key'), key_ref, key) - build_shape(location_name(value_ref, 'value'), value_ref, value) + build_shape(location_name(key_shape, 'key'), key_shape, key) + build_shape(location_name(value_shape, 'value'), value_shape, value) end end end diff --git a/gems/smithy-xml/lib/smithy-xml/parser/stack.rb b/gems/smithy-xml/lib/smithy-xml/parser/stack.rb index 97f45614b..979b4b614 100644 --- a/gems/smithy-xml/lib/smithy-xml/parser/stack.rb +++ b/gems/smithy-xml/lib/smithy-xml/parser/stack.rb @@ -22,7 +22,7 @@ def start_element(name) def attr(name, value) if name.to_s == 'encoding' && value.to_s == 'base64' - @frame = BlobFrame.new(name, @frame.parent, @frame.ref) + @frame = BlobFrame.new(name, @frame.parent, @frame.shape) else # don't try to parse shapes from xml namespace return if name.to_s == 'xmlns' From cd1c965373f19d7a395ebe6c508f406f2190b7bf Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Fri, 5 Jun 2026 09:16:35 -0700 Subject: [PATCH 22/23] Fix XML codec RBS Array type --- gems/smithy-xml/sig/smithy-xml/codec.rbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/smithy-xml/sig/smithy-xml/codec.rbs b/gems/smithy-xml/sig/smithy-xml/codec.rbs index 638f8bbca..b5f222ae5 100644 --- a/gems/smithy-xml/sig/smithy-xml/codec.rbs +++ b/gems/smithy-xml/sig/smithy-xml/codec.rbs @@ -1,7 +1,7 @@ module Smithy module Xml class Codec - def build: (Schema::Shapes::Shape shape, Object data, ?Array? output) -> (nil | String) + def build: (Schema::Shapes::Shape shape, Object data, ?Array[String]? output) -> (nil | String) def parse: (Schema::Shapes::Shape shape, String bytes, ?Object ?result) -> Object? end end From 5d6868d262b8804fb3ada5090274945375cbffd1 Mon Sep 17 00:00:00 2001 From: Juli Tera Date: Mon, 15 Jun 2026 11:48:46 -0700 Subject: [PATCH 23/23] Feeback - reword method --- gems/smithy-xml/lib/smithy-xml/builder.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gems/smithy-xml/lib/smithy-xml/builder.rb b/gems/smithy-xml/lib/smithy-xml/builder.rb index c012f818e..62f143f71 100644 --- a/gems/smithy-xml/lib/smithy-xml/builder.rb +++ b/gems/smithy-xml/lib/smithy-xml/builder.rb @@ -57,7 +57,7 @@ def map(name, shape, values) key_shape = shape.target.key value_shape = shape.target.value if flat?(shape) - resolve_flat(name, shape, values, key_shape, value_shape) + flat_map_entries(name, shape, values, key_shape, value_shape) else node(name, shape) do values.each do |key, value| @@ -70,7 +70,7 @@ def map(name, shape, values) end end - def resolve_flat(name, shape, values, key_shape, value_shape) + def flat_map_entries(name, shape, values, key_shape, value_shape) values.each do |key, value| node(name, shape) do build_shape(location_name(key_shape, 'key'), key_shape, key)