gitnexus 1.4.8 → 1.4.9

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 (211) hide show
  1. package/README.md +7 -0
  2. package/dist/cli/index-repo.d.ts +15 -0
  3. package/dist/cli/index-repo.js +115 -0
  4. package/dist/cli/index.js +11 -2
  5. package/dist/cli/setup.js +12 -9
  6. package/dist/cli/wiki.d.ts +4 -0
  7. package/dist/cli/wiki.js +174 -53
  8. package/dist/config/supported-languages.d.ts +7 -5
  9. package/dist/config/supported-languages.js +6 -4
  10. package/dist/core/graph/graph.js +9 -1
  11. package/dist/core/graph/types.d.ts +10 -2
  12. package/dist/core/ingestion/call-processor.d.ts +18 -1
  13. package/dist/core/ingestion/call-processor.js +297 -38
  14. package/dist/core/ingestion/call-routing.d.ts +3 -18
  15. package/dist/core/ingestion/call-routing.js +0 -19
  16. package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
  17. package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
  18. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
  19. package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
  20. package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
  21. package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
  22. package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
  23. package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
  24. package/dist/core/ingestion/cobol-processor.d.ts +54 -0
  25. package/dist/core/ingestion/cobol-processor.js +1186 -0
  26. package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
  27. package/dist/core/ingestion/entry-point-scoring.js +18 -4
  28. package/dist/core/ingestion/export-detection.d.ts +47 -8
  29. package/dist/core/ingestion/export-detection.js +29 -50
  30. package/dist/core/ingestion/field-extractor.d.ts +29 -0
  31. package/dist/core/ingestion/field-extractor.js +25 -0
  32. package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
  33. package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
  34. package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
  35. package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
  36. package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
  37. package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
  38. package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
  39. package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
  40. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
  41. package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
  42. package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
  43. package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
  44. package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
  45. package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
  46. package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
  47. package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
  48. package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
  49. package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
  50. package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
  51. package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
  52. package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
  53. package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
  54. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
  55. package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
  56. package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
  57. package/dist/core/ingestion/field-extractors/generic.js +111 -0
  58. package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
  59. package/dist/core/ingestion/field-extractors/typescript.js +291 -0
  60. package/dist/core/ingestion/field-types.d.ts +59 -0
  61. package/dist/core/ingestion/field-types.js +2 -0
  62. package/dist/core/ingestion/framework-detection.d.ts +87 -0
  63. package/dist/core/ingestion/framework-detection.js +65 -2
  64. package/dist/core/ingestion/heritage-processor.js +15 -17
  65. package/dist/core/ingestion/import-processor.d.ts +9 -10
  66. package/dist/core/ingestion/import-processor.js +59 -14
  67. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
  68. package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
  69. package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
  70. package/dist/core/ingestion/import-resolvers/dart.js +44 -0
  71. package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
  72. package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
  73. package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +9 -1
  74. package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.js +56 -0
  75. package/dist/core/ingestion/{resolvers → import-resolvers}/php.d.ts +6 -10
  76. package/dist/core/ingestion/{resolvers → import-resolvers}/php.js +7 -2
  77. package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
  78. package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
  79. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
  80. package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
  81. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
  82. package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
  83. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
  84. package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
  85. package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
  86. package/dist/core/ingestion/import-resolvers/swift.js +23 -0
  87. package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
  88. package/dist/core/ingestion/import-resolvers/types.js +6 -0
  89. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +0 -3
  90. package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +0 -9
  91. package/dist/core/ingestion/language-config.d.ts +4 -1
  92. package/dist/core/ingestion/language-provider.d.ts +121 -0
  93. package/dist/core/ingestion/language-provider.js +24 -0
  94. package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
  95. package/dist/core/ingestion/languages/c-cpp.js +71 -0
  96. package/dist/core/ingestion/languages/cobol.d.ts +1 -0
  97. package/dist/core/ingestion/languages/cobol.js +26 -0
  98. package/dist/core/ingestion/languages/csharp.d.ts +8 -0
  99. package/dist/core/ingestion/languages/csharp.js +49 -0
  100. package/dist/core/ingestion/languages/dart.d.ts +12 -0
  101. package/dist/core/ingestion/languages/dart.js +58 -0
  102. package/dist/core/ingestion/languages/go.d.ts +11 -0
  103. package/dist/core/ingestion/languages/go.js +28 -0
  104. package/dist/core/ingestion/languages/index.d.ts +38 -0
  105. package/dist/core/ingestion/languages/index.js +63 -0
  106. package/dist/core/ingestion/languages/java.d.ts +9 -0
  107. package/dist/core/ingestion/languages/java.js +29 -0
  108. package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
  109. package/dist/core/ingestion/languages/kotlin.js +53 -0
  110. package/dist/core/ingestion/languages/php.d.ts +8 -0
  111. package/dist/core/ingestion/languages/php.js +145 -0
  112. package/dist/core/ingestion/languages/python.d.ts +12 -0
  113. package/dist/core/ingestion/languages/python.js +39 -0
  114. package/dist/core/ingestion/languages/ruby.d.ts +9 -0
  115. package/dist/core/ingestion/languages/ruby.js +44 -0
  116. package/dist/core/ingestion/languages/rust.d.ts +12 -0
  117. package/dist/core/ingestion/languages/rust.js +44 -0
  118. package/dist/core/ingestion/languages/swift.d.ts +12 -0
  119. package/dist/core/ingestion/languages/swift.js +133 -0
  120. package/dist/core/ingestion/languages/typescript.d.ts +10 -0
  121. package/dist/core/ingestion/languages/typescript.js +60 -0
  122. package/dist/core/ingestion/mro-processor.js +14 -15
  123. package/dist/core/ingestion/{named-binding-extraction.d.ts → named-binding-processor.d.ts} +0 -9
  124. package/dist/core/ingestion/named-binding-processor.js +42 -0
  125. package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
  126. package/dist/core/ingestion/named-bindings/csharp.js +37 -0
  127. package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
  128. package/dist/core/ingestion/named-bindings/java.js +29 -0
  129. package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
  130. package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
  131. package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
  132. package/dist/core/ingestion/named-bindings/php.js +61 -0
  133. package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
  134. package/dist/core/ingestion/named-bindings/python.js +49 -0
  135. package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
  136. package/dist/core/ingestion/named-bindings/rust.js +64 -0
  137. package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
  138. package/dist/core/ingestion/named-bindings/types.js +6 -0
  139. package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
  140. package/dist/core/ingestion/named-bindings/typescript.js +58 -0
  141. package/dist/core/ingestion/parsing-processor.d.ts +5 -1
  142. package/dist/core/ingestion/parsing-processor.js +115 -16
  143. package/dist/core/ingestion/pipeline.js +925 -424
  144. package/dist/core/ingestion/resolution-context.js +1 -1
  145. package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
  146. package/dist/core/ingestion/route-extractors/expo.js +36 -0
  147. package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
  148. package/dist/core/ingestion/route-extractors/middleware.js +143 -0
  149. package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
  150. package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
  151. package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
  152. package/dist/core/ingestion/route-extractors/php.js +21 -0
  153. package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
  154. package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
  155. package/dist/core/ingestion/tree-sitter-queries.d.ts +8 -7
  156. package/dist/core/ingestion/tree-sitter-queries.js +231 -9
  157. package/dist/core/ingestion/type-env.d.ts +14 -17
  158. package/dist/core/ingestion/type-env.js +66 -14
  159. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +1 -1
  160. package/dist/core/ingestion/type-extractors/csharp.js +1 -1
  161. package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
  162. package/dist/core/ingestion/type-extractors/dart.js +371 -0
  163. package/dist/core/ingestion/type-extractors/jvm.js +1 -1
  164. package/dist/core/ingestion/type-extractors/shared.d.ts +1 -13
  165. package/dist/core/ingestion/type-extractors/shared.js +9 -102
  166. package/dist/core/ingestion/type-extractors/swift.js +334 -4
  167. package/dist/core/ingestion/type-extractors/types.d.ts +3 -1
  168. package/dist/core/ingestion/{ast-helpers.d.ts → utils/ast-helpers.d.ts} +16 -13
  169. package/dist/core/ingestion/{ast-helpers.js → utils/ast-helpers.js} +111 -32
  170. package/dist/core/ingestion/{call-analysis.js → utils/call-analysis.js} +37 -0
  171. package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
  172. package/dist/core/ingestion/utils/event-loop.js +5 -0
  173. package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
  174. package/dist/core/ingestion/utils/language-detection.js +70 -0
  175. package/dist/core/ingestion/utils/verbose.d.ts +1 -0
  176. package/dist/core/ingestion/utils/verbose.js +7 -0
  177. package/dist/core/ingestion/workers/parse-worker.d.ts +43 -2
  178. package/dist/core/ingestion/workers/parse-worker.js +361 -150
  179. package/dist/core/lbug/csv-generator.js +34 -1
  180. package/dist/core/lbug/lbug-adapter.js +6 -0
  181. package/dist/core/lbug/schema.d.ts +5 -3
  182. package/dist/core/lbug/schema.js +39 -2
  183. package/dist/core/tree-sitter/parser-loader.js +7 -1
  184. package/dist/core/wiki/cursor-client.d.ts +31 -0
  185. package/dist/core/wiki/cursor-client.js +127 -0
  186. package/dist/core/wiki/generator.d.ts +28 -9
  187. package/dist/core/wiki/generator.js +115 -18
  188. package/dist/core/wiki/graph-queries.d.ts +4 -0
  189. package/dist/core/wiki/graph-queries.js +7 -1
  190. package/dist/core/wiki/llm-client.d.ts +2 -0
  191. package/dist/core/wiki/llm-client.js +8 -4
  192. package/dist/core/wiki/prompts.d.ts +3 -3
  193. package/dist/core/wiki/prompts.js +6 -0
  194. package/dist/mcp/core/lbug-adapter.d.ts +5 -0
  195. package/dist/mcp/core/lbug-adapter.js +11 -1
  196. package/dist/mcp/local/local-backend.d.ts +16 -5
  197. package/dist/mcp/local/local-backend.js +711 -74
  198. package/dist/mcp/tools.js +71 -2
  199. package/dist/storage/repo-manager.d.ts +3 -0
  200. package/package.json +17 -16
  201. package/dist/core/ingestion/import-resolution.d.ts +0 -101
  202. package/dist/core/ingestion/import-resolution.js +0 -251
  203. package/dist/core/ingestion/named-binding-extraction.js +0 -373
  204. package/dist/core/ingestion/resolvers/index.d.ts +0 -18
  205. package/dist/core/ingestion/resolvers/index.js +0 -13
  206. package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
  207. package/dist/core/ingestion/type-extractors/index.js +0 -31
  208. package/dist/core/ingestion/utils.d.ts +0 -20
  209. package/dist/core/ingestion/utils.js +0 -242
  210. package/scripts/patch-tree-sitter-swift.cjs +0 -74
  211. /package/dist/core/ingestion/{call-analysis.d.ts → utils/call-analysis.d.ts} +0 -0
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Named binding types — shared across all per-language binding extractors.
3
+ *
4
+ * Extracted from import-resolution.ts to co-locate types with their consumers.
5
+ */
6
+ import type { SyntaxNode } from '../utils/ast-helpers.js';
7
+ /** A single named import binding: local name in the importing file and exported name from the source.
8
+ * When `isModuleAlias` is true, the binding represents a Python `import X as Y` module alias
9
+ * and is routed to moduleAliasMap instead of namedImportMap during import processing. */
10
+ export interface NamedBinding {
11
+ local: string;
12
+ exported: string;
13
+ isModuleAlias?: boolean;
14
+ }
15
+ /** Per-language named binding extractor -- optional (returns undefined if language has no named imports). */
16
+ export type NamedBindingExtractorFn = (importNode: SyntaxNode) => NamedBinding[] | undefined;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Named binding types — shared across all per-language binding extractors.
3
+ *
4
+ * Extracted from import-resolution.ts to co-locate types with their consumers.
5
+ */
6
+ export {};
@@ -0,0 +1,3 @@
1
+ import { type SyntaxNode } from '../utils/ast-helpers.js';
2
+ import type { NamedBinding } from './types.js';
3
+ export declare function extractTsNamedBindings(importNode: SyntaxNode): NamedBinding[] | undefined;
@@ -0,0 +1,58 @@
1
+ import { findChild } from '../utils/ast-helpers.js';
2
+ export function extractTsNamedBindings(importNode) {
3
+ // import_statement > import_clause > named_imports > import_specifier*
4
+ const importClause = findChild(importNode, 'import_clause');
5
+ if (importClause) {
6
+ const namedImports = findChild(importClause, 'named_imports');
7
+ if (!namedImports)
8
+ return undefined; // default import, namespace import, or side-effect
9
+ const bindings = [];
10
+ for (let i = 0; i < namedImports.namedChildCount; i++) {
11
+ const specifier = namedImports.namedChild(i);
12
+ if (specifier?.type !== 'import_specifier')
13
+ continue;
14
+ const identifiers = [];
15
+ for (let j = 0; j < specifier.namedChildCount; j++) {
16
+ const child = specifier.namedChild(j);
17
+ if (child?.type === 'identifier')
18
+ identifiers.push(child.text);
19
+ }
20
+ if (identifiers.length === 1) {
21
+ bindings.push({ local: identifiers[0], exported: identifiers[0] });
22
+ }
23
+ else if (identifiers.length === 2) {
24
+ // import { Foo as Bar } → exported='Foo', local='Bar'
25
+ bindings.push({ local: identifiers[1], exported: identifiers[0] });
26
+ }
27
+ }
28
+ return bindings.length > 0 ? bindings : undefined;
29
+ }
30
+ // Re-export: export { X } from './y' → export_statement > export_clause > export_specifier
31
+ const exportClause = findChild(importNode, 'export_clause');
32
+ if (exportClause) {
33
+ const bindings = [];
34
+ for (let i = 0; i < exportClause.namedChildCount; i++) {
35
+ const specifier = exportClause.namedChild(i);
36
+ if (specifier?.type !== 'export_specifier')
37
+ continue;
38
+ const identifiers = [];
39
+ for (let j = 0; j < specifier.namedChildCount; j++) {
40
+ const child = specifier.namedChild(j);
41
+ if (child?.type === 'identifier')
42
+ identifiers.push(child.text);
43
+ }
44
+ if (identifiers.length === 1) {
45
+ // export { User } from './base' → re-exports User as User
46
+ bindings.push({ local: identifiers[0], exported: identifiers[0] });
47
+ }
48
+ else if (identifiers.length === 2) {
49
+ // export { Repo as Repository } from './models' → name=Repo, alias=Repository
50
+ // For re-exports, the first id is the source name, second is what's exported
51
+ // When another file imports { Repository }, they get Repo from the source
52
+ bindings.push({ local: identifiers[1], exported: identifiers[0] });
53
+ }
54
+ }
55
+ return bindings.length > 0 ? bindings : undefined;
56
+ }
57
+ return undefined;
58
+ }
@@ -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, FileTypeEnvBindings } from './workers/parse-worker.js';
5
+ import type { ExtractedImport, ExtractedCall, ExtractedAssignment, ExtractedHeritage, ExtractedRoute, ExtractedFetchCall, ExtractedDecoratorRoute, ExtractedToolDef, FileConstructorBindings, FileTypeEnvBindings, ExtractedORMQuery } 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[];
@@ -10,6 +10,10 @@ export interface WorkerExtractedData {
10
10
  assignments: ExtractedAssignment[];
11
11
  heritage: ExtractedHeritage[];
12
12
  routes: ExtractedRoute[];
13
+ fetchCalls: ExtractedFetchCall[];
14
+ decoratorRoutes: ExtractedDecoratorRoute[];
15
+ toolDefs: ExtractedToolDef[];
16
+ ormQueries: ExtractedORMQuery[];
13
17
  constructorBindings: FileConstructorBindings[];
14
18
  typeEnvBindings: FileTypeEnvBindings[];
15
19
  }
@@ -1,12 +1,12 @@
1
1
  import Parser from 'tree-sitter';
2
2
  import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
3
- import { LANGUAGE_QUERIES } from './tree-sitter-queries.js';
3
+ import { getProvider } from './languages/index.js';
4
4
  import { generateId } from '../../lib/utils.js';
5
- import { getLanguageFromFilename, yieldToEventLoop, getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures } from './utils.js';
6
- import { extractPropertyDeclaredType } from './type-extractors/shared.js';
7
- import { isNodeExported } from './export-detection.js';
5
+ import { getLanguageFromFilename } from './utils/language-detection.js';
6
+ import { yieldToEventLoop } from './utils/event-loop.js';
7
+ import { getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature, getLabelFromCaptures, CLASS_CONTAINER_TYPES } from './utils/ast-helpers.js';
8
8
  import { detectFrameworkFromAST } from './framework-detection.js';
9
- import { typeConfigs } from './type-extractors/index.js';
9
+ import { buildTypeEnv } from './type-env.js';
10
10
  import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
11
11
  // ============================================================================
12
12
  // Worker-based parallel parsing
@@ -20,7 +20,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
20
20
  parseableFiles.push({ path: file.path, content: file.content });
21
21
  }
22
22
  if (parseableFiles.length === 0)
23
- return { imports: [], calls: [], assignments: [], heritage: [], routes: [], constructorBindings: [], typeEnvBindings: [] };
23
+ return { imports: [], calls: [], assignments: [], heritage: [], routes: [], fetchCalls: [], decoratorRoutes: [], toolDefs: [], ormQueries: [], constructorBindings: [], typeEnvBindings: [] };
24
24
  const total = files.length;
25
25
  // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
26
26
  const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
@@ -32,6 +32,10 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
32
32
  const allAssignments = [];
33
33
  const allHeritage = [];
34
34
  const allRoutes = [];
35
+ const allFetchCalls = [];
36
+ const allDecoratorRoutes = [];
37
+ const allToolDefs = [];
38
+ const allORMQueries = [];
35
39
  const allConstructorBindings = [];
36
40
  const allTypeEnvBindings = [];
37
41
  for (const result of chunkResults) {
@@ -60,6 +64,11 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
60
64
  allAssignments.push(...result.assignments);
61
65
  allHeritage.push(...result.heritage);
62
66
  allRoutes.push(...result.routes);
67
+ allFetchCalls.push(...result.fetchCalls);
68
+ allDecoratorRoutes.push(...result.decoratorRoutes);
69
+ allToolDefs.push(...result.toolDefs);
70
+ if (result.ormQueries)
71
+ allORMQueries.push(...result.ormQueries);
63
72
  allConstructorBindings.push(...result.constructorBindings);
64
73
  allTypeEnvBindings.push(...result.typeEnvBindings);
65
74
  }
@@ -78,17 +87,75 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
78
87
  }
79
88
  // Final progress
80
89
  onFileProgress?.(total, total, 'done');
81
- return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, constructorBindings: allConstructorBindings, typeEnvBindings: allTypeEnvBindings };
90
+ return { imports: allImports, calls: allCalls, assignments: allAssignments, heritage: allHeritage, routes: allRoutes, fetchCalls: allFetchCalls, decoratorRoutes: allDecoratorRoutes, toolDefs: allToolDefs, ormQueries: allORMQueries, constructorBindings: allConstructorBindings, typeEnvBindings: allTypeEnvBindings };
82
91
  };
83
92
  // ============================================================================
84
93
  // Sequential fallback (original implementation)
85
94
  // ============================================================================
95
+ // Inline caches to avoid repeated parent-walks per node (same pattern as parse-worker.ts).
96
+ // Keyed by tree-sitter node reference — cleared at the start of each file.
97
+ const classIdCache = new Map();
98
+ const exportCache = new Map();
99
+ const cachedFindEnclosingClassId = (node, filePath) => {
100
+ const cached = classIdCache.get(node);
101
+ if (cached !== undefined)
102
+ return cached;
103
+ const result = findEnclosingClassId(node, filePath);
104
+ classIdCache.set(node, result);
105
+ return result;
106
+ };
107
+ const cachedExportCheck = (checker, node, name) => {
108
+ const cached = exportCache.get(node);
109
+ if (cached !== undefined)
110
+ return cached;
111
+ const result = checker(node, name);
112
+ exportCache.set(node, result);
113
+ return result;
114
+ };
115
+ // FieldExtractor cache for sequential path — same pattern as parse-worker.ts
116
+ const seqFieldInfoCache = new Map();
117
+ function seqFindEnclosingClassNode(node) {
118
+ let current = node.parent;
119
+ while (current) {
120
+ if (CLASS_CONTAINER_TYPES.has(current.type))
121
+ return current;
122
+ current = current.parent;
123
+ }
124
+ return null;
125
+ }
126
+ /** Minimal no-op SymbolTable stub for FieldExtractorContext (sequential path has a real
127
+ * SymbolTable, but it's incomplete at this stage — use the stub for safety). */
128
+ const NOOP_SYMBOL_TABLE_SEQ = {
129
+ lookupExactAll: () => [],
130
+ lookupExact: () => undefined,
131
+ lookupExactFull: () => undefined,
132
+ };
133
+ function seqGetFieldInfo(classNode, provider, context) {
134
+ if (!provider.fieldExtractor)
135
+ return undefined;
136
+ const cacheKey = classNode.startIndex;
137
+ let cached = seqFieldInfoCache.get(cacheKey);
138
+ if (cached)
139
+ return cached;
140
+ const extracted = provider.fieldExtractor.extract(classNode, context);
141
+ if (!extracted?.fields?.length)
142
+ return undefined;
143
+ cached = new Map();
144
+ for (const field of extracted.fields)
145
+ cached.set(field.name, field);
146
+ seqFieldInfoCache.set(cacheKey, cached);
147
+ return cached;
148
+ }
86
149
  const processParsingSequential = async (graph, files, symbolTable, astCache, onFileProgress) => {
87
150
  const parser = await loadParser();
88
151
  const total = files.length;
89
152
  const skippedLanguages = new Map();
90
153
  for (let i = 0; i < files.length; i++) {
91
154
  const file = files[i];
155
+ // Reset memoization before each new file (node refs are per-tree)
156
+ classIdCache.clear();
157
+ exportCache.clear();
158
+ seqFieldInfoCache.clear();
92
159
  onFileProgress?.(i + 1, total, file.path);
93
160
  if (i % 20 === 0)
94
161
  await yieldToEventLoop();
@@ -118,7 +185,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
118
185
  continue;
119
186
  }
120
187
  astCache.set(file.path, tree);
121
- const queryString = LANGUAGE_QUERIES[language];
188
+ const provider = getProvider(language);
189
+ const queryString = provider.treeSitterQueries;
122
190
  if (!queryString) {
123
191
  continue;
124
192
  }
@@ -133,12 +201,14 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
133
201
  console.warn(`Query error for ${file.path}:`, queryError);
134
202
  continue;
135
203
  }
204
+ // Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor)
205
+ const typeEnv = provider.fieldExtractor ? buildTypeEnv(tree, language, { enclosingFunctionFinder: provider.enclosingFunctionFinder }) : null;
136
206
  matches.forEach(match => {
137
207
  const captureMap = {};
138
208
  match.captures.forEach(c => {
139
209
  captureMap[c.name] = c.node;
140
210
  });
141
- const nodeLabel = getLabelFromCaptures(captureMap, language);
211
+ const nodeLabel = getLabelFromCaptures(captureMap, provider);
142
212
  if (!nodeLabel)
143
213
  return;
144
214
  const nameNode = captureMap['name'];
@@ -160,7 +230,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
160
230
  // Language-specific return type fallback (e.g. Ruby YARD @return [Type])
161
231
  // Also upgrades uninformative AST types like PHP `array` with PHPDoc `@return User[]`
162
232
  if (methodSig && (!methodSig.returnType || methodSig.returnType === 'array' || methodSig.returnType === 'iterable') && definitionNode) {
163
- const tc = typeConfigs[language];
233
+ const tc = provider.typeConfig;
164
234
  if (tc?.extractReturnType) {
165
235
  const docReturn = tc.extractReturnType(definitionNode);
166
236
  if (docReturn)
@@ -176,7 +246,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
176
246
  startLine: definitionNodeForRange ? definitionNodeForRange.startPosition.row : startLine,
177
247
  endLine: definitionNodeForRange ? definitionNodeForRange.endPosition.row : startLine,
178
248
  language: language,
179
- isExported: isNodeExported(nameNode || definitionNodeForRange, nodeName, language),
249
+ isExported: cachedExportCheck(provider.exportChecker, nameNode || definitionNodeForRange, nodeName),
180
250
  ...(frameworkHint ? {
181
251
  astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
182
252
  astFrameworkReason: frameworkHint.reason,
@@ -193,11 +263,40 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
193
263
  // Compute enclosing class for Method/Constructor/Property/Function — used for both ownerId and HAS_METHOD
194
264
  // Function is included because Kotlin/Rust/Python capture class methods as Function nodes
195
265
  const needsOwner = nodeLabel === 'Method' || nodeLabel === 'Constructor' || nodeLabel === 'Property' || nodeLabel === 'Function';
196
- const enclosingClassId = needsOwner ? findEnclosingClassId(nameNode || definitionNodeForRange, file.path) : null;
197
- // Extract declared type for Property nodes (field/property type annotations)
198
- const declaredType = (nodeLabel === 'Property' && definitionNode)
199
- ? extractPropertyDeclaredType(definitionNode)
200
- : undefined;
266
+ const enclosingClassId = needsOwner ? cachedFindEnclosingClassId(nameNode || definitionNodeForRange, file.path) : null;
267
+ // Extract declared type and field metadata for Property nodes
268
+ let declaredType;
269
+ let seqVisibility;
270
+ let seqIsStatic;
271
+ let seqIsReadonly;
272
+ if (nodeLabel === 'Property' && definitionNode) {
273
+ // FieldExtractor is the single source of truth when available
274
+ if (provider.fieldExtractor && typeEnv) {
275
+ const classNode = seqFindEnclosingClassNode(definitionNode);
276
+ if (classNode) {
277
+ const fieldMap = seqGetFieldInfo(classNode, provider, {
278
+ typeEnv, symbolTable: NOOP_SYMBOL_TABLE_SEQ, filePath: file.path, language,
279
+ });
280
+ const info = fieldMap?.get(nodeName);
281
+ if (info) {
282
+ declaredType = info.type ?? undefined;
283
+ seqVisibility = info.visibility;
284
+ seqIsStatic = info.isStatic;
285
+ seqIsReadonly = info.isReadonly;
286
+ }
287
+ }
288
+ }
289
+ // All 14 languages register a FieldExtractor — no fallback needed.
290
+ }
291
+ // Apply field metadata to the graph node retroactively
292
+ if (seqVisibility !== undefined)
293
+ node.properties.visibility = seqVisibility;
294
+ if (seqIsStatic !== undefined)
295
+ node.properties.isStatic = seqIsStatic;
296
+ if (seqIsReadonly !== undefined)
297
+ node.properties.isReadonly = seqIsReadonly;
298
+ if (declaredType !== undefined)
299
+ node.properties.declaredType = declaredType;
201
300
  symbolTable.add(file.path, nodeName, nodeId, nodeLabel, {
202
301
  parameterCount: methodSig?.parameterCount,
203
302
  requiredParameterCount: methodSig?.requiredParameterCount,