mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-08-28 05:25:25 +00:00
Implements the scope-tree spine and position-indexed lookup as pure logic in `gitnexus-shared`. Generalizes the `enclosingFunctions` pattern from closed PR #902 to arbitrary `ScopeKind`s. Three modules under `gitnexus-shared/src/scope-resolution/`: 1. `scope-id.ts` — `makeScopeId({filePath, range, kind})` builds the canonical RFC §2.2 shape `scope:{filePath}#{startLine}:{startCol}-{endLine}:{endCol}:{kind}` and interns the result through a process-local pool so repeated calls with structurally identical inputs return the same string reference. `clearScopeIdInternPool()` exported for test isolation. 2. `scope-tree.ts` — `buildScopeTree(scopes)` validates invariants and returns an immutable `ScopeTree`: - `getScope(id)` / `getParent(id)` / `getChildren(id)` / `getAncestors(id)` - Implements the `ScopeLookup` contract from #916, so `resolveTypeRef` can consume a `ScopeTree` directly (test included). Invariants enforced (throw `ScopeTreeInvariantError` on violation): - Non-Module scopes must have a parent. - Parent must exist in the supplied set. - Parent range STRICTLY contains child range (equal ranges rejected). - Sibling ranges under the same parent do not overlap. Ranges that merely touch at the boundary (`a.end == b.start`) are accepted. - Parent and child live in the same filePath. - Duplicate scope ids are rejected. 3. `position-index.ts` — `buildPositionIndex(scopes)` produces a `PositionIndex` with `atPosition(filePath, line, col)`. Per-file sorted array; binary-search the upper bound of `start ≤ query`, scan backward through the prefix, return the first containing hit. Complexity: `O(log N_file + D)` typical (D = lexical depth ≤ ~10); degrades to `O(N_file)` only under pathological inputs (many scopes starting at the same position). "Innermost wins" falls out of the sort + backward-scan contract because `ScopeTree`'s invariants guarantee that scopes containing a point form an ancestor chain. Types: - `ScopeTree` now exported from `scope-tree.ts`. The Ring 1 opaque placeholder in `types.ts` has been removed; LanguageProvider hooks that previously took `ScopeTree = unknown` now receive the concrete interface (CLI `tsc --noEmit` passes — no existing callers rely on the opaque shape). Tests (39, all passing): - scope-id: canonical shape · all six ScopeKinds encoded · identity equality (same inputs → same reference) · distinguished by filePath / range / kind · purity under repeated calls · intern-pool clear preserves canonical shape. - scope-tree: empty tree · single module · nested Module→Class→Function · multiple siblings input-order preserved · ScopeLookup integration with resolveTypeRef · frozen children and ancestor arrays · all six invariant violations (non-Module orphan, parent-not-found, parent doesn't contain, parent == child, siblings overlap, cross-file parent, duplicate id) · boundary-touching siblings accepted. - position-index: empty · unindexed filePath · before/after-file queries · start/end inclusivity · innermost-wins for nested / co- starting / co-ending / same-line scopes · sibling dispatch · multi- file isolation · size · id-dedup. Combined scope-resolution / model / shadow suite: 190/190 pass. `tsc --noEmit` clean in both `gitnexus-shared` and `gitnexus`. Closes part of #909. Unblocks #917 (`Registry.lookup` needs the scope spine); makes `ScopeLookup` in #916 concrete without API churn. |
||
|---|---|---|
| .. | ||
| src | ||
| package-lock.json | ||
| package.json | ||
| tsconfig.json | ||