( ref: UnresolvedRef, context: ResolutionContext )
| 1619 | * Match all strategies in order of confidence |
| 1620 | */ |
| 1621 | export function matchReference( |
| 1622 | ref: UnresolvedRef, |
| 1623 | context: ResolutionContext |
| 1624 | ): ResolvedRef | null { |
| 1625 | // Function-as-value refs (#756) resolve ONLY through the dedicated matcher — |
| 1626 | // never the fuzzy/qualified fallthrough below (a wrong callback edge is |
| 1627 | // worse than none). |
| 1628 | if (ref.referenceKind === 'function_ref') { |
| 1629 | return matchFunctionRef(ref, context); |
| 1630 | } |
| 1631 | |
| 1632 | // Try strategies in order of confidence |
| 1633 | let result: ResolvedRef | null; |
| 1634 | |
| 1635 | // 0. File path match (e.g., "snippets/drawer-menu.liquid" → file node) |
| 1636 | result = matchByFilePath(ref, context); |
| 1637 | if (result) return result; |
| 1638 | |
| 1639 | // 1. Qualified name match (highest confidence) |
| 1640 | result = matchByQualifiedName(ref, context); |
| 1641 | if (result) return result; |
| 1642 | |
| 1643 | // 1b. C++ chained call whose receiver is another call — `Foo::instance().bar()` |
| 1644 | // encoded as `Foo::instance().bar` by the extractor (#645). Resolve the |
| 1645 | // receiver's type from what the inner call returns, then the method on it. |
| 1646 | if (ref.language === 'cpp' || ref.language === 'c') { |
| 1647 | result = matchCppCallChain(ref, context); |
| 1648 | if (result) return result; |
| 1649 | } |
| 1650 | |
| 1651 | // 1c. `::`-scoped factory chain — PHP `Cls::for($x)->method()` (#608) or Rust |
| 1652 | // `Foo::new().bar()`, both encoded as `Cls::factory().method`. The receiver's |
| 1653 | // type is the factory's `self` (PHP `: self`/`: static`, Rust `-> Self`) or |
| 1654 | // concrete return type. |
| 1655 | if (ref.language === 'php' || ref.language === 'rust') { |
| 1656 | result = matchScopedCallChain(ref, context); |
| 1657 | if (result) return result; |
| 1658 | } |
| 1659 | |
| 1660 | // 1d. Dotted chained static-factory / fluent call (Java / Kotlin / C# / Swift / |
| 1661 | // Go / Scala / Dart / Objective-C) — `Foo.getInstance().bar()` encoded as |
| 1662 | // `Foo.getInstance().bar`, Go's bare-factory `New().Method()` as `New().Method`, |
| 1663 | // Scala's companion factory, Dart's static factory / factory-constructor, or |
| 1664 | // ObjC's chained message send `[[Foo create] doIt]` encoded as `Foo.create().doIt` |
| 1665 | // (#645/#608 mechanism). Resolve the method's class from the inner call's |
| 1666 | // declared return type, then validate it. |
| 1667 | if ( |
| 1668 | ref.language === 'java' || |
| 1669 | ref.language === 'kotlin' || |
| 1670 | ref.language === 'csharp' || |
| 1671 | ref.language === 'swift' || |
| 1672 | ref.language === 'go' || |
| 1673 | ref.language === 'scala' || |
| 1674 | ref.language === 'dart' || |
| 1675 | ref.language === 'objc' || |
| 1676 | ref.language === 'pascal' |
| 1677 | ) { |
| 1678 | result = matchDottedCallChain(ref, context); |
no test coverage detected