rbs-inline 0.4.0 → 0.6.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.
- checksums.yaml +4 -4
- data/README.md +8 -5
- data/Rakefile +12 -0
- data/lib/rbs/inline/annotation_parser/tokenizer.rb +361 -0
- data/lib/rbs/inline/annotation_parser.rb +548 -326
- data/lib/rbs/inline/ast/annotations.rb +433 -138
- data/lib/rbs/inline/ast/comment_lines.rb +17 -20
- data/lib/rbs/inline/ast/declarations.rb +301 -28
- data/lib/rbs/inline/ast/members.rb +130 -121
- data/lib/rbs/inline/ast/tree.rb +37 -22
- data/lib/rbs/inline/cli.rb +12 -12
- data/lib/rbs/inline/node_utils.rb +1 -1
- data/lib/rbs/inline/parser.rb +165 -67
- data/lib/rbs/inline/version.rb +1 -1
- data/lib/rbs/inline/writer.rb +395 -118
- data/lib/rbs/inline.rb +1 -0
- data/rbs_collection.lock.yaml +2 -2
- data/sig/generated/rbs/inline/annotation_parser/tokenizer.rbs +221 -0
- data/sig/generated/rbs/inline/annotation_parser.rbs +148 -92
- data/sig/generated/rbs/inline/ast/annotations.rbs +143 -37
- data/sig/generated/rbs/inline/ast/comment_lines.rbs +8 -4
- data/sig/generated/rbs/inline/ast/declarations.rbs +133 -10
- data/sig/generated/rbs/inline/ast/members.rbs +26 -15
- data/sig/generated/rbs/inline/ast/tree.rbs +23 -17
- data/sig/generated/rbs/inline/cli.rbs +3 -3
- data/sig/generated/rbs/inline/node_utils.rbs +1 -1
- data/sig/generated/rbs/inline/parser.rbs +35 -18
- data/sig/generated/rbs/inline/writer.rbs +62 -22
- metadata +5 -3
@@ -3,7 +3,7 @@
|
|
3
3
|
module RBS
|
4
4
|
module Inline
|
5
5
|
module AST
|
6
|
-
# CommentLines represents consecutive comments
|
6
|
+
# CommentLines represents consecutive comments, providing a mapping from locations in `#string` to a pair of a comment and its offset
|
7
7
|
#
|
8
8
|
# The comments construct one String.
|
9
9
|
#
|
@@ -16,37 +16,34 @@ module RBS
|
|
16
16
|
# And want to translate a location in the string into the location in comment1 and comment2.
|
17
17
|
#
|
18
18
|
class CommentLines
|
19
|
-
attr_reader :comments
|
19
|
+
attr_reader :comments #: Array[Prism::Comment]
|
20
20
|
|
21
21
|
# @rbs comments: Array[Prism::Comment]
|
22
|
-
def initialize(comments)
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
first_offset = offsets[0]
|
27
|
-
|
28
|
-
@comments = comments.map.with_index do |comment, index|
|
29
|
-
offset = offsets[index]
|
30
|
-
offset = first_offset if offset > first_offset
|
22
|
+
def initialize(comments) #: void
|
23
|
+
@comments = comments
|
24
|
+
end
|
31
25
|
|
32
|
-
|
33
|
-
|
26
|
+
def lines #: Array[String]
|
27
|
+
comments.map {|comment| comment.location.slice }
|
34
28
|
end
|
35
29
|
|
36
|
-
def string
|
37
|
-
comments.map {|comment
|
30
|
+
def string #: String
|
31
|
+
comments.map {|comment| comment.location.slice[1..] || "" }.join("\n")
|
38
32
|
end
|
39
33
|
|
34
|
+
# Translates the cursor index of `#string` into the cursor index of a specific comment object
|
35
|
+
#
|
40
36
|
# @rbs index: Integer
|
41
|
-
# @rbs
|
37
|
+
# @rbs return: [Prism::Comment, Integer]?
|
42
38
|
def comment_location(index)
|
43
|
-
comments.each do |comment
|
39
|
+
comments.each do |comment|
|
44
40
|
comment_length = comment.location.length
|
45
41
|
|
46
|
-
if index +
|
47
|
-
return [comment, index +
|
42
|
+
if index + 1 <= comment_length
|
43
|
+
return [comment, index + 1]
|
48
44
|
else
|
49
|
-
index
|
45
|
+
index -= comment_length - 1
|
46
|
+
index -= 1 # newline
|
50
47
|
return if index < 0
|
51
48
|
end
|
52
49
|
end
|
@@ -6,28 +6,40 @@ module RBS
|
|
6
6
|
module Declarations
|
7
7
|
module ConstantUtil
|
8
8
|
# @rbs node: Prism::Node
|
9
|
-
# @rbs
|
9
|
+
# @rbs return: TypeName?
|
10
10
|
def type_name(node)
|
11
11
|
case node
|
12
12
|
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
13
13
|
TypeName(node.full_name)
|
14
14
|
end
|
15
15
|
end
|
16
|
-
end
|
17
16
|
|
18
|
-
|
17
|
+
# @rbs (Prism::Node) -> Prism::Node?
|
18
|
+
def value_node(node)
|
19
|
+
case node
|
20
|
+
when Prism::ConstantWriteNode
|
21
|
+
value_node(node.value)
|
22
|
+
when Prism::LocalVariableWriteNode
|
23
|
+
value_node(node.value)
|
24
|
+
else
|
25
|
+
node
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
19
29
|
|
20
30
|
# @rbs!
|
31
|
+
# type t = ClassDecl | ModuleDecl | ConstantDecl | SingletonClassDecl | BlockDecl | DataAssignDecl | StructAssignDecl
|
32
|
+
#
|
21
33
|
# interface _WithComments
|
22
34
|
# def comments: () -> AnnotationParser::ParsingResult?
|
23
35
|
# end
|
24
36
|
|
25
37
|
# @rbs module-self _WithComments
|
26
38
|
module Generics
|
27
|
-
# @rbs
|
39
|
+
# @rbs return: Array[RBS::AST::TypeParam]
|
28
40
|
def type_params
|
29
41
|
if comments = comments()
|
30
|
-
comments.
|
42
|
+
comments.each_annotation.filter_map do |annotation|
|
31
43
|
if annotation.is_a?(Annotations::Generic)
|
32
44
|
annotation.type_param
|
33
45
|
end
|
@@ -44,26 +56,26 @@ module RBS
|
|
44
56
|
# @rbs generic NODE < Prism::Node
|
45
57
|
class ModuleOrClass < Base
|
46
58
|
# The node that represents the declaration
|
47
|
-
attr_reader :node
|
59
|
+
attr_reader :node #: NODE
|
48
60
|
|
49
61
|
# Leading comment
|
50
|
-
attr_reader :comments
|
62
|
+
attr_reader :comments #: AnnotationParser::ParsingResult?
|
51
63
|
|
52
64
|
# Members included in the declaration
|
53
|
-
attr_reader :members
|
65
|
+
attr_reader :members #: Array[Members::t | t]
|
54
66
|
|
55
67
|
# @rbs node: NODE
|
56
68
|
# @rbs comments: AnnotationParser::ParsingResult?
|
57
|
-
def initialize(node, comments)
|
69
|
+
def initialize(node, comments) #: void
|
58
70
|
@node = node
|
59
71
|
@comments = comments
|
60
72
|
@members = []
|
61
73
|
end
|
62
74
|
|
63
75
|
# Type parameters for the declaration
|
64
|
-
def type_params
|
76
|
+
def type_params #: Array[RBS::AST::TypeParam]
|
65
77
|
if comments = comments()
|
66
|
-
comments.
|
78
|
+
comments.each_annotation.filter_map do |annotation|
|
67
79
|
if annotation.is_a?(Annotations::Generic)
|
68
80
|
annotation.type_param
|
69
81
|
end
|
@@ -73,7 +85,7 @@ module RBS
|
|
73
85
|
end
|
74
86
|
end
|
75
87
|
|
76
|
-
def start_line
|
88
|
+
def start_line #: Integer
|
77
89
|
node.location.start_line
|
78
90
|
end
|
79
91
|
end
|
@@ -82,12 +94,12 @@ module RBS
|
|
82
94
|
include ConstantUtil
|
83
95
|
|
84
96
|
# Type application for super class
|
85
|
-
attr_reader :super_app
|
97
|
+
attr_reader :super_app #: Annotations::Application?
|
86
98
|
|
87
99
|
# @rbs node: Prism::ClassNode
|
88
100
|
# @rbs comments: AnnotationParser::ParsingResult?
|
89
101
|
# @rbs super_app: Annotations::Application?
|
90
|
-
# @rbs
|
102
|
+
# @rbs return: void
|
91
103
|
def initialize(node, comments, super_app)
|
92
104
|
super(node, comments)
|
93
105
|
|
@@ -95,14 +107,14 @@ module RBS
|
|
95
107
|
end
|
96
108
|
|
97
109
|
# @rbs %a{pure}
|
98
|
-
def class_name
|
110
|
+
def class_name #: TypeName?
|
99
111
|
type_name(node.constant_path)
|
100
112
|
end
|
101
113
|
|
102
114
|
# @rbs %a{pure}
|
103
|
-
def super_class
|
115
|
+
def super_class #: RBS::AST::Declarations::Class::Super?
|
104
116
|
if comments
|
105
|
-
if inherits = comments.
|
117
|
+
if inherits = comments.each_annotation.find {|a| a.is_a?(Annotations::Inherits) } #: Annotations::Inherits?
|
106
118
|
super_name = inherits.super_name
|
107
119
|
super_args = inherits.args
|
108
120
|
|
@@ -141,14 +153,14 @@ module RBS
|
|
141
153
|
include ConstantUtil
|
142
154
|
|
143
155
|
# @rbs %a{pure}
|
144
|
-
def module_name
|
156
|
+
def module_name #: TypeName?
|
145
157
|
type_name(node.constant_path)
|
146
158
|
end
|
147
159
|
|
148
160
|
# @rbs %a{pure}
|
149
|
-
def module_selfs
|
161
|
+
def module_selfs #: Array[Annotations::ModuleSelf]
|
150
162
|
if comments
|
151
|
-
comments.
|
163
|
+
comments.each_annotation.filter_map do |ann|
|
152
164
|
if ann.is_a?(AST::Annotations::ModuleSelf)
|
153
165
|
ann
|
154
166
|
end
|
@@ -162,21 +174,21 @@ module RBS
|
|
162
174
|
class ConstantDecl < Base
|
163
175
|
include ConstantUtil
|
164
176
|
|
165
|
-
attr_reader :node
|
166
|
-
attr_reader :comments
|
167
|
-
attr_reader :assertion
|
177
|
+
attr_reader :node #: Prism::ConstantWriteNode
|
178
|
+
attr_reader :comments #: AnnotationParser::ParsingResult?
|
179
|
+
attr_reader :assertion #: Annotations::TypeAssertion?
|
168
180
|
|
169
181
|
# @rbs node: Prism::ConstantWriteNode
|
170
182
|
# @rbs comments: AnnotationParser::ParsingResult?
|
171
|
-
# @rbs assertion: Annotations::
|
172
|
-
def initialize(node, comments, assertion)
|
183
|
+
# @rbs assertion: Annotations::TypeAssertion?
|
184
|
+
def initialize(node, comments, assertion) #: void
|
173
185
|
@node = node
|
174
186
|
@comments = comments
|
175
187
|
@assertion = assertion
|
176
188
|
end
|
177
189
|
|
178
190
|
# @rbs %a{pure}
|
179
|
-
# @rbs
|
191
|
+
# @rbs return: Types::t
|
180
192
|
def type
|
181
193
|
if assertion
|
182
194
|
case assertion.type
|
@@ -218,18 +230,279 @@ module RBS
|
|
218
230
|
end
|
219
231
|
|
220
232
|
# @rbs %a{pure}
|
221
|
-
# @rbs
|
233
|
+
# @rbs return: TypeName?
|
222
234
|
def constant_name
|
223
235
|
TypeName.new(name: node.name, namespace: Namespace.empty)
|
224
236
|
end
|
225
237
|
|
226
|
-
def start_line
|
238
|
+
def start_line #: Integer
|
227
239
|
node.location.start_line
|
228
240
|
end
|
229
241
|
end
|
230
242
|
|
231
243
|
class SingletonClassDecl < ModuleOrClass #[Prism::SingletonClassNode]
|
232
244
|
end
|
245
|
+
|
246
|
+
class BlockDecl < Base
|
247
|
+
attr_reader :node #: Prism::BlockNode
|
248
|
+
|
249
|
+
attr_reader :comments #: AnnotationParser::ParsingResult?
|
250
|
+
|
251
|
+
# Members included in the declaration
|
252
|
+
attr_reader :members #: Array[Members::t | t]
|
253
|
+
|
254
|
+
# @rbs (Prism::BlockNode, AnnotationParser::ParsingResult?) -> void
|
255
|
+
def initialize(node, comments)
|
256
|
+
@node = node
|
257
|
+
@members = []
|
258
|
+
@comments = comments
|
259
|
+
end
|
260
|
+
|
261
|
+
def start_line #: Integer
|
262
|
+
node.location.start_line
|
263
|
+
end
|
264
|
+
|
265
|
+
def module_class_annotation #: Annotations::ModuleDecl | Annotations::ClassDecl | nil
|
266
|
+
if comments
|
267
|
+
comments.each_annotation.each do |annotation|
|
268
|
+
if annotation.is_a?(Annotations::ModuleDecl)
|
269
|
+
return annotation
|
270
|
+
end
|
271
|
+
|
272
|
+
if annotation.is_a?(Annotations::ClassDecl)
|
273
|
+
return annotation
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
nil
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# @rbs module-self _WithTypeDecls
|
283
|
+
module DataStructUtil
|
284
|
+
# @rbs!
|
285
|
+
# interface _WithTypeDecls
|
286
|
+
# def type_decls: () -> Hash[Integer, Annotations::TypeAssertion]
|
287
|
+
#
|
288
|
+
# def each_attribute_argument: () { (Prism::Node) -> void } -> void
|
289
|
+
#
|
290
|
+
# def comments: %a{pure} () -> AnnotationParser::ParsingResult?
|
291
|
+
# end
|
292
|
+
|
293
|
+
# @rbs %a{pure}
|
294
|
+
# @rbs () { ([Symbol, Annotations::TypeAssertion?]) -> void } -> void
|
295
|
+
# | () -> Enumerator[[Symbol, Annotations::TypeAssertion?], void]
|
296
|
+
def each_attribute(&block)
|
297
|
+
if block
|
298
|
+
each_attribute_argument do |arg|
|
299
|
+
if arg.is_a?(Prism::SymbolNode)
|
300
|
+
if name = arg.value
|
301
|
+
type = type_decls.fetch(arg.location.start_line, nil)
|
302
|
+
yield [name.to_sym, type]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
else
|
307
|
+
enum_for :each_attribute
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def class_annotations #: Array[RBS::AST::Annotation]
|
312
|
+
annotations = [] #: Array[RBS::AST::Annotation]
|
313
|
+
|
314
|
+
comments&.each_annotation do |annotation|
|
315
|
+
if annotation.is_a?(Annotations::RBSAnnotation)
|
316
|
+
annotations.concat annotation.annotations
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
annotations
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
class DataAssignDecl < Base
|
325
|
+
extend ConstantUtil
|
326
|
+
|
327
|
+
include DataStructUtil
|
328
|
+
|
329
|
+
attr_reader :node #: Prism::ConstantWriteNode
|
330
|
+
|
331
|
+
attr_reader :comments #: AnnotationParser::ParsingResult?
|
332
|
+
|
333
|
+
attr_reader :type_decls #: Hash[Integer, Annotations::TypeAssertion]
|
334
|
+
|
335
|
+
attr_reader :data_define_node #: Prism::CallNode
|
336
|
+
|
337
|
+
# @rbs (Prism::ConstantWriteNode, Prism::CallNode, AnnotationParser::ParsingResult?, Hash[Integer, Annotations::TypeAssertion]) -> void
|
338
|
+
def initialize(node, data_define_node, comments, type_decls)
|
339
|
+
@node = node
|
340
|
+
@comments = comments
|
341
|
+
@type_decls = type_decls
|
342
|
+
@data_define_node = data_define_node
|
343
|
+
end
|
344
|
+
|
345
|
+
def start_line #: Integer
|
346
|
+
node.location.start_line
|
347
|
+
end
|
348
|
+
|
349
|
+
# @rbs %a{pure}
|
350
|
+
# @rbs () -> TypeName?
|
351
|
+
def constant_name
|
352
|
+
TypeName.new(name: node.name, namespace: Namespace.empty)
|
353
|
+
end
|
354
|
+
|
355
|
+
# @rbs (Prism::ConstantWriteNode) -> Prism::CallNode?
|
356
|
+
def self.data_define?(node)
|
357
|
+
value = value_node(node)
|
358
|
+
|
359
|
+
if value.is_a?(Prism::CallNode)
|
360
|
+
if value.receiver.is_a?(Prism::ConstantReadNode)
|
361
|
+
if value.receiver.full_name.delete_prefix("::") == "Data"
|
362
|
+
if value.name == :define
|
363
|
+
return value
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# @rbs () { (Prism::Node) -> void } -> void
|
371
|
+
def each_attribute_argument(&block)
|
372
|
+
if args = data_define_node.arguments
|
373
|
+
args.arguments.each(&block)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
class StructAssignDecl < Base
|
379
|
+
extend ConstantUtil
|
380
|
+
|
381
|
+
include DataStructUtil
|
382
|
+
|
383
|
+
attr_reader :node #: Prism::ConstantWriteNode
|
384
|
+
|
385
|
+
attr_reader :comments #: AnnotationParser::ParsingResult?
|
386
|
+
|
387
|
+
attr_reader :type_decls #: Hash[Integer, Annotations::TypeAssertion]
|
388
|
+
|
389
|
+
attr_reader :struct_new_node #: Prism::CallNode
|
390
|
+
|
391
|
+
# @rbs (Prism::ConstantWriteNode, Prism::CallNode, AnnotationParser::ParsingResult?, Hash[Integer, Annotations::TypeAssertion]) -> void
|
392
|
+
def initialize(node, struct_new_node, comments, type_decls)
|
393
|
+
@node = node
|
394
|
+
@comments = comments
|
395
|
+
@type_decls = type_decls
|
396
|
+
@struct_new_node = struct_new_node
|
397
|
+
end
|
398
|
+
|
399
|
+
def start_line #: Integer
|
400
|
+
node.location.start_line
|
401
|
+
end
|
402
|
+
|
403
|
+
# @rbs %a{pure}
|
404
|
+
# @rbs () -> TypeName?
|
405
|
+
def constant_name
|
406
|
+
TypeName.new(name: node.name, namespace: Namespace.empty)
|
407
|
+
end
|
408
|
+
|
409
|
+
# @rbs () { (Prism::Node) -> void } -> void
|
410
|
+
def each_attribute_argument(&block)
|
411
|
+
if args = struct_new_node.arguments
|
412
|
+
args.arguments.each do |arg|
|
413
|
+
next if arg.is_a?(Prism::KeywordHashNode)
|
414
|
+
next if arg.is_a?(Prism::StringNode)
|
415
|
+
|
416
|
+
yield arg
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# @rbs (Prism::ConstantWriteNode) -> Prism::CallNode?
|
422
|
+
def self.struct_new?(node)
|
423
|
+
value = value_node(node)
|
424
|
+
|
425
|
+
if value.is_a?(Prism::CallNode)
|
426
|
+
if value.receiver.is_a?(Prism::ConstantReadNode)
|
427
|
+
if value.receiver.full_name.delete_prefix("::") == "Struct"
|
428
|
+
if value.name == :new
|
429
|
+
return value
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
# @rbs %a{pure}
|
437
|
+
def keyword_init? #: bool
|
438
|
+
if args = struct_new_node.arguments
|
439
|
+
args.arguments.each do |arg|
|
440
|
+
if arg.is_a?(Prism::KeywordHashNode)
|
441
|
+
arg.elements.each do |assoc|
|
442
|
+
if assoc.is_a?(Prism::AssocNode)
|
443
|
+
if (key = assoc.key).is_a?(Prism::SymbolNode)
|
444
|
+
if key.value == "keyword_init"
|
445
|
+
value = assoc.value
|
446
|
+
if value.is_a?(Prism::FalseNode)
|
447
|
+
return false
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
true
|
458
|
+
end
|
459
|
+
|
460
|
+
# @rbs %a{pure}
|
461
|
+
def positional_init? #: bool
|
462
|
+
if args = struct_new_node.arguments
|
463
|
+
args.arguments.each do |arg|
|
464
|
+
if arg.is_a?(Prism::KeywordHashNode)
|
465
|
+
arg.elements.each do |assoc|
|
466
|
+
if assoc.is_a?(Prism::AssocNode)
|
467
|
+
if (key = assoc.key).is_a?(Prism::SymbolNode)
|
468
|
+
if key.value == "keyword_init"
|
469
|
+
value = assoc.value
|
470
|
+
if value.is_a?(Prism::TrueNode)
|
471
|
+
return false
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
true
|
482
|
+
end
|
483
|
+
|
484
|
+
# Returns `true` is annotation is given to make all attributes *readonly*
|
485
|
+
#
|
486
|
+
# Add `# @rbs %a{rbs-inline:readonly-attributes=true}` to the class to make all attributes `attr_reader`, instead of `attr_accessor`.
|
487
|
+
#
|
488
|
+
# @rbs %a{pure}
|
489
|
+
def readonly_attributes? #: bool
|
490
|
+
class_annotations.any? do |annotation|
|
491
|
+
annotation.string == "rbs-inline:readonly-attributes=true"
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
# Returns `true` if annotation is given to make all `.new` arguments required
|
496
|
+
#
|
497
|
+
# Add `# @rbs %a{rbs-inline:new-args=required}` to the class to make all of the parameters required.
|
498
|
+
#
|
499
|
+
# @rbs %a{pure}
|
500
|
+
def required_new_args? #: bool
|
501
|
+
class_annotations.any? do |annotation|
|
502
|
+
annotation.string == "rbs-inline:new-args=required"
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
233
506
|
end
|
234
507
|
end
|
235
508
|
end
|