rbi 0.2.4 → 0.3.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.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/lib/rbi/formatter.rb +9 -17
- data/lib/rbi/index.rb +49 -43
- data/lib/rbi/loc.rb +7 -19
- data/lib/rbi/model.rb +238 -581
- data/lib/rbi/parser.rb +193 -91
- data/lib/rbi/printer.rb +158 -105
- data/lib/rbi/rbs/method_type_translator.rb +120 -0
- data/lib/rbi/rbs/type_translator.rb +181 -0
- data/lib/rbi/rbs_printer.rb +201 -133
- data/lib/rbi/rewriters/add_sig_templates.rb +7 -10
- data/lib/rbi/rewriters/annotate.rb +6 -9
- data/lib/rbi/rewriters/attr_to_methods.rb +16 -32
- data/lib/rbi/rewriters/deannotate.rb +5 -8
- data/lib/rbi/rewriters/filter_versions.rb +7 -12
- data/lib/rbi/rewriters/flatten_singleton_methods.rb +5 -7
- data/lib/rbi/rewriters/flatten_visibilities.rb +6 -9
- data/lib/rbi/rewriters/group_nodes.rb +6 -11
- data/lib/rbi/rewriters/merge_trees.rb +84 -132
- data/lib/rbi/rewriters/nest_non_public_members.rb +5 -10
- data/lib/rbi/rewriters/nest_singleton_methods.rb +3 -6
- data/lib/rbi/rewriters/nest_top_level_members.rb +5 -8
- data/lib/rbi/rewriters/remove_known_definitions.rb +13 -23
- data/lib/rbi/rewriters/sort_nodes.rb +10 -11
- data/lib/rbi/rewriters/translate_rbs_sigs.rb +87 -0
- data/lib/rbi/type.rb +135 -137
- data/lib/rbi/type_parser.rb +51 -27
- data/lib/rbi/type_visitor.rb +19 -21
- data/lib/rbi/version.rb +1 -1
- data/lib/rbi/visitor.rb +55 -46
- data/lib/rbi.rb +7 -3
- data/rbi/rbi.rbi +3673 -0
- metadata +21 -3
data/lib/rbi/parser.rb
CHANGED
@@ -5,12 +5,10 @@ require "prism"
|
|
5
5
|
|
6
6
|
module RBI
|
7
7
|
class ParseError < Error
|
8
|
-
|
9
|
-
|
10
|
-
sig { returns(Loc) }
|
8
|
+
#: Loc
|
11
9
|
attr_reader :location
|
12
10
|
|
13
|
-
|
11
|
+
#: (String message, Loc location) -> void
|
14
12
|
def initialize(message, location)
|
15
13
|
super(message)
|
16
14
|
@location = location
|
@@ -18,19 +16,17 @@ module RBI
|
|
18
16
|
end
|
19
17
|
|
20
18
|
class UnexpectedParserError < Error
|
21
|
-
|
22
|
-
|
23
|
-
sig { returns(Loc) }
|
19
|
+
#: Loc
|
24
20
|
attr_reader :last_location
|
25
21
|
|
26
|
-
|
22
|
+
#: (Exception parent_exception, Loc last_location) -> void
|
27
23
|
def initialize(parent_exception, last_location)
|
28
24
|
super(parent_exception)
|
29
25
|
set_backtrace(parent_exception.backtrace)
|
30
26
|
@last_location = last_location
|
31
27
|
end
|
32
28
|
|
33
|
-
|
29
|
+
#: (?io: (IO | StringIO)) -> void
|
34
30
|
def print_debug(io: $stderr)
|
35
31
|
io.puts ""
|
36
32
|
io.puts "##################################"
|
@@ -51,47 +47,43 @@ module RBI
|
|
51
47
|
end
|
52
48
|
|
53
49
|
class Parser
|
54
|
-
extend T::Sig
|
55
|
-
|
56
50
|
class << self
|
57
|
-
|
58
|
-
|
59
|
-
sig { params(string: String).returns(Tree) }
|
51
|
+
#: (String string) -> Tree
|
60
52
|
def parse_string(string)
|
61
53
|
Parser.new.parse_string(string)
|
62
54
|
end
|
63
55
|
|
64
|
-
|
56
|
+
#: (String path) -> Tree
|
65
57
|
def parse_file(path)
|
66
58
|
Parser.new.parse_file(path)
|
67
59
|
end
|
68
60
|
|
69
|
-
|
61
|
+
#: (Array[String] paths) -> Array[Tree]
|
70
62
|
def parse_files(paths)
|
71
63
|
parser = Parser.new
|
72
64
|
paths.map { |path| parser.parse_file(path) }
|
73
65
|
end
|
74
66
|
|
75
|
-
|
67
|
+
#: (Array[String] strings) -> Array[Tree]
|
76
68
|
def parse_strings(strings)
|
77
69
|
parser = Parser.new
|
78
70
|
strings.map { |string| parser.parse_string(string) }
|
79
71
|
end
|
80
72
|
end
|
81
73
|
|
82
|
-
|
74
|
+
#: (String string) -> Tree
|
83
75
|
def parse_string(string)
|
84
76
|
parse(string, file: "-")
|
85
77
|
end
|
86
78
|
|
87
|
-
|
79
|
+
#: (String path) -> Tree
|
88
80
|
def parse_file(path)
|
89
81
|
parse(::File.read(path), file: path)
|
90
82
|
end
|
91
83
|
|
92
84
|
private
|
93
85
|
|
94
|
-
|
86
|
+
#: (String source, file: String) -> Tree
|
95
87
|
def parse(source, file:)
|
96
88
|
result = Prism.parse(source)
|
97
89
|
unless result.success?
|
@@ -120,9 +112,7 @@ module RBI
|
|
120
112
|
end
|
121
113
|
|
122
114
|
class Visitor < Prism::Visitor
|
123
|
-
|
124
|
-
|
125
|
-
sig { params(source: String, file: String).void }
|
115
|
+
#: (String source, file: String) -> void
|
126
116
|
def initialize(source, file:)
|
127
117
|
super()
|
128
118
|
|
@@ -132,46 +122,56 @@ module RBI
|
|
132
122
|
|
133
123
|
private
|
134
124
|
|
135
|
-
|
125
|
+
#: (Prism::Node node) -> Loc
|
136
126
|
def node_loc(node)
|
137
127
|
Loc.from_prism(@file, node.location)
|
138
128
|
end
|
139
129
|
|
140
|
-
|
130
|
+
#: (Prism::Node? node) -> String?
|
141
131
|
def node_string(node)
|
142
132
|
return unless node
|
143
133
|
|
144
134
|
node.slice
|
145
135
|
end
|
146
136
|
|
147
|
-
|
137
|
+
#: (Prism::Node node) -> String
|
148
138
|
def node_string!(node)
|
149
|
-
|
139
|
+
node_string(node) #: as !nil
|
140
|
+
end
|
141
|
+
|
142
|
+
#: (Prism::Node node) -> Prism::Location
|
143
|
+
def adjust_prism_location_for_heredoc(node)
|
144
|
+
visitor = HeredocLocationVisitor.new(
|
145
|
+
node.location.send(:source),
|
146
|
+
node.location.start_offset,
|
147
|
+
node.location.end_offset,
|
148
|
+
)
|
149
|
+
visitor.visit(node)
|
150
|
+
visitor.location
|
150
151
|
end
|
151
152
|
end
|
152
153
|
|
153
154
|
class TreeBuilder < Visitor
|
154
|
-
|
155
|
-
|
156
|
-
sig { returns(Tree) }
|
155
|
+
#: Tree
|
157
156
|
attr_reader :tree
|
158
157
|
|
159
|
-
|
158
|
+
#: Prism::Node?
|
160
159
|
attr_reader :last_node
|
161
160
|
|
162
|
-
|
161
|
+
#: (String source, comments: Array[Prism::Comment], file: String) -> void
|
163
162
|
def initialize(source, comments:, file:)
|
164
163
|
super(source, file: file)
|
165
164
|
|
166
|
-
@comments_by_line =
|
167
|
-
@tree =
|
165
|
+
@comments_by_line = comments.to_h { |c| [c.location.start_line, c] } #: Hash[Integer, Prism::Comment]
|
166
|
+
@tree = Tree.new #: Tree
|
168
167
|
|
169
|
-
@scopes_stack =
|
170
|
-
@last_node =
|
171
|
-
@last_sigs =
|
168
|
+
@scopes_stack = [@tree] #: Array[Tree]
|
169
|
+
@last_node = nil #: Prism::Node?
|
170
|
+
@last_sigs = [] #: Array[RBI::Sig]
|
172
171
|
end
|
173
172
|
|
174
|
-
|
173
|
+
# @override
|
174
|
+
#: (Prism::ClassNode node) -> void
|
175
175
|
def visit_class_node(node)
|
176
176
|
@last_node = node
|
177
177
|
superclass_name = node_string(node.superclass)
|
@@ -206,54 +206,78 @@ module RBI
|
|
206
206
|
@last_node = nil
|
207
207
|
end
|
208
208
|
|
209
|
-
|
209
|
+
# @override
|
210
|
+
#: (Prism::ConstantWriteNode node) -> void
|
210
211
|
def visit_constant_write_node(node)
|
211
212
|
@last_node = node
|
212
213
|
visit_constant_assign(node)
|
213
214
|
@last_node = nil
|
214
215
|
end
|
215
216
|
|
216
|
-
|
217
|
+
# @override
|
218
|
+
#: (Prism::ConstantPathWriteNode node) -> void
|
217
219
|
def visit_constant_path_write_node(node)
|
218
220
|
@last_node = node
|
219
221
|
visit_constant_assign(node)
|
220
222
|
@last_node = nil
|
221
223
|
end
|
222
224
|
|
223
|
-
|
225
|
+
#: ((Prism::ConstantWriteNode | Prism::ConstantPathWriteNode) node) -> void
|
224
226
|
def visit_constant_assign(node)
|
225
227
|
struct = parse_struct(node)
|
226
228
|
|
227
229
|
current_scope << if struct
|
228
230
|
struct
|
229
|
-
elsif
|
230
|
-
|
231
|
+
elsif t_enum_value?(node)
|
232
|
+
TEnumValue.new(
|
231
233
|
case node
|
232
234
|
when Prism::ConstantWriteNode
|
233
235
|
node.name.to_s
|
234
236
|
when Prism::ConstantPathWriteNode
|
235
237
|
node_string!(node.target)
|
236
238
|
end,
|
237
|
-
node_string!(node.value),
|
238
239
|
loc: node_loc(node),
|
239
240
|
comments: node_comments(node),
|
240
241
|
)
|
241
242
|
else
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
end,
|
249
|
-
node_string!(node.value),
|
250
|
-
loc: node_loc(node),
|
251
|
-
comments: node_comments(node),
|
243
|
+
adjusted_node_location = adjust_prism_location_for_heredoc(node)
|
244
|
+
|
245
|
+
adjusted_value_location = Prism::Location.new(
|
246
|
+
node.value.location.send(:source),
|
247
|
+
node.value.location.start_offset,
|
248
|
+
adjusted_node_location.end_offset - node.value.location.start_offset,
|
252
249
|
)
|
250
|
+
|
251
|
+
if type_variable_definition?(node.value)
|
252
|
+
TypeMember.new(
|
253
|
+
case node
|
254
|
+
when Prism::ConstantWriteNode
|
255
|
+
node.name.to_s
|
256
|
+
when Prism::ConstantPathWriteNode
|
257
|
+
node_string!(node.target)
|
258
|
+
end,
|
259
|
+
adjusted_value_location.slice,
|
260
|
+
loc: Loc.from_prism(@file, adjusted_node_location),
|
261
|
+
comments: node_comments(node),
|
262
|
+
)
|
263
|
+
else
|
264
|
+
Const.new(
|
265
|
+
case node
|
266
|
+
when Prism::ConstantWriteNode
|
267
|
+
node.name.to_s
|
268
|
+
when Prism::ConstantPathWriteNode
|
269
|
+
node_string!(node.target)
|
270
|
+
end,
|
271
|
+
adjusted_value_location.slice,
|
272
|
+
loc: Loc.from_prism(@file, adjusted_node_location),
|
273
|
+
comments: node_comments(node),
|
274
|
+
)
|
275
|
+
end
|
253
276
|
end
|
254
277
|
end
|
255
278
|
|
256
|
-
|
279
|
+
# @override
|
280
|
+
#: (Prism::DefNode node) -> void
|
257
281
|
def visit_def_node(node)
|
258
282
|
@last_node = node
|
259
283
|
|
@@ -274,7 +298,8 @@ module RBI
|
|
274
298
|
@last_node = nil
|
275
299
|
end
|
276
300
|
|
277
|
-
|
301
|
+
# @override
|
302
|
+
#: (Prism::ModuleNode node) -> void
|
278
303
|
def visit_module_node(node)
|
279
304
|
@last_node = node
|
280
305
|
scope = Module.new(
|
@@ -292,7 +317,8 @@ module RBI
|
|
292
317
|
@last_node = nil
|
293
318
|
end
|
294
319
|
|
295
|
-
|
320
|
+
# @override
|
321
|
+
#: (Prism::ProgramNode node) -> void
|
296
322
|
def visit_program_node(node)
|
297
323
|
@last_node = node
|
298
324
|
super
|
@@ -303,7 +329,8 @@ module RBI
|
|
303
329
|
@last_node = nil
|
304
330
|
end
|
305
331
|
|
306
|
-
|
332
|
+
# @override
|
333
|
+
#: (Prism::SingletonClassNode node) -> void
|
307
334
|
def visit_singleton_class_node(node)
|
308
335
|
@last_node = node
|
309
336
|
scope = SingletonClass.new(
|
@@ -320,7 +347,7 @@ module RBI
|
|
320
347
|
@last_node = nil
|
321
348
|
end
|
322
349
|
|
323
|
-
|
350
|
+
#: (Prism::CallNode node) -> void
|
324
351
|
def visit_call_node(node)
|
325
352
|
@last_node = node
|
326
353
|
message = node.name.to_s
|
@@ -494,7 +521,7 @@ module RBI
|
|
494
521
|
private
|
495
522
|
|
496
523
|
# Collect all the remaining comments within a node
|
497
|
-
|
524
|
+
#: (Prism::Node node) -> void
|
498
525
|
def collect_dangling_comments(node)
|
499
526
|
first_line = node.location.start_line
|
500
527
|
last_line = node.location.end_line
|
@@ -512,9 +539,9 @@ module RBI
|
|
512
539
|
end
|
513
540
|
|
514
541
|
# Collect all the remaining comments after visiting the tree
|
515
|
-
|
542
|
+
#: -> void
|
516
543
|
def collect_orphan_comments
|
517
|
-
last_line =
|
544
|
+
last_line = nil #: Integer?
|
518
545
|
last_node_end = @tree.nodes.last&.loc&.end_line
|
519
546
|
|
520
547
|
@comments_by_line.each do |line, comment|
|
@@ -535,21 +562,21 @@ module RBI
|
|
535
562
|
end
|
536
563
|
end
|
537
564
|
|
538
|
-
|
565
|
+
#: -> Tree
|
539
566
|
def current_scope
|
540
|
-
|
567
|
+
@scopes_stack.last #: as !nil # Should never be nil since we create a Tree as the root
|
541
568
|
end
|
542
569
|
|
543
|
-
|
570
|
+
#: -> Array[Sig]
|
544
571
|
def current_sigs
|
545
572
|
sigs = @last_sigs.dup
|
546
573
|
@last_sigs.clear
|
547
574
|
sigs
|
548
575
|
end
|
549
576
|
|
550
|
-
|
577
|
+
#: (Array[Sig] sigs) -> Array[Comment]
|
551
578
|
def detach_comments_from_sigs(sigs)
|
552
|
-
comments =
|
579
|
+
comments = [] #: Array[Comment]
|
553
580
|
|
554
581
|
sigs.each do |sig|
|
555
582
|
comments += sig.comments.dup
|
@@ -559,7 +586,7 @@ module RBI
|
|
559
586
|
comments
|
560
587
|
end
|
561
588
|
|
562
|
-
|
589
|
+
#: (Prism::Node node) -> Array[Comment]
|
563
590
|
def node_comments(node)
|
564
591
|
comments = []
|
565
592
|
|
@@ -577,14 +604,22 @@ module RBI
|
|
577
604
|
comments
|
578
605
|
end
|
579
606
|
|
580
|
-
|
607
|
+
#: (Prism::Comment node) -> Comment
|
581
608
|
def parse_comment(node)
|
582
|
-
|
609
|
+
loc = Loc.from_prism(@file, node.location)
|
610
|
+
string = node.location.slice
|
611
|
+
# We also ignore RDoc directives such as `:nodoc:`
|
612
|
+
# See https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Directives
|
613
|
+
if string.start_with?("#:") && !(string =~ /^#:[a-z_]+:/)
|
614
|
+
RBSComment.new(string.gsub(/^#: ?/, "").rstrip, loc: loc)
|
615
|
+
else
|
616
|
+
Comment.new(string.gsub(/^# ?/, "").rstrip, loc: loc)
|
617
|
+
end
|
583
618
|
end
|
584
619
|
|
585
|
-
|
620
|
+
#: (Prism::Node? node) -> Array[Arg]
|
586
621
|
def parse_send_args(node)
|
587
|
-
args =
|
622
|
+
args = [] #: Array[Arg]
|
588
623
|
return args unless node.is_a?(Prism::ArgumentsNode)
|
589
624
|
|
590
625
|
node.arguments.each do |arg|
|
@@ -595,18 +630,20 @@ module RBI
|
|
595
630
|
|
596
631
|
args << KwArg.new(
|
597
632
|
node_string!(assoc.key).delete_suffix(":"),
|
598
|
-
|
633
|
+
node_string(assoc.value), #: as !nil
|
599
634
|
)
|
600
635
|
end
|
601
636
|
else
|
602
|
-
args << Arg.new(
|
637
|
+
args << Arg.new(
|
638
|
+
node_string(arg), #: as !nil
|
639
|
+
)
|
603
640
|
end
|
604
641
|
end
|
605
642
|
|
606
643
|
args
|
607
644
|
end
|
608
645
|
|
609
|
-
|
646
|
+
#: (Prism::Node? node) -> Array[Param]
|
610
647
|
def parse_params(node)
|
611
648
|
params = []
|
612
649
|
return params unless node.is_a?(Prism::ParametersNode)
|
@@ -680,7 +717,7 @@ module RBI
|
|
680
717
|
params
|
681
718
|
end
|
682
719
|
|
683
|
-
|
720
|
+
#: (Prism::CallNode node) -> Sig
|
684
721
|
def parse_sig(node)
|
685
722
|
builder = SigBuilder.new(@source, file: @file)
|
686
723
|
builder.current.loc = node_loc(node)
|
@@ -689,7 +726,7 @@ module RBI
|
|
689
726
|
builder.current
|
690
727
|
end
|
691
728
|
|
692
|
-
|
729
|
+
#: ((Prism::ConstantWriteNode | Prism::ConstantPathWriteNode) node) -> Struct?
|
693
730
|
def parse_struct(node)
|
694
731
|
send = node.value
|
695
732
|
return unless send.is_a?(Prism::CallNode)
|
@@ -700,7 +737,7 @@ module RBI
|
|
700
737
|
return unless node_string(recv) =~ /(::)?Struct/
|
701
738
|
|
702
739
|
members = []
|
703
|
-
keyword_init =
|
740
|
+
keyword_init = false #: bool
|
704
741
|
|
705
742
|
args = send.arguments
|
706
743
|
if args.is_a?(Prism::ArgumentsNode)
|
@@ -737,7 +774,7 @@ module RBI
|
|
737
774
|
struct
|
738
775
|
end
|
739
776
|
|
740
|
-
|
777
|
+
#: (Prism::CallNode send) -> void
|
741
778
|
def parse_tstruct_field(send)
|
742
779
|
args = send.arguments
|
743
780
|
return unless args.is_a?(Prism::ArgumentsNode)
|
@@ -750,7 +787,7 @@ module RBI
|
|
750
787
|
type = node_string!(type_arg)
|
751
788
|
loc = node_loc(send)
|
752
789
|
comments = node_comments(send)
|
753
|
-
default_value =
|
790
|
+
default_value = nil #: String?
|
754
791
|
|
755
792
|
rest.each do |arg|
|
756
793
|
next unless arg.is_a?(Prism::KeywordHashNode)
|
@@ -774,7 +811,7 @@ module RBI
|
|
774
811
|
end
|
775
812
|
end
|
776
813
|
|
777
|
-
|
814
|
+
#: (String name, Prism::Node node) -> Visibility
|
778
815
|
def parse_visibility(name, node)
|
779
816
|
case name
|
780
817
|
when "public"
|
@@ -788,7 +825,7 @@ module RBI
|
|
788
825
|
end
|
789
826
|
end
|
790
827
|
|
791
|
-
|
828
|
+
#: -> void
|
792
829
|
def separate_header_comments
|
793
830
|
current_scope.nodes.dup.each do |child_node|
|
794
831
|
break unless child_node.is_a?(Comment) || child_node.is_a?(BlankLine)
|
@@ -798,7 +835,7 @@ module RBI
|
|
798
835
|
end
|
799
836
|
end
|
800
837
|
|
801
|
-
|
838
|
+
#: -> void
|
802
839
|
def set_root_tree_loc
|
803
840
|
first_loc = tree.nodes.first&.loc
|
804
841
|
last_loc = tree.nodes.last&.loc
|
@@ -812,26 +849,38 @@ module RBI
|
|
812
849
|
)
|
813
850
|
end
|
814
851
|
|
815
|
-
|
852
|
+
#: (Prism::Node? node) -> bool
|
816
853
|
def type_variable_definition?(node)
|
817
854
|
node.is_a?(Prism::CallNode) && (node.message == "type_member" || node.message == "type_template")
|
818
855
|
end
|
856
|
+
|
857
|
+
#: (Prism::Node? node) -> bool
|
858
|
+
def t_enum_value?(node)
|
859
|
+
return false unless current_scope.is_a?(TEnumBlock)
|
860
|
+
|
861
|
+
return false unless node.is_a?(Prism::ConstantWriteNode)
|
862
|
+
|
863
|
+
value = node.value
|
864
|
+
return false unless value.is_a?(Prism::CallNode)
|
865
|
+
return false unless value.message == "new"
|
866
|
+
|
867
|
+
true
|
868
|
+
end
|
819
869
|
end
|
820
870
|
|
821
871
|
class SigBuilder < Visitor
|
822
|
-
|
823
|
-
|
824
|
-
sig { returns(Sig) }
|
872
|
+
#: Sig
|
825
873
|
attr_reader :current
|
826
874
|
|
827
|
-
|
875
|
+
#: (String content, file: String) -> void
|
828
876
|
def initialize(content, file:)
|
829
877
|
super
|
830
878
|
|
831
|
-
@current =
|
879
|
+
@current = Sig.new #: Sig
|
832
880
|
end
|
833
881
|
|
834
|
-
|
882
|
+
# @override
|
883
|
+
#: (Prism::CallNode node) -> void
|
835
884
|
def visit_call_node(node)
|
836
885
|
case node.message
|
837
886
|
when "sig"
|
@@ -892,7 +941,8 @@ module RBI
|
|
892
941
|
visit(node.block)
|
893
942
|
end
|
894
943
|
|
895
|
-
|
944
|
+
# @override
|
945
|
+
#: (Prism::AssocNode node) -> void
|
896
946
|
def visit_assoc_node(node)
|
897
947
|
@current.params << SigParam.new(
|
898
948
|
node_string!(node.key).delete_suffix(":"),
|
@@ -900,5 +950,57 @@ module RBI
|
|
900
950
|
)
|
901
951
|
end
|
902
952
|
end
|
953
|
+
|
954
|
+
class HeredocLocationVisitor < Prism::Visitor
|
955
|
+
#: (Prism::Source source, Integer begin_offset, Integer end_offset) -> void
|
956
|
+
def initialize(source, begin_offset, end_offset)
|
957
|
+
super()
|
958
|
+
@source = source
|
959
|
+
@begin_offset = begin_offset
|
960
|
+
@end_offset = end_offset
|
961
|
+
@offset_last_newline = false #: bool
|
962
|
+
end
|
963
|
+
|
964
|
+
#: (Prism::StringNode node) -> void
|
965
|
+
def visit_string_node(node)
|
966
|
+
return unless node.heredoc?
|
967
|
+
|
968
|
+
closing_loc = node.closing_loc
|
969
|
+
return unless closing_loc
|
970
|
+
|
971
|
+
handle_string_node(node)
|
972
|
+
end
|
973
|
+
|
974
|
+
#: (Prism::InterpolatedStringNode node) -> void
|
975
|
+
def visit_interpolated_string_node(node)
|
976
|
+
return super unless node.heredoc?
|
977
|
+
|
978
|
+
closing_loc = node.closing_loc
|
979
|
+
return super unless closing_loc
|
980
|
+
|
981
|
+
handle_string_node(node)
|
982
|
+
end
|
983
|
+
|
984
|
+
#: -> Prism::Location
|
985
|
+
def location
|
986
|
+
Prism::Location.new(
|
987
|
+
@source,
|
988
|
+
@begin_offset,
|
989
|
+
@end_offset - @begin_offset - (@offset_last_newline ? 1 : 0),
|
990
|
+
)
|
991
|
+
end
|
992
|
+
|
993
|
+
private
|
994
|
+
|
995
|
+
#: (Prism::StringNode | Prism::InterpolatedStringNode node) -> void
|
996
|
+
def handle_string_node(node)
|
997
|
+
closing_loc = node.closing_loc #: as !nil
|
998
|
+
|
999
|
+
if closing_loc.end_offset > @end_offset
|
1000
|
+
@end_offset = closing_loc.end_offset
|
1001
|
+
@offset_last_newline = true if node.closing_loc&.slice&.end_with?("\n")
|
1002
|
+
end
|
1003
|
+
end
|
1004
|
+
end
|
903
1005
|
end
|
904
1006
|
end
|