Files
codegraph/src/resolution
Colby MchenryandClaude Opus 5.5 5753de20f5 fix(swift): an extension is not the type it extends (#2107)
`extension View { … }` parses as a class_declaration, so the index held a
`class View` node for every file extending SwiftUI's View, Text, Color,
String, URL. With no declaration of the type in the project, every
`struct X: View`, `Text("…")` and `Color.red` bound to whichever
extension came first: on IceCubesApp 6 of the top 12 "most depended on"
symbols were extension files (View 632 edges, Text 402, Label 209). And
a bare `@State` bound to a view model's nested `enum State` (253 edges),
`@Test` to a test's nested struct (821 on SwiftPackageIndex), `: Error`
to a nested `IOError.Error` (233 on swift-nio).

A gate at resolveOne's seam (every strategy, framework patterns and
name matching alike) checks a Swift reference's type target against what
the site wrote:
- an extension moves to the declaration it extends, or the ref stays
  unresolved when the SDK declares the type;
- a bare name of a nested type needs the site inside its parent, the type
  itself, or a subtype that declares inheriting from the parent;
- a qualified name must fit its path. The index keeps `Build.Id` as a ref
  named `Id`, so the qualifier is read back from the source line
  (generic arguments stripped: `EventLoopFuture<T>.Isolated`); a member
  indexed top-level because an `#if` ended its type's body early still
  fits a parent declared in its file.
Redirects pick the unique declaration in scope, then the same file, then
the nearest directory; a tie is left unresolved.

Two things rode on the wrong edges and are kept:
- `getSupertypes` named `View` for `struct X: View` only because that
  edge resolved to an extension. Swift conformances to a type the
  project only extends are now read from the declaration head (once per
  node, memoized; a per-node unresolved_refs query was +75% index time on
  swift-nio), so `X().withEnvironments()` still resolves to the
  `extension View` method.
- interface-impl dispatch read a protocol's methods off the node the
  conformance landed on. Swift protocol requirements are not extracted as
  methods; the default implementations live on `extension P` nodes, which
  are now included — every extension, not one arbitrary one (+359
  dispatch edges on swift-nio, +44 on Alamofire, none lost).

Measured edge diffs vs main, every removal classified:
IceCubesApp 2473 removed (172 redirects to the declaration, 1989
SDK-extension edges, 280 wrong bare nested-type bindings, ~30 from the
class the typealias parse error swallows); SwiftPackageIndex 3810 (1461
redirects); swift-nio 10991 (5085 redirects); Alamofire 1368 (198). Index
time at parity (swift-nio 4.1s vs 4.0s, Alamofire 1.33 vs 1.37,
IceCubes 1.31 vs 1.31).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:31:21 +00:00
..