aws-sdk-code-generator 0.1.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/aws-sdk-code-generator.rb +91 -0
- data/lib/aws-sdk-code-generator/apply_docs.rb +37 -0
- data/lib/aws-sdk-code-generator/code_builder.rb +201 -0
- data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +23 -0
- data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +43 -0
- data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +11 -0
- data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +11 -0
- data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +15 -0
- data/lib/aws-sdk-code-generator/dsl/block_param.rb +11 -0
- data/lib/aws-sdk-code-generator/dsl/class.rb +27 -0
- data/lib/aws-sdk-code-generator/dsl/code_literal.rb +66 -0
- data/lib/aws-sdk-code-generator/dsl/code_object.rb +33 -0
- data/lib/aws-sdk-code-generator/dsl/docstring.rb +36 -0
- data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +15 -0
- data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +12 -0
- data/lib/aws-sdk-code-generator/dsl/formatter.rb +25 -0
- data/lib/aws-sdk-code-generator/dsl/include_statement.rb +17 -0
- data/lib/aws-sdk-code-generator/dsl/main.rb +105 -0
- data/lib/aws-sdk-code-generator/dsl/method.rb +108 -0
- data/lib/aws-sdk-code-generator/dsl/module.rb +167 -0
- data/lib/aws-sdk-code-generator/dsl/option_tag.rb +36 -0
- data/lib/aws-sdk-code-generator/dsl/param.rb +43 -0
- data/lib/aws-sdk-code-generator/dsl/param_list.rb +38 -0
- data/lib/aws-sdk-code-generator/dsl/return_tag.rb +19 -0
- data/lib/aws-sdk-code-generator/dsl/tag_default.rb +20 -0
- data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +27 -0
- data/lib/aws-sdk-code-generator/dsl/tag_type.rb +18 -0
- data/lib/aws-sdk-code-generator/errors.rb +30 -0
- data/lib/aws-sdk-code-generator/gem_builder.rb +71 -0
- data/lib/aws-sdk-code-generator/generators/client_api_module.rb +334 -0
- data/lib/aws-sdk-code-generator/generators/client_class.rb +389 -0
- data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +166 -0
- data/lib/aws-sdk-code-generator/generators/errors_module.rb +25 -0
- data/lib/aws-sdk-code-generator/generators/resource/action.rb +88 -0
- data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +211 -0
- data/lib/aws-sdk-code-generator/generators/resource/builder.rb +50 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +15 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +49 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +97 -0
- data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +88 -0
- data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +180 -0
- data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +24 -0
- data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +18 -0
- data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +49 -0
- data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +29 -0
- data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +32 -0
- data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +101 -0
- data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +108 -0
- data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +26 -0
- data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +28 -0
- data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +67 -0
- data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +65 -0
- data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +68 -0
- data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +61 -0
- data/lib/aws-sdk-code-generator/generators/resource_class.rb +325 -0
- data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +83 -0
- data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +42 -0
- data/lib/aws-sdk-code-generator/generators/service_documentation.rb +64 -0
- data/lib/aws-sdk-code-generator/generators/shared_example.rb +132 -0
- data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +95 -0
- data/lib/aws-sdk-code-generator/generators/syntax_example.rb +169 -0
- data/lib/aws-sdk-code-generator/generators/types_module.rb +52 -0
- data/lib/aws-sdk-code-generator/generators/waiter_class.rb +62 -0
- data/lib/aws-sdk-code-generator/generators/waiters_module.rb +20 -0
- data/lib/aws-sdk-code-generator/hash_formatter.rb +122 -0
- data/lib/aws-sdk-code-generator/helper.rb +215 -0
- data/lib/aws-sdk-code-generator/service.rb +126 -0
- data/lib/aws-sdk-code-generator/underscore.rb +45 -0
- data/lib/aws-sdk-code-generator/view.rb +23 -0
- data/lib/aws-sdk-code-generator/views.rb +3 -0
- data/lib/aws-sdk-code-generator/views/features/env.rb +24 -0
- data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +20 -0
- data/lib/aws-sdk-code-generator/views/gemspec.rb +41 -0
- data/lib/aws-sdk-code-generator/views/service_module.rb +85 -0
- data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +24 -0
- data/lib/aws-sdk-code-generator/views/version.rb +16 -0
- metadata +120 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
module AwsSdkCodeGenerator
|
|
4
|
+
module Generators
|
|
5
|
+
class TypesModule < Dsl::Module
|
|
6
|
+
|
|
7
|
+
include Helper
|
|
8
|
+
|
|
9
|
+
# @option options [required, Hash] :api
|
|
10
|
+
def initialize(options)
|
|
11
|
+
@api = options.fetch(:api)
|
|
12
|
+
super('Types')
|
|
13
|
+
input_shapes = compute_input_shapes(@api)
|
|
14
|
+
structures.each do |shape_name, shape|
|
|
15
|
+
add(StructureTypeClass.new(
|
|
16
|
+
name: shape_name,
|
|
17
|
+
api: @api,
|
|
18
|
+
used_as_input: input_shapes.include?(shape_name)
|
|
19
|
+
))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def compute_input_shapes(api)
|
|
26
|
+
inputs = Set.new
|
|
27
|
+
(api['operations'] || {}).each do |_, operation|
|
|
28
|
+
visit_inputs(operation['input'], inputs) if operation['input']
|
|
29
|
+
end
|
|
30
|
+
inputs
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def visit_inputs(shape_ref, inputs)
|
|
34
|
+
return if inputs.include?(shape_ref['shape']) # recursion
|
|
35
|
+
inputs << shape_ref['shape']
|
|
36
|
+
s = shape(shape_ref)
|
|
37
|
+
case s['type']
|
|
38
|
+
when 'structure'
|
|
39
|
+
s['members'].each_pair do |_, member_ref|
|
|
40
|
+
visit_inputs(member_ref, inputs)
|
|
41
|
+
end
|
|
42
|
+
when 'list'
|
|
43
|
+
visit_inputs(s['member'], inputs)
|
|
44
|
+
when 'map'
|
|
45
|
+
visit_inputs(s['key'], inputs)
|
|
46
|
+
visit_inputs(s['value'], inputs)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module AwsSdkCodeGenerator
|
|
2
|
+
module Generators
|
|
3
|
+
class WaiterClass < Dsl::Class
|
|
4
|
+
|
|
5
|
+
# @option options [required, String] :waiter_name
|
|
6
|
+
# @option options [required, Hash] :waiter
|
|
7
|
+
def initialize(options)
|
|
8
|
+
waiter = options.fetch(:waiter)
|
|
9
|
+
client_method = underscore(waiter['operation'])
|
|
10
|
+
super(options.fetch(:waiter_name))
|
|
11
|
+
code <<-CODE
|
|
12
|
+
# @param [Hash] options
|
|
13
|
+
# @option options [required, Client] :client
|
|
14
|
+
# @option options [Integer] :max_attempts (#{waiter['maxAttempts']})
|
|
15
|
+
# @option options [Integer] :delay (#{waiter['delay']})
|
|
16
|
+
# @option options [Proc] :before_attempt
|
|
17
|
+
# @option options [Proc] :before_wait
|
|
18
|
+
def initialize(options)
|
|
19
|
+
@client = options.fetch(:client)
|
|
20
|
+
@waiter = Aws::Waiters::Waiter.new({
|
|
21
|
+
max_attempts: #{waiter['maxAttempts']},
|
|
22
|
+
delay: #{waiter['delay']},
|
|
23
|
+
poller: Aws::Waiters::Poller.new(#{poller_args(waiter)} )
|
|
24
|
+
}.merge(options))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @option (see Client##{client_method})
|
|
28
|
+
# @return (see Client##{client_method})
|
|
29
|
+
def wait(params = {})
|
|
30
|
+
@waiter.wait(client: @client, params: params)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
attr_reader :waiter
|
|
35
|
+
CODE
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def poller_args(hash)
|
|
41
|
+
hash = hash.dup
|
|
42
|
+
hash.delete('delay')
|
|
43
|
+
hash.delete('maxAttempts')
|
|
44
|
+
hash[:operation_name] = Underscore.underscore(hash.delete('operation')).to_sym
|
|
45
|
+
hash[:acceptors] = hash.delete('acceptors').map do |acceptor|
|
|
46
|
+
if acceptor['argument']
|
|
47
|
+
acceptor['argument'] = Underscore.underscore_jmespath(acceptor['argument'])
|
|
48
|
+
end
|
|
49
|
+
acceptor
|
|
50
|
+
end
|
|
51
|
+
formatter = HashFormatter.new(
|
|
52
|
+
wrap: false,
|
|
53
|
+
inline: false,
|
|
54
|
+
quote_strings: true
|
|
55
|
+
)
|
|
56
|
+
lines = formatter.format(hash).lines
|
|
57
|
+
lines.map { |line| " #{line}" }.join
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module AwsSdkCodeGenerator
|
|
2
|
+
module Generators
|
|
3
|
+
class WaitersModule < Dsl::Module
|
|
4
|
+
|
|
5
|
+
include Helper
|
|
6
|
+
|
|
7
|
+
# @option options [required, Module] :parent
|
|
8
|
+
# @option options [required, Hash, nil] :waiters
|
|
9
|
+
def initialize(options)
|
|
10
|
+
waiters = options.fetch(:waiters)
|
|
11
|
+
super('Waiters', parent: options.fetch(:parent))
|
|
12
|
+
require_statement('aws-sdk-core/waiters')
|
|
13
|
+
waiters['waiters'].each do |waiter_name, waiter|
|
|
14
|
+
add(WaiterClass.new(waiter_name: waiter_name, waiter: waiter))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
module AwsSdkCodeGenerator
|
|
2
|
+
class HashFormatter
|
|
3
|
+
|
|
4
|
+
# @option options [Boolean] :wrap (true) When `true`, the formatted hash will
|
|
5
|
+
# be wrapped with curly braces.
|
|
6
|
+
#
|
|
7
|
+
# @option options [Boolean] :inline (false) When `true` the formatted hash will
|
|
8
|
+
# contain no newlines.
|
|
9
|
+
#
|
|
10
|
+
# @option options [Boolean] :quote_strings (false) By default, all hash string values
|
|
11
|
+
# must contain their own quotes. If you pass `true`, then all hash string
|
|
12
|
+
# values will be inspected via `#inspect` which will auto-quote them.
|
|
13
|
+
#
|
|
14
|
+
def initialize(options = {})
|
|
15
|
+
@wrap = options.fetch(:wrap, true)
|
|
16
|
+
@inline = options.fetch(:inline, false)
|
|
17
|
+
@quote_strings = options.fetch(:quote_strings, false)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def format(obj)
|
|
21
|
+
result = hash(obj, i:'', inline:@inline)
|
|
22
|
+
result = unwrap(result, obj.size) if !@wrap
|
|
23
|
+
result = result.strip if @inline && result.lines.to_a.length == 1
|
|
24
|
+
result
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def value(obj, options)
|
|
30
|
+
i = options.fetch(:i)
|
|
31
|
+
inline = options.fetch(:inline)
|
|
32
|
+
case obj
|
|
33
|
+
when Hash then hash(obj, i:i, inline:inline)
|
|
34
|
+
when Array then array(obj, i:i)
|
|
35
|
+
when String then @quote_strings ? obj.inspect : obj
|
|
36
|
+
when Symbol then obj.inspect
|
|
37
|
+
when Fixnum, true, false then obj.inspect
|
|
38
|
+
else raise ArgumentError, "unsupported value `#{obj.class}'"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def hash(hash, options)
|
|
43
|
+
i = options.fetch(:i)
|
|
44
|
+
inline = options.fetch(:inline)
|
|
45
|
+
if hash.empty?
|
|
46
|
+
'{}'
|
|
47
|
+
elsif inline_hash?(hash, inline)
|
|
48
|
+
inline_hash(hash)
|
|
49
|
+
else
|
|
50
|
+
multiline_hash(hash, i:i)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def inline_hash(hash)
|
|
55
|
+
"{ #{hash_entry(hash.keys[0], hash.values[0], i:'')} }"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def multiline_hash(hash, options)
|
|
59
|
+
i = options.fetch(:i)
|
|
60
|
+
str = "{\n"
|
|
61
|
+
hash.each.with_index do |(key, value), n|
|
|
62
|
+
str += "#{i} #{hash_entry(key, value, i:i)}"
|
|
63
|
+
str += "," unless n == hash.keys.length - 1
|
|
64
|
+
str += "\n"
|
|
65
|
+
end
|
|
66
|
+
str + "#{i}}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def hash_entry(key, value, options)
|
|
70
|
+
i = options.fetch(:i)
|
|
71
|
+
value = value(value, i: i + ' ', inline:false)
|
|
72
|
+
if Symbol === key
|
|
73
|
+
"#{key}: #{value}"
|
|
74
|
+
else
|
|
75
|
+
"#{key.inspect} => #{value}"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def array(array, options)
|
|
80
|
+
i = options.fetch(:i)
|
|
81
|
+
if array.empty?
|
|
82
|
+
'[]'
|
|
83
|
+
elsif inline_array?(array)
|
|
84
|
+
"[#{value(array[0], i:i, inline:true)}]"
|
|
85
|
+
else
|
|
86
|
+
format_multiline_array(array, i:i)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def format_multiline_array(array, options)
|
|
91
|
+
i = options.fetch(:i)
|
|
92
|
+
str = "[\n"
|
|
93
|
+
array.each.with_index do |value, n|
|
|
94
|
+
str += "#{i} #{value(value, i:i + ' ', inline:true)}"
|
|
95
|
+
str += "," unless n == array.length - 1
|
|
96
|
+
str += "\n"
|
|
97
|
+
end
|
|
98
|
+
str + "#{i}]"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def inline_hash?(hash, inline)
|
|
102
|
+
hash.length == 1 && String === hash.values[0] && inline
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def inline_array?(array)
|
|
106
|
+
array.length == 1# && String === array[0]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def unwrap(str, size)
|
|
110
|
+
if @inline || size > 1
|
|
111
|
+
str[1..-2]
|
|
112
|
+
else
|
|
113
|
+
lines = str.lines.to_a
|
|
114
|
+
lines.shift
|
|
115
|
+
lines.pop
|
|
116
|
+
lines = lines.map { |line| line[2..-1] }
|
|
117
|
+
lines.join.rstrip
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
require 'kramdown'
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
# disable inline attribute lists
|
|
5
|
+
class Kramdown::Converter::Kramdown
|
|
6
|
+
def ial_for_element(*args)
|
|
7
|
+
nil
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module AwsSdkCodeGenerator
|
|
12
|
+
module Helper
|
|
13
|
+
|
|
14
|
+
def identifier_type(identifier)
|
|
15
|
+
case identifier['type']
|
|
16
|
+
when nil, 'string' then 'String'
|
|
17
|
+
when 'integer' then 'Integer'
|
|
18
|
+
else
|
|
19
|
+
msg = "unsupported identifier type `#{identifier['type']}'"
|
|
20
|
+
raise ArgumentError, msg
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param [Array<Array<String>>]
|
|
25
|
+
def markdown_table(table)
|
|
26
|
+
# compute the width of each column by scanning for longest values
|
|
27
|
+
column_width = lambda do |col|
|
|
28
|
+
table.map { |row| row[col].size }.max
|
|
29
|
+
end
|
|
30
|
+
widths = [
|
|
31
|
+
column_width.call(0),
|
|
32
|
+
column_width.call(1),
|
|
33
|
+
column_width.call(2),
|
|
34
|
+
column_width.call(3),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
# insert a dashed line after the header row
|
|
38
|
+
table = [
|
|
39
|
+
table[0],
|
|
40
|
+
['-' * widths[0], '-' * widths[1], '-' * widths[2], '-' * widths[3]]
|
|
41
|
+
] + table[1..-1]
|
|
42
|
+
|
|
43
|
+
# build the final table
|
|
44
|
+
line = "| #{widths.map{|n| "%-#{n}s" }.join(' | ')} |"
|
|
45
|
+
table.map { |row| line % row }.join("\n")
|
|
46
|
+
end
|
|
47
|
+
module_function :markdown_table
|
|
48
|
+
|
|
49
|
+
def underscore(str)
|
|
50
|
+
str.split('.').map do |part|
|
|
51
|
+
Underscore.underscore(part)
|
|
52
|
+
end.join('.')
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def structures
|
|
56
|
+
Enumerator.new do |y|
|
|
57
|
+
(@api['shapes'] || {}).each do |shape_name, shape|
|
|
58
|
+
if shape['type'] == 'structure' && !shape['error'] && !shape['exception']
|
|
59
|
+
y.yield(shape_name, shape)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @option options [Boolean] :nested (false)
|
|
66
|
+
def ruby_input_type(shape_ref, options = {})
|
|
67
|
+
nested = options.fetch(:nested, false)
|
|
68
|
+
shape = @api['shapes'][shape_ref['shape']]
|
|
69
|
+
case shape['type']
|
|
70
|
+
when 'byte' then 'Integer<byte>'
|
|
71
|
+
when 'blob' then 'String, IO'
|
|
72
|
+
when 'boolean' then 'Boolean'
|
|
73
|
+
when 'character' then 'String<character>'
|
|
74
|
+
when 'double' then 'Float'
|
|
75
|
+
when 'float' then 'Float'
|
|
76
|
+
when 'integer' then 'Integer'
|
|
77
|
+
when 'list'
|
|
78
|
+
if nested
|
|
79
|
+
"Array"
|
|
80
|
+
else
|
|
81
|
+
"Array<#{ruby_input_type(shape['member'], nested:true)}>"
|
|
82
|
+
end
|
|
83
|
+
when 'long' then 'Integer'
|
|
84
|
+
when 'map'
|
|
85
|
+
if nested
|
|
86
|
+
"Hash"
|
|
87
|
+
else
|
|
88
|
+
"Hash<String,#{ruby_input_type(shape['value'], nested:true)}>"
|
|
89
|
+
end
|
|
90
|
+
when 'string' then 'String'
|
|
91
|
+
when 'structure' then "Types::#{shape_ref['shape']}"
|
|
92
|
+
when 'timestamp' then 'Time,DateTime,Date,Integer,String'
|
|
93
|
+
else
|
|
94
|
+
raise "unhandled type #{shape.type}.inspect"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ruby_type(shape_ref)
|
|
99
|
+
shape = @api['shapes'][shape_ref['shape']]
|
|
100
|
+
case shape['type']
|
|
101
|
+
when 'blob' then streaming?(shape_ref, shape) ? 'IO' : 'String'
|
|
102
|
+
when 'boolean' then 'Boolean'
|
|
103
|
+
when 'byte' then 'Integer<byte>'
|
|
104
|
+
when 'character' then 'String<character>'
|
|
105
|
+
when 'double' then 'Float'
|
|
106
|
+
when 'float' then 'Float'
|
|
107
|
+
when 'integer' then 'Integer'
|
|
108
|
+
when 'list' then "Array<#{ruby_type(shape['member'])}>"
|
|
109
|
+
when 'long' then 'Integer'
|
|
110
|
+
when 'map' then "Hash<String,#{ruby_type(shape['value'])}>"
|
|
111
|
+
when 'string' then 'String'
|
|
112
|
+
when 'structure' then "Types::#{shape_ref['shape']}"
|
|
113
|
+
when 'timestamp' then 'Time'
|
|
114
|
+
else
|
|
115
|
+
raise "unhandled type #{shape['type'].inspect}"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def streaming?(ref, shape)
|
|
120
|
+
ref['streaming'] || shape['streaming']
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# @option options [Integer] :line_width (70)
|
|
124
|
+
def documentation(ref_or_shape, options = {})
|
|
125
|
+
line_width = options.fetch(:line_width, 70)
|
|
126
|
+
shape = ref_or_shape.key?('type') ? ref_or_shape : shape(ref_or_shape)
|
|
127
|
+
docstring = ref_or_shape['documentation'] || shape['documentation'] || ''
|
|
128
|
+
|
|
129
|
+
# append boilerplate idempotency docs
|
|
130
|
+
if ref_or_shape['idempotencyToken']
|
|
131
|
+
docstring = "#{docstring}<p>**A suitable default value is "
|
|
132
|
+
docstring += "auto-generated.** You should normally "
|
|
133
|
+
docstring += "not need to pass this option.</p>"
|
|
134
|
+
docstring = docstring.strip
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
docstring == '' ? docstring : markdown(docstring, line_width:line_width)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def member_shape(shape_name, member_name)
|
|
141
|
+
shape = @api['shapes'][shape_name]
|
|
142
|
+
member_ref = shape['members'][member_name]
|
|
143
|
+
shape(member_ref)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def shape(ref)
|
|
147
|
+
if ref.nil?
|
|
148
|
+
nil
|
|
149
|
+
else
|
|
150
|
+
shape = @api['shapes'][ref['shape']]
|
|
151
|
+
raise ArgumentError, "no such shape `#{ref['shape']}'" unless shape
|
|
152
|
+
shape
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# @option options [Integer] :line_width (70)
|
|
157
|
+
def markdown(html, options = {})
|
|
158
|
+
line_width = options.fetch(:line_width, 70)
|
|
159
|
+
# TODO : this section of code is **very slow** and runs many times
|
|
160
|
+
# while building a service.
|
|
161
|
+
if html
|
|
162
|
+
html = "<p>#{html}</p>" unless html.match(/<\w+>/)
|
|
163
|
+
|
|
164
|
+
# unescaped curly braces cause YARD errors, they are interpreted
|
|
165
|
+
# as code links.
|
|
166
|
+
html = html.gsub('{', "\\{").gsub('}', "\\}")
|
|
167
|
+
|
|
168
|
+
# Kramdown generates invalid markup when there are attributes
|
|
169
|
+
# on the code tag, have to reduce these down to get the proper markdown.
|
|
170
|
+
html = html.gsub(/<code.*?>(.+?)<\/code>/) { "<code>#{$1}</code>" }
|
|
171
|
+
|
|
172
|
+
# Kramdown creates invalid markup with target="_blank" attributes.
|
|
173
|
+
html = html.gsub(' target="_blank"', '')
|
|
174
|
+
|
|
175
|
+
# There are quite a few empty <a> tags. These appear to be code names,
|
|
176
|
+
# such as structure member names, or structure type names. We should
|
|
177
|
+
# investigate if it is possible to inflect these properly and then
|
|
178
|
+
# turn them into YARD links.
|
|
179
|
+
html = html.gsub(/<a>(.+?)<\/a>/) { $1 }
|
|
180
|
+
|
|
181
|
+
# <important> tag doesn't render well
|
|
182
|
+
html = html.gsub(/<important>(.+?)<\/important>/){ "<p>#{$1}</p>" }
|
|
183
|
+
|
|
184
|
+
markdown = Kramdown::Document.new(
|
|
185
|
+
html,
|
|
186
|
+
input: 'html',
|
|
187
|
+
line_width: line_width,
|
|
188
|
+
auto_ids: false
|
|
189
|
+
).to_kramdown.strip
|
|
190
|
+
|
|
191
|
+
# remove extra escape
|
|
192
|
+
markdown.gsub(/\\(\*|`|'|")/, '\1')
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def deep_copy(obj)
|
|
197
|
+
case obj
|
|
198
|
+
when nil then nil
|
|
199
|
+
when true then true
|
|
200
|
+
when false then false
|
|
201
|
+
when Hash then obj.inject({}) { |h,(k,v)| h[deep_copy(k)] = deep_copy(v); h }
|
|
202
|
+
when Array then obj.map { |v| deep_copy(v) }
|
|
203
|
+
else
|
|
204
|
+
if obj.respond_to?(:dup)
|
|
205
|
+
obj.dup
|
|
206
|
+
elsif obj.respond_to?(:clone)
|
|
207
|
+
obj.clone
|
|
208
|
+
else
|
|
209
|
+
obj
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
end
|
|
215
|
+
end
|