Skip to content

Commit 8926c14

Browse files
authored
Merge pull request #761 from Shopify/at-rbs-multiline
Translate to RBS/RBI using multiline syntax when over --max-line-length
2 parents db5e88f + 46225f7 commit 8926c14

File tree

10 files changed

+1187
-2561
lines changed

10 files changed

+1187
-2561
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ GEM
5252
racc (1.8.1)
5353
rainbow (3.1.1)
5454
rake (13.3.0)
55-
rbi (0.3.5)
55+
rbi (0.3.6)
5656
prism (~> 1.0)
5757
rbs (>= 3.4.4)
5858
rbs (4.0.0.dev.4)

lib/spoom/cli/srb/sigs.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,26 @@ class Sigs < Thor
1616
desc: "Use positional names when translating from RBI to RBS",
1717
default: true
1818
option :include_rbi_files, type: :boolean, desc: "Include RBI files", default: false
19+
option :max_line_length, type: :numeric, desc: "Max line length (pass 0 to disable)", default: 120
1920
def translate(*paths)
2021
from = options[:from]
2122
to = options[:to]
23+
max_line_length = options[:max_line_length]
2224

2325
if from == to
2426
say_error("Can't translate signatures from `#{from}` to `#{to}`")
2527
exit(1)
2628
end
2729

30+
if max_line_length.nil? || max_line_length.zero?
31+
max_line_length = nil
32+
elsif max_line_length.negative?
33+
say_error("--max-line-length can't be negative")
34+
exit(1)
35+
else
36+
max_line_length = max_line_length.to_i
37+
end
38+
2839
files = collect_files(paths, include_rbi_files: options[:include_rbi_files])
2940

3041
say("Translating signatures from `#{from}` to `#{to}` " \
@@ -33,11 +44,20 @@ def translate(*paths)
3344
case from
3445
when "rbi"
3546
transformed_files = transform_files(files) do |file, contents|
36-
Spoom::Sorbet::Translate.sorbet_sigs_to_rbs_comments(contents, file: file, positional_names: options[:positional_names])
47+
Spoom::Sorbet::Translate.sorbet_sigs_to_rbs_comments(
48+
contents,
49+
file: file,
50+
positional_names: options[:positional_names],
51+
max_line_length: max_line_length,
52+
)
3753
end
3854
when "rbs"
3955
transformed_files = transform_files(files) do |file, contents|
40-
Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(contents, file: file)
56+
Spoom::Sorbet::Translate.rbs_comments_to_sorbet_sigs(
57+
contents,
58+
file: file,
59+
max_line_length: max_line_length,
60+
)
4161
end
4262
end
4363

lib/spoom/sorbet/translate.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ def strip_sorbet_sigs(ruby_contents, file:)
2525

2626
# Converts all `sig` nodes to RBS comments in the given Ruby code.
2727
# It also handles type members and class annotations.
28-
#: (String ruby_contents, file: String, ?positional_names: bool) -> String
29-
def sorbet_sigs_to_rbs_comments(ruby_contents, file:, positional_names: true)
30-
SorbetSigsToRBSComments.new(ruby_contents, file: file, positional_names: positional_names).rewrite
28+
#: (String ruby_contents, file: String, ?positional_names: bool, ?max_line_length: Integer?) -> String
29+
def sorbet_sigs_to_rbs_comments(ruby_contents, file:, positional_names: true, max_line_length: nil)
30+
SorbetSigsToRBSComments.new(ruby_contents, file: file, positional_names: positional_names, max_line_length: max_line_length).rewrite
3131
end
3232

3333
# Converts all the RBS comments in the given Ruby code to `sig` nodes.
3434
# It also handles type members and class annotations.
35-
#: (String ruby_contents, file: String) -> String
36-
def rbs_comments_to_sorbet_sigs(ruby_contents, file:)
37-
RBSCommentsToSorbetSigs.new(ruby_contents, file: file).rewrite
35+
#: (String ruby_contents, file: String, ?max_line_length: Integer?) -> String
36+
def rbs_comments_to_sorbet_sigs(ruby_contents, file:, max_line_length: nil)
37+
RBSCommentsToSorbetSigs.new(ruby_contents, file: file, max_line_length: max_line_length).rewrite
3838
end
3939

4040
# Converts all `T.let` and `T.cast` nodes to RBS comments in the given Ruby code.

lib/spoom/sorbet/translate/rbs_comments_to_sorbet_sigs.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ module Translate
77
class RBSCommentsToSorbetSigs < Translator
88
include Spoom::RBS::ExtractRBSComments
99

10+
#: (String, file: String, ?max_line_length: Integer?) -> void
11+
def initialize(ruby_contents, file:, max_line_length: nil)
12+
super(ruby_contents, file: file)
13+
14+
@max_line_length = max_line_length
15+
end
16+
1017
# @override
1118
#: (Prism::ClassNode node) -> void
1219
def visit_class_node(node)
@@ -53,7 +60,7 @@ def visit_def_node(node)
5360
@rewriter << Source::Replace.new(
5461
signature.location.start_offset,
5562
signature.location.end_offset,
56-
sig.string,
63+
sig.string(max_line_length: @max_line_length),
5764
)
5865
rescue ::RBS::ParsingError, ::RBI::Error
5966
# Ignore signatures with errors
@@ -104,7 +111,7 @@ def visit_attr(node)
104111
@rewriter << Source::Replace.new(
105112
signature.location.start_offset,
106113
signature.location.end_offset,
107-
sig.string,
114+
sig.string(max_line_length: @max_line_length),
108115
)
109116
rescue ::RBS::ParsingError, ::RBI::Error
110117
# Ignore signatures with errors

lib/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments.rb

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ module Translate
77
# Converts all `sig` nodes to RBS comments in the given Ruby code.
88
# It also handles type members and class annotations.
99
class SorbetSigsToRBSComments < Translator
10-
#: (String, file: String, positional_names: bool) -> void
11-
def initialize(ruby_contents, file:, positional_names:)
10+
#: (String, file: String, positional_names: bool, ?max_line_length: Integer?) -> void
11+
def initialize(ruby_contents, file:, positional_names:, max_line_length: nil)
1212
super(ruby_contents, file: file)
1313

1414
@positional_names = positional_names #: bool
@@ -18,6 +18,7 @@ def initialize(ruby_contents, file:, positional_names:)
1818
@extend_t_helpers = [] #: Array[Prism::CallNode]
1919
@extend_t_generics = [] #: Array[Prism::CallNode]
2020
@seen_mixes_in_class_methods = false #: bool
21+
@max_line_length = max_line_length #: Integer?
2122
end
2223

2324
# @override
@@ -53,12 +54,10 @@ def visit_def_node(node)
5354
rbi_node = builder.tree.nodes.first #: as RBI::Method
5455

5556
last_sigs.each do |node, sig|
56-
out = StringIO.new
57-
p = RBI::RBSPrinter.new(out: out, indent: node.location.start_column, positional_names: @positional_names)
58-
p.print("#: ")
59-
p.send(:print_method_sig, rbi_node, sig)
60-
p.print("\n")
61-
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out.string)
57+
out = rbs_print(node.location.start_column) do |printer|
58+
printer.print_method_sig(rbi_node, sig)
59+
end
60+
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out)
6261
end
6362
end
6463

@@ -165,12 +164,10 @@ def visit_attr(node)
165164
rbi_node = builder.tree.nodes.first #: as RBI::Attr
166165

167166
last_sigs.each do |node, sig|
168-
out = StringIO.new
169-
p = RBI::RBSPrinter.new(out: out, indent: node.location.start_column, positional_names: @positional_names)
170-
p.print("#: ")
171-
p.print_attr_sig(rbi_node, sig)
172-
p.print("\n")
173-
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out.string)
167+
out = rbs_print(node.location.start_column) do |printer|
168+
printer.print_attr_sig(rbi_node, sig)
169+
end
170+
@rewriter << Source::Replace.new(node.location.start_offset, node.location.end_offset, out)
174171
end
175172
end
176173

@@ -342,6 +339,22 @@ def collect_last_sigs
342339
@last_sigs = []
343340
last_sigs
344341
end
342+
343+
#: (Integer) { (RBI::RBSPrinter) -> void } -> String
344+
def rbs_print(indent, &block)
345+
out = StringIO.new
346+
p = RBI::RBSPrinter.new(out: out, positional_names: @positional_names, max_line_length: @max_line_length)
347+
block.call(p)
348+
string = out.string
349+
350+
string.lines.map.with_index do |line, index|
351+
if index == 0
352+
"#: #{line}"
353+
else
354+
"#{" " * indent}#| #{line}"
355+
end
356+
end.join + "\n"
357+
end
345358
end
346359
end
347360
end

rbi/spoom.rbi

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,14 +2839,21 @@ Spoom::Sorbet::Sigils::VALID_STRICTNESS = T.let(T.unsafe(nil), Array)
28392839

28402840
module Spoom::Sorbet::Translate
28412841
class << self
2842-
sig { params(ruby_contents: ::String, file: ::String).returns(::String) }
2843-
def rbs_comments_to_sorbet_sigs(ruby_contents, file:); end
2842+
sig { params(ruby_contents: ::String, file: ::String, max_line_length: T.nilable(::Integer)).returns(::String) }
2843+
def rbs_comments_to_sorbet_sigs(ruby_contents, file:, max_line_length: T.unsafe(nil)); end
28442844

28452845
sig { params(ruby_contents: ::String, file: ::String).returns(::String) }
28462846
def sorbet_assertions_to_rbs_comments(ruby_contents, file:); end
28472847

2848-
sig { params(ruby_contents: ::String, file: ::String, positional_names: T::Boolean).returns(::String) }
2849-
def sorbet_sigs_to_rbs_comments(ruby_contents, file:, positional_names: T.unsafe(nil)); end
2848+
sig do
2849+
params(
2850+
ruby_contents: ::String,
2851+
file: ::String,
2852+
positional_names: T::Boolean,
2853+
max_line_length: T.nilable(::Integer)
2854+
).returns(::String)
2855+
end
2856+
def sorbet_sigs_to_rbs_comments(ruby_contents, file:, positional_names: T.unsafe(nil), max_line_length: T.unsafe(nil)); end
28502857

28512858
sig { params(ruby_contents: ::String, file: ::String).returns(::String) }
28522859
def strip_sorbet_sigs(ruby_contents, file:); end
@@ -2858,6 +2865,9 @@ class Spoom::Sorbet::Translate::Error < ::Spoom::Error; end
28582865
class Spoom::Sorbet::Translate::RBSCommentsToSorbetSigs < ::Spoom::Sorbet::Translate::Translator
28592866
include ::Spoom::RBS::ExtractRBSComments
28602867

2868+
sig { params(ruby_contents: ::String, file: ::String, max_line_length: T.nilable(::Integer)).void }
2869+
def initialize(ruby_contents, file:, max_line_length: T.unsafe(nil)); end
2870+
28612871
sig { override.params(node: ::Prism::CallNode).void }
28622872
def visit_call_node(node); end
28632873

@@ -2924,8 +2934,15 @@ end
29242934
Spoom::Sorbet::Translate::SorbetAssertionsToRBSComments::LINE_BREAK = T.let(T.unsafe(nil), Integer)
29252935

29262936
class Spoom::Sorbet::Translate::SorbetSigsToRBSComments < ::Spoom::Sorbet::Translate::Translator
2927-
sig { params(ruby_contents: ::String, file: ::String, positional_names: T::Boolean).void }
2928-
def initialize(ruby_contents, file:, positional_names:); end
2937+
sig do
2938+
params(
2939+
ruby_contents: ::String,
2940+
file: ::String,
2941+
positional_names: T::Boolean,
2942+
max_line_length: T.nilable(::Integer)
2943+
).void
2944+
end
2945+
def initialize(ruby_contents, file:, positional_names:, max_line_length: T.unsafe(nil)); end
29292946

29302947
sig { override.params(node: ::Prism::CallNode).void }
29312948
def visit_call_node(node); end
@@ -2970,6 +2987,9 @@ class Spoom::Sorbet::Translate::SorbetSigsToRBSComments < ::Spoom::Sorbet::Trans
29702987
sig { void }
29712988
def delete_extend_t_helpers; end
29722989

2990+
sig { params(indent: ::Integer, block: T.proc.params(arg0: ::RBI::RBSPrinter).void).returns(::String) }
2991+
def rbs_print(indent, &block); end
2992+
29732993
sig { params(node: ::Prism::CallNode).void }
29742994
def visit_attr(node); end
29752995

0 commit comments

Comments
 (0)