@@ -563,7 +563,11 @@ private module Cached {
563
563
THashSplatArgumentPosition ( ) or
564
564
TSynthHashSplatArgumentPosition ( ) or
565
565
TSplatArgumentPosition ( int pos ) { exists ( Call c | c .getArgument ( pos ) instanceof SplatExpr ) } or
566
- TSynthSplatArgumentPosition ( ) or
566
+ TSynthSplatArgumentPosition ( int actualSplatPos ) {
567
+ actualSplatPos = - 1 // represents no actual splat
568
+ or
569
+ exists ( Call c | c .getArgument ( actualSplatPos ) instanceof SplatExpr )
570
+ } or
567
571
TAnyArgumentPosition ( ) or
568
572
TAnyKeywordArgumentPosition ( )
569
573
@@ -590,11 +594,15 @@ private module Cached {
590
594
THashSplatParameterPosition ( ) or
591
595
TSynthHashSplatParameterPosition ( ) or
592
596
TSplatParameterPosition ( int pos ) {
593
- pos = 0
597
+ pos = 0 // needed for flow summaries
594
598
or
595
599
exists ( Parameter p | p .getPosition ( ) = pos and p instanceof SplatParameter )
596
600
} or
597
- TSynthSplatParameterPosition ( ) or
601
+ TSynthSplatParameterPosition ( int actualSplatPos ) {
602
+ actualSplatPos = - 1 // represents no actual splat
603
+ or
604
+ exists ( Callable c | c .getParameter ( actualSplatPos ) instanceof SplatParameter )
605
+ } or
598
606
TAnyParameterPosition ( ) or
599
607
TAnyKeywordParameterPosition ( )
600
608
}
@@ -1383,8 +1391,14 @@ class ParameterPosition extends TParameterPosition {
1383
1391
/** Holds if this position represents a splat parameter at position `n`. */
1384
1392
predicate isSplat ( int n ) { this = TSplatParameterPosition ( n ) }
1385
1393
1386
- /** Holds if this position represents a synthetic splat parameter. */
1387
- predicate isSynthSplat ( ) { this = TSynthSplatParameterPosition ( ) }
1394
+ /**
1395
+ * Holds if this position represents a synthetic splat parameter.
1396
+ *
1397
+ * `actualSplatPos` indicates the position of the (unique) actual splat
1398
+ * parameter belonging to the same method, with `-1` representing no actual
1399
+ * splat parameter.
1400
+ */
1401
+ predicate isSynthSplat ( int actualSplatPos ) { this = TSynthSplatParameterPosition ( actualSplatPos ) }
1388
1402
1389
1403
/**
1390
1404
* Holds if this position represents any parameter, except `self` parameters. This
@@ -1419,7 +1433,11 @@ class ParameterPosition extends TParameterPosition {
1419
1433
or
1420
1434
exists ( int pos | this .isSplat ( pos ) and result = "* (position " + pos + ")" )
1421
1435
or
1422
- this .isSynthSplat ( ) and result = "synthetic *"
1436
+ exists ( int actualSplatPos , string suffix |
1437
+ this .isSynthSplat ( actualSplatPos ) and
1438
+ result = "synthetic *" + suffix and
1439
+ if actualSplatPos = - 1 then suffix = "" else suffix = " (actual at " + actualSplatPos + ")"
1440
+ )
1423
1441
}
1424
1442
}
1425
1443
@@ -1458,8 +1476,14 @@ class ArgumentPosition extends TArgumentPosition {
1458
1476
/** Holds if this position represents a splat argument at position `n`. */
1459
1477
predicate isSplat ( int n ) { this = TSplatArgumentPosition ( n ) }
1460
1478
1461
- /** Holds if this position represents a synthetic splat argument. */
1462
- predicate isSynthSplat ( ) { this = TSynthSplatArgumentPosition ( ) }
1479
+ /**
1480
+ * Holds if this position represents a synthetic splat argument.
1481
+ *
1482
+ * `actualSplatPos` indicates the position of the (unique) actual splat
1483
+ * argument belonging to the same call, with `-1` representing no actual
1484
+ * splat argument.
1485
+ */
1486
+ predicate isSynthSplat ( int actualSplatPos ) { this = TSynthSplatArgumentPosition ( actualSplatPos ) }
1463
1487
1464
1488
/** Gets a textual representation of this position. */
1465
1489
string toString ( ) {
@@ -1483,7 +1507,11 @@ class ArgumentPosition extends TArgumentPosition {
1483
1507
or
1484
1508
exists ( int pos | this .isSplat ( pos ) and result = "* (position " + pos + ")" )
1485
1509
or
1486
- this .isSynthSplat ( ) and result = "synthetic *"
1510
+ exists ( int actualSplatPos , string suffix |
1511
+ this .isSynthSplat ( actualSplatPos ) and
1512
+ result = "synthetic *" + suffix and
1513
+ if actualSplatPos = - 1 then suffix = "" else suffix = " (actual at " + actualSplatPos + ")"
1514
+ )
1487
1515
}
1488
1516
}
1489
1517
@@ -1517,19 +1545,29 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
1517
1545
exists ( string name | ppos .isKeyword ( name ) and apos .isKeyword ( name ) )
1518
1546
or
1519
1547
( ppos .isHashSplat ( ) or ppos .isSynthHashSplat ( ) ) and
1520
- ( apos .isHashSplat ( ) or apos .isSynthHashSplat ( ) )
1548
+ ( apos .isHashSplat ( ) or apos .isSynthHashSplat ( ) ) and
1549
+ // prevent synthetic hash-splat parameters from matching synthetic hash-splat
1550
+ // arguments when direct keyword matching is possible
1551
+ not ( ppos .isSynthHashSplat ( ) and apos .isSynthHashSplat ( ) )
1521
1552
or
1522
1553
exists ( int pos |
1523
1554
(
1524
1555
ppos .isSplat ( pos )
1525
1556
or
1526
- ppos .isSynthSplat ( ) and pos = 0
1557
+ ppos .isSynthSplat ( _) and
1558
+ pos = 0
1527
1559
) and
1528
1560
(
1529
1561
apos .isSplat ( pos )
1530
1562
or
1531
- apos .isSynthSplat ( ) and pos = 0
1563
+ apos .isSynthSplat ( _ ) and pos = 0
1532
1564
)
1565
+ ) and
1566
+ // prevent synthetic splat parameters from matching synthetic splat arguments
1567
+ // when direct positional matching is possible
1568
+ not exists ( int actualSplatPos |
1569
+ ppos .isSynthSplat ( actualSplatPos ) and
1570
+ apos .isSynthSplat ( actualSplatPos )
1533
1571
)
1534
1572
or
1535
1573
ppos .isAny ( ) and argumentPositionIsNotSelf ( apos )
0 commit comments