@@ -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
0 commit comments