rbs_protobuf 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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