@zuvia-software-solutions/code-mapper 1.4.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.
Files changed (213) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/ai-context.d.ts +19 -0
  3. package/dist/cli/ai-context.js +168 -0
  4. package/dist/cli/analyze.d.ts +7 -0
  5. package/dist/cli/analyze.js +325 -0
  6. package/dist/cli/augment.d.ts +7 -0
  7. package/dist/cli/augment.js +27 -0
  8. package/dist/cli/clean.d.ts +5 -0
  9. package/dist/cli/clean.js +56 -0
  10. package/dist/cli/eval-server.d.ts +25 -0
  11. package/dist/cli/eval-server.js +365 -0
  12. package/dist/cli/index.d.ts +6 -0
  13. package/dist/cli/index.js +102 -0
  14. package/dist/cli/lazy-action.d.ts +6 -0
  15. package/dist/cli/lazy-action.js +19 -0
  16. package/dist/cli/list.d.ts +2 -0
  17. package/dist/cli/list.js +27 -0
  18. package/dist/cli/mcp.d.ts +8 -0
  19. package/dist/cli/mcp.js +35 -0
  20. package/dist/cli/refresh.d.ts +12 -0
  21. package/dist/cli/refresh.js +165 -0
  22. package/dist/cli/serve.d.ts +5 -0
  23. package/dist/cli/serve.js +8 -0
  24. package/dist/cli/setup.d.ts +6 -0
  25. package/dist/cli/setup.js +218 -0
  26. package/dist/cli/status.d.ts +2 -0
  27. package/dist/cli/status.js +33 -0
  28. package/dist/cli/tool.d.ts +28 -0
  29. package/dist/cli/tool.js +87 -0
  30. package/dist/config/ignore-service.d.ts +32 -0
  31. package/dist/config/ignore-service.js +282 -0
  32. package/dist/config/supported-languages.d.ts +23 -0
  33. package/dist/config/supported-languages.js +52 -0
  34. package/dist/core/augmentation/engine.d.ts +22 -0
  35. package/dist/core/augmentation/engine.js +232 -0
  36. package/dist/core/embeddings/embedder.d.ts +35 -0
  37. package/dist/core/embeddings/embedder.js +171 -0
  38. package/dist/core/embeddings/embedding-pipeline.d.ts +41 -0
  39. package/dist/core/embeddings/embedding-pipeline.js +402 -0
  40. package/dist/core/embeddings/index.d.ts +5 -0
  41. package/dist/core/embeddings/index.js +6 -0
  42. package/dist/core/embeddings/text-generator.d.ts +20 -0
  43. package/dist/core/embeddings/text-generator.js +159 -0
  44. package/dist/core/embeddings/types.d.ts +60 -0
  45. package/dist/core/embeddings/types.js +23 -0
  46. package/dist/core/graph/graph.d.ts +4 -0
  47. package/dist/core/graph/graph.js +65 -0
  48. package/dist/core/graph/types.d.ts +69 -0
  49. package/dist/core/graph/types.js +3 -0
  50. package/dist/core/incremental/child-process.d.ts +8 -0
  51. package/dist/core/incremental/child-process.js +649 -0
  52. package/dist/core/incremental/refresh-coordinator.d.ts +32 -0
  53. package/dist/core/incremental/refresh-coordinator.js +147 -0
  54. package/dist/core/incremental/types.d.ts +78 -0
  55. package/dist/core/incremental/types.js +153 -0
  56. package/dist/core/incremental/watcher.d.ts +63 -0
  57. package/dist/core/incremental/watcher.js +338 -0
  58. package/dist/core/ingestion/ast-cache.d.ts +12 -0
  59. package/dist/core/ingestion/ast-cache.js +34 -0
  60. package/dist/core/ingestion/call-processor.d.ts +34 -0
  61. package/dist/core/ingestion/call-processor.js +937 -0
  62. package/dist/core/ingestion/call-routing.d.ts +40 -0
  63. package/dist/core/ingestion/call-routing.js +97 -0
  64. package/dist/core/ingestion/cluster-enricher.d.ts +30 -0
  65. package/dist/core/ingestion/cluster-enricher.js +151 -0
  66. package/dist/core/ingestion/community-processor.d.ts +26 -0
  67. package/dist/core/ingestion/community-processor.js +272 -0
  68. package/dist/core/ingestion/constants.d.ts +5 -0
  69. package/dist/core/ingestion/constants.js +8 -0
  70. package/dist/core/ingestion/entry-point-scoring.d.ts +23 -0
  71. package/dist/core/ingestion/entry-point-scoring.js +317 -0
  72. package/dist/core/ingestion/export-detection.d.ts +11 -0
  73. package/dist/core/ingestion/export-detection.js +203 -0
  74. package/dist/core/ingestion/filesystem-walker.d.ts +18 -0
  75. package/dist/core/ingestion/filesystem-walker.js +64 -0
  76. package/dist/core/ingestion/framework-detection.d.ts +42 -0
  77. package/dist/core/ingestion/framework-detection.js +405 -0
  78. package/dist/core/ingestion/heritage-processor.d.ts +15 -0
  79. package/dist/core/ingestion/heritage-processor.js +237 -0
  80. package/dist/core/ingestion/import-processor.d.ts +31 -0
  81. package/dist/core/ingestion/import-processor.js +416 -0
  82. package/dist/core/ingestion/language-config.d.ts +32 -0
  83. package/dist/core/ingestion/language-config.js +161 -0
  84. package/dist/core/ingestion/mro-processor.d.ts +32 -0
  85. package/dist/core/ingestion/mro-processor.js +343 -0
  86. package/dist/core/ingestion/named-binding-extraction.d.ts +51 -0
  87. package/dist/core/ingestion/named-binding-extraction.js +343 -0
  88. package/dist/core/ingestion/parsing-processor.d.ts +20 -0
  89. package/dist/core/ingestion/parsing-processor.js +282 -0
  90. package/dist/core/ingestion/pipeline.d.ts +3 -0
  91. package/dist/core/ingestion/pipeline.js +416 -0
  92. package/dist/core/ingestion/process-processor.d.ts +42 -0
  93. package/dist/core/ingestion/process-processor.js +357 -0
  94. package/dist/core/ingestion/resolution-context.d.ts +40 -0
  95. package/dist/core/ingestion/resolution-context.js +171 -0
  96. package/dist/core/ingestion/resolvers/csharp.d.ts +10 -0
  97. package/dist/core/ingestion/resolvers/csharp.js +101 -0
  98. package/dist/core/ingestion/resolvers/go.d.ts +8 -0
  99. package/dist/core/ingestion/resolvers/go.js +33 -0
  100. package/dist/core/ingestion/resolvers/index.d.ts +14 -0
  101. package/dist/core/ingestion/resolvers/index.js +10 -0
  102. package/dist/core/ingestion/resolvers/jvm.d.ts +9 -0
  103. package/dist/core/ingestion/resolvers/jvm.js +74 -0
  104. package/dist/core/ingestion/resolvers/php.d.ts +7 -0
  105. package/dist/core/ingestion/resolvers/php.js +30 -0
  106. package/dist/core/ingestion/resolvers/ruby.d.ts +9 -0
  107. package/dist/core/ingestion/resolvers/ruby.js +13 -0
  108. package/dist/core/ingestion/resolvers/rust.d.ts +5 -0
  109. package/dist/core/ingestion/resolvers/rust.js +62 -0
  110. package/dist/core/ingestion/resolvers/standard.d.ts +16 -0
  111. package/dist/core/ingestion/resolvers/standard.js +144 -0
  112. package/dist/core/ingestion/resolvers/utils.d.ts +18 -0
  113. package/dist/core/ingestion/resolvers/utils.js +113 -0
  114. package/dist/core/ingestion/structure-processor.d.ts +4 -0
  115. package/dist/core/ingestion/structure-processor.js +39 -0
  116. package/dist/core/ingestion/symbol-table.d.ts +34 -0
  117. package/dist/core/ingestion/symbol-table.js +48 -0
  118. package/dist/core/ingestion/tree-sitter-queries.d.ts +20 -0
  119. package/dist/core/ingestion/tree-sitter-queries.js +691 -0
  120. package/dist/core/ingestion/type-env.d.ts +52 -0
  121. package/dist/core/ingestion/type-env.js +349 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +4 -0
  123. package/dist/core/ingestion/type-extractors/c-cpp.js +214 -0
  124. package/dist/core/ingestion/type-extractors/csharp.d.ts +4 -0
  125. package/dist/core/ingestion/type-extractors/csharp.js +224 -0
  126. package/dist/core/ingestion/type-extractors/go.d.ts +4 -0
  127. package/dist/core/ingestion/type-extractors/go.js +261 -0
  128. package/dist/core/ingestion/type-extractors/index.d.ts +20 -0
  129. package/dist/core/ingestion/type-extractors/index.js +30 -0
  130. package/dist/core/ingestion/type-extractors/jvm.d.ts +5 -0
  131. package/dist/core/ingestion/type-extractors/jvm.js +386 -0
  132. package/dist/core/ingestion/type-extractors/php.d.ts +4 -0
  133. package/dist/core/ingestion/type-extractors/php.js +280 -0
  134. package/dist/core/ingestion/type-extractors/python.d.ts +4 -0
  135. package/dist/core/ingestion/type-extractors/python.js +175 -0
  136. package/dist/core/ingestion/type-extractors/ruby.d.ts +12 -0
  137. package/dist/core/ingestion/type-extractors/ruby.js +218 -0
  138. package/dist/core/ingestion/type-extractors/rust.d.ts +4 -0
  139. package/dist/core/ingestion/type-extractors/rust.js +290 -0
  140. package/dist/core/ingestion/type-extractors/shared.d.ts +81 -0
  141. package/dist/core/ingestion/type-extractors/shared.js +322 -0
  142. package/dist/core/ingestion/type-extractors/swift.d.ts +4 -0
  143. package/dist/core/ingestion/type-extractors/swift.js +140 -0
  144. package/dist/core/ingestion/type-extractors/types.d.ts +111 -0
  145. package/dist/core/ingestion/type-extractors/types.js +4 -0
  146. package/dist/core/ingestion/type-extractors/typescript.d.ts +4 -0
  147. package/dist/core/ingestion/type-extractors/typescript.js +227 -0
  148. package/dist/core/ingestion/utils.d.ts +73 -0
  149. package/dist/core/ingestion/utils.js +992 -0
  150. package/dist/core/ingestion/workers/parse-worker.d.ts +99 -0
  151. package/dist/core/ingestion/workers/parse-worker.js +1055 -0
  152. package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
  153. package/dist/core/ingestion/workers/worker-pool.js +123 -0
  154. package/dist/core/lbug/csv-generator.d.ts +28 -0
  155. package/dist/core/lbug/csv-generator.js +355 -0
  156. package/dist/core/lbug/lbug-adapter.d.ts +96 -0
  157. package/dist/core/lbug/lbug-adapter.js +753 -0
  158. package/dist/core/lbug/schema.d.ts +46 -0
  159. package/dist/core/lbug/schema.js +402 -0
  160. package/dist/core/search/bm25-index.d.ts +20 -0
  161. package/dist/core/search/bm25-index.js +123 -0
  162. package/dist/core/search/hybrid-search.d.ts +32 -0
  163. package/dist/core/search/hybrid-search.js +131 -0
  164. package/dist/core/search/query-cache.d.ts +18 -0
  165. package/dist/core/search/query-cache.js +47 -0
  166. package/dist/core/search/query-expansion.d.ts +19 -0
  167. package/dist/core/search/query-expansion.js +75 -0
  168. package/dist/core/search/reranker.d.ts +29 -0
  169. package/dist/core/search/reranker.js +122 -0
  170. package/dist/core/search/types.d.ts +154 -0
  171. package/dist/core/search/types.js +51 -0
  172. package/dist/core/semantic/tsgo-service.d.ts +67 -0
  173. package/dist/core/semantic/tsgo-service.js +355 -0
  174. package/dist/core/tree-sitter/parser-loader.d.ts +12 -0
  175. package/dist/core/tree-sitter/parser-loader.js +71 -0
  176. package/dist/lib/memory-guard.d.ts +35 -0
  177. package/dist/lib/memory-guard.js +70 -0
  178. package/dist/lib/utils.d.ts +3 -0
  179. package/dist/lib/utils.js +6 -0
  180. package/dist/mcp/compatible-stdio-transport.d.ts +32 -0
  181. package/dist/mcp/compatible-stdio-transport.js +209 -0
  182. package/dist/mcp/core/embedder.d.ts +24 -0
  183. package/dist/mcp/core/embedder.js +168 -0
  184. package/dist/mcp/core/lbug-adapter.d.ts +29 -0
  185. package/dist/mcp/core/lbug-adapter.js +330 -0
  186. package/dist/mcp/local/local-backend.d.ts +188 -0
  187. package/dist/mcp/local/local-backend.js +2759 -0
  188. package/dist/mcp/resources.d.ts +22 -0
  189. package/dist/mcp/resources.js +379 -0
  190. package/dist/mcp/server.d.ts +10 -0
  191. package/dist/mcp/server.js +217 -0
  192. package/dist/mcp/staleness.d.ts +10 -0
  193. package/dist/mcp/staleness.js +25 -0
  194. package/dist/mcp/tools.d.ts +21 -0
  195. package/dist/mcp/tools.js +202 -0
  196. package/dist/server/api.d.ts +5 -0
  197. package/dist/server/api.js +340 -0
  198. package/dist/server/mcp-http.d.ts +7 -0
  199. package/dist/server/mcp-http.js +95 -0
  200. package/dist/storage/git.d.ts +6 -0
  201. package/dist/storage/git.js +35 -0
  202. package/dist/storage/repo-manager.d.ts +87 -0
  203. package/dist/storage/repo-manager.js +249 -0
  204. package/dist/types/pipeline.d.ts +35 -0
  205. package/dist/types/pipeline.js +20 -0
  206. package/hooks/claude/code-mapper-hook.cjs +238 -0
  207. package/hooks/claude/pre-tool-use.sh +79 -0
  208. package/hooks/claude/session-start.sh +42 -0
  209. package/models/mlx-embedder.py +185 -0
  210. package/package.json +100 -0
  211. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  212. package/vendor/leiden/index.cjs +355 -0
  213. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @file Per-file scoped type environment for receiver-type resolution
3
+ * @description Maps (scope, variableName) -> typeName using a three-tier strategy:
4
+ * Tier 0: explicit type annotations, Tier 1: constructor inference,
5
+ * Tier 2: single-pass assignment chain propagation
6
+ */
7
+ import type { SyntaxNode } from './utils.js';
8
+ import { SupportedLanguages } from '../../config/supported-languages.js';
9
+ import type { SymbolTable } from './symbol-table.js';
10
+ /**
11
+ * Per-file scoped type environment: maps (scope, variableName) -> typeName
12
+ *
13
+ * Scope-aware: function-local variables are keyed by function name,
14
+ * file-level variables use the '' (empty string) scope.
15
+ * Built once per file, used for receiver resolution, then discarded
16
+ */
17
+ export type TypeEnv = Map<string, Map<string, string>>;
18
+ /**
19
+ * Per-file type environment with receiver resolution
20
+ *
21
+ * Built once per file via `buildTypeEnv`, used for receiver-type filtering,
22
+ * then discarded. Encapsulates scope-aware type lookup and self/this/super
23
+ * AST resolution behind a single `.lookup()` method
24
+ */
25
+ export interface TypeEnvironment {
26
+ /** Look up a variable's resolved type, with self/this/super AST resolution */
27
+ lookup(varName: string, callNode: SyntaxNode): string | undefined;
28
+ /** Unverified cross-file constructor bindings for SymbolTable verification */
29
+ readonly constructorBindings: readonly ConstructorBinding[];
30
+ /** Raw per-scope type bindings (for testing and debugging) */
31
+ readonly env: TypeEnv;
32
+ }
33
+ /**
34
+ * Build a TypeEnvironment from a tree-sitter AST in a single pass
35
+ *
36
+ * Collects class/struct names, type bindings, and constructor bindings that
37
+ * couldn't be resolved locally. When a symbolTable is provided, cross-project
38
+ * class names are available for constructor inference
39
+ */
40
+ export declare const buildTypeEnv: (tree: {
41
+ rootNode: SyntaxNode;
42
+ }, language: SupportedLanguages, symbolTable?: SymbolTable) => TypeEnvironment;
43
+ /**
44
+ * Unverified constructor binding: a `val x = Callee()` pattern where
45
+ * the callee class is in another file. Caller must verify against SymbolTable
46
+ */
47
+ export interface ConstructorBinding {
48
+ scope: string;
49
+ varName: string;
50
+ calleeName: string;
51
+ receiverClassName?: string;
52
+ }
@@ -0,0 +1,349 @@
1
+ // code-mapper/src/core/ingestion/type-env.ts
2
+ /**
3
+ * @file Per-file scoped type environment for receiver-type resolution
4
+ * @description Maps (scope, variableName) -> typeName using a three-tier strategy:
5
+ * Tier 0: explicit type annotations, Tier 1: constructor inference,
6
+ * Tier 2: single-pass assignment chain propagation
7
+ */
8
+ import { FUNCTION_NODE_TYPES, extractFunctionName, CLASS_CONTAINER_TYPES } from './utils.js';
9
+ import { typeConfigs, TYPED_PARAMETER_TYPES } from './type-extractors/index.js';
10
+ import { extractSimpleTypeName, stripNullable } from './type-extractors/shared.js';
11
+ // File-level scope key
12
+ const FILE_SCOPE = '';
13
+ // Fallback for languages where class names aren't in a 'name' field (e.g. Kotlin uses type_identifier)
14
+ const findTypeIdentifierChild = (node) => {
15
+ for (let i = 0; i < node.childCount; i++) {
16
+ const child = node.child(i);
17
+ if (child && child.type === 'type_identifier')
18
+ return child;
19
+ }
20
+ return null;
21
+ };
22
+ // Shared lookup implementation
23
+ const lookupInEnv = (env, varName, callNode) => {
24
+ // self/this receiver: resolve to enclosing class name via AST walk
25
+ if (varName === 'self' || varName === 'this' || varName === '$this') {
26
+ return findEnclosingClassName(callNode);
27
+ }
28
+ // super/base/parent receiver: walk up to enclosing class, extract superclass from heritage
29
+ if (varName === 'super' || varName === 'base' || varName === 'parent') {
30
+ return findEnclosingParentClassName(callNode);
31
+ }
32
+ // Determine enclosing function scope
33
+ const scopeKey = findEnclosingScopeKey(callNode);
34
+ // Try function-local scope first
35
+ if (scopeKey) {
36
+ const scopeEnv = env.get(scopeKey);
37
+ if (scopeEnv) {
38
+ const result = scopeEnv.get(varName);
39
+ if (result)
40
+ return stripNullable(result);
41
+ }
42
+ }
43
+ // Fall back to file-level scope
44
+ const fileEnv = env.get(FILE_SCOPE);
45
+ const raw = fileEnv?.get(varName);
46
+ return raw ? stripNullable(raw) : undefined;
47
+ };
48
+ /** Walk up AST to find the enclosing class/module name for self/this resolution */
49
+ const findEnclosingClassName = (node) => {
50
+ let current = node.parent;
51
+ while (current) {
52
+ if (CLASS_CONTAINER_TYPES.has(current.type)) {
53
+ const nameNode = current.childForFieldName('name')
54
+ ?? findTypeIdentifierChild(current);
55
+ if (nameNode)
56
+ return nameNode.text;
57
+ }
58
+ current = current.parent;
59
+ }
60
+ return undefined;
61
+ };
62
+ /** Walk up AST to find enclosing class and extract its parent class name for super/base/parent */
63
+ const findEnclosingParentClassName = (node) => {
64
+ let current = node.parent;
65
+ while (current) {
66
+ if (CLASS_CONTAINER_TYPES.has(current.type)) {
67
+ return extractParentClassFromNode(current);
68
+ }
69
+ current = current.parent;
70
+ }
71
+ return undefined;
72
+ };
73
+ /** Extract the parent/superclass name from a class declaration AST node */
74
+ const extractParentClassFromNode = (classNode) => {
75
+ // 1. Named fields: Java (superclass), Ruby (superclass), Python (superclasses)
76
+ const superclassNode = classNode.childForFieldName('superclass');
77
+ if (superclassNode) {
78
+ // Java: superclass > type_identifier or generic_type, Ruby: superclass > constant
79
+ const inner = superclassNode.childForFieldName('type')
80
+ ?? superclassNode.firstNamedChild
81
+ ?? superclassNode;
82
+ return extractSimpleTypeName(inner) ?? inner.text;
83
+ }
84
+ const superclassesNode = classNode.childForFieldName('superclasses');
85
+ if (superclassesNode) {
86
+ // Python: argument_list with identifiers or attribute nodes (e.g. models.Model)
87
+ const first = superclassesNode.firstNamedChild;
88
+ if (first)
89
+ return extractSimpleTypeName(first) ?? first.text;
90
+ }
91
+ // 2. Unnamed children: walk class node's children looking for heritage nodes
92
+ for (let i = 0; i < classNode.childCount; i++) {
93
+ const child = classNode.child(i);
94
+ if (!child)
95
+ continue;
96
+ switch (child.type) {
97
+ // TypeScript: class_heritage > extends_clause > type_identifier
98
+ // JavaScript: class_heritage > identifier (no extends_clause wrapper)
99
+ case 'class_heritage': {
100
+ for (let j = 0; j < child.childCount; j++) {
101
+ const clause = child.child(j);
102
+ if (clause?.type === 'extends_clause') {
103
+ const typeNode = clause.firstNamedChild;
104
+ if (typeNode)
105
+ return extractSimpleTypeName(typeNode) ?? typeNode.text;
106
+ }
107
+ // JS: direct identifier child (no extends_clause wrapper)
108
+ if (clause?.type === 'identifier' || clause?.type === 'type_identifier') {
109
+ return clause.text;
110
+ }
111
+ }
112
+ break;
113
+ }
114
+ // C#: base_list > identifier or generic_name > identifier
115
+ case 'base_list': {
116
+ const first = child.firstNamedChild;
117
+ if (first) {
118
+ // generic_name wraps the identifier: BaseClass<T>
119
+ if (first.type === 'generic_name') {
120
+ const inner = first.childForFieldName('name') ?? first.firstNamedChild;
121
+ if (inner)
122
+ return inner.text;
123
+ }
124
+ return first.text;
125
+ }
126
+ break;
127
+ }
128
+ // PHP: base_clause > name
129
+ case 'base_clause': {
130
+ const name = child.firstNamedChild;
131
+ if (name)
132
+ return name.text;
133
+ break;
134
+ }
135
+ // C++: base_class_clause > type_identifier (with optional access_specifier before it)
136
+ case 'base_class_clause': {
137
+ for (let j = 0; j < child.childCount; j++) {
138
+ const inner = child.child(j);
139
+ if (inner?.type === 'type_identifier')
140
+ return inner.text;
141
+ }
142
+ break;
143
+ }
144
+ // Kotlin: delegation_specifier > constructor_invocation > user_type > type_identifier
145
+ case 'delegation_specifier': {
146
+ const delegate = child.firstNamedChild;
147
+ if (delegate?.type === 'constructor_invocation') {
148
+ const userType = delegate.firstNamedChild;
149
+ if (userType?.type === 'user_type') {
150
+ const typeId = userType.firstNamedChild;
151
+ if (typeId)
152
+ return typeId.text;
153
+ }
154
+ }
155
+ // Also handle plain user_type (interface conformance without parentheses)
156
+ if (delegate?.type === 'user_type') {
157
+ const typeId = delegate.firstNamedChild;
158
+ if (typeId)
159
+ return typeId.text;
160
+ }
161
+ break;
162
+ }
163
+ // Swift: inheritance_specifier > user_type > type_identifier
164
+ case 'inheritance_specifier': {
165
+ const userType = child.childForFieldName('inherits_from') ?? child.firstNamedChild;
166
+ if (userType?.type === 'user_type') {
167
+ const typeId = userType.firstNamedChild;
168
+ if (typeId)
169
+ return typeId.text;
170
+ }
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ return undefined;
176
+ };
177
+ /** Find the enclosing function name for scope lookup */
178
+ const findEnclosingScopeKey = (node) => {
179
+ let current = node.parent;
180
+ while (current) {
181
+ if (FUNCTION_NODE_TYPES.has(current.type)) {
182
+ const { funcName } = extractFunctionName(current);
183
+ if (funcName)
184
+ return `${funcName}@${current.startIndex}`;
185
+ }
186
+ current = current.parent;
187
+ }
188
+ return undefined;
189
+ };
190
+ /**
191
+ * Create a class name lookup backed by local AST names + SymbolTable global index
192
+ *
193
+ * Distinguishes constructor calls from function calls (e.g. Kotlin `User()` vs `getUser()`)
194
+ * using cross-file type information. Results are memoized
195
+ */
196
+ const createClassNameLookup = (localNames, symbolTable) => {
197
+ if (!symbolTable)
198
+ return localNames;
199
+ const memo = new Map();
200
+ return {
201
+ has(name) {
202
+ if (localNames.has(name))
203
+ return true;
204
+ const cached = memo.get(name);
205
+ if (cached !== undefined)
206
+ return cached;
207
+ const result = symbolTable.lookupFuzzy(name).some(def => def.type === 'Class' || def.type === 'Enum' || def.type === 'Struct');
208
+ memo.set(name, result);
209
+ return result;
210
+ },
211
+ };
212
+ };
213
+ /**
214
+ * Build a TypeEnvironment from a tree-sitter AST in a single pass
215
+ *
216
+ * Collects class/struct names, type bindings, and constructor bindings that
217
+ * couldn't be resolved locally. When a symbolTable is provided, cross-project
218
+ * class names are available for constructor inference
219
+ */
220
+ export const buildTypeEnv = (tree, language, symbolTable) => {
221
+ const env = new Map();
222
+ const localClassNames = new Set();
223
+ const classNames = createClassNameLookup(localClassNames, symbolTable);
224
+ const config = typeConfigs[language];
225
+ const bindings = [];
226
+ const pendingAssignments = [];
227
+ // Maps `scope\0varName` -> type annotation AST node from the original declaration
228
+ // Allows pattern extractors to navigate back to generic type arguments
229
+ const declarationTypeNodes = new Map();
230
+ /**
231
+ * Extract a (variableName -> typeName) binding from a single AST node
232
+ *
233
+ * Tier 0: explicit type annotations, Tier 1: constructor-call inference
234
+ * Also populates declarationTypeNodes for pattern extractor access to generic args
235
+ */
236
+ const extractTypeBinding = (node, scopeEnv, scope) => {
237
+ // Fast path: eliminates 90%+ of calls before language dispatch
238
+ if (TYPED_PARAMETER_TYPES.has(node.type)) {
239
+ const keysBefore = new Set(scopeEnv.keys());
240
+ config.extractParameter(node, scopeEnv);
241
+ // Capture the type node for newly introduced parameter bindings
242
+ const typeNode = node.childForFieldName('type');
243
+ if (typeNode) {
244
+ for (const varName of scopeEnv.keys()) {
245
+ if (!keysBefore.has(varName)) {
246
+ declarationTypeNodes.set(`${scope}\0${varName}`, typeNode);
247
+ }
248
+ }
249
+ }
250
+ return;
251
+ }
252
+ // For-each loop variable bindings (Java/C#/Kotlin)
253
+ // Checked before declarationNodeTypes — loop variables are not declarations
254
+ if (config.forLoopNodeTypes?.has(node.type)) {
255
+ config.extractForLoopBinding?.(node, scopeEnv);
256
+ return;
257
+ }
258
+ if (config.declarationNodeTypes.has(node.type)) {
259
+ const keysBefore = new Set(scopeEnv.keys());
260
+ config.extractDeclaration(node, scopeEnv);
261
+ // Capture type annotation AST node for newly introduced bindings
262
+ // Only declarations with an explicit 'type' field are recorded
263
+ const typeNode = node.childForFieldName('type');
264
+ if (typeNode) {
265
+ for (const varName of scopeEnv.keys()) {
266
+ if (!keysBefore.has(varName)) {
267
+ declarationTypeNodes.set(`${scope}\0${varName}`, typeNode);
268
+ }
269
+ }
270
+ }
271
+ // Tier 1: constructor-call inference as fallback
272
+ // Each language's extractInitializer skips declarators with explicit annotations
273
+ if (config.extractInitializer) {
274
+ config.extractInitializer(node, scopeEnv, classNames);
275
+ }
276
+ }
277
+ };
278
+ const walk = (node, currentScope) => {
279
+ // Collect class/struct names for constructor vs function call disambiguation
280
+ // Currently only C++ uses local names; other languages rely on the SymbolTable
281
+ if (CLASS_CONTAINER_TYPES.has(node.type)) {
282
+ // Most languages use 'name' field; Kotlin uses a type_identifier child instead
283
+ const nameNode = node.childForFieldName('name')
284
+ ?? findTypeIdentifierChild(node);
285
+ if (nameNode)
286
+ localClassNames.add(nameNode.text);
287
+ }
288
+ // Detect scope boundaries (function/method definitions)
289
+ let scope = currentScope;
290
+ if (FUNCTION_NODE_TYPES.has(node.type)) {
291
+ const { funcName } = extractFunctionName(node);
292
+ if (funcName)
293
+ scope = `${funcName}@${node.startIndex}`;
294
+ }
295
+ // Get or create the sub-map for this scope
296
+ if (!env.has(scope))
297
+ env.set(scope, new Map());
298
+ const scopeEnv = env.get(scope);
299
+ extractTypeBinding(node, scopeEnv, scope);
300
+ // Pattern binding extraction: introduces new typed variables via pattern matching
301
+ // (e.g. `if let Some(x) = opt`, `x instanceof T t`)
302
+ // Runs after Tier 0/1 so scopeEnv already has the source variable's type
303
+ if (config.extractPatternBinding) {
304
+ const patternBinding = config.extractPatternBinding(node, scopeEnv, declarationTypeNodes, scope);
305
+ if (patternBinding && !scopeEnv.has(patternBinding.varName)) {
306
+ scopeEnv.set(patternBinding.varName, patternBinding.typeName);
307
+ }
308
+ }
309
+ // Tier 2: collect plain-identifier RHS assignments for post-walk propagation
310
+ // Delegates to per-language extractPendingAssignment (AST shapes vary by language)
311
+ if (config.extractPendingAssignment && config.declarationNodeTypes.has(node.type)) {
312
+ const pending = config.extractPendingAssignment(node, scopeEnv);
313
+ if (pending) {
314
+ pendingAssignments.push({ scope, ...pending });
315
+ }
316
+ }
317
+ // Scan for constructor bindings that couldn't be resolved locally
318
+ if (config.scanConstructorBinding) {
319
+ const result = config.scanConstructorBinding(node);
320
+ if (result && !scopeEnv.has(result.varName)) {
321
+ bindings.push({ scope, ...result });
322
+ }
323
+ }
324
+ // Recurse into children
325
+ for (let i = 0; i < node.childCount; i++) {
326
+ const child = node.child(i);
327
+ if (child)
328
+ walk(child, scope);
329
+ }
330
+ };
331
+ walk(tree.rootNode, FILE_SCOPE);
332
+ // Tier 2: single-pass assignment chain propagation in source order
333
+ // Resolves `const b = a` where `a` has a known type from Tier 0/1
334
+ // No fixpoint iteration — covers 95%+ of real-world patterns
335
+ for (const { scope, lhs, rhs } of pendingAssignments) {
336
+ const scopeEnv = env.get(scope);
337
+ if (!scopeEnv || scopeEnv.has(lhs))
338
+ continue;
339
+ const rhsType = scopeEnv.get(rhs) ?? env.get(FILE_SCOPE)?.get(rhs);
340
+ if (rhsType) {
341
+ scopeEnv.set(lhs, rhsType);
342
+ }
343
+ }
344
+ return {
345
+ lookup: (varName, callNode) => lookupInEnv(env, varName, callNode),
346
+ constructorBindings: bindings,
347
+ env,
348
+ };
349
+ };
@@ -0,0 +1,4 @@
1
+ /** @file c-cpp.ts
2
+ * @description Type extraction for C and C++ (typed declarations, auto inference, brace initialization) */
3
+ import type { LanguageTypeConfig } from './types.js';
4
+ export declare const typeConfig: LanguageTypeConfig;
@@ -0,0 +1,214 @@
1
+ // code-mapper/src/core/ingestion/type-extractors/c-cpp.ts
2
+ /** @file c-cpp.ts
3
+ * @description Type extraction for C and C++ (typed declarations, auto inference, brace initialization) */
4
+ import { extractSimpleTypeName, extractVarName } from './shared.js';
5
+ const DECLARATION_NODE_TYPES = new Set([
6
+ 'declaration',
7
+ 'for_range_loop',
8
+ ]);
9
+ // C++: Type x = ...; Type* x; Type& x;
10
+ const extractDeclaration = (node, env) => {
11
+ const typeNode = node.childForFieldName('type');
12
+ if (!typeNode)
13
+ return;
14
+ const typeName = extractSimpleTypeName(typeNode);
15
+ if (!typeName)
16
+ return;
17
+ const declarator = node.childForFieldName('declarator');
18
+ if (!declarator)
19
+ return;
20
+ // init_declarator: Type x = value
21
+ const nameNode = declarator.type === 'init_declarator'
22
+ ? declarator.childForFieldName('declarator')
23
+ : declarator;
24
+ if (!nameNode)
25
+ return;
26
+ // Handle pointer/reference declarators
27
+ const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
28
+ ? nameNode.firstNamedChild
29
+ : nameNode;
30
+ if (!finalName)
31
+ return;
32
+ const varName = extractVarName(finalName);
33
+ if (varName)
34
+ env.set(varName, typeName);
35
+ };
36
+ // C++: auto x = new User(); auto x = User()
37
+ const extractInitializer = (node, env, classNames) => {
38
+ const typeNode = node.childForFieldName('type');
39
+ if (!typeNode)
40
+ return;
41
+ // Only handle auto/placeholder -- typed declarations are handled by extractDeclaration
42
+ const typeText = typeNode.text;
43
+ if (typeText !== 'auto' &&
44
+ typeText !== 'decltype(auto)' &&
45
+ typeNode.type !== 'placeholder_type_specifier')
46
+ return;
47
+ const declarator = node.childForFieldName('declarator');
48
+ if (!declarator)
49
+ return;
50
+ // Must be an init_declarator (i.e., has an initializer value)
51
+ if (declarator.type !== 'init_declarator')
52
+ return;
53
+ const value = declarator.childForFieldName('value');
54
+ if (!value)
55
+ return;
56
+ // Resolve the variable name, unwrapping pointer/reference declarators
57
+ const nameNode = declarator.childForFieldName('declarator');
58
+ if (!nameNode)
59
+ return;
60
+ const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
61
+ ? nameNode.firstNamedChild
62
+ : nameNode;
63
+ if (!finalName)
64
+ return;
65
+ const varName = extractVarName(finalName);
66
+ if (!varName)
67
+ return;
68
+ // auto x = new User() -- new_expression
69
+ if (value.type === 'new_expression') {
70
+ const ctorType = value.childForFieldName('type');
71
+ if (ctorType) {
72
+ const typeName = extractSimpleTypeName(ctorType);
73
+ if (typeName)
74
+ env.set(varName, typeName);
75
+ }
76
+ return;
77
+ }
78
+ // auto x = User() -- call_expression where function is a type name
79
+ // tree-sitter-cpp may parse the constructor name as type_identifier or identifier
80
+ // For plain identifiers, verify against known class names from the file's AST
81
+ // to distinguish constructor calls (User()) from function calls (getUser())
82
+ if (value.type === 'call_expression') {
83
+ const func = value.childForFieldName('function');
84
+ if (!func)
85
+ return;
86
+ if (func.type === 'type_identifier') {
87
+ const typeName = func.text;
88
+ if (typeName)
89
+ env.set(varName, typeName);
90
+ }
91
+ else if (func.type === 'identifier') {
92
+ const text = func.text;
93
+ if (text && classNames.has(text))
94
+ env.set(varName, text);
95
+ }
96
+ return;
97
+ }
98
+ // auto x = User{} -- compound_literal_expression (brace initialization)
99
+ // AST: compound_literal_expression > type_identifier + initializer_list
100
+ if (value.type === 'compound_literal_expression') {
101
+ const typeId = value.firstNamedChild;
102
+ const typeName = typeId ? extractSimpleTypeName(typeId) : undefined;
103
+ if (typeName)
104
+ env.set(varName, typeName);
105
+ }
106
+ };
107
+ // C/C++: parameter_declaration -> type declarator
108
+ const extractParameter = (node, env) => {
109
+ let nameNode = null;
110
+ let typeNode = null;
111
+ if (node.type === 'parameter_declaration') {
112
+ typeNode = node.childForFieldName('type');
113
+ const declarator = node.childForFieldName('declarator');
114
+ if (declarator) {
115
+ nameNode = declarator.type === 'pointer_declarator' || declarator.type === 'reference_declarator'
116
+ ? declarator.firstNamedChild
117
+ : declarator;
118
+ }
119
+ }
120
+ else {
121
+ nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
122
+ typeNode = node.childForFieldName('type');
123
+ }
124
+ if (!nameNode || !typeNode)
125
+ return;
126
+ const varName = extractVarName(nameNode);
127
+ const typeName = extractSimpleTypeName(typeNode);
128
+ if (varName && typeName)
129
+ env.set(varName, typeName);
130
+ };
131
+ // C/C++: auto x = User() where function is an identifier (not type_identifier)
132
+ const scanConstructorBinding = (node) => {
133
+ if (node.type !== 'declaration')
134
+ return undefined;
135
+ const typeNode = node.childForFieldName('type');
136
+ if (!typeNode)
137
+ return undefined;
138
+ const typeText = typeNode.text;
139
+ if (typeText !== 'auto' && typeText !== 'decltype(auto)' && typeNode.type !== 'placeholder_type_specifier')
140
+ return undefined;
141
+ const declarator = node.childForFieldName('declarator');
142
+ if (!declarator || declarator.type !== 'init_declarator')
143
+ return undefined;
144
+ const value = declarator.childForFieldName('value');
145
+ if (!value || value.type !== 'call_expression')
146
+ return undefined;
147
+ const func = value.childForFieldName('function');
148
+ if (!func)
149
+ return undefined;
150
+ if (func.type === 'qualified_identifier' || func.type === 'scoped_identifier') {
151
+ const last = func.lastNamedChild;
152
+ if (!last)
153
+ return undefined;
154
+ const nameNode = declarator.childForFieldName('declarator');
155
+ if (!nameNode)
156
+ return undefined;
157
+ const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
158
+ ? nameNode.firstNamedChild : nameNode;
159
+ if (!finalName)
160
+ return undefined;
161
+ return { varName: finalName.text, calleeName: last.text };
162
+ }
163
+ if (func.type !== 'identifier')
164
+ return undefined;
165
+ const nameNode = declarator.childForFieldName('declarator');
166
+ if (!nameNode)
167
+ return undefined;
168
+ const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
169
+ ? nameNode.firstNamedChild : nameNode;
170
+ if (!finalName)
171
+ return undefined;
172
+ const varName = finalName.text;
173
+ if (!varName)
174
+ return undefined;
175
+ return { varName, calleeName: func.text };
176
+ };
177
+ // C++: auto alias = user -> declaration with auto type + init_declarator where value is identifier
178
+ const extractPendingAssignment = (node, scopeEnv) => {
179
+ if (node.type !== 'declaration')
180
+ return undefined;
181
+ const typeNode = node.childForFieldName('type');
182
+ if (!typeNode)
183
+ return undefined;
184
+ // Only handle auto -- typed declarations already resolved by extractDeclaration
185
+ const typeText = typeNode.text;
186
+ if (typeText !== 'auto' && typeText !== 'decltype(auto)'
187
+ && typeNode.type !== 'placeholder_type_specifier')
188
+ return undefined;
189
+ const declarator = node.childForFieldName('declarator');
190
+ if (!declarator || declarator.type !== 'init_declarator')
191
+ return undefined;
192
+ const value = declarator.childForFieldName('value');
193
+ if (!value || value.type !== 'identifier')
194
+ return undefined;
195
+ const nameNode = declarator.childForFieldName('declarator');
196
+ if (!nameNode)
197
+ return undefined;
198
+ const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
199
+ ? nameNode.firstNamedChild : nameNode;
200
+ if (!finalName)
201
+ return undefined;
202
+ const lhs = extractVarName(finalName);
203
+ if (!lhs || scopeEnv.has(lhs))
204
+ return undefined;
205
+ return { lhs, rhs: value.text };
206
+ };
207
+ export const typeConfig = {
208
+ declarationNodeTypes: DECLARATION_NODE_TYPES,
209
+ extractDeclaration,
210
+ extractParameter,
211
+ extractInitializer,
212
+ scanConstructorBinding,
213
+ extractPendingAssignment,
214
+ };
@@ -0,0 +1,4 @@
1
+ /** @file csharp.ts
2
+ * @description Type extraction for C# (typed declarations, var inference, pattern matching) */
3
+ import type { LanguageTypeConfig } from './types.js';
4
+ export declare const typeConfig: LanguageTypeConfig;