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,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Method Registry
|
|
3
|
+
*
|
|
4
|
+
* Owner-scoped method index extracted from SymbolTable.
|
|
5
|
+
* Stores Method/Constructor/Function-with-ownerId symbols keyed by
|
|
6
|
+
* `ownerNodeId\0methodName` for O(1) lookup. Supports overloads
|
|
7
|
+
* (array values) and arity-based filtering.
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Factory
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
export const createMethodRegistry = () => {
|
|
13
|
+
const methodByOwner = new Map();
|
|
14
|
+
// Secondary flat-by-name index. Values are the SAME SymbolDefinition
|
|
15
|
+
// references stored under `methodByOwner` — no copy, just a second key.
|
|
16
|
+
// Populated in lockstep by `register()` and emptied by `clear()`.
|
|
17
|
+
const methodsByName = new Map();
|
|
18
|
+
const EMPTY = Object.freeze([]);
|
|
19
|
+
// Set once when a Function+ownerId def lands here, powers the Tier 3
|
|
20
|
+
// dedup fast-path. Monotonic: never unset except on `clear()`.
|
|
21
|
+
let hasFunctionMethodsFlag = false;
|
|
22
|
+
const lookupMethodByOwner = (ownerNodeId, methodName, argCount) => {
|
|
23
|
+
const defs = methodByOwner.get(`${ownerNodeId}\0${methodName}`);
|
|
24
|
+
if (!defs || defs.length === 0)
|
|
25
|
+
return undefined;
|
|
26
|
+
// Arity narrowing: when an argCount is provided and there are multiple
|
|
27
|
+
// overloads, keep only those whose parameterCount can accommodate the
|
|
28
|
+
// call. This resolves arity-differing overloads (e.g. C++ `greet()` vs
|
|
29
|
+
// `greet(string)`) that share the same `ownerId + methodName` key.
|
|
30
|
+
//
|
|
31
|
+
// Candidates with `parameterCount === undefined` (extractor didn't
|
|
32
|
+
// populate the count — typically variadic or unknown) are retained
|
|
33
|
+
// conservatively so that legitimate variadic matches still resolve.
|
|
34
|
+
//
|
|
35
|
+
// Streaming loop avoids allocating a filtered array on the common
|
|
36
|
+
// "arity selects 0 or 1 match" path. We scan once, count arity
|
|
37
|
+
// matches, and only materialize a narrowed array if at least one
|
|
38
|
+
// match was found and at least one non-match exists. If arity rules
|
|
39
|
+
// out every candidate, fall back to the unfiltered set so the
|
|
40
|
+
// caller's fuzzy path still has something to work with.
|
|
41
|
+
let pool = defs;
|
|
42
|
+
if (argCount !== undefined && defs.length > 1) {
|
|
43
|
+
let matchedCount = 0;
|
|
44
|
+
let rejectedCount = 0;
|
|
45
|
+
for (const d of defs) {
|
|
46
|
+
if (d.parameterCount === undefined) {
|
|
47
|
+
matchedCount++;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const min = d.requiredParameterCount ?? d.parameterCount;
|
|
51
|
+
if (argCount >= min && argCount <= d.parameterCount)
|
|
52
|
+
matchedCount++;
|
|
53
|
+
else
|
|
54
|
+
rejectedCount++;
|
|
55
|
+
}
|
|
56
|
+
// Only narrow when the filter actually discriminates: at least one
|
|
57
|
+
// match AND at least one rejection. Pure-match and pure-reject
|
|
58
|
+
// paths both keep the unfiltered pool (the latter because fallback
|
|
59
|
+
// semantics demand it).
|
|
60
|
+
if (matchedCount > 0 && rejectedCount > 0) {
|
|
61
|
+
const arityMatched = [];
|
|
62
|
+
for (const d of defs) {
|
|
63
|
+
if (d.parameterCount === undefined) {
|
|
64
|
+
arityMatched.push(d);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const min = d.requiredParameterCount ?? d.parameterCount;
|
|
68
|
+
if (argCount >= min && argCount <= d.parameterCount)
|
|
69
|
+
arityMatched.push(d);
|
|
70
|
+
}
|
|
71
|
+
pool = arityMatched;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (pool.length === 1)
|
|
75
|
+
return pool[0];
|
|
76
|
+
// Multiple overloads after arity narrowing: return first if all share
|
|
77
|
+
// the same defined returnType (safe for chain resolution), undefined if
|
|
78
|
+
// return types differ (truly ambiguous — can't determine which overload).
|
|
79
|
+
const firstReturnType = pool[0].returnType;
|
|
80
|
+
if (firstReturnType === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
for (let i = 1; i < pool.length; i++) {
|
|
83
|
+
if (pool[i].returnType !== firstReturnType)
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return pool[0];
|
|
87
|
+
};
|
|
88
|
+
const lookupMethodByName = (name) => {
|
|
89
|
+
return methodsByName.get(name) ?? EMPTY;
|
|
90
|
+
};
|
|
91
|
+
const register = (ownerNodeId, methodName, def) => {
|
|
92
|
+
const key = `${ownerNodeId}\0${methodName}`;
|
|
93
|
+
const existing = methodByOwner.get(key);
|
|
94
|
+
if (existing) {
|
|
95
|
+
existing.push(def);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
methodByOwner.set(key, [def]);
|
|
99
|
+
}
|
|
100
|
+
const byName = methodsByName.get(methodName);
|
|
101
|
+
if (byName) {
|
|
102
|
+
byName.push(def);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
methodsByName.set(methodName, [def]);
|
|
106
|
+
}
|
|
107
|
+
// A `Function`-typed def reaching MethodRegistry means the worker
|
|
108
|
+
// emitted a Python/Rust/Kotlin class method as `Function + ownerId`.
|
|
109
|
+
// It was already written into `SymbolTable.callableByName` by the
|
|
110
|
+
// upstream Function callable-index gate, so the two indexes are no
|
|
111
|
+
// longer disjoint for this registry's lifetime — Tier 3 must dedup.
|
|
112
|
+
if (!hasFunctionMethodsFlag && def.type === 'Function') {
|
|
113
|
+
hasFunctionMethodsFlag = true;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const clear = () => {
|
|
117
|
+
methodByOwner.clear();
|
|
118
|
+
methodsByName.clear();
|
|
119
|
+
hasFunctionMethodsFlag = false;
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
lookupMethodByOwner,
|
|
123
|
+
lookupMethodByName,
|
|
124
|
+
register,
|
|
125
|
+
clear,
|
|
126
|
+
get hasFunctionMethods() {
|
|
127
|
+
return hasFunctionMethodsFlag;
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registration Dispatch Table
|
|
3
|
+
*
|
|
4
|
+
* Behavior-grouped O(1) dispatch table for routing `SymbolTable.add()`
|
|
5
|
+
* registrations into the semantic registries. Replaces the cascading
|
|
6
|
+
* `if/else` ladder in `symbol-table.ts` with a `Map<NodeLabel, RoutingDecision>`
|
|
7
|
+
* whose entries point to closure-captured hooks.
|
|
8
|
+
*
|
|
9
|
+
* ## Ownership diagram
|
|
10
|
+
*
|
|
11
|
+
* SemanticModel
|
|
12
|
+
* ├── types (TypeRegistry) ← classLikeHook / implHook write here
|
|
13
|
+
* ├── methods (MethodRegistry) ← methodHook writes here
|
|
14
|
+
* ├── fields (FieldRegistry) ← propertyHook writes here
|
|
15
|
+
* └── symbols (SymbolTable) ← owns fileIndex + callableByName,
|
|
16
|
+
* calls dispatch() in add()
|
|
17
|
+
*
|
|
18
|
+
* ## Behavior groups (5 hooks, 13 table entries)
|
|
19
|
+
*
|
|
20
|
+
* | Group | NodeLabel values | Hook | Skip callable? |
|
|
21
|
+
* |---------------|---------------------------------------------------|--------------|----------------|
|
|
22
|
+
* | class-like | Class, Struct, Interface, Enum, Record, Trait | classLikeHook | no |
|
|
23
|
+
* | method-like | Method, Constructor | methodHook | no |
|
|
24
|
+
* | property | Property | propertyHook | YES |
|
|
25
|
+
* | impl-block | Impl | implHook | no |
|
|
26
|
+
* | callable-only | Function, Macro, Delegate | (no entry) | no |
|
|
27
|
+
*
|
|
28
|
+
* Every other `NodeLabel` is "inert" — reached by `fileIndex` only. No
|
|
29
|
+
* specialized registry, no callable index append.
|
|
30
|
+
*
|
|
31
|
+
* ## How to add a new NodeLabel
|
|
32
|
+
*
|
|
33
|
+
* 1. Add the variant to the `NodeLabel` union in `gitnexus-shared/src/graph/types.ts`.
|
|
34
|
+
* 2. Decide which behavior group it belongs to by asking "which lookups must
|
|
35
|
+
* return this symbol?" (not "what language feature is it?"). A new Swift
|
|
36
|
+
* `Extension` is class-like if you want owner-scoped method lookup on it;
|
|
37
|
+
* a new Kotlin `Object` is class-like for the same reason.
|
|
38
|
+
* 3. Either:
|
|
39
|
+
* - Add a table entry here pointing at one of the existing hooks, OR
|
|
40
|
+
* - Add it to `CALLABLE_ONLY_LABELS` if it is a free callable, OR
|
|
41
|
+
* - Add it to `INERT_LABELS` if it's metadata-only (File, Folder, Decorator,
|
|
42
|
+
* etc.) — never queried via owner/class lookups.
|
|
43
|
+
* 4. If none of the above fit — the new kind needs a brand-new registry —
|
|
44
|
+
* design the registry first in `model/`, then add a new hook closure
|
|
45
|
+
* and table entries. Update `DISPATCH_LABELS` / the exhaustiveness guard
|
|
46
|
+
* accordingly.
|
|
47
|
+
*
|
|
48
|
+
* The runtime exhaustiveness guard in `symbol-table.ts` will warn if a
|
|
49
|
+
* `NodeLabel` is missing from all three sets.
|
|
50
|
+
*/
|
|
51
|
+
import type { NodeLabel } from '../../../_shared/index.js';
|
|
52
|
+
import type { SymbolDefinition } from './symbol-table.js';
|
|
53
|
+
import type { MutableTypeRegistry } from './type-registry.js';
|
|
54
|
+
import type { MutableMethodRegistry } from './method-registry.js';
|
|
55
|
+
import type { MutableFieldRegistry } from './field-registry.js';
|
|
56
|
+
/**
|
|
57
|
+
* Registration hook — a pure side-effectful function closed over a
|
|
58
|
+
* specific registry. Performs the specialized registry write into the
|
|
59
|
+
* appropriate owner-scoped registry for one NodeLabel.
|
|
60
|
+
*
|
|
61
|
+
* Closure capture is the isolation mechanism: `propertyHook` literally
|
|
62
|
+
* cannot call `types.registerClass` because its closure does not hold
|
|
63
|
+
* a reference to `types`. This is the runtime half of the principle of
|
|
64
|
+
* least authority — the compile-time half is enforced by TypeScript.
|
|
65
|
+
*
|
|
66
|
+
* The callable-index gate lives inside `SymbolTable.add()` via the
|
|
67
|
+
* `FREE_CALLABLE_TYPES` allowlist — the dispatch table does not
|
|
68
|
+
* participate in that decision.
|
|
69
|
+
*/
|
|
70
|
+
export type RegistrationHook = (name: string, def: SymbolDefinition) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Dependencies required to build the dispatch table. Matches the shape
|
|
73
|
+
* that `createSemanticModel()` passes into `createRegistrationTable()`.
|
|
74
|
+
*/
|
|
75
|
+
export interface RegistrationTableDeps {
|
|
76
|
+
readonly types: MutableTypeRegistry;
|
|
77
|
+
readonly methods: MutableMethodRegistry;
|
|
78
|
+
readonly fields: MutableFieldRegistry;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Behavior category for a NodeLabel during ingestion. Determines which
|
|
82
|
+
* registry (if any) receives the symbol write during `SymbolTable.add()`:
|
|
83
|
+
*
|
|
84
|
+
* - `dispatch` — owner-scoped registry write via the dispatch table
|
|
85
|
+
* (Class/Struct/Interface/Enum/Record/Trait → types.registerClass,
|
|
86
|
+
* Method/Constructor → methods.register,
|
|
87
|
+
* Property → fields.register,
|
|
88
|
+
* Impl → types.registerImpl)
|
|
89
|
+
* - `callable-only` — no specialized registry; symbol appears in
|
|
90
|
+
* `callableByName` via `SymbolTable.add()`'s
|
|
91
|
+
* FREE_CALLABLE_TYPES gate (Function/Macro/Delegate)
|
|
92
|
+
* - `inert` — no registry, no callable index; file-index only
|
|
93
|
+
* (metadata / structural nodes like Project, Module,
|
|
94
|
+
* Import, Decorator, etc.)
|
|
95
|
+
*
|
|
96
|
+
* `Function` has a twist: `Function`-with-`ownerId` (Python `def` in a
|
|
97
|
+
* class body, Rust trait method, Kotlin companion method) is pre-normalized
|
|
98
|
+
* to `Method` in `createSemanticModel`'s `wrappedAdd` before dispatch lookup,
|
|
99
|
+
* so only free functions actually flow through the callable-only path.
|
|
100
|
+
*/
|
|
101
|
+
export type LabelBehavior = 'dispatch' | 'callable-only' | 'inert';
|
|
102
|
+
/**
|
|
103
|
+
* All known NodeLabels, derived from the keys of `LABEL_BEHAVIOR`. The
|
|
104
|
+
* `satisfies Record<NodeLabel, LabelBehavior>` bijection above proves
|
|
105
|
+
* that `Object.keys(LABEL_BEHAVIOR)` is exactly the NodeLabel set —
|
|
106
|
+
* the cast to `NodeLabel[]` is sound, not a type-system bypass.
|
|
107
|
+
*
|
|
108
|
+
* Consumers (e.g., the semantic-model barrel re-export for tests) can
|
|
109
|
+
* rely on this list being complete by construction. No runtime drift
|
|
110
|
+
* check is needed or possible — the type system is the proof.
|
|
111
|
+
*/
|
|
112
|
+
export declare const ALL_NODE_LABELS: readonly NodeLabel[];
|
|
113
|
+
/**
|
|
114
|
+
* NodeLabel values that are free callables — appear in `callableByName`
|
|
115
|
+
* but have no owner-scoped specialized registry. Alias of
|
|
116
|
+
* {@link FREE_CALLABLE_TYPES} exported here for taxonomy-test use. The
|
|
117
|
+
* compile-time cross-invariant on `LABEL_BEHAVIOR` above guarantees the
|
|
118
|
+
* alias and the LABEL_BEHAVIOR `callable-only` classification cannot
|
|
119
|
+
* drift.
|
|
120
|
+
*/
|
|
121
|
+
export declare const CALLABLE_ONLY_LABELS: ReadonlySet<NodeLabel>;
|
|
122
|
+
/**
|
|
123
|
+
* NodeLabel values that touch only the file index — no specialized
|
|
124
|
+
* registry, no callable index.
|
|
125
|
+
*/
|
|
126
|
+
export declare const INERT_LABELS: ReadonlySet<NodeLabel>;
|
|
127
|
+
/**
|
|
128
|
+
* NodeLabel values that have a dispatch table entry. `createRegistrationTable`
|
|
129
|
+
* below must provide a hook for exactly this set — the test file's behavior-
|
|
130
|
+
* group tests and the integration tests pin the hook↔label correspondence.
|
|
131
|
+
*/
|
|
132
|
+
export declare const DISPATCH_LABELS: ReadonlySet<NodeLabel>;
|
|
133
|
+
/**
|
|
134
|
+
* Build the dispatch table. Must be called once per `createSymbolTable`
|
|
135
|
+
* invocation so each hook closes over that SymbolTable's injected
|
|
136
|
+
* registries. Reusing a single module-level instance would cause hooks
|
|
137
|
+
* to write into the wrong SemanticModel.
|
|
138
|
+
*/
|
|
139
|
+
export declare const createRegistrationTable: (deps: RegistrationTableDeps) => Map<NodeLabel, RegistrationHook>;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registration Dispatch Table
|
|
3
|
+
*
|
|
4
|
+
* Behavior-grouped O(1) dispatch table for routing `SymbolTable.add()`
|
|
5
|
+
* registrations into the semantic registries. Replaces the cascading
|
|
6
|
+
* `if/else` ladder in `symbol-table.ts` with a `Map<NodeLabel, RoutingDecision>`
|
|
7
|
+
* whose entries point to closure-captured hooks.
|
|
8
|
+
*
|
|
9
|
+
* ## Ownership diagram
|
|
10
|
+
*
|
|
11
|
+
* SemanticModel
|
|
12
|
+
* ├── types (TypeRegistry) ← classLikeHook / implHook write here
|
|
13
|
+
* ├── methods (MethodRegistry) ← methodHook writes here
|
|
14
|
+
* ├── fields (FieldRegistry) ← propertyHook writes here
|
|
15
|
+
* └── symbols (SymbolTable) ← owns fileIndex + callableByName,
|
|
16
|
+
* calls dispatch() in add()
|
|
17
|
+
*
|
|
18
|
+
* ## Behavior groups (5 hooks, 13 table entries)
|
|
19
|
+
*
|
|
20
|
+
* | Group | NodeLabel values | Hook | Skip callable? |
|
|
21
|
+
* |---------------|---------------------------------------------------|--------------|----------------|
|
|
22
|
+
* | class-like | Class, Struct, Interface, Enum, Record, Trait | classLikeHook | no |
|
|
23
|
+
* | method-like | Method, Constructor | methodHook | no |
|
|
24
|
+
* | property | Property | propertyHook | YES |
|
|
25
|
+
* | impl-block | Impl | implHook | no |
|
|
26
|
+
* | callable-only | Function, Macro, Delegate | (no entry) | no |
|
|
27
|
+
*
|
|
28
|
+
* Every other `NodeLabel` is "inert" — reached by `fileIndex` only. No
|
|
29
|
+
* specialized registry, no callable index append.
|
|
30
|
+
*
|
|
31
|
+
* ## How to add a new NodeLabel
|
|
32
|
+
*
|
|
33
|
+
* 1. Add the variant to the `NodeLabel` union in `gitnexus-shared/src/graph/types.ts`.
|
|
34
|
+
* 2. Decide which behavior group it belongs to by asking "which lookups must
|
|
35
|
+
* return this symbol?" (not "what language feature is it?"). A new Swift
|
|
36
|
+
* `Extension` is class-like if you want owner-scoped method lookup on it;
|
|
37
|
+
* a new Kotlin `Object` is class-like for the same reason.
|
|
38
|
+
* 3. Either:
|
|
39
|
+
* - Add a table entry here pointing at one of the existing hooks, OR
|
|
40
|
+
* - Add it to `CALLABLE_ONLY_LABELS` if it is a free callable, OR
|
|
41
|
+
* - Add it to `INERT_LABELS` if it's metadata-only (File, Folder, Decorator,
|
|
42
|
+
* etc.) — never queried via owner/class lookups.
|
|
43
|
+
* 4. If none of the above fit — the new kind needs a brand-new registry —
|
|
44
|
+
* design the registry first in `model/`, then add a new hook closure
|
|
45
|
+
* and table entries. Update `DISPATCH_LABELS` / the exhaustiveness guard
|
|
46
|
+
* accordingly.
|
|
47
|
+
*
|
|
48
|
+
* The runtime exhaustiveness guard in `symbol-table.ts` will warn if a
|
|
49
|
+
* `NodeLabel` is missing from all three sets.
|
|
50
|
+
*/
|
|
51
|
+
import { FREE_CALLABLE_TYPES } from './symbol-table.js';
|
|
52
|
+
/**
|
|
53
|
+
* **Single source of truth** for NodeLabel classification. Every NodeLabel
|
|
54
|
+
* has exactly one behavior category — enforced at compile time by the
|
|
55
|
+
* `as const satisfies Record<NodeLabel, LabelBehavior>` combo:
|
|
56
|
+
*
|
|
57
|
+
* - **Completeness** — `Record<NodeLabel, LabelBehavior>` requires every
|
|
58
|
+
* NodeLabel to be a key. Missing a label fails to compile with
|
|
59
|
+
* "Property 'X' is missing in type ..." naming the drifted label.
|
|
60
|
+
* - **No extras** — `satisfies` performs excess-property checking on
|
|
61
|
+
* object literals, so a non-NodeLabel string key fails to compile.
|
|
62
|
+
* - **No duplicates** — object keys are unique by construction. A label
|
|
63
|
+
* cannot be classified into two categories by accident.
|
|
64
|
+
* - **Valid values** — `LabelBehavior` is a narrow union, so a typo in
|
|
65
|
+
* the category name fails to compile.
|
|
66
|
+
*
|
|
67
|
+
* Adding a new NodeLabel to `gitnexus-shared`: TypeScript will flag this
|
|
68
|
+
* file as incomplete. Add the new label with its behavior category and
|
|
69
|
+
* the three `*_LABELS` Sets + `ALL_NODE_LABELS` array below are derived
|
|
70
|
+
* automatically — no separate list to update, no runtime drift detection
|
|
71
|
+
* needed.
|
|
72
|
+
*
|
|
73
|
+
* NOTE: `Type` and `CodeElement` are inert wrappers for language features
|
|
74
|
+
* that don't yet have a dedicated registry (typedefs, synthesized dynamic
|
|
75
|
+
* calls). If future work needs owner-scoped lookup for them, change their
|
|
76
|
+
* category to `'dispatch'` and add a hook in `createRegistrationTable`.
|
|
77
|
+
* Do not special-case them inside `SymbolTable.add()`.
|
|
78
|
+
*/
|
|
79
|
+
const LABEL_BEHAVIOR = {
|
|
80
|
+
// dispatch — owner-scoped registry writes
|
|
81
|
+
Class: 'dispatch',
|
|
82
|
+
Struct: 'dispatch',
|
|
83
|
+
Interface: 'dispatch',
|
|
84
|
+
Enum: 'dispatch',
|
|
85
|
+
Record: 'dispatch',
|
|
86
|
+
Trait: 'dispatch',
|
|
87
|
+
Method: 'dispatch',
|
|
88
|
+
Constructor: 'dispatch',
|
|
89
|
+
Property: 'dispatch',
|
|
90
|
+
Impl: 'dispatch',
|
|
91
|
+
// callable-only — file index + callableByName, no owner scope
|
|
92
|
+
Function: 'callable-only',
|
|
93
|
+
Macro: 'callable-only',
|
|
94
|
+
Delegate: 'callable-only',
|
|
95
|
+
// inert — file index only
|
|
96
|
+
Project: 'inert',
|
|
97
|
+
Package: 'inert',
|
|
98
|
+
Module: 'inert',
|
|
99
|
+
Folder: 'inert',
|
|
100
|
+
File: 'inert',
|
|
101
|
+
Variable: 'inert',
|
|
102
|
+
Decorator: 'inert',
|
|
103
|
+
Import: 'inert',
|
|
104
|
+
Type: 'inert',
|
|
105
|
+
CodeElement: 'inert',
|
|
106
|
+
Community: 'inert',
|
|
107
|
+
Process: 'inert',
|
|
108
|
+
Typedef: 'inert',
|
|
109
|
+
Union: 'inert',
|
|
110
|
+
Namespace: 'inert',
|
|
111
|
+
TypeAlias: 'inert',
|
|
112
|
+
Const: 'inert',
|
|
113
|
+
Static: 'inert',
|
|
114
|
+
Annotation: 'inert',
|
|
115
|
+
Template: 'inert',
|
|
116
|
+
Section: 'inert',
|
|
117
|
+
Route: 'inert',
|
|
118
|
+
Tool: 'inert',
|
|
119
|
+
};
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Derived runtime collections — all keyed off LABEL_BEHAVIOR
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
/**
|
|
124
|
+
* All known NodeLabels, derived from the keys of `LABEL_BEHAVIOR`. The
|
|
125
|
+
* `satisfies Record<NodeLabel, LabelBehavior>` bijection above proves
|
|
126
|
+
* that `Object.keys(LABEL_BEHAVIOR)` is exactly the NodeLabel set —
|
|
127
|
+
* the cast to `NodeLabel[]` is sound, not a type-system bypass.
|
|
128
|
+
*
|
|
129
|
+
* Consumers (e.g., the semantic-model barrel re-export for tests) can
|
|
130
|
+
* rely on this list being complete by construction. No runtime drift
|
|
131
|
+
* check is needed or possible — the type system is the proof.
|
|
132
|
+
*/
|
|
133
|
+
export const ALL_NODE_LABELS = Object.keys(LABEL_BEHAVIOR);
|
|
134
|
+
const labelsWithBehavior = (behavior) => ALL_NODE_LABELS.filter((label) => LABEL_BEHAVIOR[label] === behavior);
|
|
135
|
+
/**
|
|
136
|
+
* NodeLabel values that are free callables — appear in `callableByName`
|
|
137
|
+
* but have no owner-scoped specialized registry. Alias of
|
|
138
|
+
* {@link FREE_CALLABLE_TYPES} exported here for taxonomy-test use. The
|
|
139
|
+
* compile-time cross-invariant on `LABEL_BEHAVIOR` above guarantees the
|
|
140
|
+
* alias and the LABEL_BEHAVIOR `callable-only` classification cannot
|
|
141
|
+
* drift.
|
|
142
|
+
*/
|
|
143
|
+
export const CALLABLE_ONLY_LABELS = FREE_CALLABLE_TYPES;
|
|
144
|
+
/**
|
|
145
|
+
* NodeLabel values that touch only the file index — no specialized
|
|
146
|
+
* registry, no callable index.
|
|
147
|
+
*/
|
|
148
|
+
export const INERT_LABELS = new Set(labelsWithBehavior('inert'));
|
|
149
|
+
/**
|
|
150
|
+
* NodeLabel values that have a dispatch table entry. `createRegistrationTable`
|
|
151
|
+
* below must provide a hook for exactly this set — the test file's behavior-
|
|
152
|
+
* group tests and the integration tests pin the hook↔label correspondence.
|
|
153
|
+
*/
|
|
154
|
+
export const DISPATCH_LABELS = new Set(labelsWithBehavior('dispatch'));
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Factory
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
/**
|
|
159
|
+
* Build the dispatch table. Must be called once per `createSymbolTable`
|
|
160
|
+
* invocation so each hook closes over that SymbolTable's injected
|
|
161
|
+
* registries. Reusing a single module-level instance would cause hooks
|
|
162
|
+
* to write into the wrong SemanticModel.
|
|
163
|
+
*/
|
|
164
|
+
export const createRegistrationTable = (deps) => {
|
|
165
|
+
const { types, methods, fields } = deps;
|
|
166
|
+
// Hook 1: class-like — Class, Struct, Interface, Enum, Record, Trait.
|
|
167
|
+
// Shared reference — six table entries point at this one closure.
|
|
168
|
+
const classLikeHook = (name, def) => {
|
|
169
|
+
const qualifiedKey = def.qualifiedName ?? name;
|
|
170
|
+
types.registerClass(name, qualifiedKey, def);
|
|
171
|
+
};
|
|
172
|
+
// Hook 2: method-like — Method, Constructor. Silently skipped if the
|
|
173
|
+
// caller did not provide an ownerId (Property without ownerId is
|
|
174
|
+
// treated the same way).
|
|
175
|
+
const methodHook = (name, def) => {
|
|
176
|
+
if (def.ownerId) {
|
|
177
|
+
methods.register(def.ownerId, name, def);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
// Hook 3: property — Property. Silently skipped without ownerId.
|
|
181
|
+
// Property is not in `FREE_CALLABLE_TYPES`, so `SymbolTable.add()` already
|
|
182
|
+
// excludes it from `callableByName`; common property names like
|
|
183
|
+
// `id` / `name` / `type` never pollute the callable index.
|
|
184
|
+
const propertyHook = (name, def) => {
|
|
185
|
+
if (def.ownerId) {
|
|
186
|
+
fields.register(def.ownerId, name, def);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
// Hook 4: impl-block — Rust `impl` blocks. Kept separate from classLikeHook
|
|
190
|
+
// because heritage resolution must not treat Impls as class candidates
|
|
191
|
+
// (an Impl is not a parent type, it's an ancillary dispatch table).
|
|
192
|
+
const implHook = (name, def) => {
|
|
193
|
+
types.registerImpl(name, def);
|
|
194
|
+
};
|
|
195
|
+
// Single source of truth for the label → hook mapping. The
|
|
196
|
+
// `satisfies Record<DispatchLabel, RegistrationHook>` intersection
|
|
197
|
+
// fails at build time if (a) any label classified as 'dispatch' in
|
|
198
|
+
// `LABEL_BEHAVIOR` is missing here, or (b) any key here is not
|
|
199
|
+
// classified as 'dispatch'. This is the compile-time twin of the
|
|
200
|
+
// runtime taxonomy — no drift possible.
|
|
201
|
+
const dispatchByLabel = {
|
|
202
|
+
// class-like — six labels share the single `classLikeHook` closure,
|
|
203
|
+
// kept in lockstep with `CLASS_TYPES_TUPLE` via the
|
|
204
|
+
// `Record<ClassLikeLabel, 'dispatch'>` cross-invariant on
|
|
205
|
+
// `LABEL_BEHAVIOR`.
|
|
206
|
+
Class: classLikeHook,
|
|
207
|
+
Struct: classLikeHook,
|
|
208
|
+
Interface: classLikeHook,
|
|
209
|
+
Enum: classLikeHook,
|
|
210
|
+
Record: classLikeHook,
|
|
211
|
+
Trait: classLikeHook,
|
|
212
|
+
// method-like — routed via dispatch-key normalization in
|
|
213
|
+
// `wrappedAdd` so Function+ownerId also reaches `methodHook`.
|
|
214
|
+
Method: methodHook,
|
|
215
|
+
Constructor: methodHook,
|
|
216
|
+
// property — callable-index exclusion is enforced by
|
|
217
|
+
// `SymbolTable.add()` (Property is not in `FREE_CALLABLE_TYPES`).
|
|
218
|
+
Property: propertyHook,
|
|
219
|
+
// impl-block — Rust `impl` blocks. Separate from classLikeHook because
|
|
220
|
+
// heritage resolution must not treat Impls as class candidates.
|
|
221
|
+
Impl: implHook,
|
|
222
|
+
};
|
|
223
|
+
return new Map(Object.entries(dispatchByLabel));
|
|
224
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution Context
|
|
3
|
+
*
|
|
4
|
+
* Single implementation of tiered name resolution.
|
|
5
|
+
*
|
|
6
|
+
* Resolution tiers (highest confidence first):
|
|
7
|
+
* 1. Same file (lookupExactAll — authoritative)
|
|
8
|
+
* 2a-named. Named binding chain (walkBindingChain via NamedImportMap)
|
|
9
|
+
* 2a. Import-scoped (iterate importedFiles with lookupExactAll per file)
|
|
10
|
+
* 2b. Package-scoped (iterate indexed files matching package dir with lookupExactAll)
|
|
11
|
+
* 3. Global (lookupClassByName + lookupImplByName + lookupCallableByName — consumers must check count)
|
|
12
|
+
*
|
|
13
|
+
* Each tier queries the minimum necessary scope directly:
|
|
14
|
+
* - Tier 2a iterates the caller's import set (O(imports) × O(1) lookupExactAll).
|
|
15
|
+
* - Tier 2b iterates all indexed files filtered by package dir
|
|
16
|
+
* (O(files) × O(1) lookupExactAll — avoids a global name scan).
|
|
17
|
+
* - Tier 3 combines lookupClassByName + lookupImplByName + lookupCallableByName
|
|
18
|
+
* (three O(1) index lookups with a narrow, type-specific result set).
|
|
19
|
+
*/
|
|
20
|
+
import type { SymbolDefinition } from './symbol-table.js';
|
|
21
|
+
import type { MutableSemanticModel } from './semantic-model.js';
|
|
22
|
+
/**
|
|
23
|
+
* A single named binding in a source file (e.g. `import { User as U }`).
|
|
24
|
+
* Stores both the resolved source path and the original exported name so
|
|
25
|
+
* that aliased imports can resolve U → User in the source file.
|
|
26
|
+
*/
|
|
27
|
+
export interface NamedImportBinding {
|
|
28
|
+
sourcePath: string;
|
|
29
|
+
exportedName: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Map<ImportingFilePath, Map<LocalName, NamedImportBinding>>.
|
|
33
|
+
*
|
|
34
|
+
* Tracks which specific names a file imports from which sources (TS / Python
|
|
35
|
+
* / Rust / Java-static / ...). Used to tighten Tier 2a resolution:
|
|
36
|
+
* `import { User } from './models'` means only `User` (not `Repo`) is
|
|
37
|
+
* visible from models.ts via this import.
|
|
38
|
+
*/
|
|
39
|
+
export type NamedImportMap = Map<string, Map<string, NamedImportBinding>>;
|
|
40
|
+
/**
|
|
41
|
+
* Check if a file path is directly inside a package directory identified by
|
|
42
|
+
* its suffix. Used by Tier 2b package-scoped resolution (Go / C#).
|
|
43
|
+
*/
|
|
44
|
+
export declare function isFileInPackageDir(filePath: string, dirSuffix: string): boolean;
|
|
45
|
+
/** Resolution tier for tracking, logging, and test assertions. */
|
|
46
|
+
export type ResolutionTier = 'same-file' | 'import-scoped' | 'global';
|
|
47
|
+
/** Tier-selected candidates with metadata. */
|
|
48
|
+
export interface TieredCandidates {
|
|
49
|
+
readonly candidates: readonly SymbolDefinition[];
|
|
50
|
+
readonly tier: ResolutionTier;
|
|
51
|
+
}
|
|
52
|
+
/** Confidence scores per resolution tier. */
|
|
53
|
+
export declare const TIER_CONFIDENCE: Record<ResolutionTier, number>;
|
|
54
|
+
export type ImportMap = Map<string, Set<string>>;
|
|
55
|
+
export type PackageMap = Map<string, Set<string>>;
|
|
56
|
+
/** Maps callerFile → (moduleAlias → sourceFilePath) for Python namespace imports.
|
|
57
|
+
* e.g. `import models` in app.py → moduleAliasMap.get('app.py')?.get('models') === 'models.py' */
|
|
58
|
+
export type ModuleAliasMap = Map<string, Map<string, string>>;
|
|
59
|
+
export interface ResolutionContext {
|
|
60
|
+
/**
|
|
61
|
+
* The only resolution API. Returns all candidates at the winning tier.
|
|
62
|
+
*
|
|
63
|
+
* Tier 3 ('global') returns ALL candidates regardless of count —
|
|
64
|
+
* consumers must check candidates.length and refuse ambiguous matches.
|
|
65
|
+
*/
|
|
66
|
+
resolve(name: string, fromFile: string): TieredCandidates | null;
|
|
67
|
+
/** Semantic model — the top-level container for types, methods, fields,
|
|
68
|
+
* and the nested file/callable SymbolTable. Typed as
|
|
69
|
+
* {@link MutableSemanticModel} because `ResolutionContext` is the
|
|
70
|
+
* lifecycle owner — the pipeline registers symbols through it during
|
|
71
|
+
* the fan-out phase. Resolvers that only query should annotate their
|
|
72
|
+
* own fields as {@link SemanticModel} to drop write access. */
|
|
73
|
+
readonly model: MutableSemanticModel;
|
|
74
|
+
/** Raw maps — used by import-processor to populate import data. */
|
|
75
|
+
readonly importMap: ImportMap;
|
|
76
|
+
readonly packageMap: PackageMap;
|
|
77
|
+
readonly namedImportMap: NamedImportMap;
|
|
78
|
+
/** Module-alias map for Python namespace imports: callerFile → (alias → sourceFile). */
|
|
79
|
+
readonly moduleAliasMap: ModuleAliasMap;
|
|
80
|
+
enableCache(filePath: string): void;
|
|
81
|
+
clearCache(): void;
|
|
82
|
+
getStats(): {
|
|
83
|
+
fileCount: number;
|
|
84
|
+
cacheHits: number;
|
|
85
|
+
cacheMisses: number;
|
|
86
|
+
tierSameFile: number;
|
|
87
|
+
tierImportScoped: number;
|
|
88
|
+
tierGlobal: number;
|
|
89
|
+
tierMiss: number;
|
|
90
|
+
};
|
|
91
|
+
clear(): void;
|
|
92
|
+
}
|
|
93
|
+
export declare const createResolutionContext: () => ResolutionContext;
|