gitnexus 1.4.7 → 1.4.8

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.
Files changed (92) hide show
  1. package/README.md +22 -1
  2. package/dist/cli/ai-context.d.ts +1 -1
  3. package/dist/cli/ai-context.js +1 -1
  4. package/dist/cli/analyze.d.ts +2 -0
  5. package/dist/cli/analyze.js +54 -21
  6. package/dist/cli/index.js +2 -1
  7. package/dist/cli/setup.js +78 -1
  8. package/dist/config/supported-languages.d.ts +30 -0
  9. package/dist/config/supported-languages.js +30 -0
  10. package/dist/core/embeddings/embedder.d.ts +6 -1
  11. package/dist/core/embeddings/embedder.js +65 -5
  12. package/dist/core/embeddings/embedding-pipeline.js +11 -9
  13. package/dist/core/embeddings/http-client.d.ts +31 -0
  14. package/dist/core/embeddings/http-client.js +179 -0
  15. package/dist/core/embeddings/index.d.ts +1 -0
  16. package/dist/core/embeddings/index.js +1 -0
  17. package/dist/core/embeddings/types.d.ts +1 -1
  18. package/dist/core/graph/types.d.ts +2 -1
  19. package/dist/core/ingestion/ast-helpers.d.ts +80 -0
  20. package/dist/core/ingestion/ast-helpers.js +738 -0
  21. package/dist/core/ingestion/call-analysis.d.ts +73 -0
  22. package/dist/core/ingestion/call-analysis.js +490 -0
  23. package/dist/core/ingestion/call-processor.d.ts +48 -1
  24. package/dist/core/ingestion/call-processor.js +368 -7
  25. package/dist/core/ingestion/call-routing.d.ts +6 -0
  26. package/dist/core/ingestion/entry-point-scoring.js +36 -26
  27. package/dist/core/ingestion/framework-detection.d.ts +10 -2
  28. package/dist/core/ingestion/framework-detection.js +49 -12
  29. package/dist/core/ingestion/heritage-processor.js +47 -49
  30. package/dist/core/ingestion/import-processor.d.ts +1 -1
  31. package/dist/core/ingestion/import-processor.js +103 -194
  32. package/dist/core/ingestion/import-resolution.d.ts +101 -0
  33. package/dist/core/ingestion/import-resolution.js +251 -0
  34. package/dist/core/ingestion/language-config.d.ts +3 -0
  35. package/dist/core/ingestion/language-config.js +13 -0
  36. package/dist/core/ingestion/markdown-processor.d.ts +17 -0
  37. package/dist/core/ingestion/markdown-processor.js +124 -0
  38. package/dist/core/ingestion/mro-processor.js +8 -3
  39. package/dist/core/ingestion/named-binding-extraction.d.ts +9 -43
  40. package/dist/core/ingestion/named-binding-extraction.js +89 -79
  41. package/dist/core/ingestion/parsing-processor.d.ts +2 -2
  42. package/dist/core/ingestion/parsing-processor.js +14 -73
  43. package/dist/core/ingestion/pipeline.d.ts +10 -0
  44. package/dist/core/ingestion/pipeline.js +421 -4
  45. package/dist/core/ingestion/resolution-context.d.ts +5 -0
  46. package/dist/core/ingestion/resolution-context.js +7 -4
  47. package/dist/core/ingestion/resolvers/index.d.ts +1 -1
  48. package/dist/core/ingestion/resolvers/index.js +1 -1
  49. package/dist/core/ingestion/resolvers/jvm.d.ts +2 -1
  50. package/dist/core/ingestion/resolvers/jvm.js +25 -9
  51. package/dist/core/ingestion/resolvers/php.d.ts +14 -0
  52. package/dist/core/ingestion/resolvers/php.js +43 -3
  53. package/dist/core/ingestion/resolvers/utils.d.ts +5 -0
  54. package/dist/core/ingestion/resolvers/utils.js +16 -0
  55. package/dist/core/ingestion/symbol-table.d.ts +16 -0
  56. package/dist/core/ingestion/symbol-table.js +20 -6
  57. package/dist/core/ingestion/tree-sitter-queries.d.ts +4 -4
  58. package/dist/core/ingestion/tree-sitter-queries.js +43 -2
  59. package/dist/core/ingestion/type-env.d.ts +28 -1
  60. package/dist/core/ingestion/type-env.js +419 -96
  61. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +5 -0
  62. package/dist/core/ingestion/type-extractors/c-cpp.js +119 -0
  63. package/dist/core/ingestion/type-extractors/csharp.js +149 -16
  64. package/dist/core/ingestion/type-extractors/index.d.ts +1 -1
  65. package/dist/core/ingestion/type-extractors/index.js +1 -1
  66. package/dist/core/ingestion/type-extractors/jvm.js +169 -66
  67. package/dist/core/ingestion/type-extractors/rust.js +35 -1
  68. package/dist/core/ingestion/type-extractors/shared.d.ts +0 -2
  69. package/dist/core/ingestion/type-extractors/shared.js +5 -10
  70. package/dist/core/ingestion/type-extractors/swift.js +7 -6
  71. package/dist/core/ingestion/type-extractors/types.d.ts +37 -7
  72. package/dist/core/ingestion/type-extractors/typescript.js +141 -9
  73. package/dist/core/ingestion/utils.d.ts +2 -120
  74. package/dist/core/ingestion/utils.js +3 -1051
  75. package/dist/core/ingestion/workers/parse-worker.d.ts +13 -4
  76. package/dist/core/ingestion/workers/parse-worker.js +66 -87
  77. package/dist/core/lbug/csv-generator.js +18 -1
  78. package/dist/core/lbug/lbug-adapter.d.ts +10 -0
  79. package/dist/core/lbug/lbug-adapter.js +69 -4
  80. package/dist/core/lbug/schema.d.ts +5 -3
  81. package/dist/core/lbug/schema.js +26 -2
  82. package/dist/mcp/core/embedder.js +11 -3
  83. package/dist/mcp/core/lbug-adapter.js +12 -1
  84. package/dist/mcp/local/local-backend.d.ts +22 -0
  85. package/dist/mcp/local/local-backend.js +133 -29
  86. package/dist/mcp/resources.js +2 -0
  87. package/dist/mcp/tools.js +2 -2
  88. package/dist/server/api.d.ts +19 -1
  89. package/dist/server/api.js +66 -6
  90. package/dist/storage/git.d.ts +12 -0
  91. package/dist/storage/git.js +21 -0
  92. package/package.json +10 -2
@@ -1,4 +1,4 @@
1
- import { SupportedLanguages } from '../../config/supported-languages.js';
1
+ import { findChild } from './resolvers/utils.js';
2
2
  /**
3
3
  * Walk a named-binding re-export chain through NamedImportMap.
4
4
  *
@@ -41,40 +41,6 @@ export function walkBindingChain(name, currentFilePath, symbolTable, namedImport
41
41
  }
42
42
  return null;
43
43
  }
44
- /**
45
- * Extract named bindings from an import AST node.
46
- * Returns undefined if the import is not a named import (e.g., import * or default).
47
- *
48
- * TS: import { User, Repo as R } from './models'
49
- * → [{local:'User', exported:'User'}, {local:'R', exported:'Repo'}]
50
- *
51
- * Python: from models import User, Repo as R
52
- * → [{local:'User', exported:'User'}, {local:'R', exported:'Repo'}]
53
- */
54
- export function extractNamedBindings(importNode, language) {
55
- if (language === SupportedLanguages.TypeScript || language === SupportedLanguages.JavaScript) {
56
- return extractTsNamedBindings(importNode);
57
- }
58
- if (language === SupportedLanguages.Python) {
59
- return extractPythonNamedBindings(importNode);
60
- }
61
- if (language === SupportedLanguages.Kotlin) {
62
- return extractKotlinNamedBindings(importNode);
63
- }
64
- if (language === SupportedLanguages.Rust) {
65
- return extractRustNamedBindings(importNode);
66
- }
67
- if (language === SupportedLanguages.PHP) {
68
- return extractPhpNamedBindings(importNode);
69
- }
70
- if (language === SupportedLanguages.CSharp) {
71
- return extractCsharpNamedBindings(importNode);
72
- }
73
- if (language === SupportedLanguages.Java) {
74
- return extractJavaNamedBindings(importNode);
75
- }
76
- return undefined;
77
- }
78
44
  export function extractTsNamedBindings(importNode) {
79
45
  // import_statement > import_clause > named_imports > import_specifier*
80
46
  const importClause = findChild(importNode, 'import_clause');
@@ -133,34 +99,52 @@ export function extractTsNamedBindings(importNode) {
133
99
  return undefined;
134
100
  }
135
101
  export function extractPythonNamedBindings(importNode) {
136
- // Only from import_from_statement, not plain import_statement
137
- if (importNode.type !== 'import_from_statement')
138
- return undefined;
139
- const bindings = [];
140
- for (let i = 0; i < importNode.namedChildCount; i++) {
141
- const child = importNode.namedChild(i);
142
- if (!child)
143
- continue;
144
- if (child.type === 'dotted_name') {
145
- // Skip the module_name (first dotted_name is the source module)
146
- const fieldName = importNode.childForFieldName?.('module_name');
147
- if (fieldName && child.startIndex === fieldName.startIndex)
102
+ // Handle: from x import User, Repo as R
103
+ if (importNode.type === 'import_from_statement') {
104
+ const bindings = [];
105
+ for (let i = 0; i < importNode.namedChildCount; i++) {
106
+ const child = importNode.namedChild(i);
107
+ if (!child)
148
108
  continue;
149
- // This is an imported name: from x import User
150
- const name = child.text;
151
- if (name)
152
- bindings.push({ local: name, exported: name });
109
+ if (child.type === 'dotted_name') {
110
+ // Skip the module_name (first dotted_name is the source module)
111
+ const fieldName = importNode.childForFieldName?.('module_name');
112
+ if (fieldName && child.startIndex === fieldName.startIndex)
113
+ continue;
114
+ // This is an imported name: from x import User
115
+ const name = child.text;
116
+ if (name)
117
+ bindings.push({ local: name, exported: name });
118
+ }
119
+ if (child.type === 'aliased_import') {
120
+ // from x import Repo as R
121
+ const dottedName = findChild(child, 'dotted_name');
122
+ const aliasIdent = findChild(child, 'identifier');
123
+ if (dottedName && aliasIdent) {
124
+ bindings.push({ local: aliasIdent.text, exported: dottedName.text });
125
+ }
126
+ }
153
127
  }
154
- if (child.type === 'aliased_import') {
155
- // from x import Repo as R
128
+ return bindings.length > 0 ? bindings : undefined;
129
+ }
130
+ // Handle: import numpy as np (import_statement with aliased_import child)
131
+ // Tagged with isModuleAlias so applyImportResult routes these directly to
132
+ // moduleAliasMap (e.g. "np" → "numpy.py") instead of namedImportMap.
133
+ if (importNode.type === 'import_statement') {
134
+ const bindings = [];
135
+ for (let i = 0; i < importNode.namedChildCount; i++) {
136
+ const child = importNode.namedChild(i);
137
+ if (!child || child.type !== 'aliased_import')
138
+ continue;
156
139
  const dottedName = findChild(child, 'dotted_name');
157
140
  const aliasIdent = findChild(child, 'identifier');
158
141
  if (dottedName && aliasIdent) {
159
- bindings.push({ local: aliasIdent.text, exported: dottedName.text });
142
+ bindings.push({ local: aliasIdent.text, exported: dottedName.text, isModuleAlias: true });
160
143
  }
161
144
  }
145
+ return bindings.length > 0 ? bindings : undefined;
162
146
  }
163
- return bindings.length > 0 ? bindings : undefined;
147
+ return undefined;
164
148
  }
165
149
  export function extractKotlinNamedBindings(importNode) {
166
150
  // import_header > identifier + import_alias > simple_identifier
@@ -180,15 +164,21 @@ export function extractKotlinNamedBindings(importNode) {
180
164
  return [{ local: aliasIdent.text, exported: exportedName }];
181
165
  }
182
166
  // Non-aliased: import com.example.User → local="User", exported="User"
167
+ // Also handles top-level function imports: import models.getUser → local="getUser"
183
168
  // Skip wildcard imports (ending in *)
184
169
  if (fullText.endsWith('.*') || fullText.endsWith('*'))
185
170
  return undefined;
186
- // Skip lowercase last segments — those are member/function imports (e.g.,
187
- // import util.OneArg.writeAudit), not class imports. Multiple member imports
171
+ // Skip class-member imports (e.g., import util.OneArg.writeAudit) where the
172
+ // second-to-last segment is PascalCase (a class name). Multiple member imports
188
173
  // with the same function name would collide in NamedImportMap, breaking
189
- // arity-based disambiguation.
190
- if (exportedName[0] && exportedName[0] === exportedName[0].toLowerCase())
191
- return undefined;
174
+ // arity-based disambiguation. Top-level function imports (import models.getUser)
175
+ // and class imports (import models.User) have package-only prefixes.
176
+ const segments = fullText.split('.');
177
+ if (segments.length >= 3) {
178
+ const parentSegment = segments[segments.length - 2];
179
+ if (parentSegment[0] && parentSegment[0] === parentSegment[0].toUpperCase())
180
+ return undefined;
181
+ }
192
182
  return [{ local: exportedName, exported: exportedName }];
193
183
  }
194
184
  export function extractRustNamedBindings(importNode) {
@@ -260,6 +250,12 @@ export function extractPhpNamedBindings(importNode) {
260
250
  // namespace_use_declaration > namespace_use_group > namespace_use_clause* (grouped)
261
251
  if (importNode.type !== 'namespace_use_declaration')
262
252
  return undefined;
253
+ // Skip 'use function' and 'use const' declarations — these import callables/constants,
254
+ // not class types, and should not be added to namedImportMap as type bindings.
255
+ const useTypeNode = importNode.childForFieldName?.('type');
256
+ if (useTypeNode && (useTypeNode.text === 'function' || useTypeNode.text === 'const')) {
257
+ return undefined;
258
+ }
263
259
  const bindings = [];
264
260
  // Collect all clauses — from direct children AND from namespace_use_group
265
261
  const clauses = [];
@@ -311,11 +307,20 @@ export function extractPhpNamedBindings(importNode) {
311
307
  return bindings.length > 0 ? bindings : undefined;
312
308
  }
313
309
  export function extractCsharpNamedBindings(importNode) {
314
- // using_directive with identifier (alias) + qualified_name (target)
310
+ // using_directive three forms:
311
+ // using Alias = NS.Type; → aliasIdent + qualifiedName
312
+ // using static NS.Type; → static + qualifiedName (no alias)
313
+ // using NS; → qualifiedName only (namespace, not capturable)
315
314
  if (importNode.type !== 'using_directive')
316
315
  return undefined;
317
316
  let aliasIdent = null;
318
317
  let qualifiedName = null;
318
+ let isStatic = false;
319
+ for (let i = 0; i < importNode.childCount; i++) {
320
+ const child = importNode.child(i);
321
+ if (child?.text === 'static')
322
+ isStatic = true;
323
+ }
319
324
  for (let i = 0; i < importNode.namedChildCount; i++) {
320
325
  const child = importNode.namedChild(i);
321
326
  if (child?.type === 'identifier' && !aliasIdent)
@@ -323,22 +328,34 @@ export function extractCsharpNamedBindings(importNode) {
323
328
  else if (child?.type === 'qualified_name')
324
329
  qualifiedName = child;
325
330
  }
326
- if (!aliasIdent || !qualifiedName)
327
- return undefined;
328
- const fullText = qualifiedName.text;
329
- const exportedName = fullText.includes('.') ? fullText.split('.').pop() : fullText;
330
- return [{ local: aliasIdent.text, exported: exportedName }];
331
+ // Form 1: using Alias = NS.Type;
332
+ if (aliasIdent && qualifiedName) {
333
+ const fullText = qualifiedName.text;
334
+ const exportedName = fullText.includes('.') ? fullText.split('.').pop() : fullText;
335
+ return [{ local: aliasIdent.text, exported: exportedName }];
336
+ }
337
+ // Form 2: using static NS.Type; — last segment is the class name
338
+ if (isStatic && qualifiedName) {
339
+ const fullText = qualifiedName.text;
340
+ const lastSegment = fullText.includes('.') ? fullText.split('.').pop() : fullText;
341
+ return [{ local: lastSegment, exported: lastSegment }];
342
+ }
343
+ // Form 3: using NS; — namespace import, can't resolve to per-symbol bindings
344
+ return undefined;
331
345
  }
332
346
  export function extractJavaNamedBindings(importNode) {
333
347
  // import_declaration > scoped_identifier "com.example.models.User"
334
348
  // Wildcard imports (.*) don't produce named bindings
335
349
  if (importNode.type !== 'import_declaration')
336
350
  return undefined;
337
- // Check for asterisk (wildcard import) skip those
351
+ // Check for asterisk (wildcard import) and static modifier
352
+ let isStatic = false;
338
353
  for (let i = 0; i < importNode.childCount; i++) {
339
354
  const child = importNode.child(i);
340
355
  if (child?.type === 'asterisk')
341
356
  return undefined;
357
+ if (child?.text === 'static')
358
+ isStatic = true;
342
359
  }
343
360
  const scopedId = findChild(importNode, 'scoped_identifier');
344
361
  if (!scopedId)
@@ -347,17 +364,10 @@ export function extractJavaNamedBindings(importNode) {
347
364
  const lastDot = fullText.lastIndexOf('.');
348
365
  if (lastDot === -1)
349
366
  return undefined;
350
- const className = fullText.slice(lastDot + 1);
351
- // Skip lowercase names — those are package imports, not class imports
352
- if (className[0] && className[0] === className[0].toLowerCase())
367
+ const name = fullText.slice(lastDot + 1);
368
+ // Non-static: skip lowercase names — those are package imports, not class imports.
369
+ // Static: allow lowercase `import static models.UserFactory.getUser` imports a method.
370
+ if (!isStatic && name[0] && name[0] === name[0].toLowerCase())
353
371
  return undefined;
354
- return [{ local: className, exported: className }];
355
- }
356
- function findChild(node, type) {
357
- for (let i = 0; i < node.namedChildCount; i++) {
358
- const child = node.namedChild(i);
359
- if (child?.type === type)
360
- return child;
361
- }
362
- return null;
372
+ return [{ local: name, exported: name }];
363
373
  }
@@ -2,7 +2,7 @@ import { KnowledgeGraph } from '../graph/types.js';
2
2
  import { SymbolTable } from './symbol-table.js';
3
3
  import { ASTCache } from './ast-cache.js';
4
4
  import { WorkerPool } from './workers/worker-pool.js';
5
- import type { ExtractedImport, ExtractedCall, ExtractedAssignment, ExtractedHeritage, ExtractedRoute, FileConstructorBindings } from './workers/parse-worker.js';
5
+ import type { ExtractedImport, ExtractedCall, ExtractedAssignment, ExtractedHeritage, ExtractedRoute, FileConstructorBindings, FileTypeEnvBindings } from './workers/parse-worker.js';
6
6
  export type FileProgressCallback = (current: number, total: number, filePath: string) => void;
7
7
  export interface WorkerExtractedData {
8
8
  imports: ExtractedImport[];
@@ -11,8 +11,8 @@ export interface WorkerExtractedData {
11
11
  heritage: ExtractedHeritage[];
12
12
  routes: ExtractedRoute[];
13
13
  constructorBindings: FileConstructorBindings[];
14
+ typeEnvBindings: FileTypeEnvBindings[];
14
15
  }
15
- export { isNodeExported } from './export-detection.js';
16
16
  export declare const processParsing: (graph: KnowledgeGraph, files: {
17
17
  path: string;
18
18
  content: string;
@@ -2,16 +2,12 @@ import Parser from 'tree-sitter';
2
2
  import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
3
3
  import { LANGUAGE_QUERIES } from './tree-sitter-queries.js';
4
4
  import { generateId } from '../../lib/utils.js';
5
- import { getLanguageFromFilename, yieldToEventLoop, getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature } from './utils.js';
5
+ import { getLanguageFromFilename, yieldToEventLoop, getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures } from './utils.js';
6
6
  import { extractPropertyDeclaredType } from './type-extractors/shared.js';
7
7
  import { isNodeExported } from './export-detection.js';
8
8
  import { detectFrameworkFromAST } from './framework-detection.js';
9
9
  import { typeConfigs } from './type-extractors/index.js';
10
- import { SupportedLanguages } from '../../config/supported-languages.js';
11
10
  import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
12
- // isNodeExported imported from ./export-detection.js (shared module)
13
- // Re-export for backward compatibility with any external consumers
14
- export { isNodeExported } from './export-detection.js';
15
11
  // ============================================================================
16
12
  // Worker-based parallel parsing
17
13
  // ============================================================================
@@ -24,7 +20,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
24
20
  parseableFiles.push({ path: file.path, content: file.content });
25
21
  }
26
22
  if (parseableFiles.length === 0)
27
- return { imports: [], calls: [], assignments: [], heritage: [], routes: [], constructorBindings: [] };
23
+ return { imports: [], calls: [], assignments: [], heritage: [], routes: [], constructorBindings: [], typeEnvBindings: [] };
28
24
  const total = files.length;
29
25
  // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
30
26
  const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
@@ -37,6 +33,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
37
33
  const allHeritage = [];
38
34
  const allRoutes = [];
39
35
  const allConstructorBindings = [];
36
+ const allTypeEnvBindings = [];
40
37
  for (const result of chunkResults) {
41
38
  for (const node of result.nodes) {
42
39
  graph.addNode({
@@ -51,6 +48,8 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
51
48
  for (const sym of result.symbols) {
52
49
  symbolTable.add(sym.filePath, sym.name, sym.nodeId, sym.type, {
53
50
  parameterCount: sym.parameterCount,
51
+ requiredParameterCount: sym.requiredParameterCount,
52
+ parameterTypes: sym.parameterTypes,
54
53
  returnType: sym.returnType,
55
54
  declaredType: sym.declaredType,
56
55
  ownerId: sym.ownerId,
@@ -62,6 +61,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
62
61
  allHeritage.push(...result.heritage);
63
62
  allRoutes.push(...result.routes);
64
63
  allConstructorBindings.push(...result.constructorBindings);
64
+ allTypeEnvBindings.push(...result.typeEnvBindings);
65
65
  }
66
66
  // Merge and log skipped languages from workers
67
67
  const skippedLanguages = new Map();
@@ -78,7 +78,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
78
78
  }
79
79
  // Final progress
80
80
  onFileProgress?.(total, total, 'done');
81
- return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, constructorBindings: allConstructorBindings };
81
+ return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, constructorBindings: allConstructorBindings, typeEnvBindings: allTypeEnvBindings };
82
82
  };
83
83
  // ============================================================================
84
84
  // Sequential fallback (original implementation)
@@ -138,77 +138,14 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
138
138
  match.captures.forEach(c => {
139
139
  captureMap[c.name] = c.node;
140
140
  });
141
- if (captureMap['import']) {
141
+ const nodeLabel = getLabelFromCaptures(captureMap, language);
142
+ if (!nodeLabel)
142
143
  return;
143
- }
144
- if (captureMap['call']) {
145
- return;
146
- }
147
144
  const nameNode = captureMap['name'];
148
145
  // Synthesize name for constructors without explicit @name capture (e.g. Swift init)
149
- if (!nameNode && !captureMap['definition.constructor'])
146
+ if (!nameNode && nodeLabel !== 'Constructor')
150
147
  return;
151
148
  const nodeName = nameNode ? nameNode.text : 'init';
152
- let nodeLabel = 'CodeElement';
153
- if (captureMap['definition.function']) {
154
- // C/C++: @definition.function is broad and also matches inline class methods (inside
155
- // a class/struct body). Those are already captured by @definition.method, so skip
156
- // the duplicate Function entry to prevent double-indexing in globalIndex.
157
- if (language === SupportedLanguages.CPlusPlus || language === SupportedLanguages.C) {
158
- let ancestor = captureMap['definition.function']?.parent;
159
- while (ancestor) {
160
- if (ancestor.type === 'class_specifier' || ancestor.type === 'struct_specifier') {
161
- break;
162
- }
163
- ancestor = ancestor.parent;
164
- }
165
- if (ancestor)
166
- return; // inside a class body — handled by @definition.method
167
- }
168
- nodeLabel = 'Function';
169
- }
170
- else if (captureMap['definition.class'])
171
- nodeLabel = 'Class';
172
- else if (captureMap['definition.interface'])
173
- nodeLabel = 'Interface';
174
- else if (captureMap['definition.method'])
175
- nodeLabel = 'Method';
176
- else if (captureMap['definition.struct'])
177
- nodeLabel = 'Struct';
178
- else if (captureMap['definition.enum'])
179
- nodeLabel = 'Enum';
180
- else if (captureMap['definition.namespace'])
181
- nodeLabel = 'Namespace';
182
- else if (captureMap['definition.module'])
183
- nodeLabel = 'Module';
184
- else if (captureMap['definition.trait'])
185
- nodeLabel = 'Trait';
186
- else if (captureMap['definition.impl'])
187
- nodeLabel = 'Impl';
188
- else if (captureMap['definition.type'])
189
- nodeLabel = 'TypeAlias';
190
- else if (captureMap['definition.const'])
191
- nodeLabel = 'Const';
192
- else if (captureMap['definition.static'])
193
- nodeLabel = 'Static';
194
- else if (captureMap['definition.typedef'])
195
- nodeLabel = 'Typedef';
196
- else if (captureMap['definition.macro'])
197
- nodeLabel = 'Macro';
198
- else if (captureMap['definition.union'])
199
- nodeLabel = 'Union';
200
- else if (captureMap['definition.property'])
201
- nodeLabel = 'Property';
202
- else if (captureMap['definition.record'])
203
- nodeLabel = 'Record';
204
- else if (captureMap['definition.delegate'])
205
- nodeLabel = 'Delegate';
206
- else if (captureMap['definition.annotation'])
207
- nodeLabel = 'Annotation';
208
- else if (captureMap['definition.constructor'])
209
- nodeLabel = 'Constructor';
210
- else if (captureMap['definition.template'])
211
- nodeLabel = 'Template';
212
149
  const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
213
150
  const startLine = definitionNodeForRange ? definitionNodeForRange.startPosition.row : (nameNode ? nameNode.startPosition.row : 0);
214
151
  const nodeId = generateId(nodeLabel, `${file.path}:${nodeName}`);
@@ -246,6 +183,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
246
183
  } : {}),
247
184
  ...(methodSig ? {
248
185
  parameterCount: methodSig.parameterCount,
186
+ ...(methodSig.requiredParameterCount !== undefined ? { requiredParameterCount: methodSig.requiredParameterCount } : {}),
187
+ ...(methodSig.parameterTypes ? { parameterTypes: methodSig.parameterTypes } : {}),
249
188
  returnType: methodSig.returnType,
250
189
  } : {}),
251
190
  },
@@ -261,6 +200,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
261
200
  : undefined;
262
201
  symbolTable.add(file.path, nodeName, nodeId, nodeLabel, {
263
202
  parameterCount: methodSig?.parameterCount,
203
+ requiredParameterCount: methodSig?.requiredParameterCount,
204
+ parameterTypes: methodSig?.parameterTypes,
264
205
  returnType: methodSig?.returnType,
265
206
  declaredType,
266
207
  ownerId: enclosingClassId ?? undefined,
@@ -1,6 +1,16 @@
1
1
  import { PipelineProgress, PipelineResult } from '../../types/pipeline.js';
2
+ /** A group of files with no mutual dependencies, safe to process in parallel. */
3
+ type IndependentFileGroup = readonly string[];
4
+ /** Kahn's algorithm: returns files grouped by topological level.
5
+ * Files in the same level have no mutual dependencies — safe to process in parallel.
6
+ * Files in cycles are returned as a final group (no cross-cycle propagation). */
7
+ export declare function topologicalLevelSort(importMap: ReadonlyMap<string, ReadonlySet<string>>): {
8
+ levels: readonly IndependentFileGroup[];
9
+ cycleCount: number;
10
+ };
2
11
  export interface PipelineOptions {
3
12
  /** Skip MRO, community detection, and process extraction for faster test runs. */
4
13
  skipGraphPhases?: boolean;
5
14
  }
6
15
  export declare const runPipelineFromRepo: (repoPath: string, onProgress: (progress: PipelineProgress) => void, options?: PipelineOptions) => Promise<PipelineResult>;
16
+ export {};