gitnexus 1.6.3-rc.8 → 1.6.3
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/README.md +21 -5
- 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 +20 -2
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +11 -0
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/scope-resolution/def-index.js +2 -2
- package/dist/_shared/scope-resolution/def-index.js.map +1 -1
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +8 -0
- package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/method-dispatch-index.js +2 -2
- package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
- package/dist/_shared/scope-resolution/module-scope-index.d.ts +8 -0
- package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/module-scope-index.js +10 -2
- package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +76 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/parsed-file.js +54 -0
- package/dist/_shared/scope-resolution/parsed-file.js.map +1 -0
- package/dist/_shared/scope-resolution/position-index.d.ts +12 -0
- package/dist/_shared/scope-resolution/position-index.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/position-index.js +2 -2
- package/dist/_shared/scope-resolution/position-index.js.map +1 -1
- package/dist/_shared/scope-resolution/qualified-name-index.js +2 -2
- package/dist/_shared/scope-resolution/qualified-name-index.js.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +75 -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 +1 -10
- package/dist/_shared/scope-resolution/resolve-type-ref.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/resolve-type-ref.js +6 -0
- package/dist/_shared/scope-resolution/resolve-type-ref.js.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.d.ts +4 -4
- package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.js +3 -2
- package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +6 -2
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/shadow/aggregate.js +5 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.js.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +11 -0
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.js +35 -4
- package/dist/cli/analyze.d.ts +27 -0
- package/dist/cli/analyze.js +31 -1
- package/dist/cli/clean.js +19 -1
- package/dist/cli/group.js +73 -0
- package/dist/cli/index-repo.js +8 -1
- package/dist/cli/index.js +26 -1
- package/dist/cli/list.js +11 -1
- package/dist/cli/remove.d.ts +30 -0
- package/dist/cli/remove.js +99 -0
- package/dist/cli/setup.js +185 -57
- package/dist/cli/tool.d.ts +5 -0
- package/dist/cli/tool.js +42 -0
- package/dist/config/ignore-service.d.ts +9 -0
- package/dist/config/ignore-service.js +80 -13
- package/dist/core/embedding-mode.d.ts +30 -0
- package/dist/core/embedding-mode.js +30 -0
- package/dist/core/embeddings/ast-utils.js +22 -22
- package/dist/core/embeddings/chunker.js +30 -25
- package/dist/core/embeddings/embedding-pipeline.d.ts +6 -0
- package/dist/core/embeddings/embedding-pipeline.js +15 -6
- package/dist/core/embeddings/text-generator.d.ts +1 -1
- package/dist/core/embeddings/text-generator.js +33 -24
- package/dist/core/embeddings/types.d.ts +43 -1
- package/dist/core/embeddings/types.js +101 -29
- package/dist/core/git-staleness.d.ts +18 -0
- package/dist/core/git-staleness.js +108 -0
- package/dist/core/graph/graph.js +115 -20
- package/dist/core/graph/types.d.ts +12 -1
- package/dist/core/group/config-parser.d.ts +4 -0
- package/dist/core/group/config-parser.js +18 -1
- package/dist/core/group/cross-impact.d.ts +41 -0
- package/dist/core/group/cross-impact.js +441 -0
- package/dist/core/group/extractors/http-patterns/php.js +126 -18
- package/dist/core/group/group-path-utils.d.ts +17 -0
- package/dist/core/group/group-path-utils.js +40 -0
- package/dist/core/group/resolve-at-member.d.ts +10 -0
- package/dist/core/group/resolve-at-member.js +31 -0
- package/dist/core/group/service.d.ts +9 -0
- package/dist/core/group/service.js +259 -25
- package/dist/core/group/types.d.ts +30 -0
- package/dist/core/ingestion/ast-cache.d.ts +16 -1
- package/dist/core/ingestion/ast-cache.js +14 -2
- package/dist/core/ingestion/call-processor.js +9 -0
- package/dist/core/ingestion/emit-references.d.ts +88 -0
- package/dist/core/ingestion/emit-references.js +229 -0
- package/dist/core/ingestion/filesystem-walker.js +6 -4
- 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-processor.js +4 -0
- package/dist/core/ingestion/import-resolvers/python.js +9 -6
- 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 +36 -33
- package/dist/core/ingestion/languages/csharp/accessor-unwrap.d.ts +21 -0
- package/dist/core/ingestion/languages/csharp/accessor-unwrap.js +56 -0
- package/dist/core/ingestion/languages/csharp/arity-metadata.d.ts +26 -0
- package/dist/core/ingestion/languages/csharp/arity-metadata.js +46 -0
- package/dist/core/ingestion/languages/csharp/arity.d.ts +23 -0
- package/dist/core/ingestion/languages/csharp/arity.js +37 -0
- package/dist/core/ingestion/languages/csharp/cache-stats.d.ts +15 -0
- package/dist/core/ingestion/languages/csharp/cache-stats.js +26 -0
- package/dist/core/ingestion/languages/csharp/captures.d.ts +19 -0
- package/dist/core/ingestion/languages/csharp/captures.js +249 -0
- package/dist/core/ingestion/languages/csharp/import-decomposer.d.ts +19 -0
- package/dist/core/ingestion/languages/csharp/import-decomposer.js +93 -0
- package/dist/core/ingestion/languages/csharp/import-target.d.ts +25 -0
- package/dist/core/ingestion/languages/csharp/import-target.js +123 -0
- package/dist/core/ingestion/languages/csharp/index.d.ts +82 -0
- package/dist/core/ingestion/languages/csharp/index.js +82 -0
- package/dist/core/ingestion/languages/csharp/interpret.d.ts +15 -0
- package/dist/core/ingestion/languages/csharp/interpret.js +132 -0
- package/dist/core/ingestion/languages/csharp/merge-bindings.d.ts +27 -0
- package/dist/core/ingestion/languages/csharp/merge-bindings.js +55 -0
- package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +50 -0
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +374 -0
- package/dist/core/ingestion/languages/csharp/query.d.ts +35 -0
- package/dist/core/ingestion/languages/csharp/query.js +515 -0
- package/dist/core/ingestion/languages/csharp/receiver-binding.d.ts +31 -0
- package/dist/core/ingestion/languages/csharp/receiver-binding.js +135 -0
- package/dist/core/ingestion/languages/csharp/scope-resolver.d.ts +10 -0
- package/dist/core/ingestion/languages/csharp/scope-resolver.js +63 -0
- package/dist/core/ingestion/languages/csharp/simple-hooks.d.ts +53 -0
- package/dist/core/ingestion/languages/csharp/simple-hooks.js +76 -0
- package/dist/core/ingestion/languages/csharp.js +14 -0
- package/dist/core/ingestion/languages/python/arity-metadata.d.ts +24 -0
- package/dist/core/ingestion/languages/python/arity-metadata.js +45 -0
- package/dist/core/ingestion/languages/python/arity.d.ts +22 -0
- package/dist/core/ingestion/languages/python/arity.js +38 -0
- package/dist/core/ingestion/languages/python/cache-stats.d.ts +17 -0
- package/dist/core/ingestion/languages/python/cache-stats.js +28 -0
- package/dist/core/ingestion/languages/python/captures.d.ts +19 -0
- package/dist/core/ingestion/languages/python/captures.js +106 -0
- package/dist/core/ingestion/languages/python/import-decomposer.d.ts +15 -0
- package/dist/core/ingestion/languages/python/import-decomposer.js +112 -0
- package/dist/core/ingestion/languages/python/import-target.d.ts +21 -0
- package/dist/core/ingestion/languages/python/import-target.js +99 -0
- package/dist/core/ingestion/languages/python/index.d.ts +80 -0
- package/dist/core/ingestion/languages/python/index.js +80 -0
- package/dist/core/ingestion/languages/python/interpret.d.ts +15 -0
- package/dist/core/ingestion/languages/python/interpret.js +191 -0
- package/dist/core/ingestion/languages/python/merge-bindings.d.ts +16 -0
- package/dist/core/ingestion/languages/python/merge-bindings.js +44 -0
- package/dist/core/ingestion/languages/python/query.d.ts +9 -0
- package/dist/core/ingestion/languages/python/query.js +267 -0
- package/dist/core/ingestion/languages/python/receiver-binding.d.ts +21 -0
- package/dist/core/ingestion/languages/python/receiver-binding.js +116 -0
- package/dist/core/ingestion/languages/python/scope-resolver.d.ts +16 -0
- package/dist/core/ingestion/languages/python/scope-resolver.js +53 -0
- package/dist/core/ingestion/languages/python/simple-hooks.d.ts +23 -0
- package/dist/core/ingestion/languages/python/simple-hooks.js +35 -0
- package/dist/core/ingestion/languages/python.js +14 -0
- package/dist/core/ingestion/model/method-registry.d.ts +9 -0
- package/dist/core/ingestion/model/method-registry.js +4 -0
- 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 +64 -0
- package/dist/core/ingestion/model/semantic-model.js +55 -0
- package/dist/core/ingestion/mro-processor.js +38 -22
- package/dist/core/ingestion/parsing-processor.d.ts +18 -1
- package/dist/core/ingestion/parsing-processor.js +45 -11
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +17 -2
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +18 -0
- package/dist/core/ingestion/pipeline.js +2 -1
- package/dist/core/ingestion/registry-primary-flag.d.ts +86 -0
- package/dist/core/ingestion/registry-primary-flag.js +111 -0
- package/dist/core/ingestion/resolve-references.d.ts +63 -0
- package/dist/core/ingestion/resolve-references.js +175 -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 +86 -0
- package/dist/core/ingestion/scope-extractor.js +758 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +372 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +212 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +43 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +79 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +57 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +112 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.d.ts +17 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +46 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +19 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +30 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.d.ts +37 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +113 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +38 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +73 -0
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +42 -0
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +198 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +27 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +131 -0
- package/dist/core/ingestion/scope-resolution/passes/imported-return-types.d.ts +48 -0
- package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +130 -0
- package/dist/core/ingestion/scope-resolution/passes/mro.d.ts +42 -0
- package/dist/core/ingestion/scope-resolution/passes/mro.js +99 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +26 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +61 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +46 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +327 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +47 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +130 -0
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.d.ts +68 -0
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +125 -0
- package/dist/core/ingestion/scope-resolution/pipeline/registry.d.ts +17 -0
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +21 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +66 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +157 -0
- package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +36 -0
- package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +52 -0
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +127 -0
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +349 -0
- package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +52 -0
- package/dist/core/ingestion/scope-resolution/workspace-index.js +61 -0
- package/dist/core/ingestion/shadow-harness.d.ts +113 -0
- package/dist/core/ingestion/shadow-harness.js +148 -0
- package/dist/core/ingestion/utils/ast-helpers.d.ts +19 -1
- package/dist/core/ingestion/utils/ast-helpers.js +70 -0
- package/dist/core/ingestion/utils/max-file-size.d.ts +20 -0
- package/dist/core/ingestion/utils/max-file-size.js +52 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +9 -0
- package/dist/core/ingestion/workers/parse-worker.js +57 -21
- package/dist/core/lbug/lbug-adapter.d.ts +22 -2
- package/dist/core/lbug/lbug-adapter.js +58 -14
- package/dist/core/lbug/pool-adapter.d.ts +17 -0
- package/dist/core/lbug/pool-adapter.js +24 -14
- package/dist/core/run-analyze.d.ts +32 -0
- package/dist/core/run-analyze.js +74 -19
- package/dist/core/search/bm25-index.d.ts +18 -0
- package/dist/core/search/bm25-index.js +125 -12
- package/dist/core/tree-sitter/parser-loader.js +6 -1
- package/dist/mcp/local/local-backend.d.ts +67 -3
- package/dist/mcp/local/local-backend.js +296 -34
- package/dist/mcp/resources.d.ts +31 -0
- package/dist/mcp/resources.js +100 -17
- package/dist/mcp/tools.d.ts +4 -1
- package/dist/mcp/tools.js +75 -54
- package/dist/server/api.js +6 -2
- package/dist/storage/git.d.ts +49 -0
- package/dist/storage/git.js +111 -0
- package/dist/storage/repo-manager.d.ts +246 -1
- package/dist/storage/repo-manager.js +391 -9
- package/package.json +7 -6
- package/scripts/bench-scope-resolution.ts +134 -0
- package/scripts/ci-list-migrated-languages.ts +24 -0
- package/skills/gitnexus-cli.md +1 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `REGISTRY_PRIMARY_<LANG>` per-language feature flags for the scope-based
|
|
3
|
+
* resolution rollout (RFC §6.1 Ring 3; Ring 2 PKG #924).
|
|
4
|
+
*
|
|
5
|
+
* This module is the single source of truth for whether a given language
|
|
6
|
+
* has been flipped to registry-primary call resolution. When a language's
|
|
7
|
+
* flag is true, its files route through `Registry.lookup` (RFC §4) instead
|
|
8
|
+
* of the legacy call-resolution DAG; when false (the default), the legacy
|
|
9
|
+
* DAG runs unchanged.
|
|
10
|
+
*
|
|
11
|
+
* ## Contract
|
|
12
|
+
*
|
|
13
|
+
* - Env-var name per language: `REGISTRY_PRIMARY_<UPPER(enum-value)>`.
|
|
14
|
+
* Example: `SupportedLanguages.Python` → `REGISTRY_PRIMARY_PYTHON`;
|
|
15
|
+
* `SupportedLanguages.CPlusPlus` (value `'cpp'`) → `REGISTRY_PRIMARY_CPP`.
|
|
16
|
+
* - Truthy values: `'true'`, `'1'`, `'yes'` (case-insensitive,
|
|
17
|
+
* whitespace-trimmed). Anything else — including `undefined`, empty
|
|
18
|
+
* string, or unknown tokens — is `false`.
|
|
19
|
+
* - No per-process caching. `process.env` is read on every call. The
|
|
20
|
+
* flag is consulted once per file at call-resolution time, so the
|
|
21
|
+
* overhead is negligible; skipping caching keeps test isolation
|
|
22
|
+
* trivial (no `resetFlagCache()` coordination needed).
|
|
23
|
+
*
|
|
24
|
+
* ## Integration site
|
|
25
|
+
*
|
|
26
|
+
* `call-processor.ts` integration lands in **#921** (`finalize-orchestrator`)
|
|
27
|
+
* where the `SemanticModel` becomes accessible and `Registry.lookup` can
|
|
28
|
+
* actually be called with a populated context. This module ships the flag
|
|
29
|
+
* primitive in isolation so #921 has a clean, tested utility to consult.
|
|
30
|
+
*
|
|
31
|
+
* ## Shadow mode is orthogonal
|
|
32
|
+
*
|
|
33
|
+
* Shadow mode (`GITNEXUS_SHADOW_MODE=1`, introduced in #923) runs BOTH
|
|
34
|
+
* legacy and registry paths regardless of the per-language flag, so the
|
|
35
|
+
* parity dashboard has signal even for un-flipped languages. That logic
|
|
36
|
+
* lives in `shadow-harness.ts` (#923), not here.
|
|
37
|
+
*/
|
|
38
|
+
import { SupportedLanguages } from '../../_shared/index.js';
|
|
39
|
+
/**
|
|
40
|
+
* Languages whose RFC #909 Ring 3 scope-resolution migration is complete.
|
|
41
|
+
*
|
|
42
|
+
* This is the single source of truth for "migrated" — the list drives:
|
|
43
|
+
*
|
|
44
|
+
* 1. **Production default behavior.** `isRegistryPrimary(lang)` returns
|
|
45
|
+
* `true` by default for languages in this set (env-var override to
|
|
46
|
+
* any falsy value still wins — e.g. `REGISTRY_PRIMARY_PYTHON=0`).
|
|
47
|
+
* 2. **CI parity gate.** `.github/workflows/ci-scope-parity.yml` auto-
|
|
48
|
+
* discovers this set and, for every language in it, runs the
|
|
49
|
+
* resolver integration test at `test/integration/resolvers/<slug>.test.ts`
|
|
50
|
+
* TWICE on every PR — once with the legacy DAG (flag forced off)
|
|
51
|
+
* and once with the registry-primary path (flag forced on). BOTH
|
|
52
|
+
* must pass. Adding a language is automatic — no workflow edit,
|
|
53
|
+
* no JSON registry.
|
|
54
|
+
* 3. **Legacy-path gating.** `call-processor.ts` / `import-processor.ts`
|
|
55
|
+
* skip per-language work when `isRegistryPrimary(lang)` is `true`,
|
|
56
|
+
* so this set also controls what gets silenced in the legacy DAG.
|
|
57
|
+
*
|
|
58
|
+
* Add a language here ONLY after shadow parity ≥ 99% fixtures / ≥ 98%
|
|
59
|
+
* corpus per RFC §6.4. The parity CI gate will block the PR otherwise.
|
|
60
|
+
*
|
|
61
|
+
* The set is intentionally a static TypeScript literal (not a JSON import,
|
|
62
|
+
* not an env lookup) so CI can discover it via `tsx` without a build step
|
|
63
|
+
* and reviewers see the change inline with the code that consumes it.
|
|
64
|
+
*/
|
|
65
|
+
export declare const MIGRATED_LANGUAGES: ReadonlySet<SupportedLanguages>;
|
|
66
|
+
/**
|
|
67
|
+
* Return the env-var name that controls a given language's registry-
|
|
68
|
+
* primary flag. Exported for test assertions and for the PR-labeling
|
|
69
|
+
* CI job that cross-references per-language flag changes.
|
|
70
|
+
*/
|
|
71
|
+
export declare function envVarNameFor(lang: SupportedLanguages): string;
|
|
72
|
+
/**
|
|
73
|
+
* Whether `lang` runs through the registry-primary call-resolution path.
|
|
74
|
+
*
|
|
75
|
+
* Resolution order: an explicit env-var value wins (so operators and CI
|
|
76
|
+
* can force either path for a given run), and the default falls back to
|
|
77
|
+
* `MIGRATED_LANGUAGES.has(lang)` — so languages whose migration is
|
|
78
|
+
* complete default to registry-primary without touching any env.
|
|
79
|
+
*/
|
|
80
|
+
export declare function isRegistryPrimary(lang: SupportedLanguages): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* All languages whose registry-primary flag is currently on. Useful for
|
|
83
|
+
* startup-time logging + the shadow-harness dashboard, which wants to
|
|
84
|
+
* distinguish "primary: legacy" from "primary: registry" rows.
|
|
85
|
+
*/
|
|
86
|
+
export declare function primaryLanguages(): ReadonlySet<SupportedLanguages>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `REGISTRY_PRIMARY_<LANG>` per-language feature flags for the scope-based
|
|
3
|
+
* resolution rollout (RFC §6.1 Ring 3; Ring 2 PKG #924).
|
|
4
|
+
*
|
|
5
|
+
* This module is the single source of truth for whether a given language
|
|
6
|
+
* has been flipped to registry-primary call resolution. When a language's
|
|
7
|
+
* flag is true, its files route through `Registry.lookup` (RFC §4) instead
|
|
8
|
+
* of the legacy call-resolution DAG; when false (the default), the legacy
|
|
9
|
+
* DAG runs unchanged.
|
|
10
|
+
*
|
|
11
|
+
* ## Contract
|
|
12
|
+
*
|
|
13
|
+
* - Env-var name per language: `REGISTRY_PRIMARY_<UPPER(enum-value)>`.
|
|
14
|
+
* Example: `SupportedLanguages.Python` → `REGISTRY_PRIMARY_PYTHON`;
|
|
15
|
+
* `SupportedLanguages.CPlusPlus` (value `'cpp'`) → `REGISTRY_PRIMARY_CPP`.
|
|
16
|
+
* - Truthy values: `'true'`, `'1'`, `'yes'` (case-insensitive,
|
|
17
|
+
* whitespace-trimmed). Anything else — including `undefined`, empty
|
|
18
|
+
* string, or unknown tokens — is `false`.
|
|
19
|
+
* - No per-process caching. `process.env` is read on every call. The
|
|
20
|
+
* flag is consulted once per file at call-resolution time, so the
|
|
21
|
+
* overhead is negligible; skipping caching keeps test isolation
|
|
22
|
+
* trivial (no `resetFlagCache()` coordination needed).
|
|
23
|
+
*
|
|
24
|
+
* ## Integration site
|
|
25
|
+
*
|
|
26
|
+
* `call-processor.ts` integration lands in **#921** (`finalize-orchestrator`)
|
|
27
|
+
* where the `SemanticModel` becomes accessible and `Registry.lookup` can
|
|
28
|
+
* actually be called with a populated context. This module ships the flag
|
|
29
|
+
* primitive in isolation so #921 has a clean, tested utility to consult.
|
|
30
|
+
*
|
|
31
|
+
* ## Shadow mode is orthogonal
|
|
32
|
+
*
|
|
33
|
+
* Shadow mode (`GITNEXUS_SHADOW_MODE=1`, introduced in #923) runs BOTH
|
|
34
|
+
* legacy and registry paths regardless of the per-language flag, so the
|
|
35
|
+
* parity dashboard has signal even for un-flipped languages. That logic
|
|
36
|
+
* lives in `shadow-harness.ts` (#923), not here.
|
|
37
|
+
*/
|
|
38
|
+
import { SupportedLanguages } from '../../_shared/index.js';
|
|
39
|
+
/**
|
|
40
|
+
* Languages whose RFC #909 Ring 3 scope-resolution migration is complete.
|
|
41
|
+
*
|
|
42
|
+
* This is the single source of truth for "migrated" — the list drives:
|
|
43
|
+
*
|
|
44
|
+
* 1. **Production default behavior.** `isRegistryPrimary(lang)` returns
|
|
45
|
+
* `true` by default for languages in this set (env-var override to
|
|
46
|
+
* any falsy value still wins — e.g. `REGISTRY_PRIMARY_PYTHON=0`).
|
|
47
|
+
* 2. **CI parity gate.** `.github/workflows/ci-scope-parity.yml` auto-
|
|
48
|
+
* discovers this set and, for every language in it, runs the
|
|
49
|
+
* resolver integration test at `test/integration/resolvers/<slug>.test.ts`
|
|
50
|
+
* TWICE on every PR — once with the legacy DAG (flag forced off)
|
|
51
|
+
* and once with the registry-primary path (flag forced on). BOTH
|
|
52
|
+
* must pass. Adding a language is automatic — no workflow edit,
|
|
53
|
+
* no JSON registry.
|
|
54
|
+
* 3. **Legacy-path gating.** `call-processor.ts` / `import-processor.ts`
|
|
55
|
+
* skip per-language work when `isRegistryPrimary(lang)` is `true`,
|
|
56
|
+
* so this set also controls what gets silenced in the legacy DAG.
|
|
57
|
+
*
|
|
58
|
+
* Add a language here ONLY after shadow parity ≥ 99% fixtures / ≥ 98%
|
|
59
|
+
* corpus per RFC §6.4. The parity CI gate will block the PR otherwise.
|
|
60
|
+
*
|
|
61
|
+
* The set is intentionally a static TypeScript literal (not a JSON import,
|
|
62
|
+
* not an env lookup) so CI can discover it via `tsx` without a build step
|
|
63
|
+
* and reviewers see the change inline with the code that consumes it.
|
|
64
|
+
*/
|
|
65
|
+
export const MIGRATED_LANGUAGES = new Set([
|
|
66
|
+
SupportedLanguages.Python,
|
|
67
|
+
SupportedLanguages.CSharp,
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* Return the env-var name that controls a given language's registry-
|
|
71
|
+
* primary flag. Exported for test assertions and for the PR-labeling
|
|
72
|
+
* CI job that cross-references per-language flag changes.
|
|
73
|
+
*/
|
|
74
|
+
export function envVarNameFor(lang) {
|
|
75
|
+
return `REGISTRY_PRIMARY_${lang.toUpperCase()}`;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Whether `lang` runs through the registry-primary call-resolution path.
|
|
79
|
+
*
|
|
80
|
+
* Resolution order: an explicit env-var value wins (so operators and CI
|
|
81
|
+
* can force either path for a given run), and the default falls back to
|
|
82
|
+
* `MIGRATED_LANGUAGES.has(lang)` — so languages whose migration is
|
|
83
|
+
* complete default to registry-primary without touching any env.
|
|
84
|
+
*/
|
|
85
|
+
export function isRegistryPrimary(lang) {
|
|
86
|
+
const raw = process.env[envVarNameFor(lang)];
|
|
87
|
+
if (raw !== undefined)
|
|
88
|
+
return parseFlag(raw);
|
|
89
|
+
return MIGRATED_LANGUAGES.has(lang);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* All languages whose registry-primary flag is currently on. Useful for
|
|
93
|
+
* startup-time logging + the shadow-harness dashboard, which wants to
|
|
94
|
+
* distinguish "primary: legacy" from "primary: registry" rows.
|
|
95
|
+
*/
|
|
96
|
+
export function primaryLanguages() {
|
|
97
|
+
const out = new Set();
|
|
98
|
+
for (const lang of Object.values(SupportedLanguages)) {
|
|
99
|
+
if (isRegistryPrimary(lang))
|
|
100
|
+
out.add(lang);
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
// ─── Internal ───────────────────────────────────────────────────────────────
|
|
105
|
+
/** Accepted truthy strings (case-insensitive, trimmed). */
|
|
106
|
+
const TRUTHY_VALUES = new Set(['true', '1', 'yes']);
|
|
107
|
+
function parseFlag(raw) {
|
|
108
|
+
if (raw === undefined)
|
|
109
|
+
return false;
|
|
110
|
+
return TRUTHY_VALUES.has(raw.trim().toLowerCase());
|
|
111
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolveReferenceSites` — drain `ReferenceSite[]` from a finalized
|
|
3
|
+
* `ScopeResolutionIndexes` into a `ReferenceIndex` by routing each site
|
|
4
|
+
* through the appropriate scope-aware `Registry.lookup` (RFC §3.2 Phase 4).
|
|
5
|
+
*
|
|
6
|
+
* This is the missing producer that `emit-references.ts` (#925) was
|
|
7
|
+
* waiting on. The two together form the registry-primary resolution
|
|
8
|
+
* pipeline:
|
|
9
|
+
*
|
|
10
|
+
* ScopeResolutionIndexes.referenceSites
|
|
11
|
+
* │ resolveReferenceSites
|
|
12
|
+
* ▼
|
|
13
|
+
* ReferenceIndex
|
|
14
|
+
* │ emitReferencesToGraph
|
|
15
|
+
* ▼
|
|
16
|
+
* graph: CALLS / ACCESSES / INHERITS / USES edges
|
|
17
|
+
*
|
|
18
|
+
* ## What this module does
|
|
19
|
+
*
|
|
20
|
+
* - For each `ReferenceSite`, picks the registry by `kind`:
|
|
21
|
+
* · `call` / `inherits` → MethodRegistry / ClassRegistry (call-form aware)
|
|
22
|
+
* · `read` / `write` → FieldRegistry (falls through to MethodRegistry for free names)
|
|
23
|
+
* · `type-reference` → ClassRegistry
|
|
24
|
+
* · `import-use` → all three (best-effort name-lookup)
|
|
25
|
+
* - Calls `Registry.lookup` with the site's `inScope`, optional
|
|
26
|
+
* explicit receiver, and arity.
|
|
27
|
+
* - Takes the top-ranked `Resolution` (best by confidence + tie-break
|
|
28
|
+
* cascade); folds it into a `Reference` record and bins by source scope.
|
|
29
|
+
*
|
|
30
|
+
* ## What this module does NOT do
|
|
31
|
+
*
|
|
32
|
+
* - No AST walks. The `ReferenceSite[]` is already extracted.
|
|
33
|
+
* - No language switches. Per-language behavior flows through
|
|
34
|
+
* `RegistryProviders.arityCompatibility` (see `RegistryContext`).
|
|
35
|
+
* - No multi-candidate fan-out. We pick `[0]` per RFC §4.3 ("one-shot
|
|
36
|
+
* answer"). The full ranked list is preserved in the per-site
|
|
37
|
+
* resolution but not emitted as multiple edges; callers that want
|
|
38
|
+
* branch-on-ambiguity behavior should consume the registries directly.
|
|
39
|
+
*/
|
|
40
|
+
import { CLASS_KINDS, FIELD_KINDS, METHOD_KINDS, type ReferenceIndex, type RegistryProviders } from '../../_shared/index.js';
|
|
41
|
+
import type { ScopeResolutionIndexes } from './model/scope-resolution-indexes.js';
|
|
42
|
+
export interface ResolveReferencesInput {
|
|
43
|
+
readonly scopes: ScopeResolutionIndexes;
|
|
44
|
+
/** Provider hooks consumed by the registries (e.g. `arityCompatibility`). */
|
|
45
|
+
readonly providers?: RegistryProviders;
|
|
46
|
+
}
|
|
47
|
+
export interface ResolveStats {
|
|
48
|
+
readonly sitesProcessed: number;
|
|
49
|
+
readonly referencesEmitted: number;
|
|
50
|
+
/** Sites where `Registry.lookup` returned no candidates. */
|
|
51
|
+
readonly unresolved: number;
|
|
52
|
+
}
|
|
53
|
+
export interface ResolveReferencesOutput {
|
|
54
|
+
readonly referenceIndex: ReferenceIndex;
|
|
55
|
+
readonly stats: ResolveStats;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve every `ReferenceSite` in `scopes.referenceSites` against the
|
|
59
|
+
* matching registry and produce a `ReferenceIndex` keyed by source scope
|
|
60
|
+
* + target def.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveReferenceSites(input: ResolveReferencesInput): ResolveReferencesOutput;
|
|
63
|
+
export { CLASS_KINDS, METHOD_KINDS, FIELD_KINDS };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolveReferenceSites` — drain `ReferenceSite[]` from a finalized
|
|
3
|
+
* `ScopeResolutionIndexes` into a `ReferenceIndex` by routing each site
|
|
4
|
+
* through the appropriate scope-aware `Registry.lookup` (RFC §3.2 Phase 4).
|
|
5
|
+
*
|
|
6
|
+
* This is the missing producer that `emit-references.ts` (#925) was
|
|
7
|
+
* waiting on. The two together form the registry-primary resolution
|
|
8
|
+
* pipeline:
|
|
9
|
+
*
|
|
10
|
+
* ScopeResolutionIndexes.referenceSites
|
|
11
|
+
* │ resolveReferenceSites
|
|
12
|
+
* ▼
|
|
13
|
+
* ReferenceIndex
|
|
14
|
+
* │ emitReferencesToGraph
|
|
15
|
+
* ▼
|
|
16
|
+
* graph: CALLS / ACCESSES / INHERITS / USES edges
|
|
17
|
+
*
|
|
18
|
+
* ## What this module does
|
|
19
|
+
*
|
|
20
|
+
* - For each `ReferenceSite`, picks the registry by `kind`:
|
|
21
|
+
* · `call` / `inherits` → MethodRegistry / ClassRegistry (call-form aware)
|
|
22
|
+
* · `read` / `write` → FieldRegistry (falls through to MethodRegistry for free names)
|
|
23
|
+
* · `type-reference` → ClassRegistry
|
|
24
|
+
* · `import-use` → all three (best-effort name-lookup)
|
|
25
|
+
* - Calls `Registry.lookup` with the site's `inScope`, optional
|
|
26
|
+
* explicit receiver, and arity.
|
|
27
|
+
* - Takes the top-ranked `Resolution` (best by confidence + tie-break
|
|
28
|
+
* cascade); folds it into a `Reference` record and bins by source scope.
|
|
29
|
+
*
|
|
30
|
+
* ## What this module does NOT do
|
|
31
|
+
*
|
|
32
|
+
* - No AST walks. The `ReferenceSite[]` is already extracted.
|
|
33
|
+
* - No language switches. Per-language behavior flows through
|
|
34
|
+
* `RegistryProviders.arityCompatibility` (see `RegistryContext`).
|
|
35
|
+
* - No multi-candidate fan-out. We pick `[0]` per RFC §4.3 ("one-shot
|
|
36
|
+
* answer"). The full ranked list is preserved in the per-site
|
|
37
|
+
* resolution but not emitted as multiple edges; callers that want
|
|
38
|
+
* branch-on-ambiguity behavior should consume the registries directly.
|
|
39
|
+
*/
|
|
40
|
+
import { buildClassRegistry, buildFieldRegistry, buildMethodRegistry, CLASS_KINDS, FIELD_KINDS, METHOD_KINDS, } from '../../_shared/index.js';
|
|
41
|
+
/**
|
|
42
|
+
* Resolve every `ReferenceSite` in `scopes.referenceSites` against the
|
|
43
|
+
* matching registry and produce a `ReferenceIndex` keyed by source scope
|
|
44
|
+
* + target def.
|
|
45
|
+
*/
|
|
46
|
+
export function resolveReferenceSites(input) {
|
|
47
|
+
const { scopes } = input;
|
|
48
|
+
const providers = input.providers ?? {};
|
|
49
|
+
const ctx = {
|
|
50
|
+
scopes: scopes.scopeTree,
|
|
51
|
+
defs: scopes.defs,
|
|
52
|
+
qualifiedNames: scopes.qualifiedNames,
|
|
53
|
+
moduleScopes: scopes.moduleScopes,
|
|
54
|
+
methodDispatch: scopes.methodDispatch,
|
|
55
|
+
providers,
|
|
56
|
+
};
|
|
57
|
+
const classRegistry = buildClassRegistry(ctx);
|
|
58
|
+
const methodRegistry = buildMethodRegistry(ctx);
|
|
59
|
+
const fieldRegistry = buildFieldRegistry(ctx);
|
|
60
|
+
// bySourceScope is the canonical index; byTargetDef is derived from it.
|
|
61
|
+
const bySourceScope = new Map();
|
|
62
|
+
const byTargetDef = new Map();
|
|
63
|
+
let sitesProcessed = 0;
|
|
64
|
+
let referencesEmitted = 0;
|
|
65
|
+
let unresolved = 0;
|
|
66
|
+
for (const site of scopes.referenceSites) {
|
|
67
|
+
sitesProcessed++;
|
|
68
|
+
const resolutions = lookupForSite(site, classRegistry, methodRegistry, fieldRegistry);
|
|
69
|
+
if (resolutions.length === 0) {
|
|
70
|
+
unresolved++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const top = resolutions[0];
|
|
74
|
+
const ref = buildReference(site, top);
|
|
75
|
+
referencesEmitted++;
|
|
76
|
+
let bySource = bySourceScope.get(site.inScope);
|
|
77
|
+
if (bySource === undefined) {
|
|
78
|
+
bySource = [];
|
|
79
|
+
bySourceScope.set(site.inScope, bySource);
|
|
80
|
+
}
|
|
81
|
+
bySource.push(ref);
|
|
82
|
+
let byTarget = byTargetDef.get(top.def.nodeId);
|
|
83
|
+
if (byTarget === undefined) {
|
|
84
|
+
byTarget = [];
|
|
85
|
+
byTargetDef.set(top.def.nodeId, byTarget);
|
|
86
|
+
}
|
|
87
|
+
byTarget.push(ref);
|
|
88
|
+
}
|
|
89
|
+
// Freeze inner arrays so consumers don't accidentally mutate.
|
|
90
|
+
const frozenBySource = new Map();
|
|
91
|
+
for (const [k, v] of bySourceScope)
|
|
92
|
+
frozenBySource.set(k, Object.freeze([...v]));
|
|
93
|
+
const frozenByTarget = new Map();
|
|
94
|
+
for (const [k, v] of byTargetDef)
|
|
95
|
+
frozenByTarget.set(k, Object.freeze([...v]));
|
|
96
|
+
return {
|
|
97
|
+
referenceIndex: { bySourceScope: frozenBySource, byTargetDef: frozenByTarget },
|
|
98
|
+
stats: { sitesProcessed, referencesEmitted, unresolved },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// ─── Internal ───────────────────────────────────────────────────────────────
|
|
102
|
+
/**
|
|
103
|
+
* Pick the right registry for the site's `kind` and call `lookup`.
|
|
104
|
+
*
|
|
105
|
+
* The kind→registry mapping mirrors `mapKindToType` in `emit-references.ts`:
|
|
106
|
+
*
|
|
107
|
+
* | site.kind | primary registry | acceptedKinds source |
|
|
108
|
+
* |------------------|-------------------|------------------------------|
|
|
109
|
+
* | `call` | MethodRegistry | METHOD_KINDS (Method/Func/Ctor)
|
|
110
|
+
* | `inherits` | ClassRegistry | CLASS_KINDS |
|
|
111
|
+
* | `type-reference` | ClassRegistry | CLASS_KINDS |
|
|
112
|
+
* | `read`/`write` | FieldRegistry | FIELD_KINDS |
|
|
113
|
+
* | `import-use` | tiered fallback | METHOD ∪ CLASS ∪ FIELD |
|
|
114
|
+
*
|
|
115
|
+
* `import-use` doesn't have a single registry — the imported name might
|
|
116
|
+
* be a class, a function, or a constant. Try each in priority order and
|
|
117
|
+
* return the first non-empty result. Provenance still flows through the
|
|
118
|
+
* scope's `bindings` (Step 1 lexical hit), so the lookup is correct
|
|
119
|
+
* regardless of which registry surfaces the def.
|
|
120
|
+
*/
|
|
121
|
+
function lookupForSite(site, classRegistry, methodRegistry, fieldRegistry) {
|
|
122
|
+
switch (site.kind) {
|
|
123
|
+
case 'call': {
|
|
124
|
+
const opts = {
|
|
125
|
+
...(site.arity !== undefined ? { callsite: { arity: site.arity } } : {}),
|
|
126
|
+
...(site.explicitReceiver !== undefined ? { explicitReceiver: site.explicitReceiver } : {}),
|
|
127
|
+
};
|
|
128
|
+
return methodRegistry.lookup(site.name, site.inScope, opts);
|
|
129
|
+
}
|
|
130
|
+
case 'inherits':
|
|
131
|
+
case 'type-reference': {
|
|
132
|
+
return classRegistry.lookup(site.name, site.inScope);
|
|
133
|
+
}
|
|
134
|
+
case 'read':
|
|
135
|
+
case 'write': {
|
|
136
|
+
// Try field first; fall through to method then class so bare-name
|
|
137
|
+
// reads of a function (e.g. `cb = save`) still resolve.
|
|
138
|
+
const fieldHits = fieldRegistry.lookup(site.name, site.inScope);
|
|
139
|
+
if (fieldHits.length > 0)
|
|
140
|
+
return fieldHits;
|
|
141
|
+
const methodHits = methodRegistry.lookup(site.name, site.inScope);
|
|
142
|
+
if (methodHits.length > 0)
|
|
143
|
+
return methodHits;
|
|
144
|
+
return classRegistry.lookup(site.name, site.inScope);
|
|
145
|
+
}
|
|
146
|
+
case 'import-use': {
|
|
147
|
+
// Try class, method, then field. The lexical-hit Step 1 in
|
|
148
|
+
// `lookupCore` handles the actual binding lookup; the choice of
|
|
149
|
+
// registry only narrows `acceptedKinds`.
|
|
150
|
+
const classHits = classRegistry.lookup(site.name, site.inScope);
|
|
151
|
+
if (classHits.length > 0)
|
|
152
|
+
return classHits;
|
|
153
|
+
const methodHits = methodRegistry.lookup(site.name, site.inScope);
|
|
154
|
+
if (methodHits.length > 0)
|
|
155
|
+
return methodHits;
|
|
156
|
+
return fieldRegistry.lookup(site.name, site.inScope);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Compose a `Reference` record from a site + its top resolution. */
|
|
161
|
+
function buildReference(site, top) {
|
|
162
|
+
return {
|
|
163
|
+
fromScope: site.inScope,
|
|
164
|
+
toDef: top.def.nodeId,
|
|
165
|
+
atRange: site.atRange,
|
|
166
|
+
kind: site.kind,
|
|
167
|
+
confidence: top.confidence,
|
|
168
|
+
evidence: top.evidence,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// Re-export the kind sets so consumers don't have to import them
|
|
172
|
+
// separately when constructing custom resolution flows. The mappings
|
|
173
|
+
// stay in `gitnexus-shared` (single source of truth); this is a
|
|
174
|
+
// convenience pass-through only.
|
|
175
|
+
export { CLASS_KINDS, METHOD_KINDS, FIELD_KINDS };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge between a language provider's `emitScopeCaptures` hook and the
|
|
3
|
+
* `ScopeExtractor` (RFC #909 Ring 2 PKG #920).
|
|
4
|
+
*
|
|
5
|
+
* Extracted into its own module so it can be imported by test code
|
|
6
|
+
* without pulling in `parse-worker.ts` — which has a top-level
|
|
7
|
+
* `parentPort!.on('message', ...)` call that assumes a worker-thread
|
|
8
|
+
* context and throws on direct import.
|
|
9
|
+
*
|
|
10
|
+
* The bridge:
|
|
11
|
+
*
|
|
12
|
+
* 1. Short-circuits when the provider has NOT implemented
|
|
13
|
+
* `emitScopeCaptures`. Returns `undefined`; zero work done. This is
|
|
14
|
+
* the state of every language today — `ParsedFile` production stays
|
|
15
|
+
* dormant until a language migrates.
|
|
16
|
+
* 2. Invokes the hook + feeds its output to `ScopeExtractor.extract`.
|
|
17
|
+
* 3. **Swallows exceptions from either side.** A failure here returns
|
|
18
|
+
* `undefined` and emits a warning via `onWarn`; legacy parsing on
|
|
19
|
+
* the same file continues unaffected by the scope-extraction miss.
|
|
20
|
+
* Scope-based resolution is the new path under construction — it
|
|
21
|
+
* must not destabilize the legacy DAG.
|
|
22
|
+
*/
|
|
23
|
+
import type { ParsedFile } from '../../_shared/index.js';
|
|
24
|
+
import type { LanguageProvider } from './language-provider.js';
|
|
25
|
+
/** Callback used to report scope-extraction warnings to the host (worker or direct). */
|
|
26
|
+
export type ScopeBridgeWarn = (message: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Produce a `ParsedFile` for the given file, or `undefined` when the
|
|
29
|
+
* provider hasn't migrated / the extractor throws. Never propagates
|
|
30
|
+
* exceptions.
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractParsedFile(provider: LanguageProvider, sourceText: string, filePath: string, onWarn?: ScopeBridgeWarn, cachedTree?: unknown): ParsedFile | undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge between a language provider's `emitScopeCaptures` hook and the
|
|
3
|
+
* `ScopeExtractor` (RFC #909 Ring 2 PKG #920).
|
|
4
|
+
*
|
|
5
|
+
* Extracted into its own module so it can be imported by test code
|
|
6
|
+
* without pulling in `parse-worker.ts` — which has a top-level
|
|
7
|
+
* `parentPort!.on('message', ...)` call that assumes a worker-thread
|
|
8
|
+
* context and throws on direct import.
|
|
9
|
+
*
|
|
10
|
+
* The bridge:
|
|
11
|
+
*
|
|
12
|
+
* 1. Short-circuits when the provider has NOT implemented
|
|
13
|
+
* `emitScopeCaptures`. Returns `undefined`; zero work done. This is
|
|
14
|
+
* the state of every language today — `ParsedFile` production stays
|
|
15
|
+
* dormant until a language migrates.
|
|
16
|
+
* 2. Invokes the hook + feeds its output to `ScopeExtractor.extract`.
|
|
17
|
+
* 3. **Swallows exceptions from either side.** A failure here returns
|
|
18
|
+
* `undefined` and emits a warning via `onWarn`; legacy parsing on
|
|
19
|
+
* the same file continues unaffected by the scope-extraction miss.
|
|
20
|
+
* Scope-based resolution is the new path under construction — it
|
|
21
|
+
* must not destabilize the legacy DAG.
|
|
22
|
+
*/
|
|
23
|
+
import { extract as extractScope } from './scope-extractor.js';
|
|
24
|
+
/**
|
|
25
|
+
* Produce a `ParsedFile` for the given file, or `undefined` when the
|
|
26
|
+
* provider hasn't migrated / the extractor throws. Never propagates
|
|
27
|
+
* exceptions.
|
|
28
|
+
*/
|
|
29
|
+
export function extractParsedFile(provider, sourceText, filePath, onWarn, cachedTree) {
|
|
30
|
+
if (provider.emitScopeCaptures === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
try {
|
|
33
|
+
const captures = provider.emitScopeCaptures(sourceText, filePath, cachedTree);
|
|
34
|
+
return extractScope(captures, filePath, provider);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const message = `scope extraction failed for ${filePath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
38
|
+
if (onWarn !== undefined)
|
|
39
|
+
onWarn(message);
|
|
40
|
+
else
|
|
41
|
+
console.warn(message);
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ScopeExtractor` — the central, source-agnostic driver that turns a
|
|
3
|
+
* language provider's `CaptureMatch[]` into a `ParsedFile`
|
|
4
|
+
* (RFC §5.3 + §3.2 Phase 1; Ring 2 PKG #919).
|
|
5
|
+
*
|
|
6
|
+
* Exactly one entry point: `extract(matches, filePath, provider) → ParsedFile`.
|
|
7
|
+
* Runs a five-pass pipeline over the matches. Each pass is internal; the
|
|
8
|
+
* public contract is the output `ParsedFile`.
|
|
9
|
+
*
|
|
10
|
+
* ## Design principles
|
|
11
|
+
*
|
|
12
|
+
* - **Source-agnostic.** Consumes `CaptureMatch[]` from providers;
|
|
13
|
+
* doesn't know whether they came from tree-sitter queries or COBOL's
|
|
14
|
+
* regex tagger. No `Tree` / `SyntaxNode` types leak into this file.
|
|
15
|
+
* - **One AST walk per language.** Providers do the AST walk inside
|
|
16
|
+
* their `emitScopeCaptures` hook; this driver does zero further
|
|
17
|
+
* traversal — it consumes captures only.
|
|
18
|
+
* - **Pure-ish.** The extractor itself is pure (same matches →
|
|
19
|
+
* same ParsedFile) when providers are pure. No side effects, no I/O.
|
|
20
|
+
* - **Centralized invariant enforcement.** Structural invariants on the
|
|
21
|
+
* scope tree (non-module has parent; parent contains child; siblings
|
|
22
|
+
* don't overlap) are enforced by `buildScopeTree` from Ring 2 SHARED
|
|
23
|
+
* (#912). Malformed inputs throw `ScopeTreeInvariantError`.
|
|
24
|
+
*
|
|
25
|
+
* ## The five passes
|
|
26
|
+
*
|
|
27
|
+
* 1. **Build scope tree.** Walk `@scope.*` matches. For each, consult
|
|
28
|
+
* `provider.resolveScopeKind` (default: suffix of the capture name).
|
|
29
|
+
* Derive parent by lexical-range containment. Hand the resulting
|
|
30
|
+
* `Scope[]` to `buildScopeTree` for validation.
|
|
31
|
+
* 2. **Attach declarations + local bindings.** Walk `@declaration.*`
|
|
32
|
+
* matches. For each, build a `SymbolDefinition` and attach it to
|
|
33
|
+
* `provider.bindingScopeFor` (default: innermost containing scope)
|
|
34
|
+
* as `ownedDefs` + a local `BindingRef { origin: 'local' }`.
|
|
35
|
+
* 3. **Collect raw imports.** Walk `@import.*` matches. Call
|
|
36
|
+
* `provider.interpretImport` per match; attach the returned
|
|
37
|
+
* `ParsedImport` to the ParsedFile (not to any `Scope` — finalize
|
|
38
|
+
* reconstructs the owning scope via `provider.importOwningScope`
|
|
39
|
+
* during Phase 2).
|
|
40
|
+
* 4. **Collect type bindings.** Walk `@type-binding.*` matches. Call
|
|
41
|
+
* `provider.interpretTypeBinding` per match. Attach the resulting
|
|
42
|
+
* `TypeRef` to the innermost containing scope's `typeBindings`
|
|
43
|
+
* (or override via `provider.bindingScopeFor` if set).
|
|
44
|
+
* 5. **Collect reference sites.** Walk `@reference.*` matches. Emit
|
|
45
|
+
* one `ReferenceSite` per match. Classify call form via
|
|
46
|
+
* `provider.classifyCallForm` (default: the capture's sub-tag if
|
|
47
|
+
* present; else `'free'`).
|
|
48
|
+
*
|
|
49
|
+
* ## What gets attached where
|
|
50
|
+
*
|
|
51
|
+
* - `Scope.bindings` — **local bindings only** at this stage (Pass 2).
|
|
52
|
+
* Finalize (#915) merges imports/wildcards on top.
|
|
53
|
+
* - `Scope.ownedDefs` — declarations structurally owned by this scope.
|
|
54
|
+
* - `Scope.typeBindings` — local type facts (parameter annotations, `self`).
|
|
55
|
+
* - `Scope.imports` — empty here. Populated by the finalize algorithm
|
|
56
|
+
* when it resolves `ParsedImport.targetRaw`.
|
|
57
|
+
* - `ParsedFile.parsedImports` — every raw import in this file.
|
|
58
|
+
* - `ParsedFile.localDefs` — flattened union of `Scope.ownedDefs`.
|
|
59
|
+
* - `ParsedFile.referenceSites` — pre-resolution usage facts.
|
|
60
|
+
*/
|
|
61
|
+
import type { CaptureMatch, ParsedFile } from '../../_shared/index.js';
|
|
62
|
+
import type { LanguageProvider } from './language-provider.js';
|
|
63
|
+
/**
|
|
64
|
+
* The subset of `LanguageProvider` hooks that `extract()` reads. Declared
|
|
65
|
+
* as its own type so:
|
|
66
|
+
*
|
|
67
|
+
* - Tests can implement just these six hooks without faking the whole
|
|
68
|
+
* `LanguageProvider` interface (which is ~40 fields including the
|
|
69
|
+
* legacy-DAG surface).
|
|
70
|
+
* - The extractor's dependency contract stays explicit — adding a new
|
|
71
|
+
* hook read requires updating this type.
|
|
72
|
+
*
|
|
73
|
+
* Real callers pass a full `LanguageProvider` — structural typing makes it
|
|
74
|
+
* a `ScopeExtractorHooks` for free.
|
|
75
|
+
*/
|
|
76
|
+
export type ScopeExtractorHooks = Pick<LanguageProvider, 'resolveScopeKind' | 'bindingScopeFor' | 'interpretImport' | 'interpretTypeBinding' | 'classifyCallForm'>;
|
|
77
|
+
/**
|
|
78
|
+
* Drive the five extraction passes and return a `ParsedFile`.
|
|
79
|
+
*
|
|
80
|
+
* Throws `ScopeTreeInvariantError` (from #912) when the provider emits
|
|
81
|
+
* captures that violate structural scope invariants. The error surfaces
|
|
82
|
+
* upward rather than being silently corrected — a malformed capture set
|
|
83
|
+
* is a bug in the provider's `emitScopeCaptures`, not a data condition
|
|
84
|
+
* to tolerate.
|
|
85
|
+
*/
|
|
86
|
+
export declare function extract(matches: readonly CaptureMatch[], filePath: string, provider: ScopeExtractorHooks): ParsedFile;
|