syntax_tree 2.0.1 → 2.1.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.
@@ -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
- find_next_statement_start(lbrace.location.end_char),
257
- rbrace.location.start_char
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
- find_next_statement_start(lbrace.location.end_char),
286
- rbrace.location.start_char
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
 
@@ -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:
@@ -551,7 +564,7 @@ module SyntaxTree
551
564
  def on_backref(value)
552
565
  Backref.new(
553
566
  value: value,
554
- location: Location.token(line: lineno, char: char_pos, size: value.size)
567
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
555
568
  )
556
569
  end
557
570
 
@@ -561,7 +574,7 @@ module SyntaxTree
561
574
  node =
562
575
  Backtick.new(
563
576
  value: value,
564
- location: Location.token(line: lineno, char: char_pos, size: value.size)
577
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
565
578
  )
566
579
 
567
580
  tokens << node
@@ -592,15 +605,20 @@ module SyntaxTree
592
605
  PinnedBegin.new(statement: bodystmt, location: location)
593
606
  else
594
607
  keyword = find_token(Kw, "begin")
595
- end_char =
608
+ end_location =
596
609
  if bodystmt.rescue_clause || bodystmt.ensure_clause ||
597
610
  bodystmt.else_clause
598
- bodystmt.location.end_char
611
+ bodystmt.location
599
612
  else
600
- find_token(Kw, "end").location.end_char
613
+ find_token(Kw, "end").location
601
614
  end
602
615
 
603
- bodystmt.bind(keyword.location.end_char, end_char)
616
+ bodystmt.bind(
617
+ keyword.location.end_char,
618
+ keyword.location.end_column,
619
+ end_location.end_char,
620
+ end_location.end_column
621
+ )
604
622
  location = keyword.location.to(bodystmt.location)
605
623
 
606
624
  Begin.new(bodystmt: bodystmt, location: location)
@@ -682,9 +700,10 @@ module SyntaxTree
682
700
  BodyStmt.new(
683
701
  statements: statements,
684
702
  rescue_clause: rescue_clause,
703
+ else_keyword: else_clause && find_token(Kw, "else"),
685
704
  else_clause: else_clause,
686
705
  ensure_clause: ensure_clause,
687
- location: Location.fixed(line: lineno, char: char_pos)
706
+ location: Location.fixed(line: lineno, char: char_pos, column: current_column)
688
707
  )
689
708
  end
690
709
 
@@ -696,18 +715,24 @@ module SyntaxTree
696
715
  def on_brace_block(block_var, statements)
697
716
  lbrace = find_token(LBrace)
698
717
  rbrace = find_token(RBrace)
718
+ location = (block_var || lbrace).location
719
+ start_char = find_next_statement_start(location.end_char)
699
720
 
700
721
  statements.bind(
701
- find_next_statement_start((block_var || lbrace).location.end_char),
702
- rbrace.location.start_char
722
+ start_char,
723
+ start_char - line_counts[location.start_line - 1].start,
724
+ rbrace.location.start_char,
725
+ rbrace.location.start_column
703
726
  )
704
727
 
705
728
  location =
706
729
  Location.new(
707
730
  start_line: lbrace.location.start_line,
708
731
  start_char: lbrace.location.start_char,
732
+ start_column: lbrace.location.start_column,
709
733
  end_line: [rbrace.location.end_line, statements.location.end_line].max,
710
- end_char: rbrace.location.end_char
734
+ end_char: rbrace.location.end_char,
735
+ end_column: rbrace.location.end_column
711
736
  )
712
737
 
713
738
  BraceBlock.new(
@@ -781,10 +806,14 @@ module SyntaxTree
781
806
  def on_class(constant, superclass, bodystmt)
782
807
  beginning = find_token(Kw, "class")
783
808
  ending = find_token(Kw, "end")
809
+ location = (superclass || constant).location
810
+ start_char = find_next_statement_start(location.end_char)
784
811
 
785
812
  bodystmt.bind(
786
- find_next_statement_start((superclass || constant).location.end_char),
787
- ending.location.start_char
813
+ start_char,
814
+ start_char - line_counts[location.start_line - 1].start,
815
+ ending.location.start_char,
816
+ ending.location.start_column
788
817
  )
789
818
 
790
819
  ClassDeclaration.new(
@@ -801,7 +830,7 @@ module SyntaxTree
801
830
  node =
802
831
  Comma.new(
803
832
  value: value,
804
- location: Location.token(line: lineno, char: char_pos, size: value.size)
833
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
805
834
  )
806
835
 
807
836
  tokens << node
@@ -846,7 +875,7 @@ module SyntaxTree
846
875
  value: value.chomp,
847
876
  inline: value.strip != lines[line - 1].strip,
848
877
  location:
849
- Location.token(line: line, char: char_pos, size: value.size - 1)
878
+ Location.token(line: line, char: char_pos, column: current_column, size: value.size - 1)
850
879
  )
851
880
 
852
881
  @comments << comment
@@ -858,7 +887,7 @@ module SyntaxTree
858
887
  def on_const(value)
859
888
  Const.new(
860
889
  value: value,
861
- location: Location.token(line: lineno, char: char_pos, size: value.size)
890
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
862
891
  )
863
892
  end
864
893
 
@@ -893,7 +922,7 @@ module SyntaxTree
893
922
  def on_cvar(value)
894
923
  CVar.new(
895
924
  value: value,
896
- location: Location.token(line: lineno, char: char_pos, size: value.size)
925
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
897
926
  )
898
927
  end
899
928
 
@@ -917,12 +946,15 @@ module SyntaxTree
917
946
  # location information
918
947
  if params.is_a?(Params) && params.empty?
919
948
  end_char = name.location.end_char
949
+ end_column = name.location.end_column
920
950
  location =
921
951
  Location.new(
922
952
  start_line: params.location.start_line,
923
953
  start_char: end_char,
954
+ start_column: end_column,
924
955
  end_line: params.location.end_line,
925
- end_char: end_char
956
+ end_char: end_char,
957
+ end_column: end_column
926
958
  )
927
959
 
928
960
  params = Params.new(location: location)
@@ -932,9 +964,13 @@ module SyntaxTree
932
964
 
933
965
  if ending
934
966
  tokens.delete(ending)
967
+ start_char = find_next_statement_start(params.location.end_char)
968
+
935
969
  bodystmt.bind(
936
- find_next_statement_start(params.location.end_char),
937
- ending.location.start_char
970
+ start_char,
971
+ start_char - line_counts[params.location.start_line - 1].start,
972
+ ending.location.start_char,
973
+ ending.location.start_column
938
974
  )
939
975
 
940
976
  Def.new(
@@ -992,12 +1028,15 @@ module SyntaxTree
992
1028
  # location information
993
1029
  if params.is_a?(Params) && params.empty?
994
1030
  end_char = name.location.end_char
1031
+ end_column = name.location.end_column
995
1032
  location =
996
1033
  Location.new(
997
1034
  start_line: params.location.start_line,
998
1035
  start_char: end_char,
1036
+ start_column: end_column,
999
1037
  end_line: params.location.end_line,
1000
- end_char: end_char
1038
+ end_char: end_char,
1039
+ end_column: end_column
1001
1040
  )
1002
1041
 
1003
1042
  params = Params.new(location: location)
@@ -1008,9 +1047,13 @@ module SyntaxTree
1008
1047
 
1009
1048
  if ending
1010
1049
  tokens.delete(ending)
1050
+ start_char = find_next_statement_start(params.location.end_char)
1051
+
1011
1052
  bodystmt.bind(
1012
- find_next_statement_start(params.location.end_char),
1013
- ending.location.start_char
1053
+ start_char,
1054
+ start_char - line_counts[params.location.start_line - 1].start,
1055
+ ending.location.start_char,
1056
+ ending.location.start_column
1014
1057
  )
1015
1058
 
1016
1059
  Defs.new(
@@ -1042,10 +1085,14 @@ module SyntaxTree
1042
1085
  def on_do_block(block_var, bodystmt)
1043
1086
  beginning = find_token(Kw, "do")
1044
1087
  ending = find_token(Kw, "end")
1088
+ location = (block_var || beginning).location
1089
+ start_char = find_next_statement_start(location.end_char)
1045
1090
 
1046
1091
  bodystmt.bind(
1047
- find_next_statement_start((block_var || beginning).location.end_char),
1048
- ending.location.start_char
1092
+ start_char,
1093
+ start_char - line_counts[location.start_line - 1].start,
1094
+ ending.location.start_char,
1095
+ ending.location.start_column
1049
1096
  )
1050
1097
 
1051
1098
  DoBlock.new(
@@ -1115,7 +1162,7 @@ module SyntaxTree
1115
1162
  # :call-seq:
1116
1163
  # on_else: (Statements statements) -> Else
1117
1164
  def on_else(statements)
1118
- beginning = find_token(Kw, "else")
1165
+ keyword = find_token(Kw, "else")
1119
1166
 
1120
1167
  # else can either end with an end keyword (in which case we'll want to
1121
1168
  # consume that event) or it can end with an ensure keyword (in which case
@@ -1127,13 +1174,19 @@ module SyntaxTree
1127
1174
 
1128
1175
  node = tokens[index]
1129
1176
  ending = node.value == "end" ? tokens.delete_at(index) : node
1130
- # ending = node
1177
+ start_char = find_next_statement_start(keyword.location.end_char)
1131
1178
 
1132
- statements.bind(beginning.location.end_char, ending.location.start_char)
1179
+ statements.bind(
1180
+ start_char,
1181
+ start_char - line_counts[keyword.location.start_line - 1].start,
1182
+ ending.location.start_char,
1183
+ ending.location.start_column
1184
+ )
1133
1185
 
1134
1186
  Else.new(
1187
+ keyword: keyword,
1135
1188
  statements: statements,
1136
- location: beginning.location.to(ending.location)
1189
+ location: keyword.location.to(ending.location)
1137
1190
  )
1138
1191
  end
1139
1192
 
@@ -1147,7 +1200,12 @@ module SyntaxTree
1147
1200
  beginning = find_token(Kw, "elsif")
1148
1201
  ending = consequent || find_token(Kw, "end")
1149
1202
 
1150
- statements.bind(predicate.location.end_char, ending.location.start_char)
1203
+ statements.bind(
1204
+ predicate.location.end_char,
1205
+ predicate.location.end_column,
1206
+ ending.location.start_char,
1207
+ ending.location.start_column
1208
+ )
1151
1209
 
1152
1210
  Elsif.new(
1153
1211
  predicate: predicate,
@@ -1170,7 +1228,7 @@ module SyntaxTree
1170
1228
  @embdoc =
1171
1229
  EmbDoc.new(
1172
1230
  value: value,
1173
- location: Location.fixed(line: lineno, char: char_pos)
1231
+ location: Location.fixed(line: lineno, column: current_column, char: char_pos)
1174
1232
  )
1175
1233
  end
1176
1234
 
@@ -1185,8 +1243,10 @@ module SyntaxTree
1185
1243
  Location.new(
1186
1244
  start_line: location.start_line,
1187
1245
  start_char: location.start_char,
1246
+ start_column: location.start_column,
1188
1247
  end_line: lineno,
1189
- end_char: char_pos + value.length - 1
1248
+ end_char: char_pos + value.length - 1,
1249
+ end_column: current_column + value.length - 1
1190
1250
  )
1191
1251
  )
1192
1252
 
@@ -1202,7 +1262,7 @@ module SyntaxTree
1202
1262
  node =
1203
1263
  EmbExprBeg.new(
1204
1264
  value: value,
1205
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1265
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1206
1266
  )
1207
1267
 
1208
1268
  tokens << node
@@ -1215,7 +1275,7 @@ module SyntaxTree
1215
1275
  node =
1216
1276
  EmbExprEnd.new(
1217
1277
  value: value,
1218
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1278
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1219
1279
  )
1220
1280
 
1221
1281
  tokens << node
@@ -1228,7 +1288,7 @@ module SyntaxTree
1228
1288
  node =
1229
1289
  EmbVar.new(
1230
1290
  value: value,
1231
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1291
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1232
1292
  )
1233
1293
 
1234
1294
  tokens << node
@@ -1243,9 +1303,12 @@ module SyntaxTree
1243
1303
  # We don't want to consume the :@kw event, because that would break
1244
1304
  # def..ensure..end chains.
1245
1305
  ending = find_token(Kw, "end", consume: false)
1306
+ start_char = find_next_statement_start(keyword.location.end_char)
1246
1307
  statements.bind(
1247
- find_next_statement_start(keyword.location.end_char),
1248
- ending.location.start_char
1308
+ start_char,
1309
+ start_char - line_counts[keyword.location.start_line - 1].start,
1310
+ ending.location.start_char,
1311
+ ending.location.start_column
1249
1312
  )
1250
1313
 
1251
1314
  Ensure.new(
@@ -1292,7 +1355,7 @@ module SyntaxTree
1292
1355
  def on_float(value)
1293
1356
  FloatLiteral.new(
1294
1357
  value: value,
1295
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1358
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1296
1359
  )
1297
1360
  end
1298
1361
 
@@ -1337,7 +1400,9 @@ module SyntaxTree
1337
1400
 
1338
1401
  statements.bind(
1339
1402
  (keyword || collection).location.end_char,
1340
- ending.location.start_char
1403
+ (keyword || collection).location.end_column,
1404
+ ending.location.start_char,
1405
+ ending.location.start_column
1341
1406
  )
1342
1407
 
1343
1408
  if index.is_a?(MLHS)
@@ -1358,7 +1423,7 @@ module SyntaxTree
1358
1423
  def on_gvar(value)
1359
1424
  GVar.new(
1360
1425
  value: value,
1361
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1426
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1362
1427
  )
1363
1428
  end
1364
1429
 
@@ -1379,7 +1444,7 @@ module SyntaxTree
1379
1444
  # on_heredoc_beg: (String value) -> HeredocBeg
1380
1445
  def on_heredoc_beg(value)
1381
1446
  location =
1382
- Location.token(line: lineno, char: char_pos, size: value.size + 1)
1447
+ Location.token(line: lineno, char: char_pos, column: current_column, size: value.size + 1)
1383
1448
 
1384
1449
  # Here we're going to artificially create an extra node type so that if
1385
1450
  # there are comments after the declaration of a heredoc, they get printed.
@@ -1415,8 +1480,10 @@ module SyntaxTree
1415
1480
  Location.new(
1416
1481
  start_line: heredoc.location.start_line,
1417
1482
  start_char: heredoc.location.start_char,
1483
+ start_column: heredoc.location.start_column,
1418
1484
  end_line: lineno,
1419
- end_char: char_pos
1485
+ end_char: char_pos,
1486
+ end_column: current_column,
1420
1487
  )
1421
1488
  )
1422
1489
  end
@@ -1443,7 +1510,7 @@ module SyntaxTree
1443
1510
  def on_ident(value)
1444
1511
  Ident.new(
1445
1512
  value: value,
1446
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1513
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1447
1514
  )
1448
1515
  end
1449
1516
 
@@ -1457,7 +1524,12 @@ module SyntaxTree
1457
1524
  beginning = find_token(Kw, "if")
1458
1525
  ending = consequent || find_token(Kw, "end")
1459
1526
 
1460
- statements.bind(predicate.location.end_char, ending.location.start_char)
1527
+ statements.bind(
1528
+ predicate.location.end_char,
1529
+ predicate.location.end_column,
1530
+ ending.location.start_char,
1531
+ ending.location.start_column
1532
+ )
1461
1533
 
1462
1534
  If.new(
1463
1535
  predicate: predicate,
@@ -1503,7 +1575,7 @@ module SyntaxTree
1503
1575
  def on_imaginary(value)
1504
1576
  Imaginary.new(
1505
1577
  value: value,
1506
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1578
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1507
1579
  )
1508
1580
  end
1509
1581
 
@@ -1527,9 +1599,12 @@ module SyntaxTree
1527
1599
  statements_start = token
1528
1600
  end
1529
1601
 
1602
+ start_char = find_next_statement_start(statements_start.location.end_char)
1530
1603
  statements.bind(
1531
- find_next_statement_start(statements_start.location.end_char),
1532
- ending.location.start_char
1604
+ start_char,
1605
+ start_char - line_counts[statements_start.location.start_line - 1].start,
1606
+ ending.location.start_char,
1607
+ ending.location.start_column
1533
1608
  )
1534
1609
 
1535
1610
  In.new(
@@ -1545,7 +1620,7 @@ module SyntaxTree
1545
1620
  def on_int(value)
1546
1621
  Int.new(
1547
1622
  value: value,
1548
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1623
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1549
1624
  )
1550
1625
  end
1551
1626
 
@@ -1554,7 +1629,7 @@ module SyntaxTree
1554
1629
  def on_ivar(value)
1555
1630
  IVar.new(
1556
1631
  value: value,
1557
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1632
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1558
1633
  )
1559
1634
  end
1560
1635
 
@@ -1564,7 +1639,7 @@ module SyntaxTree
1564
1639
  node =
1565
1640
  Kw.new(
1566
1641
  value: value,
1567
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1642
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1568
1643
  )
1569
1644
 
1570
1645
  tokens << node
@@ -1585,7 +1660,7 @@ module SyntaxTree
1585
1660
  def on_label(value)
1586
1661
  Label.new(
1587
1662
  value: value,
1588
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1663
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1589
1664
  )
1590
1665
  end
1591
1666
 
@@ -1595,7 +1670,7 @@ module SyntaxTree
1595
1670
  node =
1596
1671
  LabelEnd.new(
1597
1672
  value: value,
1598
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1673
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1599
1674
  )
1600
1675
 
1601
1676
  tokens << node
@@ -1621,7 +1696,12 @@ module SyntaxTree
1621
1696
  closing = find_token(Kw, "end")
1622
1697
  end
1623
1698
 
1624
- statements.bind(opening.location.end_char, closing.location.start_char)
1699
+ statements.bind(
1700
+ opening.location.end_char,
1701
+ opening.location.end_column,
1702
+ closing.location.start_char,
1703
+ closing.location.start_column
1704
+ )
1625
1705
 
1626
1706
  Lambda.new(
1627
1707
  params: params,
@@ -1636,7 +1716,7 @@ module SyntaxTree
1636
1716
  node =
1637
1717
  LBrace.new(
1638
1718
  value: value,
1639
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1719
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1640
1720
  )
1641
1721
 
1642
1722
  tokens << node
@@ -1649,7 +1729,7 @@ module SyntaxTree
1649
1729
  node =
1650
1730
  LBracket.new(
1651
1731
  value: value,
1652
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1732
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1653
1733
  )
1654
1734
 
1655
1735
  tokens << node
@@ -1662,7 +1742,7 @@ module SyntaxTree
1662
1742
  node =
1663
1743
  LParen.new(
1664
1744
  value: value,
1665
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1745
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1666
1746
  )
1667
1747
 
1668
1748
  tokens << node
@@ -1761,7 +1841,7 @@ module SyntaxTree
1761
1841
  # :call-seq:
1762
1842
  # on_mlhs_new: () -> MLHS
1763
1843
  def on_mlhs_new
1764
- MLHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
1844
+ MLHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos, column: current_column))
1765
1845
  end
1766
1846
 
1767
1847
  # :call-seq:
@@ -1787,10 +1867,13 @@ module SyntaxTree
1787
1867
  def on_module(constant, bodystmt)
1788
1868
  beginning = find_token(Kw, "module")
1789
1869
  ending = find_token(Kw, "end")
1870
+ start_char = find_next_statement_start(constant.location.end_char)
1790
1871
 
1791
1872
  bodystmt.bind(
1792
- find_next_statement_start(constant.location.end_char),
1793
- ending.location.start_char
1873
+ start_char,
1874
+ start_char - line_counts[constant.location.start_line - 1].start,
1875
+ ending.location.start_char,
1876
+ ending.location.start_column
1794
1877
  )
1795
1878
 
1796
1879
  ModuleDeclaration.new(
@@ -1803,7 +1886,7 @@ module SyntaxTree
1803
1886
  # :call-seq:
1804
1887
  # on_mrhs_new: () -> MRHS
1805
1888
  def on_mrhs_new
1806
- MRHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
1889
+ MRHS.new(parts: [], location: Location.fixed(line: lineno, char: char_pos, column: current_column))
1807
1890
  end
1808
1891
 
1809
1892
  # :call-seq:
@@ -1872,7 +1955,7 @@ module SyntaxTree
1872
1955
  node =
1873
1956
  Op.new(
1874
1957
  value: value,
1875
- location: Location.token(line: lineno, char: char_pos, size: value.size)
1958
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
1876
1959
  )
1877
1960
 
1878
1961
  tokens << node
@@ -1931,7 +2014,7 @@ module SyntaxTree
1931
2014
  if parts.any?
1932
2015
  parts[0].location.to(parts[-1].location)
1933
2016
  else
1934
- Location.fixed(line: lineno, char: char_pos)
2017
+ Location.fixed(line: lineno, char: char_pos, column: current_column)
1935
2018
  end
1936
2019
 
1937
2020
  Params.new(
@@ -1954,12 +2037,15 @@ module SyntaxTree
1954
2037
 
1955
2038
  if contents && contents.is_a?(Params)
1956
2039
  location = contents.location
2040
+ start_char = find_next_statement_start(lparen.location.end_char)
1957
2041
  location =
1958
2042
  Location.new(
1959
2043
  start_line: location.start_line,
1960
- start_char: find_next_statement_start(lparen.location.end_char),
2044
+ start_char: start_char,
2045
+ start_column: start_char - line_counts[lparen.location.start_line - 1].start,
1961
2046
  end_line: location.end_line,
1962
- end_char: rparen.location.start_char
2047
+ end_char: rparen.location.start_char,
2048
+ end_column: rparen.location.start_column
1963
2049
  )
1964
2050
 
1965
2051
  contents =
@@ -1997,23 +2083,26 @@ module SyntaxTree
1997
2083
  def on_period(value)
1998
2084
  Period.new(
1999
2085
  value: value,
2000
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2086
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2001
2087
  )
2002
2088
  end
2003
2089
 
2004
2090
  # :call-seq:
2005
2091
  # on_program: (Statements statements) -> Program
2006
2092
  def on_program(statements)
2093
+ last_column = source.length - line_counts[lines.length - 1].start
2007
2094
  location =
2008
2095
  Location.new(
2009
2096
  start_line: 1,
2010
2097
  start_char: 0,
2098
+ start_column: 0,
2011
2099
  end_line: lines.length,
2012
- end_char: source.length
2100
+ end_char: source.length,
2101
+ end_column: last_column
2013
2102
  )
2014
2103
 
2015
2104
  statements.body << @__end__ if @__end__
2016
- statements.bind(0, source.length)
2105
+ statements.bind(0, 0, source.length, last_column)
2017
2106
 
2018
2107
  program = Program.new(statements: statements, location: location)
2019
2108
  attach_comments(program, @comments)
@@ -2126,7 +2215,7 @@ module SyntaxTree
2126
2215
  node =
2127
2216
  QSymbolsBeg.new(
2128
2217
  value: value,
2129
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2218
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2130
2219
  )
2131
2220
 
2132
2221
  tokens << node
@@ -2161,7 +2250,7 @@ module SyntaxTree
2161
2250
  node =
2162
2251
  QWordsBeg.new(
2163
2252
  value: value,
2164
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2253
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2165
2254
  )
2166
2255
 
2167
2256
  tokens << node
@@ -2181,7 +2270,7 @@ module SyntaxTree
2181
2270
  def on_rational(value)
2182
2271
  RationalLiteral.new(
2183
2272
  value: value,
2184
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2273
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2185
2274
  )
2186
2275
  end
2187
2276
 
@@ -2191,7 +2280,7 @@ module SyntaxTree
2191
2280
  node =
2192
2281
  RBrace.new(
2193
2282
  value: value,
2194
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2283
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2195
2284
  )
2196
2285
 
2197
2286
  tokens << node
@@ -2204,7 +2293,7 @@ module SyntaxTree
2204
2293
  node =
2205
2294
  RBracket.new(
2206
2295
  value: value,
2207
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2296
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2208
2297
  )
2209
2298
 
2210
2299
  tokens << node
@@ -2238,7 +2327,7 @@ module SyntaxTree
2238
2327
  node =
2239
2328
  RegexpBeg.new(
2240
2329
  value: value,
2241
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2330
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2242
2331
  )
2243
2332
 
2244
2333
  tokens << node
@@ -2250,7 +2339,7 @@ module SyntaxTree
2250
2339
  def on_regexp_end(value)
2251
2340
  RegexpEnd.new(
2252
2341
  value: value,
2253
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2342
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2254
2343
  )
2255
2344
  end
2256
2345
 
@@ -2292,9 +2381,12 @@ module SyntaxTree
2292
2381
  exceptions = exceptions[0] if exceptions.is_a?(Array)
2293
2382
 
2294
2383
  last_node = variable || exceptions || keyword
2384
+ start_char = find_next_statement_start(last_node.location.end_char)
2295
2385
  statements.bind(
2296
- find_next_statement_start(last_node.location.end_char),
2297
- char_pos
2386
+ start_char,
2387
+ start_char - line_counts[last_node.location.start_line - 1].start,
2388
+ char_pos,
2389
+ current_column
2298
2390
  )
2299
2391
 
2300
2392
  # We add an additional inner node here that ripper doesn't provide so that
@@ -2309,13 +2401,16 @@ module SyntaxTree
2309
2401
  Location.new(
2310
2402
  start_line: keyword.location.start_line,
2311
2403
  start_char: keyword.location.end_char + 1,
2404
+ start_column: keyword.location.end_column + 1,
2312
2405
  end_line: last_node.location.end_line,
2313
- end_char: last_node.location.end_char
2406
+ end_char: last_node.location.end_char,
2407
+ end_column: last_node.location.end_column
2314
2408
  )
2315
2409
  )
2316
2410
  end
2317
2411
 
2318
2412
  Rescue.new(
2413
+ keyword: keyword,
2319
2414
  exception: rescue_ex,
2320
2415
  statements: statements,
2321
2416
  consequent: consequent,
@@ -2323,8 +2418,10 @@ module SyntaxTree
2323
2418
  Location.new(
2324
2419
  start_line: keyword.location.start_line,
2325
2420
  start_char: keyword.location.start_char,
2421
+ start_column: keyword.location.start_column,
2326
2422
  end_line: lineno,
2327
- end_char: char_pos
2423
+ end_char: char_pos,
2424
+ end_column: current_column
2328
2425
  )
2329
2426
  )
2330
2427
  end
@@ -2383,7 +2480,7 @@ module SyntaxTree
2383
2480
  node =
2384
2481
  RParen.new(
2385
2482
  value: value,
2386
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2483
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2387
2484
  )
2388
2485
 
2389
2486
  tokens << node
@@ -2395,10 +2492,13 @@ module SyntaxTree
2395
2492
  def on_sclass(target, bodystmt)
2396
2493
  beginning = find_token(Kw, "class")
2397
2494
  ending = find_token(Kw, "end")
2495
+ start_char = find_next_statement_start(target.location.end_char)
2398
2496
 
2399
2497
  bodystmt.bind(
2400
- find_next_statement_start(target.location.end_char),
2401
- ending.location.start_char
2498
+ start_char,
2499
+ start_char - line_counts[target.location.start_line - 1].start,
2500
+ ending.location.start_char,
2501
+ ending.location.start_column
2402
2502
  )
2403
2503
 
2404
2504
  SClass.new(
@@ -2437,7 +2537,7 @@ module SyntaxTree
2437
2537
  Statements.new(
2438
2538
  self,
2439
2539
  body: [],
2440
- location: Location.fixed(line: lineno, char: char_pos)
2540
+ location: Location.fixed(line: lineno, char: char_pos, column: current_column)
2441
2541
  )
2442
2542
  end
2443
2543
 
@@ -2471,7 +2571,7 @@ module SyntaxTree
2471
2571
  def on_string_content
2472
2572
  StringContent.new(
2473
2573
  parts: [],
2474
- location: Location.fixed(line: lineno, char: char_pos)
2574
+ location: Location.fixed(line: lineno, char: char_pos, column: current_column)
2475
2575
  )
2476
2576
  end
2477
2577
 
@@ -2494,18 +2594,22 @@ module SyntaxTree
2494
2594
 
2495
2595
  statements.bind(
2496
2596
  embexpr_beg.location.end_char,
2497
- embexpr_end.location.start_char
2597
+ embexpr_beg.location.end_column,
2598
+ embexpr_end.location.start_char,
2599
+ embexpr_end.location.start_column
2498
2600
  )
2499
2601
 
2500
2602
  location =
2501
2603
  Location.new(
2502
2604
  start_line: embexpr_beg.location.start_line,
2503
2605
  start_char: embexpr_beg.location.start_char,
2606
+ start_column: embexpr_beg.location.start_column,
2504
2607
  end_line: [
2505
2608
  embexpr_end.location.end_line,
2506
2609
  statements.location.end_line
2507
2610
  ].max,
2508
- end_char: embexpr_end.location.end_char
2611
+ end_char: embexpr_end.location.end_char,
2612
+ end_column: embexpr_end.location.end_column
2509
2613
  )
2510
2614
 
2511
2615
  StringEmbExpr.new(statements: statements, location: location)
@@ -2533,11 +2637,13 @@ module SyntaxTree
2533
2637
  Location.new(
2534
2638
  start_line: tstring_beg.location.start_line,
2535
2639
  start_char: tstring_beg.location.start_char,
2640
+ start_column: tstring_beg.location.start_column,
2536
2641
  end_line: [
2537
2642
  tstring_end.location.end_line,
2538
2643
  string.location.end_line
2539
2644
  ].max,
2540
- end_char: tstring_end.location.end_char
2645
+ end_char: tstring_end.location.end_char,
2646
+ end_column: tstring_end.location.end_column
2541
2647
  )
2542
2648
 
2543
2649
  StringLiteral.new(
@@ -2566,7 +2672,7 @@ module SyntaxTree
2566
2672
  node =
2567
2673
  SymBeg.new(
2568
2674
  value: value,
2569
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2675
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2570
2676
  )
2571
2677
 
2572
2678
  tokens << node
@@ -2620,7 +2726,7 @@ module SyntaxTree
2620
2726
  node =
2621
2727
  SymbolsBeg.new(
2622
2728
  value: value,
2623
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2729
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2624
2730
  )
2625
2731
 
2626
2732
  tokens << node
@@ -2645,7 +2751,7 @@ module SyntaxTree
2645
2751
  node =
2646
2752
  TLambda.new(
2647
2753
  value: value,
2648
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2754
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2649
2755
  )
2650
2756
 
2651
2757
  tokens << node
@@ -2658,7 +2764,7 @@ module SyntaxTree
2658
2764
  node =
2659
2765
  TLamBeg.new(
2660
2766
  value: value,
2661
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2767
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2662
2768
  )
2663
2769
 
2664
2770
  tokens << node
@@ -2693,7 +2799,7 @@ module SyntaxTree
2693
2799
  node =
2694
2800
  TStringBeg.new(
2695
2801
  value: value,
2696
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2802
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2697
2803
  )
2698
2804
 
2699
2805
  tokens << node
@@ -2705,7 +2811,7 @@ module SyntaxTree
2705
2811
  def on_tstring_content(value)
2706
2812
  TStringContent.new(
2707
2813
  value: value,
2708
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2814
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2709
2815
  )
2710
2816
  end
2711
2817
 
@@ -2715,7 +2821,7 @@ module SyntaxTree
2715
2821
  node =
2716
2822
  TStringEnd.new(
2717
2823
  value: value,
2718
- location: Location.token(line: lineno, char: char_pos, size: value.size)
2824
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
2719
2825
  )
2720
2826
 
2721
2827
  tokens << node
@@ -2789,7 +2895,12 @@ module SyntaxTree
2789
2895
  beginning = find_token(Kw, "unless")
2790
2896
  ending = consequent || find_token(Kw, "end")
2791
2897
 
2792
- statements.bind(predicate.location.end_char, ending.location.start_char)
2898
+ statements.bind(
2899
+ predicate.location.end_char,
2900
+ predicate.location.end_column,
2901
+ ending.location.start_char,
2902
+ ending.location.start_column
2903
+ )
2793
2904
 
2794
2905
  Unless.new(
2795
2906
  predicate: predicate,
@@ -2826,7 +2937,12 @@ module SyntaxTree
2826
2937
  end
2827
2938
 
2828
2939
  # Update the Statements location information
2829
- statements.bind(predicate.location.end_char, ending.location.start_char)
2940
+ statements.bind(
2941
+ predicate.location.end_char,
2942
+ predicate.location.end_column,
2943
+ ending.location.start_char,
2944
+ ending.location.start_column
2945
+ )
2830
2946
 
2831
2947
  Until.new(
2832
2948
  predicate: predicate,
@@ -2870,7 +2986,7 @@ module SyntaxTree
2870
2986
  else
2871
2987
  # You can hit this pattern if you're assigning to a splat using
2872
2988
  # pattern matching syntax in Ruby 2.7+
2873
- Location.fixed(line: lineno, char: char_pos)
2989
+ Location.fixed(line: lineno, char: char_pos, column: current_column)
2874
2990
  end
2875
2991
 
2876
2992
  VarField.new(value: value, location: location)
@@ -2898,7 +3014,7 @@ module SyntaxTree
2898
3014
  # :call-seq:
2899
3015
  # on_void_stmt: () -> VoidStmt
2900
3016
  def on_void_stmt
2901
- VoidStmt.new(location: Location.fixed(line: lineno, char: char_pos))
3017
+ VoidStmt.new(location: Location.fixed(line: lineno, char: char_pos, column: current_column))
2902
3018
  end
2903
3019
 
2904
3020
  # :call-seq:
@@ -2917,9 +3033,13 @@ module SyntaxTree
2917
3033
  statements_start = token
2918
3034
  end
2919
3035
 
3036
+ start_char = find_next_statement_start(statements_start.location.end_char)
3037
+
2920
3038
  statements.bind(
2921
- find_next_statement_start(statements_start.location.end_char),
2922
- ending.location.start_char
3039
+ start_char,
3040
+ start_char - line_counts[statements_start.location.start_line - 1].start,
3041
+ ending.location.start_char,
3042
+ ending.location.start_column
2923
3043
  )
2924
3044
 
2925
3045
  When.new(
@@ -2945,7 +3065,12 @@ module SyntaxTree
2945
3065
  end
2946
3066
 
2947
3067
  # Update the Statements location information
2948
- statements.bind(predicate.location.end_char, ending.location.start_char)
3068
+ statements.bind(
3069
+ predicate.location.end_char,
3070
+ predicate.location.end_column,
3071
+ ending.location.start_char,
3072
+ ending.location.start_column
3073
+ )
2949
3074
 
2950
3075
  While.new(
2951
3076
  predicate: predicate,
@@ -2981,7 +3106,7 @@ module SyntaxTree
2981
3106
  # :call-seq:
2982
3107
  # on_word_new: () -> Word
2983
3108
  def on_word_new
2984
- Word.new(parts: [], location: Location.fixed(line: lineno, char: char_pos))
3109
+ Word.new(parts: [], location: Location.fixed(line: lineno, char: char_pos, column: current_column))
2985
3110
  end
2986
3111
 
2987
3112
  # :call-seq:
@@ -3000,7 +3125,7 @@ module SyntaxTree
3000
3125
  node =
3001
3126
  WordsBeg.new(
3002
3127
  value: value,
3003
- location: Location.token(line: lineno, char: char_pos, size: value.size)
3128
+ location: Location.token(line: lineno, char: char_pos, column: current_column, size: value.size)
3004
3129
  )
3005
3130
 
3006
3131
  tokens << node