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.
@@ -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 #:: Array[[Prism::Comment, Integer]]
19
+ attr_reader :comments #: Array[Prism::Comment]
20
20
 
21
21
  # @rbs comments: Array[Prism::Comment]
22
- def initialize(comments)
23
- offsets = comments.map do |comment|
24
- comment.location.slice.index(/[^#\s]/) || 1
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
- [comment, offset]
33
- end
26
+ def lines #: Array[String]
27
+ comments.map {|comment| comment.location.slice }
34
28
  end
35
29
 
36
- def string #:: String
37
- comments.map {|comment, offset| comment.location.slice[offset..] }.join("\n")
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 returns [Prism::Comment, Integer]?
37
+ # @rbs return: [Prism::Comment, Integer]?
42
38
  def comment_location(index)
43
- comments.each do |comment, offset|
39
+ comments.each do |comment|
44
40
  comment_length = comment.location.length
45
41
 
46
- if index + offset <= comment_length
47
- return [comment, index + offset]
42
+ if index + 1 <= comment_length
43
+ return [comment, index + 1]
48
44
  else
49
- index = index - comment_length + offset - 1
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 returns TypeName?
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
- # @rbs! type t = ClassDecl | ModuleDecl | ConstantDecl | SingletonClassDecl
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 returns Array[RBS::AST::TypeParam]
39
+ # @rbs return: Array[RBS::AST::TypeParam]
28
40
  def type_params
29
41
  if comments = comments()
30
- comments.annotations.filter_map do |annotation|
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 #:: NODE
59
+ attr_reader :node #: NODE
48
60
 
49
61
  # Leading comment
50
- attr_reader :comments #:: AnnotationParser::ParsingResult?
62
+ attr_reader :comments #: AnnotationParser::ParsingResult?
51
63
 
52
64
  # Members included in the declaration
53
- attr_reader :members #:: Array[Members::t | t]
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) #:: void
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 #:: Array[RBS::AST::TypeParam]
76
+ def type_params #: Array[RBS::AST::TypeParam]
65
77
  if comments = comments()
66
- comments.annotations.filter_map do |annotation|
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 #:: Integer
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 #:: Annotations::Application?
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 returns void
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 #:: TypeName?
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 #:: RBS::AST::Declarations::Class::Super?
115
+ def super_class #: RBS::AST::Declarations::Class::Super?
104
116
  if comments
105
- if inherits = comments.annotations.find {|a| a.is_a?(Annotations::Inherits) } #: Annotations::Inherits?
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 #:: TypeName?
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 #:: Array[Annotations::ModuleSelf]
161
+ def module_selfs #: Array[Annotations::ModuleSelf]
150
162
  if comments
151
- comments.annotations.filter_map do |ann|
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 #:: Prism::ConstantWriteNode
166
- attr_reader :comments #:: AnnotationParser::ParsingResult?
167
- attr_reader :assertion #:: Annotations::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::Assertion?
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 returns Types::t
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 returns TypeName?
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 #:: Integer
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