@@ -516,12 +516,46 @@ def on_array(contents)
516516 def on_aryptn ( constant , requireds , rest , posts )
517517 parts = [ constant , *requireds , rest , *posts ] . compact
518518
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+
519553 AryPtn . new (
520554 constant : constant ,
521555 requireds : requireds || [ ] ,
522556 rest : rest ,
523557 posts : posts || [ ] ,
524- location : parts [ 0 ] . location . to ( parts [ - 1 ] . location )
558+ location : location
525559 )
526560 end
527561
@@ -1373,15 +1407,35 @@ def on_float(value)
13731407 # VarField right
13741408 # ) -> FndPtn
13751409 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
13781432
13791433 FndPtn . new (
13801434 constant : constant ,
13811435 left : left ,
13821436 values : values ,
13831437 right : right ,
1384- location : beginning . location . to ( ending . location )
1438+ location : ( constant || opening ) . location . to ( closing . location )
13851439 )
13861440 end
13871441
@@ -1468,6 +1522,7 @@ def on_heredoc_dedent(string, width)
14681522 @heredocs [ -1 ] = Heredoc . new (
14691523 beginning : heredoc . beginning ,
14701524 ending : heredoc . ending ,
1525+ dedent : width ,
14711526 parts : string . parts ,
14721527 location : heredoc . location
14731528 )
@@ -1481,6 +1536,7 @@ def on_heredoc_end(value)
14811536 @heredocs [ -1 ] = Heredoc . new (
14821537 beginning : heredoc . beginning ,
14831538 ending : value . chomp ,
1539+ dedent : heredoc . dedent ,
14841540 parts : heredoc . parts ,
14851541 location :
14861542 Location . new (
@@ -1501,12 +1557,23 @@ def on_heredoc_end(value)
15011557 # (nil | VarField) keyword_rest
15021558 # ) -> HshPtn
15031559 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+
15041571 parts = [ constant , *keywords &.flatten ( 1 ) , keyword_rest ] . compact
15051572 location =
1506- if parts . empty?
1507- find_token ( LBrace ) . location . to ( find_token ( RBrace ) . location )
1508- else
1573+ if parts . any?
15091574 parts [ 0 ] . location . to ( parts [ -1 ] . location )
1575+ else
1576+ find_token ( LBrace ) . location . to ( find_token ( RBrace ) . location )
15101577 end
15111578
15121579 HshPtn . new (
@@ -2638,6 +2705,7 @@ def on_string_literal(string)
26382705 Heredoc . new (
26392706 beginning : heredoc . beginning ,
26402707 ending : heredoc . ending ,
2708+ dedent : heredoc . dedent ,
26412709 parts : string . parts ,
26422710 location : heredoc . location
26432711 )
@@ -3190,6 +3258,7 @@ def on_xstring_literal(xstring)
31903258 Heredoc . new (
31913259 beginning : heredoc . beginning ,
31923260 ending : heredoc . ending ,
3261+ dedent : heredoc . dedent ,
31933262 parts : xstring . parts ,
31943263 location : heredoc . location
31953264 )
0 commit comments