gapic-generator 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +13 -0
  3. data/CHANGELOG.md +38 -0
  4. data/CODE_OF_CONDUCT.md +43 -0
  5. data/CONTRIBUTING.md +28 -0
  6. data/LICENSE +202 -0
  7. data/README.md +72 -0
  8. data/bin/gapic-generator +103 -0
  9. data/bin/protoc-gen-ruby_gapic +33 -0
  10. data/default-rubocop.yml +10 -0
  11. data/gem_templates/binary.erb +20 -0
  12. data/gem_templates/dockerfile.erb +39 -0
  13. data/gem_templates/entrypoint.erb +24 -0
  14. data/gem_templates/gapic_sh.erb +97 -0
  15. data/gem_templates/gemfile.erb +8 -0
  16. data/gem_templates/gemspec.erb +36 -0
  17. data/gem_templates/generator.erb +37 -0
  18. data/gem_templates/gitignore.erb +10 -0
  19. data/gem_templates/rakefile.erb +29 -0
  20. data/gem_templates/readme.erb +69 -0
  21. data/gem_templates/rubocop.erb +16 -0
  22. data/gem_templates/shared/_header.erb +4 -0
  23. data/gem_templates/shared/_license.erb +13 -0
  24. data/gem_templates/shared/_warning.erb +1 -0
  25. data/gem_templates/test_generator.erb +13 -0
  26. data/gem_templates/test_helper.erb +25 -0
  27. data/gem_templates/version.erb +10 -0
  28. data/lib/gapic/file_formatter.rb +62 -0
  29. data/lib/gapic/gem_builder.rb +98 -0
  30. data/lib/gapic/generator.rb +30 -0
  31. data/lib/gapic/generator/version.rb +21 -0
  32. data/lib/gapic/generators/base_generator.rb +91 -0
  33. data/lib/gapic/generators/default_generator.rb +101 -0
  34. data/lib/gapic/grpc_service_config/method_config.rb +49 -0
  35. data/lib/gapic/grpc_service_config/parser.rb +218 -0
  36. data/lib/gapic/grpc_service_config/parsing_error.rb +25 -0
  37. data/lib/gapic/grpc_service_config/retry_policy.rb +51 -0
  38. data/lib/gapic/grpc_service_config/service_config.rb +42 -0
  39. data/lib/gapic/path_template.rb +35 -0
  40. data/lib/gapic/path_template/parser.rb +83 -0
  41. data/lib/gapic/path_template/segment.rb +67 -0
  42. data/lib/gapic/resource_lookup.rb +91 -0
  43. data/lib/gapic/runner.rb +76 -0
  44. data/lib/gapic/schema.rb +17 -0
  45. data/lib/gapic/schema/api.rb +264 -0
  46. data/lib/gapic/schema/loader.rb +269 -0
  47. data/lib/gapic/schema/wrappers.rb +718 -0
  48. data/lib/google/api/annotations.pb.rb +39 -0
  49. data/lib/google/api/client.pb.rb +43 -0
  50. data/lib/google/api/field_behavior.pb.rb +51 -0
  51. data/lib/google/api/http.pb.rb +60 -0
  52. data/lib/google/api/resource.pb.rb +80 -0
  53. data/lib/google/longrunning/operations.pb.rb +115 -0
  54. data/lib/google/protobuf/any.pb.rb +40 -0
  55. data/lib/google/protobuf/compiler/plugin.pb.rb +72 -0
  56. data/lib/google/protobuf/descriptor.pb.rb +359 -0
  57. data/lib/google/protobuf/empty.pb.rb +36 -0
  58. data/lib/google/rpc/status.pb.rb +46 -0
  59. data/templates/default/gem/_version.erb +2 -0
  60. data/templates/default/gem/changelog.erb +3 -0
  61. data/templates/default/gem/gemfile.erb +4 -0
  62. data/templates/default/gem/gemspec.erb +37 -0
  63. data/templates/default/gem/gitignore.erb +18 -0
  64. data/templates/default/gem/license.erb +22 -0
  65. data/templates/default/gem/rakefile.erb +27 -0
  66. data/templates/default/gem/readme.erb +24 -0
  67. data/templates/default/gem/rubocop.erb +59 -0
  68. data/templates/default/gem/version.erb +6 -0
  69. data/templates/default/gem/yardopts.erb +12 -0
  70. data/templates/default/helpers/default_helper.rb +56 -0
  71. data/templates/default/helpers/filepath_helper.rb +38 -0
  72. data/templates/default/helpers/namespace_helper.rb +44 -0
  73. data/templates/default/helpers/presenter_helper.rb +24 -0
  74. data/templates/default/helpers/presenters/enum_presenter.rb +35 -0
  75. data/templates/default/helpers/presenters/enum_value_presenter.rb +33 -0
  76. data/templates/default/helpers/presenters/field_presenter.rb +146 -0
  77. data/templates/default/helpers/presenters/file_presenter.rb +53 -0
  78. data/templates/default/helpers/presenters/gem_presenter.rb +140 -0
  79. data/templates/default/helpers/presenters/message_presenter.rb +66 -0
  80. data/templates/default/helpers/presenters/method_presenter.rb +293 -0
  81. data/templates/default/helpers/presenters/package_presenter.rb +65 -0
  82. data/templates/default/helpers/presenters/resource_presenter.rb +92 -0
  83. data/templates/default/helpers/presenters/sample_presenter.rb +74 -0
  84. data/templates/default/helpers/presenters/service_presenter.rb +276 -0
  85. data/templates/default/layouts/_ruby.erb +20 -0
  86. data/templates/default/package.erb +6 -0
  87. data/templates/default/proto_docs/_enum.erb +13 -0
  88. data/templates/default/proto_docs/_message.erb +23 -0
  89. data/templates/default/proto_docs/_proto_file.erb +9 -0
  90. data/templates/default/proto_docs/proto_file.erb +6 -0
  91. data/templates/default/proto_docs/readme.erb +5 -0
  92. data/templates/default/service.erb +8 -0
  93. data/templates/default/service/client.erb +6 -0
  94. data/templates/default/service/client/_client.erb +137 -0
  95. data/templates/default/service/client/_config.erb +155 -0
  96. data/templates/default/service/client/_credentials.erb +21 -0
  97. data/templates/default/service/client/_helpers.erb +9 -0
  98. data/templates/default/service/client/_operations.erb +88 -0
  99. data/templates/default/service/client/_paths.erb +8 -0
  100. data/templates/default/service/client/_requires.erb +1 -0
  101. data/templates/default/service/client/_resource.erb +6 -0
  102. data/templates/default/service/client/_self_configure.erb +9 -0
  103. data/templates/default/service/client/_self_configure_defaults.erb +22 -0
  104. data/templates/default/service/client/_self_configure_retry_policy.erb +15 -0
  105. data/templates/default/service/client/method/_def.erb +21 -0
  106. data/templates/default/service/client/method/def/_options_defaults.erb +29 -0
  107. data/templates/default/service/client/method/def/_request.erb +6 -0
  108. data/templates/default/service/client/method/def/_request_normal.erb +4 -0
  109. data/templates/default/service/client/method/def/_request_streaming.erb +9 -0
  110. data/templates/default/service/client/method/def/_rescue.erb +1 -0
  111. data/templates/default/service/client/method/def/_response.erb +6 -0
  112. data/templates/default/service/client/method/def/_response_normal.erb +8 -0
  113. data/templates/default/service/client/method/def/_response_paged.erb +9 -0
  114. data/templates/default/service/client/method/docs/_error.erb +2 -0
  115. data/templates/default/service/client/method/docs/_request.erb +6 -0
  116. data/templates/default/service/client/method/docs/_request_field.erb +7 -0
  117. data/templates/default/service/client/method/docs/_request_normal.erb +20 -0
  118. data/templates/default/service/client/method/docs/_request_streaming.erb +5 -0
  119. data/templates/default/service/client/method/docs/_response.erb +6 -0
  120. data/templates/default/service/client/method/docs/_sample.erb +20 -0
  121. data/templates/default/service/client/method/docs/_sample_response.erb +24 -0
  122. data/templates/default/service/client/method/docs/_samples.erb +6 -0
  123. data/templates/default/service/client/method/docs/request_field/_arg.erb +10 -0
  124. data/templates/default/service/client/method/docs/request_field/_hash.erb +19 -0
  125. data/templates/default/service/client/method/docs/sample_response/_comment.erb +5 -0
  126. data/templates/default/service/client/method/docs/sample_response/_define.erb +2 -0
  127. data/templates/default/service/client/method/docs/sample_response/_loop.erb +12 -0
  128. data/templates/default/service/client/method/docs/sample_response/_print.erb +2 -0
  129. data/templates/default/service/client/method/docs/sample_response/_write_file.erb +2 -0
  130. data/templates/default/service/client/resource/_def.erb +6 -0
  131. data/templates/default/service/client/resource/_doc.erb +8 -0
  132. data/templates/default/service/client/resource/_multi.erb +28 -0
  133. data/templates/default/service/client/resource/_single.erb +11 -0
  134. data/templates/default/service/credentials.erb +6 -0
  135. data/templates/default/service/operations.erb +6 -0
  136. data/templates/default/service/paths.erb +6 -0
  137. data/templates/default/service/test/client.erb +24 -0
  138. data/templates/default/service/test/client_operations.erb +24 -0
  139. data/templates/default/service/test/method/_assert_response.erb +11 -0
  140. data/templates/default/service/test/method/_bidi.erb +100 -0
  141. data/templates/default/service/test/method/_client.erb +84 -0
  142. data/templates/default/service/test/method/_normal.erb +69 -0
  143. data/templates/default/service/test/method/_server.erb +85 -0
  144. data/templates/default/service/test/method/_setup.erb +21 -0
  145. data/templates/default/service/test/smoke.erb +12 -0
  146. data/templates/default/shared/_header.erb +4 -0
  147. data/templates/default/shared/_license.erb +21 -0
  148. data/templates/default/shared/_warning.erb +1 -0
  149. metadata +350 -0
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "active_support/inflector"
18
+
19
+ class FieldPresenter
20
+ include NamespaceHelper
21
+
22
+ def initialize api, message, field
23
+ @api = api
24
+ @message = message
25
+ @field = field
26
+ end
27
+
28
+ def name
29
+ @field.name
30
+ end
31
+
32
+ def doc_types
33
+ field_doc_types @field, false
34
+ end
35
+
36
+ def doc_attribute_type
37
+ mode = @field.output_only? ? "r" : "rw"
38
+ "@!attribute [#{mode}] #{@field.name}"
39
+ end
40
+
41
+ def output_doc_types
42
+ field_doc_types @field, true
43
+ end
44
+
45
+ def doc_description
46
+ @field.docs_leading_comments
47
+ end
48
+
49
+ def default_value
50
+ single = default_singular_value
51
+ return "[#{single}]" if @field.repeated? && !@field.map?
52
+ single
53
+ end
54
+
55
+ def as_kwarg value: nil
56
+ "#{name}: #{value || name}"
57
+ end
58
+
59
+ # TODO: remove, only used in tests
60
+ def type_name
61
+ @field.type_name
62
+ end
63
+
64
+ def type_name_full
65
+ return nil if type_name.blank?
66
+ ruby_namespace @api, type_name
67
+ end
68
+
69
+ def message?
70
+ @field.message?
71
+ end
72
+
73
+ def enum?
74
+ @field.enum?
75
+ end
76
+
77
+ def repeated?
78
+ @field.repeated?
79
+ end
80
+
81
+ def map?
82
+ @field.map?
83
+ end
84
+
85
+ protected
86
+
87
+ def field_doc_types field, output
88
+ return field_map_type field.message, output if field.map?
89
+ base_type =
90
+ if field.message?
91
+ type = message_ruby_type field.message
92
+ output ? type : "#{type} | Hash"
93
+ elsif field.enum?
94
+ # TODO: handle when arg message is nil and enum is the type
95
+ message_ruby_type field.enum
96
+ else
97
+ case field.type
98
+ when 1, 2 then "Float"
99
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "Integer"
100
+ when 9, 12 then "String"
101
+ when 8 then "Boolean"
102
+ else
103
+ "Object"
104
+ end
105
+ end
106
+ field.repeated? ? "Array<#{base_type}>" : base_type
107
+ end
108
+
109
+ def field_map_type entry_message, output
110
+ key_field = value_field = nil
111
+ entry_message.fields.each do |field|
112
+ key_field = field if field.name == "key"
113
+ value_field = field if field.name == "value"
114
+ end
115
+ class_name = output ? "Google::Protobuf::Map" : "Hash"
116
+ if key_field && value_field
117
+ key_type = field_doc_types key_field, output
118
+ value_type = field_doc_types value_field, output
119
+ "#{class_name}{#{key_type} => #{value_type}}"
120
+ else
121
+ class_name
122
+ end
123
+ end
124
+
125
+ def default_singular_value
126
+ if @field.message?
127
+ "{}"
128
+ elsif @field.enum?
129
+ # TODO: select the first non-0 enum value
130
+ ":#{@field.enum.values.first.name}"
131
+ else
132
+ case @field.type
133
+ when 1, 2 then "3.5"
134
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "42"
135
+ when 9, 12 then "\"hello world\""
136
+ when 8 then "true"
137
+ else
138
+ "Object"
139
+ end
140
+ end
141
+ end
142
+
143
+ def message_ruby_type message
144
+ ruby_namespace @api, message.address.join(".")
145
+ end
146
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative "enum_presenter"
18
+ require_relative "message_presenter"
19
+
20
+ class FilePresenter
21
+ include NamespaceHelper
22
+
23
+ # @param file [Gapic::Schema::File] the file to present
24
+ def initialize api, file
25
+ @api = api
26
+ @file = file
27
+ end
28
+
29
+ def name
30
+ @file.name
31
+ end
32
+
33
+ def address
34
+ @file.address
35
+ end
36
+
37
+ def namespace
38
+ return @file.ruby_package if @file.ruby_package.present?
39
+ ruby_namespace_for_address address
40
+ end
41
+
42
+ def messages
43
+ @messages ||= @file.messages.map { |m| MessagePresenter.new @api, m }
44
+ end
45
+
46
+ def enums
47
+ @enums ||= @file.enums.map { |e| EnumPresenter.new e }
48
+ end
49
+
50
+ def docs_file_path
51
+ @file.name.gsub ".proto", ".rb"
52
+ end
53
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative "file_presenter"
18
+ require_relative "package_presenter"
19
+ require_relative "service_presenter"
20
+
21
+ class GemPresenter
22
+ include FilepathHelper
23
+ include NamespaceHelper
24
+
25
+ def initialize api
26
+ @api = api
27
+ end
28
+
29
+ def packages
30
+ @packages ||= begin
31
+ packages = @api.generate_files.map(&:package).uniq.sort
32
+ packages.map { |p| PackagePresenter.new @api, p }.delete_if(&:empty?)
33
+ end
34
+ end
35
+
36
+ def services
37
+ @services ||= begin
38
+ files = @api.generate_files
39
+ files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
40
+ end
41
+ end
42
+
43
+ def proto_files
44
+ @proto_files ||= begin
45
+ files = @api.files
46
+ files = files.reject { |f| blacklist_protos.include? f.name }
47
+ files = files.reject { |f| f.messages.empty? && f.enums.empty? }
48
+ files.map { |f| FilePresenter.new @api, f }
49
+ end
50
+ end
51
+
52
+ def address
53
+ name.split("-").map(&:camelize)
54
+ end
55
+
56
+ def name
57
+ gem_config :name
58
+ end
59
+
60
+ def namespace
61
+ gem_config(:namespace) ||
62
+ fix_namespace(@api, name.split("-").map(&:camelize).join("::"))
63
+ end
64
+
65
+ def title
66
+ gem_config(:title) ||
67
+ namespace.split("::").join(" ")
68
+ end
69
+
70
+ def version
71
+ gem_config(:version) ||
72
+ "0.0.1"
73
+ end
74
+
75
+ def version_require
76
+ ruby_file_path @api, version_name_full
77
+ end
78
+
79
+ def version_file_path
80
+ "#{version_require}.rb"
81
+ end
82
+
83
+ def version_name_full
84
+ "#{namespace}::VERSION"
85
+ end
86
+
87
+ def authors
88
+ gem_config(:authors) ||
89
+ ["Google LLC"]
90
+ end
91
+
92
+ def email
93
+ gem_config(:email) ||
94
+ "googleapis-packages@google.com"
95
+ end
96
+
97
+ def description
98
+ gem_config(:description) ||
99
+ "#{name} is the official library for #{title} API."
100
+ end
101
+
102
+ def summary
103
+ gem_config(:summary) ||
104
+ "API Client library for #{title} API"
105
+ end
106
+
107
+ def homepage
108
+ gem_config(:homepage) ||
109
+ "https://github.com/googleapis/googleapis"
110
+ end
111
+
112
+ def env_prefix
113
+ (gem_config(:env_prefix) || name.split("-").last).upcase
114
+ end
115
+
116
+ def iam_dependency?
117
+ @api.files.map(&:name).include? "google/iam/v1/iam_policy.proto"
118
+ end
119
+
120
+ private
121
+
122
+ def gem_config key
123
+ return unless @api.configuration[:gem]
124
+
125
+ @api.configuration[:gem][key]
126
+ end
127
+
128
+ def blacklist_protos
129
+ blacklist = gem_config :blacklist
130
+
131
+ return default_blacklist_protos if blacklist.nil?
132
+ return default_blacklist_protos if blacklist[:protos].nil?
133
+
134
+ default_blacklist_protos[:protos]
135
+ end
136
+
137
+ def default_blacklist_protos
138
+ ["google/api/http.proto", "google/protobuf/descriptor.proto"]
139
+ end
140
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "active_support/inflector"
18
+
19
+ require_relative "field_presenter"
20
+
21
+ class MessagePresenter
22
+ include NamespaceHelper
23
+
24
+ def initialize api, message
25
+ @api = api
26
+ @message = message
27
+ end
28
+
29
+ def name
30
+ @message.name
31
+ end
32
+
33
+ def doc_types
34
+ type_name_full
35
+ end
36
+
37
+ def doc_description
38
+ @message.docs_leading_comments
39
+ end
40
+
41
+ def default_value
42
+ "{}"
43
+ end
44
+
45
+ def type_name_full
46
+ message_ruby_type @message
47
+ end
48
+
49
+ def fields
50
+ @fields = @message.fields.map { |f| FieldPresenter.new @api, @message, f }
51
+ end
52
+
53
+ def nested_enums
54
+ @nested_enums ||= @message.nested_enums.map { |e| EnumPresenter.new e }
55
+ end
56
+
57
+ def nested_messages
58
+ @nested_messages ||= @message.nested_messages.map { |m| MessagePresenter.new @api, m }
59
+ end
60
+
61
+ protected
62
+
63
+ def message_ruby_type message
64
+ ruby_namespace @api, message.address.join(".")
65
+ end
66
+ end
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "active_support/inflector"
18
+ require "gapic/path_template"
19
+ require_relative "service_presenter"
20
+ require_relative "field_presenter"
21
+ require_relative "sample_presenter"
22
+
23
+ class MethodPresenter
24
+ include NamespaceHelper
25
+
26
+ def initialize api, method
27
+ @api = api
28
+ @method = method
29
+ end
30
+
31
+ def service
32
+ ServicePresenter.new @api, @method.parent
33
+ end
34
+
35
+ def name
36
+ ActiveSupport::Inflector.underscore @method.name
37
+ end
38
+
39
+ def kind
40
+ if client_streaming?
41
+ if server_streaming?
42
+ :bidi
43
+ else
44
+ :client
45
+ end
46
+ elsif server_streaming?
47
+ :server
48
+ else
49
+ :normal
50
+ end
51
+ end
52
+
53
+ def doc_description
54
+ @method.docs_leading_comments
55
+ end
56
+
57
+ def doc_response_type
58
+ ret = return_type
59
+ ret = "Gapic::Operation" if lro?
60
+ if server_streaming?
61
+ ret = "Enumerable<#{ret}>"
62
+ elsif paged?
63
+ paged_type = paged_response_type
64
+ paged_type = "Gapic::Operation" if paged_type == "Google::Longrunning::Operation"
65
+ ret = "Gapic::PagedEnumerable<#{paged_type}>"
66
+ end
67
+ ret
68
+ end
69
+
70
+ def arguments
71
+ arguments = @method.input.fields.reject(&:output_only?)
72
+ arguments.map { |arg| FieldPresenter.new @api, @method.input, arg }
73
+ end
74
+
75
+ def fields
76
+ @method.input.fields.map { |field| FieldPresenter.new @api, @method.input, field }
77
+ end
78
+
79
+ def fields_with_first_oneof
80
+ return fields if @method.input.oneof_decl.empty?
81
+
82
+ selected_fields = []
83
+ have_oneof = []
84
+
85
+ @method.input.fields.each do |field|
86
+ idx = field.oneof_index
87
+ selected_fields << field unless have_oneof.include? idx
88
+ have_oneof << idx
89
+ end
90
+
91
+ selected_fields.map { |field| FieldPresenter.new @api, @method.input, field }
92
+ end
93
+
94
+ def request_type
95
+ message_ruby_type @method.input
96
+ end
97
+
98
+ def return_type
99
+ message_ruby_type @method.output
100
+ end
101
+
102
+ def yields?
103
+ # Server streaming RCP calls are the only one that does not yield
104
+ !server_streaming?
105
+ end
106
+
107
+ def yield_doc_description
108
+ return "Register a callback to be run when an operation is done." if lro?
109
+
110
+ "Access the result along with the RPC operation"
111
+ end
112
+
113
+ def yield_params
114
+ if lro?
115
+ return [
116
+ OpenStruct.new(
117
+ name: "operation",
118
+ doc_types: "Gapic::Operation"
119
+ )
120
+ ]
121
+ end
122
+ [
123
+ OpenStruct.new(
124
+ name: "result",
125
+ doc_types: return_type
126
+ ),
127
+ OpenStruct.new(
128
+ name: "operation",
129
+ doc_types: "GRPC::ActiveCall::Operation"
130
+ )
131
+ ]
132
+ end
133
+
134
+ # @api.incode samples and sample_configs are yaml configuration files such as
135
+ # speech_transcribe_sync_gcs.yaml
136
+ def samples
137
+ sample_configs = @api.incode_samples.select do |sample_config|
138
+ sample_config["service"] == @method.address[0...-1].join(".") &&
139
+ sample_config["rpc"] == @method.name
140
+ end
141
+ sample_configs.map { |sample_config| SamplePresenter.new @api, sample_config }
142
+ end
143
+
144
+ def lro?
145
+ return paged_response_type == "Google::Longrunning::Operation" if paged?
146
+
147
+ message_ruby_type(@method.output) == "Google::Longrunning::Operation"
148
+ end
149
+
150
+ def client_streaming?
151
+ @method.client_streaming
152
+ end
153
+
154
+ def server_streaming?
155
+ @method.server_streaming
156
+ end
157
+
158
+ def paged?
159
+ return false if server_streaming? # Cannot page a streaming response
160
+ paged_request?(@method.input) && paged_response?(@method.output)
161
+ end
162
+
163
+ def paged_response_type
164
+ return nil unless paged_response? @method.output
165
+
166
+ repeated_field = @method.output.fields.find do |f|
167
+ f.label == Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED &&
168
+ f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
169
+ end
170
+ message_ruby_type repeated_field.message
171
+ end
172
+
173
+ ##
174
+ #
175
+ # @return [Array<String>] The segment key names.
176
+ #
177
+ def routing_params
178
+ segments = Gapic::PathTemplate.parse method_path
179
+ segments.select { |s| s.is_a? Gapic::PathTemplate::Segment }.map(&:name)
180
+ end
181
+
182
+ def routing_params?
183
+ routing_params.any?
184
+ end
185
+
186
+ def grpc_service_config
187
+ if @api.grpc_service_config&.service_method_level_configs&.key?(service.grpc_full_name) &&
188
+ @api.grpc_service_config.service_method_level_configs[service.grpc_full_name]&.key?(grpc_method_name)
189
+ @api.grpc_service_config.service_method_level_configs[service.grpc_full_name][grpc_method_name]
190
+ end
191
+ end
192
+
193
+ def grpc_method_name
194
+ @method.name
195
+ end
196
+
197
+ protected
198
+
199
+ def message_ruby_type message
200
+ ruby_namespace @api, message.address.join(".")
201
+ end
202
+
203
+ def doc_types_for arg
204
+ if arg.message?
205
+ "#{message_ruby_type arg.message} | Hash"
206
+ elsif arg.enum?
207
+ # TODO: handle when arg message is nil and enum is the type
208
+ message_ruby_type arg.enum
209
+ else
210
+ case arg.type
211
+ when 1, 2 then "Float"
212
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "Integer"
213
+ when 9, 12 then "String"
214
+ when 8 then "Boolean"
215
+ else
216
+ "Object"
217
+ end
218
+ end
219
+ end
220
+
221
+ def doc_desc_for arg
222
+ return nil if arg.docs.leading_comments.empty?
223
+
224
+ arg.docs.leading_comments
225
+ end
226
+
227
+ def default_value_for arg
228
+ if arg.message?
229
+ "{}"
230
+ elsif arg.enum?
231
+ # TODO: select the first non-0 enum value
232
+ # ":ENUM"
233
+ arg.enum.values.first
234
+ else
235
+ case arg.type
236
+ when 1, 2 then "3.14"
237
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "42"
238
+ when 9, 12 then "\"hello world\""
239
+ when 8 then "true"
240
+ else
241
+ "Object"
242
+ end
243
+ end
244
+ end
245
+
246
+ def method_path
247
+ return "" if @method.http.nil?
248
+
249
+ method = [
250
+ @method.http.get, @method.http.post, @method.http.put,
251
+ @method.http.patch, @method.http.delete
252
+ ].find { |x| !x.empty? }
253
+ return method unless method.nil?
254
+
255
+ return @method.http.custom.path unless @method.http.custom.nil?
256
+ end
257
+
258
+ def paged_request? request
259
+ page_token = request.fields.find do |f|
260
+ f.name == "page_token" && f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
261
+ end
262
+ return false if page_token.nil?
263
+
264
+ page_size_types = [
265
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32,
266
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
267
+ ]
268
+ page_size = request.fields.find do |f|
269
+ f.name == "page_size" && page_size_types.include?(f.type)
270
+ end
271
+ return false if page_size.nil?
272
+
273
+ true
274
+ end
275
+
276
+ def paged_response? response
277
+ next_page_token = response.fields.find do |f|
278
+ f.name == "next_page_token" && f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
279
+ end
280
+ return false if next_page_token.nil?
281
+
282
+ repeated_field = response.fields.find do |f|
283
+ f.label == Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED &&
284
+ f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
285
+ end
286
+ return false if repeated_field.nil?
287
+
288
+ # We want to make sure the first repeated field is also has the lowest field number,
289
+ # but the google-protobuf gem sorts fields by number, so we lose the original order.
290
+
291
+ true
292
+ end
293
+ end