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.
@@ -1,293 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RBS
4
- class TypeName
5
- def format(q)
6
- q.text(to_s)
7
- end
8
-
9
- def pretty_print(q)
10
- q.group(2, "(type-name", ")") do
11
- q.breakable
12
- q.pp(to_s)
13
- end
14
- end
15
- end
16
-
17
- module Types
18
- class Alias
19
- def format(q)
20
- name.format(q)
21
- end
22
-
23
- def pretty_print(q)
24
- q.group(2, "(alias", ")") do
25
- q.breakable
26
- q.text("name=")
27
- q.pp(name)
28
- end
29
- end
30
- end
31
-
32
- module Bases
33
- class Base
34
- def format(q)
35
- q.text(to_s)
36
- end
37
-
38
- def pretty_print(q)
39
- q.text("(#{self.class.name.downcase})")
40
- end
41
- end
42
- end
43
-
44
- class ClassInstance
45
- def format(q)
46
- SyntaxTree::RBS::NameAndArgs.new(self).format(q)
47
- end
48
-
49
- def pretty_print(q)
50
- q.group(2, "(class-instance", ")") do
51
- q.pp(SyntaxTree::RBS::NameAndArgs.new(self))
52
- end
53
- end
54
- end
55
-
56
- class ClassSingleton
57
- def format(q)
58
- q.text("singleton(")
59
- name.format(q)
60
- q.text(")")
61
- end
62
-
63
- def pretty_print(q)
64
- q.group(2, "(class-singleton", ")") do
65
- q.breakable
66
- q.text("name=")
67
- q.pp(name)
68
- end
69
- end
70
- end
71
-
72
- class Function
73
- class Param
74
- def format(q)
75
- type.format(q)
76
-
77
- if name
78
- q.text(" ")
79
-
80
- if Parser::KEYWORDS.include?(name.to_s)
81
- q.text("`#{name}`")
82
- else
83
- q.text(name)
84
- end
85
- end
86
- end
87
-
88
- def pretty_print(q)
89
- q.group(2, "(param", ")") do
90
- q.breakable
91
- q.text("type=")
92
- q.pp(type)
93
-
94
- if name
95
- q.breakable
96
- q.text("name=")
97
- q.pp(name)
98
- end
99
- end
100
- end
101
- end
102
- end
103
-
104
- class Interface
105
- def format(q)
106
- SyntaxTree::RBS::NameAndArgs.new(self).format(q)
107
- end
108
-
109
- def pretty_print(q)
110
- q.group(2, "(interface", ")") do
111
- q.pp(SyntaxTree::RBS::NameAndArgs.new(self))
112
- end
113
- end
114
- end
115
-
116
- class Intersection
117
- def format(q)
118
- separator =
119
- lambda do
120
- q.breakable
121
- q.text("& ")
122
- end
123
-
124
- q.text("(") if q.force_parens?
125
- q.group do
126
- q.force_parens { q.seplist(types, separator) { |type| type.format(q) } }
127
- end
128
- q.text(")") if q.force_parens?
129
- end
130
-
131
- def pretty_print(q)
132
- q.group(2, "(intersection", ")") do
133
- q.breakable
134
- q.text("types=")
135
- q.pp(types)
136
- end
137
- end
138
- end
139
-
140
- class Literal
141
- def format(q)
142
- unless literal.is_a?(String)
143
- q.text(literal.inspect)
144
- return
145
- end
146
-
147
- # We're going to go straight to the source here, as if we don't then
148
- # we're going to end up with the result of String#inspect, which does
149
- # weird things to escape sequences.
150
- source = q.source[location.range]
151
- quote = source.include?("\\") ? source[0] : "\""
152
- source = SyntaxTree::Quotes.normalize(source[1..-2], quote)
153
-
154
- q.text(quote)
155
- q.seplist(source.split(/\r?\n/), -> { q.breakable(force: true) }) do |line|
156
- q.text(line)
157
- end
158
- q.text(quote)
159
- end
160
-
161
- def pretty_print(q)
162
- q.group(2, "(literal", ")") do
163
- q.breakable
164
- q.pp(literal)
165
- end
166
- end
167
- end
168
-
169
- class Optional
170
- def format(q)
171
- q.force_parens { type.format(q) }
172
- q.text("?")
173
- end
174
-
175
- def pretty_print(q)
176
- q.group(2, "(optional", ")") do
177
- q.breakable
178
- q.pp(type)
179
- end
180
- end
181
- end
182
-
183
- class Proc
184
- def format(q)
185
- q.text("^")
186
- SyntaxTree::RBS::MethodSignature.new(self).format(q)
187
- end
188
-
189
- def pretty_print(q)
190
- q.group(2, "(proc", ")") do
191
- q.pp(SyntaxTree::RBS::MethodSignature.new(self))
192
- end
193
- end
194
- end
195
-
196
- class Record
197
- def format(q)
198
- separator =
199
- lambda do
200
- q.text(",")
201
- q.breakable
202
- end
203
-
204
- q.group do
205
- q.text("{")
206
- q.indent do
207
- q.breakable
208
- q.seplist(fields, separator, :each_pair) do |key, type|
209
- if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_]*\z/)
210
- q.text("#{key}: ")
211
- else
212
- q.text("#{key.inspect} => ")
213
- end
214
-
215
- type.format(q)
216
- end
217
- end
218
- q.breakable
219
- q.text("}")
220
- end
221
- end
222
-
223
- def pretty_print(q)
224
- q.group(2, "(record", ")") do
225
- q.breakable
226
- q.text("fields=")
227
- q.pp(fields)
228
- end
229
- end
230
- end
231
-
232
- class Tuple
233
- def format(q)
234
- # If we don't have any sub types, we explicitly need the space in
235
- # between the brackets to not confuse the parser.
236
- if types.empty?
237
- q.text("[ ]")
238
- return
239
- end
240
-
241
- q.group do
242
- q.text("[")
243
- q.seplist(types, -> { q.text(", ") }) { |type| type.format(q) }
244
- q.text("]")
245
- end
246
- end
247
-
248
- def pretty_print(q)
249
- q.group(2, "(tuple", ")") do
250
- q.breakable
251
- q.text("types=")
252
- q.pp(types)
253
- end
254
- end
255
- end
256
-
257
- class Union
258
- def format(q)
259
- separator =
260
- lambda do
261
- q.breakable
262
- q.text("| ")
263
- end
264
-
265
- q.text("(") if q.force_parens?
266
- q.group { q.seplist(types, separator) { |type| type.format(q) } }
267
- q.text(")") if q.force_parens?
268
- end
269
-
270
- def pretty_print(q)
271
- q.group(2, "(union", ")") do
272
- q.breakable
273
- q.text("types=")
274
- q.pp(types)
275
- end
276
- end
277
- end
278
-
279
- class Variable
280
- def format(q)
281
- q.text(name)
282
- end
283
-
284
- def pretty_print(q)
285
- q.group(2, "(variable", ")") do
286
- q.breakable
287
- q.text("name=")
288
- q.pp(name)
289
- end
290
- end
291
- end
292
- end
293
- end
@@ -1,432 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SyntaxTree
4
- module RBS
5
- # An annotation can be attached to many kinds of nodes, and should be
6
- # printed using %a{}. This class wraps a set of annotations and provides the
7
- # ability to print them if they are found.
8
- class Annotations
9
- attr_reader :annotations
10
-
11
- def initialize(annotations)
12
- @annotations = annotations
13
- end
14
-
15
- def format(q)
16
- q.seplist(annotations, -> { q.breakable(force: true) }) do |annotation|
17
- if annotation.string.match?(/[{}]/)
18
- # Bail out and just print the source string if there are any braces
19
- # because we don't want to mess with escaping them.
20
- q.text(q.source[annotation.location.range])
21
- else
22
- q.text("%a{")
23
- q.text(annotation.string)
24
- q.text("}")
25
- end
26
- end
27
- q.breakable(force: true)
28
- end
29
-
30
- def pretty_print(q)
31
- q.seplist(annotations) do |annotation|
32
- q.group(2, "(annotation", ")") do
33
- q.breakable
34
- q.pp(annotation.string)
35
- end
36
- end
37
- end
38
-
39
- def self.maybe_format(q, annotations)
40
- new(annotations).format(q) if annotations.any?
41
- end
42
-
43
- def self.maybe_pretty_print(q, annotations)
44
- if annotations.any?
45
- q.breakable
46
- q.text("annotations=")
47
- q.pp(new(annotations))
48
- end
49
- end
50
- end
51
-
52
- # A comment can be attached to many kinds of nodes, and should be printed
53
- # before them. This class wraps a comment and provides the ability to print
54
- # it if it is found.
55
- class Comment
56
- attr_reader :comment
57
-
58
- def initialize(comment)
59
- @comment = comment
60
- end
61
-
62
- # Comments come in as one whole string, so here we split it up into
63
- # multiple lines and then prefix it with the pound sign.
64
- def format(q)
65
- q.seplist(comment.string.split(/\r?\n/), -> { q.breakable(force: true) }) do |line|
66
- q.text("# #{line}")
67
- end
68
- q.breakable(force: true)
69
- end
70
-
71
- def pretty_print(q)
72
- q.group(2, "(comment", ")") do
73
- q.breakable
74
- q.pp(comment.string)
75
- end
76
- end
77
-
78
- def self.maybe_format(q, comment)
79
- new(comment).format(q) if comment
80
- end
81
-
82
- def self.maybe_pretty_print(q, comment)
83
- if comment
84
- q.breakable
85
- q.text("comment=")
86
- q.pp(new(comment))
87
- end
88
- end
89
- end
90
-
91
- # Certain nodes are names with optional arguments attached, as in Array[A].
92
- # We handle all of that printing centralized here.
93
- class NameAndArgs
94
- attr_reader :node
95
-
96
- def initialize(node)
97
- @node = node
98
- end
99
-
100
- def format(q)
101
- q.group do
102
- node.name.format(q)
103
-
104
- if node.args.any?
105
- q.text("[")
106
- q.seplist(node.args, -> { q.text(", ") }) { |arg| arg.format(q) }
107
- q.text("]")
108
- end
109
- end
110
- end
111
-
112
- def pretty_print(q)
113
- q.breakable
114
- q.pp(node.name)
115
-
116
- if node.args.any?
117
- q.breakable
118
- q.pp(node.args)
119
- end
120
- end
121
- end
122
-
123
- # Prints out the name of a class, interface, or module declaration.
124
- # Additionally loops through each type parameter if there are any and print
125
- # them out joined by commas. Checks for validation and variance.
126
- class NameAndTypeParams
127
- attr_reader :node
128
-
129
- def initialize(node)
130
- @node = node
131
- end
132
-
133
- def format(q)
134
- node.name.format(q)
135
- return if node.type_params.empty?
136
-
137
- q.text("[")
138
- q.seplist(node.type_params, -> { q.text(", ") }) do |param|
139
- parts = []
140
-
141
- if param.unchecked?
142
- parts << "unchecked"
143
- end
144
-
145
- if param.variance == :covariant
146
- parts << "out"
147
- elsif param.variance == :contravariant
148
- parts << "in"
149
- end
150
-
151
- parts << param.name
152
- q.text(parts.join(" "))
153
-
154
- if param.upper_bound
155
- q.text(" < ")
156
- param.upper_bound.format(q)
157
- end
158
- end
159
-
160
- q.text("]")
161
- end
162
-
163
- def pretty_print(q)
164
- q.breakable
165
- q.pp(node.name)
166
-
167
- if node.type_params.any?
168
- q.breakable
169
- q.group(2, "type_params=[", "]") do
170
- q.seplist(node.type_params) do |param|
171
- q.group(2, "(type-param", ")") do
172
- if param.unchecked?
173
- q.breakable
174
- q.text("unchecked")
175
- end
176
-
177
- if param.variance == :covariant
178
- q.breakable
179
- q.text("covariant")
180
- elsif param.variance == :contravariant
181
- q.breakable
182
- q.text("contravariant")
183
- end
184
-
185
- q.breakable
186
- q.text("name=")
187
- q.pp(param.name)
188
-
189
- if param.upper_bound
190
- q.breakable
191
- q.text("upper_bound=")
192
- q.pp(param.upper_bound)
193
- end
194
- end
195
- end
196
- end
197
- end
198
- end
199
- end
200
-
201
- # Nodes which have members will all flow their printing through this class,
202
- # which keeps track of
203
- class Members
204
- attr_reader :node
205
-
206
- def initialize(node)
207
- @node = node
208
- end
209
-
210
- def format(q)
211
- last_line = nil
212
-
213
- node.members.each do |member|
214
- q.breakable(force: true)
215
-
216
- if last_line && (member.location.start_line - last_line >= 2)
217
- q.breakable(force: true)
218
- end
219
-
220
- member.format(q)
221
- last_line = member.location.end_line
222
- end
223
- end
224
- end
225
-
226
- # Prints out a specific method signature, which looks like:
227
- # (T t) -> void
228
- class MethodSignature
229
- class OptionalPositional
230
- attr_reader :param
231
-
232
- def initialize(param)
233
- @param = param
234
- end
235
-
236
- def format(q)
237
- q.text("?")
238
- param.format(q)
239
- end
240
- end
241
-
242
- class RestPositional
243
- attr_reader :param
244
-
245
- def initialize(param)
246
- @param = param
247
- end
248
-
249
- def format(q)
250
- q.text("*")
251
- param.format(q)
252
- end
253
- end
254
-
255
- class RequiredKeyword
256
- attr_reader :name, :param
257
-
258
- def initialize(name, param)
259
- @name = name
260
- @param = param
261
- end
262
-
263
- def format(q)
264
- q.text(name)
265
- q.text(": ")
266
- param.format(q)
267
- end
268
- end
269
-
270
- class OptionalKeyword
271
- attr_reader :name, :param
272
-
273
- def initialize(name, param)
274
- @name = name
275
- @param = param
276
- end
277
-
278
- def format(q)
279
- q.text("?")
280
- q.text(name)
281
- q.text(": ")
282
- param.format(q)
283
- end
284
- end
285
-
286
- class RestKeyword
287
- attr_reader :param
288
-
289
- def initialize(param)
290
- @param = param
291
- end
292
-
293
- def format(q)
294
- q.text("**")
295
- param.format(q)
296
- end
297
- end
298
-
299
- attr_reader :node
300
-
301
- def initialize(node)
302
- @node = node
303
- end
304
-
305
- def format(q)
306
- q.group do
307
- # We won't have a type_params key if we're printing a block
308
- if node.respond_to?(:type_params) && node.type_params.any?
309
- q.text("[")
310
- q.seplist(node.type_params, -> { q.text(", ") }) do |param|
311
- # We need to do a type check here to support RBS 1.0
312
- q.text(param.is_a?(Symbol) ? param.to_s : param.name)
313
- end
314
- q.text("] ")
315
- end
316
-
317
- params = [
318
- *node.type.required_positionals,
319
- *node.type.optional_positionals.map { |param| OptionalPositional.new(param) },
320
- *(RestPositional.new(node.type.rest_positionals) if node.type.rest_positionals),
321
- *node.type.trailing_positionals,
322
- *node.type.required_keywords.map { |name, param| RequiredKeyword.new(name, param) },
323
- *node.type.optional_keywords.map { |name, param| OptionalKeyword.new(name, param) },
324
- *(RestKeyword.new(node.type.rest_keywords) if node.type.rest_keywords)
325
- ]
326
-
327
- if params.any?
328
- q.text("(")
329
- q.indent do
330
- q.breakable("")
331
- q.seplist(params) { |param| param.format(q) }
332
- end
333
- q.breakable("")
334
- q.text(") ")
335
- end
336
-
337
- if node.respond_to?(:block) && node.block
338
- q.text("?") unless node.block.required
339
- q.text("{")
340
- q.indent do
341
- q.breakable
342
- MethodSignature.new(node.block).format(q)
343
- end
344
- q.breakable
345
- q.text("} ")
346
- end
347
-
348
- q.text("-> ")
349
- q.force_parens { node.type.return_type.format(q) }
350
- end
351
- end
352
-
353
- def pretty_print(q)
354
- if node.respond_to?(:type_params) && node.type_params.any?
355
- q.breakable
356
- q.text("type_params=")
357
- q.group(2, "[", "]") do
358
- q.breakable("")
359
- q.seplist(node.type_params) do |param|
360
- q.group(2, "(type-param", ")") do
361
- q.breakable
362
- q.text("name=")
363
- q.pp(param.name)
364
- end
365
- end
366
- q.breakable("")
367
- end
368
- end
369
-
370
- if node.type.required_positionals.any?
371
- q.breakable
372
- q.text("required_positionals=")
373
- q.pp(node.type.required_positionals)
374
- end
375
-
376
- if node.type.optional_positionals.any?
377
- q.breakable
378
- q.text("optional_positionals=")
379
- q.pp(node.type.optional_positionals)
380
- end
381
-
382
- if node.type.rest_positionals
383
- q.breakable
384
- q.text("rest_positionals=")
385
- q.pp(node.type.rest_positionals)
386
- end
387
-
388
- if node.type.trailing_positionals.any?
389
- q.breakable
390
- q.text("trailing_positionals=")
391
- q.pp(node.type.trailing_positionals)
392
- end
393
-
394
- if node.type.required_keywords.any?
395
- q.breakable
396
- q.text("required_keywords=")
397
- q.pp(node.type.required_keywords)
398
- end
399
-
400
- if node.type.optional_keywords.any?
401
- q.breakable
402
- q.text("optional_keywords=")
403
- q.pp(node.type.optional_keywords)
404
- end
405
-
406
- if node.type.rest_keywords
407
- q.breakable
408
- q.text("rest_keywords=")
409
- q.pp(node.type.rest_keywords)
410
- end
411
-
412
- if node.respond_to?(:block) && node.block
413
- q.breakable
414
- q.text("block=")
415
- q.group(2, "(block", ")") do
416
- if node.block.required
417
- q.breakable
418
- q.text("required")
419
- end
420
-
421
- q.breakable
422
- q.pp(MethodSignature.new(node.block))
423
- end
424
- end
425
-
426
- q.breakable
427
- q.text("return_type=")
428
- q.pp(node.type.return_type)
429
- end
430
- end
431
- end
432
- end