syntax_tree-rbs 0.2.0 → 0.5.0

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.
@@ -0,0 +1,533 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SyntaxTree
4
+ module RBS
5
+ class PrettyPrint < Visitor
6
+ attr_reader :q
7
+
8
+ def initialize(q)
9
+ @q = q
10
+ end
11
+
12
+ def visit_base_type(node)
13
+ q.text("(#{node.class.name.downcase})")
14
+ end
15
+
16
+ # Visit a RBS::AST::Declarations::Alias node.
17
+ def visit_alias_declaration(node)
18
+ group("constant") do
19
+ print_comment(node)
20
+ print_annotations(node)
21
+ visit_field("name", node.name)
22
+ visit_field("type", node.type)
23
+ end
24
+ end
25
+
26
+ # Visit a RBS::AST::Members::Alias node.
27
+ def visit_alias_member(node)
28
+ group("alias") do
29
+ print_comment(node)
30
+ print_annotations(node)
31
+ bool_field("singleton") if node.kind == :singleton
32
+ pp_field("new_name", node.new_name)
33
+ pp_field("old_name", node.old_name)
34
+ end
35
+ end
36
+
37
+ # Visit a RBS::Types::Alias node.
38
+ def visit_alias_type(node)
39
+ group("alias") { visit_field("name", node.name) }
40
+ end
41
+
42
+ # Visit a RBS::Types::Bases::Any node.
43
+ alias visit_any_type visit_base_type
44
+
45
+ # Visit a RBS::AST::Members::AttrAccessor node.
46
+ def visit_attr_accessor_member(node)
47
+ group("attr-accessor") do
48
+ print_comment(node)
49
+ print_annotations(node)
50
+ print_attribute(node)
51
+ end
52
+ end
53
+
54
+ # Visit a RBS::AST::Members::AttrReader node.
55
+ def visit_attr_reader_member(node)
56
+ group("attr-reader") do
57
+ print_comment(node)
58
+ print_annotations(node)
59
+ print_attribute(node)
60
+ end
61
+ end
62
+
63
+ # Visit a RBS::AST::Members::AttrWriter node.
64
+ def visit_attr_writer_member(node)
65
+ group("attr-writer") do
66
+ print_comment(node)
67
+ print_annotations(node)
68
+ print_attribute(node)
69
+ end
70
+ end
71
+
72
+ # Visit a RBS::Types::Bases::Bool node.
73
+ alias visit_bool_type visit_base_type
74
+
75
+ # Visit a RBS::Types::Bases::Bottom node.
76
+ alias visit_bottom_type visit_base_type
77
+
78
+ # Visit a RBS::AST::Declarations::Class node.
79
+ def visit_class_declaration(node)
80
+ group("class") do
81
+ print_comment(node)
82
+ print_annotations(node)
83
+ print_name_and_type_params(node)
84
+
85
+ if node.super_class
86
+ q.breakable
87
+ q.text("super_class=")
88
+ print_name_and_args(node.super_class)
89
+ end
90
+
91
+ pp_field("members", node.members)
92
+ end
93
+ end
94
+
95
+ # Visit a RBS::Types::ClassInstance node.
96
+ def visit_class_instance_type(node)
97
+ group("class-instance") { print_name_and_args(node) }
98
+ end
99
+
100
+ # Visit a RBS::AST::Members::ClassInstanceVariable node.
101
+ def visit_class_instance_variable_member(node)
102
+ group("class-instance-variable") do
103
+ print_comment(node)
104
+ pp_field("name", node.name)
105
+ end
106
+ end
107
+
108
+ # Visit a RBS::Types::ClassSingleton node.
109
+ def visit_class_singleton_type(node)
110
+ group("class-singleton") { pp_field("name", node.name) }
111
+ end
112
+
113
+ # Visit a RBS::Types::Bases::Class node.
114
+ alias visit_class_type visit_base_type
115
+
116
+ # Visit a RBS::AST::Members::ClassVariable node.
117
+ def visit_class_variable_member(node)
118
+ group("class-variable") do
119
+ print_comment(node)
120
+ pp_field("name", node.name)
121
+ end
122
+ end
123
+
124
+ # Visit a RBS::AST::Declarations::Constant node.
125
+ def visit_constant_declaration(node)
126
+ group("constant") do
127
+ print_comment(node)
128
+ visit_field("name", node.name)
129
+ visit_field("type", node.type)
130
+ end
131
+ end
132
+
133
+ # Visit a RBS::AST::Members::Extend node.
134
+ def visit_extend_member(node)
135
+ group("extend") do
136
+ print_comment(node)
137
+ print_annotations(node)
138
+ print_name_and_args(node)
139
+ end
140
+ end
141
+
142
+ # Visit a RBS::Types::Function::Param node.
143
+ def visit_function_param_type(node)
144
+ group("param") do
145
+ visit_field("type", node.type)
146
+ pp_field("name", node.name) if node.name
147
+ end
148
+ end
149
+
150
+ # Visit a RBS::AST::Declarations::Global node.
151
+ def visit_global_declaration(node)
152
+ group("global") do
153
+ print_comment(node)
154
+ pp_field("name", node.name)
155
+ visit_field("type", node.type)
156
+ end
157
+ end
158
+
159
+ # Visit a RBS::AST::Members::Include node.
160
+ def visit_include_member(node)
161
+ group("include") do
162
+ print_comment(node)
163
+ print_annotations(node)
164
+ print_name_and_args(node)
165
+ end
166
+ end
167
+
168
+ # Visit a RBS::Types::Bases::Instance node.
169
+ alias visit_instance_type visit_base_type
170
+
171
+ # Visit a RBS::AST::Members::InstanceVariable node.
172
+ def visit_instance_variable_member(node)
173
+ group("instance-variable") do
174
+ print_comment(node)
175
+ pp_field("name", node.name)
176
+ end
177
+ end
178
+
179
+ # Visit a RBS::AST::Declarations::Interface node.
180
+ def visit_interface_declaration(node)
181
+ group("interface") do
182
+ print_comment(node)
183
+ print_annotations(node)
184
+ print_name_and_type_params(node)
185
+ pp_field("members", node.members)
186
+ end
187
+ end
188
+
189
+ # Visit a RBS::Types::Interface node.
190
+ def visit_interface_type(node)
191
+ group("interface") { print_name_and_args(node) }
192
+ end
193
+
194
+ # Visit a RBS::Types::Intersection node.
195
+ def visit_intersection_type(node)
196
+ group("intersection") { pp_field("types", node.types) }
197
+ end
198
+
199
+ # Visit a RBS::Types::Literal node.
200
+ def visit_literal_type(node)
201
+ group("literal") { pp_field("literal", node.literal) }
202
+ end
203
+
204
+ # Visit a RBS::AST::Members::MethodDefinition node.
205
+ def visit_method_definition_member(node)
206
+ group("(method-definition") do
207
+ print_comment(node)
208
+ print_annotations(node)
209
+ pp_field("kind", node.kind)
210
+ pp_field("name", node.name)
211
+ pp_field("visibility", node.visibility) if node.visibility
212
+ bool_field("overload") if node.overload?
213
+
214
+ q.breakable
215
+ q.text("types=")
216
+ q.group(2, "[", "]") do
217
+ q.seplist(node.types) { |type| print_method_signature(type) }
218
+ end
219
+ end
220
+ end
221
+
222
+ # Visit a RBS::AST::Declarations::Module node.
223
+ def visit_module_declaration(node)
224
+ group("module") do
225
+ print_comment(node)
226
+ print_annotations(node)
227
+ print_name_and_type_params(node)
228
+
229
+ if node.self_types.any?
230
+ q.breakable
231
+ q.text("self_types=")
232
+ q.group(2, "[", "]") do
233
+ q.seplist(node.self_types) do |self_type|
234
+ print_name_and_args(self_type)
235
+ end
236
+ end
237
+ end
238
+
239
+ pp_field("members", node.members)
240
+ end
241
+ end
242
+
243
+ # Visit a RBS::Types::Bases::Nil node.
244
+ alias visit_nil_type visit_base_type
245
+
246
+ # Visit a RBS::Types::Optional node.
247
+ def visit_optional_type(node)
248
+ group("optional") { visit_field("type", node.type) }
249
+ end
250
+
251
+ # Visit a RBS::AST::Members::Prepend node.
252
+ def visit_prepend_member(node)
253
+ group("prepend") do
254
+ print_comment(node)
255
+ print_annotations(node)
256
+ print_name_and_args(node)
257
+ end
258
+ end
259
+
260
+ # Visit a RBS::AST::Members::Private node.
261
+ def visit_private_member(node)
262
+ q.text("(private)")
263
+ end
264
+
265
+ # Visit a RBS::Types::Proc node.
266
+ def visit_proc_type(node)
267
+ group("proc") { print_method_signature(node) }
268
+ end
269
+
270
+ # Visit a RBS::AST::Members::Public node.
271
+ def visit_public_member(node)
272
+ q.text("(public)")
273
+ end
274
+
275
+ # Visit a RBS::Types::Record node.
276
+ def visit_record_type(node)
277
+ group("record") { pp_field("fields", node.fields) }
278
+ end
279
+
280
+ # Visit a SyntaxTree::RBS::Root node.
281
+ def visit_root(node)
282
+ group("root") { pp_field("declarations", node.declarations) }
283
+ end
284
+
285
+ # Visit a RBS::Types::Self node.
286
+ alias visit_self_type visit_base_type
287
+
288
+ # Visit a RBS::Types::Top node.
289
+ alias visit_top_type visit_base_type
290
+
291
+ # Visit a RBS::Types::Tuple node.
292
+ def visit_tuple_type(node)
293
+ group("tuple") { pp_field("types", node.types) }
294
+ end
295
+
296
+ # Visit a RBS::TypeName node.
297
+ def visit_type_name(node)
298
+ group("type-name") do
299
+ q.breakable
300
+ q.pp(node.to_s)
301
+ end
302
+ end
303
+
304
+ # Visit a RBS::Types::Union node.
305
+ def visit_union_type(node)
306
+ group("union") { pp_field("types", node.types) }
307
+ end
308
+
309
+ # Visit a RBS::Types::Variable node.
310
+ def visit_variable_type(node)
311
+ group("variable") { pp_field("name", node.name) }
312
+ end
313
+
314
+ # Visit a RBS::Types::Bases::Void node.
315
+ alias visit_void_type visit_base_type
316
+
317
+ private
318
+
319
+ #-------------------------------------------------------------------------
320
+ # Printing structure
321
+ #-------------------------------------------------------------------------
322
+
323
+ def group(name)
324
+ q.group do
325
+ q.text("(")
326
+ q.text(name)
327
+ q.nest(2) { yield }
328
+ q.breakable("")
329
+ q.text(")")
330
+ end
331
+ end
332
+
333
+ def bool_field(name)
334
+ q.breakable
335
+ q.text(name)
336
+ end
337
+
338
+ def pp_field(name, field)
339
+ q.breakable
340
+ q.text("#{name}=")
341
+ q.pp(field)
342
+ end
343
+
344
+ def visit_field(name, field)
345
+ q.breakable
346
+ q.text("#{name}=")
347
+ visit(field)
348
+ end
349
+
350
+ #-------------------------------------------------------------------------
351
+ # Printing certain kinds of nodes
352
+ #-------------------------------------------------------------------------
353
+
354
+ def print_annotations(node)
355
+ annotations = node.annotations
356
+ return if annotations.empty?
357
+
358
+ q.breakable
359
+ q.text("annotations=")
360
+ q.seplist(annotations) do |annotation|
361
+ q.group(2, "(annotation", ")") do
362
+ q.breakable
363
+ q.pp(annotation.string)
364
+ end
365
+ end
366
+ end
367
+
368
+ def print_attribute(node)
369
+ if node.kind == :singleton
370
+ q.breakable
371
+ q.text("singleton")
372
+ end
373
+
374
+ q.breakable
375
+ q.text("name=")
376
+ q.pp(node.name)
377
+
378
+ if node.visibility
379
+ q.breakable
380
+ q.text("visibility=")
381
+ q.pp(node.visibility)
382
+ end
383
+
384
+ unless node.ivar_name.nil?
385
+ q.breakable
386
+ q.text("ivar_name=")
387
+ q.pp(node.ivar_name)
388
+ end
389
+
390
+ q.breakable
391
+ q.text("type=")
392
+ q.pp(node.type)
393
+ end
394
+
395
+ def print_comment(node)
396
+ comment = node.comment
397
+ return unless comment
398
+
399
+ q.breakable
400
+ q.text("comment=")
401
+ q.group(2, "(comment", ")") do
402
+ q.breakable
403
+ q.pp(comment.string)
404
+ end
405
+ end
406
+
407
+ def print_method_signature(node)
408
+ if node.respond_to?(:type_params) && node.type_params.any?
409
+ q.breakable
410
+ q.text("type_params=")
411
+ q.group(2, "[", "]") do
412
+ q.breakable("")
413
+ q.seplist(node.type_params) do |param|
414
+ q.group(2, "(type-param", ")") do
415
+ q.breakable
416
+ q.text("name=")
417
+ q.pp(param.name)
418
+ end
419
+ end
420
+ q.breakable("")
421
+ end
422
+ end
423
+
424
+ if node.type.required_positionals.any?
425
+ q.breakable
426
+ q.text("required_positionals=")
427
+ q.pp(node.type.required_positionals)
428
+ end
429
+
430
+ if node.type.optional_positionals.any?
431
+ q.breakable
432
+ q.text("optional_positionals=")
433
+ q.pp(node.type.optional_positionals)
434
+ end
435
+
436
+ if node.type.rest_positionals
437
+ q.breakable
438
+ q.text("rest_positionals=")
439
+ q.pp(node.type.rest_positionals)
440
+ end
441
+
442
+ if node.type.trailing_positionals.any?
443
+ q.breakable
444
+ q.text("trailing_positionals=")
445
+ q.pp(node.type.trailing_positionals)
446
+ end
447
+
448
+ if node.type.required_keywords.any?
449
+ q.breakable
450
+ q.text("required_keywords=")
451
+ q.pp(node.type.required_keywords)
452
+ end
453
+
454
+ if node.type.optional_keywords.any?
455
+ q.breakable
456
+ q.text("optional_keywords=")
457
+ q.pp(node.type.optional_keywords)
458
+ end
459
+
460
+ if node.type.rest_keywords
461
+ q.breakable
462
+ q.text("rest_keywords=")
463
+ q.pp(node.type.rest_keywords)
464
+ end
465
+
466
+ if node.respond_to?(:block) && node.block
467
+ q.breakable
468
+ q.text("block=")
469
+ q.group(2, "(block", ")") do
470
+ if node.block.required
471
+ q.breakable
472
+ q.text("required")
473
+ end
474
+
475
+ q.breakable
476
+ print_method_signature(node.block)
477
+ end
478
+ end
479
+
480
+ q.breakable
481
+ q.text("return_type=")
482
+ q.pp(node.type.return_type)
483
+ end
484
+
485
+ def print_name_and_args(node)
486
+ q.breakable
487
+ q.pp(node.name)
488
+
489
+ if node.args.any?
490
+ q.breakable
491
+ q.pp(node.args)
492
+ end
493
+ end
494
+
495
+ def print_name_and_type_params(node)
496
+ q.breakable
497
+ q.pp(node.name)
498
+
499
+ if node.type_params.any?
500
+ q.breakable
501
+ q.group(2, "type_params=[", "]") do
502
+ q.seplist(node.type_params) do |param|
503
+ q.group(2, "(type-param", ")") do
504
+ if param.unchecked?
505
+ q.breakable
506
+ q.text("unchecked")
507
+ end
508
+
509
+ if param.variance == :covariant
510
+ q.breakable
511
+ q.text("covariant")
512
+ elsif param.variance == :contravariant
513
+ q.breakable
514
+ q.text("contravariant")
515
+ end
516
+
517
+ q.breakable
518
+ q.text("name=")
519
+ q.pp(param.name)
520
+
521
+ if param.upper_bound
522
+ q.breakable
523
+ q.text("upper_bound=")
524
+ q.pp(param.upper_bound)
525
+ end
526
+ end
527
+ end
528
+ end
529
+ end
530
+ end
531
+ end
532
+ end
533
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SyntaxTree
4
4
  module RBS
5
- VERSION = "0.2.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
@@ -1,22 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "prettier_print"
3
4
  require "rbs"
4
5
  require "syntax_tree"
5
6
 
6
- require_relative "rbs/declarations"
7
- require_relative "rbs/members"
8
7
  require_relative "rbs/shims"
9
- require_relative "rbs/types"
10
- require_relative "rbs/utils"
11
8
  require_relative "rbs/version"
12
9
 
13
10
  module SyntaxTree
14
11
  module RBS
15
- # A slight extension to the default PP formatter that keeps track of the
16
- # source (so that it can be referenced by annotations if they need it) and
17
- # keeps track of the level of intersections and unions so that parentheses
18
- # can be forced if necessary.
19
- class Formatter < PP
12
+ # This is the parent class of any of the visitors that we define in this
13
+ # module. It is used to walk through the tree.
14
+ class Visitor
15
+ def visit(node)
16
+ node&.accept(self)
17
+ end
18
+ end
19
+
20
+ # A slight extension to the default PrettierPrint formatter that keeps track
21
+ # of the source (so that it can be referenced by annotations if they need
22
+ # it) and keeps track of the level of intersections and unions so that
23
+ # parentheses can be forced if necessary.
24
+ class Formatter < PrettierPrint
20
25
  attr_reader :source
21
26
 
22
27
  def initialize(source, ...)
@@ -38,38 +43,9 @@ module SyntaxTree
38
43
  end
39
44
  end
40
45
 
41
- # This is the root node of the entire tree. It contains all of the top-level
42
- # declarations within the file.
43
- class Root
44
- attr_reader :declarations
45
-
46
- def initialize(declarations)
47
- @declarations = declarations
48
- end
49
-
50
- def format(q)
51
- separator =
52
- lambda do
53
- q.breakable(force: true)
54
- q.breakable(force: true)
55
- end
56
-
57
- q.seplist(declarations, separator) { |declaration| declaration.format(q) }
58
- q.breakable(force: true)
59
- end
60
-
61
- def pretty_print(q)
62
- q.group(2, "(root", ")") do
63
- q.breakable
64
- q.text("declarations=")
65
- q.pp(declarations)
66
- end
67
- end
68
- end
69
-
70
46
  class << self
71
- def format(source)
72
- formatter = Formatter.new(source, [])
47
+ def format(source, maxwidth = 80)
48
+ formatter = Formatter.new(source, [], maxwidth)
73
49
  parse(source).format(formatter)
74
50
 
75
51
  formatter.flush
@@ -88,3 +64,7 @@ module SyntaxTree
88
64
 
89
65
  register_handler(".rbs", RBS)
90
66
  end
67
+
68
+ require_relative "rbs/entrypoints"
69
+ require_relative "rbs/format"
70
+ require_relative "rbs/pretty_print"
@@ -3,26 +3,27 @@
3
3
  require_relative "lib/syntax_tree/rbs/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "syntax_tree-rbs"
7
- spec.version = SyntaxTree::RBS::VERSION
8
- spec.authors = ["Kevin Newton"]
9
- spec.email = ["kddnewton@gmail.com"]
6
+ spec.name = "syntax_tree-rbs"
7
+ spec.version = SyntaxTree::RBS::VERSION
8
+ spec.authors = ["Kevin Newton"]
9
+ spec.email = ["kddnewton@gmail.com"]
10
10
 
11
- spec.summary = "Syntax Tree support for RBS"
12
- spec.homepage = "https://github.com/ruby-syntax-tree/syntax_tree-rbs"
13
- spec.license = "MIT"
14
- spec.metadata = { "rubygems_mfa_required" => "true" }
11
+ spec.summary = "Syntax Tree support for RBS"
12
+ spec.homepage = "https://github.com/ruby-syntax-tree/syntax_tree-rbs"
13
+ spec.license = "MIT"
14
+ spec.metadata = { "rubygems_mfa_required" => "true" }
15
15
 
16
- spec.files = Dir.chdir(__dir__) do
17
- `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features)/})
16
+ spec.files =
17
+ Dir.chdir(__dir__) do
18
+ `git ls-files -z`.split("\x0")
19
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
19
20
  end
20
- end
21
21
 
22
- spec.bindir = "exe"
23
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = %w[lib]
25
25
 
26
+ spec.add_dependency "prettier_print"
26
27
  spec.add_dependency "rbs"
27
28
  spec.add_dependency "syntax_tree", ">= 2.0.1"
28
29