Skip to content

Commit 7a5304c

Browse files
committed
Preserve sig param comments in RBS output
1 parent 14259a5 commit 7a5304c

4 files changed

Lines changed: 139 additions & 7 deletions

File tree

lib/rbi/parser.rb

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,13 @@ def t_sig_without_runtime?(node)
161161
!!(node.is_a?(Prism::ConstantPathNode) && node_string(node) =~ /(::)?T::Sig::WithoutRuntime/)
162162
end
163163

164-
#: (Prism::Node node) -> Array[Comment]
165-
def node_comments(node)
164+
#: (Prism::Node node, ?min_line: Integer?) -> Array[Comment]
165+
def node_comments(node, min_line: nil)
166166
comments = []
167167

168168
start_line = node.location.start_line
169169
start_line -= 1 unless @comments_by_line.key?(start_line)
170+
start_line = [start_line, min_line].max if min_line
170171

171172
rbs_continuation = [] #: Array[Prism::Comment]
172173

@@ -767,7 +768,7 @@ def parse_params(node)
767768

768769
#: (Prism::CallNode node) -> Sig
769770
def parse_sig(node)
770-
builder = SigBuilder.new(@source, file: @file)
771+
builder = SigBuilder.new(@source, comments_by_line: @comments_by_line, file: @file)
771772
builder.current.loc = node_loc(node)
772773
builder.visit_call_node(node)
773774
builder.current.comments = node_comments(node)
@@ -920,11 +921,15 @@ class SigBuilder < Visitor
920921
#: Sig
921922
attr_reader :current
922923

923-
#: (String content, file: String) -> void
924-
def initialize(content, file:)
925-
super
924+
#: Integer?
925+
attr_reader :params_start_line
926+
927+
#: (String content, comments_by_line: Hash[Integer, Prism::Comment], file: String) -> void
928+
def initialize(content, comments_by_line:, file:)
929+
super(content, comments_by_line: comments_by_line, file: file)
926930

927931
@current = Sig.new #: Sig
932+
@params_start_line = nil #: Integer?
928933
end
929934

930935
# @override
@@ -955,7 +960,9 @@ def visit_call_node(node)
955960
when "overridable"
956961
@current.is_overridable = true
957962
when "params"
963+
@params_start_line = node.location.start_line
958964
visit(node.arguments)
965+
@params_start_line = nil
959966
when "returns"
960967
args = node.arguments
961968
if args.is_a?(Prism::ArgumentsNode)
@@ -983,6 +990,8 @@ def visit_assoc_node(node)
983990
@current.params << SigParam.new(
984991
node_string!(node.key).delete_suffix(":"),
985992
node_string!(node.value),
993+
loc: node_loc(node),
994+
comments: node_comments(node, min_line: params_start_line),
986995
)
987996
end
988997

lib/rbi/rbs_printer.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ def print_method_sig(node, sig)
406406
@out = old_out
407407

408408
max_line_length = @max_line_length
409-
if max_line_length.nil? || new_out.string.size <= max_line_length
409+
if !sig_params_have_comments?(node, sig) && (max_line_length.nil? || new_out.string.size <= max_line_length)
410410
print(new_out.string)
411411
else
412412
print_method_sig_multiline(node, sig)
@@ -495,6 +495,7 @@ def print_method_sig_multiline(node, sig)
495495
printl("(")
496496
indent
497497
sig_params.each_with_index do |param, index|
498+
print_sig_param_comments(param)
498499
printt
499500
print_sig_param(node, param)
500501
print(",") if index < sig_params.size - 1
@@ -899,6 +900,23 @@ def print_sig_param(node, param)
899900
end
900901
end
901902

903+
#: (Method node, Sig sig) -> bool
904+
def sig_params_have_comments?(node, sig)
905+
sig_params = sig.params
906+
907+
block_param = node.params.find { |param| param.is_a?(BlockParam) }
908+
if block_param
909+
sig_params = sig_params.reject { |param| param.name == block_param.name }
910+
end
911+
912+
sig_params.any?(&:comments?)
913+
end
914+
915+
#: (SigParam param) -> void
916+
def print_sig_param_comments(param)
917+
visit_all(param.comments)
918+
end
919+
902920
#: (Param node, last: bool) -> void
903921
def print_param_comment_leading_space(node, last:)
904922
printn

test/rbi/parser_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,33 @@ def test_parse_sig_comments
318318
assert_equal(rbi, out.string)
319319
end
320320

321+
def test_parse_sig_param_comments
322+
rbi = <<~RBI
323+
sig do
324+
params(
325+
# `a` comment
326+
a: Integer,
327+
# `b` comment 1
328+
# `b` comment 2
329+
b: String
330+
).void
331+
end
332+
def foo(a, b); end
333+
RBI
334+
335+
out = Parser.parse_string(rbi)
336+
assert_equal(<<~RBI, out.string)
337+
sig do
338+
params(
339+
a: Integer, # `a` comment
340+
b: String # `b` comment 1
341+
# `b` comment 2
342+
).void
343+
end
344+
def foo(a, b); end
345+
RBI
346+
end
347+
321348
def test_parse_methods_with_visibility
322349
rbi = <<~RBI
323350
private def m1; end

test/rbi/rbs_printer_test.rb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,84 @@ def test_print_breaks_long_signatures
560560
RBI
561561
end
562562

563+
def test_print_breaks_signatures_with_sig_param_comments
564+
rbi_def = Method.new("foo") do |node|
565+
node.params << ReqParam.new("a")
566+
node.params << ReqParam.new("b")
567+
end
568+
569+
rbi_sig = Sig.new do |sig|
570+
sig.params << SigParam.new("a", "Integer", comments: [Comment.new("First param")])
571+
sig.params << SigParam.new("b", "String")
572+
sig.return_type = "void"
573+
end
574+
575+
out = StringIO.new
576+
printer = RBI::RBSPrinter.new(out: out)
577+
printer.print_method_sig(rbi_def, rbi_sig)
578+
579+
assert_equal(<<~RBI.strip, out.string)
580+
(
581+
# First param
582+
Integer a,
583+
String b
584+
) -> void
585+
RBI
586+
end
587+
588+
def test_print_breaks_signatures_with_multiple_sig_param_comments
589+
rbi_def = Method.new("foo") do |node|
590+
node.params << ReqParam.new("a")
591+
node.params << ReqParam.new("b")
592+
node.params << KwParam.new("c")
593+
end
594+
595+
rbi_sig = Sig.new do |sig|
596+
sig.params << SigParam.new("a", "Integer", comments: [Comment.new("First param")])
597+
sig.params << SigParam.new("b", "String", comments: [Comment.new("Second param")])
598+
sig.params << SigParam.new("c", "Symbol", comments: [Comment.new("Keyword param")])
599+
sig.return_type = "void"
600+
end
601+
602+
out = StringIO.new
603+
printer = RBI::RBSPrinter.new(out: out)
604+
printer.print_method_sig(rbi_def, rbi_sig)
605+
606+
assert_equal(<<~RBI.strip, out.string)
607+
(
608+
# First param
609+
Integer a,
610+
# Second param
611+
String b,
612+
# Keyword param
613+
c: Symbol
614+
) -> void
615+
RBI
616+
end
617+
618+
def test_print_breaks_signatures_with_mixed_sig_param_comments
619+
rbi = parse_rbi(<<~RBI)
620+
sig do
621+
params(
622+
a: Integer,
623+
# Commented param
624+
b: String,
625+
c: Symbol
626+
).void
627+
end
628+
def foo(a, b, c:); end
629+
RBI
630+
631+
assert_equal(<<~RBI, rbi.rbs_string)
632+
def foo: (
633+
Integer a,
634+
# Commented param
635+
String b,
636+
c: Symbol
637+
) -> void
638+
RBI
639+
end
640+
563641
def test_print_simplified_types
564642
rbi = parse_rbi(<<~RBI)
565643
sig { returns(T.any(String, String, NilClass, T.nilable(T.nilable(Integer)), TrueClass, FalseClass)) }

0 commit comments

Comments
 (0)