Skip to content

Commit cfe3511

Browse files
committed
Only delete extend T::Helpers when needed
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
1 parent 3fc4c73 commit cfe3511

2 files changed

Lines changed: 60 additions & 15 deletions

File tree

lib/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments.rb

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ def initialize(ruby_contents, file:, positional_names:)
1212
super(ruby_contents, file: file)
1313

1414
@positional_names = positional_names #: bool
15-
@nesting = [] #: Array[Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode]
1615
@last_sigs = [] #: Array[[Prism::CallNode, RBI::Sig]]
16+
@class_annotations = [] #: Array[Prism::CallNode]
1717
@type_members = [] #: Array[String]
1818
@extend_t_helpers = [] #: Array[Prism::CallNode]
1919
@extend_t_generics = [] #: Array[Prism::CallNode]
20+
@seen_mixes_in_class_methods = false #: bool
2021
end
2122

2223
# @override
@@ -73,7 +74,9 @@ def visit_call_node(node)
7374
when "extend"
7475
visit_extend(node)
7576
when "abstract!", "interface!", "sealed!", "final!", "requires_ancestor"
76-
visit_class_annotation(node)
77+
@class_annotations << node
78+
when "mixes_in_class_methods"
79+
@seen_mixes_in_class_methods = true
7780
else
7881
super
7982
end
@@ -99,25 +102,39 @@ def visit_constant_write_node(node)
99102

100103
#: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode) { -> void } -> void
101104
def visit_scope(node, &block)
102-
@nesting << node
105+
old_class_annotations = @class_annotations
106+
@class_annotations = []
103107
old_type_members = @type_members
104108
@type_members = []
105109
old_extend_t_helpers = @extend_t_helpers
106110
@extend_t_helpers = []
107111
old_extend_t_generics = @extend_t_generics
108112
@extend_t_generics = []
113+
old_seen_mixes_in_class_methods = @seen_mixes_in_class_methods
114+
@seen_mixes_in_class_methods = false
109115

110116
yield
111117

118+
delete_extend_t_generics
119+
112120
if @type_members.any?
113121
indent = " " * node.location.start_column
114122
@rewriter << Source::Insert.new(node.location.start_offset, "#: [#{@type_members.join(", ")}]\n#{indent}")
115123
end
116124

125+
unless @seen_mixes_in_class_methods
126+
delete_extend_t_helpers
127+
end
128+
129+
@class_annotations.each do |call|
130+
apply_class_annotation(node, call)
131+
end
132+
133+
@class_annotations = old_class_annotations
117134
@type_members = old_type_members
118135
@extend_t_helpers = old_extend_t_helpers
119136
@extend_t_generics = old_extend_t_generics
120-
@nesting.pop
137+
@seen_mixes_in_class_methods = old_seen_mixes_in_class_methods
121138
end
122139

123140
#: (Prism::CallNode) -> void
@@ -177,8 +194,8 @@ def visit_extend(node)
177194
end
178195
end
179196

180-
#: (Prism::CallNode node) -> void
181-
def visit_class_annotation(node)
197+
#: (Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode, Prism::CallNode) -> void
198+
def apply_class_annotation(parent, node)
182199
unless node.message == "abstract!" || node.message == "interface!" || node.message == "sealed!" ||
183200
node.message == "final!" || node.message == "requires_ancestor"
184201
raise Error, "Expected abstract!, interface!, sealed!, final!, or requires_ancestor"
@@ -187,18 +204,17 @@ def visit_class_annotation(node)
187204
return unless node.receiver.nil? || node.receiver.is_a?(Prism::SelfNode)
188205
return unless node.arguments.nil?
189206

190-
klass = @nesting.last #: as Prism::Node
191-
indent = " " * klass.location.start_column
207+
indent = " " * parent.location.start_column
192208

193209
case node.message
194210
when "abstract!"
195-
@rewriter << Source::Insert.new(klass.location.start_offset, "# @abstract\n#{indent}")
211+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @abstract\n#{indent}")
196212
when "interface!"
197-
@rewriter << Source::Insert.new(klass.location.start_offset, "# @interface\n#{indent}")
213+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @interface\n#{indent}")
198214
when "sealed!"
199-
@rewriter << Source::Insert.new(klass.location.start_offset, "# @sealed\n#{indent}")
215+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @sealed\n#{indent}")
200216
when "final!"
201-
@rewriter << Source::Insert.new(klass.location.start_offset, "# @final\n#{indent}")
217+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @final\n#{indent}")
202218
when "requires_ancestor"
203219
block = node.block
204220
return unless block.is_a?(Prism::BlockNode)
@@ -209,7 +225,7 @@ def visit_class_annotation(node)
209225

210226
arg = body.body.first #: as Prism::Node
211227
srb_type = RBI::Type.parse_node(arg)
212-
@rewriter << Source::Insert.new(klass.location.start_offset, "# @requires_ancestor: #{srb_type.rbs_string}\n#{indent}")
228+
@rewriter << Source::Insert.new(parent.location.start_offset, "# @requires_ancestor: #{srb_type.rbs_string}\n#{indent}")
213229
end
214230

215231
from = adjust_to_line_start(node.location.start_offset)
@@ -305,6 +321,8 @@ def delete_extend_t_helpers
305321
to = adjust_to_new_line(to)
306322
@rewriter << Source::Delete.new(from, to)
307323
end
324+
325+
@extend_t_helpers.clear
308326
end
309327

310328
#: -> void
@@ -315,6 +333,8 @@ def delete_extend_t_generics
315333
to = adjust_to_new_line(to)
316334
@rewriter << Source::Delete.new(from, to)
317335
end
336+
337+
@extend_t_generics.clear
318338
end
319339
end
320340
end

test/spoom/sorbet/translate/sorbet_sigs_to_rbs_comments_test.rb

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ class << self
226226
# @abstract
227227
# @requires_ancestor: singleton(Foo::Bar)
228228
class A
229-
# @interface
230229
# @sealed
230+
# @interface
231231
module B
232232
# @final
233233
class << self
@@ -249,9 +249,34 @@ def bar
249249
end
250250
end
251251
end
252+
253+
module Baz
254+
extend T::Helpers
255+
256+
mixes_in_class_methods Foo::Bar
257+
requires_ancestor { Foo::Bar }
258+
end
252259
RB
253260

254-
assert_equal(contents, sorbet_sigs_to_rbs_comments(contents))
261+
assert_equal(<<~RB, sorbet_sigs_to_rbs_comments(contents))
262+
module Foo
263+
extend T::Helpers
264+
265+
mixes_in_class_methods Bar
266+
267+
module Bar
268+
def bar
269+
end
270+
end
271+
end
272+
273+
# @requires_ancestor: Foo::Bar
274+
module Baz
275+
extend T::Helpers
276+
277+
mixes_in_class_methods Foo::Bar
278+
end
279+
RB
255280
end
256281

257282
def test_translate_to_rbs_generics

0 commit comments

Comments
 (0)