aws-sdk-code-generator 0.1.0.pre → 0.2.4.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +5 -5
  2. data/lib/aws-sdk-code-generator/api.rb +150 -0
  3. data/lib/aws-sdk-code-generator/apply_docs.rb +15 -2
  4. data/lib/aws-sdk-code-generator/client_constructor.rb +39 -0
  5. data/lib/aws-sdk-code-generator/client_operation_documentation.rb +282 -0
  6. data/lib/aws-sdk-code-generator/client_operation_list.rb +148 -0
  7. data/lib/aws-sdk-code-generator/client_response_structure_example.rb +115 -0
  8. data/lib/aws-sdk-code-generator/code_builder.rb +146 -133
  9. data/lib/aws-sdk-code-generator/crosslink.rb +42 -0
  10. data/lib/aws-sdk-code-generator/docstring.rb +199 -0
  11. data/lib/aws-sdk-code-generator/error_list.rb +77 -0
  12. data/lib/aws-sdk-code-generator/errors.rb +2 -0
  13. data/lib/aws-sdk-code-generator/eventstream_example.rb +220 -0
  14. data/lib/aws-sdk-code-generator/gem_builder.rb +42 -25
  15. data/lib/aws-sdk-code-generator/hash_formatter.rb +5 -2
  16. data/lib/aws-sdk-code-generator/helper.rb +86 -119
  17. data/lib/aws-sdk-code-generator/plugin_list.rb +147 -0
  18. data/lib/aws-sdk-code-generator/resource_action.rb +69 -0
  19. data/lib/aws-sdk-code-generator/resource_action_code.rb +57 -0
  20. data/lib/aws-sdk-code-generator/resource_association.rb +37 -0
  21. data/lib/aws-sdk-code-generator/resource_attribute.rb +76 -0
  22. data/lib/aws-sdk-code-generator/resource_batch_action.rb +56 -0
  23. data/lib/aws-sdk-code-generator/resource_batch_action_code.rb +136 -0
  24. data/lib/aws-sdk-code-generator/resource_batch_action_documentation.rb +108 -0
  25. data/lib/aws-sdk-code-generator/resource_batch_builder.rb +212 -0
  26. data/lib/aws-sdk-code-generator/resource_builder.rb +48 -0
  27. data/lib/aws-sdk-code-generator/resource_client_request.rb +62 -0
  28. data/lib/aws-sdk-code-generator/resource_client_request_documentation.rb +81 -0
  29. data/lib/aws-sdk-code-generator/resource_client_request_params.rb +86 -0
  30. data/lib/aws-sdk-code-generator/resource_data_method.rb +60 -0
  31. data/lib/aws-sdk-code-generator/resource_has_association.rb +117 -0
  32. data/lib/aws-sdk-code-generator/resource_has_many_association.rb +52 -0
  33. data/lib/aws-sdk-code-generator/resource_has_many_association_code.rb +76 -0
  34. data/lib/aws-sdk-code-generator/resource_identifier.rb +44 -0
  35. data/lib/aws-sdk-code-generator/resource_identifiers_method.rb +29 -0
  36. data/lib/aws-sdk-code-generator/resource_load_method.rb +68 -0
  37. data/lib/aws-sdk-code-generator/resource_method.rb +22 -0
  38. data/lib/aws-sdk-code-generator/resource_skip_params.rb +36 -0
  39. data/lib/aws-sdk-code-generator/resource_value_source.rb +68 -0
  40. data/lib/aws-sdk-code-generator/resource_waiter.rb +80 -0
  41. data/lib/aws-sdk-code-generator/service.rb +30 -7
  42. data/lib/aws-sdk-code-generator/shared_example.rb +131 -0
  43. data/lib/aws-sdk-code-generator/syntax_example.rb +60 -0
  44. data/lib/aws-sdk-code-generator/syntax_example_hash.rb +174 -0
  45. data/lib/aws-sdk-code-generator/underscore.rb +10 -5
  46. data/lib/aws-sdk-code-generator/view.rb +33 -0
  47. data/lib/aws-sdk-code-generator/views/apig_endpoint_class.rb +25 -0
  48. data/lib/aws-sdk-code-generator/views/apig_readme.rb +32 -0
  49. data/lib/aws-sdk-code-generator/views/async_client_class.rb +68 -0
  50. data/lib/aws-sdk-code-generator/views/authorizer_class.rb +17 -0
  51. data/lib/aws-sdk-code-generator/views/client_api_module.rb +602 -0
  52. data/lib/aws-sdk-code-generator/views/client_class.rb +93 -0
  53. data/lib/aws-sdk-code-generator/views/docstring.rb +27 -0
  54. data/lib/aws-sdk-code-generator/views/errors_module.rb +32 -0
  55. data/lib/aws-sdk-code-generator/views/event_streams_module.rb +149 -0
  56. data/lib/aws-sdk-code-generator/views/features/env.rb +9 -0
  57. data/lib/aws-sdk-code-generator/views/features/smoke.rb +52 -0
  58. data/lib/aws-sdk-code-generator/views/features/smoke_step_definitions.rb +26 -0
  59. data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +6 -2
  60. data/lib/aws-sdk-code-generator/views/gemspec.rb +39 -5
  61. data/lib/aws-sdk-code-generator/views/resource_class.rb +122 -0
  62. data/lib/aws-sdk-code-generator/views/root_resource_class.rb +58 -0
  63. data/lib/aws-sdk-code-generator/views/service_module.rb +38 -14
  64. data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +9 -0
  65. data/lib/aws-sdk-code-generator/views/types_module.rb +329 -0
  66. data/lib/aws-sdk-code-generator/views/version.rb +2 -0
  67. data/lib/aws-sdk-code-generator/views/waiters_module.rb +37 -0
  68. data/lib/aws-sdk-code-generator/views.rb +2 -0
  69. data/lib/aws-sdk-code-generator/waiter.rb +95 -0
  70. data/lib/aws-sdk-code-generator/yard_option_tag.rb +43 -0
  71. data/lib/aws-sdk-code-generator.rb +68 -75
  72. data/templates/apig_endpoint_class.mustache +16 -0
  73. data/templates/apig_readme.mustache +62 -0
  74. data/templates/async_client_class.mustache +125 -0
  75. data/templates/authorizer_class.mustache +37 -0
  76. data/templates/client_api_module.mustache +106 -0
  77. data/templates/client_class.mustache +295 -0
  78. data/templates/code.mustache +4 -0
  79. data/templates/documentation.mustache +4 -0
  80. data/templates/errors_module.mustache +70 -0
  81. data/templates/event_streams_module.mustache +76 -0
  82. data/templates/features/env.mustache +15 -0
  83. data/templates/features/smoke.mustache +22 -0
  84. data/templates/features/smoke_step_definitions.mustache +31 -0
  85. data/templates/features/step_definitions.mustache +13 -0
  86. data/templates/gemspec.mustache +31 -0
  87. data/templates/license.txt +202 -0
  88. data/templates/method.mustache +7 -0
  89. data/templates/resource_class.mustache +304 -0
  90. data/templates/root_resource_class.mustache +51 -0
  91. data/templates/service_module.mustache +58 -0
  92. data/templates/spec/spec_helper.mustache +15 -0
  93. data/templates/types_module.mustache +53 -0
  94. data/templates/version.mustache +1 -0
  95. data/templates/waiters_module.mustache +112 -0
  96. metadata +115 -70
  97. data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +0 -23
  98. data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +0 -43
  99. data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +0 -11
  100. data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +0 -11
  101. data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +0 -15
  102. data/lib/aws-sdk-code-generator/dsl/block_param.rb +0 -11
  103. data/lib/aws-sdk-code-generator/dsl/class.rb +0 -27
  104. data/lib/aws-sdk-code-generator/dsl/code_literal.rb +0 -66
  105. data/lib/aws-sdk-code-generator/dsl/code_object.rb +0 -33
  106. data/lib/aws-sdk-code-generator/dsl/docstring.rb +0 -36
  107. data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +0 -15
  108. data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +0 -12
  109. data/lib/aws-sdk-code-generator/dsl/formatter.rb +0 -25
  110. data/lib/aws-sdk-code-generator/dsl/include_statement.rb +0 -17
  111. data/lib/aws-sdk-code-generator/dsl/main.rb +0 -105
  112. data/lib/aws-sdk-code-generator/dsl/method.rb +0 -108
  113. data/lib/aws-sdk-code-generator/dsl/module.rb +0 -167
  114. data/lib/aws-sdk-code-generator/dsl/option_tag.rb +0 -36
  115. data/lib/aws-sdk-code-generator/dsl/param.rb +0 -43
  116. data/lib/aws-sdk-code-generator/dsl/param_list.rb +0 -38
  117. data/lib/aws-sdk-code-generator/dsl/return_tag.rb +0 -19
  118. data/lib/aws-sdk-code-generator/dsl/tag_default.rb +0 -20
  119. data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +0 -27
  120. data/lib/aws-sdk-code-generator/dsl/tag_type.rb +0 -18
  121. data/lib/aws-sdk-code-generator/generators/client_api_module.rb +0 -334
  122. data/lib/aws-sdk-code-generator/generators/client_class.rb +0 -389
  123. data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +0 -166
  124. data/lib/aws-sdk-code-generator/generators/errors_module.rb +0 -25
  125. data/lib/aws-sdk-code-generator/generators/resource/action.rb +0 -88
  126. data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +0 -211
  127. data/lib/aws-sdk-code-generator/generators/resource/builder.rb +0 -50
  128. data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +0 -15
  129. data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +0 -49
  130. data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +0 -97
  131. data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +0 -88
  132. data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +0 -180
  133. data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +0 -24
  134. data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +0 -18
  135. data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +0 -49
  136. data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +0 -29
  137. data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +0 -32
  138. data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +0 -101
  139. data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +0 -108
  140. data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +0 -26
  141. data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +0 -28
  142. data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +0 -67
  143. data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +0 -65
  144. data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +0 -68
  145. data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +0 -61
  146. data/lib/aws-sdk-code-generator/generators/resource_class.rb +0 -325
  147. data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +0 -83
  148. data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +0 -42
  149. data/lib/aws-sdk-code-generator/generators/service_documentation.rb +0 -64
  150. data/lib/aws-sdk-code-generator/generators/shared_example.rb +0 -132
  151. data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +0 -95
  152. data/lib/aws-sdk-code-generator/generators/syntax_example.rb +0 -169
  153. data/lib/aws-sdk-code-generator/generators/types_module.rb +0 -52
  154. data/lib/aws-sdk-code-generator/generators/waiter_class.rb +0 -62
  155. data/lib/aws-sdk-code-generator/generators/waiters_module.rb +0 -20
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceBatchAction
5
+ class << self
6
+
7
+ # @return [Array<ResourceMethod>]
8
+ def build_list(resource_name, resource, api)
9
+ resource.fetch('batchActions', {}).map do |name, action|
10
+ method_name = build_method_name(name, action)
11
+ ResourceMethod.new.tap do |m|
12
+ m.method_name = method_name
13
+ m.arguments = 'options = {}'
14
+ m.code = code(action, api)
15
+ m.documentation = docs(method_name, resource_name, action, api)
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def code(action, api)
23
+ ResourceBatchActionCode.new(action: action, api: api).build
24
+ end
25
+
26
+ def docs(method_name, resource_name, action, api)
27
+ ResourceBatchActionDocumentation.new(
28
+ method_name: method_name,
29
+ var_name: Underscore.underscore(resource_name),
30
+ action: action,
31
+ api: api
32
+ ).build
33
+ end
34
+
35
+ def build_method_name(name, action)
36
+ method_name = "batch_" + Underscore.underscore(name)
37
+ method_name += '!' if dangerous?(name, action)
38
+ method_name
39
+ end
40
+
41
+ def dangerous?(name, action)
42
+ if
43
+ name.match(/delete/i) ||
44
+ name.match(/terminate/i) ||
45
+ action['request']['operation'].match(/delete/i) ||
46
+ action['request']['operation'].match(/terminate/i)
47
+ then
48
+ true
49
+ else
50
+ false
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceBatchActionCode
5
+
6
+ def initialize(options)
7
+ @action = options.fetch(:action)
8
+ @api = options.fetch(:api)
9
+ compute_params
10
+ end
11
+
12
+ # @return [String]
13
+ def build
14
+ parts = []
15
+ parts << 'batch_enum.each do |batch|'
16
+ parts << initialize_params
17
+ parts << apply_params_per_batch
18
+ parts << " batch[0].client.#{client_method}(params)"
19
+ parts << 'end'
20
+ parts << 'nil'
21
+ parts.join("\n").rstrip
22
+ end
23
+
24
+ private
25
+
26
+ def compute_params
27
+ @batch_obj = {}
28
+ @per_batch = {}
29
+ @action_prefix = false
30
+ @action['request']['params'].each do |param|
31
+ if param['target'].include?('[')
32
+ parts = param['target'].split('[')
33
+ pair = parts[0].split('.')
34
+ if pair.length > 1
35
+ @action_prefix = pair.first
36
+ end
37
+ batch_name = pair.last
38
+ batch_param = underscore(parts[1].sub(/.*?\./, ''))
39
+ batch_param = batch_param == "" ? underscore(param['name']) : batch_param
40
+ (@batch_obj[batch_name] ||= []) << {
41
+ batch_param.to_sym => underscore(param['name'] || param['path'])
42
+ }
43
+ else
44
+ @per_batch[param['target']] = underscore(param['name'])
45
+ end
46
+ end
47
+ end
48
+
49
+ def client_method
50
+ Underscore.underscore(@action['request']['operation'])
51
+ end
52
+
53
+ def initialize_params
54
+ param_block = []
55
+ param_block << " params = Aws::Util.copy_hash(options)"
56
+ param_block << apply_param_hash
57
+ param_block.join("\n")
58
+ end
59
+
60
+ def apply_param_hash
61
+ block = []
62
+ @per_batch.each do |key, value|
63
+ block << " params[:#{underscore(key)}] = batch[0].#{value}"
64
+ end
65
+ if @action_prefix
66
+ action = underscore(@action_prefix)
67
+ block << " params[:#{action}] ||= {}"
68
+ @batch_obj.keys.each do |key|
69
+ block << " params[:#{action}][:#{underscore(key)}] ||= []"
70
+ end
71
+ else
72
+ @batch_obj.keys.each {|key| block << " params[:#{underscore(key)}] ||= []"}
73
+ end
74
+ block.join("\n")
75
+ end
76
+
77
+ def apply_params_per_batch
78
+ each_batch = []
79
+ each_batch << " batch.each do |item|"
80
+ @batch_obj.each do |key, value|
81
+ hash = {}
82
+ value.each do |v|
83
+ param, identifier = v.first
84
+ hash[param.to_sym] = "item.#{identifier}"
85
+ end
86
+ first_line = @action_prefix ? " params[:#{underscore(@action_prefix)}][:#{underscore(key)}] << "
87
+ : " params[:#{underscore(key)}] << "
88
+ if list_of_string?(key, @action['request']['operation'])
89
+ _, v = hash.first
90
+ each_batch << first_line + v
91
+ else
92
+ each_batch << first_line + "{"
93
+ # hashformatter treats this as inline, need extra indent
94
+ indent_count = hash.size == 1 ? 3 : 2
95
+ each_batch << indent_helper(HashFormatter.new(wrap: false).format(hash), indent_count)
96
+ each_batch << " }"
97
+ end
98
+ end
99
+ each_batch << " end"
100
+ each_batch.join("\n")
101
+ end
102
+
103
+ def indent_helper(lines, count)
104
+ block = []
105
+ lines.split("\n").each do |line|
106
+ next if line.strip == ""
107
+ block << " " * count + line
108
+ end
109
+ block.join("\n")
110
+ end
111
+
112
+ def underscore(str)
113
+ Underscore.underscore(str)
114
+ end
115
+
116
+ def list_of_string?(member, operation_name)
117
+ operation_shape = @api['operations'][operation_name]
118
+ input_shape = @api['shapes'][operation_shape['input']['shape']]
119
+
120
+ members = input_shape['type'] == 'structure' ? 'members' : 'member'
121
+ if @action_prefix
122
+ prefix_shape_ref = input_shape[members][@action_prefix]
123
+ _, prefix_shape = Api.resolve(prefix_shape_ref, @api)
124
+ prefix_members = prefix_shape['type'] == 'structure' ? 'members' : 'member'
125
+ member_shape_ref = prefix_shape[prefix_members][member]
126
+ else
127
+ member_shape_ref = input_shape[members][member]
128
+ end
129
+ _, shape = Api.resolve(member_shape_ref, @api)
130
+ return false unless shape['type'] == 'list'
131
+ _, item_shape = Api.resolve(shape['member'], @api)
132
+ item_shape['type'] == 'string'
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceBatchActionDocumentation
5
+
6
+ def initialize(options)
7
+ @var_name = options.fetch(:var_name)
8
+ @method_name = options.fetch(:method_name)
9
+ @action = options.fetch(:action)
10
+ @api = options.fetch(:api)
11
+ compute_params
12
+ end
13
+
14
+ # @return [String]
15
+ def build
16
+ Docstring.join_docstrings([
17
+ request_syntax_example,
18
+ '# @param options ({})',
19
+ option_tags,
20
+ "# @return [void]",
21
+ ], block_comment: false, separator: false)
22
+ end
23
+
24
+ private
25
+
26
+ def request_syntax_example
27
+ if input_ref
28
+ SyntaxExample.new(
29
+ api: @api,
30
+ shape: input_shape,
31
+ method_name: @method_name,
32
+ receiver: @var_name,
33
+ resp_var: nil,
34
+ skip: skip_params
35
+ ).format
36
+ end
37
+ end
38
+
39
+ def skip_params
40
+ skip = []
41
+ if @action_prefix
42
+ skip << @action_prefix
43
+ else
44
+ skip += @per_batch.keys
45
+ skip += @batch_obj.keys
46
+ end
47
+ skip + ResourceSkipParams.compute(input_shape, @action['request'])
48
+ end
49
+
50
+ def option_tags
51
+ skip = skip_params
52
+ if input_shape = Api.shape(input_ref, @api)
53
+ input_shape['members'].map do |member_name, member_ref|
54
+ if skip.include?(member_name)
55
+ nil # skipped
56
+ else
57
+ YardOptionTag.new(
58
+ name: Underscore.underscore(member_name),
59
+ required: input_shape.fetch('required', []).include?(member_name),
60
+ ruby_type: Api.ruby_input_type(member_ref, @api),
61
+ docstring: Docstring.html_to_markdown(Api.docstring(member_ref, @api)),
62
+ ).to_str
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def input_ref
69
+ @api['operations'][@action['request']['operation']]['input']
70
+ end
71
+
72
+ def input_shape
73
+ Api.shape(input_ref, @api)
74
+ end
75
+
76
+ def compute_params
77
+ @batch_obj = {}
78
+ @per_batch = {}
79
+ @action_prefix = false
80
+ @action['request']['params'].each do |param|
81
+ if param['target'].include?('[')
82
+ parts = param['target'].split('[')
83
+ pair = parts[0].split('.')
84
+ if pair.length > 1
85
+ @action_prefix = pair.first
86
+ end
87
+ batch_name = pair.last
88
+ batch_param = underscore(parts[1].sub(/.*?\./, ''))
89
+ batch_param = batch_param == "" ? underscore(param['name']) : batch_param
90
+ (@batch_obj[batch_name] ||= []) << {
91
+ batch_param.to_sym => underscore(param['name'] || param['path'])
92
+ }
93
+ else
94
+ @per_batch[param['target']] = underscore(param['name'])
95
+ end
96
+ end
97
+ end
98
+
99
+ def client_method
100
+ underscore(@action['request']['operation'])
101
+ end
102
+
103
+ def underscore(str)
104
+ Underscore.underscore(str)
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module AwsSdkCodeGenerator
6
+ class ResourceBatchBuilder
7
+
8
+ # @option options [required, Hash] :resource
9
+ # @option options [String] :resp_var_name ('resp')
10
+ def initialize(options)
11
+ @resource = options.fetch(:resource)
12
+ @resp_var_name = options.fetch(:resp_var_name, 'resp')
13
+ verify_resource!
14
+ @context = loop_context
15
+ @indent = options.fetch(:indent, '')
16
+ end
17
+
18
+ def build
19
+ code = ''
20
+ loops = self.send(:loops)
21
+ count = loops.size
22
+ loops.each.with_index do |loop_expression, n|
23
+ i = ' ' * n
24
+ code += "#{i}#{loop_expression}\n"
25
+ if n == count - 1
26
+ code += i + ' ' + Docstring.indent("batch << #{resource_class}.new(#{constructor_args})\n", i + ' ')
27
+ end
28
+ end
29
+ (count).times do |n|
30
+ i = ' ' * (count - n - 1)
31
+ code += "#{i}end\n"
32
+ end
33
+ code.rstrip
34
+ end
35
+
36
+ private
37
+
38
+ def resource_class
39
+ @resource['type']
40
+ end
41
+
42
+ def constructor_args
43
+ hash = {}
44
+ hash.update(identifiers)
45
+ hash[:data] = data_path if @resource['path']
46
+ hash[:client] = "@client"
47
+ HashFormatter.new(wrap:false, inline:true).format(hash)
48
+ end
49
+
50
+ def identifiers
51
+ (@resource['identifiers'] || []).inject({}) do |hash, identifier|
52
+ value = relative_identifier_path(identifier)
53
+ hash[underscore(identifier['target']).to_sym] = value
54
+ hash
55
+ end
56
+ end
57
+
58
+ def data_path
59
+ relative_identifier_path({
60
+ 'source' => 'data',
61
+ 'path' => @resource['path'],
62
+ })
63
+ end
64
+
65
+ def relative_identifier_path(identifier)
66
+ path = identifier['path']
67
+ if path && path.include?('[]')
68
+ prefix = loops.last.match(/\|(.+)\|/)[1]
69
+ suffix = underscore(path[common_prefix.length..-1])
70
+ unless @context == :response
71
+ suffix = suffix.gsub(/\.\w+/) { |word| "[:#{word[1..-1]}]" }
72
+ end
73
+ suffix.length == 0 ? prefix : prefix + suffix
74
+ else
75
+ ResourceValueSource.new(identifier).to_s
76
+ end
77
+ end
78
+
79
+ def common_prefix
80
+ paths = plural_paths
81
+ if paths.empty?
82
+ ''
83
+ elsif paths.size == 1
84
+ # grab everything upto and including the final []
85
+ paths.first.match(/(.+\[\]).*?$/)[1]
86
+ else
87
+ prefix = find_prefix(paths)
88
+ prefix = prefix.sub(/\[\].+?$/, '[]')
89
+ if prefix[-2..-1] != '[]'
90
+ msg = 'response paths must have a common prefix ending in [], got :'
91
+ msg << paths.inspect
92
+ raise ArgumentError, msg
93
+ else
94
+ prefix
95
+ end
96
+ end
97
+ end
98
+
99
+ def find_prefix(paths)
100
+ prefix = ''
101
+ loop.with_index do |_, n|
102
+ return prefix if paths.empty?
103
+ letter = paths[0][n]
104
+ paths.each do |path|
105
+ return prefix if path[n].nil?
106
+ return prefix if path[n] != letter
107
+ end
108
+ prefix += letter
109
+ end
110
+ end
111
+
112
+ def loops
113
+ loop_var =
114
+ case @context
115
+ when :data then 'data'
116
+ when :options then 'options'
117
+ when :response then "#{@resp_var_name}.data."
118
+ end
119
+
120
+ used_vars = Set.new
121
+ used_vars << loop_var
122
+
123
+ parts = common_prefix.split('[]')
124
+ parts = parts.map.with_index do |part,n|
125
+ part = underscore(part)
126
+ unless @context == :response
127
+ part = part.gsub(/\w+/) { |word| "[:#{word}]" }
128
+ part = part.gsub(/\./, '')
129
+ end
130
+ part = "#{loop_var}#{part}"
131
+ loop_var = loop_letter(part, used_vars)
132
+ part = part + ".each do |#{loop_var}|"
133
+ part
134
+ end
135
+ parts
136
+ end
137
+
138
+ def loop_letter(str, used_vars)
139
+ letter = if @context == :options
140
+ str.scan(/:\w/).last[1]
141
+ else
142
+ str.split('.').last[0]
143
+ end
144
+ n = 1
145
+ var = letter
146
+ while used_vars.include?(var)
147
+ n += 1
148
+ var = "#{letter}#{n}"
149
+ end
150
+ used_vars << var
151
+ var
152
+ end
153
+
154
+ def all_plural_paths
155
+ paths = {}
156
+ @resource['identifiers'].each do |i|
157
+ if i['path'] && i['path'].include?('[]')
158
+ paths[i['source']] ||= []
159
+ paths[i['source']] << i['path']
160
+ end
161
+ end
162
+ paths
163
+ end
164
+
165
+ def plural_paths
166
+ all_plural_paths.values.first
167
+ end
168
+
169
+ def verify_resource!
170
+ verify_plural_paths!
171
+ end
172
+
173
+ def verify_plural_paths!
174
+ paths = all_plural_paths
175
+ case paths.size
176
+ when 0
177
+ msg = 'expected at least one plural identifier path, got none'
178
+ raise ArgumentError, msg
179
+ when 1
180
+ case paths.keys.first
181
+ when 'requestParameter'
182
+ when 'response'
183
+ when 'data'
184
+ else
185
+ msg = "unsupported identifier source #{paths.keys.first.inspect}"
186
+ raise ArgumentError, msg
187
+ end
188
+ else
189
+ msg = 'mixing plural source types is not supported'
190
+ raise ArgumentError, msg
191
+ end
192
+ end
193
+
194
+ def loop_context
195
+ case all_plural_paths.keys
196
+ when ['response'] then :response
197
+ when ['data'] then :data
198
+ when ['requestParameter'] then :options
199
+ else
200
+ msg = "unable to determine loop context: #{@resource.inspect}"
201
+ raise msg
202
+ end
203
+ end
204
+
205
+ def underscore(str)
206
+ str.split('.').map do |part|
207
+ Underscore.underscore(part)
208
+ end.join('.')
209
+ end
210
+
211
+ end
212
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceBuilder
5
+
6
+ # @option options [required, Hash] :resource
7
+ # @option options [required, Boolean] :request_made
8
+ def initialize(options = {})
9
+ @resource = options.fetch(:resource)
10
+ @request_made = options.fetch(:request_made)
11
+ end
12
+
13
+ def build
14
+ "#{resource_class}.new(#{constructor_options})"
15
+ end
16
+
17
+ private
18
+
19
+ def resource_class
20
+ @resource['type']
21
+ end
22
+
23
+ def constructor_options
24
+ options = {}
25
+ options.update(identifiers)
26
+ options[:data] = data_path if @resource['path']
27
+ options[:client] = "@client"
28
+ HashFormatter.new(wrap:false).format(options)
29
+ end
30
+
31
+ def identifiers
32
+ (@resource['identifiers'] || []).inject({}) do |hash, identifier|
33
+ value = ResourceValueSource.new(identifier).to_s
34
+ hash[Underscore.underscore(identifier['target']).to_sym] = value
35
+ hash
36
+ end
37
+ end
38
+
39
+ def data_path
40
+ if @request_made
41
+ ResourceValueSource.new('source' => 'response', 'path' => @resource['path'])
42
+ else
43
+ ResourceValueSource.new('source' => 'data', 'path' => @resource['path'])
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceClientRequest
5
+ class << self
6
+
7
+ # @option options [required, Hash] :request
8
+ # @option options [Boolean] :resp (false)
9
+ # @option options [Boolean] :merge (true)
10
+ def build(options)
11
+ request = options.fetch(:request)
12
+ merge = options.fetch(:merge, true)
13
+ streaming = options.fetch(:streaming, false)
14
+ params = ResourceClientRequestParams.new(params: request['params'])
15
+ parts = []
16
+ parts << request_options(params) if merge
17
+ parts << assignment(options)
18
+ parts << "@client."
19
+ parts << operation_name(request)
20
+ parts << arguments(merge, params, streaming)
21
+ parts.join
22
+ end
23
+
24
+ private
25
+
26
+ def request_options(params)
27
+ if params.empty?
28
+ ''
29
+ elsif params.simple?
30
+ "options = options.merge(#{params})\n"
31
+ else
32
+ hash = params
33
+ hash = ' ' + hash unless hash[0] == "\n"
34
+ "options = Aws::Util.deep_merge(options,#{hash})\n"
35
+ end
36
+ end
37
+
38
+ def assignment(options)
39
+ if options.fetch(:resp, false)
40
+ 'resp = '
41
+ else
42
+ ''
43
+ end
44
+ end
45
+
46
+ def operation_name(request)
47
+ Underscore.underscore(request['operation'])
48
+ end
49
+
50
+ def arguments(merge, params, streaming)
51
+ if merge
52
+ streaming ? '(options, &block)' : '(options)'
53
+ elsif params.empty?
54
+ ''
55
+ else
56
+ streaming ? "(#{params}, &block)" : "(#{params})"
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module AwsSdkCodeGenerator
6
+ class ResourceClientReqeustDocumentation
7
+
8
+ def initialize(options)
9
+ @api = options.fetch(:api)
10
+ @method_name = options.fetch(:method_name)
11
+ @receiver = options.fetch(:receiver)
12
+ @resp_var = options.fetch(:resp_var, nil)
13
+ @request = options.fetch(:request)
14
+ @shape_ref = @api['operations'][@request['operation']]['input']
15
+ @returns = options.fetch(:returns, nil)
16
+ @skip = Set.new(options.fetch(:skip, []) + ResourceSkipParams.compute(input_shape, @request))
17
+ end
18
+
19
+ def build
20
+ Docstring.join_docstrings([
21
+ request_syntax_example,
22
+ param_tag,
23
+ option_tags,
24
+ return_tag,
25
+ ], block_comment: false, separator: false)
26
+ end
27
+
28
+ private
29
+
30
+ def request_syntax_example
31
+ if @shape_ref && Api.shape(@shape_ref, @api)['members'].count - @skip.count > 0
32
+ SyntaxExample.new(
33
+ api: @api,
34
+ shape: input_shape,
35
+ method_name: @method_name,
36
+ receiver: @receiver,
37
+ resp_var: @resp_var,
38
+ skip: @skip,
39
+ ).format
40
+ else
41
+ # TODO : remove these empty examples, not really needed
42
+ <<-DOCS.rstrip
43
+ # @example Request syntax with placeholder values
44
+ #
45
+ # #{@receiver}.#{@method_name}()
46
+ DOCS
47
+ end
48
+ end
49
+
50
+ def param_tag
51
+ '# @param [Hash] options ({})'
52
+ end
53
+
54
+ def option_tags
55
+ if input_shape
56
+ input_shape['members'].map do |member_name, member_ref|
57
+ next if @skip.include?(member_name)
58
+ YardOptionTag.new(
59
+ name: Underscore.underscore(member_name),
60
+ required: input_shape.fetch('required', []).include?(member_name),
61
+ ruby_type: Api.ruby_input_type(member_ref, @api),
62
+ docstring: Docstring.html_to_markdown(Api.docstring(member_ref, @api)),
63
+ ).to_str
64
+ end
65
+ end
66
+ end
67
+
68
+ def input_shape
69
+ Api.shape(@shape_ref, @api)
70
+ end
71
+
72
+ def return_tag
73
+ if @returns
74
+ "# @return [#{@returns}]"
75
+ else
76
+ nil
77
+ end
78
+ end
79
+
80
+ end
81
+ end