Skip to content

Add typed enums #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: decaf
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gems/smithy-client/lib/smithy-client/endpoint_rules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def self.set?(value)

# not(value: bool) bool
# @api private
def self.not(bool)
def self.not?(bool)
!bool
end

Expand Down
6 changes: 3 additions & 3 deletions gems/smithy-client/spec/smithy-client/endpoint_rules_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,13 @@ module Client
end
end

describe '.not' do
describe '.not?' do
it 'returns true when the value is false' do
expect(EndpointRules.not(false)).to be true
expect(EndpointRules.not?(false)).to be true
end

it 'returns false when the value is true' do
expect(EndpointRules.not(true)).to be false
expect(EndpointRules.not?(true)).to be false
end
end

Expand Down
14 changes: 12 additions & 2 deletions gems/smithy/lib/smithy/templates/client/types.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ module <%= module_name %>
<% type.docstrings.each do |docstring| -%>
# <%= docstring %>
<% end -%>
<% if type.type == 'structure' -%>
<% case type.type -%>
<% when 'enum', 'intEnum' -%>
module <%= type.name %>
<% type.members.each do |member| -%>
<% member.docstrings.each do |docstring| -%>
# <%= docstring %>
<% end -%>
<%= member.name %> = <%= member.value %>
<% end -%>
end
<% when 'structure' -%>
<% type.attribute_docstrings.each do |docstring| -%>
# <%= docstring %>
<% end -%>
Expand All @@ -30,7 +40,7 @@ module <%= module_name %>
end
<% end -%>
end
<% elsif type.type == 'union' -%>
<% when 'union' -%>
class <%= type.name %> < Smithy::Schema::Union
<% type.members.each do |member| -%>
<% member.docstrings.each do |docstring| -%>
Expand Down
7 changes: 7 additions & 0 deletions gems/smithy/lib/smithy/views/client/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,16 @@ def initializer

# @api private
class StructureShape < Shape
OMITTED_TRAITS = %w[
smithy.api#documentation
smithy.api#input
smithy.api#output
].freeze

def initialize(service, id, shape)
super
@members = build_shape_refs(shape['members'])
@traits = shape.fetch('traits', {}).except(*OMITTED_TRAITS)
end

attr_reader :members
Expand Down
155 changes: 113 additions & 42 deletions gems/smithy/lib/smithy/views/client/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,35 @@ def types
Model::ServiceIndex
.new(@model)
.shapes_for(@plan.service)
.select { |_key, shape| %w[structure union].include?(shape['type']) }
.map { |id, shape| Type.new(@plan.service, @model, id, shape) }
.select { |_key, shape| %w[enum intEnum structure union].include?(shape['type']) }
.map { |id, shape| build_type(id, shape) }
end

private

def build_type(id, shape)
args = [@plan.service, @model, id, shape]
case shape['type']
when 'enum', 'intEnum' then EnumType.new(*args)
when 'structure' then StructureType.new(*args)
when 'union' then UnionType.new(*args)
end
end

# @api private
class Type
def initialize(service, model, id, shape)
_, service = service.first
_, @service = service.first
@model = model
@shape = shape
@type = shape['type']
@name = (service.dig('rename', id) || Model::Shape.name(id)).camelize
@members = shape['members'].map { |name, member| Member.new(service, model, name, member) }
@name = (@service.dig('rename', id) || Model::Shape.name(id)).camelize
@traits = shape.fetch('traits', {})
@members = build_members(shape['members'])
end

attr_reader :type, :name, :members

def input?
@traits.key?('smithy.api#input')
end

def defaults
@members.select { |member| member if member.default? }
end

def docstrings
lines = []
lines.concat(documentation_docstrings)
Expand All @@ -55,13 +59,7 @@ def docstrings
lines
end

def attribute_docstrings
lines = []
members.each do |member|
lines.concat(member.docstrings)
end
lines
end
private

def documentation_docstrings
@traits.fetch('smithy.api#documentation', '').split("\n")
Expand Down Expand Up @@ -101,6 +99,49 @@ def unstable_docstrings
end
end

# @api private
class EnumType < Type
private

def build_members(members)
members.map { |name, member| EnumMember.new(@service, @model, name, member) }
end
end

# @api private
class StructureType < Type
def input?
@traits.key?('smithy.api#input')
end

def defaults
@members.select { |member| member if member.default? }
end

def attribute_docstrings
lines = []
members.each do |member|
lines.concat(member.docstrings)
end
lines
end

private

def build_members(members)
members.map { |name, member| StructureMember.new(@service, @model, name, member) }
end
end

# @api private
class UnionType < Type
private

def build_members(members)
members.map { |name, member| Member.new(@service, @model, name, member) }
end
end

# @api private
class Member
def initialize(service, model, name, member)
Expand All @@ -114,19 +155,13 @@ def initialize(service, model, name, member)

attr_reader :name

def indented_docstrings(docstrings)
docstrings.map { |docstring| " #{docstring}" }
end

def docstrings # rubocop:disable Metrics/AbcSize
lines = ["@!attribute #{@name.underscore}"]
lines.concat(indented_docstrings(documentation_docstrings))
lines.concat(indented_docstrings(deprecated_docstrings))
lines.concat(indented_docstrings(external_documentation_docstrings))
lines.concat(indented_docstrings(recommended_docstrings))
lines.concat(indented_docstrings(since_docstrings))
lines.concat(indented_docstrings(unstable_docstrings))
lines.concat(indented_docstrings(return_docstrings))
def docstrings
lines = []
lines.concat(documentation_docstrings)
lines.concat(deprecated_docstrings)
lines.concat(external_documentation_docstrings)
lines.concat(since_docstrings)
lines.concat(unstable_docstrings)
lines
end

Expand All @@ -152,13 +187,6 @@ def external_documentation_docstrings
Model::YARD.external_documentation_docstrings(hash)
end

def recommended_docstrings
return [] unless @traits.key?('smithy.api#recommended')

reason = @traits['smithy.api#recommended'].fetch('reason', '')
Model::YARD.recommended_docstrings(reason)
end

def since_docstrings
return [] unless @traits.key?('smithy.api#since')

Expand All @@ -170,9 +198,35 @@ def unstable_docstrings

[Model::YARD.unstable_docstring]
end
end

def return_docstrings
[Model::YARD.return_docstring(@service, @model, @member['target'], @target)]
# @api private
class EnumMember < Member
def value
value = @traits['smithy.api#enumValue']
case value
when String then "'#{value}'"
else value
end
end

def documentation_docstrings
@member.fetch('traits', {}).fetch('smithy.api#documentation', '').split("\n")
end
end

# @api private
class StructureMember < Member
def docstrings # rubocop:disable Metrics/AbcSize
lines = ["@!attribute #{@name.underscore}"]
lines.concat(indented_docstrings(documentation_docstrings))
lines.concat(indented_docstrings(deprecated_docstrings))
lines.concat(indented_docstrings(external_documentation_docstrings))
lines.concat(indented_docstrings(recommended_docstrings))
lines.concat(indented_docstrings(since_docstrings))
lines.concat(indented_docstrings(unstable_docstrings))
lines.concat(indented_docstrings(return_docstrings))
lines
end

def default?
Expand All @@ -192,6 +246,23 @@ def default
end
end

private

def indented_docstrings(docstrings)
docstrings.map { |docstring| " #{docstring}" }
end

def recommended_docstrings
return [] unless @traits.key?('smithy.api#recommended')

reason = @traits['smithy.api#recommended'].fetch('reason', '')
Model::YARD.recommended_docstrings(reason)
end

def return_docstrings
[Model::YARD.return_docstring(@service, @model, @member['target'], @target)]
end

def document_default(default)
case default
when nil then 'nil'
Expand Down
2 changes: 1 addition & 1 deletion gems/smithy/lib/smithy/welds/transforms/endpoints.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def endpoint_function_bindings
'substring' => 'Smithy::Client::EndpointRules.substring',
'uriEncode' => 'Smithy::Client::EndpointRules.uri_encode',
'isSet' => 'Smithy::Client::EndpointRules.set?',
'not' => 'Smithy::Client::EndpointRules.not',
'not' => 'Smithy::Client::EndpointRules.not?',
'getAttr' => 'Smithy::Client::EndpointRules.attr',
'stringEquals' => 'Smithy::Client::EndpointRules.string_equals?',
'booleanEquals' => 'Smithy::Client::EndpointRules.boolean_equals?'
Expand Down
Loading