rbi 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/rbi/parser.rb ADDED
@@ -0,0 +1,449 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "unparser"
5
+
6
+ module RBI
7
+ class Parser
8
+ extend T::Sig
9
+
10
+ class Error < StandardError; end
11
+
12
+ # opt-in to most recent AST format
13
+ ::Parser::Builders::Default.emit_lambda = true
14
+ ::Parser::Builders::Default.emit_procarg0 = true
15
+ ::Parser::Builders::Default.emit_encoding = true
16
+ ::Parser::Builders::Default.emit_index = true
17
+ ::Parser::Builders::Default.emit_arg_inside_procarg0 = true
18
+
19
+ sig { params(string: String).returns(Tree) }
20
+ def self.parse_string(string)
21
+ Parser.new.parse_string(string)
22
+ end
23
+
24
+ sig { params(path: String).returns(Tree) }
25
+ def self.parse_file(path)
26
+ Parser.new.parse_file(path)
27
+ end
28
+
29
+ sig { params(string: String).returns(Tree) }
30
+ def parse_string(string)
31
+ parse(string, file: "-")
32
+ rescue ::Parser::SyntaxError => e
33
+ raise Error, e.message
34
+ end
35
+
36
+ sig { params(path: String).returns(Tree) }
37
+ def parse_file(path)
38
+ parse(::File.read(path), file: path)
39
+ rescue ::Parser::SyntaxError => e
40
+ raise Error, e.message
41
+ end
42
+
43
+ private
44
+
45
+ sig { params(content: String, file: String).returns(Tree) }
46
+ def parse(content, file:)
47
+ node, comments = Unparser.parse_with_comments(content)
48
+ assoc = ::Parser::Source::Comment.associate_locations(node, comments)
49
+ builder = TreeBuilder.new(file: file, comments: assoc)
50
+ builder.visit(node)
51
+ builder.assoc_dangling_comments(comments)
52
+ builder.tree
53
+ end
54
+ end
55
+
56
+ class ASTVisitor
57
+ extend T::Helpers
58
+ extend T::Sig
59
+
60
+ abstract!
61
+
62
+ sig { params(nodes: T::Array[AST::Node]).void }
63
+ def visit_all(nodes)
64
+ nodes.each { |node| visit(node) }
65
+ end
66
+
67
+ sig { abstract.params(node: T.nilable(AST::Node)).void }
68
+ def visit(node); end
69
+
70
+ private
71
+
72
+ sig { params(node: AST::Node).returns(String) }
73
+ def visit_name(node)
74
+ T.must(ConstBuilder.visit(node))
75
+ end
76
+
77
+ sig { params(node: AST::Node).returns(String) }
78
+ def visit_expr(node)
79
+ Unparser.unparse(node)
80
+ end
81
+ end
82
+
83
+ class TreeBuilder < ASTVisitor
84
+ extend T::Sig
85
+
86
+ sig { returns(Tree) }
87
+ attr_reader :tree
88
+
89
+ sig do
90
+ params(
91
+ file: String,
92
+ comments: T.nilable(T::Hash[::Parser::Source::Map, T::Array[::Parser::Source::Comment]])
93
+ ).void
94
+ end
95
+ def initialize(file:, comments: nil)
96
+ super()
97
+ @file = file
98
+ @comments = comments
99
+ @tree = T.let(Tree.new, Tree)
100
+ @scopes_stack = T.let([@tree], T::Array[Tree])
101
+ @last_sigs = T.let([], T::Array[RBI::Sig])
102
+ end
103
+
104
+ sig { override.params(node: T.nilable(Object)).void }
105
+ def visit(node)
106
+ return unless node.is_a?(AST::Node)
107
+ case node.type
108
+ when :module, :class, :sclass
109
+ visit_scope(node)
110
+ when :casgn
111
+ visit_const_assign(node)
112
+ when :def, :defs
113
+ visit_def(node)
114
+ when :send
115
+ visit_send(node)
116
+ when :block
117
+ visit_block(node)
118
+ else
119
+ visit_all(node.children)
120
+ end
121
+ end
122
+
123
+ sig { params(comments: T::Array[::Parser::Source::Comment]).void }
124
+ def assoc_dangling_comments(comments)
125
+ return unless tree.empty?
126
+ comments.each do |comment|
127
+ text = comment.text[1..-1].strip
128
+ loc = ast_to_rbi_loc(comment.location)
129
+ tree.comments << Comment.new(text, loc: loc)
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ sig { params(node: AST::Node).void }
136
+ def visit_scope(node)
137
+ loc = node_loc(node)
138
+ comments = node_comments(node)
139
+
140
+ scope = case node.type
141
+ when :module
142
+ name = visit_name(node.children[0])
143
+ Module.new(name, loc: loc, comments: comments)
144
+ when :class
145
+ name = visit_name(node.children[0])
146
+ superclass_name = ConstBuilder.visit(node.children[1])
147
+ Class.new(name, superclass_name: superclass_name, loc: loc, comments: comments)
148
+ when :sclass
149
+ SingletonClass.new(loc: loc, comments: comments)
150
+ else
151
+ raise "Unsupported node #{node.type}"
152
+ end
153
+ current_scope << scope
154
+
155
+ @scopes_stack << scope
156
+ visit_all(node.children)
157
+ @scopes_stack.pop
158
+ end
159
+
160
+ sig { params(node: AST::Node).void }
161
+ def visit_const_assign(node)
162
+ name = visit_name(node)
163
+ value = visit_expr(node.children[2])
164
+ loc = node_loc(node)
165
+ comments = node_comments(node)
166
+
167
+ current_scope << Const.new(name, value, loc: loc, comments: comments)
168
+ end
169
+
170
+ sig { params(node: AST::Node).void }
171
+ def visit_def(node)
172
+ current_scope << case node.type
173
+ when :def
174
+ Method.new(
175
+ node.children[0].to_s,
176
+ params: node.children[1].children.map { |child| visit_param(child) },
177
+ sigs: current_sigs,
178
+ loc: node_loc(node),
179
+ comments: node_comments(node)
180
+ )
181
+ when :defs
182
+ Method.new(
183
+ node.children[1].to_s,
184
+ params: node.children[2].children.map { |child| visit_param(child) },
185
+ is_singleton: true,
186
+ sigs: current_sigs,
187
+ loc: node_loc(node),
188
+ comments: node_comments(node)
189
+ )
190
+ else
191
+ raise "Unsupported node #{node.type}"
192
+ end
193
+ end
194
+
195
+ sig { params(node: AST::Node).returns(Param) }
196
+ def visit_param(node)
197
+ name = node.children[0].to_s
198
+ loc = node_loc(node)
199
+ comments = node_comments(node)
200
+
201
+ case node.type
202
+ when :arg
203
+ Param.new(name, loc: loc, comments: comments)
204
+ when :optarg
205
+ value = visit_expr(node.children[1])
206
+ OptParam.new(name, value, loc: loc, comments: comments)
207
+ when :restarg
208
+ RestParam.new(name, loc: loc, comments: comments)
209
+ when :kwarg
210
+ KwParam.new(name, loc: loc, comments: comments)
211
+ when :kwoptarg
212
+ value = visit_expr(node.children[1])
213
+ KwOptParam.new(name, value, loc: loc, comments: comments)
214
+ when :kwrestarg
215
+ KwRestParam.new(name, loc: loc, comments: comments)
216
+ when :blockarg
217
+ BlockParam.new(name, loc: loc, comments: comments)
218
+ else
219
+ raise "Unsupported node #{node.type}"
220
+ end
221
+ end
222
+
223
+ sig { params(node: AST::Node).void }
224
+ def visit_send(node)
225
+ recv = node.children[0]
226
+ return if recv && recv != :self
227
+
228
+ method_name = node.children[1]
229
+ loc = node_loc(node)
230
+ comments = node_comments(node)
231
+
232
+ current_scope << case method_name
233
+ when :attr_reader
234
+ symbols = node.children[2..-1].map { |child| child.children[0] }
235
+ AttrReader.new(*symbols, sigs: current_sigs, loc: loc, comments: comments)
236
+ when :attr_writer
237
+ symbols = node.children[2..-1].map { |child| child.children[0] }
238
+ AttrWriter.new(*symbols, sigs: current_sigs, loc: loc, comments: comments)
239
+ when :attr_accessor
240
+ symbols = node.children[2..-1].map { |child| child.children[0] }
241
+ AttrAccessor.new(*symbols, sigs: current_sigs, loc: loc, comments: comments)
242
+ when :include
243
+ names = node.children[2..-1].map { |child| visit_name(child) }
244
+ Include.new(*names, loc: loc, comments: comments)
245
+ when :extend
246
+ names = node.children[2..-1].map { |child| visit_name(child) }
247
+ Extend.new(*names, loc: loc, comments: comments)
248
+ when :abstract!, :sealed!, :interface!
249
+ Helper.new(method_name.to_s.delete_suffix("!"), loc: loc, comments: comments)
250
+ when :mixes_in_class_methods
251
+ names = node.children[2..-1].map { |child| visit_name(child) }
252
+ MixesInClassMethods.new(*names, loc: loc, comments: comments)
253
+ when :public, :protected, :private
254
+ Visibility.new(method_name, loc: loc)
255
+ when :prop
256
+ name, type, default_value = visit_struct_prop(node)
257
+ TStructProp.new(name, type, default: default_value, loc: loc, comments: comments)
258
+ when :const
259
+ name, type, default_value = visit_struct_prop(node)
260
+ TStructConst.new(name, type, default: default_value, loc: loc, comments: comments)
261
+ else
262
+ raise "Unsupported node #{node.type} with name #{method_name}"
263
+ end
264
+ end
265
+
266
+ sig { params(node: AST::Node).void }
267
+ def visit_block(node)
268
+ name = node.children[0].children[1]
269
+
270
+ case name
271
+ when :sig
272
+ @last_sigs << visit_sig(node)
273
+ when :enums
274
+ current_scope << visit_enum(node)
275
+ else
276
+ raise "Unsupported node #{node.type} with name #{name}"
277
+ end
278
+ end
279
+
280
+ sig { params(node: AST::Node).returns([String, String, T.nilable(String)]) }
281
+ def visit_struct_prop(node)
282
+ name = node.children[2].children[0].to_s
283
+ type = visit_expr(node.children[3])
284
+ has_default = node.children[4]
285
+ &.children&.fetch(0, nil)
286
+ &.children&.fetch(0, nil)
287
+ &.children&.fetch(0, nil) == :default
288
+ default_value = if has_default
289
+ visit_expr(node.children.fetch(4, nil)
290
+ &.children&.fetch(0, nil)
291
+ &.children&.fetch(1, nil))
292
+ end
293
+ [name, type, default_value]
294
+ end
295
+
296
+ sig { params(node: AST::Node).returns(Sig) }
297
+ def visit_sig(node)
298
+ sig = SigBuilder.build(node)
299
+ sig.loc = node_loc(node)
300
+ sig
301
+ end
302
+
303
+ sig { params(node: AST::Node).returns(TEnumBlock) }
304
+ def visit_enum(node)
305
+ enum = TEnumBlock.new
306
+ node.children[2].children.each do |child|
307
+ enum << visit_name(child)
308
+ end
309
+ enum.loc = node_loc(node)
310
+ enum
311
+ end
312
+
313
+ sig { params(node: AST::Node).returns(Loc) }
314
+ def node_loc(node)
315
+ ast_to_rbi_loc(node.location)
316
+ end
317
+
318
+ sig { params(ast_loc: ::Parser::Source::Map).returns(Loc) }
319
+ def ast_to_rbi_loc(ast_loc)
320
+ Loc.new(
321
+ file: @file,
322
+ begin_line: ast_loc.line,
323
+ begin_column: ast_loc.column,
324
+ end_line: ast_loc.last_line,
325
+ end_column: ast_loc.last_column
326
+ )
327
+ end
328
+
329
+ sig { params(node: AST::Node).returns(T::Array[Comment]) }
330
+ def node_comments(node)
331
+ return [] unless @comments
332
+ comments = @comments[node.location]
333
+ return [] unless comments
334
+ comments.map do |comment|
335
+ text = comment.text[1..-1].strip
336
+ loc = ast_to_rbi_loc(comment.location)
337
+ Comment.new(text, loc: loc)
338
+ end
339
+ end
340
+
341
+ sig { returns(Tree) }
342
+ def current_scope
343
+ T.must(@scopes_stack.last) # Should never be nil since we create a Tree as the root
344
+ end
345
+
346
+ sig { returns(T::Array[Sig]) }
347
+ def current_sigs
348
+ sigs = @last_sigs.dup
349
+ @last_sigs.clear
350
+ sigs
351
+ end
352
+ end
353
+
354
+ class ConstBuilder < ASTVisitor
355
+ extend T::Sig
356
+
357
+ sig { params(node: T.nilable(AST::Node)).returns(T.nilable(String)) }
358
+ def self.visit(node)
359
+ v = ConstBuilder.new
360
+ v.visit(node)
361
+ return nil if v.names.empty?
362
+ v.names.join("::")
363
+ end
364
+
365
+ sig { returns(T::Array[String]) }
366
+ attr_accessor :names
367
+
368
+ sig { void }
369
+ def initialize
370
+ super
371
+ @names = T.let([], T::Array[String])
372
+ end
373
+
374
+ sig { override.params(node: T.nilable(AST::Node)).void }
375
+ def visit(node)
376
+ return unless node
377
+ case node.type
378
+ when :const, :casgn
379
+ visit(node.children[0])
380
+ @names << node.children[1].to_s
381
+ when :cbase
382
+ @names << ""
383
+ when :sym
384
+ @names << ":#{node.children[0]}"
385
+ end
386
+ end
387
+ end
388
+
389
+ class SigBuilder < ASTVisitor
390
+ extend T::Sig
391
+
392
+ sig { params(node: AST::Node).returns(Sig) }
393
+ def self.build(node)
394
+ v = SigBuilder.new
395
+ v.visit_all(node.children[2..-1])
396
+ v.current
397
+ end
398
+
399
+ sig { returns(Sig) }
400
+ attr_accessor :current
401
+
402
+ sig { void }
403
+ def initialize
404
+ super
405
+ @current = T.let(Sig.new, Sig)
406
+ end
407
+
408
+ sig { override.params(node: T.nilable(AST::Node)).void }
409
+ def visit(node)
410
+ return unless node
411
+ case node.type
412
+ when :send
413
+ visit_send(node)
414
+ end
415
+ end
416
+
417
+ sig { params(node: AST::Node).void }
418
+ def visit_send(node)
419
+ visit(node.children[0]) if node.children[0]
420
+ name = node.children[1]
421
+ case name
422
+ when :abstract
423
+ @current.is_abstract = true
424
+ when :override
425
+ @current.is_override = true
426
+ when :overridable
427
+ @current.is_overridable = true
428
+ when :checked
429
+ @current.checked = node.children[2].children[0]
430
+ when :type_parameters
431
+ node.children[2..-1].each do |child|
432
+ @current.type_params << child.children[0].to_s
433
+ end
434
+ when :params
435
+ node.children[2].children.each do |child|
436
+ name = child.children[0].children[0].to_s
437
+ type = visit_expr(child.children[1])
438
+ @current << SigParam.new(name, type)
439
+ end
440
+ when :returns
441
+ @current.return_type = visit_expr(node.children[2])
442
+ when :void
443
+ @current.return_type = nil
444
+ else
445
+ raise "#{node.location.line}: Unhandled #{name}"
446
+ end
447
+ end
448
+ end
449
+ end
@@ -0,0 +1,643 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ class Printer < Visitor
6
+ extend T::Sig
7
+
8
+ sig { returns(T::Boolean) }
9
+ attr_accessor :print_locs, :in_visibility_group
10
+
11
+ sig { returns(T.nilable(Node)) }
12
+ attr_reader :previous_node
13
+
14
+ sig { params(out: T.any(IO, StringIO), indent: Integer, print_locs: T::Boolean).void }
15
+ def initialize(out: $stdout, indent: 0, print_locs: false)
16
+ super()
17
+ @out = out
18
+ @current_indent = indent
19
+ @print_locs = print_locs
20
+ @in_visibility_group = T.let(false, T::Boolean)
21
+ @previous_node = T.let(nil, T.nilable(Node))
22
+ end
23
+
24
+ # Printing
25
+
26
+ sig { void }
27
+ def indent
28
+ @current_indent += 2
29
+ end
30
+
31
+ sig { void }
32
+ def dedent
33
+ @current_indent -= 2
34
+ end
35
+
36
+ # Print a string without indentation nor `\n` at the end.
37
+ sig { params(string: String).void }
38
+ def print(string)
39
+ @out.print(string)
40
+ end
41
+
42
+ # Print a string without indentation but with a `\n` at the end.
43
+ sig { params(string: T.nilable(String)).void }
44
+ def printn(string = nil)
45
+ print(string) if string
46
+ print("\n")
47
+ end
48
+
49
+ # Print a string with indentation but without a `\n` at the end.
50
+ sig { params(string: T.nilable(String)).void }
51
+ def printt(string = nil)
52
+ print(" " * @current_indent)
53
+ print(string) if string
54
+ end
55
+
56
+ # Print a string with indentation and `\n` at the end.
57
+ sig { params(string: String).void }
58
+ def printl(string)
59
+ printt
60
+ printn(string)
61
+ end
62
+
63
+ sig { params(file: File).void }
64
+ def visit_file(file)
65
+ file.accept_printer(self)
66
+ end
67
+
68
+ sig { override.params(node: T.nilable(Node)).void }
69
+ def visit(node)
70
+ return unless node
71
+ node.accept_printer(self)
72
+ end
73
+
74
+ sig { override.params(nodes: T::Array[Node]).void }
75
+ def visit_all(nodes)
76
+ previous_node = @previous_node
77
+ @previous_node = nil
78
+ nodes.each do |node|
79
+ visit(node)
80
+ @previous_node = node
81
+ end
82
+ @previous_node = previous_node
83
+ end
84
+ end
85
+
86
+ class File
87
+ extend T::Sig
88
+
89
+ sig { params(v: Printer).void }
90
+ def accept_printer(v)
91
+ strictness = self.strictness
92
+ if strictness
93
+ v.printl("# typed: #{strictness}")
94
+ end
95
+ unless comments.empty?
96
+ v.printn if strictness
97
+ v.visit_all(comments)
98
+ end
99
+
100
+ unless root.empty?
101
+ v.printn if strictness || !comments.empty?
102
+ v.visit(root)
103
+ end
104
+ end
105
+
106
+ sig { params(out: T.any(IO, StringIO), indent: Integer, print_locs: T::Boolean).void }
107
+ def print(out: $stdout, indent: 0, print_locs: false)
108
+ p = Printer.new(out: out, indent: indent, print_locs: print_locs)
109
+ p.visit_file(self)
110
+ end
111
+
112
+ sig { params(indent: Integer, print_locs: T::Boolean).returns(String) }
113
+ def string(indent: 0, print_locs: false)
114
+ out = StringIO.new
115
+ print(out: out, indent: indent, print_locs: print_locs)
116
+ out.string
117
+ end
118
+ end
119
+
120
+ class Node
121
+ extend T::Sig
122
+
123
+ sig { abstract.params(v: Printer).void }
124
+ def accept_printer(v); end
125
+
126
+ sig { params(out: T.any(IO, StringIO), indent: Integer, print_locs: T::Boolean).void }
127
+ def print(out: $stdout, indent: 0, print_locs: false)
128
+ p = Printer.new(out: out, indent: indent, print_locs: print_locs)
129
+ p.visit(self)
130
+ end
131
+
132
+ sig { params(indent: Integer, print_locs: T::Boolean).returns(String) }
133
+ def string(indent: 0, print_locs: false)
134
+ out = StringIO.new
135
+ print(out: out, indent: indent, print_locs: print_locs)
136
+ out.string
137
+ end
138
+
139
+ sig { returns(T::Boolean) }
140
+ def oneline?
141
+ true
142
+ end
143
+ end
144
+
145
+ class NodeWithComments
146
+ extend T::Sig
147
+
148
+ sig { override.returns(T::Boolean) }
149
+ def oneline?
150
+ comments.empty?
151
+ end
152
+ end
153
+
154
+ class Comment
155
+ extend T::Sig
156
+
157
+ sig { override.params(v: Printer).void }
158
+ def accept_printer(v)
159
+ text = self.text.strip
160
+ v.printt("#")
161
+ v.print(" #{text}") unless text.empty?
162
+ v.printn
163
+ end
164
+ end
165
+
166
+ class Tree
167
+ extend T::Sig
168
+
169
+ sig { override.params(v: Printer).void }
170
+ def accept_printer(v)
171
+ v.visit_all(comments)
172
+ v.printn if !comments.empty? && !empty?
173
+ v.visit_all(nodes)
174
+ end
175
+
176
+ sig { override.returns(T::Boolean) }
177
+ def oneline?
178
+ comments.empty? && empty?
179
+ end
180
+ end
181
+
182
+ class Scope
183
+ extend T::Sig
184
+
185
+ sig { override.params(v: Printer).void }
186
+ def accept_printer(v)
187
+ previous_node = v.previous_node
188
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
189
+
190
+ v.printl("# #{loc}") if loc && v.print_locs
191
+ v.visit_all(comments)
192
+
193
+ print_header(v)
194
+ print_body(v)
195
+ end
196
+
197
+ sig { abstract.params(v: Printer).void }
198
+ def print_header(v); end
199
+
200
+ sig { params(v: Printer).void }
201
+ def print_body(v)
202
+ unless empty?
203
+ v.indent
204
+ v.visit_all(nodes)
205
+ v.dedent
206
+ v.printl("end")
207
+ end
208
+ end
209
+ end
210
+
211
+ class Module
212
+ extend T::Sig
213
+
214
+ sig { override.params(v: Printer).void }
215
+ def print_header(v)
216
+ v.printt("module #{name}")
217
+ if empty?
218
+ v.printn("; end")
219
+ else
220
+ v.printn
221
+ end
222
+ end
223
+ end
224
+
225
+ class Class
226
+ extend T::Sig
227
+
228
+ sig { override.params(v: Printer).void }
229
+ def print_header(v)
230
+ v.printt("class #{name}")
231
+ superclass = superclass_name
232
+ v.print(" < #{superclass}") if superclass
233
+ if empty?
234
+ v.printn("; end")
235
+ else
236
+ v.printn
237
+ end
238
+ end
239
+ end
240
+
241
+ class SingletonClass
242
+ extend T::Sig
243
+
244
+ sig { override.params(v: Printer).void }
245
+ def print_header(v)
246
+ v.printt("class << self")
247
+ if empty?
248
+ v.printn("; end")
249
+ else
250
+ v.printn
251
+ end
252
+ end
253
+ end
254
+
255
+ class Const
256
+ extend T::Sig
257
+
258
+ sig { override.params(v: Printer).void }
259
+ def accept_printer(v)
260
+ previous_node = v.previous_node
261
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
262
+
263
+ v.printl("# #{loc}") if loc && v.print_locs
264
+ v.visit_all(comments)
265
+ v.printl("#{name} = #{value}")
266
+ end
267
+ end
268
+
269
+ class Attr
270
+ extend T::Sig
271
+
272
+ sig { override.params(v: Printer).void }
273
+ def accept_printer(v)
274
+ previous_node = v.previous_node
275
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
276
+
277
+ v.visit_all(comments)
278
+ sigs.each { |sig| v.visit(sig) }
279
+ v.printl("# #{loc}") if loc && v.print_locs
280
+ v.printt
281
+ unless v.in_visibility_group || visibility == Visibility::Public
282
+ v.print(visibility.visibility.to_s)
283
+ v.print(" ")
284
+ end
285
+ case self
286
+ when AttrAccessor
287
+ v.print("attr_accessor")
288
+ when AttrReader
289
+ v.print("attr_reader")
290
+ when AttrWriter
291
+ v.print("attr_writer")
292
+ end
293
+ unless names.empty?
294
+ v.print(" ")
295
+ v.print(names.map { |name| ":#{name}" }.join(", "))
296
+ end
297
+ v.printn
298
+ end
299
+
300
+ sig { override.returns(T::Boolean) }
301
+ def oneline?
302
+ comments.empty? && sigs.empty?
303
+ end
304
+ end
305
+
306
+ class Method
307
+ extend T::Sig
308
+
309
+ sig { override.params(v: Printer).void }
310
+ def accept_printer(v)
311
+ previous_node = v.previous_node
312
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
313
+
314
+ v.visit_all(comments)
315
+ v.visit_all(sigs)
316
+ v.printl("# #{loc}") if loc && v.print_locs
317
+ v.printt
318
+ unless v.in_visibility_group || visibility == Visibility::Public
319
+ v.print(visibility.visibility.to_s)
320
+ v.print(" ")
321
+ end
322
+ v.print("def ")
323
+ v.print("self.") if is_singleton
324
+ v.print(name)
325
+ unless params.empty?
326
+ v.print("(")
327
+ if inline_params?
328
+ params.each_with_index do |param, index|
329
+ v.print(", ") if index > 0
330
+ v.visit(param)
331
+ end
332
+ else
333
+ v.printn
334
+ v.indent
335
+ params.each_with_index do |param, pindex|
336
+ v.printt
337
+ v.visit(param)
338
+ v.print(",") if pindex < params.size - 1
339
+ param.comments.each_with_index do |comment, cindex|
340
+ if cindex > 0
341
+ param.print_comment_leading_space(v)
342
+ else
343
+ v.print(" ")
344
+ end
345
+ v.print("# #{comment.text.strip}")
346
+ end
347
+ v.printn
348
+ end
349
+ v.dedent
350
+ end
351
+ v.print(")")
352
+ end
353
+ v.print("; end")
354
+ v.printn
355
+ end
356
+
357
+ sig { override.returns(T::Boolean) }
358
+ def oneline?
359
+ comments.empty? && sigs.empty? && inline_params?
360
+ end
361
+
362
+ sig { returns(T::Boolean) }
363
+ def inline_params?
364
+ params.all? { |p| p.comments.empty? }
365
+ end
366
+ end
367
+
368
+ class Param
369
+ extend T::Sig
370
+
371
+ sig { override.params(v: Printer).void }
372
+ def accept_printer(v)
373
+ v.print(name.to_s)
374
+ end
375
+
376
+ sig { params(v: Printer).void }
377
+ def print_comment_leading_space(v)
378
+ v.printn
379
+ v.printt
380
+ v.print(" " * (name.size + 2))
381
+ end
382
+ end
383
+
384
+ class OptParam
385
+ extend T::Sig
386
+
387
+ sig { override.params(v: Printer).void }
388
+ def accept_printer(v)
389
+ v.print("#{name} = #{value}")
390
+ end
391
+
392
+ sig { override.params(v: Printer).void }
393
+ def print_comment_leading_space(v)
394
+ super
395
+ v.print(" " * (value.size + 3))
396
+ end
397
+ end
398
+
399
+ class RestParam
400
+ extend T::Sig
401
+
402
+ sig { override.params(v: Printer).void }
403
+ def accept_printer(v)
404
+ v.print("*#{name}")
405
+ end
406
+
407
+ sig { override.params(v: Printer).void }
408
+ def print_comment_leading_space(v)
409
+ super
410
+ v.print(" ")
411
+ end
412
+ end
413
+
414
+ class KwParam
415
+ extend T::Sig
416
+
417
+ sig { override.params(v: Printer).void }
418
+ def accept_printer(v)
419
+ v.print("#{name}:")
420
+ end
421
+
422
+ sig { override.params(v: Printer).void }
423
+ def print_comment_leading_space(v)
424
+ super
425
+ v.print(" ")
426
+ end
427
+ end
428
+
429
+ class KwOptParam
430
+ extend T::Sig
431
+
432
+ sig { override.params(v: Printer).void }
433
+ def accept_printer(v)
434
+ v.print("#{name}: #{value}")
435
+ end
436
+
437
+ sig { override.params(v: Printer).void }
438
+ def print_comment_leading_space(v)
439
+ v.printn
440
+ v.printt
441
+ v.print(" " * (name.size + 2))
442
+ v.print(" " * (value.size + 2))
443
+ end
444
+ end
445
+
446
+ class KwRestParam
447
+ extend T::Sig
448
+
449
+ sig { override.params(v: Printer).void }
450
+ def accept_printer(v)
451
+ v.print("**#{name}")
452
+ end
453
+
454
+ sig { override.params(v: Printer).void }
455
+ def print_comment_leading_space(v)
456
+ super
457
+ v.print(" ")
458
+ end
459
+ end
460
+
461
+ class BlockParam
462
+ extend T::Sig
463
+
464
+ sig { override.params(v: Printer).void }
465
+ def accept_printer(v)
466
+ v.print("&#{name}")
467
+ end
468
+ end
469
+
470
+ class Mixin
471
+ extend T::Sig
472
+
473
+ sig { override.params(v: Printer).void }
474
+ def accept_printer(v)
475
+ previous_node = v.previous_node
476
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
477
+
478
+ v.printl("# #{loc}") if loc && v.print_locs
479
+ v.visit_all(comments)
480
+ case self
481
+ when Include
482
+ v.printt("include")
483
+ when Extend
484
+ v.printt("extend")
485
+ when MixesInClassMethods
486
+ v.printt("mixes_in_class_methods")
487
+ end
488
+ v.printn(" #{names.join(", ")}")
489
+ end
490
+ end
491
+
492
+ class Visibility
493
+ extend T::Sig
494
+
495
+ sig { override.params(v: Printer).void }
496
+ def accept_printer(v)
497
+ v.printl("# #{loc}") if loc && v.print_locs
498
+ v.printl(visibility.to_s)
499
+ end
500
+ end
501
+
502
+ class Sig
503
+ extend T::Sig
504
+
505
+ sig { override.params(v: Printer).void }
506
+ def accept_printer(v)
507
+ v.printl("# #{loc}") if loc && v.print_locs
508
+ v.printt("sig { ")
509
+ v.print("abstract.") if is_abstract
510
+ v.print("override.") if is_override
511
+ v.print("overridable.") if is_overridable
512
+ unless type_params.empty?
513
+ v.print("type_parameters(")
514
+ type_params.each_with_index do |param, index|
515
+ v.print(":#{param}")
516
+ v.print(", ") if index < type_params.length - 1
517
+ end
518
+ v.print(").")
519
+ end
520
+ unless params.empty?
521
+ v.print("params(")
522
+ params.each_with_index do |param, index|
523
+ v.visit(param)
524
+ v.print(", ") if index < params.length - 1
525
+ end
526
+ v.print(").")
527
+ end
528
+ if return_type && return_type != "void"
529
+ v.print("returns(#{return_type})")
530
+ else
531
+ v.print("void")
532
+ end
533
+ if checked
534
+ v.print(".checked(:#{checked})")
535
+ end
536
+ v.printn(" }")
537
+ end
538
+ end
539
+
540
+ class SigParam
541
+ extend T::Sig
542
+
543
+ sig { override.params(v: Printer).void }
544
+ def accept_printer(v)
545
+ v.print("#{name}: #{type}")
546
+ end
547
+ end
548
+
549
+ class TStructField
550
+ extend T::Sig
551
+
552
+ sig { override.params(v: Printer).void }
553
+ def accept_printer(v)
554
+ previous_node = v.previous_node
555
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
556
+
557
+ v.printl("# #{loc}") if loc && v.print_locs
558
+ v.visit_all(comments)
559
+ case self
560
+ when TStructProp
561
+ v.printt("prop")
562
+ when TStructConst
563
+ v.printt("const")
564
+ end
565
+ v.print(" :#{name}, #{type}")
566
+ default = self.default
567
+ v.print(", default: #{default}") if default
568
+ v.printn
569
+ end
570
+ end
571
+
572
+ class TEnumBlock
573
+ extend T::Sig
574
+
575
+ sig { override.params(v: Printer).void }
576
+ def accept_printer(v)
577
+ v.printl("# #{loc}") if loc && v.print_locs
578
+ v.visit_all(comments)
579
+ v.printl("enums do")
580
+ v.indent
581
+ names.each do |name|
582
+ v.printl("#{name} = new")
583
+ end
584
+ v.dedent
585
+ v.printl("end")
586
+ end
587
+ end
588
+
589
+ class TypeMember
590
+ extend T::Sig
591
+
592
+ sig { override.params(v: Printer).void }
593
+ def accept_printer(v)
594
+ previous_node = v.previous_node
595
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
596
+
597
+ v.printl("# #{loc}") if loc && v.print_locs
598
+ v.visit_all(comments)
599
+ v.printl("#{name} = #{value}")
600
+ end
601
+ end
602
+
603
+ class Helper
604
+ extend T::Sig
605
+
606
+ sig { override.params(v: Printer).void }
607
+ def accept_printer(v)
608
+ previous_node = v.previous_node
609
+ v.printn if previous_node && (!previous_node.oneline? || !oneline?)
610
+
611
+ v.printl("# #{loc}") if loc && v.print_locs
612
+ v.visit_all(comments)
613
+ v.printl("#{name}!")
614
+ end
615
+ end
616
+
617
+ class Group
618
+ extend T::Sig
619
+
620
+ sig { override.params(v: Printer).void }
621
+ def accept_printer(v)
622
+ v.printn unless v.previous_node.nil?
623
+ v.visit_all(nodes)
624
+ end
625
+ end
626
+
627
+ class VisibilityGroup
628
+ extend T::Sig
629
+
630
+ sig { override.params(v: Printer).void }
631
+ def accept_printer(v)
632
+ v.in_visibility_group = true
633
+ v.printn unless v.previous_node.nil?
634
+ case visibility
635
+ when Visibility::Protected, Visibility::Private
636
+ v.visit(visibility)
637
+ v.printn
638
+ end
639
+ v.visit_all(nodes)
640
+ v.in_visibility_group = false
641
+ end
642
+ end
643
+ end