gapic-generator 0.1.4
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/.yardopts +13 -0
- data/CHANGELOG.md +43 -0
- data/CODE_OF_CONDUCT.md +43 -0
- data/CONTRIBUTING.md +28 -0
- data/LICENSE +202 -0
- data/README.md +72 -0
- data/bin/gapic-generator +103 -0
- data/bin/protoc-gen-ruby_gapic +33 -0
- data/default-rubocop.yml +10 -0
- data/gem_templates/binary.erb +20 -0
- data/gem_templates/dockerfile.erb +39 -0
- data/gem_templates/entrypoint.erb +24 -0
- data/gem_templates/gapic_sh.erb +97 -0
- data/gem_templates/gemfile.erb +8 -0
- data/gem_templates/gemspec.erb +36 -0
- data/gem_templates/generator.erb +37 -0
- data/gem_templates/gitignore.erb +10 -0
- data/gem_templates/rakefile.erb +29 -0
- data/gem_templates/readme.erb +69 -0
- data/gem_templates/rubocop.erb +16 -0
- data/gem_templates/shared/_header.erb +4 -0
- data/gem_templates/shared/_license.erb +13 -0
- data/gem_templates/shared/_warning.erb +1 -0
- data/gem_templates/test_generator.erb +13 -0
- data/gem_templates/test_helper.erb +25 -0
- data/gem_templates/version.erb +10 -0
- data/lib/gapic/file_formatter.rb +62 -0
- data/lib/gapic/formatting_utils.rb +109 -0
- data/lib/gapic/gem_builder.rb +98 -0
- data/lib/gapic/generator.rb +30 -0
- data/lib/gapic/generator/version.rb +21 -0
- data/lib/gapic/generators/base_generator.rb +91 -0
- data/lib/gapic/generators/default_generator.rb +101 -0
- data/lib/gapic/grpc_service_config/method_config.rb +49 -0
- data/lib/gapic/grpc_service_config/parser.rb +218 -0
- data/lib/gapic/grpc_service_config/parsing_error.rb +25 -0
- data/lib/gapic/grpc_service_config/retry_policy.rb +51 -0
- data/lib/gapic/grpc_service_config/service_config.rb +42 -0
- data/lib/gapic/path_template.rb +35 -0
- data/lib/gapic/path_template/parser.rb +83 -0
- data/lib/gapic/path_template/segment.rb +67 -0
- data/lib/gapic/resource_lookup.rb +91 -0
- data/lib/gapic/runner.rb +76 -0
- data/lib/gapic/schema.rb +17 -0
- data/lib/gapic/schema/api.rb +264 -0
- data/lib/gapic/schema/loader.rb +269 -0
- data/lib/gapic/schema/wrappers.rb +717 -0
- data/lib/google/api/annotations.pb.rb +39 -0
- data/lib/google/api/client.pb.rb +43 -0
- data/lib/google/api/field_behavior.pb.rb +51 -0
- data/lib/google/api/http.pb.rb +60 -0
- data/lib/google/api/resource.pb.rb +80 -0
- data/lib/google/longrunning/operations.pb.rb +115 -0
- data/lib/google/protobuf/any.pb.rb +40 -0
- data/lib/google/protobuf/compiler/plugin.pb.rb +72 -0
- data/lib/google/protobuf/descriptor.pb.rb +359 -0
- data/lib/google/protobuf/empty.pb.rb +36 -0
- data/lib/google/rpc/status.pb.rb +46 -0
- data/templates/default/gem/_version.erb +2 -0
- data/templates/default/gem/changelog.erb +3 -0
- data/templates/default/gem/gemfile.erb +4 -0
- data/templates/default/gem/gemspec.erb +37 -0
- data/templates/default/gem/gitignore.erb +20 -0
- data/templates/default/gem/license.erb +22 -0
- data/templates/default/gem/rakefile.erb +27 -0
- data/templates/default/gem/readme.erb +24 -0
- data/templates/default/gem/rubocop.erb +59 -0
- data/templates/default/gem/version.erb +6 -0
- data/templates/default/gem/yardopts.erb +12 -0
- data/templates/default/helpers/default_helper.rb +50 -0
- data/templates/default/helpers/filepath_helper.rb +38 -0
- data/templates/default/helpers/namespace_helper.rb +44 -0
- data/templates/default/helpers/presenter_helper.rb +24 -0
- data/templates/default/helpers/presenters/enum_presenter.rb +35 -0
- data/templates/default/helpers/presenters/enum_value_presenter.rb +33 -0
- data/templates/default/helpers/presenters/field_presenter.rb +146 -0
- data/templates/default/helpers/presenters/file_presenter.rb +53 -0
- data/templates/default/helpers/presenters/gem_presenter.rb +140 -0
- data/templates/default/helpers/presenters/message_presenter.rb +66 -0
- data/templates/default/helpers/presenters/method_presenter.rb +293 -0
- data/templates/default/helpers/presenters/package_presenter.rb +65 -0
- data/templates/default/helpers/presenters/resource_presenter.rb +92 -0
- data/templates/default/helpers/presenters/sample_presenter.rb +74 -0
- data/templates/default/helpers/presenters/service_presenter.rb +276 -0
- data/templates/default/layouts/_ruby.erb +20 -0
- data/templates/default/package.erb +6 -0
- data/templates/default/proto_docs/_enum.erb +13 -0
- data/templates/default/proto_docs/_message.erb +23 -0
- data/templates/default/proto_docs/_proto_file.erb +9 -0
- data/templates/default/proto_docs/proto_file.erb +6 -0
- data/templates/default/proto_docs/readme.erb +5 -0
- data/templates/default/service.erb +8 -0
- data/templates/default/service/client.erb +6 -0
- data/templates/default/service/client/_client.erb +137 -0
- data/templates/default/service/client/_config.erb +155 -0
- data/templates/default/service/client/_credentials.erb +21 -0
- data/templates/default/service/client/_helpers.erb +9 -0
- data/templates/default/service/client/_operations.erb +88 -0
- data/templates/default/service/client/_paths.erb +8 -0
- data/templates/default/service/client/_requires.erb +1 -0
- data/templates/default/service/client/_resource.erb +6 -0
- data/templates/default/service/client/_self_configure.erb +9 -0
- data/templates/default/service/client/_self_configure_defaults.erb +22 -0
- data/templates/default/service/client/_self_configure_retry_policy.erb +15 -0
- data/templates/default/service/client/method/_def.erb +21 -0
- data/templates/default/service/client/method/def/_options_defaults.erb +29 -0
- data/templates/default/service/client/method/def/_request.erb +6 -0
- data/templates/default/service/client/method/def/_request_normal.erb +4 -0
- data/templates/default/service/client/method/def/_request_streaming.erb +9 -0
- data/templates/default/service/client/method/def/_rescue.erb +1 -0
- data/templates/default/service/client/method/def/_response.erb +6 -0
- data/templates/default/service/client/method/def/_response_normal.erb +8 -0
- data/templates/default/service/client/method/def/_response_paged.erb +9 -0
- data/templates/default/service/client/method/docs/_error.erb +2 -0
- data/templates/default/service/client/method/docs/_request.erb +6 -0
- data/templates/default/service/client/method/docs/_request_field.erb +7 -0
- data/templates/default/service/client/method/docs/_request_normal.erb +20 -0
- data/templates/default/service/client/method/docs/_request_streaming.erb +5 -0
- data/templates/default/service/client/method/docs/_response.erb +6 -0
- data/templates/default/service/client/method/docs/_sample.erb +20 -0
- data/templates/default/service/client/method/docs/_sample_response.erb +24 -0
- data/templates/default/service/client/method/docs/_samples.erb +6 -0
- data/templates/default/service/client/method/docs/request_field/_arg.erb +10 -0
- data/templates/default/service/client/method/docs/request_field/_hash.erb +19 -0
- data/templates/default/service/client/method/docs/sample_response/_comment.erb +5 -0
- data/templates/default/service/client/method/docs/sample_response/_define.erb +2 -0
- data/templates/default/service/client/method/docs/sample_response/_loop.erb +12 -0
- data/templates/default/service/client/method/docs/sample_response/_print.erb +2 -0
- data/templates/default/service/client/method/docs/sample_response/_write_file.erb +2 -0
- data/templates/default/service/client/resource/_def.erb +6 -0
- data/templates/default/service/client/resource/_doc.erb +8 -0
- data/templates/default/service/client/resource/_multi.erb +28 -0
- data/templates/default/service/client/resource/_single.erb +11 -0
- data/templates/default/service/credentials.erb +6 -0
- data/templates/default/service/operations.erb +6 -0
- data/templates/default/service/paths.erb +6 -0
- data/templates/default/service/test/client.erb +24 -0
- data/templates/default/service/test/client_operations.erb +24 -0
- data/templates/default/service/test/method/_assert_response.erb +11 -0
- data/templates/default/service/test/method/_bidi.erb +100 -0
- data/templates/default/service/test/method/_client.erb +84 -0
- data/templates/default/service/test/method/_normal.erb +69 -0
- data/templates/default/service/test/method/_server.erb +85 -0
- data/templates/default/service/test/method/_setup.erb +21 -0
- data/templates/default/service/test/smoke.erb +12 -0
- data/templates/default/shared/_header.erb +4 -0
- data/templates/default/shared/_license.erb +21 -0
- data/templates/default/shared/_warning.erb +1 -0
- metadata +351 -0
|
@@ -0,0 +1,35 @@
|
|
|
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 "gapic/path_template/parser"
|
|
18
|
+
|
|
19
|
+
module Gapic
|
|
20
|
+
# TODO: Enter docs
|
|
21
|
+
# Dooooooooocs!!!
|
|
22
|
+
module PathTemplate
|
|
23
|
+
# Parse a URI path template.
|
|
24
|
+
#
|
|
25
|
+
# @see https://tools.ietf.org/html/rfc6570 URI Template
|
|
26
|
+
#
|
|
27
|
+
# @param path_template [String] The URI path template to be parsed.
|
|
28
|
+
#
|
|
29
|
+
# @return [Array<PathTemplate::Segment|String>] The segments of the URI
|
|
30
|
+
# path template.
|
|
31
|
+
def self.parse path_template
|
|
32
|
+
Parser.new(path_template).segments
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
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 "gapic/path_template/segment"
|
|
18
|
+
|
|
19
|
+
module Gapic
|
|
20
|
+
module PathTemplate
|
|
21
|
+
# A URI path template parser.
|
|
22
|
+
#
|
|
23
|
+
# @see https://tools.ietf.org/html/rfc6570 URI Template
|
|
24
|
+
#
|
|
25
|
+
# @!attribute [r] path_template
|
|
26
|
+
# @return [String] The URI path template to be parsed.
|
|
27
|
+
# @!attribute [r] segments
|
|
28
|
+
# @return [Array<Segment|String>] The segments of the parsed URI path
|
|
29
|
+
# template.
|
|
30
|
+
class Parser
|
|
31
|
+
# @private
|
|
32
|
+
# /((?<positional>\*\*?)|{(?<name>[^\/]+?)(?:=(?<template>.+?))?})/
|
|
33
|
+
PATH_TEMPLATE = %r{
|
|
34
|
+
(
|
|
35
|
+
(?<positional>\*\*?)
|
|
36
|
+
|
|
|
37
|
+
{(?<name>[^\/]+?)(?:=(?<template>.+?))?}
|
|
38
|
+
)
|
|
39
|
+
}x.freeze
|
|
40
|
+
|
|
41
|
+
attr_reader :path_template, :segments
|
|
42
|
+
|
|
43
|
+
# Create a new URI path template parser.
|
|
44
|
+
#
|
|
45
|
+
# @param path_template [String] The URI path template to be parsed.
|
|
46
|
+
def initialize path_template
|
|
47
|
+
@path_template = path_template
|
|
48
|
+
@segments = parse! path_template
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
protected
|
|
52
|
+
|
|
53
|
+
def parse! path_template
|
|
54
|
+
# segments contain either Strings or segment objects
|
|
55
|
+
segments = []
|
|
56
|
+
segment_pos = 0
|
|
57
|
+
|
|
58
|
+
while (match = PATH_TEMPLATE.match path_template)
|
|
59
|
+
# The String before the match needs to be added to the segments
|
|
60
|
+
segments << match.pre_match unless match.pre_match.empty?
|
|
61
|
+
|
|
62
|
+
segment, segment_pos = segment_and_pos_from_match match, segment_pos
|
|
63
|
+
segments << segment
|
|
64
|
+
|
|
65
|
+
path_template = match.post_match
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Whatever String is unmatched needs to be added to the segments
|
|
69
|
+
segments << path_template unless path_template.empty?
|
|
70
|
+
|
|
71
|
+
segments
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def segment_and_pos_from_match match, pos
|
|
75
|
+
if match[:positional]
|
|
76
|
+
[Segment.new(pos, match[:positional]), pos + 1]
|
|
77
|
+
else
|
|
78
|
+
[Segment.new(match[:name], match[:template]), pos]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
module Gapic
|
|
18
|
+
module PathTemplate
|
|
19
|
+
# A segment in a URI path template.
|
|
20
|
+
#
|
|
21
|
+
# @see https://tools.ietf.org/html/rfc6570 URI Template
|
|
22
|
+
#
|
|
23
|
+
# @!attribute [r] name
|
|
24
|
+
# @return [String, Integer] The name of a named segment, or the position
|
|
25
|
+
# of a positional segment.
|
|
26
|
+
# @!attribute [r] pattern
|
|
27
|
+
# @return [String, nil] The pattern of the segment, nil if not set.
|
|
28
|
+
class Segment
|
|
29
|
+
attr_reader :name, :pattern
|
|
30
|
+
|
|
31
|
+
def initialize name, pattern
|
|
32
|
+
@name = name
|
|
33
|
+
@pattern = pattern
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Determines if the segment is positional (has a number for a name).
|
|
37
|
+
#
|
|
38
|
+
# @return [Boolean]
|
|
39
|
+
def positional?
|
|
40
|
+
name.is_a? Integer
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Determines if the segment is named (has a string for a name).
|
|
44
|
+
#
|
|
45
|
+
# @return [Boolean]
|
|
46
|
+
def named?
|
|
47
|
+
!positional?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Determines if the segment has a pattern. Positional segments always
|
|
51
|
+
# have a pattern. Named segments may have a pattern if provided in the
|
|
52
|
+
# URI path template.
|
|
53
|
+
#
|
|
54
|
+
# @return [Boolean]
|
|
55
|
+
def pattern?
|
|
56
|
+
!@pattern.nil?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @private
|
|
60
|
+
def == other
|
|
61
|
+
return false unless other.is_a? self.class
|
|
62
|
+
|
|
63
|
+
(name == other.name) && (pattern == other.pattern)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2020 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
|
+
module Gapic
|
|
18
|
+
# TODO: Enter docs
|
|
19
|
+
# Dooooooooocs!!!
|
|
20
|
+
class ResourceLookup
|
|
21
|
+
# @private
|
|
22
|
+
def initialize service
|
|
23
|
+
@service = service
|
|
24
|
+
@api = service.parent.parent
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @private
|
|
28
|
+
def lookup!
|
|
29
|
+
resources = @api.files.flat_map { |file| lookup_file_resource_descriptors file }
|
|
30
|
+
resources.compact.uniq
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @private
|
|
34
|
+
def lookup_file_resource_descriptors file
|
|
35
|
+
resources = []
|
|
36
|
+
resources += file.resources.select { |resource| service_resource_types.include? resource.type }
|
|
37
|
+
resources += file.messages.flat_map { |message| lookup_message_resources_descriptors message }
|
|
38
|
+
resources
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @private
|
|
42
|
+
def service_resource_types
|
|
43
|
+
@service_resource_types ||= begin
|
|
44
|
+
@service.methods.flat_map do |method|
|
|
45
|
+
message_resource_types method.input
|
|
46
|
+
end.uniq
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @private
|
|
51
|
+
def message_resource_types message, seen_messages = []
|
|
52
|
+
return [] if seen_messages.include? message
|
|
53
|
+
seen_messages << message
|
|
54
|
+
resource_types = []
|
|
55
|
+
resource_types << message.resource.type if message.resource
|
|
56
|
+
resource_types += message.nested_messages.map do |nested_message|
|
|
57
|
+
message_resource_types nested_message, seen_messages
|
|
58
|
+
end
|
|
59
|
+
message.fields.each do |field|
|
|
60
|
+
resource_types << field.resource_reference.type if field.resource_reference
|
|
61
|
+
resource_types += message_resource_types field.message, seen_messages if field.message?
|
|
62
|
+
end
|
|
63
|
+
resource_types.flatten
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @private
|
|
67
|
+
def lookup_message_resources_descriptors message
|
|
68
|
+
resources = []
|
|
69
|
+
|
|
70
|
+
# We don't expect service_resource_types to iclude nil, so we can use message.resource&.type
|
|
71
|
+
resources << message.resource if service_resource_types.include? message.resource&.type
|
|
72
|
+
|
|
73
|
+
if message.nested_messages
|
|
74
|
+
resources += message.nested_messages.flat_map do |nested_message|
|
|
75
|
+
lookup_message_resources_descriptors nested_message
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
resources
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Lookup all resources for a given service.
|
|
83
|
+
#
|
|
84
|
+
# @param service [Gapic::Service] The service to lookup on.
|
|
85
|
+
#
|
|
86
|
+
# @return [Array<Google::Api::ResourceDescriptor>]
|
|
87
|
+
def self.for_service service
|
|
88
|
+
ResourceLookup.new(service).lookup!
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/gapic/runner.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
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 "gapic/generator"
|
|
18
|
+
require "gapic/schema"
|
|
19
|
+
require "google/protobuf/compiler/plugin.pb"
|
|
20
|
+
|
|
21
|
+
module Gapic
|
|
22
|
+
# TODO: Enter docs
|
|
23
|
+
# Dooooooooocs!!!
|
|
24
|
+
class Runner
|
|
25
|
+
attr_reader :request
|
|
26
|
+
|
|
27
|
+
# Initializes the runner.
|
|
28
|
+
# @param [Google::Protobuf::Compiler::CodeGeneratorRequest] request
|
|
29
|
+
def initialize request
|
|
30
|
+
@request = request
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Run protoc generation.
|
|
34
|
+
# @param [String] generator_type
|
|
35
|
+
# @return [Google::Protobuf::Compiler::CodeGeneratorResponse]
|
|
36
|
+
def run generator_type: nil
|
|
37
|
+
# Create an API Schema from the FileDescriptorProtos
|
|
38
|
+
api = Gapic::Schema::Api.new request
|
|
39
|
+
|
|
40
|
+
write_binary_file! api
|
|
41
|
+
|
|
42
|
+
# Retrieve generator type from protoc_options if not already provided.
|
|
43
|
+
generator_type ||= api.protoc_options["generator"]
|
|
44
|
+
# Find the generator for the generator type.
|
|
45
|
+
generator = Gapic::Generator.find generator_type
|
|
46
|
+
|
|
47
|
+
# Create and run the generator from the API.
|
|
48
|
+
output_files = generator.new(api).generate
|
|
49
|
+
|
|
50
|
+
# Create and write the response
|
|
51
|
+
Google::Protobuf::Compiler::CodeGeneratorResponse.new \
|
|
52
|
+
file: output_files
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Run protoc generation.
|
|
56
|
+
# @param [Google::Protobuf::Compiler::CodeGeneratorRequest] request
|
|
57
|
+
# @param [String] generator
|
|
58
|
+
# @return [Google::Protobuf::Compiler::CodeGeneratorResponse]
|
|
59
|
+
def self.run request, generator: nil
|
|
60
|
+
new(request).run generator_type: generator
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def write_binary_file! api
|
|
66
|
+
return unless api.protoc_options["binary_output"]
|
|
67
|
+
|
|
68
|
+
# First, strip the binary_output parameter out so it doesn't get saved
|
|
69
|
+
binary_file = api.protoc_options.delete "binary_output"
|
|
70
|
+
request.parameter = api.protoc_parameter
|
|
71
|
+
|
|
72
|
+
# Write binary file if the binary_output option is set
|
|
73
|
+
File.binwrite binary_file, request.to_proto
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/gapic/schema.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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 "gapic/schema/api"
|
|
@@ -0,0 +1,264 @@
|
|
|
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 "yaml"
|
|
18
|
+
require "json"
|
|
19
|
+
require "gapic/schema/loader"
|
|
20
|
+
require "gapic/grpc_service_config/parser"
|
|
21
|
+
|
|
22
|
+
module Gapic
|
|
23
|
+
module Schema
|
|
24
|
+
# rubocop:disable Metrics/ClassLength
|
|
25
|
+
|
|
26
|
+
# A representation of a full API.
|
|
27
|
+
#
|
|
28
|
+
# @!attribute [r] files
|
|
29
|
+
# @return [Array<File>] The files represented by this API.
|
|
30
|
+
# @!attribute [r] services
|
|
31
|
+
# @return [<Array<Service>] The services seen across all files in this
|
|
32
|
+
# API.
|
|
33
|
+
# @!attribute [r] messages
|
|
34
|
+
# @return [Array<Message>] The top level messages seen across all files
|
|
35
|
+
# in this API.
|
|
36
|
+
# @!attribute [r] enums
|
|
37
|
+
# @return [Array<Enum>] The top level enums seen across all files in
|
|
38
|
+
# this API.
|
|
39
|
+
class Api
|
|
40
|
+
attr_accessor :request, :files
|
|
41
|
+
|
|
42
|
+
# Initializes an API object with the file descriptors that represent the
|
|
43
|
+
# API.
|
|
44
|
+
#
|
|
45
|
+
# @param request [Google::Protobuf::Compiler::CodeGeneratorRequest]
|
|
46
|
+
# The request object.
|
|
47
|
+
def initialize request
|
|
48
|
+
@request = request
|
|
49
|
+
loader = Loader.new
|
|
50
|
+
@files = request.proto_file.map do |fd|
|
|
51
|
+
loader.load_file fd, request.file_to_generate.include?(fd.name)
|
|
52
|
+
end
|
|
53
|
+
@files.each { |f| f.parent = self }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def lookup address
|
|
57
|
+
address = address.join "." if address.is_a? Array
|
|
58
|
+
@files.each do |f|
|
|
59
|
+
lookup = f.lookup address
|
|
60
|
+
return lookup if lookup
|
|
61
|
+
end
|
|
62
|
+
nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def file_for address
|
|
66
|
+
address = address.join "." if address.is_a? Array
|
|
67
|
+
matching_files = @files.select { |f| f.lookup address }
|
|
68
|
+
matching_files.first
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def fix_file_path str
|
|
72
|
+
str = String str
|
|
73
|
+
return str if configuration[:overrides].nil?
|
|
74
|
+
return str if configuration[:overrides][:file_path].nil?
|
|
75
|
+
configuration[:overrides][:file_path].fetch str, str
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def fix_namespace str
|
|
79
|
+
str = String str
|
|
80
|
+
return str if configuration[:overrides].nil?
|
|
81
|
+
return str if configuration[:overrides][:namespace].nil?
|
|
82
|
+
configuration[:overrides][:namespace].fetch str, str
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def generate_files
|
|
86
|
+
@files.select(&:generate?)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def services
|
|
90
|
+
@files.map(&:services).flatten
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def messages
|
|
94
|
+
@files.map(&:messages).flatten
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Structured Hash representation of the parameter values.
|
|
98
|
+
# @return [Hash]
|
|
99
|
+
# A Hash of the request parameters.
|
|
100
|
+
def protoc_options
|
|
101
|
+
@protoc_options ||= begin
|
|
102
|
+
result = {}
|
|
103
|
+
parameters = parse_parameter request.parameter
|
|
104
|
+
parameters.each do |param_array|
|
|
105
|
+
key = param_array.first
|
|
106
|
+
next if key.empty?
|
|
107
|
+
value = param_array[1..-1]
|
|
108
|
+
value = value.first if value.size == 1
|
|
109
|
+
value = nil if value.empty?
|
|
110
|
+
result[str_to_key(key)] = value
|
|
111
|
+
end
|
|
112
|
+
result
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Reconstructed string representation of the protoc options
|
|
117
|
+
# @return [String]
|
|
118
|
+
def protoc_parameter
|
|
119
|
+
protoc_options.map do |k, v|
|
|
120
|
+
v = Array(v).map do |s|
|
|
121
|
+
s.gsub("\\", "\\\\\\\\").gsub(",", "\\\\,").gsub("=", "\\\\=")
|
|
122
|
+
end.join("=")
|
|
123
|
+
k = key_to_str k
|
|
124
|
+
"#{k}=#{v}"
|
|
125
|
+
end.join ","
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Structured representation of the samples configuration files.
|
|
129
|
+
# @return [Array<Hash>]
|
|
130
|
+
# An array of the sample file hashes.
|
|
131
|
+
def samples
|
|
132
|
+
@samples ||= begin
|
|
133
|
+
protoc_options["samples"].to_s.split(";").flat_map do |sample_path|
|
|
134
|
+
YAML.load_file sample_path
|
|
135
|
+
end.compact
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Structured representation of the standalone samples configuration files.
|
|
140
|
+
# @return [Array<Hash>]
|
|
141
|
+
# An array of the standalone sample configuration hashes.
|
|
142
|
+
def standalone_samples
|
|
143
|
+
@standalone_samples ||= begin
|
|
144
|
+
supported_types = [
|
|
145
|
+
"com.google.api.codegen.SampleConfigProto",
|
|
146
|
+
"com.google.api.codegen.samplegen.v1p2.SampleConfigProto"
|
|
147
|
+
]
|
|
148
|
+
supported_sample_types = [nil, "standalone"]
|
|
149
|
+
samples.select { |sample_file| supported_types.include? sample_file["type"] }
|
|
150
|
+
.select { |sample_file| sample_file["schema_version"] == "1.2.0" }
|
|
151
|
+
.map { |sample_file| sample_file["samples"] }
|
|
152
|
+
.flatten.compact
|
|
153
|
+
.select { |sample_config| supported_sample_types.include? sample_config["sample_type"] }
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Structured representation of the standalone test samples configuration files.
|
|
158
|
+
# @return [Array<Hash>]
|
|
159
|
+
# An array of the standalone sample configuration hashes.
|
|
160
|
+
def standalone_test_samples
|
|
161
|
+
@standalone_test_samples ||= begin
|
|
162
|
+
samples.select { |sample| sample["type"] == "test/samples" }
|
|
163
|
+
.select { |sample| sample["schema_version"] == "1" || sample["schema_version"] == 1 }
|
|
164
|
+
.map { |sample| sample["samples"] }
|
|
165
|
+
.flatten.compact
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Structured representation of the inline samples configuration files.
|
|
170
|
+
# @return [Array<Hash>]
|
|
171
|
+
# An array of the incode sample configuration hashes, sorted by sample_type.
|
|
172
|
+
def incode_samples
|
|
173
|
+
@incode_samples ||= begin
|
|
174
|
+
supported_types = [
|
|
175
|
+
"com.google.api.codegen.SampleConfigProto",
|
|
176
|
+
"com.google.api.codegen.samplegen.v1p2.SampleConfigProto"
|
|
177
|
+
]
|
|
178
|
+
samples.select { |sample_file| supported_types.include? sample_file["type"] }
|
|
179
|
+
.select { |sample_file| sample_file["schema_version"] == "1.2.0" }
|
|
180
|
+
.map { |sample_file| sample_file["samples"] }
|
|
181
|
+
.flatten.compact
|
|
182
|
+
.select { |sample_config| sample_config["sample_type"]&.start_with? "incode/" }
|
|
183
|
+
.sort_by { |sample_config| sample_config["sample_type"] }
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Structured Hash representation of the configuration file.
|
|
188
|
+
# @return [Hash]
|
|
189
|
+
# A Hash of the configuration values.
|
|
190
|
+
def configuration
|
|
191
|
+
@configuration ||= begin
|
|
192
|
+
config_file = protoc_options["configuration"]
|
|
193
|
+
config = config_file ? YAML.load_file(config_file) : {}
|
|
194
|
+
protoc_options.each do |k, v|
|
|
195
|
+
next if k == "configuration"
|
|
196
|
+
branch = key_to_str(k).split(".").reverse.inject(v) { |m, s| { str_to_key(s) => m } }
|
|
197
|
+
config = deep_merge config, branch
|
|
198
|
+
end
|
|
199
|
+
config
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Raw parsed json of the combined grpc service config files if provided
|
|
204
|
+
# or an empty hash if no config was provided
|
|
205
|
+
def grpc_service_config_raw
|
|
206
|
+
@grpc_service_config_raw ||= begin
|
|
207
|
+
filenames = protoc_options["grpc_service_config"].to_s.split ";"
|
|
208
|
+
filenames.inject({}) do |running_hash, filename|
|
|
209
|
+
file_hash = JSON.parse ::File.read filename
|
|
210
|
+
deep_merge running_hash, file_hash
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Parsed grpc service config
|
|
216
|
+
def grpc_service_config
|
|
217
|
+
@grpc_service_config ||= begin
|
|
218
|
+
Gapic::GrpcServiceConfig::Parser.parse grpc_service_config_raw
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
private
|
|
223
|
+
|
|
224
|
+
def parse_parameter str
|
|
225
|
+
str.scan(/\\.|,|=|[^\\,=]+/)
|
|
226
|
+
.each_with_object([[String.new]]) do |tok, arr|
|
|
227
|
+
if tok == ","
|
|
228
|
+
arr.append [String.new]
|
|
229
|
+
elsif tok == "="
|
|
230
|
+
arr.last.append String.new
|
|
231
|
+
elsif tok.start_with? "\\"
|
|
232
|
+
arr.last.last << tok[1]
|
|
233
|
+
else
|
|
234
|
+
arr.last.last << tok
|
|
235
|
+
end
|
|
236
|
+
arr
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def str_to_key str
|
|
241
|
+
str = str.to_s
|
|
242
|
+
str.start_with?(":") ? str[1..-1].to_sym : str
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def key_to_str key
|
|
246
|
+
key.is_a?(::Symbol) ? ":#{key}" : key.to_s
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def deep_merge left, right
|
|
250
|
+
left.merge right do |_k, lt, rt|
|
|
251
|
+
if lt.is_a?(Hash) && rt.is_a?(Hash)
|
|
252
|
+
deep_merge lt, rt
|
|
253
|
+
elsif lt.is_a?(Array) && rt.is_a?(Array)
|
|
254
|
+
lt + rt
|
|
255
|
+
else
|
|
256
|
+
rt
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# rubocop:enable Metrics/ClassLength
|
|
263
|
+
end
|
|
264
|
+
end
|