gitnexus 1.6.3-rc.2 → 1.6.3-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_shared/graph/types.d.ts +16 -0
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +41 -1
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +28 -0
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/scope-resolution/def-index.d.ts +36 -0
- package/dist/_shared/scope-resolution/def-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/def-index.js +51 -0
- package/dist/_shared/scope-resolution/def-index.js.map +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +139 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.js +479 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +80 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.js +79 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -0
- package/dist/_shared/scope-resolution/module-scope-index.d.ts +46 -0
- package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/module-scope-index.js +58 -0
- package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts +64 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/parsed-file.js +42 -0
- package/dist/_shared/scope-resolution/parsed-file.js.map +1 -0
- package/dist/_shared/scope-resolution/position-index.d.ts +62 -0
- package/dist/_shared/scope-resolution/position-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/position-index.js +134 -0
- package/dist/_shared/scope-resolution/position-index.js.map +1 -0
- package/dist/_shared/scope-resolution/qualified-name-index.d.ts +44 -0
- package/dist/_shared/scope-resolution/qualified-name-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/qualified-name-index.js +75 -0
- package/dist/_shared/scope-resolution/qualified-name-index.js.map +1 -0
- package/dist/_shared/scope-resolution/reference-site.d.ts +67 -0
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/reference-site.js +24 -0
- package/dist/_shared/scope-resolution/reference-site.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/class-registry.d.ts +27 -0
- package/dist/_shared/scope-resolution/registries/class-registry.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/class-registry.js +30 -0
- package/dist/_shared/scope-resolution/registries/class-registry.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/context.d.ts +69 -0
- package/dist/_shared/scope-resolution/registries/context.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/context.js +44 -0
- package/dist/_shared/scope-resolution/registries/context.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/evidence.d.ts +56 -0
- package/dist/_shared/scope-resolution/registries/evidence.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/evidence.js +150 -0
- package/dist/_shared/scope-resolution/registries/evidence.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/field-registry.d.ts +26 -0
- package/dist/_shared/scope-resolution/registries/field-registry.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/field-registry.js +31 -0
- package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/lookup-core.d.ts +81 -0
- package/dist/_shared/scope-resolution/registries/lookup-core.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/lookup-core.js +332 -0
- package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/lookup-qualified.d.ts +33 -0
- package/dist/_shared/scope-resolution/registries/lookup-qualified.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/lookup-qualified.js +56 -0
- package/dist/_shared/scope-resolution/registries/lookup-qualified.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/method-registry.d.ts +36 -0
- package/dist/_shared/scope-resolution/registries/method-registry.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/method-registry.js +32 -0
- package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -0
- package/dist/_shared/scope-resolution/registries/tie-breaks.d.ts +43 -0
- package/dist/_shared/scope-resolution/registries/tie-breaks.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/registries/tie-breaks.js +60 -0
- package/dist/_shared/scope-resolution/registries/tie-breaks.js.map +1 -0
- package/dist/_shared/scope-resolution/resolve-type-ref.d.ts +53 -0
- package/dist/_shared/scope-resolution/resolve-type-ref.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/resolve-type-ref.js +126 -0
- package/dist/_shared/scope-resolution/resolve-type-ref.js.map +1 -0
- package/dist/_shared/scope-resolution/scope-id.d.ts +43 -0
- package/dist/_shared/scope-resolution/scope-id.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/scope-id.js +46 -0
- package/dist/_shared/scope-resolution/scope-id.js.map +1 -0
- package/dist/_shared/scope-resolution/scope-tree.d.ts +61 -0
- package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/scope-tree.js +186 -0
- package/dist/_shared/scope-resolution/scope-tree.js.map +1 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +63 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.js +122 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.js.map +1 -0
- package/dist/_shared/scope-resolution/shadow/diff.d.ts +59 -0
- package/dist/_shared/scope-resolution/shadow/diff.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/shadow/diff.js +79 -0
- package/dist/_shared/scope-resolution/shadow/diff.js.map +1 -0
- package/dist/_shared/scope-resolution/types.d.ts +156 -0
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/analyze.d.ts +15 -0
- package/dist/cli/analyze.js +22 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/list.js +11 -1
- package/dist/core/ingestion/emit-references.d.ts +88 -0
- package/dist/core/ingestion/emit-references.js +229 -0
- package/dist/core/ingestion/finalize-orchestrator.d.ts +63 -0
- package/dist/core/ingestion/finalize-orchestrator.js +139 -0
- package/dist/core/ingestion/framework-detection.js +6 -2
- package/dist/core/ingestion/import-target-adapter.d.ts +73 -0
- package/dist/core/ingestion/import-target-adapter.js +95 -0
- package/dist/core/ingestion/language-provider.d.ts +187 -1
- package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +59 -0
- package/dist/core/ingestion/model/scope-resolution-indexes.js +42 -0
- package/dist/core/ingestion/model/semantic-model.d.ts +25 -0
- package/dist/core/ingestion/model/semantic-model.js +16 -0
- package/dist/core/ingestion/parsing-processor.d.ts +9 -0
- package/dist/core/ingestion/parsing-processor.js +10 -0
- package/dist/core/ingestion/registry-primary-flag.d.ts +59 -0
- package/dist/core/ingestion/registry-primary-flag.js +78 -0
- package/dist/core/ingestion/scope-extractor-bridge.d.ts +32 -0
- package/dist/core/ingestion/scope-extractor-bridge.js +44 -0
- package/dist/core/ingestion/scope-extractor.d.ts +87 -0
- package/dist/core/ingestion/scope-extractor.js +603 -0
- package/dist/core/ingestion/shadow-harness.d.ts +113 -0
- package/dist/core/ingestion/shadow-harness.js +148 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +9 -0
- package/dist/core/ingestion/workers/parse-worker.js +20 -1
- package/dist/core/run-analyze.d.ts +21 -0
- package/dist/core/run-analyze.js +15 -4
- package/dist/core/search/phase-timer.d.ts +72 -0
- package/dist/core/search/phase-timer.js +106 -0
- package/dist/mcp/local/local-backend.js +70 -8
- package/dist/storage/git.d.ts +25 -0
- package/dist/storage/git.js +52 -0
- package/dist/storage/repo-manager.d.ts +70 -1
- package/dist/storage/repo-manager.js +107 -5
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolveTypeRef` — strict single-return resolver for `TypeRef`s
|
|
3
|
+
* (RFC §4.6; Ring 2 SHARED #916).
|
|
4
|
+
*
|
|
5
|
+
* Narrower contract than `Registry.lookup`: no name-only global fallback, no
|
|
6
|
+
* confidence ranking, no arity check. Used by `Registry.lookup` Step 2 (type-
|
|
7
|
+
* binding propagation) and by any caller that wants the single best type-
|
|
8
|
+
* target for an annotation without paying for the full evidence pipeline.
|
|
9
|
+
*
|
|
10
|
+
* **Algorithm (strict).** Walk the scope chain from `ref.declaredAtScope`:
|
|
11
|
+
*
|
|
12
|
+
* 1. At each scope, inspect `bindings.get(ref.rawName)`:
|
|
13
|
+
* - If one of the bindings is a **type-kind** def with a **strict origin**
|
|
14
|
+
* (`'local' | 'import' | 'namespace' | 'reexport'`), return it.
|
|
15
|
+
* - If any binding for this name exists at this scope but none qualifies
|
|
16
|
+
* (e.g., a local variable named `User` shadows an outer import of class
|
|
17
|
+
* `User`), return `null`. The nearer binding shadows; we do NOT fall
|
|
18
|
+
* through to the global qualified-name index.
|
|
19
|
+
* - Otherwise continue to the parent scope.
|
|
20
|
+
* 2. If the raw name is a dotted path (e.g., `'models.User'`) and the scope
|
|
21
|
+
* walk produced no match, consult `QualifiedNameIndex.byQualifiedName`.
|
|
22
|
+
* Only accept **exactly one** type-kind hit — anything ambiguous returns
|
|
23
|
+
* `null` rather than a guess.
|
|
24
|
+
* 3. Return `null`.
|
|
25
|
+
*
|
|
26
|
+
* **What `'strict' origins' means.** `'wildcard'` is intentionally excluded.
|
|
27
|
+
* A wildcard-expanded name (`from x import *`) is too loose to use as an
|
|
28
|
+
* anchor for type resolution — it gives no signal about whether the name was
|
|
29
|
+
* actually imported. `Registry.lookup` may accept wildcard bindings at its
|
|
30
|
+
* own discretion (with lower evidence weight); `resolveTypeRef` does not.
|
|
31
|
+
*
|
|
32
|
+
* **What 'type-kind' means.** The subset of `NodeLabel` that a type annotation
|
|
33
|
+
* may legitimately reference: class-like, interface-like, enum-like, and
|
|
34
|
+
* alias-like kinds. See `TYPE_KINDS` below.
|
|
35
|
+
*
|
|
36
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
37
|
+
*/
|
|
38
|
+
import type { SymbolDefinition } from './symbol-definition.js';
|
|
39
|
+
import type { ScopeLookup, TypeRef } from './types.js';
|
|
40
|
+
import type { DefIndex } from './def-index.js';
|
|
41
|
+
import type { QualifiedNameIndex } from './qualified-name-index.js';
|
|
42
|
+
/**
|
|
43
|
+
* All inputs `resolveTypeRef` needs from the semantic model. Bundled into a
|
|
44
|
+
* context object so the call site stays short and the interface is stable as
|
|
45
|
+
* additional indexes get threaded through in later rings.
|
|
46
|
+
*/
|
|
47
|
+
export interface ResolveTypeRefContext {
|
|
48
|
+
readonly scopes: ScopeLookup;
|
|
49
|
+
readonly defIndex: DefIndex;
|
|
50
|
+
readonly qualifiedNameIndex: QualifiedNameIndex;
|
|
51
|
+
}
|
|
52
|
+
export declare function resolveTypeRef(ref: TypeRef, ctx: ResolveTypeRefContext): SymbolDefinition | null;
|
|
53
|
+
//# sourceMappingURL=resolve-type-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-type-ref.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/resolve-type-ref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAuB,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIpE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CACjD;AA4CD,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,IAAI,CAgDhG"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolveTypeRef` — strict single-return resolver for `TypeRef`s
|
|
3
|
+
* (RFC §4.6; Ring 2 SHARED #916).
|
|
4
|
+
*
|
|
5
|
+
* Narrower contract than `Registry.lookup`: no name-only global fallback, no
|
|
6
|
+
* confidence ranking, no arity check. Used by `Registry.lookup` Step 2 (type-
|
|
7
|
+
* binding propagation) and by any caller that wants the single best type-
|
|
8
|
+
* target for an annotation without paying for the full evidence pipeline.
|
|
9
|
+
*
|
|
10
|
+
* **Algorithm (strict).** Walk the scope chain from `ref.declaredAtScope`:
|
|
11
|
+
*
|
|
12
|
+
* 1. At each scope, inspect `bindings.get(ref.rawName)`:
|
|
13
|
+
* - If one of the bindings is a **type-kind** def with a **strict origin**
|
|
14
|
+
* (`'local' | 'import' | 'namespace' | 'reexport'`), return it.
|
|
15
|
+
* - If any binding for this name exists at this scope but none qualifies
|
|
16
|
+
* (e.g., a local variable named `User` shadows an outer import of class
|
|
17
|
+
* `User`), return `null`. The nearer binding shadows; we do NOT fall
|
|
18
|
+
* through to the global qualified-name index.
|
|
19
|
+
* - Otherwise continue to the parent scope.
|
|
20
|
+
* 2. If the raw name is a dotted path (e.g., `'models.User'`) and the scope
|
|
21
|
+
* walk produced no match, consult `QualifiedNameIndex.byQualifiedName`.
|
|
22
|
+
* Only accept **exactly one** type-kind hit — anything ambiguous returns
|
|
23
|
+
* `null` rather than a guess.
|
|
24
|
+
* 3. Return `null`.
|
|
25
|
+
*
|
|
26
|
+
* **What `'strict' origins' means.** `'wildcard'` is intentionally excluded.
|
|
27
|
+
* A wildcard-expanded name (`from x import *`) is too loose to use as an
|
|
28
|
+
* anchor for type resolution — it gives no signal about whether the name was
|
|
29
|
+
* actually imported. `Registry.lookup` may accept wildcard bindings at its
|
|
30
|
+
* own discretion (with lower evidence weight); `resolveTypeRef` does not.
|
|
31
|
+
*
|
|
32
|
+
* **What 'type-kind' means.** The subset of `NodeLabel` that a type annotation
|
|
33
|
+
* may legitimately reference: class-like, interface-like, enum-like, and
|
|
34
|
+
* alias-like kinds. See `TYPE_KINDS` below.
|
|
35
|
+
*
|
|
36
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
37
|
+
*/
|
|
38
|
+
// ─── Strict policy constants ────────────────────────────────────────────────
|
|
39
|
+
/** `'wildcard'` is deliberately absent. See file header. */
|
|
40
|
+
const STRICT_ORIGINS = new Set([
|
|
41
|
+
'local',
|
|
42
|
+
'import',
|
|
43
|
+
'namespace',
|
|
44
|
+
'reexport',
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* `NodeLabel` values that may appear on the RHS of a type annotation.
|
|
48
|
+
*
|
|
49
|
+
* Includes the usual class-like and interface-like kinds plus the alias-like
|
|
50
|
+
* ones (`TypeAlias`, `Typedef`). `Namespace` is excluded — it is a scope
|
|
51
|
+
* container, not a value type. `Function` / `Method` / `Variable` are
|
|
52
|
+
* excluded by design: a `rawName` bound to them at a strict origin is a
|
|
53
|
+
* *shadowing* binding, which the algorithm short-circuits to `null`.
|
|
54
|
+
*
|
|
55
|
+
* `'Type'` (the generic `NodeLabel` value) is also excluded — verified
|
|
56
|
+
* against `gitnexus/src/core/ingestion/` at the time of writing, no
|
|
57
|
+
* production extractor emits `type: 'Type'` for annotation-relevant
|
|
58
|
+
* symbols. Should a future extractor start emitting it, add `'Type'`
|
|
59
|
+
* here and add a test asserting the new path.
|
|
60
|
+
*/
|
|
61
|
+
const TYPE_KINDS = new Set([
|
|
62
|
+
'Class',
|
|
63
|
+
'Interface',
|
|
64
|
+
'Enum',
|
|
65
|
+
'Struct',
|
|
66
|
+
'Union',
|
|
67
|
+
'Trait',
|
|
68
|
+
'TypeAlias',
|
|
69
|
+
'Typedef',
|
|
70
|
+
'Record',
|
|
71
|
+
'Delegate',
|
|
72
|
+
'Annotation',
|
|
73
|
+
'Template',
|
|
74
|
+
]);
|
|
75
|
+
// ─── Main entry point ──────────────────────────────────────────────────────
|
|
76
|
+
export function resolveTypeRef(ref, ctx) {
|
|
77
|
+
// Phase 1: scope-chain walk anchored at the declaration site.
|
|
78
|
+
let currentId = ref.declaredAtScope;
|
|
79
|
+
const visited = new Set();
|
|
80
|
+
while (currentId !== null) {
|
|
81
|
+
// Cycle guard — a well-formed scope tree never loops, but a bug in the
|
|
82
|
+
// construction path should fail fast here rather than hanging.
|
|
83
|
+
if (visited.has(currentId))
|
|
84
|
+
return null;
|
|
85
|
+
visited.add(currentId);
|
|
86
|
+
const scope = ctx.scopes.getScope(currentId);
|
|
87
|
+
if (scope === undefined)
|
|
88
|
+
return null; // broken chain = unresolvable
|
|
89
|
+
const bindings = scope.bindings.get(ref.rawName);
|
|
90
|
+
if (bindings !== undefined && bindings.length > 0) {
|
|
91
|
+
// At least one binding exists at this scope → it is the shadowing site.
|
|
92
|
+
// Either one of them qualifies, or the name is shadowed by a non-type.
|
|
93
|
+
for (const binding of bindings) {
|
|
94
|
+
if (!STRICT_ORIGINS.has(binding.origin))
|
|
95
|
+
continue;
|
|
96
|
+
if (TYPE_KINDS.has(binding.def.type)) {
|
|
97
|
+
return binding.def;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Shadowed by a non-type / non-strict-origin binding. Fail fast — no
|
|
101
|
+
// global fallback, no walk to the parent.
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
currentId = scope.parent;
|
|
105
|
+
}
|
|
106
|
+
// Phase 2: dotted fallback via `QualifiedNameIndex`. Only accept a unique
|
|
107
|
+
// type-kind hit; anything ambiguous returns null (strict: no guesses).
|
|
108
|
+
if (ref.rawName.includes('.')) {
|
|
109
|
+
const candidates = ctx.qualifiedNameIndex.get(ref.rawName);
|
|
110
|
+
let onlyTypeDef = null;
|
|
111
|
+
for (const defId of candidates) {
|
|
112
|
+
const def = ctx.defIndex.get(defId);
|
|
113
|
+
if (def === undefined)
|
|
114
|
+
continue;
|
|
115
|
+
if (!TYPE_KINDS.has(def.type))
|
|
116
|
+
continue;
|
|
117
|
+
if (onlyTypeDef !== null)
|
|
118
|
+
return null; // ambiguous
|
|
119
|
+
onlyTypeDef = def;
|
|
120
|
+
}
|
|
121
|
+
if (onlyTypeDef !== null)
|
|
122
|
+
return onlyTypeDef;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=resolve-type-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-type-ref.js","sourceRoot":"","sources":["../../src/scope-resolution/resolve-type-ref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAqBH,+EAA+E;AAE/E,4DAA4D;AAC5D,MAAM,cAAc,GAAsC,IAAI,GAAG,CAAuB;IACtF,OAAO;IACP,QAAQ;IACR,WAAW;IACX,UAAU;CACX,CAAC,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,GAA2B,IAAI,GAAG,CAAY;IAC5D,OAAO;IACP,WAAW;IACX,MAAM;IACN,QAAQ;IACR,OAAO;IACP,OAAO;IACP,WAAW;IACX,SAAS;IACT,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,UAAU;CACX,CAAC,CAAC;AAEH,8EAA8E;AAE9E,MAAM,UAAU,cAAc,CAAC,GAAY,EAAE,GAA0B;IACrE,8DAA8D;IAC9D,IAAI,SAAS,GAAmB,GAAG,CAAC,eAAe,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAW,CAAC;IAEnC,OAAO,SAAS,KAAK,IAAI,EAAE,CAAC;QAC1B,uEAAuE;QACvE,+DAA+D;QAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEvB,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,CAAC,8BAA8B;QAEpE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,wEAAwE;YACxE,uEAAuE;YACvE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;oBAAE,SAAS;gBAClD,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrC,OAAO,OAAO,CAAC,GAAG,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,qEAAqE;YACrE,0CAA0C;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,WAAW,GAA4B,IAAI,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS;YAChC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YACxC,IAAI,WAAW,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC,CAAC,YAAY;YACnD,WAAW,GAAG,GAAG,CAAC;QACpB,CAAC;QACD,IAAI,WAAW,KAAK,IAAI;YAAE,OAAO,WAAW,CAAC;IAC/C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ScopeId` canonical constructor + string intern pool
|
|
3
|
+
* (RFC §2.2; Ring 2 SHARED #912).
|
|
4
|
+
*
|
|
5
|
+
* `ScopeId` is a deterministic string derived from the scope's file path,
|
|
6
|
+
* byte range, and kind:
|
|
7
|
+
*
|
|
8
|
+
* scope:{filePath}#{startLine}:{startCol}-{endLine}:{endCol}:{kind}
|
|
9
|
+
*
|
|
10
|
+
* Two scopes produced by reparsing the same file at the same positions are
|
|
11
|
+
* `===`-equal as strings. Beyond the canonical shape, `makeScopeId` also
|
|
12
|
+
* **interns** the string through a process-local pool, so repeated calls
|
|
13
|
+
* with structurally identical inputs return the same string reference —
|
|
14
|
+
* making `Map<ScopeId, ...>` lookups and cache keys identity-fast.
|
|
15
|
+
*
|
|
16
|
+
* The intern pool is unbounded. The number of distinct `ScopeId`s across a
|
|
17
|
+
* single indexing run is O(total scopes in workspace), which is bounded by
|
|
18
|
+
* source-text size and already in memory; interning adds no asymptotic
|
|
19
|
+
* pressure. `clearScopeIdInternPool` is exported for test isolation.
|
|
20
|
+
*/
|
|
21
|
+
import type { Range } from './types.js';
|
|
22
|
+
import type { ScopeId, ScopeKind } from './types.js';
|
|
23
|
+
/** Inputs required to construct a canonical `ScopeId`. */
|
|
24
|
+
export interface ScopeIdInput {
|
|
25
|
+
readonly filePath: string;
|
|
26
|
+
readonly range: Range;
|
|
27
|
+
readonly kind: ScopeKind;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build a canonical `ScopeId` from its structural parts and intern it.
|
|
31
|
+
*
|
|
32
|
+
* Pure + referentially transparent: given the same input shape, always
|
|
33
|
+
* returns the same string reference for the lifetime of the pool.
|
|
34
|
+
*/
|
|
35
|
+
export declare function makeScopeId(input: ScopeIdInput): ScopeId;
|
|
36
|
+
/**
|
|
37
|
+
* Drop the intern pool. Intended for test setup/teardown — production code
|
|
38
|
+
* should not need this, since the pool's memory usage is bounded by the
|
|
39
|
+
* number of live scopes and cleaning it mid-run would break identity
|
|
40
|
+
* equality for existing scope ids.
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearScopeIdInternPool(): void;
|
|
43
|
+
//# sourceMappingURL=scope-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-id.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/scope-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAErD,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAMxD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ScopeId` canonical constructor + string intern pool
|
|
3
|
+
* (RFC §2.2; Ring 2 SHARED #912).
|
|
4
|
+
*
|
|
5
|
+
* `ScopeId` is a deterministic string derived from the scope's file path,
|
|
6
|
+
* byte range, and kind:
|
|
7
|
+
*
|
|
8
|
+
* scope:{filePath}#{startLine}:{startCol}-{endLine}:{endCol}:{kind}
|
|
9
|
+
*
|
|
10
|
+
* Two scopes produced by reparsing the same file at the same positions are
|
|
11
|
+
* `===`-equal as strings. Beyond the canonical shape, `makeScopeId` also
|
|
12
|
+
* **interns** the string through a process-local pool, so repeated calls
|
|
13
|
+
* with structurally identical inputs return the same string reference —
|
|
14
|
+
* making `Map<ScopeId, ...>` lookups and cache keys identity-fast.
|
|
15
|
+
*
|
|
16
|
+
* The intern pool is unbounded. The number of distinct `ScopeId`s across a
|
|
17
|
+
* single indexing run is O(total scopes in workspace), which is bounded by
|
|
18
|
+
* source-text size and already in memory; interning adds no asymptotic
|
|
19
|
+
* pressure. `clearScopeIdInternPool` is exported for test isolation.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Build a canonical `ScopeId` from its structural parts and intern it.
|
|
23
|
+
*
|
|
24
|
+
* Pure + referentially transparent: given the same input shape, always
|
|
25
|
+
* returns the same string reference for the lifetime of the pool.
|
|
26
|
+
*/
|
|
27
|
+
export function makeScopeId(input) {
|
|
28
|
+
const raw = `scope:${input.filePath}#${input.range.startLine}:${input.range.startCol}-${input.range.endLine}:${input.range.endCol}:${input.kind}`;
|
|
29
|
+
const existing = INTERN_POOL.get(raw);
|
|
30
|
+
if (existing !== undefined)
|
|
31
|
+
return existing;
|
|
32
|
+
INTERN_POOL.set(raw, raw);
|
|
33
|
+
return raw;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Drop the intern pool. Intended for test setup/teardown — production code
|
|
37
|
+
* should not need this, since the pool's memory usage is bounded by the
|
|
38
|
+
* number of live scopes and cleaning it mid-run would break identity
|
|
39
|
+
* equality for existing scope ids.
|
|
40
|
+
*/
|
|
41
|
+
export function clearScopeIdInternPool() {
|
|
42
|
+
INTERN_POOL.clear();
|
|
43
|
+
}
|
|
44
|
+
/** Internal: shared intern pool (process-local). */
|
|
45
|
+
const INTERN_POOL = new Map();
|
|
46
|
+
//# sourceMappingURL=scope-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-id.js","sourceRoot":"","sources":["../../src/scope-resolution/scope-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAYH;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAmB;IAC7C,MAAM,GAAG,GAAG,SAAS,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;IAClJ,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB;IACpC,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,oDAAoD;AACpD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ScopeTree` — the lexical-scope spine of the `SemanticModel`
|
|
3
|
+
* (RFC §2.2 + §3.1; Ring 2 SHARED #912).
|
|
4
|
+
*
|
|
5
|
+
* Generalizes the `enclosingFunctions` pattern from closed PR #902 to
|
|
6
|
+
* arbitrary `ScopeKind`s. Owns the (parent ↔ children) relationship
|
|
7
|
+
* derived from each `Scope.parent` pointer, and validates the structural
|
|
8
|
+
* invariants a well-formed scope tree must satisfy.
|
|
9
|
+
*
|
|
10
|
+
* Invariants enforced at build time (throw on violation):
|
|
11
|
+
*
|
|
12
|
+
* - Every non-`Module` scope has a non-null parent.
|
|
13
|
+
* - Every parent pointer references a scope that was also supplied to
|
|
14
|
+
* `buildScopeTree`.
|
|
15
|
+
* - Parent range **strictly contains** child range.
|
|
16
|
+
* - Sibling ranges under the same parent do not overlap.
|
|
17
|
+
* - Parent and child live in the same `filePath`. (Cross-file parent
|
|
18
|
+
* pointers would be a category error — a `File` scope is not the
|
|
19
|
+
* parent of another file's scopes; imports do that job.)
|
|
20
|
+
*
|
|
21
|
+
* Satisfies the `ScopeLookup` contract (defined in `./types.js`), so
|
|
22
|
+
* `resolveTypeRef` (#916) and the scope-aware registries (#917) can take a
|
|
23
|
+
* `ScopeTree` directly without adapters.
|
|
24
|
+
*
|
|
25
|
+
* Immutable surface: `byId` is a `ReadonlyMap`; children arrays are
|
|
26
|
+
* `Object.freeze`d; miss lookups return a shared frozen empty array.
|
|
27
|
+
*/
|
|
28
|
+
import type { Scope, ScopeId, ScopeLookup } from './types.js';
|
|
29
|
+
export interface ScopeTree extends ScopeLookup {
|
|
30
|
+
readonly size: number;
|
|
31
|
+
readonly byId: ReadonlyMap<ScopeId, Scope>;
|
|
32
|
+
getScope(id: ScopeId): Scope | undefined;
|
|
33
|
+
getParent(id: ScopeId): Scope | undefined;
|
|
34
|
+
/** Child `ScopeId`s of `id`, in input order. Frozen empty array on miss. */
|
|
35
|
+
getChildren(id: ScopeId): readonly ScopeId[];
|
|
36
|
+
/**
|
|
37
|
+
* Ancestor chain from the immediate parent up to (and including) the
|
|
38
|
+
* root module scope. Excludes the starting scope itself. Frozen empty
|
|
39
|
+
* array on miss / for a root scope.
|
|
40
|
+
*/
|
|
41
|
+
getAncestors(id: ScopeId): readonly ScopeId[];
|
|
42
|
+
has(id: ScopeId): boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Thrown by `buildScopeTree` when the input violates a structural
|
|
46
|
+
* invariant. Carries the offending ids + the invariant name so failed
|
|
47
|
+
* extraction pipelines can report actionable diagnostics.
|
|
48
|
+
*/
|
|
49
|
+
export declare class ScopeTreeInvariantError extends Error {
|
|
50
|
+
readonly invariant: 'non-module-requires-parent' | 'parent-not-found' | 'parent-must-contain-child' | 'sibling-ranges-overlap' | 'parent-must-share-filepath' | 'duplicate-scope-id';
|
|
51
|
+
constructor(invariant: 'non-module-requires-parent' | 'parent-not-found' | 'parent-must-contain-child' | 'sibling-ranges-overlap' | 'parent-must-share-filepath' | 'duplicate-scope-id', message: string);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build an immutable `ScopeTree` from a flat list of `Scope` records.
|
|
55
|
+
*
|
|
56
|
+
* Throws `ScopeTreeInvariantError` on the first invariant violation; a
|
|
57
|
+
* malformed tree is a bug in the extraction pipeline, not a data case for
|
|
58
|
+
* consumers to handle, so fail-fast is the correct posture.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildScopeTree(scopes: readonly Scope[]): ScopeTree;
|
|
61
|
+
//# sourceMappingURL=scope-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-tree.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/scope-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAS,MAAM,YAAY,CAAC;AAIrE,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE3C,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IACzC,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IAC1C,4EAA4E;IAC5E,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,CAAC;IAC7C;;;;OAIG;IACH,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,CAAC;IAC9C,GAAG,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC;CAC3B;AAID;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAE9C,QAAQ,CAAC,SAAS,EACd,4BAA4B,GAC5B,kBAAkB,GAClB,2BAA2B,GAC3B,wBAAwB,GACxB,4BAA4B,GAC5B,oBAAoB;gBANf,SAAS,EACd,4BAA4B,GAC5B,kBAAkB,GAClB,2BAA2B,GAC3B,wBAAwB,GACxB,4BAA4B,GAC5B,oBAAoB,EACxB,OAAO,EAAE,MAAM;CAKlB;AAID;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,SAAS,CAiFlE"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ScopeTree` — the lexical-scope spine of the `SemanticModel`
|
|
3
|
+
* (RFC §2.2 + §3.1; Ring 2 SHARED #912).
|
|
4
|
+
*
|
|
5
|
+
* Generalizes the `enclosingFunctions` pattern from closed PR #902 to
|
|
6
|
+
* arbitrary `ScopeKind`s. Owns the (parent ↔ children) relationship
|
|
7
|
+
* derived from each `Scope.parent` pointer, and validates the structural
|
|
8
|
+
* invariants a well-formed scope tree must satisfy.
|
|
9
|
+
*
|
|
10
|
+
* Invariants enforced at build time (throw on violation):
|
|
11
|
+
*
|
|
12
|
+
* - Every non-`Module` scope has a non-null parent.
|
|
13
|
+
* - Every parent pointer references a scope that was also supplied to
|
|
14
|
+
* `buildScopeTree`.
|
|
15
|
+
* - Parent range **strictly contains** child range.
|
|
16
|
+
* - Sibling ranges under the same parent do not overlap.
|
|
17
|
+
* - Parent and child live in the same `filePath`. (Cross-file parent
|
|
18
|
+
* pointers would be a category error — a `File` scope is not the
|
|
19
|
+
* parent of another file's scopes; imports do that job.)
|
|
20
|
+
*
|
|
21
|
+
* Satisfies the `ScopeLookup` contract (defined in `./types.js`), so
|
|
22
|
+
* `resolveTypeRef` (#916) and the scope-aware registries (#917) can take a
|
|
23
|
+
* `ScopeTree` directly without adapters.
|
|
24
|
+
*
|
|
25
|
+
* Immutable surface: `byId` is a `ReadonlyMap`; children arrays are
|
|
26
|
+
* `Object.freeze`d; miss lookups return a shared frozen empty array.
|
|
27
|
+
*/
|
|
28
|
+
// ─── Build errors ───────────────────────────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Thrown by `buildScopeTree` when the input violates a structural
|
|
31
|
+
* invariant. Carries the offending ids + the invariant name so failed
|
|
32
|
+
* extraction pipelines can report actionable diagnostics.
|
|
33
|
+
*/
|
|
34
|
+
export class ScopeTreeInvariantError extends Error {
|
|
35
|
+
invariant;
|
|
36
|
+
constructor(invariant, message) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.invariant = invariant;
|
|
39
|
+
this.name = 'ScopeTreeInvariantError';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// ─── Builder ───────────────────────────────────────────────────────────────
|
|
43
|
+
/**
|
|
44
|
+
* Build an immutable `ScopeTree` from a flat list of `Scope` records.
|
|
45
|
+
*
|
|
46
|
+
* Throws `ScopeTreeInvariantError` on the first invariant violation; a
|
|
47
|
+
* malformed tree is a bug in the extraction pipeline, not a data case for
|
|
48
|
+
* consumers to handle, so fail-fast is the correct posture.
|
|
49
|
+
*/
|
|
50
|
+
export function buildScopeTree(scopes) {
|
|
51
|
+
const byId = new Map();
|
|
52
|
+
const childrenById = new Map();
|
|
53
|
+
// ── Pass 1: collect by id + duplicate check ───────────────────────────
|
|
54
|
+
for (const scope of scopes) {
|
|
55
|
+
if (byId.has(scope.id)) {
|
|
56
|
+
throw new ScopeTreeInvariantError('duplicate-scope-id', `Two scopes share id '${scope.id}'. Scope ids must be unique per tree.`);
|
|
57
|
+
}
|
|
58
|
+
byId.set(scope.id, scope);
|
|
59
|
+
}
|
|
60
|
+
// ── Pass 2: validate parent pointers + build children buckets ─────────
|
|
61
|
+
for (const scope of scopes) {
|
|
62
|
+
if (scope.parent === null) {
|
|
63
|
+
if (scope.kind !== 'Module') {
|
|
64
|
+
throw new ScopeTreeInvariantError('non-module-requires-parent', `Scope '${scope.id}' has kind '${scope.kind}' but no parent. Only 'Module' scopes may be root-level.`);
|
|
65
|
+
}
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const parent = byId.get(scope.parent);
|
|
69
|
+
if (parent === undefined) {
|
|
70
|
+
throw new ScopeTreeInvariantError('parent-not-found', `Scope '${scope.id}' references parent '${scope.parent}' which is not part of this tree.`);
|
|
71
|
+
}
|
|
72
|
+
if (parent.filePath !== scope.filePath) {
|
|
73
|
+
throw new ScopeTreeInvariantError('parent-must-share-filepath', `Scope '${scope.id}' (${scope.filePath}) has parent '${parent.id}' in a different file (${parent.filePath}). Parent/child scopes must share filePath.`);
|
|
74
|
+
}
|
|
75
|
+
if (!rangeStrictlyContains(parent.range, scope.range)) {
|
|
76
|
+
throw new ScopeTreeInvariantError('parent-must-contain-child', `Parent scope '${parent.id}' at ${formatRange(parent.range)} does not strictly contain child '${scope.id}' at ${formatRange(scope.range)}.`);
|
|
77
|
+
}
|
|
78
|
+
let bucket = childrenById.get(parent.id);
|
|
79
|
+
if (bucket === undefined) {
|
|
80
|
+
bucket = [];
|
|
81
|
+
childrenById.set(parent.id, bucket);
|
|
82
|
+
}
|
|
83
|
+
bucket.push(scope.id);
|
|
84
|
+
}
|
|
85
|
+
// ── Pass 3: sibling-overlap check ─────────────────────────────────────
|
|
86
|
+
for (const [parentId, childIds] of childrenById) {
|
|
87
|
+
if (childIds.length < 2)
|
|
88
|
+
continue;
|
|
89
|
+
// Sort siblings by (startLine, startCol) for an O(n log n) pairwise
|
|
90
|
+
// scan instead of O(n²) all-pairs.
|
|
91
|
+
const children = childIds.map((id) => byId.get(id)).slice();
|
|
92
|
+
children.sort((a, b) => comparePosition(a.range, b.range));
|
|
93
|
+
for (let i = 1; i < children.length; i++) {
|
|
94
|
+
const prev = children[i - 1];
|
|
95
|
+
const curr = children[i];
|
|
96
|
+
if (rangesOverlap(prev.range, curr.range)) {
|
|
97
|
+
throw new ScopeTreeInvariantError('sibling-ranges-overlap', `Sibling scopes under parent '${parentId}' overlap: '${prev.id}' ${formatRange(prev.range)} and '${curr.id}' ${formatRange(curr.range)}.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Freeze children arrays so the surface is truly read-only.
|
|
102
|
+
const frozenChildren = new Map();
|
|
103
|
+
for (const [parentId, childIds] of childrenById) {
|
|
104
|
+
frozenChildren.set(parentId, Object.freeze(childIds.slice()));
|
|
105
|
+
}
|
|
106
|
+
return freezeTree(byId, frozenChildren);
|
|
107
|
+
}
|
|
108
|
+
// ─── Internals ──────────────────────────────────────────────────────────────
|
|
109
|
+
const EMPTY_CHILDREN = Object.freeze([]);
|
|
110
|
+
function freezeTree(byId, childrenById) {
|
|
111
|
+
return {
|
|
112
|
+
byId,
|
|
113
|
+
get size() {
|
|
114
|
+
return byId.size;
|
|
115
|
+
},
|
|
116
|
+
getScope(id) {
|
|
117
|
+
return byId.get(id);
|
|
118
|
+
},
|
|
119
|
+
getParent(id) {
|
|
120
|
+
const scope = byId.get(id);
|
|
121
|
+
if (scope === undefined || scope.parent === null)
|
|
122
|
+
return undefined;
|
|
123
|
+
return byId.get(scope.parent);
|
|
124
|
+
},
|
|
125
|
+
getChildren(id) {
|
|
126
|
+
return childrenById.get(id) ?? EMPTY_CHILDREN;
|
|
127
|
+
},
|
|
128
|
+
getAncestors(id) {
|
|
129
|
+
const start = byId.get(id);
|
|
130
|
+
if (start === undefined || start.parent === null)
|
|
131
|
+
return EMPTY_CHILDREN;
|
|
132
|
+
const out = [];
|
|
133
|
+
const visited = new Set([id]);
|
|
134
|
+
let cursor = start.parent;
|
|
135
|
+
while (cursor !== null && !visited.has(cursor)) {
|
|
136
|
+
visited.add(cursor);
|
|
137
|
+
out.push(cursor);
|
|
138
|
+
const next = byId.get(cursor);
|
|
139
|
+
cursor = next === undefined ? null : next.parent;
|
|
140
|
+
}
|
|
141
|
+
return Object.freeze(out);
|
|
142
|
+
},
|
|
143
|
+
has(id) {
|
|
144
|
+
return byId.has(id);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* `outer` strictly contains `inner` when `outer`'s start is at or before
|
|
150
|
+
* `inner`'s start, `outer`'s end is at or after `inner`'s end, and they are
|
|
151
|
+
* not the exact same range. Equal ranges are rejected — a child cannot
|
|
152
|
+
* occupy the exact same span as its parent.
|
|
153
|
+
*/
|
|
154
|
+
function rangeStrictlyContains(outer, inner) {
|
|
155
|
+
if (outer.startLine === inner.startLine &&
|
|
156
|
+
outer.startCol === inner.startCol &&
|
|
157
|
+
outer.endLine === inner.endLine &&
|
|
158
|
+
outer.endCol === inner.endCol) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
const outerStartsAtOrBefore = outer.startLine < inner.startLine ||
|
|
162
|
+
(outer.startLine === inner.startLine && outer.startCol <= inner.startCol);
|
|
163
|
+
const outerEndsAtOrAfter = outer.endLine > inner.endLine ||
|
|
164
|
+
(outer.endLine === inner.endLine && outer.endCol >= inner.endCol);
|
|
165
|
+
return outerStartsAtOrBefore && outerEndsAtOrAfter;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Two ranges overlap when neither finishes before the other begins. Ranges
|
|
169
|
+
* that merely touch at a single boundary point (`a.end === b.start`) do
|
|
170
|
+
* NOT overlap — this matches tree-sitter's half-open-like range semantics
|
|
171
|
+
* and the typical "sibling blocks meet but don't overlap" pattern.
|
|
172
|
+
*/
|
|
173
|
+
function rangesOverlap(a, b) {
|
|
174
|
+
const aEndsBeforeB = a.endLine < b.startLine || (a.endLine === b.startLine && a.endCol <= b.startCol);
|
|
175
|
+
const bEndsBeforeA = b.endLine < a.startLine || (b.endLine === a.startLine && b.endCol <= a.startCol);
|
|
176
|
+
return !(aEndsBeforeB || bEndsBeforeA);
|
|
177
|
+
}
|
|
178
|
+
function comparePosition(a, b) {
|
|
179
|
+
if (a.startLine !== b.startLine)
|
|
180
|
+
return a.startLine - b.startLine;
|
|
181
|
+
return a.startCol - b.startCol;
|
|
182
|
+
}
|
|
183
|
+
function formatRange(r) {
|
|
184
|
+
return `${r.startLine}:${r.startCol}-${r.endLine}:${r.endCol}`;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=scope-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-tree.js","sourceRoot":"","sources":["../../src/scope-resolution/scope-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-mode aggregation — per-language parity %, per-evidence-kind
|
|
3
|
+
* breakdown of divergences. Consumed by the parity dashboard (RING2-PKG-5).
|
|
4
|
+
*
|
|
5
|
+
* Pure functions; no I/O. The harness persists per-run JSON; the dashboard
|
|
6
|
+
* reads `.gitnexus/shadow-parity/latest.json` and renders.
|
|
7
|
+
*
|
|
8
|
+
* Related types — `ShadowAgreement`, `ShadowCallsite`, `ShadowDiff` — are
|
|
9
|
+
* defined alongside `diffResolutions` in `./diff.ts` and re-exported
|
|
10
|
+
* through the top-level `gitnexus-shared` barrel. Consumers import all
|
|
11
|
+
* three from `gitnexus-shared`, not from this module.
|
|
12
|
+
*
|
|
13
|
+
* Part of RFC #909 Ring 2 SHARED — #918.
|
|
14
|
+
*/
|
|
15
|
+
import type { SupportedLanguages } from '../../languages.js';
|
|
16
|
+
import type { ResolutionEvidence } from '../types.js';
|
|
17
|
+
import type { ShadowDiff } from './diff.js';
|
|
18
|
+
export interface LanguageParityRow {
|
|
19
|
+
readonly language: SupportedLanguages;
|
|
20
|
+
readonly totalCalls: number;
|
|
21
|
+
readonly bothAgree: number;
|
|
22
|
+
readonly onlyLegacy: number;
|
|
23
|
+
readonly onlyNew: number;
|
|
24
|
+
readonly bothDisagree: number;
|
|
25
|
+
readonly bothEmpty: number;
|
|
26
|
+
/**
|
|
27
|
+
* Fraction in [0, 1]. Numerator = `bothAgree`; denominator = "calls where
|
|
28
|
+
* at least one side resolved" = `totalCalls - bothEmpty`.
|
|
29
|
+
*
|
|
30
|
+
* When the denominator is 0 (all calls for this language were
|
|
31
|
+
* `both-empty`), returns 0. Callers rendering the dashboard should treat
|
|
32
|
+
* a 0 parity alongside `totalCalls === bothEmpty` as "no signal" rather
|
|
33
|
+
* than "total disagreement".
|
|
34
|
+
*/
|
|
35
|
+
readonly parity: number;
|
|
36
|
+
/**
|
|
37
|
+
* Divergence signals broken down by `ResolutionEvidence.kind`. Sourced
|
|
38
|
+
* from `ShadowDiff.evidenceDelta` on non-agreeing rows only — `both-agree`
|
|
39
|
+
* and `both-empty` do not contribute.
|
|
40
|
+
*/
|
|
41
|
+
readonly evidenceBreakdown: ReadonlyMap<ResolutionEvidence['kind'], number>;
|
|
42
|
+
}
|
|
43
|
+
export interface ShadowParityReport {
|
|
44
|
+
readonly generatedAt: string;
|
|
45
|
+
readonly perLanguage: readonly LanguageParityRow[];
|
|
46
|
+
readonly overall: Omit<LanguageParityRow, 'language' | 'evidenceBreakdown'>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Aggregate a stream of `ShadowDiff` records into a `ShadowParityReport`,
|
|
50
|
+
* bucketed by language. Pure function.
|
|
51
|
+
*
|
|
52
|
+
* - `perLanguage` rows are sorted alphabetically by `SupportedLanguages`
|
|
53
|
+
* value for stable JSON output (the dashboard reads
|
|
54
|
+
* `.gitnexus/shadow-parity/latest.json` and diffing snapshots is useful).
|
|
55
|
+
* - `overall` is the column-wise sum across languages.
|
|
56
|
+
* - `generatedAt` is injected via the `now` parameter so tests stay
|
|
57
|
+
* deterministic; production callers let it default to `new Date()`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function aggregateDiffs(diffs: readonly {
|
|
60
|
+
readonly language: SupportedLanguages;
|
|
61
|
+
readonly diff: ShadowDiff;
|
|
62
|
+
}[], now?: Date): ShadowParityReport;
|
|
63
|
+
//# sourceMappingURL=aggregate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../src/scope-resolution/shadow/aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAmB,UAAU,EAAE,MAAM,WAAW,CAAC;AAI7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,mBAAmB,CAAC,CAAC;CAC7E;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS;IAAE,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,EAAE,EACtF,GAAG,GAAE,IAAiB,GACrB,kBAAkB,CAuBpB"}
|