rbs_protobuf 1.0.0 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 563169bcedcc8c4392d8ad6c428c8fd4f31b5ca3373705439fa94a0e3f05b138
4
- data.tar.gz: a55dd8d55cc9b866b101e51bb90ba88aa5e138251c3083b010671b03346d9db8
3
+ metadata.gz: bcaf6201c92331c28b9fa7d1791711def79ccb4803d81692a220b60d08e640a6
4
+ data.tar.gz: 93651dffc7e86d657f5ed5298b3ab43042a7e663fd07a502b25fe968ede6cef2
5
5
  SHA512:
6
- metadata.gz: d0ea93fd55f7b9efb4a864156e428033da4116499c99ef8f222949ae301b16fe302cd00c022ce2ad91ac9216dca508a084a9c59fb5b296dbd5e41d4d8dd6b205
7
- data.tar.gz: c143b93fce43ede0ff094a26f2e51d3d72e6b35853852cc11e1b571f74abbe68ec7f579af206bec8213c908bb34d1421986f57a6f14417d316d7b666491c04ce
6
+ metadata.gz: '09835d51dd74b278a376dc721bbde2527f6e501596dd5239b29a0da5aa96af69cfc08831e2dafc7b6ac67491ef3e5c35b2ec2dca536fbc66864291b3a2109e6a'
7
+ data.tar.gz: 42b4c2d53a767f7b8732f8d4ee7a74d724ba334280cf006326a1ebfcd5f1dc4031d44404d149ee63e8c66f46da5dee2f519eaa6539d7789fb8b9b5e5a9dfb863
@@ -12,12 +12,13 @@ jobs:
12
12
  strategy:
13
13
  matrix:
14
14
  container_tag:
15
- - 2.7-bionic
16
- - 3.0-focal
17
- - 3.1-focal
15
+ - 3.0-dev-focal
16
+ - 3.1-dev-jammy
17
+ - 3.2-dev-jammy
18
18
  protoc_version:
19
- - 3.18.2
20
- - 3.19.4
19
+ - "3.18.2"
20
+ - "3.19.4"
21
+ - "24.0"
21
22
  container:
22
23
  image: rubylang/ruby:${{ matrix.container_tag }}
23
24
  steps:
@@ -31,8 +32,9 @@ jobs:
31
32
  mv bin/protoc /usr/local/bin/protoc
32
33
  protoc --version
33
34
  - uses: actions/checkout@v3
34
- with:
35
- submodules: true
35
+ - name: Set up git safe.directory
36
+ run: |
37
+ git config --global --add safe.directory /__w/rbs_protobuf/rbs_protobuf
36
38
  - name: Run test
37
39
  run: |
38
40
  ruby -v
data/.gitmodules CHANGED
@@ -1,3 +0,0 @@
1
- [submodule "vendor/gem_rbs_collection"]
2
- path = vendor/gem_rbs_collection
3
- url = git@github.com:ruby/gem_rbs_collection.git
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.2.0 (2023-09-06)
4
+
5
+ * Add `RBS_PROTOBUF_CONCAT_LEVEL` option ([#38](https://github.com/square/rbs_protobuf/pull/38))
6
+ * Generate rpc method types and interfaces ([#37](https://github.com/square/rbs_protobuf/pull/37))
7
+ * Generate `record` type of each proto message ([#36](https://github.com/square/rbs_protobuf/pull/36))
8
+ * Add filter ([#34](https://github.com/square/rbs_protobuf/pull/34))
9
+
10
+ ## 1.1.0 (2023-08-16)
11
+
12
+ * Support optional fields in proto3 ([\#32](https://github.com/square/rbs_protobuf/pull/32))
13
+ * Update Steep to 1.5 and RBS to 3.1 ([\#30](https://github.com/square/rbs_protobuf/pull/30))
14
+
3
15
  ## 1.0.0 (2022-04-25)
4
16
 
5
17
  This is version 1.0.0. 🎉
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
7
  gem "minitest", "~> 5.0"
8
- gem "steep"
9
- gem "rbs"
8
+ gem "steep", require: false
9
+ gem "rbs", "~> 3.1"
10
10
 
11
11
  gem "protobuf", "~> 3.10"
data/Gemfile.lock CHANGED
@@ -1,59 +1,72 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbs_protobuf (1.0.0)
4
+ rbs_protobuf (1.2.0)
5
5
  activesupport (>= 4.0)
6
6
  rbs (>= 2.2.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (7.0.2.3)
11
+ activesupport (7.0.7.2)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 1.6, < 2)
14
14
  minitest (>= 5.1)
15
15
  tzinfo (~> 2.0)
16
16
  ast (2.4.2)
17
- concurrent-ruby (1.1.10)
17
+ concurrent-ruby (1.2.2)
18
+ csv (3.2.7)
18
19
  ffi (1.15.5)
19
- i18n (1.10.0)
20
+ fileutils (1.7.1)
21
+ i18n (1.14.1)
20
22
  concurrent-ruby (~> 1.0)
21
- language_server-protocol (3.16.0.3)
22
- listen (3.7.1)
23
+ json (2.6.3)
24
+ language_server-protocol (3.17.0.3)
25
+ listen (3.8.0)
23
26
  rb-fsevent (~> 0.10, >= 0.10.3)
24
27
  rb-inotify (~> 0.9, >= 0.9.10)
28
+ logger (1.5.3)
25
29
  middleware (0.1.0)
26
- minitest (5.15.0)
27
- parallel (1.22.1)
28
- parser (3.1.2.0)
30
+ minitest (5.19.0)
31
+ parser (3.2.2.3)
29
32
  ast (~> 2.4.1)
33
+ racc
30
34
  protobuf (3.10.5)
31
35
  activesupport (>= 3.2)
32
36
  middleware
33
37
  thor
34
38
  thread_safe
39
+ racc (1.7.1)
35
40
  rainbow (3.1.1)
36
41
  rake (12.3.3)
37
- rb-fsevent (0.11.1)
42
+ rb-fsevent (0.11.2)
38
43
  rb-inotify (0.10.1)
39
44
  ffi (~> 1.0)
40
- rbs (2.3.2)
41
- steep (0.52.1)
45
+ rbs (3.1.3)
46
+ securerandom (0.2.2)
47
+ steep (1.5.3)
42
48
  activesupport (>= 5.1)
49
+ concurrent-ruby (>= 1.1.10)
50
+ csv (>= 3.0.9)
51
+ fileutils (>= 1.1.0)
52
+ json (>= 2.1.0)
43
53
  language_server-protocol (>= 3.15, < 4.0)
44
54
  listen (~> 3.0)
45
- parallel (>= 1.0.0)
46
- parser (>= 3.0)
55
+ logger (>= 1.3.0)
56
+ parser (>= 3.1)
47
57
  rainbow (>= 2.2.2, < 4.0)
48
- rbs (>= 2.3.2)
58
+ rbs (>= 3.1.0)
59
+ securerandom (>= 0.1)
60
+ strscan (>= 1.0.0)
49
61
  terminal-table (>= 2, < 4)
62
+ strscan (3.0.6)
50
63
  terminal-table (3.0.2)
51
64
  unicode-display_width (>= 1.1.1, < 3)
52
65
  thor (1.2.1)
53
66
  thread_safe (0.3.6)
54
- tzinfo (2.0.4)
67
+ tzinfo (2.0.6)
55
68
  concurrent-ruby (~> 1.0)
56
- unicode-display_width (2.1.0)
69
+ unicode-display_width (2.4.2)
57
70
 
58
71
  PLATFORMS
59
72
  ruby
@@ -62,7 +75,7 @@ DEPENDENCIES
62
75
  minitest (~> 5.0)
63
76
  protobuf (~> 3.10)
64
77
  rake (~> 12.0)
65
- rbs
78
+ rbs (~> 3.1)
66
79
  rbs_protobuf!
67
80
  steep
68
81
 
data/README.md CHANGED
@@ -82,21 +82,6 @@ Run `protoc` with `--rbs_out` option.
82
82
 
83
83
  You may need `bundle exec protoc ...` to let bundler set up PATH.
84
84
 
85
- ## Type checking
86
-
87
- To type check the output, you need to configure your tools to import [gem_rbs_collection](https://github.com/ruby/gem_rbs_collection) with `rbs collection` command.
88
-
89
- ```yaml
90
- # Add the dependency in rbs_collection.yaml
91
- gems:
92
- - name: rbs_protobuf
93
- ```
94
-
95
- We assume that you don't type check the generated `.pb.rb` code.
96
- If you want to type check them, you need the definition of `Google::Protobuf`, which can be generated from [`descriptor.proto`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto).
97
-
98
- Note: `rbs_protobuf` generates RBS files assuming some types added in [this PR](https://github.com/ruby/gem_rbs_collection/pull/145). Make sure you are using one of the newer versions of `rbs_gem_collection` definitions.
99
-
100
85
  ### Options
101
86
 
102
87
  * `RBS_PROTOBUF_BACKEND` specifies the Ruby code generator gem. Supported value is `protobuf`. (We will add `google-protobuf` for `google-protobuf` gem.)
@@ -104,6 +89,20 @@ Note: `rbs_protobuf` generates RBS files assuming some types added in [this PR](
104
89
  * `RBS_PROTOBUF_NO_NESTED_NAMESPACE` is to make the RBS declarations flat.
105
90
  * `RBS_PROTOBUF_EXTENSION` specifies what to do for extensions.
106
91
  * `RBS_PROTOBUF_ACCEPT_NIL_ATTR_WRITER` is to allow passing `nil` to required fields.
92
+ * `RBS_PROTOBUF_FILTERS` contains filter Ruby script paths separated by `File::PATH_SEPARATOR`
93
+ * `RBS_PROTOBUF_CONCAT_LEVEL` contains the number of dir levels that groups generated RBS files to concat
94
+
95
+ ## Type checking
96
+
97
+ To type check the output, make sure your type checker configuration loads type definitions of `protobuf` gem.
98
+
99
+ ```ruby
100
+ # Declare in Gemfile and load it with rbs-collection
101
+ gem 'protobuf'
102
+ ```
103
+
104
+ We assume that you don't type check the generated `.pb.rb` code.
105
+ If you want to type check them, you need the definition of `Google::Protobuf`, which can be generated from [`descriptor.proto`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto).
107
106
 
108
107
  ## Supported features
109
108
 
@@ -118,7 +117,7 @@ Note: `rbs_protobuf` generates RBS files assuming some types added in [this PR](
118
117
  | Services | Only generates classes |
119
118
  | Oneof | No support in `protobuf` gem |
120
119
 
121
- ### Extensions
120
+ ## Extensions
122
121
 
123
122
  Adding extensions may cause problems if the name of new attribute conflicts.
124
123
 
@@ -144,6 +143,27 @@ You can control the behavior with `RBS_PROTOBUF_EXTENSION` environment variable.
144
143
  * Any value else: Generates RBS for extensions.
145
144
  * undefined: Ignores extensions but print messages to ask you to specify a value.
146
145
 
146
+ ## Filters
147
+
148
+ You can apply filters that modifies generated RBS files.
149
+
150
+ A filter is a proc object with type of `^(String rbs_name, String rbs_content, untyped proto_file) -> [String, String]`:
151
+ It receives the file name of RBS file, the content of RBS file, the source protobuf object, and returns a pair of RBS file name and content.
152
+
153
+ ```ruby
154
+ # example_fitler.rb: It adds a warning comment at the top of the RBS content.
155
+ ->(rbs_name, rbs_content, _proto_file) {
156
+ [
157
+ rbs_name,
158
+ "# Don't modify this file. This is generated with rbs_protobuf.\n\n" + rbs_content
159
+ ]
160
+ }
161
+ ```
162
+
163
+ You can apply filters by setting `RBS_PROTOBUF_FILTERS` environment variable.
164
+
165
+ $ RBS_PROTOBUF_BACKEND=protobuf RBS_PROTOBUF_FILTERS=example_filter.rb protoc ...
166
+
147
167
  ## Development
148
168
 
149
169
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test example:typecheck` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/Rakefile CHANGED
@@ -27,7 +27,8 @@ namespace :example do
27
27
  "-I#{proto_path}",
28
28
  "example/a.proto",
29
29
  "example/b.proto",
30
- "example/c.proto"
30
+ "example/c.proto",
31
+ "example/d.proto"
31
32
  )
32
33
  sh(
33
34
  { "RBS_PROTOBUF_BACKEND" => "protobuf", "RBS_PROTOBUF_EXTENSION" => "true" },
@@ -35,7 +36,8 @@ namespace :example do
35
36
  "--rbs_out=example/protobuf-gem",
36
37
  "-Iexample",
37
38
  "example/a.proto",
38
- "example/b.proto"
39
+ "example/b.proto",
40
+ "example/d.proto"
39
41
  )
40
42
  sh(
41
43
  { "RBS_PROTOBUF_BACKEND" => "protobuf", "RBS_PROTOBUF_EXTENSION" => "true", "RUBYOPT" => "-rbundler/setup -Iexample/protobuf-gem -rc.pb" },
data/Steepfile CHANGED
@@ -2,7 +2,6 @@ D = Steep::Diagnostic
2
2
 
3
3
  target :lib do
4
4
  signature "sig"
5
- signature "vendor/gem_rbs_collection/gems/protobuf"
6
5
  check "lib"
7
6
 
8
7
  configure_code_diagnostics do |hash|
@@ -7,5 +7,7 @@ require "rbs_protobuf"
7
7
  input = STDIN.read()
8
8
  File.write(ENV["PROTOC_DUMPER_OUT"] || "a.pb.out", input)
9
9
 
10
- response = Google::Protobuf::Compiler::CodeGeneratorResponse.new
10
+ response = Google::Protobuf::Compiler::CodeGeneratorResponse.new(
11
+ :supported_features => ::Google::Protobuf::Compiler::CodeGeneratorResponse::Feature::FEATURE_PROTO3_OPTIONAL.to_i
12
+ )
11
13
  print Google::Protobuf::Compiler::CodeGeneratorResponse.encode(response)
data/bin/setup CHANGED
@@ -9,13 +9,4 @@ echo ">>> Checking if protoc is available... 👀"
9
9
  protoc --version
10
10
 
11
11
  echo ">>> Setting up gem_rbs_collection... 💎"
12
- REPODIR=$(cd $(dirname $0)/..; pwd)/tmp/rbs/gem_rbs_collection
13
- if [ -e $REPODIR ]; then
14
- echo " ${REPODIR} exists"
15
- else
16
- echo " Cloning git repo into ${REPODIR}..."
17
- mkdir -p $REPODIR/..
18
- git clone https://github.com/ruby/gem_rbs_collection.git ${REPODIR}
19
- fi
20
-
21
12
  bundle exec rbs collection install
data/example/d.proto ADDED
@@ -0,0 +1,6 @@
1
+ syntax = "proto3";
2
+
3
+ message Foo {
4
+ string bar = 2;
5
+ optional string baz = 1;
6
+ }
data/exe/protoc-gen-rbs CHANGED
@@ -13,6 +13,20 @@ unless backend
13
13
  exit 1
14
14
  end
15
15
 
16
+ filters = []
17
+
18
+ if string = ENV["RBS_PROTOBUF_FILTERS"]
19
+ string.split(File::PATH_SEPARATOR).each do |file|
20
+ filter = Module.new.instance_eval(File.read(file), file)
21
+
22
+ if filter.respond_to?(:call)
23
+ filters << filter
24
+ else
25
+ raise "A filter `#{file}` returns `#{filter.inspect}`, but a proc object of type `^(String rbs_name, String rbs_content, untyped proto_file) -> [String, String]` is expected"
26
+ end
27
+ end
28
+ end
29
+
16
30
  input = Google::Protobuf::Compiler::CodeGeneratorRequest.decode(STDIN.read)
17
31
 
18
32
  translator = case backend
@@ -34,6 +48,7 @@ translator = case backend
34
48
 
35
49
  RBSProtobuf::Translator::ProtobufGem.new(
36
50
  input,
51
+ filters,
37
52
  upcase_enum: upcase_enum,
38
53
  nested_namespace: !no_nested_namespace,
39
54
  extension: extension,
@@ -43,6 +58,9 @@ translator = case backend
43
58
  raise NotImplementedError
44
59
  end
45
60
 
61
+ if level = ENV["RBS_PROTOBUF_CONCAT_LEVEL"]
62
+ translator.rbs_concat_level = level.to_i
63
+ end
46
64
  translator.generate_rbs!
47
65
 
48
66
  response = translator.response
@@ -46,6 +46,7 @@ module RBSProtobuf
46
46
  end
47
47
 
48
48
  def union_type(type, *types)
49
+ types = types.compact
49
50
  if types.empty?
50
51
  type
51
52
  else
@@ -3,10 +3,19 @@ module RBSProtobuf
3
3
  class Base
4
4
  FieldDescriptorProto = Google::Protobuf::FieldDescriptorProto
5
5
 
6
- attr_reader :input
6
+ attr_reader :input, :filters
7
7
 
8
- def initialize(input)
8
+ attr_accessor :rbs_concat_level
9
+
10
+ def initialize(input, filters = [])
9
11
  @input = input
12
+ @filters = filters
13
+ end
14
+
15
+ def apply_filter(rbs_name, rbs_content, proto_files)
16
+ filters.inject([rbs_name, rbs_content]) do |(rbs_name, rbs_content), filter| #$ [String, String]
17
+ filter[rbs_name, rbs_content, proto_files] or return
18
+ end
10
19
  end
11
20
 
12
21
  def factory
@@ -14,18 +23,65 @@ module RBSProtobuf
14
23
  end
15
24
 
16
25
  def response
17
- @response ||= Google::Protobuf::Compiler::CodeGeneratorResponse.new
26
+ @response ||= Google::Protobuf::Compiler::CodeGeneratorResponse.new(:supported_features => ::Google::Protobuf::Compiler::CodeGeneratorResponse::Feature::FEATURE_PROTO3_OPTIONAL.to_i)
18
27
  end
19
28
 
20
29
  def generate_rbs!
30
+ rbs_decls = {} #: Hash[Pathname, [Array[RBS::AST::Declarations::t], untyped]]
31
+
21
32
  input.proto_file.each do |file|
22
- response.file << Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(
23
- name: rbs_name(file.name),
24
- content: rbs_content(file)
25
- )
33
+ path = Pathname(file.name).sub_ext(".rbs")
34
+ decls = rbs_content(file)
35
+ rbs_decls[path] = [decls, file]
36
+ end
37
+
38
+ rbs_contents = {} #: Hash[Pathname, [String, Array[untyped]]]
39
+
40
+ if (level = rbs_concat_level)&.nonzero?
41
+ groups = rbs_decls.each_key.group_by do |path|
42
+ path.sub_ext("").to_s.split(File::SEPARATOR).take(level).join(File::SEPARATOR)
43
+ end
44
+
45
+ groups.each do |prefix, paths|
46
+ path = Pathname(prefix).sub_ext(".rbs")
47
+
48
+ decls = [] #: Array[RBS::AST::Declarations::t]
49
+ files = [] #: Array[untyped]
50
+
51
+ paths.each do |path|
52
+ ds, file = rbs_decls.fetch(path)
53
+ decls.concat(ds)
54
+ files.push(file)
55
+ end
56
+
57
+ rbs_contents[path] = [
58
+ format_rbs(decls: decls),
59
+ files
60
+ ]
61
+ end
62
+ else
63
+ rbs_decls.each do |path, (decls, file)|
64
+ content = format_rbs(decls: decls)
65
+ rbs_contents[path] = [content, [file]]
66
+ end
67
+ end
68
+
69
+ rbs_contents.each do |path, (content, files)|
70
+ if (name, content = apply_filter(path.to_s, content, files))
71
+ response.file << Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(
72
+ name: name,
73
+ content: content
74
+ )
75
+ end
26
76
  end
27
77
  end
28
78
 
79
+ def format_rbs(dirs: [], decls: [])
80
+ StringIO.new.tap do |io|
81
+ RBS::Writer.new(out: io).write(dirs + decls)
82
+ end.string
83
+ end
84
+
29
85
  def rbs_name(proto_name)
30
86
  dirname = File.dirname(proto_name)
31
87
  basename = File.basename(proto_name, File.extname(proto_name))
@@ -120,6 +176,15 @@ module RBSProtobuf
120
176
  )
121
177
  )
122
178
  end
179
+
180
+ def optional_type(type)
181
+ case type
182
+ when RBS::Types::Optional
183
+ type
184
+ else
185
+ RBS::Types::Optional.new(type: type, location: nil)
186
+ end
187
+ end
123
188
  end
124
189
  end
125
190
  end