gapic-generator 0.1.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/lib/gapic/formatting_utils.rb +63 -12
  4. data/lib/gapic/generator/version.rb +1 -1
  5. data/lib/gapic/generators/base_generator.rb +0 -8
  6. data/lib/gapic/generators/default_generator.rb +13 -14
  7. data/lib/gapic/helpers/filepath_helper.rb +45 -0
  8. data/lib/gapic/helpers/namespace_helper.rb +51 -0
  9. data/lib/gapic/presenters.rb +44 -0
  10. data/{templates/default/helpers → lib/gapic}/presenters/enum_presenter.rb +19 -14
  11. data/{templates/default/helpers → lib/gapic}/presenters/enum_value_presenter.rb +19 -12
  12. data/lib/gapic/presenters/field_presenter.rb +154 -0
  13. data/lib/gapic/presenters/file_presenter.rb +59 -0
  14. data/lib/gapic/presenters/gem_presenter.rb +176 -0
  15. data/lib/gapic/presenters/message_presenter.rb +73 -0
  16. data/lib/gapic/presenters/method_presenter.rb +307 -0
  17. data/lib/gapic/presenters/package_presenter.rb +80 -0
  18. data/lib/gapic/presenters/resource_presenter.rb +99 -0
  19. data/lib/gapic/presenters/sample_presenter.rb +84 -0
  20. data/lib/gapic/presenters/service_presenter.rb +306 -0
  21. data/lib/gapic/resource_lookup.rb +23 -38
  22. data/lib/gapic/schema/api.rb +70 -0
  23. data/lib/gapic/schema/loader.rb +9 -2
  24. data/lib/gapic/schema/wrappers.rb +134 -24
  25. data/templates/default/gem/entrypoint.erb +8 -0
  26. data/templates/default/gem/gemspec.erb +2 -2
  27. data/templates/default/gem/readme.erb +17 -3
  28. data/templates/default/gem/rubocop.erb +13 -41
  29. data/templates/default/helpers/filepath_helper.rb +2 -21
  30. data/templates/default/helpers/namespace_helper.rb +2 -27
  31. data/templates/default/layouts/_ruby.erb +1 -3
  32. data/templates/default/lib/_package.erb +17 -0
  33. data/templates/default/lib/_service.erb +32 -0
  34. data/templates/default/package.erb +5 -5
  35. data/templates/default/service.erb +5 -7
  36. data/templates/default/service/_helpers.erb +3 -0
  37. data/templates/default/service/client/_client.erb +7 -17
  38. data/templates/default/service/client/_operations.erb +0 -4
  39. data/templates/default/service/client/_paths.erb +1 -0
  40. data/templates/default/service/client/method/def/_options_defaults.erb +1 -1
  41. data/templates/default/service/client/method/def/_response_normal.erb +1 -1
  42. data/templates/default/service/client/method/docs/_request_normal.erb +10 -5
  43. data/templates/default/service/client/method/docs/_request_streaming.erb +1 -1
  44. metadata +20 -15
  45. data/templates/default/helpers/presenter_helper.rb +0 -24
  46. data/templates/default/helpers/presenters/field_presenter.rb +0 -146
  47. data/templates/default/helpers/presenters/file_presenter.rb +0 -53
  48. data/templates/default/helpers/presenters/gem_presenter.rb +0 -140
  49. data/templates/default/helpers/presenters/message_presenter.rb +0 -66
  50. data/templates/default/helpers/presenters/method_presenter.rb +0 -293
  51. data/templates/default/helpers/presenters/package_presenter.rb +0 -65
  52. data/templates/default/helpers/presenters/resource_presenter.rb +0 -92
  53. data/templates/default/helpers/presenters/sample_presenter.rb +0 -74
  54. data/templates/default/helpers/presenters/service_presenter.rb +0 -276
  55. data/templates/default/service/client/_helpers.erb +0 -9
@@ -51,6 +51,15 @@ module Gapic
51
51
  loader.load_file fd, request.file_to_generate.include?(fd.name)
52
52
  end
53
53
  @files.each { |f| f.parent = self }
54
+ @resource_types = analyze_resources
55
+ end
56
+
57
+ def containing_api
58
+ self
59
+ end
60
+
61
+ def containing_file
62
+ nil
54
63
  end
55
64
 
56
65
  def lookup address
@@ -200,6 +209,22 @@ module Gapic
200
209
  end
201
210
  end
202
211
 
212
+ # Whether the generate_path_helpers_output parameter was given in the configuration
213
+ def generate_path_helpers_output_defined?
214
+ configuration.key? :generate_path_helpers_output
215
+ end
216
+
217
+ # Sets the generate_path_helpers_output parameter in the configuration
218
+ def generate_path_helpers_output= value
219
+ configuration[:generate_path_helpers_output] = value
220
+ end
221
+
222
+ # Whether to generate path helpers for output as well as input messages
223
+ def generate_path_helpers_output?
224
+ # if not set in configuration, false by default
225
+ configuration[:generate_path_helpers_output] ||= false
226
+ end
227
+
203
228
  # Raw parsed json of the combined grpc service config files if provided
204
229
  # or an empty hash if no config was provided
205
230
  def grpc_service_config_raw
@@ -219,8 +244,53 @@ module Gapic
219
244
  end
220
245
  end
221
246
 
247
+ # Get a resource given its type string
248
+ def lookup_resource_type resource_type
249
+ @resource_types[resource_type]
250
+ end
251
+
222
252
  private
223
253
 
254
+ # Does a pre-analysis of all resources defined in the job. This has
255
+ # two effects:
256
+ # * Side effect: each resource has its parent_resources field set.
257
+ # * A mapping from resource type to resource wrapper is returned.
258
+ def analyze_resources
259
+ # In order to set parent_resources, we first populate a mapping from
260
+ # parsed pattern to resource mapping (in the patterns variable). This
261
+ # is done in one pass along with populating the resource type mapping.
262
+ # Then, we go through all resources again, get its expected parent
263
+ # patterns, and anything that shows up in the patterns mapping is taken
264
+ # to be a parent.
265
+ types = {}
266
+ patterns = {}
267
+ @files.each do |file|
268
+ file.resources.each { |resource| populate_resource_lookups resource, types, patterns }
269
+ file.messages.each { |message| populate_message_resource_lookups message, types, patterns }
270
+ end
271
+ types.each do |_type, resource|
272
+ parents = resource.parsed_parent_patterns
273
+ .map { |pat| patterns[pat] }
274
+ .compact.uniq
275
+ resource.parent_resources.replace parents
276
+ end
277
+ types
278
+ end
279
+
280
+ def populate_resource_lookups resource, types, patterns
281
+ types[resource.type] = resource
282
+ resource.parsed_patterns.each do |pat|
283
+ patterns[pat] = resource
284
+ end
285
+ end
286
+
287
+ def populate_message_resource_lookups message, types, patterns
288
+ populate_resource_lookups message.resource, types, patterns if message.resource
289
+ message.nested_messages.each do |nested|
290
+ populate_message_resource_lookups nested, types, patterns
291
+ end
292
+ end
293
+
224
294
  def parse_parameter str
225
295
  str.scan(/\\.|,|=|[^\\,=]+/)
226
296
  .each_with_object([[String.new]]) do |tok, arr|
@@ -64,9 +64,13 @@ module Gapic
64
64
  load_service registry, s, address, docs, [6, i]
65
65
  end
66
66
 
67
+ # Load top-level resources
68
+ resource_descriptors = file_descriptor.options[:".google.api.resource_definition"] if file_descriptor.options
69
+ resources = Array(resource_descriptors).map { |descriptor| Resource.new descriptor }
70
+
67
71
  # Construct and return the file.
68
72
  File.new file_descriptor, address, docs[path], messages, enums,
69
- services, file_to_generate, registry
73
+ services, resources, file_to_generate, registry
70
74
  end
71
75
 
72
76
  # Updates the fields of a message and it's nested messages.
@@ -158,9 +162,12 @@ module Gapic
158
162
  load_field registry, e, address, docs, path + [6, i]
159
163
  end
160
164
 
165
+ resource_descriptor = descriptor.options[:".google.api.resource"] if descriptor.options
166
+ resource = resource_descriptor ? Resource.new(resource_descriptor) : nil
167
+
161
168
  # Construct, cache, and return.
162
169
  msg = Message.new(descriptor, address, docs[path], fields, extensions,
163
- nested_messages, nested_enums)
170
+ resource, nested_messages, nested_enums)
164
171
  @prior_messages << msg
165
172
  add_to_registry registry, address, msg
166
173
  end
@@ -95,14 +95,33 @@ module Gapic
95
95
  @docs = docs
96
96
  end
97
97
 
98
+ # Returns the "root" of this schema.
99
+ # @return [Gapic::Schema::Api]
100
+ def containing_api
101
+ parent&.containing_api
102
+ end
103
+
104
+ # Returns the file containing this proto entity
105
+ # @return [Gapic::Schema::File]
106
+ def containing_file
107
+ parent&.containing_file
108
+ end
109
+
110
+ ##
98
111
  # Gets the cleaned up leading comments documentation
99
- def docs_leading_comments
112
+ #
113
+ # @param disable_xrefs [Boolean] (default is `false`) Disable linking to
114
+ # cross-references, and render them simply as text. This can be used if
115
+ # it is known that the targets are not present in the current library.
116
+ # @return [String]
117
+ #
118
+ def docs_leading_comments disable_xrefs: false
100
119
  return nil if @docs.nil?
101
120
  return nil if @docs.leading_comments.empty?
102
121
 
103
122
  lines = @docs.leading_comments.each_line.to_a
104
123
  lines.map! { |line| line.start_with?(" ") ? line[1..-1] : line }
105
- lines = FormattingUtils.escape_braces lines
124
+ lines = FormattingUtils.format_doc_lines containing_api, lines, disable_xrefs: disable_xrefs
106
125
  lines.join
107
126
  end
108
127
 
@@ -338,16 +357,19 @@ module Gapic
338
357
  # Wrapper for a protobuf file.
339
358
  #
340
359
  # @!attribute [r] messages
341
- # @ return [Enumerable<Message>] The top level messages contained in
360
+ # @return [Enumerable<Message>] The top level messages contained in
342
361
  # this file.
343
362
  # @!attribute [r] enums
344
- # @ return [Enumerable<Enum>] The top level enums contained in this
363
+ # @return [Enumerable<Enum>] The top level enums contained in this
345
364
  # file.
346
365
  # @!attribute [r] services
347
- # @ return [Enumerable<Service>] The services contained in this file.
366
+ # @return [Enumerable<Service>] The services contained in this file.
367
+ # @!attribute [r] resources
368
+ # @return [Enumerable<Resource>] The top level resources contained in
369
+ # this file.
348
370
  class File < Proto
349
371
  extend Forwardable
350
- attr_reader :messages, :enums, :services, :registry
372
+ attr_reader :messages, :enums, :services, :resources, :registry
351
373
 
352
374
  # Initializes a message object.
353
375
  # @param descriptor [Google::Protobuf::DescriptorProto] the protobuf
@@ -360,20 +382,27 @@ module Gapic
360
382
  # file.
361
383
  # @param enums [Enumerable<Enum>] The top level enums of this file.
362
384
  # @param services [Enumerable<Service>] The services of this file.
385
+ # @param resources [Enumerable<Resource>] The resources from this file.
363
386
  # @param generate [Boolean] Whether this file should be generated.
364
387
  def initialize descriptor, address, docs, messages, enums, services,
365
- generate, registry
388
+ resources, generate, registry
366
389
  super descriptor, address, docs
367
390
  @messages = messages || []
368
391
  @enums = enums || []
369
392
  @services = services || []
393
+ @resources = resources || []
370
394
  @generate = generate
371
395
  @registry = registry
372
396
 
373
397
  # Apply parent
374
398
  @messages.each { |m| m.parent = self }
375
- @enums.each { |m| m.parent = self }
399
+ @enums.each { |m| m.parent = self }
376
400
  @services.each { |m| m.parent = self }
401
+ @resources.each { |m| m.parent = self }
402
+ end
403
+
404
+ def containing_file
405
+ self
377
406
  end
378
407
 
379
408
  def lookup address
@@ -390,13 +419,6 @@ module Gapic
390
419
  options[:ruby_package] if options
391
420
  end
392
421
 
393
- # @return [Array<Google::Api::ResourceDescriptor>] A representation of the resource.
394
- # This is generally intended to be attached to the "name" field.
395
- # See `google/api/resource.proto`.
396
- def resources
397
- options[:".google.api.resource_definition"] if options
398
- end
399
-
400
422
  # @!method name
401
423
  # @return [String] file name, relative to root of source tree.
402
424
  # @!method package
@@ -488,6 +510,8 @@ module Gapic
488
510
  # @ return [Enumerable<Field>] The fields of a message.
489
511
  # @!attribute [r] extensions
490
512
  # @ return [Enumerable<Field>] The extensions of a message.
513
+ # @!attribute [r] resource
514
+ # @ return [Resource,nil] A representation of the resource.
491
515
  # @!attribute [r] nested_messages
492
516
  # @ return [Enumerable<Message>] The nested message declarations of a
493
517
  # message.
@@ -495,7 +519,7 @@ module Gapic
495
519
  # @ return [Enumerable<Enum>] The nested enum declarations of a message.
496
520
  class Message < Proto
497
521
  extend Forwardable
498
- attr_reader :fields, :extensions, :nested_messages, :nested_enums
522
+ attr_reader :fields, :extensions, :resource, :nested_messages, :nested_enums
499
523
 
500
524
  # Initializes a message object.
501
525
  # @param descriptor [Google::Protobuf::DescriptorProto] the protobuf
@@ -506,15 +530,17 @@ module Gapic
506
530
  # of the proto. See #docs for more info.
507
531
  # @param fields [Enumerable<Field>] The fields of this message.
508
532
  # @param extensions [Enumerable<Field>] The extensions of this message.
533
+ # @param resource [Resource,nil] The resource of this message, or nil if none.
509
534
  # @param nested_messages [Enumerable<Message>] The nested message
510
535
  # declarations of this message.
511
536
  # @param nested_enums [Enumerable<Enum>] The nested enum declarations
512
537
  # of this message.
513
- def initialize descriptor, address, docs, fields, extensions,
538
+ def initialize descriptor, address, docs, fields, extensions, resource,
514
539
  nested_messages, nested_enums
515
540
  super descriptor, address, docs
516
541
  @fields = fields || []
517
542
  @extensions = extensions || []
543
+ @resource = resource
518
544
  @nested_messages = nested_messages || []
519
545
  @nested_enums = nested_enums || []
520
546
 
@@ -522,13 +548,7 @@ module Gapic
522
548
  @extensions.each { |x| x.parent = self }
523
549
  @nested_messages.each { |m| m.parent = self }
524
550
  @nested_enums.each { |e| e.parent = self }
525
- end
526
-
527
- # @return [Google::Api::ResourceDescriptor] A representation of the resource.
528
- # This is generally intended to be attached to the "name" field.
529
- # See `google/api/resource.proto`.
530
- def resource
531
- options[:".google.api.resource"] if options
551
+ @resource.parent = self if @resource
532
552
  end
533
553
 
534
554
  # @return [Boolean] whether this type is a map entry
@@ -713,5 +733,95 @@ module Gapic
713
733
  :options
714
734
  )
715
735
  end
736
+
737
+ # Wrapper for a protobuf Resource.
738
+ #
739
+ # Unlike most wrappers, this does not subclass the {Proto} wrapper because
740
+ # it does not use the fields exposed by that wrapper (`address`, `docs`,
741
+ # etc.) This is here principally to augment the resource definition with
742
+ # information about resource parent-child relationships.
743
+ #
744
+ # Resource parentage is defined implicitly by path patterns. The algorithm
745
+ # is as follows:
746
+ # * If the final segment of a pattern is an ID segment (i.e. `*` or some
747
+ # `{name}`) then remove it and the previous segment (which we assume to
748
+ # be the corresponding collection identifier, as described in AIP-122.)
749
+ # The resulting pattern is what we expect a parent to have.
750
+ # * If the final segment is static, then assume the pattern represents a
751
+ # singleton resource (AIP-156) and remove only that one segment. The
752
+ # resulting pattern is what we expect a parent to have.
753
+ #
754
+ # The {Resource#parsed_parent_patterns} method returns the set of patterns
755
+ # we expect of parents. It is then possible to search for resources with
756
+ # those patterns to determine what the parents are.
757
+ #
758
+ # @!attribute [rw] parent
759
+ # @return [Gapic::Schema::File,Gapic::Schema::Message] The parent object.
760
+ # @!attribute [r] descriptor
761
+ # @return [Array<Gapic::Schema::ResourceDescriptor>] The resource
762
+ # descriptor.
763
+ # @!attribute [r] parsed_patterns
764
+ # @return [Array<Array<String>>] The normalized, segmented forms of the
765
+ # patterns. Normalized means all ID segments are replaced by asterisks
766
+ # to remove non-structural differences due to different names being
767
+ # used. Segmented means simply split on slashes.
768
+ # For example, if a pattern is `"projects/{project}""`, the
769
+ # corresponding parsed pattern would be `["projects", "*"]`.
770
+ # @!attribute [r] parent_resources
771
+ # @return [Array<Gapic::Schema::Resource>] Parent resources
772
+ class Resource
773
+ extend Forwardable
774
+ attr_reader :descriptor, :parsed_patterns, :parent_resources
775
+ attr_accessor :parent
776
+
777
+ # Initializes a resource object.
778
+ # @param descriptor [Google::Protobuf::ResourceDescriptor] the protobuf
779
+ # representation of this resource.
780
+ def initialize descriptor
781
+ @parent = nil
782
+ @descriptor = descriptor
783
+ @parsed_patterns = descriptor.pattern.map do |pattern|
784
+ pattern.split("/").map do |segment|
785
+ segment =~ %r{\{[^/\}]+(=[^\}]+)?\}} ? "*" : segment
786
+ end.freeze
787
+ end.freeze
788
+ @parent_resources = []
789
+ end
790
+
791
+ # Returns the "root" of this schema.
792
+ # @return [Gapic::Schema::Api]
793
+ def containing_api
794
+ parent&.containing_api
795
+ end
796
+
797
+ # Returns the file containing this proto entity
798
+ # @return [Gapic::Schema::File]
799
+ def containing_file
800
+ parent&.containing_file
801
+ end
802
+
803
+ # Returns parsed patterns for the expected parents.
804
+ # @return [Array<Array<String>>]
805
+ def parsed_parent_patterns
806
+ @parsed_patterns.map do |pat|
807
+ parent = pat.last =~ /^\*\*?$/ ? pat[0...-2] : pat[0...-1]
808
+ parent.empty? ? nil : parent
809
+ end.compact.uniq
810
+ end
811
+
812
+ # @!method type
813
+ # @return [String] the resource type string.
814
+ # @!method pattern
815
+ # @return [Array<String>] the set of patterns.
816
+ # @!method name_field
817
+ # @return [String] the field on the resource that designates the
818
+ # resource name field. If omitted, this is assumed to be "name".
819
+ def_delegators(
820
+ :descriptor,
821
+ :type,
822
+ :pattern,
823
+ :name_field
824
+ )
825
+ end
716
826
  end
717
827
  end
@@ -0,0 +1,8 @@
1
+ <%- assert_locals gem -%>
2
+ <%= render partial: "shared/header" -%>
3
+
4
+ # This gem does not autoload during Bundler.require. To load this gem,
5
+ # issue explicit require statements for the packages desired, e.g.:
6
+ <%- gem.packages.each do |package| -%>
7
+ # require "<%= package.package_require %>"
8
+ <%- end -%>
@@ -23,9 +23,9 @@ Gem::Specification.new do |gem|
23
23
 
24
24
  gem.required_ruby_version = ">= 2.4"
25
25
 
26
- gem.add_dependency "gapic-common", "~> 0.1.0"
26
+ gem.add_dependency "gapic-common", "~> 0.2"
27
27
  <%- if gem.iam_dependency? -%>
28
- gem.add_dependency "grpc-google-iam-v1", "~> 0.6.9"
28
+ gem.add_dependency "grpc-google-iam-v1", ">= 0.6.10", "< 2.0"
29
29
  <%- end -%>
30
30
 
31
31
  gem.add_development_dependency "google-style", "~> 1.24.0"
@@ -1,9 +1,9 @@
1
- # <%= gem.title %>
2
-
3
- <%= gem.description %>
1
+ # Ruby Client for the <%= gem.title %> API
4
2
 
5
3
  <%= gem.summary %>
6
4
 
5
+ <%= gem.description %>
6
+
7
7
  <%= gem.homepage %>
8
8
 
9
9
  ## Installation
@@ -12,6 +12,20 @@
12
12
  $ gem install <%= gem.name %>
13
13
  ```
14
14
 
15
+ ## Quick Start
16
+
17
+ ```ruby
18
+ require "<%= gem.entrypoint_require %>"
19
+ <%- service = gem.packages.first&.services.first -%>
20
+ <%- method = service&.methods.first -%>
21
+ <%- if service && method -%>
22
+
23
+ client = <%= service.create_client_call %>
24
+ request = my_create_request
25
+ response = client.<%= method.name %> request
26
+ <%- end -%>
27
+ ```
28
+
15
29
  ## Supported Ruby Versions
16
30
 
17
31
  This library is supported on Ruby 2.4+.
@@ -9,51 +9,23 @@ AllCops:
9
9
  - "test/**/*"
10
10
 
11
11
  Metrics/AbcSize:
12
- Exclude:
13
- <%- gem.packages.each do |package| -%>
14
- <%- package.services.each do |service| -%>
15
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
16
- <%- end -%>
17
- <%- end -%>
12
+ Enabled: false
18
13
  Metrics/ClassLength:
19
- Exclude:
20
- <%- gem.packages.each do |package| -%>
21
- <%- package.services.each do |service| -%>
22
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
23
- <%- end -%>
24
- <%- end -%>
14
+ Enabled: false
25
15
  Metrics/CyclomaticComplexity:
26
- Exclude:
27
- <%- gem.packages.each do |package| -%>
28
- <%- package.services.each do |service| -%>
29
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
30
- <%- end -%>
31
- <%- end -%>
16
+ Enabled: false
32
17
  Metrics/LineLength:
33
- Exclude:
34
- <%- gem.packages.each do |package| -%>
35
- <%- package.services.each do |service| -%>
36
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
37
- <%- end -%>
38
- <%- end -%>
18
+ Enabled: false
39
19
  Metrics/MethodLength:
40
- Exclude:
41
- <%- gem.packages.each do |package| -%>
42
- <%- package.services.each do |service| -%>
43
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
44
- <%- end -%>
45
- <%- end -%>
20
+ Enabled: false
46
21
  Metrics/PerceivedComplexity:
22
+ Enabled: false
23
+ Naming/FileName:
47
24
  Exclude:
48
- <%- gem.packages.each do |package| -%>
49
- <%- package.services.each do |service| -%>
50
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
51
- <%- end -%>
52
- <%- end -%>
25
+ - "lib/<%= gem.name %>.rb"
53
26
  Style/CaseEquality:
54
- Exclude:
55
- <%- gem.packages.each do |package| -%>
56
- <%- package.services.each do |service| -%>
57
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
58
- <%- end -%>
59
- <%- end -%>
27
+ Enabled: false
28
+ Style/IfUnlessModifier:
29
+ Enabled: false
30
+ Style/ModuleFunction:
31
+ Enabled: false