syntax_tree 2.0.1 → 2.2.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/.github/workflows/main.yml +9 -1
- data/CHANGELOG.md +43 -1
- data/Gemfile +0 -5
- data/Gemfile.lock +3 -17
- data/README.md +288 -26
- data/bin/bench +11 -6
- data/bin/profile +16 -7
- data/lib/syntax_tree/cli.rb +46 -34
- data/lib/syntax_tree/language_server/inlay_hints.rb +0 -16
- data/lib/syntax_tree/node.rb +1073 -3164
- data/lib/syntax_tree/parser.rb +338 -134
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/visitor/json_visitor.rb +1335 -0
- data/lib/syntax_tree/visitor/pretty_print_visitor.rb +1213 -0
- data/lib/syntax_tree/visitor.rb +548 -0
- data/lib/syntax_tree.rb +4 -0
- metadata +6 -4
- data/bin/setup +0 -6
data/lib/syntax_tree/parser.rb
CHANGED
@@ -163,6 +163,13 @@ module SyntaxTree
|
|
163
163
|
line_counts[lineno - 1][column]
|
164
164
|
end
|
165
165
|
|
166
|
+
# This represents the current column we're in relative to the beginning of
|
167
|
+
# the current line.
|
168
|
+
def current_column
|
169
|
+
line = line_counts[lineno - 1]
|
170
|
+
line[column].to_i - line.start
|
171
|
+
end
|
172
|
+
|
166
173
|
# As we build up a list of tokens, we'll periodically need to go backwards
|
167
174
|
# and find the ones that we've already hit in order to determine the
|
168
175
|
# location information for nodes that use them. For example, if you have a
|
@@ -251,10 +258,13 @@ module SyntaxTree
|
|
251
258
|
def on_BEGIN(statements)
|
252
259
|
lbrace = find_token(LBrace)
|
253
260
|
rbrace = find_token(RBrace)
|
261
|
+
start_char = find_next_statement_start(lbrace.location.end_char)
|
254
262
|
|
255
263
|
statements.bind(
|
256
|
-
|
257
|
-
|
264
|
+
start_char,
|
265
|
+
start_char - line_counts[lbrace.location.start_line - 1].start,
|
266
|
+
rbrace.location.start_char,
|
267
|
+
rbrace.location.start_column,
|
258
268
|
)
|
259
269
|
|
260
270
|
keyword = find_token(Kw, "BEGIN")
|
@@ -271,7 +281,7 @@ module SyntaxTree
|
|
271
281
|
def on_CHAR(value)
|
272
282
|
CHAR.new(
|
273
283
|
value: value,
|
274
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
284
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
275
285
|
)
|
276
286
|
end
|
277
287
|
|
@@ -280,10 +290,13 @@ module SyntaxTree
|
|
280
290
|
def on_END(statements)
|
281
291
|
lbrace = find_token(LBrace)
|
282
292
|
rbrace = find_token(RBrace)
|
293
|
+
start_char = find_next_statement_start(lbrace.location.end_char)
|
283
294
|
|
284
295
|
statements.bind(
|
285
|
-
|
286
|
-
|
296
|
+
start_char,
|
297
|
+
start_char - line_counts[lbrace.location.start_line - 1].start,
|
298
|
+
rbrace.location.start_char,
|
299
|
+
rbrace.location.start_column
|
287
300
|
)
|
288
301
|
|
289
302
|
keyword = find_token(Kw, "END")
|
@@ -301,7 +314,7 @@ module SyntaxTree
|
|
301
314
|
@__end__ =
|
302
315
|
EndContent.new(
|
303
316
|
value: source[(char_pos + value.length)..-1],
|
304
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
317
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
305
318
|
)
|
306
319
|
end
|
307
320
|
|
@@ -401,12 +414,19 @@ module SyntaxTree
|
|
401
414
|
# (false | untyped) block
|
402
415
|
# ) -> Args
|
403
416
|
def on_args_add_block(arguments, block)
|
417
|
+
# First, see if there is an & operator that could potentially be
|
418
|
+
# associated with the block part of this args_add_block. If there is not,
|
419
|
+
# then just return the arguments.
|
404
420
|
operator = find_token(Op, "&", consume: false)
|
405
|
-
|
406
|
-
# If we can't find the & operator, then there's no block to add to the
|
407
|
-
# list, so we're just going to return the arguments as-is.
|
408
421
|
return arguments unless operator
|
409
422
|
|
423
|
+
# If there are any arguments and the operator we found from the list is
|
424
|
+
# not after them, then we're going to return the arguments as-is because
|
425
|
+
# we're looking at an & that occurs before the arguments are done.
|
426
|
+
if arguments.parts.any? && operator.location.start_char < arguments.location.end_char
|
427
|
+
return arguments
|
428
|
+
end
|
429
|
+
|
410
430
|
# Now we know we have an & operator, so we're going to delete it from the
|
411
431
|
# list of tokens to make sure it doesn't get confused with anything else.
|
412
432
|
tokens.delete(operator)
|
@@ -415,13 +435,6 @@ module SyntaxTree
|
|
415
435
|
location = operator.location
|
416
436
|
location = operator.location.to(block.location) if block
|
417
437
|
|
418
|
-
# If there are any arguments and the operator we found from the list is
|
419
|
-
# not after them, then we're going to return the arguments as-is because
|
420
|
-
# we're looking at an & that occurs before the arguments are done.
|
421
|
-
if arguments.parts.any? && location.start_char < arguments.location.end_char
|
422
|
-
return arguments
|
423
|
-
end
|
424
|
-
|
425
438
|
# Otherwise, we're looking at an actual block argument (with or without a
|
426
439
|
# block, which could be missing because it could be a bare & since 3.1.0).
|
427
440
|
arg_block = ArgBlock.new(value: block, location: location)
|
@@ -465,7 +478,7 @@ module SyntaxTree
|
|
465
478
|
# :call-seq:
|
466
479
|
# on_args_new: () -> Args
|
467
480
|
def on_args_new
|
468
|
-
Args.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
|
481
|
+
Args.new(parts: [], location: Location.fixed(line: lineno, column: current_column, char: char_pos))
|
469
482
|
end
|
470
483
|
|
471
484
|
# :call-seq:
|
@@ -503,12 +516,46 @@ module SyntaxTree
|
|
503
516
|
def on_aryptn(constant, requireds, rest, posts)
|
504
517
|
parts = [constant, *requireds, rest, *posts].compact
|
505
518
|
|
519
|
+
# If there aren't any parts (no constant, no positional arguments), then
|
520
|
+
# we're matching an empty array. In this case, we're going to look for the
|
521
|
+
# left and right brackets explicitly. Otherwise, we'll just use the bounds
|
522
|
+
# of the various parts.
|
523
|
+
location =
|
524
|
+
if parts.empty?
|
525
|
+
find_token(LBracket).location.to(find_token(RBracket).location)
|
526
|
+
else
|
527
|
+
parts[0].location.to(parts[-1].location)
|
528
|
+
end
|
529
|
+
|
530
|
+
# If there's the optional then keyword, then we'll delete that and use it
|
531
|
+
# as the end bounds of the location.
|
532
|
+
if token = find_token(Kw, "then", consume: false)
|
533
|
+
tokens.delete(token)
|
534
|
+
location = location.to(token.location)
|
535
|
+
end
|
536
|
+
|
537
|
+
# If there is a plain *, then we're going to fix up the location of it
|
538
|
+
# here because it currently doesn't have anything to use for its precise
|
539
|
+
# location. If we hit a comma, then we've gone too far.
|
540
|
+
if rest.is_a?(VarField) && rest.value.nil?
|
541
|
+
tokens.rindex do |token|
|
542
|
+
case token
|
543
|
+
in Op[value: "*"]
|
544
|
+
rest = VarField.new(value: nil, location: token.location)
|
545
|
+
break
|
546
|
+
in Comma
|
547
|
+
break
|
548
|
+
else
|
549
|
+
end
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
506
553
|
AryPtn.new(
|
507
554
|
constant: constant,
|
508
555
|
requireds: requireds || [],
|
509
556
|
rest: rest,
|
510
557
|
posts: posts || [],
|
511
|
-
location:
|
558
|
+
location: location
|
512
559
|
)
|
513
560
|
end
|
514
561
|
|
@@ -551,7 +598,7 @@ module SyntaxTree
|
|
551
598
|
def on_backref(value)
|
552
599
|
Backref.new(
|
553
600
|
value: value,
|
554
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
601
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
555
602
|
)
|
556
603
|
end
|
557
604
|
|
@@ -561,7 +608,7 @@ module SyntaxTree
|
|
561
608
|
node =
|
562
609
|
Backtick.new(
|
563
610
|
value: value,
|
564
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
611
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
565
612
|
)
|
566
613
|
|
567
614
|
tokens << node
|
@@ -592,15 +639,20 @@ module SyntaxTree
|
|
592
639
|
PinnedBegin.new(statement: bodystmt, location: location)
|
593
640
|
else
|
594
641
|
keyword = find_token(Kw, "begin")
|
595
|
-
|
642
|
+
end_location =
|
596
643
|
if bodystmt.rescue_clause || bodystmt.ensure_clause ||
|
597
644
|
bodystmt.else_clause
|
598
|
-
bodystmt.location
|
645
|
+
bodystmt.location
|
599
646
|
else
|
600
|
-
find_token(Kw, "end").location
|
647
|
+
find_token(Kw, "end").location
|
601
648
|
end
|
602
649
|
|
603
|
-
bodystmt.bind(
|
650
|
+
bodystmt.bind(
|
651
|
+
keyword.location.end_char,
|
652
|
+
keyword.location.end_column,
|
653
|
+
end_location.end_char,
|
654
|
+
end_location.end_column
|
655
|
+
)
|
604
656
|
location = keyword.location.to(bodystmt.location)
|
605
657
|
|
606
658
|
Begin.new(bodystmt: bodystmt, location: location)
|
@@ -682,9 +734,10 @@ module SyntaxTree
|
|
682
734
|
BodyStmt.new(
|
683
735
|
statements: statements,
|
684
736
|
rescue_clause: rescue_clause,
|
737
|
+
else_keyword: else_clause && find_token(Kw, "else"),
|
685
738
|
else_clause: else_clause,
|
686
739
|
ensure_clause: ensure_clause,
|
687
|
-
location: Location.fixed(line: lineno, char: char_pos)
|
740
|
+
location: Location.fixed(line: lineno, char: char_pos, column: current_column)
|
688
741
|
)
|
689
742
|
end
|
690
743
|
|
@@ -696,18 +749,24 @@ module SyntaxTree
|
|
696
749
|
def on_brace_block(block_var, statements)
|
697
750
|
lbrace = find_token(LBrace)
|
698
751
|
rbrace = find_token(RBrace)
|
752
|
+
location = (block_var || lbrace).location
|
753
|
+
start_char = find_next_statement_start(location.end_char)
|
699
754
|
|
700
755
|
statements.bind(
|
701
|
-
|
702
|
-
|
756
|
+
start_char,
|
757
|
+
start_char - line_counts[location.start_line - 1].start,
|
758
|
+
rbrace.location.start_char,
|
759
|
+
rbrace.location.start_column
|
703
760
|
)
|
704
761
|
|
705
762
|
location =
|
706
763
|
Location.new(
|
707
764
|
start_line: lbrace.location.start_line,
|
708
765
|
start_char: lbrace.location.start_char,
|
766
|
+
start_column: lbrace.location.start_column,
|
709
767
|
end_line: [rbrace.location.end_line, statements.location.end_line].max,
|
710
|
-
end_char: rbrace.location.end_char
|
768
|
+
end_char: rbrace.location.end_char,
|
769
|
+
end_column: rbrace.location.end_column
|
711
770
|
)
|
712
771
|
|
713
772
|
BraceBlock.new(
|
@@ -736,8 +795,14 @@ module SyntaxTree
|
|
736
795
|
# (:call | Backtick | Const | Ident | Op) message
|
737
796
|
# ) -> Call
|
738
797
|
def on_call(receiver, operator, message)
|
739
|
-
ending =
|
740
|
-
|
798
|
+
ending =
|
799
|
+
if message != :call
|
800
|
+
message
|
801
|
+
elsif operator != :"::"
|
802
|
+
operator
|
803
|
+
else
|
804
|
+
receiver
|
805
|
+
end
|
741
806
|
|
742
807
|
Call.new(
|
743
808
|
receiver: receiver,
|
@@ -781,10 +846,14 @@ module SyntaxTree
|
|
781
846
|
def on_class(constant, superclass, bodystmt)
|
782
847
|
beginning = find_token(Kw, "class")
|
783
848
|
ending = find_token(Kw, "end")
|
849
|
+
location = (superclass || constant).location
|
850
|
+
start_char = find_next_statement_start(location.end_char)
|
784
851
|
|
785
852
|
bodystmt.bind(
|
786
|
-
|
787
|
-
|
853
|
+
start_char,
|
854
|
+
start_char - line_counts[location.start_line - 1].start,
|
855
|
+
ending.location.start_char,
|
856
|
+
ending.location.start_column
|
788
857
|
)
|
789
858
|
|
790
859
|
ClassDeclaration.new(
|
@@ -801,7 +870,7 @@ module SyntaxTree
|
|
801
870
|
node =
|
802
871
|
Comma.new(
|
803
872
|
value: value,
|
804
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
873
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
805
874
|
)
|
806
875
|
|
807
876
|
tokens << node
|
@@ -846,7 +915,7 @@ module SyntaxTree
|
|
846
915
|
value: value.chomp,
|
847
916
|
inline: value.strip != lines[line - 1].strip,
|
848
917
|
location:
|
849
|
-
Location.token(line: line, char: char_pos, size: value.size - 1)
|
918
|
+
Location.token(line: line, char: char_pos, column: current_column, size: value.size - 1)
|
850
919
|
)
|
851
920
|
|
852
921
|
@comments << comment
|
@@ -858,7 +927,7 @@ module SyntaxTree
|
|
858
927
|
def on_const(value)
|
859
928
|
Const.new(
|
860
929
|
value: value,
|
861
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
930
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
862
931
|
)
|
863
932
|
end
|
864
933
|
|
@@ -893,7 +962,7 @@ module SyntaxTree
|
|
893
962
|
def on_cvar(value)
|
894
963
|
CVar.new(
|
895
964
|
value: value,
|
896
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
965
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
897
966
|
)
|
898
967
|
end
|
899
968
|
|
@@ -917,12 +986,15 @@ module SyntaxTree
|
|
917
986
|
# location information
|
918
987
|
if params.is_a?(Params) && params.empty?
|
919
988
|
end_char = name.location.end_char
|
989
|
+
end_column = name.location.end_column
|
920
990
|
location =
|
921
991
|
Location.new(
|
922
992
|
start_line: params.location.start_line,
|
923
993
|
start_char: end_char,
|
994
|
+
start_column: end_column,
|
924
995
|
end_line: params.location.end_line,
|
925
|
-
end_char: end_char
|
996
|
+
end_char: end_char,
|
997
|
+
end_column: end_column
|
926
998
|
)
|
927
999
|
|
928
1000
|
params = Params.new(location: location)
|
@@ -932,9 +1004,13 @@ module SyntaxTree
|
|
932
1004
|
|
933
1005
|
if ending
|
934
1006
|
tokens.delete(ending)
|
1007
|
+
start_char = find_next_statement_start(params.location.end_char)
|
1008
|
+
|
935
1009
|
bodystmt.bind(
|
936
|
-
|
937
|
-
|
1010
|
+
start_char,
|
1011
|
+
start_char - line_counts[params.location.start_line - 1].start,
|
1012
|
+
ending.location.start_char,
|
1013
|
+
ending.location.start_column
|
938
1014
|
)
|
939
1015
|
|
940
1016
|
Def.new(
|
@@ -992,12 +1068,15 @@ module SyntaxTree
|
|
992
1068
|
# location information
|
993
1069
|
if params.is_a?(Params) && params.empty?
|
994
1070
|
end_char = name.location.end_char
|
1071
|
+
end_column = name.location.end_column
|
995
1072
|
location =
|
996
1073
|
Location.new(
|
997
1074
|
start_line: params.location.start_line,
|
998
1075
|
start_char: end_char,
|
1076
|
+
start_column: end_column,
|
999
1077
|
end_line: params.location.end_line,
|
1000
|
-
end_char: end_char
|
1078
|
+
end_char: end_char,
|
1079
|
+
end_column: end_column
|
1001
1080
|
)
|
1002
1081
|
|
1003
1082
|
params = Params.new(location: location)
|
@@ -1008,9 +1087,13 @@ module SyntaxTree
|
|
1008
1087
|
|
1009
1088
|
if ending
|
1010
1089
|
tokens.delete(ending)
|
1090
|
+
start_char = find_next_statement_start(params.location.end_char)
|
1091
|
+
|
1011
1092
|
bodystmt.bind(
|
1012
|
-
|
1013
|
-
|
1093
|
+
start_char,
|
1094
|
+
start_char - line_counts[params.location.start_line - 1].start,
|
1095
|
+
ending.location.start_char,
|
1096
|
+
ending.location.start_column
|
1014
1097
|
)
|
1015
1098
|
|
1016
1099
|
Defs.new(
|
@@ -1042,10 +1125,14 @@ module SyntaxTree
|
|
1042
1125
|
def on_do_block(block_var, bodystmt)
|
1043
1126
|
beginning = find_token(Kw, "do")
|
1044
1127
|
ending = find_token(Kw, "end")
|
1128
|
+
location = (block_var || beginning).location
|
1129
|
+
start_char = find_next_statement_start(location.end_char)
|
1045
1130
|
|
1046
1131
|
bodystmt.bind(
|
1047
|
-
|
1048
|
-
|
1132
|
+
start_char,
|
1133
|
+
start_char - line_counts[location.start_line - 1].start,
|
1134
|
+
ending.location.start_char,
|
1135
|
+
ending.location.start_column
|
1049
1136
|
)
|
1050
1137
|
|
1051
1138
|
DoBlock.new(
|
@@ -1115,7 +1202,7 @@ module SyntaxTree
|
|
1115
1202
|
# :call-seq:
|
1116
1203
|
# on_else: (Statements statements) -> Else
|
1117
1204
|
def on_else(statements)
|
1118
|
-
|
1205
|
+
keyword = find_token(Kw, "else")
|
1119
1206
|
|
1120
1207
|
# else can either end with an end keyword (in which case we'll want to
|
1121
1208
|
# consume that event) or it can end with an ensure keyword (in which case
|
@@ -1127,13 +1214,19 @@ module SyntaxTree
|
|
1127
1214
|
|
1128
1215
|
node = tokens[index]
|
1129
1216
|
ending = node.value == "end" ? tokens.delete_at(index) : node
|
1130
|
-
|
1217
|
+
start_char = find_next_statement_start(keyword.location.end_char)
|
1131
1218
|
|
1132
|
-
statements.bind(
|
1219
|
+
statements.bind(
|
1220
|
+
start_char,
|
1221
|
+
start_char - line_counts[keyword.location.start_line - 1].start,
|
1222
|
+
ending.location.start_char,
|
1223
|
+
ending.location.start_column
|
1224
|
+
)
|
1133
1225
|
|
1134
1226
|
Else.new(
|
1227
|
+
keyword: keyword,
|
1135
1228
|
statements: statements,
|
1136
|
-
location:
|
1229
|
+
location: keyword.location.to(ending.location)
|
1137
1230
|
)
|
1138
1231
|
end
|
1139
1232
|
|
@@ -1147,7 +1240,12 @@ module SyntaxTree
|
|
1147
1240
|
beginning = find_token(Kw, "elsif")
|
1148
1241
|
ending = consequent || find_token(Kw, "end")
|
1149
1242
|
|
1150
|
-
statements.bind(
|
1243
|
+
statements.bind(
|
1244
|
+
predicate.location.end_char,
|
1245
|
+
predicate.location.end_column,
|
1246
|
+
ending.location.start_char,
|
1247
|
+
ending.location.start_column
|
1248
|
+
)
|
1151
1249
|
|
1152
1250
|
Elsif.new(
|
1153
1251
|
predicate: predicate,
|
@@ -1170,7 +1268,7 @@ module SyntaxTree
|
|
1170
1268
|
@embdoc =
|
1171
1269
|
EmbDoc.new(
|
1172
1270
|
value: value,
|
1173
|
-
location: Location.fixed(line: lineno, char: char_pos)
|
1271
|
+
location: Location.fixed(line: lineno, column: current_column, char: char_pos)
|
1174
1272
|
)
|
1175
1273
|
end
|
1176
1274
|
|
@@ -1185,8 +1283,10 @@ module SyntaxTree
|
|
1185
1283
|
Location.new(
|
1186
1284
|
start_line: location.start_line,
|
1187
1285
|
start_char: location.start_char,
|
1286
|
+
start_column: location.start_column,
|
1188
1287
|
end_line: lineno,
|
1189
|
-
end_char: char_pos + value.length - 1
|
1288
|
+
end_char: char_pos + value.length - 1,
|
1289
|
+
end_column: current_column + value.length - 1
|
1190
1290
|
)
|
1191
1291
|
)
|
1192
1292
|
|
@@ -1202,7 +1302,7 @@ module SyntaxTree
|
|
1202
1302
|
node =
|
1203
1303
|
EmbExprBeg.new(
|
1204
1304
|
value: value,
|
1205
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1305
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1206
1306
|
)
|
1207
1307
|
|
1208
1308
|
tokens << node
|
@@ -1215,7 +1315,7 @@ module SyntaxTree
|
|
1215
1315
|
node =
|
1216
1316
|
EmbExprEnd.new(
|
1217
1317
|
value: value,
|
1218
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1318
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1219
1319
|
)
|
1220
1320
|
|
1221
1321
|
tokens << node
|
@@ -1228,7 +1328,7 @@ module SyntaxTree
|
|
1228
1328
|
node =
|
1229
1329
|
EmbVar.new(
|
1230
1330
|
value: value,
|
1231
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1331
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1232
1332
|
)
|
1233
1333
|
|
1234
1334
|
tokens << node
|
@@ -1243,9 +1343,12 @@ module SyntaxTree
|
|
1243
1343
|
# We don't want to consume the :@kw event, because that would break
|
1244
1344
|
# def..ensure..end chains.
|
1245
1345
|
ending = find_token(Kw, "end", consume: false)
|
1346
|
+
start_char = find_next_statement_start(keyword.location.end_char)
|
1246
1347
|
statements.bind(
|
1247
|
-
|
1248
|
-
|
1348
|
+
start_char,
|
1349
|
+
start_char - line_counts[keyword.location.start_line - 1].start,
|
1350
|
+
ending.location.start_char,
|
1351
|
+
ending.location.start_column
|
1249
1352
|
)
|
1250
1353
|
|
1251
1354
|
Ensure.new(
|
@@ -1292,7 +1395,7 @@ module SyntaxTree
|
|
1292
1395
|
def on_float(value)
|
1293
1396
|
FloatLiteral.new(
|
1294
1397
|
value: value,
|
1295
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1398
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1296
1399
|
)
|
1297
1400
|
end
|
1298
1401
|
|
@@ -1304,15 +1407,35 @@ module SyntaxTree
|
|
1304
1407
|
# VarField right
|
1305
1408
|
# ) -> FndPtn
|
1306
1409
|
def on_fndptn(constant, left, values, right)
|
1307
|
-
|
1308
|
-
|
1410
|
+
# The opening of this find pattern is either going to be a left bracket, a
|
1411
|
+
# right left parenthesis, or the left splat. We're going to use this to
|
1412
|
+
# determine how to find the closing of the pattern, as well as determining
|
1413
|
+
# the location of the node.
|
1414
|
+
opening =
|
1415
|
+
find_token(LBracket, consume: false) ||
|
1416
|
+
find_token(LParen, consume: false) ||
|
1417
|
+
left
|
1418
|
+
|
1419
|
+
# The closing is based on the opening, which is either the matched
|
1420
|
+
# punctuation or the right splat.
|
1421
|
+
closing =
|
1422
|
+
case opening
|
1423
|
+
in LBracket
|
1424
|
+
tokens.delete(opening)
|
1425
|
+
find_token(RBracket)
|
1426
|
+
in LParen
|
1427
|
+
tokens.delete(opening)
|
1428
|
+
find_token(RParen)
|
1429
|
+
else
|
1430
|
+
right
|
1431
|
+
end
|
1309
1432
|
|
1310
1433
|
FndPtn.new(
|
1311
1434
|
constant: constant,
|
1312
1435
|
left: left,
|
1313
1436
|
values: values,
|
1314
1437
|
right: right,
|
1315
|
-
location:
|
1438
|
+
location: (constant || opening).location.to(closing.location)
|
1316
1439
|
)
|
1317
1440
|
end
|
1318
1441
|
|
@@ -1337,7 +1460,9 @@ module SyntaxTree
|
|
1337
1460
|
|
1338
1461
|
statements.bind(
|
1339
1462
|
(keyword || collection).location.end_char,
|
1340
|
-
|
1463
|
+
(keyword || collection).location.end_column,
|
1464
|
+
ending.location.start_char,
|
1465
|
+
ending.location.start_column
|
1341
1466
|
)
|
1342
1467
|
|
1343
1468
|
if index.is_a?(MLHS)
|
@@ -1358,7 +1483,7 @@ module SyntaxTree
|
|
1358
1483
|
def on_gvar(value)
|
1359
1484
|
GVar.new(
|
1360
1485
|
value: value,
|
1361
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1486
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1362
1487
|
)
|
1363
1488
|
end
|
1364
1489
|
|
@@ -1379,7 +1504,7 @@ module SyntaxTree
|
|
1379
1504
|
# on_heredoc_beg: (String value) -> HeredocBeg
|
1380
1505
|
def on_heredoc_beg(value)
|
1381
1506
|
location =
|
1382
|
-
Location.token(line: lineno, char: char_pos, size: value.size + 1)
|
1507
|
+
Location.token(line: lineno, char: char_pos, column: current_column, size: value.size + 1)
|
1383
1508
|
|
1384
1509
|
# Here we're going to artificially create an extra node type so that if
|
1385
1510
|
# there are comments after the declaration of a heredoc, they get printed.
|
@@ -1397,6 +1522,7 @@ module SyntaxTree
|
|
1397
1522
|
@heredocs[-1] = Heredoc.new(
|
1398
1523
|
beginning: heredoc.beginning,
|
1399
1524
|
ending: heredoc.ending,
|
1525
|
+
dedent: width,
|
1400
1526
|
parts: string.parts,
|
1401
1527
|
location: heredoc.location
|
1402
1528
|
)
|
@@ -1410,13 +1536,16 @@ module SyntaxTree
|
|
1410
1536
|
@heredocs[-1] = Heredoc.new(
|
1411
1537
|
beginning: heredoc.beginning,
|
1412
1538
|
ending: value.chomp,
|
1539
|
+
dedent: heredoc.dedent,
|
1413
1540
|
parts: heredoc.parts,
|
1414
1541
|
location:
|
1415
1542
|
Location.new(
|
1416
1543
|
start_line: heredoc.location.start_line,
|
1417
1544
|
start_char: heredoc.location.start_char,
|
1545
|
+
start_column: heredoc.location.start_column,
|
1418
1546
|
end_line: lineno,
|
1419
|
-
end_char: char_pos
|
1547
|
+
end_char: char_pos,
|
1548
|
+
end_column: current_column,
|
1420
1549
|
)
|
1421
1550
|
)
|
1422
1551
|
end
|
@@ -1428,13 +1557,30 @@ module SyntaxTree
|
|
1428
1557
|
# (nil | VarField) keyword_rest
|
1429
1558
|
# ) -> HshPtn
|
1430
1559
|
def on_hshptn(constant, keywords, keyword_rest)
|
1431
|
-
|
1560
|
+
# Create an artificial VarField if we find an extra ** on the end
|
1561
|
+
if !keyword_rest && (token = find_token(Op, "**", consume: false))
|
1562
|
+
tokens.delete(token)
|
1563
|
+
keyword_rest = VarField.new(value: nil, location: token.location)
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
# Delete the optional then keyword
|
1567
|
+
if token = find_token(Kw, "then", consume: false)
|
1568
|
+
tokens.delete(token)
|
1569
|
+
end
|
1570
|
+
|
1571
|
+
parts = [constant, *keywords&.flatten(1), keyword_rest].compact
|
1572
|
+
location =
|
1573
|
+
if parts.any?
|
1574
|
+
parts[0].location.to(parts[-1].location)
|
1575
|
+
else
|
1576
|
+
find_token(LBrace).location.to(find_token(RBrace).location)
|
1577
|
+
end
|
1432
1578
|
|
1433
1579
|
HshPtn.new(
|
1434
1580
|
constant: constant,
|
1435
|
-
keywords: keywords,
|
1581
|
+
keywords: keywords || [],
|
1436
1582
|
keyword_rest: keyword_rest,
|
1437
|
-
location:
|
1583
|
+
location: location
|
1438
1584
|
)
|
1439
1585
|
end
|
1440
1586
|
|
@@ -1443,7 +1589,7 @@ module SyntaxTree
|
|
1443
1589
|
def on_ident(value)
|
1444
1590
|
Ident.new(
|
1445
1591
|
value: value,
|
1446
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1592
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1447
1593
|
)
|
1448
1594
|
end
|
1449
1595
|
|
@@ -1457,7 +1603,12 @@ module SyntaxTree
|
|
1457
1603
|
beginning = find_token(Kw, "if")
|
1458
1604
|
ending = consequent || find_token(Kw, "end")
|
1459
1605
|
|
1460
|
-
statements.bind(
|
1606
|
+
statements.bind(
|
1607
|
+
predicate.location.end_char,
|
1608
|
+
predicate.location.end_column,
|
1609
|
+
ending.location.start_char,
|
1610
|
+
ending.location.start_column
|
1611
|
+
)
|
1461
1612
|
|
1462
1613
|
If.new(
|
1463
1614
|
predicate: predicate,
|
@@ -1503,7 +1654,7 @@ module SyntaxTree
|
|
1503
1654
|
def on_imaginary(value)
|
1504
1655
|
Imaginary.new(
|
1505
1656
|
value: value,
|
1506
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1657
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1507
1658
|
)
|
1508
1659
|
end
|
1509
1660
|
|
@@ -1527,9 +1678,12 @@ module SyntaxTree
|
|
1527
1678
|
statements_start = token
|
1528
1679
|
end
|
1529
1680
|
|
1681
|
+
start_char = find_next_statement_start(statements_start.location.end_char)
|
1530
1682
|
statements.bind(
|
1531
|
-
|
1532
|
-
|
1683
|
+
start_char,
|
1684
|
+
start_char - line_counts[statements_start.location.start_line - 1].start,
|
1685
|
+
ending.location.start_char,
|
1686
|
+
ending.location.start_column
|
1533
1687
|
)
|
1534
1688
|
|
1535
1689
|
In.new(
|
@@ -1545,7 +1699,7 @@ module SyntaxTree
|
|
1545
1699
|
def on_int(value)
|
1546
1700
|
Int.new(
|
1547
1701
|
value: value,
|
1548
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1702
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1549
1703
|
)
|
1550
1704
|
end
|
1551
1705
|
|
@@ -1554,7 +1708,7 @@ module SyntaxTree
|
|
1554
1708
|
def on_ivar(value)
|
1555
1709
|
IVar.new(
|
1556
1710
|
value: value,
|
1557
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1711
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1558
1712
|
)
|
1559
1713
|
end
|
1560
1714
|
|
@@ -1564,7 +1718,7 @@ module SyntaxTree
|
|
1564
1718
|
node =
|
1565
1719
|
Kw.new(
|
1566
1720
|
value: value,
|
1567
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1721
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1568
1722
|
)
|
1569
1723
|
|
1570
1724
|
tokens << node
|
@@ -1585,7 +1739,7 @@ module SyntaxTree
|
|
1585
1739
|
def on_label(value)
|
1586
1740
|
Label.new(
|
1587
1741
|
value: value,
|
1588
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1742
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1589
1743
|
)
|
1590
1744
|
end
|
1591
1745
|
|
@@ -1595,7 +1749,7 @@ module SyntaxTree
|
|
1595
1749
|
node =
|
1596
1750
|
LabelEnd.new(
|
1597
1751
|
value: value,
|
1598
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1752
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1599
1753
|
)
|
1600
1754
|
|
1601
1755
|
tokens << node
|
@@ -1621,7 +1775,12 @@ module SyntaxTree
|
|
1621
1775
|
closing = find_token(Kw, "end")
|
1622
1776
|
end
|
1623
1777
|
|
1624
|
-
statements.bind(
|
1778
|
+
statements.bind(
|
1779
|
+
opening.location.end_char,
|
1780
|
+
opening.location.end_column,
|
1781
|
+
closing.location.start_char,
|
1782
|
+
closing.location.start_column
|
1783
|
+
)
|
1625
1784
|
|
1626
1785
|
Lambda.new(
|
1627
1786
|
params: params,
|
@@ -1636,7 +1795,7 @@ module SyntaxTree
|
|
1636
1795
|
node =
|
1637
1796
|
LBrace.new(
|
1638
1797
|
value: value,
|
1639
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1798
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1640
1799
|
)
|
1641
1800
|
|
1642
1801
|
tokens << node
|
@@ -1649,7 +1808,7 @@ module SyntaxTree
|
|
1649
1808
|
node =
|
1650
1809
|
LBracket.new(
|
1651
1810
|
value: value,
|
1652
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1811
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1653
1812
|
)
|
1654
1813
|
|
1655
1814
|
tokens << node
|
@@ -1662,7 +1821,7 @@ module SyntaxTree
|
|
1662
1821
|
node =
|
1663
1822
|
LParen.new(
|
1664
1823
|
value: value,
|
1665
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
1824
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1666
1825
|
)
|
1667
1826
|
|
1668
1827
|
tokens << node
|
@@ -1761,7 +1920,7 @@ module SyntaxTree
|
|
1761
1920
|
# :call-seq:
|
1762
1921
|
# on_mlhs_new: () -> MLHS
|
1763
1922
|
def on_mlhs_new
|
1764
|
-
MLHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
|
1923
|
+
MLHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos, column: current_column))
|
1765
1924
|
end
|
1766
1925
|
|
1767
1926
|
# :call-seq:
|
@@ -1787,10 +1946,13 @@ module SyntaxTree
|
|
1787
1946
|
def on_module(constant, bodystmt)
|
1788
1947
|
beginning = find_token(Kw, "module")
|
1789
1948
|
ending = find_token(Kw, "end")
|
1949
|
+
start_char = find_next_statement_start(constant.location.end_char)
|
1790
1950
|
|
1791
1951
|
bodystmt.bind(
|
1792
|
-
|
1793
|
-
|
1952
|
+
start_char,
|
1953
|
+
start_char - line_counts[constant.location.start_line - 1].start,
|
1954
|
+
ending.location.start_char,
|
1955
|
+
ending.location.start_column
|
1794
1956
|
)
|
1795
1957
|
|
1796
1958
|
ModuleDeclaration.new(
|
@@ -1803,7 +1965,7 @@ module SyntaxTree
|
|
1803
1965
|
# :call-seq:
|
1804
1966
|
# on_mrhs_new: () -> MRHS
|
1805
1967
|
def on_mrhs_new
|
1806
|
-
MRHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
|
1968
|
+
MRHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos, column: current_column))
|
1807
1969
|
end
|
1808
1970
|
|
1809
1971
|
# :call-seq:
|
@@ -1872,7 +2034,7 @@ module SyntaxTree
|
|
1872
2034
|
node =
|
1873
2035
|
Op.new(
|
1874
2036
|
value: value,
|
1875
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2037
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
1876
2038
|
)
|
1877
2039
|
|
1878
2040
|
tokens << node
|
@@ -1931,7 +2093,7 @@ module SyntaxTree
|
|
1931
2093
|
if parts.any?
|
1932
2094
|
parts[0].location.to(parts[-1].location)
|
1933
2095
|
else
|
1934
|
-
Location.fixed(line: lineno, char: char_pos)
|
2096
|
+
Location.fixed(line: lineno, char: char_pos, column: current_column)
|
1935
2097
|
end
|
1936
2098
|
|
1937
2099
|
Params.new(
|
@@ -1954,12 +2116,15 @@ module SyntaxTree
|
|
1954
2116
|
|
1955
2117
|
if contents && contents.is_a?(Params)
|
1956
2118
|
location = contents.location
|
2119
|
+
start_char = find_next_statement_start(lparen.location.end_char)
|
1957
2120
|
location =
|
1958
2121
|
Location.new(
|
1959
2122
|
start_line: location.start_line,
|
1960
|
-
start_char:
|
2123
|
+
start_char: start_char,
|
2124
|
+
start_column: start_char - line_counts[lparen.location.start_line - 1].start,
|
1961
2125
|
end_line: location.end_line,
|
1962
|
-
end_char: rparen.location.start_char
|
2126
|
+
end_char: rparen.location.start_char,
|
2127
|
+
end_column: rparen.location.start_column
|
1963
2128
|
)
|
1964
2129
|
|
1965
2130
|
contents =
|
@@ -1997,23 +2162,26 @@ module SyntaxTree
|
|
1997
2162
|
def on_period(value)
|
1998
2163
|
Period.new(
|
1999
2164
|
value: value,
|
2000
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2165
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2001
2166
|
)
|
2002
2167
|
end
|
2003
2168
|
|
2004
2169
|
# :call-seq:
|
2005
2170
|
# on_program: (Statements statements) -> Program
|
2006
2171
|
def on_program(statements)
|
2172
|
+
last_column = source.length - line_counts[lines.length - 1].start
|
2007
2173
|
location =
|
2008
2174
|
Location.new(
|
2009
2175
|
start_line: 1,
|
2010
2176
|
start_char: 0,
|
2177
|
+
start_column: 0,
|
2011
2178
|
end_line: lines.length,
|
2012
|
-
end_char: source.length
|
2179
|
+
end_char: source.length,
|
2180
|
+
end_column: last_column
|
2013
2181
|
)
|
2014
2182
|
|
2015
2183
|
statements.body << @__end__ if @__end__
|
2016
|
-
statements.bind(0, source.length)
|
2184
|
+
statements.bind(0, 0, source.length, last_column)
|
2017
2185
|
|
2018
2186
|
program = Program.new(statements: statements, location: location)
|
2019
2187
|
attach_comments(program, @comments)
|
@@ -2126,7 +2294,7 @@ module SyntaxTree
|
|
2126
2294
|
node =
|
2127
2295
|
QSymbolsBeg.new(
|
2128
2296
|
value: value,
|
2129
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2297
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2130
2298
|
)
|
2131
2299
|
|
2132
2300
|
tokens << node
|
@@ -2161,7 +2329,7 @@ module SyntaxTree
|
|
2161
2329
|
node =
|
2162
2330
|
QWordsBeg.new(
|
2163
2331
|
value: value,
|
2164
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2332
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2165
2333
|
)
|
2166
2334
|
|
2167
2335
|
tokens << node
|
@@ -2181,7 +2349,7 @@ module SyntaxTree
|
|
2181
2349
|
def on_rational(value)
|
2182
2350
|
RationalLiteral.new(
|
2183
2351
|
value: value,
|
2184
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2352
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2185
2353
|
)
|
2186
2354
|
end
|
2187
2355
|
|
@@ -2191,7 +2359,7 @@ module SyntaxTree
|
|
2191
2359
|
node =
|
2192
2360
|
RBrace.new(
|
2193
2361
|
value: value,
|
2194
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2362
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2195
2363
|
)
|
2196
2364
|
|
2197
2365
|
tokens << node
|
@@ -2204,7 +2372,7 @@ module SyntaxTree
|
|
2204
2372
|
node =
|
2205
2373
|
RBracket.new(
|
2206
2374
|
value: value,
|
2207
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2375
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2208
2376
|
)
|
2209
2377
|
|
2210
2378
|
tokens << node
|
@@ -2238,7 +2406,7 @@ module SyntaxTree
|
|
2238
2406
|
node =
|
2239
2407
|
RegexpBeg.new(
|
2240
2408
|
value: value,
|
2241
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2409
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2242
2410
|
)
|
2243
2411
|
|
2244
2412
|
tokens << node
|
@@ -2250,7 +2418,7 @@ module SyntaxTree
|
|
2250
2418
|
def on_regexp_end(value)
|
2251
2419
|
RegexpEnd.new(
|
2252
2420
|
value: value,
|
2253
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2421
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2254
2422
|
)
|
2255
2423
|
end
|
2256
2424
|
|
@@ -2292,9 +2460,12 @@ module SyntaxTree
|
|
2292
2460
|
exceptions = exceptions[0] if exceptions.is_a?(Array)
|
2293
2461
|
|
2294
2462
|
last_node = variable || exceptions || keyword
|
2463
|
+
start_char = find_next_statement_start(last_node.location.end_char)
|
2295
2464
|
statements.bind(
|
2296
|
-
|
2297
|
-
|
2465
|
+
start_char,
|
2466
|
+
start_char - line_counts[last_node.location.start_line - 1].start,
|
2467
|
+
char_pos,
|
2468
|
+
current_column
|
2298
2469
|
)
|
2299
2470
|
|
2300
2471
|
# We add an additional inner node here that ripper doesn't provide so that
|
@@ -2309,13 +2480,16 @@ module SyntaxTree
|
|
2309
2480
|
Location.new(
|
2310
2481
|
start_line: keyword.location.start_line,
|
2311
2482
|
start_char: keyword.location.end_char + 1,
|
2483
|
+
start_column: keyword.location.end_column + 1,
|
2312
2484
|
end_line: last_node.location.end_line,
|
2313
|
-
end_char: last_node.location.end_char
|
2485
|
+
end_char: last_node.location.end_char,
|
2486
|
+
end_column: last_node.location.end_column
|
2314
2487
|
)
|
2315
2488
|
)
|
2316
2489
|
end
|
2317
2490
|
|
2318
2491
|
Rescue.new(
|
2492
|
+
keyword: keyword,
|
2319
2493
|
exception: rescue_ex,
|
2320
2494
|
statements: statements,
|
2321
2495
|
consequent: consequent,
|
@@ -2323,8 +2497,10 @@ module SyntaxTree
|
|
2323
2497
|
Location.new(
|
2324
2498
|
start_line: keyword.location.start_line,
|
2325
2499
|
start_char: keyword.location.start_char,
|
2500
|
+
start_column: keyword.location.start_column,
|
2326
2501
|
end_line: lineno,
|
2327
|
-
end_char: char_pos
|
2502
|
+
end_char: char_pos,
|
2503
|
+
end_column: current_column
|
2328
2504
|
)
|
2329
2505
|
)
|
2330
2506
|
end
|
@@ -2383,7 +2559,7 @@ module SyntaxTree
|
|
2383
2559
|
node =
|
2384
2560
|
RParen.new(
|
2385
2561
|
value: value,
|
2386
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2562
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2387
2563
|
)
|
2388
2564
|
|
2389
2565
|
tokens << node
|
@@ -2395,10 +2571,13 @@ module SyntaxTree
|
|
2395
2571
|
def on_sclass(target, bodystmt)
|
2396
2572
|
beginning = find_token(Kw, "class")
|
2397
2573
|
ending = find_token(Kw, "end")
|
2574
|
+
start_char = find_next_statement_start(target.location.end_char)
|
2398
2575
|
|
2399
2576
|
bodystmt.bind(
|
2400
|
-
|
2401
|
-
|
2577
|
+
start_char,
|
2578
|
+
start_char - line_counts[target.location.start_line - 1].start,
|
2579
|
+
ending.location.start_char,
|
2580
|
+
ending.location.start_column
|
2402
2581
|
)
|
2403
2582
|
|
2404
2583
|
SClass.new(
|
@@ -2437,7 +2616,7 @@ module SyntaxTree
|
|
2437
2616
|
Statements.new(
|
2438
2617
|
self,
|
2439
2618
|
body: [],
|
2440
|
-
location: Location.fixed(line: lineno, char: char_pos)
|
2619
|
+
location: Location.fixed(line: lineno, char: char_pos, column: current_column)
|
2441
2620
|
)
|
2442
2621
|
end
|
2443
2622
|
|
@@ -2471,7 +2650,7 @@ module SyntaxTree
|
|
2471
2650
|
def on_string_content
|
2472
2651
|
StringContent.new(
|
2473
2652
|
parts: [],
|
2474
|
-
location: Location.fixed(line: lineno, char: char_pos)
|
2653
|
+
location: Location.fixed(line: lineno, char: char_pos, column: current_column)
|
2475
2654
|
)
|
2476
2655
|
end
|
2477
2656
|
|
@@ -2494,18 +2673,22 @@ module SyntaxTree
|
|
2494
2673
|
|
2495
2674
|
statements.bind(
|
2496
2675
|
embexpr_beg.location.end_char,
|
2497
|
-
|
2676
|
+
embexpr_beg.location.end_column,
|
2677
|
+
embexpr_end.location.start_char,
|
2678
|
+
embexpr_end.location.start_column
|
2498
2679
|
)
|
2499
2680
|
|
2500
2681
|
location =
|
2501
2682
|
Location.new(
|
2502
2683
|
start_line: embexpr_beg.location.start_line,
|
2503
2684
|
start_char: embexpr_beg.location.start_char,
|
2685
|
+
start_column: embexpr_beg.location.start_column,
|
2504
2686
|
end_line: [
|
2505
2687
|
embexpr_end.location.end_line,
|
2506
2688
|
statements.location.end_line
|
2507
2689
|
].max,
|
2508
|
-
end_char: embexpr_end.location.end_char
|
2690
|
+
end_char: embexpr_end.location.end_char,
|
2691
|
+
end_column: embexpr_end.location.end_column
|
2509
2692
|
)
|
2510
2693
|
|
2511
2694
|
StringEmbExpr.new(statements: statements, location: location)
|
@@ -2522,6 +2705,7 @@ module SyntaxTree
|
|
2522
2705
|
Heredoc.new(
|
2523
2706
|
beginning: heredoc.beginning,
|
2524
2707
|
ending: heredoc.ending,
|
2708
|
+
dedent: heredoc.dedent,
|
2525
2709
|
parts: string.parts,
|
2526
2710
|
location: heredoc.location
|
2527
2711
|
)
|
@@ -2533,11 +2717,13 @@ module SyntaxTree
|
|
2533
2717
|
Location.new(
|
2534
2718
|
start_line: tstring_beg.location.start_line,
|
2535
2719
|
start_char: tstring_beg.location.start_char,
|
2720
|
+
start_column: tstring_beg.location.start_column,
|
2536
2721
|
end_line: [
|
2537
2722
|
tstring_end.location.end_line,
|
2538
2723
|
string.location.end_line
|
2539
2724
|
].max,
|
2540
|
-
end_char: tstring_end.location.end_char
|
2725
|
+
end_char: tstring_end.location.end_char,
|
2726
|
+
end_column: tstring_end.location.end_column
|
2541
2727
|
)
|
2542
2728
|
|
2543
2729
|
StringLiteral.new(
|
@@ -2566,7 +2752,7 @@ module SyntaxTree
|
|
2566
2752
|
node =
|
2567
2753
|
SymBeg.new(
|
2568
2754
|
value: value,
|
2569
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2755
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2570
2756
|
)
|
2571
2757
|
|
2572
2758
|
tokens << node
|
@@ -2620,7 +2806,7 @@ module SyntaxTree
|
|
2620
2806
|
node =
|
2621
2807
|
SymbolsBeg.new(
|
2622
2808
|
value: value,
|
2623
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2809
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2624
2810
|
)
|
2625
2811
|
|
2626
2812
|
tokens << node
|
@@ -2645,7 +2831,7 @@ module SyntaxTree
|
|
2645
2831
|
node =
|
2646
2832
|
TLambda.new(
|
2647
2833
|
value: value,
|
2648
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2834
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2649
2835
|
)
|
2650
2836
|
|
2651
2837
|
tokens << node
|
@@ -2658,7 +2844,7 @@ module SyntaxTree
|
|
2658
2844
|
node =
|
2659
2845
|
TLamBeg.new(
|
2660
2846
|
value: value,
|
2661
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2847
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2662
2848
|
)
|
2663
2849
|
|
2664
2850
|
tokens << node
|
@@ -2693,7 +2879,7 @@ module SyntaxTree
|
|
2693
2879
|
node =
|
2694
2880
|
TStringBeg.new(
|
2695
2881
|
value: value,
|
2696
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2882
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2697
2883
|
)
|
2698
2884
|
|
2699
2885
|
tokens << node
|
@@ -2705,7 +2891,7 @@ module SyntaxTree
|
|
2705
2891
|
def on_tstring_content(value)
|
2706
2892
|
TStringContent.new(
|
2707
2893
|
value: value,
|
2708
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2894
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2709
2895
|
)
|
2710
2896
|
end
|
2711
2897
|
|
@@ -2715,7 +2901,7 @@ module SyntaxTree
|
|
2715
2901
|
node =
|
2716
2902
|
TStringEnd.new(
|
2717
2903
|
value: value,
|
2718
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
2904
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
2719
2905
|
)
|
2720
2906
|
|
2721
2907
|
tokens << node
|
@@ -2731,19 +2917,17 @@ module SyntaxTree
|
|
2731
2917
|
# parentheses they don't get reported as a paren node for some reason.
|
2732
2918
|
|
2733
2919
|
beginning = find_token(Kw, "not")
|
2734
|
-
ending = statement
|
2735
|
-
|
2736
|
-
range = beginning.location.end_char...statement.location.start_char
|
2737
|
-
paren = source[range].include?("(")
|
2920
|
+
ending = statement || beginning
|
2921
|
+
parentheses = source[beginning.location.end_char] == "("
|
2738
2922
|
|
2739
|
-
if
|
2923
|
+
if parentheses
|
2740
2924
|
find_token(LParen)
|
2741
2925
|
ending = find_token(RParen)
|
2742
2926
|
end
|
2743
2927
|
|
2744
2928
|
Not.new(
|
2745
2929
|
statement: statement,
|
2746
|
-
parentheses:
|
2930
|
+
parentheses: parentheses,
|
2747
2931
|
location: beginning.location.to(ending.location)
|
2748
2932
|
)
|
2749
2933
|
else
|
@@ -2789,7 +2973,12 @@ module SyntaxTree
|
|
2789
2973
|
beginning = find_token(Kw, "unless")
|
2790
2974
|
ending = consequent || find_token(Kw, "end")
|
2791
2975
|
|
2792
|
-
statements.bind(
|
2976
|
+
statements.bind(
|
2977
|
+
predicate.location.end_char,
|
2978
|
+
predicate.location.end_column,
|
2979
|
+
ending.location.start_char,
|
2980
|
+
ending.location.start_column
|
2981
|
+
)
|
2793
2982
|
|
2794
2983
|
Unless.new(
|
2795
2984
|
predicate: predicate,
|
@@ -2826,7 +3015,12 @@ module SyntaxTree
|
|
2826
3015
|
end
|
2827
3016
|
|
2828
3017
|
# Update the Statements location information
|
2829
|
-
statements.bind(
|
3018
|
+
statements.bind(
|
3019
|
+
predicate.location.end_char,
|
3020
|
+
predicate.location.end_column,
|
3021
|
+
ending.location.start_char,
|
3022
|
+
ending.location.start_column
|
3023
|
+
)
|
2830
3024
|
|
2831
3025
|
Until.new(
|
2832
3026
|
predicate: predicate,
|
@@ -2865,12 +3059,12 @@ module SyntaxTree
|
|
2865
3059
|
# ) -> VarField
|
2866
3060
|
def on_var_field(value)
|
2867
3061
|
location =
|
2868
|
-
if value
|
3062
|
+
if value && value != :nil
|
2869
3063
|
value.location
|
2870
3064
|
else
|
2871
3065
|
# You can hit this pattern if you're assigning to a splat using
|
2872
3066
|
# pattern matching syntax in Ruby 2.7+
|
2873
|
-
Location.fixed(line: lineno, char: char_pos)
|
3067
|
+
Location.fixed(line: lineno, char: char_pos, column: current_column)
|
2874
3068
|
end
|
2875
3069
|
|
2876
3070
|
VarField.new(value: value, location: location)
|
@@ -2898,7 +3092,7 @@ module SyntaxTree
|
|
2898
3092
|
# :call-seq:
|
2899
3093
|
# on_void_stmt: () -> VoidStmt
|
2900
3094
|
def on_void_stmt
|
2901
|
-
VoidStmt.new(location: Location.fixed(line: lineno, char: char_pos))
|
3095
|
+
VoidStmt.new(location: Location.fixed(line: lineno, char: char_pos, column: current_column))
|
2902
3096
|
end
|
2903
3097
|
|
2904
3098
|
# :call-seq:
|
@@ -2917,9 +3111,13 @@ module SyntaxTree
|
|
2917
3111
|
statements_start = token
|
2918
3112
|
end
|
2919
3113
|
|
3114
|
+
start_char = find_next_statement_start(statements_start.location.end_char)
|
3115
|
+
|
2920
3116
|
statements.bind(
|
2921
|
-
|
2922
|
-
|
3117
|
+
start_char,
|
3118
|
+
start_char - line_counts[statements_start.location.start_line - 1].start,
|
3119
|
+
ending.location.start_char,
|
3120
|
+
ending.location.start_column
|
2923
3121
|
)
|
2924
3122
|
|
2925
3123
|
When.new(
|
@@ -2945,7 +3143,12 @@ module SyntaxTree
|
|
2945
3143
|
end
|
2946
3144
|
|
2947
3145
|
# Update the Statements location information
|
2948
|
-
statements.bind(
|
3146
|
+
statements.bind(
|
3147
|
+
predicate.location.end_char,
|
3148
|
+
predicate.location.end_column,
|
3149
|
+
ending.location.start_char,
|
3150
|
+
ending.location.start_column
|
3151
|
+
)
|
2949
3152
|
|
2950
3153
|
While.new(
|
2951
3154
|
predicate: predicate,
|
@@ -2981,7 +3184,7 @@ module SyntaxTree
|
|
2981
3184
|
# :call-seq:
|
2982
3185
|
# on_word_new: () -> Word
|
2983
3186
|
def on_word_new
|
2984
|
-
Word.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
|
3187
|
+
Word.new(parts: [], location: Location.fixed(line: lineno, char: char_pos, column: current_column))
|
2985
3188
|
end
|
2986
3189
|
|
2987
3190
|
# :call-seq:
|
@@ -3000,7 +3203,7 @@ module SyntaxTree
|
|
3000
3203
|
node =
|
3001
3204
|
WordsBeg.new(
|
3002
3205
|
value: value,
|
3003
|
-
location: Location.token(line: lineno, char: char_pos, size: value.size)
|
3206
|
+
location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
|
3004
3207
|
)
|
3005
3208
|
|
3006
3209
|
tokens << node
|
@@ -3055,6 +3258,7 @@ module SyntaxTree
|
|
3055
3258
|
Heredoc.new(
|
3056
3259
|
beginning: heredoc.beginning,
|
3057
3260
|
ending: heredoc.ending,
|
3261
|
+
dedent: heredoc.dedent,
|
3058
3262
|
parts: xstring.parts,
|
3059
3263
|
location: heredoc.location
|
3060
3264
|
)
|