gitnexus 1.5.3 → 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/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-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 +52 -3
- 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.js +85 -8
- 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 +5 -5
- package/dist/core/ingestion/tree-sitter-queries.js +21 -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 -572
- 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/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
|
@@ -2,11 +2,13 @@ import Parser from 'tree-sitter';
|
|
|
2
2
|
import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
|
|
3
3
|
import { getProvider } from './languages/index.js';
|
|
4
4
|
import { generateId } from '../../lib/utils.js';
|
|
5
|
-
import { getLanguageFromFilename } from '../../_shared/index.js';
|
|
5
|
+
import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index.js';
|
|
6
|
+
import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
|
|
6
7
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
7
|
-
import { getDefinitionNodeFromCaptures,
|
|
8
|
+
import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
|
|
8
9
|
import { detectFrameworkFromAST } from './framework-detection.js';
|
|
9
10
|
import { buildTypeEnv } from './type-env.js';
|
|
11
|
+
import { buildMethodProps, arityForIdFromInfo, typeTagForId, constTagForId, buildCollisionGroups, } from './utils/method-props.js';
|
|
10
12
|
import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
|
|
11
13
|
// ============================================================================
|
|
12
14
|
// Worker-based parallel parsing
|
|
@@ -31,7 +33,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
31
33
|
toolDefs: [],
|
|
32
34
|
ormQueries: [],
|
|
33
35
|
constructorBindings: [],
|
|
34
|
-
|
|
36
|
+
fileScopeBindings: [],
|
|
35
37
|
};
|
|
36
38
|
const total = files.length;
|
|
37
39
|
// Dispatch to worker pool — pool handles splitting into chunks and sub-batching
|
|
@@ -49,7 +51,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
49
51
|
const allToolDefs = [];
|
|
50
52
|
const allORMQueries = [];
|
|
51
53
|
const allConstructorBindings = [];
|
|
52
|
-
const
|
|
54
|
+
const fileScopeBindingsByFile = [];
|
|
53
55
|
for (const result of chunkResults) {
|
|
54
56
|
for (const node of result.nodes) {
|
|
55
57
|
graph.addNode({
|
|
@@ -69,20 +71,33 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
69
71
|
returnType: sym.returnType,
|
|
70
72
|
declaredType: sym.declaredType,
|
|
71
73
|
ownerId: sym.ownerId,
|
|
74
|
+
qualifiedName: sym.qualifiedName,
|
|
72
75
|
});
|
|
73
76
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
for (const _item of result.imports)
|
|
78
|
+
allImports.push(_item);
|
|
79
|
+
for (const _item of result.calls)
|
|
80
|
+
allCalls.push(_item);
|
|
81
|
+
for (const _item of result.assignments)
|
|
82
|
+
allAssignments.push(_item);
|
|
83
|
+
for (const _item of result.heritage)
|
|
84
|
+
allHeritage.push(_item);
|
|
85
|
+
for (const _item of result.routes)
|
|
86
|
+
allRoutes.push(_item);
|
|
87
|
+
for (const _item of result.fetchCalls)
|
|
88
|
+
allFetchCalls.push(_item);
|
|
89
|
+
for (const _item of result.decoratorRoutes)
|
|
90
|
+
allDecoratorRoutes.push(_item);
|
|
91
|
+
for (const _item of result.toolDefs)
|
|
92
|
+
allToolDefs.push(_item);
|
|
82
93
|
if (result.ormQueries)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
for (const _item of result.ormQueries)
|
|
95
|
+
allORMQueries.push(_item);
|
|
96
|
+
for (const _item of result.constructorBindings)
|
|
97
|
+
allConstructorBindings.push(_item);
|
|
98
|
+
if (result.fileScopeBindings)
|
|
99
|
+
for (const _item of result.fileScopeBindings)
|
|
100
|
+
fileScopeBindingsByFile.push(_item);
|
|
86
101
|
}
|
|
87
102
|
// Merge and log skipped languages from workers
|
|
88
103
|
const skippedLanguages = new Map();
|
|
@@ -110,7 +125,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
110
125
|
toolDefs: allToolDefs,
|
|
111
126
|
ormQueries: allORMQueries,
|
|
112
127
|
constructorBindings: allConstructorBindings,
|
|
113
|
-
|
|
128
|
+
fileScopeBindings: fileScopeBindingsByFile,
|
|
114
129
|
};
|
|
115
130
|
};
|
|
116
131
|
// ============================================================================
|
|
@@ -118,14 +133,14 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
118
133
|
// ============================================================================
|
|
119
134
|
// Inline caches to avoid repeated parent-walks per node (same pattern as parse-worker.ts).
|
|
120
135
|
// Keyed by tree-sitter node reference — cleared at the start of each file.
|
|
121
|
-
const
|
|
136
|
+
const classInfoCache = new Map();
|
|
122
137
|
const exportCache = new Map();
|
|
123
|
-
const
|
|
124
|
-
const cached =
|
|
138
|
+
const cachedFindEnclosingClassInfo = (node, filePath) => {
|
|
139
|
+
const cached = classInfoCache.get(node);
|
|
125
140
|
if (cached !== undefined)
|
|
126
141
|
return cached;
|
|
127
|
-
const result =
|
|
128
|
-
|
|
142
|
+
const result = findEnclosingClassInfo(node, filePath);
|
|
143
|
+
classInfoCache.set(node, result);
|
|
129
144
|
return result;
|
|
130
145
|
};
|
|
131
146
|
const cachedExportCheck = (checker, node, name) => {
|
|
@@ -138,21 +153,36 @@ const cachedExportCheck = (checker, node, name) => {
|
|
|
138
153
|
};
|
|
139
154
|
// FieldExtractor cache for sequential path — same pattern as parse-worker.ts
|
|
140
155
|
const seqFieldInfoCache = new Map();
|
|
156
|
+
// MethodExtractor cache for sequential path — avoids re-traversing the same class
|
|
157
|
+
// body once per method. Keyed on classNode.id (tree-sitter node identity number).
|
|
158
|
+
const seqMethodExtractCache = new Map();
|
|
159
|
+
// Derived method map + collision groups cache — avoids rebuilding per method.
|
|
160
|
+
const seqMethodMapCache = new Map();
|
|
141
161
|
function seqFindEnclosingClassNode(node) {
|
|
142
162
|
let current = node.parent;
|
|
143
163
|
while (current) {
|
|
144
|
-
if (CLASS_CONTAINER_TYPES.has(current.type))
|
|
164
|
+
if (CLASS_CONTAINER_TYPES.has(current.type)) {
|
|
165
|
+
// Return singleton_class directly so the method extractor sees it as
|
|
166
|
+
// the owner node and correctly marks methods as static. Name resolution
|
|
167
|
+
// for qualified names is handled separately by findEnclosingClassInfo.
|
|
145
168
|
return current;
|
|
169
|
+
}
|
|
146
170
|
current = current.parent;
|
|
147
171
|
}
|
|
148
172
|
return null;
|
|
149
173
|
}
|
|
150
|
-
/** Minimal no-op SymbolTable stub for FieldExtractorContext (sequential
|
|
151
|
-
* SymbolTable, but it's incomplete at this stage — use
|
|
174
|
+
/** Minimal no-op SymbolTable stub for FieldExtractorContext (sequential
|
|
175
|
+
* path has a real SymbolTable, but it's incomplete at this stage — use
|
|
176
|
+
* the stub for safety). Implements the full {@link SymbolTableReader}
|
|
177
|
+
* surface so future extractor additions don't silently fall off an
|
|
178
|
+
* `as unknown as` cast. */
|
|
152
179
|
const NOOP_SYMBOL_TABLE_SEQ = {
|
|
153
|
-
lookupExactAll: () => [],
|
|
154
180
|
lookupExact: () => undefined,
|
|
155
181
|
lookupExactFull: () => undefined,
|
|
182
|
+
lookupExactAll: () => [],
|
|
183
|
+
lookupCallableByName: () => [],
|
|
184
|
+
getFiles: () => [][Symbol.iterator](),
|
|
185
|
+
getStats: () => ({ fileCount: 0 }),
|
|
156
186
|
};
|
|
157
187
|
function seqGetFieldInfo(classNode, provider, context) {
|
|
158
188
|
if (!provider.fieldExtractor)
|
|
@@ -177,9 +207,11 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
177
207
|
for (let i = 0; i < files.length; i++) {
|
|
178
208
|
const file = files[i];
|
|
179
209
|
// Reset memoization before each new file (node refs are per-tree)
|
|
180
|
-
|
|
210
|
+
classInfoCache.clear();
|
|
181
211
|
exportCache.clear();
|
|
182
212
|
seqFieldInfoCache.clear();
|
|
213
|
+
seqMethodExtractCache.clear();
|
|
214
|
+
seqMethodMapCache.clear();
|
|
183
215
|
onFileProgress?.(i + 1, total, file.path);
|
|
184
216
|
if (i % 20 === 0)
|
|
185
217
|
await yieldToEventLoop();
|
|
@@ -194,6 +226,18 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
194
226
|
// Skip files larger than the max tree-sitter buffer (32 MB)
|
|
195
227
|
if (file.content.length > TREE_SITTER_MAX_BUFFER)
|
|
196
228
|
continue;
|
|
229
|
+
// Vue SFC preprocessing: extract <script> block content
|
|
230
|
+
let parseContent = file.content;
|
|
231
|
+
let lineOffset = 0;
|
|
232
|
+
let isVueSetup = false;
|
|
233
|
+
if (language === SupportedLanguages.Vue) {
|
|
234
|
+
const extracted = extractVueScript(file.content);
|
|
235
|
+
if (!extracted)
|
|
236
|
+
continue; // skip .vue files with no script block
|
|
237
|
+
parseContent = extracted.scriptContent;
|
|
238
|
+
lineOffset = extracted.lineOffset;
|
|
239
|
+
isVueSetup = extracted.isSetup;
|
|
240
|
+
}
|
|
197
241
|
try {
|
|
198
242
|
await loadLanguage(language, file.path);
|
|
199
243
|
}
|
|
@@ -202,8 +246,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
202
246
|
}
|
|
203
247
|
let tree;
|
|
204
248
|
try {
|
|
205
|
-
tree = parser.parse(
|
|
206
|
-
bufferSize: getTreeSitterBufferSize(
|
|
249
|
+
tree = parser.parse(parseContent, undefined, {
|
|
250
|
+
bufferSize: getTreeSitterBufferSize(parseContent.length),
|
|
207
251
|
});
|
|
208
252
|
}
|
|
209
253
|
catch (parseError) {
|
|
@@ -227,90 +271,170 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
227
271
|
console.warn(`Query error for ${file.path}:`, queryError);
|
|
228
272
|
continue;
|
|
229
273
|
}
|
|
230
|
-
// Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor)
|
|
274
|
+
// Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor).
|
|
275
|
+
//
|
|
276
|
+
// Note: this TypeEnv is intentionally NOT flushed into the BindingAccumulator.
|
|
277
|
+
// The accumulator feed happens later in `call-processor.ts` via its own
|
|
278
|
+
// `typeEnv.flush(accumulator)` call. Flushing here would double-count
|
|
279
|
+
// file-scope bindings and break the single-use invariant of `flush()`.
|
|
280
|
+
// See the BindingAccumulator class JSDoc for the full accumulator
|
|
281
|
+
// lifecycle and flush-site ownership rules.
|
|
231
282
|
const typeEnv = provider.fieldExtractor
|
|
232
|
-
? buildTypeEnv(tree, language, {
|
|
283
|
+
? buildTypeEnv(tree, language, {
|
|
284
|
+
enclosingFunctionFinder: provider.enclosingFunctionFinder,
|
|
285
|
+
extractFunctionName: provider.methodExtractor?.extractFunctionName,
|
|
286
|
+
})
|
|
233
287
|
: null;
|
|
234
288
|
matches.forEach((match) => {
|
|
235
289
|
const captureMap = {};
|
|
236
290
|
match.captures.forEach((c) => {
|
|
237
291
|
captureMap[c.name] = c.node;
|
|
238
292
|
});
|
|
239
|
-
const
|
|
240
|
-
|
|
293
|
+
const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
|
|
294
|
+
const definitionNode = getDefinitionNodeFromCaptures(captureMap);
|
|
295
|
+
const defaultNodeLabel = getLabelFromCaptures(captureMap, provider);
|
|
296
|
+
if (!defaultNodeLabel)
|
|
241
297
|
return;
|
|
242
298
|
const nameNode = captureMap['name'];
|
|
299
|
+
const extractedClassSymbol = definitionNode && provider.classExtractor?.isTypeDeclaration(definitionNode)
|
|
300
|
+
? provider.classExtractor.extract(definitionNode, {
|
|
301
|
+
name: nameNode?.text,
|
|
302
|
+
type: defaultNodeLabel,
|
|
303
|
+
})
|
|
304
|
+
: null;
|
|
305
|
+
const nodeLabel = extractedClassSymbol?.type ?? defaultNodeLabel;
|
|
243
306
|
// Synthesize name for constructors without explicit @name capture (e.g. Swift init)
|
|
244
|
-
if (!nameNode && nodeLabel !== 'Constructor')
|
|
307
|
+
if (!nameNode && nodeLabel !== 'Constructor' && !extractedClassSymbol)
|
|
245
308
|
return;
|
|
246
|
-
const nodeName = nameNode ? nameNode.text : 'init';
|
|
247
|
-
const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
|
|
309
|
+
const nodeName = extractedClassSymbol?.name ?? (nameNode ? nameNode.text : 'init');
|
|
248
310
|
const startLine = definitionNodeForRange
|
|
249
|
-
? definitionNodeForRange.startPosition.row
|
|
311
|
+
? definitionNodeForRange.startPosition.row + lineOffset
|
|
250
312
|
: nameNode
|
|
251
|
-
? nameNode.startPosition.row
|
|
252
|
-
:
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
313
|
+
? nameNode.startPosition.row + lineOffset
|
|
314
|
+
: lineOffset;
|
|
315
|
+
// Compute enclosing class BEFORE node ID — needed to qualify method IDs
|
|
316
|
+
const needsOwner = nodeLabel === 'Method' ||
|
|
317
|
+
nodeLabel === 'Constructor' ||
|
|
318
|
+
nodeLabel === 'Property' ||
|
|
319
|
+
nodeLabel === 'Function';
|
|
320
|
+
const enclosingClassInfo = needsOwner
|
|
321
|
+
? cachedFindEnclosingClassInfo(nameNode || definitionNodeForRange, file.path)
|
|
257
322
|
: null;
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
323
|
+
const enclosingClassId = enclosingClassInfo?.classId ?? null;
|
|
324
|
+
// Qualify method/property IDs with enclosing class name to avoid collisions
|
|
325
|
+
// e.g. "Method:animal.dart:Animal.speak" vs "Method:animal.dart:Dog.speak"
|
|
326
|
+
const qualifiedName = enclosingClassInfo
|
|
327
|
+
? `${enclosingClassInfo.className}.${nodeName}`
|
|
328
|
+
: nodeName;
|
|
329
|
+
// Extract method metadata for Function/Method/Constructor nodes BEFORE generating
|
|
330
|
+
// the node ID — parameterCount is needed to disambiguate overloaded methods.
|
|
331
|
+
// Use the per-language MethodExtractor for method metadata (isAbstract, isStatic,
|
|
332
|
+
// visibility, annotations, parameterCount, parameterTypes, returnType, etc.).
|
|
333
|
+
const isMethodLike = nodeLabel === 'Function' || nodeLabel === 'Method' || nodeLabel === 'Constructor';
|
|
334
|
+
let methodProps = {};
|
|
335
|
+
let arityForId; // raw param count for ID, even for variadic
|
|
336
|
+
let seqDefMethodInfo;
|
|
337
|
+
let seqDefMethods;
|
|
338
|
+
let seqClassNodeId;
|
|
339
|
+
if (isMethodLike && definitionNode) {
|
|
340
|
+
let enriched = false;
|
|
341
|
+
if (provider.methodExtractor) {
|
|
342
|
+
// Try class-based extraction (method inside a class/struct/trait body)
|
|
343
|
+
const classNode = seqFindEnclosingClassNode(definitionNode);
|
|
344
|
+
if (classNode) {
|
|
345
|
+
// Cache extract() results per class node to avoid re-traversing the
|
|
346
|
+
// same class body for every method it contains (O(N) -> O(1) per hit).
|
|
347
|
+
let result = seqMethodExtractCache.get(classNode.id);
|
|
348
|
+
if (result === undefined) {
|
|
349
|
+
result =
|
|
350
|
+
provider.methodExtractor.extract(classNode, {
|
|
351
|
+
filePath: file.path,
|
|
352
|
+
language,
|
|
353
|
+
}) ?? null;
|
|
354
|
+
seqMethodExtractCache.set(classNode.id, result);
|
|
355
|
+
}
|
|
356
|
+
if (result?.methods?.length) {
|
|
357
|
+
const defLine = definitionNode.startPosition.row + 1;
|
|
358
|
+
const info = result.methods.find((m) => m.name === nodeName && m.line === defLine);
|
|
359
|
+
if (info) {
|
|
360
|
+
enriched = true;
|
|
361
|
+
arityForId = arityForIdFromInfo(info);
|
|
362
|
+
methodProps = buildMethodProps(info);
|
|
363
|
+
seqDefMethodInfo = info;
|
|
364
|
+
seqDefMethods = result.methods;
|
|
365
|
+
seqClassNodeId = classNode.id;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// For top-level methods (e.g. Go method_declaration), try extractFromNode
|
|
370
|
+
if (!enriched && provider.methodExtractor.extractFromNode) {
|
|
371
|
+
const info = provider.methodExtractor.extractFromNode(definitionNode, {
|
|
372
|
+
filePath: file.path,
|
|
373
|
+
language,
|
|
374
|
+
});
|
|
375
|
+
if (info) {
|
|
376
|
+
enriched = true;
|
|
377
|
+
arityForId = arityForIdFromInfo(info);
|
|
378
|
+
methodProps = buildMethodProps(info);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// Append #<paramCount> to Method/Constructor IDs to disambiguate overloads.
|
|
384
|
+
// Functions are not suffixed — they don't overload by name in the same scope.
|
|
385
|
+
// When same-arity collisions exist, append ~type1,type2 for further disambiguation.
|
|
386
|
+
const needsAritySuffix = nodeLabel === 'Method' || nodeLabel === 'Constructor';
|
|
387
|
+
let arityTag = needsAritySuffix && arityForId !== undefined ? `#${arityForId}` : '';
|
|
388
|
+
if (arityTag && seqDefMethods && seqDefMethodInfo && seqClassNodeId !== undefined) {
|
|
389
|
+
// Use cached method map + collision groups (built once per class, not per method)
|
|
390
|
+
let cached = seqMethodMapCache.get(seqClassNodeId);
|
|
391
|
+
if (!cached) {
|
|
392
|
+
const tempMap = new Map();
|
|
393
|
+
for (const m of seqDefMethods)
|
|
394
|
+
tempMap.set(`${m.name}:${m.line}`, m);
|
|
395
|
+
cached = { map: tempMap, groups: buildCollisionGroups(tempMap) };
|
|
396
|
+
seqMethodMapCache.set(seqClassNodeId, cached);
|
|
274
397
|
}
|
|
398
|
+
arityTag += typeTagForId(cached.map, nodeName, arityForId, seqDefMethodInfo, language, cached.groups);
|
|
399
|
+
arityTag += constTagForId(cached.map, nodeName, arityForId, seqDefMethodInfo, cached.groups);
|
|
275
400
|
}
|
|
401
|
+
const nodeId = generateId(nodeLabel, `${file.path}:${qualifiedName}${arityTag}`);
|
|
402
|
+
const classNodeForSymbol = definitionNodeForRange || definitionNode || nameNode;
|
|
403
|
+
const qualifiedTypeName = extractedClassSymbol?.qualifiedName ??
|
|
404
|
+
(classNodeForSymbol && provider.classExtractor?.isTypeDeclaration(classNodeForSymbol)
|
|
405
|
+
? (provider.classExtractor.extractQualifiedName(classNodeForSymbol, nodeName) ?? nodeName)
|
|
406
|
+
: undefined);
|
|
407
|
+
const frameworkHint = definitionNode
|
|
408
|
+
? detectFrameworkFromAST(language, (definitionNode.text || '').slice(0, 300))
|
|
409
|
+
: null;
|
|
276
410
|
const node = {
|
|
277
411
|
id: nodeId,
|
|
278
412
|
label: nodeLabel,
|
|
279
413
|
properties: {
|
|
280
414
|
name: nodeName,
|
|
281
415
|
filePath: file.path,
|
|
282
|
-
startLine: definitionNodeForRange
|
|
283
|
-
|
|
416
|
+
startLine: definitionNodeForRange
|
|
417
|
+
? definitionNodeForRange.startPosition.row + lineOffset
|
|
418
|
+
: startLine,
|
|
419
|
+
endLine: definitionNodeForRange
|
|
420
|
+
? definitionNodeForRange.endPosition.row + lineOffset
|
|
421
|
+
: startLine,
|
|
284
422
|
language: language,
|
|
285
|
-
isExported:
|
|
423
|
+
isExported: language === SupportedLanguages.Vue && isVueSetup
|
|
424
|
+
? isVueSetupTopLevel(nameNode || definitionNodeForRange)
|
|
425
|
+
: cachedExportCheck(provider.exportChecker, nameNode || definitionNodeForRange, nodeName),
|
|
426
|
+
...(qualifiedTypeName !== undefined ? { qualifiedName: qualifiedTypeName } : {}),
|
|
286
427
|
...(frameworkHint
|
|
287
428
|
? {
|
|
288
429
|
astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
|
|
289
430
|
astFrameworkReason: frameworkHint.reason,
|
|
290
431
|
}
|
|
291
432
|
: {}),
|
|
292
|
-
...
|
|
293
|
-
? {
|
|
294
|
-
parameterCount: methodSig.parameterCount,
|
|
295
|
-
...(methodSig.requiredParameterCount !== undefined
|
|
296
|
-
? { requiredParameterCount: methodSig.requiredParameterCount }
|
|
297
|
-
: {}),
|
|
298
|
-
...(methodSig.parameterTypes ? { parameterTypes: methodSig.parameterTypes } : {}),
|
|
299
|
-
returnType: methodSig.returnType,
|
|
300
|
-
}
|
|
301
|
-
: {}),
|
|
433
|
+
...methodProps,
|
|
302
434
|
},
|
|
303
435
|
};
|
|
304
436
|
graph.addNode(node);
|
|
305
|
-
//
|
|
306
|
-
// Function is included because Kotlin/Rust/Python capture class methods as Function nodes
|
|
307
|
-
const needsOwner = nodeLabel === 'Method' ||
|
|
308
|
-
nodeLabel === 'Constructor' ||
|
|
309
|
-
nodeLabel === 'Property' ||
|
|
310
|
-
nodeLabel === 'Function';
|
|
311
|
-
const enclosingClassId = needsOwner
|
|
312
|
-
? cachedFindEnclosingClassId(nameNode || definitionNodeForRange, file.path)
|
|
313
|
-
: null;
|
|
437
|
+
// enclosingClassId already computed above (before nodeId generation)
|
|
314
438
|
// Extract declared type and field metadata for Property nodes
|
|
315
439
|
let declaredType;
|
|
316
440
|
let seqVisibility;
|
|
@@ -336,7 +460,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
336
460
|
}
|
|
337
461
|
}
|
|
338
462
|
}
|
|
339
|
-
// All
|
|
463
|
+
// All 15 tree-sitter languages register a FieldExtractor — no fallback needed.
|
|
340
464
|
}
|
|
341
465
|
// Apply field metadata to the graph node retroactively
|
|
342
466
|
if (seqVisibility !== undefined)
|
|
@@ -348,12 +472,13 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
348
472
|
if (declaredType !== undefined)
|
|
349
473
|
node.properties.declaredType = declaredType;
|
|
350
474
|
symbolTable.add(file.path, nodeName, nodeId, nodeLabel, {
|
|
351
|
-
parameterCount:
|
|
352
|
-
requiredParameterCount:
|
|
353
|
-
parameterTypes:
|
|
354
|
-
returnType:
|
|
475
|
+
parameterCount: methodProps.parameterCount,
|
|
476
|
+
requiredParameterCount: methodProps.requiredParameterCount,
|
|
477
|
+
parameterTypes: methodProps.parameterTypes,
|
|
478
|
+
returnType: methodProps.returnType,
|
|
355
479
|
declaredType,
|
|
356
480
|
ownerId: enclosingClassId ?? undefined,
|
|
481
|
+
qualifiedName: qualifiedTypeName,
|
|
357
482
|
});
|
|
358
483
|
const fileId = generateId('File', file.path);
|
|
359
484
|
const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
|
|
@@ -12,6 +12,8 @@ export declare function topologicalLevelSort(importMap: ReadonlyMap<string, Read
|
|
|
12
12
|
export interface PipelineOptions {
|
|
13
13
|
/** Skip MRO, community detection, and process extraction for faster test runs. */
|
|
14
14
|
skipGraphPhases?: boolean;
|
|
15
|
+
/** Force sequential parsing (no worker pool). Useful for testing the sequential path. */
|
|
16
|
+
skipWorkers?: boolean;
|
|
15
17
|
}
|
|
16
18
|
export declare const runPipelineFromRepo: (repoPath: string, onProgress: (progress: PipelineProgress) => void, options?: PipelineOptions) => Promise<PipelineResult>;
|
|
17
19
|
export {};
|