From b274f2fa41ba10df81d78ca07340c6dea6453d1e Mon Sep 17 00:00:00 2001 From: Alexandre Terrasa Date: Mon, 9 Jun 2025 16:16:13 -0400 Subject: [PATCH 1/4] Only translate top level assertions Signed-off-by: Alexandre Terrasa --- .../sorbet_assertions_to_rbs_comments.rb | 41 +++++++++++++++---- .../sorbet_assertions_to_rbs_comments_test.rb | 8 ++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb b/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb index 84856a81..edf4eb13 100644 --- a/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb +++ b/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb @@ -8,6 +8,15 @@ module Translate class SorbetAssertionsToRBSComments < Translator LINE_BREAK = "\n".ord #: Integer + # @override + #: (Prism::StatementsNode) -> void + def visit_statements_node(node) + node.body.each do |statement| + translated = maybe_translate_assertion(statement) + visit(statement) unless translated + end + end + # @override #: (Prism::IfNode) -> void def visit_if_node(node) @@ -29,11 +38,29 @@ def visit_if_node(node) end end - # @override - #: (Prism::CallNode) -> void - def visit_call_node(node) - return super unless t_annotation?(node) - return super unless at_end_of_line?(node) + private + + #: (Prism::Node) -> bool + def maybe_translate_assertion(node) + node = case node + when Prism::MultiWriteNode, + Prism::ClassVariableWriteNode, Prism::ClassVariableAndWriteNode, Prism::ClassVariableOperatorWriteNode, Prism::ClassVariableOrWriteNode, + Prism::ConstantWriteNode, Prism::ConstantAndWriteNode, Prism::ConstantOperatorWriteNode, Prism::ConstantOrWriteNode, + Prism::ConstantPathWriteNode, Prism::ConstantPathAndWriteNode, Prism::ConstantPathOperatorWriteNode, Prism::ConstantPathOrWriteNode, + Prism::GlobalVariableWriteNode, Prism::GlobalVariableAndWriteNode, Prism::GlobalVariableOperatorWriteNode, Prism::GlobalVariableOrWriteNode, + Prism::InstanceVariableWriteNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, + Prism::LocalVariableWriteNode, Prism::LocalVariableAndWriteNode, Prism::LocalVariableOperatorWriteNode, Prism::LocalVariableOrWriteNode, + Prism::CallAndWriteNode, Prism::CallOperatorWriteNode, Prism::CallOrWriteNode + node.value + when Prism::CallNode + node + else + return false + end + + return false unless node.is_a?(Prism::CallNode) + return false unless t_annotation?(node) + return false unless at_end_of_line?(node) value = T.must(node.arguments&.arguments&.first) rbs_annotation = build_rbs_annotation(node) @@ -41,9 +68,9 @@ def visit_call_node(node) start_offset = node.location.start_offset end_offset = node.location.end_offset @rewriter << Source::Replace.new(start_offset, end_offset - 1, "#{dedent_value(node, value)} #{rbs_annotation}") - end - private + true + end #: (Prism::CallNode) -> void def build_rbs_annotation(call) diff --git a/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb b/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb index 43bdc8a0..782365ec 100644 --- a/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb +++ b/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb @@ -482,6 +482,14 @@ def test_doesnt_translate_cast_in_string_interpolation assert_equal(rb, rbi_to_rbs(rb)) end + def test_doesnt_translate_in_expressions + rb = <<~RB + a - T.must(b) + RB + + assert_equal(rb, rbi_to_rbs(rb)) + end + def test_doesnt_translate_in_ternary_expressions rb = <<~RB a = T.must(b) ? T.must(c) : T.must(d) From ced444a96b35237665a63289d55f84c80249f6c7 Mon Sep 17 00:00:00 2001 From: Alexandre Terrasa Date: Mon, 9 Jun 2025 16:20:05 -0400 Subject: [PATCH 2/4] Update exported RBI Signed-off-by: Alexandre Terrasa --- rbi/spoom.rbi | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rbi/spoom.rbi b/rbi/spoom.rbi index 2777aef6..5f6cd2ad 100644 --- a/rbi/spoom.rbi +++ b/rbi/spoom.rbi @@ -2934,12 +2934,12 @@ class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs < ::Spoom::Sorbet::Trans end class Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments < ::Spoom::Sorbet::Translate::Translator - sig { override.params(node: ::Prism::CallNode).void } - def visit_call_node(node); end - sig { override.params(node: ::Prism::IfNode).void } def visit_if_node(node); end + sig { override.params(node: ::Prism::StatementsNode).void } + def visit_statements_node(node); end + private sig { params(node: ::Prism::Node).returns(T::Boolean) } @@ -2951,6 +2951,9 @@ class Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments < ::Spoom::Sorbet: sig { params(assign: ::Prism::Node, value: ::Prism::Node).returns(::String) } def dedent_value(assign, value); end + sig { params(node: ::Prism::Node).returns(T::Boolean) } + def maybe_translate_assertion(node); end + sig { params(node: T.nilable(::Prism::Node)).returns(T::Boolean) } def t?(node); end From 5eb996343fe0adf5fc92a99e6629b72eda9f941d Mon Sep 17 00:00:00 2001 From: Alexandre Terrasa Date: Mon, 9 Jun 2025 16:29:17 -0400 Subject: [PATCH 3/4] Translate `T.bind(self, X)` calls to RBS comments Signed-off-by: Alexandre Terrasa --- .../sorbet_assertions_to_rbs_comments.rb | 15 +++++++++++++-- .../sorbet_assertions_to_rbs_comments_test.rb | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb b/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb index edf4eb13..406bbdff 100644 --- a/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb +++ b/lib/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments.rb @@ -67,12 +67,17 @@ def maybe_translate_assertion(node) start_offset = node.location.start_offset end_offset = node.location.end_offset - @rewriter << Source::Replace.new(start_offset, end_offset - 1, "#{dedent_value(node, value)} #{rbs_annotation}") + + @rewriter << if node.name == :bind + Source::Replace.new(start_offset, end_offset - 1, rbs_annotation) + else + Source::Replace.new(start_offset, end_offset - 1, "#{dedent_value(node, value)} #{rbs_annotation}") + end true end - #: (Prism::CallNode) -> void + #: (Prism::CallNode) -> String def build_rbs_annotation(call) case call.name when :let @@ -83,6 +88,10 @@ def build_rbs_annotation(call) srb_type = call.arguments&.arguments&.last #: as !nil rbs_type = RBI::Type.parse_node(srb_type).rbs_string "#: as #{rbs_type}" + when :bind + srb_type = call.arguments&.arguments&.last #: as !nil + rbs_type = RBI::Type.parse_node(srb_type).rbs_string + "#: self as #{rbs_type}" when :must "#: as !nil" when :unsafe @@ -113,6 +122,8 @@ def t_annotation?(node) case node.name when :let, :cast return node.arguments&.arguments&.size == 2 + when :bind + return node.arguments&.arguments&.size == 2 && node.arguments&.arguments&.first.is_a?(Prism::SelfNode) when :must, :unsafe return node.arguments&.arguments&.size == 1 end diff --git a/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb b/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb index 782365ec..6ec81251 100644 --- a/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb +++ b/test/spoom/sorbet/translate/sorbet_assertions_to_rbs_comments_test.rb @@ -498,6 +498,24 @@ def test_doesnt_translate_in_ternary_expressions assert_equal(rb, rbi_to_rbs(rb)) end + def test_translate_bind + rb = <<~RB + T.bind(self, T.class_of(String)) + + T.bind(foo, String) + + before_enqueue { T.bind(self, String) } + RB + + assert_equal(<<~RB, rbi_to_rbs(rb)) + #: self as singleton(String) + + T.bind(foo, String) + + before_enqueue { T.bind(self, String) } + RB + end + private #: (String) -> String From 207e6f2b16dc3c9f2f9aaa8a5cde752aea032d7d Mon Sep 17 00:00:00 2001 From: Alexandre Terrasa Date: Mon, 9 Jun 2025 16:30:40 -0400 Subject: [PATCH 4/4] Update exported RBI Signed-off-by: Alexandre Terrasa --- rbi/spoom.rbi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rbi/spoom.rbi b/rbi/spoom.rbi index 5f6cd2ad..6ccce9b1 100644 --- a/rbi/spoom.rbi +++ b/rbi/spoom.rbi @@ -2945,7 +2945,7 @@ class Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments < ::Spoom::Sorbet: sig { params(node: ::Prism::Node).returns(T::Boolean) } def at_end_of_line?(node); end - sig { params(call: ::Prism::CallNode).void } + sig { params(call: ::Prism::CallNode).returns(::String) } def build_rbs_annotation(call); end sig { params(assign: ::Prism::Node, value: ::Prism::Node).returns(::String) }