@@ -516,12 +516,46 @@ def on_array(contents)
516
516
def on_aryptn ( constant , requireds , rest , posts )
517
517
parts = [ constant , *requireds , rest , *posts ] . compact
518
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
+
519
553
AryPtn . new (
520
554
constant : constant ,
521
555
requireds : requireds || [ ] ,
522
556
rest : rest ,
523
557
posts : posts || [ ] ,
524
- location : parts [ 0 ] . location . to ( parts [ - 1 ] . location )
558
+ location : location
525
559
)
526
560
end
527
561
@@ -1373,15 +1407,35 @@ def on_float(value)
1373
1407
# VarField right
1374
1408
# ) -> FndPtn
1375
1409
def on_fndptn ( constant , left , values , right )
1376
- beginning = constant || find_token ( LBracket )
1377
- ending = find_token ( RBracket )
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
1378
1432
1379
1433
FndPtn . new (
1380
1434
constant : constant ,
1381
1435
left : left ,
1382
1436
values : values ,
1383
1437
right : right ,
1384
- location : beginning . location . to ( ending . location )
1438
+ location : ( constant || opening ) . location . to ( closing . location )
1385
1439
)
1386
1440
end
1387
1441
@@ -1468,6 +1522,7 @@ def on_heredoc_dedent(string, width)
1468
1522
@heredocs [ -1 ] = Heredoc . new (
1469
1523
beginning : heredoc . beginning ,
1470
1524
ending : heredoc . ending ,
1525
+ dedent : width ,
1471
1526
parts : string . parts ,
1472
1527
location : heredoc . location
1473
1528
)
@@ -1481,6 +1536,7 @@ def on_heredoc_end(value)
1481
1536
@heredocs [ -1 ] = Heredoc . new (
1482
1537
beginning : heredoc . beginning ,
1483
1538
ending : value . chomp ,
1539
+ dedent : heredoc . dedent ,
1484
1540
parts : heredoc . parts ,
1485
1541
location :
1486
1542
Location . new (
@@ -1501,12 +1557,23 @@ def on_heredoc_end(value)
1501
1557
# (nil | VarField) keyword_rest
1502
1558
# ) -> HshPtn
1503
1559
def on_hshptn ( constant , keywords , keyword_rest )
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
+
1504
1571
parts = [ constant , *keywords &.flatten ( 1 ) , keyword_rest ] . compact
1505
1572
location =
1506
- if parts . empty?
1507
- find_token ( LBrace ) . location . to ( find_token ( RBrace ) . location )
1508
- else
1573
+ if parts . any?
1509
1574
parts [ 0 ] . location . to ( parts [ -1 ] . location )
1575
+ else
1576
+ find_token ( LBrace ) . location . to ( find_token ( RBrace ) . location )
1510
1577
end
1511
1578
1512
1579
HshPtn . new (
@@ -2638,6 +2705,7 @@ def on_string_literal(string)
2638
2705
Heredoc . new (
2639
2706
beginning : heredoc . beginning ,
2640
2707
ending : heredoc . ending ,
2708
+ dedent : heredoc . dedent ,
2641
2709
parts : string . parts ,
2642
2710
location : heredoc . location
2643
2711
)
@@ -3190,6 +3258,7 @@ def on_xstring_literal(xstring)
3190
3258
Heredoc . new (
3191
3259
beginning : heredoc . beginning ,
3192
3260
ending : heredoc . ending ,
3261
+ dedent : heredoc . dedent ,
3193
3262
parts : xstring . parts ,
3194
3263
location : heredoc . location
3195
3264
)
0 commit comments