gitnexus 1.5.2 → 1.6.0
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 +10 -0
- package/dist/_shared/graph/types.d.ts +1 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +1 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +1 -0
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +1 -0
- package/dist/_shared/languages.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +3 -1
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/mro-strategy.d.ts +19 -0
- package/dist/_shared/mro-strategy.d.ts.map +1 -0
- package/dist/_shared/mro-strategy.js +2 -0
- package/dist/_shared/mro-strategy.js.map +1 -0
- package/dist/cli/ai-context.d.ts +1 -0
- package/dist/cli/ai-context.js +28 -4
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +2 -1
- package/dist/cli/group.d.ts +2 -0
- package/dist/cli/group.js +233 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/serve.js +4 -1
- package/dist/cli/setup.js +34 -3
- package/dist/cli/wiki.js +15 -44
- package/dist/config/ignore-service.js +8 -3
- package/dist/core/augmentation/engine.js +1 -1
- package/dist/core/git-staleness.d.ts +13 -0
- package/dist/core/git-staleness.js +29 -0
- package/dist/core/group/bridge-db.d.ts +82 -0
- package/dist/core/group/bridge-db.js +460 -0
- package/dist/core/group/bridge-schema.d.ts +27 -0
- package/dist/core/group/bridge-schema.js +55 -0
- package/dist/core/group/config-parser.d.ts +3 -0
- package/dist/core/group/config-parser.js +83 -0
- package/dist/core/group/contract-extractor.d.ts +7 -0
- package/dist/core/group/contract-extractor.js +1 -0
- package/dist/core/group/extractors/grpc-extractor.d.ts +16 -0
- package/dist/core/group/extractors/grpc-extractor.js +264 -0
- package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
- package/dist/core/group/extractors/http-route-extractor.js +428 -0
- package/dist/core/group/extractors/topic-extractor.d.ts +9 -0
- package/dist/core/group/extractors/topic-extractor.js +234 -0
- package/dist/core/group/matching.d.ts +13 -0
- package/dist/core/group/matching.js +198 -0
- package/dist/core/group/normalization.d.ts +3 -0
- package/dist/core/group/normalization.js +115 -0
- package/dist/core/group/service-boundary-detector.d.ts +8 -0
- package/dist/core/group/service-boundary-detector.js +155 -0
- package/dist/core/group/service.d.ts +46 -0
- package/dist/core/group/service.js +160 -0
- package/dist/core/group/storage.d.ts +9 -0
- package/dist/core/group/storage.js +91 -0
- package/dist/core/group/sync.d.ts +21 -0
- package/dist/core/group/sync.js +148 -0
- package/dist/core/group/types.d.ts +130 -0
- package/dist/core/group/types.js +1 -0
- package/dist/core/ingestion/binding-accumulator.d.ts +207 -0
- package/dist/core/ingestion/binding-accumulator.js +332 -0
- package/dist/core/ingestion/call-processor.d.ts +155 -24
- package/dist/core/ingestion/call-processor.js +1129 -247
- package/dist/core/ingestion/class-extractors/generic.d.ts +2 -0
- package/dist/core/ingestion/class-extractors/generic.js +135 -0
- package/dist/core/ingestion/class-types.d.ts +34 -0
- package/dist/core/ingestion/class-types.js +1 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +1 -0
- package/dist/core/ingestion/entry-point-scoring.js +1 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +5 -1
- package/dist/core/ingestion/field-extractors/configs/helpers.js +13 -3
- package/dist/core/ingestion/field-types.d.ts +2 -2
- package/dist/core/ingestion/filesystem-walker.js +8 -0
- package/dist/core/ingestion/framework-detection.d.ts +1 -0
- package/dist/core/ingestion/framework-detection.js +1 -0
- package/dist/core/ingestion/heritage-processor.d.ts +8 -15
- package/dist/core/ingestion/heritage-processor.js +15 -28
- package/dist/core/ingestion/import-processor.d.ts +1 -11
- package/dist/core/ingestion/import-processor.js +0 -12
- package/dist/core/ingestion/import-resolvers/utils.js +1 -0
- package/dist/core/ingestion/import-resolvers/vue.d.ts +8 -0
- package/dist/core/ingestion/import-resolvers/vue.js +9 -0
- package/dist/core/ingestion/language-provider.d.ts +6 -3
- package/dist/core/ingestion/languages/c-cpp.js +168 -1
- package/dist/core/ingestion/languages/csharp.js +20 -0
- package/dist/core/ingestion/languages/dart.js +26 -4
- package/dist/core/ingestion/languages/go.js +22 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java.js +17 -0
- package/dist/core/ingestion/languages/kotlin.js +24 -1
- package/dist/core/ingestion/languages/php.js +23 -11
- package/dist/core/ingestion/languages/python.js +9 -0
- package/dist/core/ingestion/languages/ruby.js +28 -0
- package/dist/core/ingestion/languages/rust.js +38 -0
- package/dist/core/ingestion/languages/swift.js +31 -0
- package/dist/core/ingestion/languages/typescript.d.ts +1 -0
- package/dist/core/ingestion/languages/typescript.js +54 -1
- package/dist/core/ingestion/languages/vue.d.ts +13 -0
- package/dist/core/ingestion/languages/vue.js +81 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
- package/dist/core/ingestion/method-extractors/configs/csharp.js +5 -1
- package/dist/core/ingestion/method-extractors/configs/dart.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/dart.js +376 -0
- package/dist/core/ingestion/method-extractors/configs/go.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/go.js +176 -0
- package/dist/core/ingestion/method-extractors/configs/jvm.js +13 -4
- package/dist/core/ingestion/method-extractors/configs/php.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/php.js +304 -0
- package/dist/core/ingestion/method-extractors/configs/python.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/python.js +309 -0
- package/dist/core/ingestion/method-extractors/configs/ruby.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/ruby.js +285 -0
- package/dist/core/ingestion/method-extractors/configs/rust.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/rust.js +195 -0
- package/dist/core/ingestion/method-extractors/configs/swift.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/swift.js +277 -0
- package/dist/core/ingestion/method-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +338 -0
- package/dist/core/ingestion/method-extractors/generic.js +38 -15
- package/dist/core/ingestion/method-types.d.ts +25 -0
- package/dist/core/ingestion/model/field-registry.d.ts +18 -0
- package/dist/core/ingestion/model/field-registry.js +22 -0
- package/dist/core/ingestion/model/heritage-map.d.ts +70 -0
- package/dist/core/ingestion/model/heritage-map.js +159 -0
- package/dist/core/ingestion/model/index.d.ts +20 -0
- package/dist/core/ingestion/model/index.js +41 -0
- package/dist/core/ingestion/model/method-registry.d.ts +62 -0
- package/dist/core/ingestion/model/method-registry.js +130 -0
- package/dist/core/ingestion/model/registration-table.d.ts +139 -0
- package/dist/core/ingestion/model/registration-table.js +224 -0
- package/dist/core/ingestion/model/resolution-context.d.ts +93 -0
- package/dist/core/ingestion/model/resolution-context.js +337 -0
- package/dist/core/ingestion/model/resolve.d.ts +56 -0
- package/dist/core/ingestion/model/resolve.js +242 -0
- package/dist/core/ingestion/model/semantic-model.d.ts +86 -0
- package/dist/core/ingestion/model/semantic-model.js +120 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +222 -0
- package/dist/core/ingestion/model/symbol-table.js +206 -0
- package/dist/core/ingestion/model/type-registry.d.ts +39 -0
- package/dist/core/ingestion/model/type-registry.js +62 -0
- package/dist/core/ingestion/mro-processor.d.ts +4 -3
- package/dist/core/ingestion/mro-processor.js +310 -106
- package/dist/core/ingestion/parsing-processor.d.ts +5 -4
- package/dist/core/ingestion/parsing-processor.js +210 -85
- package/dist/core/ingestion/pipeline.d.ts +2 -0
- package/dist/core/ingestion/pipeline.js +192 -68
- package/dist/core/ingestion/tree-sitter-queries.d.ts +6 -6
- package/dist/core/ingestion/tree-sitter-queries.js +37 -0
- package/dist/core/ingestion/type-env.d.ts +15 -2
- package/dist/core/ingestion/type-env.js +163 -102
- package/dist/core/ingestion/type-extractors/csharp.js +17 -0
- package/dist/core/ingestion/type-extractors/jvm.js +11 -0
- package/dist/core/ingestion/type-extractors/php.js +0 -55
- package/dist/core/ingestion/type-extractors/ruby.js +0 -32
- package/dist/core/ingestion/type-extractors/swift.js +13 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +8 -8
- package/dist/core/ingestion/type-extractors/typescript.js +66 -69
- package/dist/core/ingestion/utils/ast-helpers.d.ts +33 -43
- package/dist/core/ingestion/utils/ast-helpers.js +129 -565
- package/dist/core/ingestion/utils/method-props.d.ts +32 -0
- package/dist/core/ingestion/utils/method-props.js +147 -0
- package/dist/core/ingestion/vue-sfc-extractor.d.ts +44 -0
- package/dist/core/ingestion/vue-sfc-extractor.js +94 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +31 -19
- package/dist/core/ingestion/workers/parse-worker.js +463 -198
- package/dist/core/lbug/lbug-adapter.d.ts +6 -0
- package/dist/core/lbug/lbug-adapter.js +68 -3
- package/dist/core/lbug/pool-adapter.d.ts +76 -0
- package/dist/core/lbug/pool-adapter.js +522 -0
- package/dist/core/run-analyze.d.ts +2 -0
- package/dist/core/run-analyze.js +1 -1
- package/dist/core/search/bm25-index.js +1 -1
- package/dist/core/tree-sitter/parser-loader.js +1 -0
- package/dist/core/wiki/graph-queries.js +1 -1
- package/dist/core/wiki/html-viewer.js +6 -4
- package/dist/core/wiki/llm-client.js +4 -6
- package/dist/mcp/core/embedder.js +6 -5
- package/dist/mcp/core/lbug-adapter.d.ts +3 -63
- package/dist/mcp/core/lbug-adapter.js +3 -484
- package/dist/mcp/local/local-backend.d.ts +31 -2
- package/dist/mcp/local/local-backend.js +255 -46
- package/dist/mcp/resources.js +5 -4
- package/dist/mcp/staleness.d.ts +3 -13
- package/dist/mcp/staleness.js +2 -31
- package/dist/mcp/tools.js +80 -4
- package/dist/server/analyze-job.d.ts +2 -0
- package/dist/server/analyze-job.js +4 -0
- package/dist/server/api.d.ts +20 -1
- package/dist/server/api.js +306 -71
- package/dist/server/git-clone.d.ts +2 -1
- package/dist/server/git-clone.js +98 -5
- package/dist/storage/git.d.ts +13 -0
- package/dist/storage/git.js +25 -0
- package/dist/storage/repo-manager.js +1 -1
- package/package.json +8 -2
- package/scripts/patch-tree-sitter-swift.cjs +78 -0
- package/dist/core/ingestion/named-binding-processor.d.ts +0 -18
- package/dist/core/ingestion/named-binding-processor.js +0 -42
- package/dist/core/ingestion/resolution-context.d.ts +0 -58
- package/dist/core/ingestion/resolution-context.js +0 -135
- package/dist/core/ingestion/symbol-table.d.ts +0 -79
- package/dist/core/ingestion/symbol-table.js +0 -115
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Model
|
|
3
|
+
*
|
|
4
|
+
* Top-level orchestrator for all resolution-time data. Owns:
|
|
5
|
+
*
|
|
6
|
+
* - Three owner-scoped registries (types, methods, fields)
|
|
7
|
+
* - A nested SymbolTable (file + callable name indexes) wrapped so
|
|
8
|
+
* that `add()` fans out into the registries via the dispatch table
|
|
9
|
+
*
|
|
10
|
+
* ## DAG direction
|
|
11
|
+
*
|
|
12
|
+
* gitnexus-shared (NodeLabel) — leaf
|
|
13
|
+
* ↑
|
|
14
|
+
* symbol-table.ts — pure file/callable index
|
|
15
|
+
* ↑
|
|
16
|
+
* model/type-registry / method-registry / field-registry
|
|
17
|
+
* ↑
|
|
18
|
+
* model/registration-table.ts — dispatch table factory
|
|
19
|
+
* ↑
|
|
20
|
+
* model/semantic-model.ts — THIS FILE (orchestrator)
|
|
21
|
+
* ↑
|
|
22
|
+
* resolve.ts, call-processor.ts, resolution-context.ts, ...
|
|
23
|
+
*
|
|
24
|
+
* `symbol-table.ts` is a leaf — it never imports from `./model/`. This
|
|
25
|
+
* file (semantic-model.ts) is the ONLY place where SymbolTable and the
|
|
26
|
+
* owner-scoped registries are composed. Upstream consumers pass around
|
|
27
|
+
* the `SemanticModel` interface and reach into `.symbols` for file-scoped
|
|
28
|
+
* operations or `.types` / `.methods` / `.fields` for owner-scoped ones.
|
|
29
|
+
*
|
|
30
|
+
* ## Fan-out via wrapped add()
|
|
31
|
+
*
|
|
32
|
+
* `createSemanticModel()` creates a pure SymbolTable, creates the three
|
|
33
|
+
* registries, builds a dispatch table via `createRegistrationTable`, and
|
|
34
|
+
* exposes a SymbolTable-shaped façade whose `add()`:
|
|
35
|
+
*
|
|
36
|
+
* 1. Calls `rawSymbols.add()` — writes the fileIndex + callable index
|
|
37
|
+
* and returns the fully-built `SymbolDefinition`.
|
|
38
|
+
* 2. Runs pre-dispatch normalization (`Function`-with-`ownerId` routes
|
|
39
|
+
* as `Method`).
|
|
40
|
+
* 3. Looks up the dispatch table and invokes the hook, which writes to
|
|
41
|
+
* the appropriate owner-scoped registry.
|
|
42
|
+
*
|
|
43
|
+
* The wrapper is the only place where the two layers are combined. A
|
|
44
|
+
* direct `createSymbolTable()` caller (e.g. an isolated unit test) gets
|
|
45
|
+
* the pure, registry-free behavior — no surprises, no hidden side
|
|
46
|
+
* effects.
|
|
47
|
+
*/
|
|
48
|
+
import type { TypeRegistry, MutableTypeRegistry } from './type-registry.js';
|
|
49
|
+
import type { MethodRegistry, MutableMethodRegistry } from './method-registry.js';
|
|
50
|
+
import type { FieldRegistry, MutableFieldRegistry } from './field-registry.js';
|
|
51
|
+
import type { SymbolTableReader, SymbolTableWriter } from './symbol-table.js';
|
|
52
|
+
/**
|
|
53
|
+
* Aggregated read-only view of the semantic registries plus the nested
|
|
54
|
+
* file/callable SymbolTable.
|
|
55
|
+
*
|
|
56
|
+
* `symbols` is typed as {@link SymbolTableReader} — consumers can query
|
|
57
|
+
* symbols but cannot register new ones or trigger a reset. Callers that
|
|
58
|
+
* need to register symbols or reset state must hold a
|
|
59
|
+
* {@link MutableSemanticModel} reference instead, which widens
|
|
60
|
+
* `symbols` back to {@link SymbolTableWriter} and adds `clear()` on the
|
|
61
|
+
* model itself.
|
|
62
|
+
*
|
|
63
|
+
* This segregation is the runtime half of the principle of least
|
|
64
|
+
* authority: a resolver that receives `SemanticModel` physically cannot
|
|
65
|
+
* mutate the index, so it cannot desync the leaf from the owner-scoped
|
|
66
|
+
* registries even accidentally.
|
|
67
|
+
*/
|
|
68
|
+
export interface SemanticModel {
|
|
69
|
+
readonly types: TypeRegistry;
|
|
70
|
+
readonly methods: MethodRegistry;
|
|
71
|
+
readonly fields: FieldRegistry;
|
|
72
|
+
readonly symbols: SymbolTableReader;
|
|
73
|
+
}
|
|
74
|
+
/** Mutable variant — exposes the MutableX registries, a Writer-typed
|
|
75
|
+
* `symbols` facade, and a full-cascade reset. This is the interface
|
|
76
|
+
* held by the lifecycle owner (pipeline, resolution-context); resolvers
|
|
77
|
+
* that only query should hold the narrower {@link SemanticModel}. */
|
|
78
|
+
export interface MutableSemanticModel extends SemanticModel {
|
|
79
|
+
readonly types: MutableTypeRegistry;
|
|
80
|
+
readonly methods: MutableMethodRegistry;
|
|
81
|
+
readonly fields: MutableFieldRegistry;
|
|
82
|
+
readonly symbols: SymbolTableWriter;
|
|
83
|
+
/** Clear all registries AND the nested SymbolTable. */
|
|
84
|
+
clear(): void;
|
|
85
|
+
}
|
|
86
|
+
export declare const createSemanticModel: () => MutableSemanticModel;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Model
|
|
3
|
+
*
|
|
4
|
+
* Top-level orchestrator for all resolution-time data. Owns:
|
|
5
|
+
*
|
|
6
|
+
* - Three owner-scoped registries (types, methods, fields)
|
|
7
|
+
* - A nested SymbolTable (file + callable name indexes) wrapped so
|
|
8
|
+
* that `add()` fans out into the registries via the dispatch table
|
|
9
|
+
*
|
|
10
|
+
* ## DAG direction
|
|
11
|
+
*
|
|
12
|
+
* gitnexus-shared (NodeLabel) — leaf
|
|
13
|
+
* ↑
|
|
14
|
+
* symbol-table.ts — pure file/callable index
|
|
15
|
+
* ↑
|
|
16
|
+
* model/type-registry / method-registry / field-registry
|
|
17
|
+
* ↑
|
|
18
|
+
* model/registration-table.ts — dispatch table factory
|
|
19
|
+
* ↑
|
|
20
|
+
* model/semantic-model.ts — THIS FILE (orchestrator)
|
|
21
|
+
* ↑
|
|
22
|
+
* resolve.ts, call-processor.ts, resolution-context.ts, ...
|
|
23
|
+
*
|
|
24
|
+
* `symbol-table.ts` is a leaf — it never imports from `./model/`. This
|
|
25
|
+
* file (semantic-model.ts) is the ONLY place where SymbolTable and the
|
|
26
|
+
* owner-scoped registries are composed. Upstream consumers pass around
|
|
27
|
+
* the `SemanticModel` interface and reach into `.symbols` for file-scoped
|
|
28
|
+
* operations or `.types` / `.methods` / `.fields` for owner-scoped ones.
|
|
29
|
+
*
|
|
30
|
+
* ## Fan-out via wrapped add()
|
|
31
|
+
*
|
|
32
|
+
* `createSemanticModel()` creates a pure SymbolTable, creates the three
|
|
33
|
+
* registries, builds a dispatch table via `createRegistrationTable`, and
|
|
34
|
+
* exposes a SymbolTable-shaped façade whose `add()`:
|
|
35
|
+
*
|
|
36
|
+
* 1. Calls `rawSymbols.add()` — writes the fileIndex + callable index
|
|
37
|
+
* and returns the fully-built `SymbolDefinition`.
|
|
38
|
+
* 2. Runs pre-dispatch normalization (`Function`-with-`ownerId` routes
|
|
39
|
+
* as `Method`).
|
|
40
|
+
* 3. Looks up the dispatch table and invokes the hook, which writes to
|
|
41
|
+
* the appropriate owner-scoped registry.
|
|
42
|
+
*
|
|
43
|
+
* The wrapper is the only place where the two layers are combined. A
|
|
44
|
+
* direct `createSymbolTable()` caller (e.g. an isolated unit test) gets
|
|
45
|
+
* the pure, registry-free behavior — no surprises, no hidden side
|
|
46
|
+
* effects.
|
|
47
|
+
*/
|
|
48
|
+
import { createTypeRegistry } from './type-registry.js';
|
|
49
|
+
import { createMethodRegistry } from './method-registry.js';
|
|
50
|
+
import { createFieldRegistry } from './field-registry.js';
|
|
51
|
+
import { createSymbolTable } from './symbol-table.js';
|
|
52
|
+
import { createRegistrationTable } from './registration-table.js';
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Factory
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
//
|
|
57
|
+
// NodeLabel taxonomy drift detection lives in `registration-table.ts` as a
|
|
58
|
+
// pure compile-time check — the `LABEL_BEHAVIOR` map is
|
|
59
|
+
// `Record<NodeLabel, LabelBehavior>` with `as const satisfies`, which proves
|
|
60
|
+
// coverage, uniqueness, and no-extra-keys at build time. No runtime guard
|
|
61
|
+
// is needed because drift is structurally impossible in the source.
|
|
62
|
+
export const createSemanticModel = () => {
|
|
63
|
+
// 1. Create the pure, registry-unaware SymbolTable leaf.
|
|
64
|
+
// rawSymbols is the only handle in the codebase whose type (the
|
|
65
|
+
// internal createSymbolTable return) includes `.clear()`. cascadeClear
|
|
66
|
+
// below reaches it here; no external caller receives this variable.
|
|
67
|
+
const rawSymbols = createSymbolTable();
|
|
68
|
+
// 2. Create the three owner-scoped registries.
|
|
69
|
+
const types = createTypeRegistry();
|
|
70
|
+
const methods = createMethodRegistry();
|
|
71
|
+
const fields = createFieldRegistry();
|
|
72
|
+
// 3. Build the dispatch table, closed over THIS instance's registries.
|
|
73
|
+
const dispatchTable = createRegistrationTable({ types, methods, fields });
|
|
74
|
+
// 4. Wrap rawSymbols so `add()` fans out into the registries via the
|
|
75
|
+
// dispatch table. See module JSDoc for the three-step contract.
|
|
76
|
+
const wrappedAdd = (filePath, name, nodeId, type, metadata) => {
|
|
77
|
+
const def = rawSymbols.add(filePath, name, nodeId, type, metadata);
|
|
78
|
+
// Function-with-ownerId (Python `def` in a class body, Rust trait
|
|
79
|
+
// method, Kotlin companion method) routes as Method. Keeps the
|
|
80
|
+
// dispatch table single-purpose.
|
|
81
|
+
const dispatchKey = type === 'Function' && metadata?.ownerId !== undefined ? 'Method' : type;
|
|
82
|
+
const hook = dispatchTable.get(dispatchKey);
|
|
83
|
+
if (hook) {
|
|
84
|
+
hook(name, def);
|
|
85
|
+
}
|
|
86
|
+
return def;
|
|
87
|
+
};
|
|
88
|
+
// Cascade clear: single source of truth for "reset the entire model".
|
|
89
|
+
// Wired into both `model.clear()` AND `model.symbols.clear()` so that a
|
|
90
|
+
// caller holding only a SymbolTable reference can't leave the
|
|
91
|
+
// owner-scoped registries populated while the file/callable indexes go
|
|
92
|
+
// empty (the phantom-resolution failure mode).
|
|
93
|
+
const cascadeClear = () => {
|
|
94
|
+
types.clear();
|
|
95
|
+
methods.clear();
|
|
96
|
+
fields.clear();
|
|
97
|
+
rawSymbols.clear();
|
|
98
|
+
};
|
|
99
|
+
// Writer-typed facade: exposes reads + add, but NO `clear` field.
|
|
100
|
+
// Callers holding a `SemanticModel.symbols` reference cannot desync
|
|
101
|
+
// the leaf indexes from the owner-scoped registries. Consumers that
|
|
102
|
+
// only query should widen their annotation to SymbolTableReader for
|
|
103
|
+
// least-authority clarity.
|
|
104
|
+
const symbols = {
|
|
105
|
+
add: wrappedAdd,
|
|
106
|
+
lookupExact: rawSymbols.lookupExact,
|
|
107
|
+
lookupExactFull: rawSymbols.lookupExactFull,
|
|
108
|
+
lookupExactAll: rawSymbols.lookupExactAll,
|
|
109
|
+
lookupCallableByName: rawSymbols.lookupCallableByName,
|
|
110
|
+
getFiles: rawSymbols.getFiles,
|
|
111
|
+
getStats: rawSymbols.getStats,
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
types,
|
|
115
|
+
methods,
|
|
116
|
+
fields,
|
|
117
|
+
symbols,
|
|
118
|
+
clear: cascadeClear,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbol Table — file-indexed + callable-name symbol storage.
|
|
3
|
+
*
|
|
4
|
+
* This module is a PURE LEAF in the ingestion DAG. It owns two orthogonal
|
|
5
|
+
* O(1) indexes:
|
|
6
|
+
*
|
|
7
|
+
* 1. fileIndex — Map<filePath, Map<name, SymbolDefinition[]>>
|
|
8
|
+
* for same-file lookups (Tier 1 resolution)
|
|
9
|
+
* 2. callableByName — Map<name, SymbolDefinition[]>
|
|
10
|
+
* for name-keyed callable lookups (Tier 3 widen)
|
|
11
|
+
*
|
|
12
|
+
* SymbolTable deliberately knows NOTHING about the owner-scoped registries
|
|
13
|
+
* (types, methods, fields) that sit above it in the DAG. Those registries
|
|
14
|
+
* live in `model/` and depend on SymbolTable, not the other way around.
|
|
15
|
+
* {@link createSemanticModel} composes this pure SymbolTable with the
|
|
16
|
+
* registries and wraps `add()` to fan out registrations into both layers.
|
|
17
|
+
*
|
|
18
|
+
* DAG direction (strictly enforced):
|
|
19
|
+
*
|
|
20
|
+
* gitnexus-shared (NodeLabel) — leaf type
|
|
21
|
+
* ↑
|
|
22
|
+
* symbol-table.ts — THIS FILE (pure storage)
|
|
23
|
+
* ↑
|
|
24
|
+
* model/type-registry.ts, method-registry.ts, field-registry.ts
|
|
25
|
+
* ↑
|
|
26
|
+
* model/registration-table.ts — dispatch table factory
|
|
27
|
+
* ↑
|
|
28
|
+
* model/semantic-model.ts — orchestrator, wraps add()
|
|
29
|
+
* ↑
|
|
30
|
+
* model/resolve.ts, call-processor.ts, resolution-context.ts, ...
|
|
31
|
+
*
|
|
32
|
+
* No arrow ever points downward from this file. If you are tempted to
|
|
33
|
+
* import from `./model/` here, you are going the wrong way — move the
|
|
34
|
+
* logic up the DAG instead.
|
|
35
|
+
*/
|
|
36
|
+
import type { NodeLabel } from '../../../_shared/index.js';
|
|
37
|
+
/**
|
|
38
|
+
* Class-like NodeLabels — used for qualifiedName fallback inside
|
|
39
|
+
* `SymbolTable.add()` and (via import into `model/registration-table.ts`)
|
|
40
|
+
* as the single source of truth for which labels route to classHook
|
|
41
|
+
* in the dispatch table.
|
|
42
|
+
*
|
|
43
|
+
* Exported as a `readonly` tuple so that `typeof CLASS_TYPES_TUPLE[number]`
|
|
44
|
+
* yields a precise literal union (`ClassLikeLabel`). The model layer
|
|
45
|
+
* imports this tuple and uses `Record<ClassLikeLabel, 'dispatch'>` in a
|
|
46
|
+
* `satisfies` intersection to enforce at COMPILE TIME that every label
|
|
47
|
+
* listed here is also classified as dispatch in `LABEL_BEHAVIOR`. Adding
|
|
48
|
+
* a new class-like label to this tuple without updating `LABEL_BEHAVIOR`
|
|
49
|
+
* fails TypeScript.
|
|
50
|
+
*
|
|
51
|
+
* Traits are class-like for heritage resolution: PHP `use Trait;`, Rust
|
|
52
|
+
* `impl Trait for Struct`, and Scala traits all contribute methods to the
|
|
53
|
+
* hierarchy of their using/implementing type.
|
|
54
|
+
*/
|
|
55
|
+
export declare const CLASS_TYPES_TUPLE: readonly ["Class", "Struct", "Interface", "Enum", "Record", "Trait"];
|
|
56
|
+
export type ClassLikeLabel = (typeof CLASS_TYPES_TUPLE)[number];
|
|
57
|
+
export declare const CLASS_TYPES: ReadonlySet<NodeLabel>;
|
|
58
|
+
/** Free-callable labels — single source of truth for "callables that have
|
|
59
|
+
* NO owner scope". Methods and constructors are owner-scoped and live in
|
|
60
|
+
* `MethodRegistry` — Tier 3 reaches them via
|
|
61
|
+
* `model.methods.lookupMethodByName`. See `resolution-context.ts` Tier 3
|
|
62
|
+
* for how both indexes are consulted together.
|
|
63
|
+
*
|
|
64
|
+
* Exported as a `readonly` tuple so that `typeof FREE_CALLABLE_TUPLE[number]`
|
|
65
|
+
* yields a precise literal union (`FreeCallableLabel`). `registration-table.ts`
|
|
66
|
+
* imports this type and uses `Record<FreeCallableLabel, 'callable-only'>` in
|
|
67
|
+
* a `satisfies` intersection to enforce at COMPILE TIME that every label
|
|
68
|
+
* listed here is also classified as `callable-only` in `LABEL_BEHAVIOR`.
|
|
69
|
+
* Adding a label to this tuple without updating `LABEL_BEHAVIOR` fails
|
|
70
|
+
* TypeScript.
|
|
71
|
+
*
|
|
72
|
+
* Partial-state caveat: Python/Rust/Kotlin class methods are emitted by
|
|
73
|
+
* the worker as `Function` + `ownerId` (not `Method`), so they still land
|
|
74
|
+
* here via the `Function` entry. Collapsing those three languages onto the
|
|
75
|
+
* `Method` label is pending a `def.type` preservation decision.
|
|
76
|
+
*/
|
|
77
|
+
export declare const FREE_CALLABLE_TUPLE: readonly ["Function", "Macro", "Delegate"];
|
|
78
|
+
export type FreeCallableLabel = (typeof FREE_CALLABLE_TUPLE)[number];
|
|
79
|
+
export declare const FREE_CALLABLE_TYPES: ReadonlySet<NodeLabel>;
|
|
80
|
+
/** Symbol types that can be the TARGET of a call in the resolver's kind
|
|
81
|
+
* filter — superset of {@link FREE_CALLABLE_TYPES} that also admits
|
|
82
|
+
* owner-scoped methods and constructors pulled in from `MethodRegistry`.
|
|
83
|
+
*
|
|
84
|
+
* Why the split: `FREE_CALLABLE_TYPES` now has a narrow meaning (free
|
|
85
|
+
* callables indexed in `callableByName`), but call resolution still
|
|
86
|
+
* needs to accept Method and Constructor candidates once they have been
|
|
87
|
+
* unioned in from `model.methods.lookupMethodByName`. The resolver uses
|
|
88
|
+
* this constant for kind filtering in
|
|
89
|
+
* `filterCallableCandidates` / `countCallableCandidates`.
|
|
90
|
+
*/
|
|
91
|
+
export declare const CALL_TARGET_TYPES: ReadonlySet<NodeLabel>;
|
|
92
|
+
export interface SymbolDefinition {
|
|
93
|
+
nodeId: string;
|
|
94
|
+
filePath: string;
|
|
95
|
+
type: NodeLabel;
|
|
96
|
+
/** Canonical dot-separated qualified type name for class-like symbols
|
|
97
|
+
* (e.g. `App.Models.User`). Falls back to the simple symbol name when no
|
|
98
|
+
* package/namespace/module scope exists or no explicit qualified metadata is provided. */
|
|
99
|
+
qualifiedName?: string;
|
|
100
|
+
parameterCount?: number;
|
|
101
|
+
/** Number of required (non-optional, non-default) parameters.
|
|
102
|
+
* Enables range-based arity filtering: argCount >= requiredParameterCount && argCount <= parameterCount. */
|
|
103
|
+
requiredParameterCount?: number;
|
|
104
|
+
/** Per-parameter type names for overload disambiguation (e.g. ['int', 'String']).
|
|
105
|
+
* Populated when parameter types are resolvable from AST (any typed language). */
|
|
106
|
+
parameterTypes?: string[];
|
|
107
|
+
/** Raw return type text extracted from AST (e.g. 'User', 'Promise<User>') */
|
|
108
|
+
returnType?: string;
|
|
109
|
+
/** Declared type for non-callable symbols — fields/properties (e.g. 'Address', 'List<User>') */
|
|
110
|
+
declaredType?: string;
|
|
111
|
+
/** Links Method/Constructor/Property to owning Class/Struct/Trait nodeId */
|
|
112
|
+
ownerId?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Optional metadata accepted by {@link SymbolTable.add}. Kept as a separate
|
|
116
|
+
* type alias so callers and wrappers can share the same shape.
|
|
117
|
+
*/
|
|
118
|
+
export interface AddMetadata {
|
|
119
|
+
parameterCount?: number;
|
|
120
|
+
requiredParameterCount?: number;
|
|
121
|
+
parameterTypes?: string[];
|
|
122
|
+
returnType?: string;
|
|
123
|
+
declaredType?: string;
|
|
124
|
+
ownerId?: string;
|
|
125
|
+
qualifiedName?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Pure read-only view over the file and callable indexes. Does NOT
|
|
129
|
+
* include `add()` or `clear()`.
|
|
130
|
+
*
|
|
131
|
+
* Used by consumers that only query symbols (resolvers, type-env, field
|
|
132
|
+
* extractors). The interface is strictly observational — holding a
|
|
133
|
+
* `SymbolTableReader` cannot mutate the table in any way.
|
|
134
|
+
*
|
|
135
|
+
* For consumers that also need to register symbols, use
|
|
136
|
+
* {@link SymbolTableWriter}, which extends this interface with `add()`.
|
|
137
|
+
* Neither interface exposes `clear()` — that capability lives on the
|
|
138
|
+
* internal factory return type and is reachable only inside
|
|
139
|
+
* `SemanticModel` via `rawSymbols`.
|
|
140
|
+
*
|
|
141
|
+
* Segregating the observer contract from the mutation contract means
|
|
142
|
+
* callers holding only a Reader can never desync the model.
|
|
143
|
+
*/
|
|
144
|
+
export interface SymbolTableReader {
|
|
145
|
+
/**
|
|
146
|
+
* High Confidence: Look for a symbol specifically inside a file.
|
|
147
|
+
* Returns the Node ID if found.
|
|
148
|
+
*/
|
|
149
|
+
lookupExact: (filePath: string, name: string) => string | undefined;
|
|
150
|
+
/**
|
|
151
|
+
* High Confidence: Look for a symbol in a specific file, returning full definition.
|
|
152
|
+
* Returns first matching definition — use lookupExactAll for overloaded methods.
|
|
153
|
+
*/
|
|
154
|
+
lookupExactFull: (filePath: string, name: string) => SymbolDefinition | undefined;
|
|
155
|
+
/**
|
|
156
|
+
* High Confidence: Look for ALL symbols with this name in a specific file.
|
|
157
|
+
* Returns all definitions, including overloaded methods with the same name.
|
|
158
|
+
* The returned array is a view into the live internal index — callers
|
|
159
|
+
* MUST NOT mutate it. Use `readonly` to enforce this at the type level.
|
|
160
|
+
*/
|
|
161
|
+
lookupExactAll: (filePath: string, name: string) => readonly SymbolDefinition[];
|
|
162
|
+
/**
|
|
163
|
+
* Look up callable symbols (Function, Macro, Delegate) by name.
|
|
164
|
+
* O(1) via dedicated eagerly-populated index keyed by symbol name.
|
|
165
|
+
* Returned array is a view into the live index — do not mutate.
|
|
166
|
+
*/
|
|
167
|
+
lookupCallableByName: (name: string) => readonly SymbolDefinition[];
|
|
168
|
+
/**
|
|
169
|
+
* Iterate all indexed file paths.
|
|
170
|
+
* Used by Tier 2b (package-scoped) resolution to walk files matching a
|
|
171
|
+
* package directory suffix without a global name scan.
|
|
172
|
+
*/
|
|
173
|
+
getFiles: () => IterableIterator<string>;
|
|
174
|
+
/**
|
|
175
|
+
* Debugging: See how many files are tracked.
|
|
176
|
+
*/
|
|
177
|
+
getStats: () => {
|
|
178
|
+
fileCount: number;
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Writer view — reads + symbol registration. Does NOT include `clear()`.
|
|
183
|
+
*
|
|
184
|
+
* `MutableSemanticModel.symbols` is typed as this interface, so the
|
|
185
|
+
* lifecycle owner can register symbols and query them. Full-model
|
|
186
|
+
* resets flow through `model.clear()`.
|
|
187
|
+
*
|
|
188
|
+
* The cascading `clear()` capability lives exclusively on the internal
|
|
189
|
+
* factory return type ({@link createSymbolTable}) — a private handle
|
|
190
|
+
* held only by `SemanticModel` via `rawSymbols`.
|
|
191
|
+
*/
|
|
192
|
+
export interface SymbolTableWriter extends SymbolTableReader {
|
|
193
|
+
/**
|
|
194
|
+
* Register a symbol in the file and (if callable) name-keyed indexes.
|
|
195
|
+
*
|
|
196
|
+
* Returns the constructed {@link SymbolDefinition} so higher-layer
|
|
197
|
+
* wrappers (e.g. `createSemanticModel`) can reuse it without rebuilding
|
|
198
|
+
* the def. This keeps the fan-out in one allocation.
|
|
199
|
+
*/
|
|
200
|
+
add: (filePath: string, name: string, nodeId: string, type: NodeLabel, metadata?: AddMetadata) => SymbolDefinition;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Internal return type for {@link createSymbolTable} — extends the
|
|
204
|
+
* writer with `clear()`. This capability is intentionally NOT exported
|
|
205
|
+
* as a named interface; consumers should hold a `SymbolTableReader` or
|
|
206
|
+
* `SymbolTableWriter` instead.
|
|
207
|
+
*
|
|
208
|
+
* `SemanticModel`'s constructor is the only caller of `createSymbolTable`,
|
|
209
|
+
* and it retains the returned handle as the private `rawSymbols`
|
|
210
|
+
* reference so `cascadeClear` can reach `clear()`. Every other consumer
|
|
211
|
+
* receives the narrower `SymbolTableWriter` facade on `model.symbols`.
|
|
212
|
+
*/
|
|
213
|
+
interface InternalSymbolTable extends SymbolTableWriter {
|
|
214
|
+
/**
|
|
215
|
+
* Cleanup memory. Clears only the file and callable indexes owned here —
|
|
216
|
+
* owner-scoped registries are cleared by their respective owners via
|
|
217
|
+
* `model.clear()`.
|
|
218
|
+
*/
|
|
219
|
+
clear: () => void;
|
|
220
|
+
}
|
|
221
|
+
export declare const createSymbolTable: () => InternalSymbolTable;
|
|
222
|
+
export {};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbol Table — file-indexed + callable-name symbol storage.
|
|
3
|
+
*
|
|
4
|
+
* This module is a PURE LEAF in the ingestion DAG. It owns two orthogonal
|
|
5
|
+
* O(1) indexes:
|
|
6
|
+
*
|
|
7
|
+
* 1. fileIndex — Map<filePath, Map<name, SymbolDefinition[]>>
|
|
8
|
+
* for same-file lookups (Tier 1 resolution)
|
|
9
|
+
* 2. callableByName — Map<name, SymbolDefinition[]>
|
|
10
|
+
* for name-keyed callable lookups (Tier 3 widen)
|
|
11
|
+
*
|
|
12
|
+
* SymbolTable deliberately knows NOTHING about the owner-scoped registries
|
|
13
|
+
* (types, methods, fields) that sit above it in the DAG. Those registries
|
|
14
|
+
* live in `model/` and depend on SymbolTable, not the other way around.
|
|
15
|
+
* {@link createSemanticModel} composes this pure SymbolTable with the
|
|
16
|
+
* registries and wraps `add()` to fan out registrations into both layers.
|
|
17
|
+
*
|
|
18
|
+
* DAG direction (strictly enforced):
|
|
19
|
+
*
|
|
20
|
+
* gitnexus-shared (NodeLabel) — leaf type
|
|
21
|
+
* ↑
|
|
22
|
+
* symbol-table.ts — THIS FILE (pure storage)
|
|
23
|
+
* ↑
|
|
24
|
+
* model/type-registry.ts, method-registry.ts, field-registry.ts
|
|
25
|
+
* ↑
|
|
26
|
+
* model/registration-table.ts — dispatch table factory
|
|
27
|
+
* ↑
|
|
28
|
+
* model/semantic-model.ts — orchestrator, wraps add()
|
|
29
|
+
* ↑
|
|
30
|
+
* model/resolve.ts, call-processor.ts, resolution-context.ts, ...
|
|
31
|
+
*
|
|
32
|
+
* No arrow ever points downward from this file. If you are tempted to
|
|
33
|
+
* import from `./model/` here, you are going the wrong way — move the
|
|
34
|
+
* logic up the DAG instead.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Class-like NodeLabels — used for qualifiedName fallback inside
|
|
38
|
+
* `SymbolTable.add()` and (via import into `model/registration-table.ts`)
|
|
39
|
+
* as the single source of truth for which labels route to classHook
|
|
40
|
+
* in the dispatch table.
|
|
41
|
+
*
|
|
42
|
+
* Exported as a `readonly` tuple so that `typeof CLASS_TYPES_TUPLE[number]`
|
|
43
|
+
* yields a precise literal union (`ClassLikeLabel`). The model layer
|
|
44
|
+
* imports this tuple and uses `Record<ClassLikeLabel, 'dispatch'>` in a
|
|
45
|
+
* `satisfies` intersection to enforce at COMPILE TIME that every label
|
|
46
|
+
* listed here is also classified as dispatch in `LABEL_BEHAVIOR`. Adding
|
|
47
|
+
* a new class-like label to this tuple without updating `LABEL_BEHAVIOR`
|
|
48
|
+
* fails TypeScript.
|
|
49
|
+
*
|
|
50
|
+
* Traits are class-like for heritage resolution: PHP `use Trait;`, Rust
|
|
51
|
+
* `impl Trait for Struct`, and Scala traits all contribute methods to the
|
|
52
|
+
* hierarchy of their using/implementing type.
|
|
53
|
+
*/
|
|
54
|
+
export const CLASS_TYPES_TUPLE = [
|
|
55
|
+
'Class',
|
|
56
|
+
'Struct',
|
|
57
|
+
'Interface',
|
|
58
|
+
'Enum',
|
|
59
|
+
'Record',
|
|
60
|
+
'Trait',
|
|
61
|
+
];
|
|
62
|
+
export const CLASS_TYPES = new Set(CLASS_TYPES_TUPLE);
|
|
63
|
+
/** Free-callable labels — single source of truth for "callables that have
|
|
64
|
+
* NO owner scope". Methods and constructors are owner-scoped and live in
|
|
65
|
+
* `MethodRegistry` — Tier 3 reaches them via
|
|
66
|
+
* `model.methods.lookupMethodByName`. See `resolution-context.ts` Tier 3
|
|
67
|
+
* for how both indexes are consulted together.
|
|
68
|
+
*
|
|
69
|
+
* Exported as a `readonly` tuple so that `typeof FREE_CALLABLE_TUPLE[number]`
|
|
70
|
+
* yields a precise literal union (`FreeCallableLabel`). `registration-table.ts`
|
|
71
|
+
* imports this type and uses `Record<FreeCallableLabel, 'callable-only'>` in
|
|
72
|
+
* a `satisfies` intersection to enforce at COMPILE TIME that every label
|
|
73
|
+
* listed here is also classified as `callable-only` in `LABEL_BEHAVIOR`.
|
|
74
|
+
* Adding a label to this tuple without updating `LABEL_BEHAVIOR` fails
|
|
75
|
+
* TypeScript.
|
|
76
|
+
*
|
|
77
|
+
* Partial-state caveat: Python/Rust/Kotlin class methods are emitted by
|
|
78
|
+
* the worker as `Function` + `ownerId` (not `Method`), so they still land
|
|
79
|
+
* here via the `Function` entry. Collapsing those three languages onto the
|
|
80
|
+
* `Method` label is pending a `def.type` preservation decision.
|
|
81
|
+
*/
|
|
82
|
+
export const FREE_CALLABLE_TUPLE = [
|
|
83
|
+
'Function',
|
|
84
|
+
'Macro', // C/C++
|
|
85
|
+
'Delegate', // C#
|
|
86
|
+
];
|
|
87
|
+
export const FREE_CALLABLE_TYPES = new Set(FREE_CALLABLE_TUPLE);
|
|
88
|
+
/** Symbol types that can be the TARGET of a call in the resolver's kind
|
|
89
|
+
* filter — superset of {@link FREE_CALLABLE_TYPES} that also admits
|
|
90
|
+
* owner-scoped methods and constructors pulled in from `MethodRegistry`.
|
|
91
|
+
*
|
|
92
|
+
* Why the split: `FREE_CALLABLE_TYPES` now has a narrow meaning (free
|
|
93
|
+
* callables indexed in `callableByName`), but call resolution still
|
|
94
|
+
* needs to accept Method and Constructor candidates once they have been
|
|
95
|
+
* unioned in from `model.methods.lookupMethodByName`. The resolver uses
|
|
96
|
+
* this constant for kind filtering in
|
|
97
|
+
* `filterCallableCandidates` / `countCallableCandidates`.
|
|
98
|
+
*/
|
|
99
|
+
export const CALL_TARGET_TYPES = new Set([
|
|
100
|
+
...FREE_CALLABLE_TYPES,
|
|
101
|
+
'Method',
|
|
102
|
+
'Constructor',
|
|
103
|
+
]);
|
|
104
|
+
export const createSymbolTable = () => {
|
|
105
|
+
// 1. File-Specific Index — stores full SymbolDefinition(s) for O(1) lookup.
|
|
106
|
+
// Structure: FilePath -> (SymbolName -> SymbolDefinition[])
|
|
107
|
+
// Array allows overloaded methods (same name, different signatures) to coexist.
|
|
108
|
+
const fileIndex = new Map();
|
|
109
|
+
// 2. Eagerly-populated Callable Index — maintained on add().
|
|
110
|
+
// Structure: SymbolName -> [Callable Definitions]
|
|
111
|
+
// Only Function, Method, Constructor, Macro, Delegate symbols are indexed.
|
|
112
|
+
const callableByName = new Map();
|
|
113
|
+
const add = (filePath, name, nodeId, type, metadata) => {
|
|
114
|
+
const qualifiedName = CLASS_TYPES.has(type)
|
|
115
|
+
? (metadata?.qualifiedName ?? name)
|
|
116
|
+
: metadata?.qualifiedName;
|
|
117
|
+
const def = {
|
|
118
|
+
nodeId,
|
|
119
|
+
filePath,
|
|
120
|
+
type,
|
|
121
|
+
...(qualifiedName !== undefined ? { qualifiedName } : {}),
|
|
122
|
+
...(metadata?.parameterCount !== undefined
|
|
123
|
+
? { parameterCount: metadata.parameterCount }
|
|
124
|
+
: {}),
|
|
125
|
+
...(metadata?.requiredParameterCount !== undefined
|
|
126
|
+
? { requiredParameterCount: metadata.requiredParameterCount }
|
|
127
|
+
: {}),
|
|
128
|
+
...(metadata?.parameterTypes !== undefined
|
|
129
|
+
? { parameterTypes: metadata.parameterTypes }
|
|
130
|
+
: {}),
|
|
131
|
+
...(metadata?.returnType !== undefined ? { returnType: metadata.returnType } : {}),
|
|
132
|
+
...(metadata?.declaredType !== undefined ? { declaredType: metadata.declaredType } : {}),
|
|
133
|
+
...(metadata?.ownerId !== undefined ? { ownerId: metadata.ownerId } : {}),
|
|
134
|
+
};
|
|
135
|
+
// A. File Index — unconditional.
|
|
136
|
+
if (!fileIndex.has(filePath)) {
|
|
137
|
+
fileIndex.set(filePath, new Map());
|
|
138
|
+
}
|
|
139
|
+
const fileMap = fileIndex.get(filePath);
|
|
140
|
+
if (!fileMap.has(name)) {
|
|
141
|
+
fileMap.set(name, [def]);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
fileMap.get(name).push(def);
|
|
145
|
+
}
|
|
146
|
+
// B. Callable Index — gated by FREE_CALLABLE_TYPES.
|
|
147
|
+
// Note: Property is NOT in FREE_CALLABLE_TYPES, so it never lands here.
|
|
148
|
+
// This is the single source of truth for callable-index membership;
|
|
149
|
+
// the higher-layer dispatch table only decides owner-scoped routing.
|
|
150
|
+
//
|
|
151
|
+
// Fallback: `Method` or `Constructor` without an `ownerId` is an
|
|
152
|
+
// extractor contract violation (AST-degraded parse, or a buggy
|
|
153
|
+
// language extractor). The owner-scoped dispatch hook silently
|
|
154
|
+
// skips such defs because it has no owner to key them under, so
|
|
155
|
+
// without this fallback they would be invisible at Tier 3 global
|
|
156
|
+
// resolution. Route them through `callableByName` so they remain
|
|
157
|
+
// reachable by name — matching pre-dispatch-table behavior.
|
|
158
|
+
const isOrphanedOwnerScoped = (type === 'Method' || type === 'Constructor') && metadata?.ownerId === undefined;
|
|
159
|
+
if (FREE_CALLABLE_TYPES.has(type) || isOrphanedOwnerScoped) {
|
|
160
|
+
const existing = callableByName.get(name);
|
|
161
|
+
if (existing) {
|
|
162
|
+
existing.push(def);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
callableByName.set(name, [def]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return def;
|
|
169
|
+
};
|
|
170
|
+
const lookupExact = (filePath, name) => {
|
|
171
|
+
const defs = fileIndex.get(filePath)?.get(name);
|
|
172
|
+
return defs?.[0]?.nodeId;
|
|
173
|
+
};
|
|
174
|
+
const lookupExactFull = (filePath, name) => {
|
|
175
|
+
const defs = fileIndex.get(filePath)?.get(name);
|
|
176
|
+
return defs?.[0];
|
|
177
|
+
};
|
|
178
|
+
const lookupExactAll = (filePath, name) => {
|
|
179
|
+
return fileIndex.get(filePath)?.get(name) ?? [];
|
|
180
|
+
};
|
|
181
|
+
const lookupCallableByName = (name) => {
|
|
182
|
+
return callableByName.get(name) ?? [];
|
|
183
|
+
};
|
|
184
|
+
/** Returns a live iterator over all indexed file paths (fileIndex.keys()).
|
|
185
|
+
* The iterator is invalidated if add() changes fileIndex.size during
|
|
186
|
+
* iteration (ES2015 Map spec). Safe in the current pipeline because all
|
|
187
|
+
* symbols are added before resolution begins. */
|
|
188
|
+
const getFiles = () => fileIndex.keys();
|
|
189
|
+
const getStats = () => ({
|
|
190
|
+
fileCount: fileIndex.size,
|
|
191
|
+
});
|
|
192
|
+
const clear = () => {
|
|
193
|
+
fileIndex.clear();
|
|
194
|
+
callableByName.clear();
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
add,
|
|
198
|
+
lookupExact,
|
|
199
|
+
lookupExactFull,
|
|
200
|
+
lookupExactAll,
|
|
201
|
+
lookupCallableByName,
|
|
202
|
+
getFiles,
|
|
203
|
+
getStats,
|
|
204
|
+
clear,
|
|
205
|
+
};
|
|
206
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type Registry
|
|
3
|
+
*
|
|
4
|
+
* Class/struct/interface index extracted from SymbolTable.
|
|
5
|
+
* Eagerly-populated indexes keyed by symbol name and qualified name.
|
|
6
|
+
* Also includes a separate index for Rust Impl blocks.
|
|
7
|
+
*/
|
|
8
|
+
import type { SymbolDefinition } from './symbol-table.js';
|
|
9
|
+
export interface TypeRegistry {
|
|
10
|
+
/**
|
|
11
|
+
* Look up class-like definitions (Class, Struct, Interface, Enum, Record, Trait)
|
|
12
|
+
* by simple name. Returns all matching definitions across files
|
|
13
|
+
* (e.g. partial classes). Returned array is a view into the live
|
|
14
|
+
* internal index — do not mutate.
|
|
15
|
+
*/
|
|
16
|
+
lookupClassByName(name: string): readonly SymbolDefinition[];
|
|
17
|
+
/**
|
|
18
|
+
* Look up class-like definitions by canonical qualified name.
|
|
19
|
+
* Qualified names are normalized to dot-separated scope segments across languages,
|
|
20
|
+
* e.g. `App.Models.User`, `com.example.User`, or `Admin.User`.
|
|
21
|
+
* Returned array is a view into the live index — do not mutate.
|
|
22
|
+
*/
|
|
23
|
+
lookupClassByQualifiedName(qualifiedName: string): readonly SymbolDefinition[];
|
|
24
|
+
/**
|
|
25
|
+
* Look up Impl nodes by name. Used by Tier 3 resolution to include Rust
|
|
26
|
+
* impl blocks alongside class-like candidates.
|
|
27
|
+
* Returned array is a view into the live index — do not mutate.
|
|
28
|
+
*/
|
|
29
|
+
lookupImplByName(name: string): readonly SymbolDefinition[];
|
|
30
|
+
}
|
|
31
|
+
export interface MutableTypeRegistry extends TypeRegistry {
|
|
32
|
+
/** Register a class-like type by name and qualified name. */
|
|
33
|
+
registerClass(name: string, qualifiedName: string, def: SymbolDefinition): void;
|
|
34
|
+
/** Register a Rust Impl block by name. */
|
|
35
|
+
registerImpl(name: string, def: SymbolDefinition): void;
|
|
36
|
+
/** Clear all entries. */
|
|
37
|
+
clear(): void;
|
|
38
|
+
}
|
|
39
|
+
export declare const createTypeRegistry: () => MutableTypeRegistry;
|