Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion lib/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def visit_def_node(node)
out = rbs_print(node.location.start_column) do |printer|
printer.print_method_sig(rbi_node, sig)
end
out = add_sig_comments(node, out)
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out)
end

Expand Down Expand Up @@ -179,7 +180,7 @@ def visit_scope(node, &block)
def visit_sig(node)
return unless sorbet_sig?(node)

builder = RBI::Parser::SigBuilder.new(@ruby_contents, file: @file)
builder = RBI::Parser::SigBuilder.new(@ruby_contents, comments_by_line: @comments_by_line, file: @file)
builder.current.loc = node.location
builder.visit_call_node(node)
builder.current.comments = []
Expand Down Expand Up @@ -207,6 +208,7 @@ def visit_attr(node)
out = rbs_print(node.location.start_column) do |printer|
printer.print_attr_sig(rbi_node, sig)
end
out = add_sig_comments(node, out)
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out)
end
end
Expand Down Expand Up @@ -379,6 +381,20 @@ def delete_extend_t_generics
@extend_t_generics.clear
end

# `RBI::SigBuilder` consumes parameter comments and attaches them to `RBI::SigParam`.
# Preserve any other comments left inside the sig body, like comments before `returns`.
#: (Prism::CallNode, String) -> String
def add_sig_comments(sig_node, out)
comments = @comments_by_line.values.select do |comment|
comment.location.start_offset > sig_node.location.start_offset &&
comment.location.end_offset <= sig_node.location.end_offset
end
return out if comments.empty?

indent = " " * sig_node.location.start_column
comments.map { |comment| "#{comment.slice}\n#{indent}" }.join + out
end

# Collects the last signatures visited and clears the current list
#: -> Array[[Prism::CallNode, RBI::Sig]]
def collect_last_sigs
Expand Down
1 change: 1 addition & 0 deletions lib/spoom/sorbet/translate/translator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def initialize(ruby_contents, file:)
node, comments = Spoom.parse_ruby(ruby_contents, file: file)
@node = node #: Prism::Node
@comments = comments #: Array[Prism::Comment]
@comments_by_line = comments.to_h { |comment| [comment.location.start_line, comment] } #: Hash[Integer, Prism::Comment]
@ruby_bytes = ruby_contents.bytes #: Array[Integer]
@rewriter = Spoom::Source::Rewriter.new #: Source::Rewriter
end
Expand Down
3 changes: 3 additions & 0 deletions rbi/spoom.rbi
Original file line number Diff line number Diff line change
Expand Up @@ -3023,6 +3023,9 @@ class Spoom::Sorbet::Translate::SorbetSigsToRBSComments < ::Spoom::Sorbet::Trans

private

sig { params(sig_node: ::Prism::CallNode, out: ::String).returns(::String) }
def add_sig_comments(sig_node, out); end

sig do
params(
parent: T.any(::Prism::ClassNode, ::Prism::ModuleNode, ::Prism::SingletonClassNode),
Expand Down
58 changes: 58 additions & 0 deletions test/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,64 @@ def foo(param1:, param2:); end
RBS
end

def test_translate_to_rbs_sig_with_inline_param_comments
contents = <<~RB
sig do
params(
# First param
a: Integer,
# Second param
b: String
).void
end
def foo(a, b); end

sig do
# A comment
returns(Integer)
end
attr_reader :x
RB

assert_equal(<<~RBS, sorbet_sigs_to_rbs_comments(contents))
#: (
#| # First param
#| Integer a,
#| # Second param
#| String b
#| ) -> void
def foo(a, b); end

# A comment
#: Integer
attr_reader :x
Comment thread
KaanOzkan marked this conversation as resolved.
RBS
end

def test_translate_to_rbs_sig_with_inline_param_comments_indented
contents = <<~RB
class Foo
sig do
params(
# First param
a: Integer
).void
end
def foo(a); end
end
RB

assert_equal(<<~RBS, sorbet_sigs_to_rbs_comments(contents))
class Foo
#: (
#| # First param
#| Integer a
#| ) -> void
def foo(a); end
end
RBS
end

def test_translate_to_rbs_defs_within_send
contents = <<~RB
sig { void }
Expand Down
Loading