From 59678bd0ea55b398b55d297b455e58a1f275d2ec Mon Sep 17 00:00:00 2001 From: prattik-wav Date: Mon, 1 Jun 2026 21:45:49 +0530 Subject: [PATCH 1/5] Fix invalid sig generated for anonymous block param (&) When a method uses Ruby 3.1+ anonymous block forwarding (def foo(&); end), rbs_comments_to_sorbet_sigs was generating `&block:` inside params(), which is a syntax error. Named block params (`&block`) were already handled correctly. Detect a nil-named BlockParameterNode in the def and strip the leading `&` from any block param name in the translated sig. Fixes #928 --- .../translate/rbs_comments_to_sorbet_sigs.rb | 20 +++++++++- .../rbs_comments_to_sorbet_sigs_test.rb | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb b/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb index 989a9061..57b20347 100644 --- a/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb +++ b/lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb @@ -184,6 +184,16 @@ def rewrite_def(def_node, comments) sig = translator.result + # When the method uses Ruby 3.1+ anonymous block forwarding (`&` with no name), + # the RBI translator names the block param `&block`, producing `&block:` inside + # `params()` which is a syntax error. Detect that case and rename it to `block` + # (without the `&`) so the generated sig is valid Ruby. + if anonymous_block_param?(def_node) + sig.params.each do |param| + param.name = param.name.delete_prefix("&") if param.name.start_with?("&") + end + end + apply_member_annotations(comments.method_annotations, sig) # Sorbet runtime doesn't support `sig` on `method_added` or @@ -348,6 +358,14 @@ def apply_member_annotations(annotations, sig) end end + # Returns true if the def node uses an anonymous block parameter (`&` with no name), + # i.e. Ruby 3.1+ anonymous block forwarding like `def foo(&); end`. + #: (Prism::DefNode) -> bool + def anonymous_block_param?(def_node) + block_param = def_node.parameters&.block + block_param.is_a?(Prism::BlockParameterNode) && block_param.name.nil? + end + #: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode, Regexp) -> bool def already_extends?(node, constant_regex) node.child_nodes.any? do |c| @@ -438,4 +456,4 @@ def apply_type_aliases(comments) end end end -end +end \ No newline at end of file diff --git a/test/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs_test.rb b/test/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs_test.rb index 77342b9b..eb8c38d7 100644 --- a/test/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs_test.rb +++ b/test/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs_test.rb @@ -890,6 +890,45 @@ def rbs_comments_to_sorbet_sigs(ruby_contents, max_line_length: nil, overloads_s overloads_strategy: overloads_strategy, ).rewrite end + + def test_rbs_comments_to_sorbet_sigs_anonymous_block_param + res = Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(<<~RUBY, file: "test.rb") + # typed: true + class Foo + #: (String) ?{ (String) -> void } -> String + def bar(request, &); end + end + RUBY + + assert_equal(<<~RUBY, res) + # typed: true + class Foo + sig { params(request: String, block: ::T.nilable(::T.proc.params(arg0: String).void)).returns(String) } + def bar(request, &); end + end + RUBY + + # Must also be valid Ruby + assert RubyVM::InstructionSequence.compile(res) + end + + def test_rbs_comments_to_sorbet_sigs_named_block_param_unchanged + res = Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(<<~RUBY, file: "test.rb") + # typed: true + class Foo + #: (String) ?{ (String) -> void } -> String + def bar(request, &block); end + end + RUBY + + assert_equal(<<~RUBY, res) + # typed: true + class Foo + sig { params(request: String, block: ::T.nilable(::T.proc.params(arg0: String).void)).returns(String) } + def bar(request, &block); end + end + RUBY + end end end end From 7b4b166152273763a858931390d5fc1e757122c6 Mon Sep 17 00:00:00 2001 From: prattik-wav Date: Mon, 1 Jun 2026 21:56:44 +0530 Subject: [PATCH 2/5] Trigger CLA check From f44e4b6fcad4333b74aee197593ac17a408432b8 Mon Sep 17 00:00:00 2001 From: prattik-wav Date: Mon, 1 Jun 2026 22:31:16 +0530 Subject: [PATCH 3/5] Trigger CLA check --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index fcdb2e10..f9892605 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -4.0.0 +3.4.4 From 6b103ce91c2ee82e8ff0393331de6c034ce248ad Mon Sep 17 00:00:00 2001 From: prattik-wav Date: Mon, 1 Jun 2026 22:34:58 +0530 Subject: [PATCH 4/5] Trigger CLA check From ffa7e824405ac7b4dbd821b59e69ec6a1773683c Mon Sep 17 00:00:00 2001 From: prattik-wav Date: Mon, 1 Jun 2026 22:36:27 +0530 Subject: [PATCH 5/5] Trigger CLA check