@colbymchenry/codegraph-darwin-arm64 0.9.5 → 0.9.6

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 (97) hide show
  1. package/lib/dist/db/queries.d.ts +1 -0
  2. package/lib/dist/db/queries.d.ts.map +1 -1
  3. package/lib/dist/db/queries.js +31 -3
  4. package/lib/dist/db/queries.js.map +1 -1
  5. package/lib/dist/extraction/grammars.d.ts +1 -1
  6. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  7. package/lib/dist/extraction/grammars.js +15 -0
  8. package/lib/dist/extraction/grammars.js.map +1 -1
  9. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  10. package/lib/dist/extraction/languages/c-cpp.js +45 -0
  11. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  12. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
  13. package/lib/dist/extraction/languages/csharp.js +2 -1
  14. package/lib/dist/extraction/languages/csharp.js.map +1 -1
  15. package/lib/dist/extraction/languages/go.d.ts.map +1 -1
  16. package/lib/dist/extraction/languages/go.js +12 -0
  17. package/lib/dist/extraction/languages/go.js.map +1 -1
  18. package/lib/dist/extraction/mybatis-extractor.d.ts +48 -0
  19. package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  20. package/lib/dist/extraction/mybatis-extractor.js +198 -0
  21. package/lib/dist/extraction/mybatis-extractor.js.map +1 -0
  22. package/lib/dist/extraction/tree-sitter.d.ts +33 -0
  23. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  24. package/lib/dist/extraction/tree-sitter.js +269 -9
  25. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  26. package/lib/dist/index.d.ts +1 -1
  27. package/lib/dist/index.d.ts.map +1 -1
  28. package/lib/dist/index.js +20 -1
  29. package/lib/dist/index.js.map +1 -1
  30. package/lib/dist/installer/index.d.ts +1 -1
  31. package/lib/dist/installer/index.js +3 -3
  32. package/lib/dist/installer/index.js.map +1 -1
  33. package/lib/dist/installer/targets/antigravity.d.ts +57 -0
  34. package/lib/dist/installer/targets/antigravity.d.ts.map +1 -0
  35. package/lib/dist/installer/targets/antigravity.js +307 -0
  36. package/lib/dist/installer/targets/antigravity.js.map +1 -0
  37. package/lib/dist/installer/targets/gemini.d.ts +26 -0
  38. package/lib/dist/installer/targets/gemini.d.ts.map +1 -0
  39. package/lib/dist/installer/targets/gemini.js +165 -0
  40. package/lib/dist/installer/targets/gemini.js.map +1 -0
  41. package/lib/dist/installer/targets/hermes.d.ts.map +1 -1
  42. package/lib/dist/installer/targets/hermes.js +57 -3
  43. package/lib/dist/installer/targets/hermes.js.map +1 -1
  44. package/lib/dist/installer/targets/kiro.d.ts +27 -0
  45. package/lib/dist/installer/targets/kiro.d.ts.map +1 -0
  46. package/lib/dist/installer/targets/kiro.js +196 -0
  47. package/lib/dist/installer/targets/kiro.js.map +1 -0
  48. package/lib/dist/installer/targets/registry.d.ts.map +1 -1
  49. package/lib/dist/installer/targets/registry.js +6 -0
  50. package/lib/dist/installer/targets/registry.js.map +1 -1
  51. package/lib/dist/installer/targets/types.d.ts +1 -1
  52. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  53. package/lib/dist/mcp/tools.d.ts.map +1 -1
  54. package/lib/dist/mcp/tools.js +14 -3
  55. package/lib/dist/mcp/tools.js.map +1 -1
  56. package/lib/dist/resolution/callback-synthesizer.d.ts +2 -2
  57. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  58. package/lib/dist/resolution/callback-synthesizer.js +79 -2
  59. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  60. package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
  61. package/lib/dist/resolution/frameworks/java.js +270 -1
  62. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  63. package/lib/dist/resolution/frameworks/nestjs.d.ts.map +1 -1
  64. package/lib/dist/resolution/frameworks/nestjs.js +324 -0
  65. package/lib/dist/resolution/frameworks/nestjs.js.map +1 -1
  66. package/lib/dist/resolution/go-module.d.ts +26 -0
  67. package/lib/dist/resolution/go-module.d.ts.map +1 -0
  68. package/lib/dist/resolution/go-module.js +78 -0
  69. package/lib/dist/resolution/go-module.js.map +1 -0
  70. package/lib/dist/resolution/import-resolver.d.ts +18 -0
  71. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  72. package/lib/dist/resolution/import-resolver.js +537 -4
  73. package/lib/dist/resolution/import-resolver.js.map +1 -1
  74. package/lib/dist/resolution/index.d.ts +10 -0
  75. package/lib/dist/resolution/index.d.ts.map +1 -1
  76. package/lib/dist/resolution/index.js +102 -0
  77. package/lib/dist/resolution/index.js.map +1 -1
  78. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  79. package/lib/dist/resolution/name-matcher.js +212 -0
  80. package/lib/dist/resolution/name-matcher.js.map +1 -1
  81. package/lib/dist/resolution/types.d.ts +29 -0
  82. package/lib/dist/resolution/types.d.ts.map +1 -1
  83. package/lib/dist/sync/index.d.ts +1 -1
  84. package/lib/dist/sync/index.d.ts.map +1 -1
  85. package/lib/dist/sync/index.js +2 -1
  86. package/lib/dist/sync/index.js.map +1 -1
  87. package/lib/dist/sync/watcher.d.ts +10 -0
  88. package/lib/dist/sync/watcher.d.ts.map +1 -1
  89. package/lib/dist/sync/watcher.js +28 -4
  90. package/lib/dist/sync/watcher.js.map +1 -1
  91. package/lib/dist/types.d.ts +1 -1
  92. package/lib/dist/types.d.ts.map +1 -1
  93. package/lib/dist/types.js +2 -0
  94. package/lib/dist/types.js.map +1 -1
  95. package/lib/node_modules/.package-lock.json +1 -1
  96. package/lib/package.json +1 -1
  97. package/package.json +1 -1
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MyBatisExtractor = void 0;
4
+ const tree_sitter_helpers_1 = require("./tree-sitter-helpers");
5
+ /**
6
+ * MyBatisExtractor — parses MyBatis mapper XML files.
7
+ *
8
+ * MyBatis splits a DAO interface across two files: a Java interface (parsed by
9
+ * tree-sitter) declares the method, and an XML mapper file holds the SQL keyed
10
+ * by `<namespace>` (the fully-qualified Java type name) and `id` (the method
11
+ * name). Without the XML side in the graph, `trace(Controller, ...DAO.method)`
12
+ * dead-ends at the interface method — the SQL it actually runs is invisible,
13
+ * and "what does this query touch" / "where is this column written" can't be
14
+ * answered.
15
+ *
16
+ * This extractor emits one method-shaped node per `<select|insert|update|
17
+ * delete>` and per `<sql>` fragment, qualified as `<namespace>::<id>` so the
18
+ * MyBatis framework synthesizer (`src/resolution/frameworks/mybatis.ts`) can
19
+ * link the matching Java method → XML statement by suffix-matching qualified
20
+ * names. `<include refid="...">` inside a statement yields an unresolved
21
+ * reference to the SQL fragment, also keyed by `<namespace>::<refid>`.
22
+ *
23
+ * Non-mapper XML (Maven `pom.xml`, Spring beans XML, `web.xml`, log4j config,
24
+ * etc.) is detected by the absence of a `<mapper namespace="...">` root and
25
+ * returns just a file node — we still need the file row so the watcher can
26
+ * track it, but we emit no symbols.
27
+ */
28
+ class MyBatisExtractor {
29
+ filePath;
30
+ source;
31
+ nodes = [];
32
+ edges = [];
33
+ unresolvedReferences = [];
34
+ errors = [];
35
+ lineStarts = [];
36
+ constructor(filePath, source) {
37
+ this.filePath = filePath;
38
+ this.source = source;
39
+ this.computeLineStarts();
40
+ }
41
+ extract() {
42
+ const startTime = Date.now();
43
+ const fileNode = this.createFileNode();
44
+ try {
45
+ const mapperMatch = this.findMapperRoot();
46
+ if (mapperMatch) {
47
+ this.extractMapper(fileNode.id, mapperMatch.namespace, mapperMatch.bodyStart, mapperMatch.bodyEnd);
48
+ }
49
+ }
50
+ catch (error) {
51
+ this.errors.push({
52
+ message: `MyBatis extraction error: ${error instanceof Error ? error.message : String(error)}`,
53
+ severity: 'error',
54
+ code: 'parse_error',
55
+ });
56
+ }
57
+ return {
58
+ nodes: this.nodes,
59
+ edges: this.edges,
60
+ unresolvedReferences: this.unresolvedReferences,
61
+ errors: this.errors,
62
+ durationMs: Date.now() - startTime,
63
+ };
64
+ }
65
+ createFileNode() {
66
+ const lines = this.source.split('\n');
67
+ const id = (0, tree_sitter_helpers_1.generateNodeId)(this.filePath, 'file', this.filePath, 1);
68
+ const node = {
69
+ id,
70
+ kind: 'file',
71
+ name: this.filePath.split('/').pop() || this.filePath,
72
+ qualifiedName: this.filePath,
73
+ filePath: this.filePath,
74
+ language: 'xml',
75
+ startLine: 1,
76
+ endLine: lines.length || 1,
77
+ startColumn: 0,
78
+ endColumn: lines[lines.length - 1]?.length ?? 0,
79
+ updatedAt: Date.now(),
80
+ };
81
+ this.nodes.push(node);
82
+ return node;
83
+ }
84
+ /**
85
+ * Find the `<mapper namespace="X">` opening tag. Returns the namespace and
86
+ * the byte offsets of the body (between the opening and closing tag) so
87
+ * statement extraction can be scoped to mapper contents.
88
+ */
89
+ findMapperRoot() {
90
+ const open = /<mapper\b([^>]*)>/.exec(this.source);
91
+ if (!open)
92
+ return null;
93
+ const attrs = open[1] ?? '';
94
+ const nsMatch = /\bnamespace\s*=\s*"([^"]+)"/.exec(attrs);
95
+ if (!nsMatch)
96
+ return null;
97
+ const bodyStart = open.index + open[0].length;
98
+ const closeIdx = this.source.indexOf('</mapper>', bodyStart);
99
+ const bodyEnd = closeIdx >= 0 ? closeIdx : this.source.length;
100
+ return { namespace: nsMatch[1], bodyStart, bodyEnd };
101
+ }
102
+ extractMapper(fileNodeId, namespace, bodyStart, bodyEnd) {
103
+ const body = this.source.slice(bodyStart, bodyEnd);
104
+ // Match each top-level statement-shaped element. The body may have nested
105
+ // tags (`<if>`, `<foreach>`, `<include>`), so we scan with a regex that
106
+ // pairs an opening tag to its matching close — the simple form below works
107
+ // because MyBatis statement elements are not themselves nested.
108
+ const stmtRegex = /<(select|insert|update|delete|sql)\b([^>]*)>([\s\S]*?)<\/\1>/g;
109
+ let m;
110
+ while ((m = stmtRegex.exec(body)) !== null) {
111
+ const elemType = m[1];
112
+ const attrs = m[2] ?? '';
113
+ const elemBody = m[3] ?? '';
114
+ const idMatch = /\bid\s*=\s*"([^"]+)"/.exec(attrs);
115
+ if (!idMatch)
116
+ continue;
117
+ const id = idMatch[1];
118
+ const absoluteIndex = bodyStart + m.index;
119
+ const startLine = this.getLineNumber(absoluteIndex);
120
+ const endLine = this.getLineNumber(absoluteIndex + m[0].length);
121
+ const qualified = `${namespace}::${id}`;
122
+ const isSqlFragment = elemType === 'sql';
123
+ const nodeId = (0, tree_sitter_helpers_1.generateNodeId)(this.filePath, 'method', qualified, startLine);
124
+ const node = {
125
+ id: nodeId,
126
+ kind: 'method',
127
+ name: id,
128
+ qualifiedName: qualified,
129
+ filePath: this.filePath,
130
+ language: 'xml',
131
+ signature: this.buildSignature(elemType, attrs, isSqlFragment),
132
+ startLine,
133
+ endLine,
134
+ startColumn: 0,
135
+ endColumn: 0,
136
+ docstring: this.previewSql(elemBody),
137
+ updatedAt: Date.now(),
138
+ };
139
+ this.nodes.push(node);
140
+ this.edges.push({ source: fileNodeId, target: nodeId, kind: 'contains' });
141
+ // <include refid="X"/> → reference to the SQL fragment in this mapper
142
+ // (or in another mapper, when the refid is qualified — `ns.X`).
143
+ const includeRegex = /<include\b[^>]*\brefid\s*=\s*"([^"]+)"/g;
144
+ let inc;
145
+ while ((inc = includeRegex.exec(elemBody)) !== null) {
146
+ const refid = inc[1];
147
+ const refQualified = refid.includes('.') ? refid.replace(/\./g, '::') : `${namespace}::${refid}`;
148
+ const includeOffset = absoluteIndex + (m[0].length - m[3].length - `</${elemType}>`.length) + inc.index;
149
+ const line = this.getLineNumber(includeOffset);
150
+ this.unresolvedReferences.push({
151
+ fromNodeId: nodeId,
152
+ referenceName: refQualified,
153
+ referenceKind: 'references',
154
+ line,
155
+ column: 0,
156
+ });
157
+ }
158
+ }
159
+ }
160
+ buildSignature(elemType, attrs, isSqlFragment) {
161
+ if (isSqlFragment)
162
+ return '<sql>';
163
+ const verb = elemType.toUpperCase();
164
+ const result = /\bresultType\s*=\s*"([^"]+)"/.exec(attrs)?.[1];
165
+ const param = /\bparameterType\s*=\s*"([^"]+)"/.exec(attrs)?.[1];
166
+ const parts = [verb];
167
+ if (param)
168
+ parts.push(`param=${param}`);
169
+ if (result)
170
+ parts.push(`result=${result}`);
171
+ return parts.join(' ');
172
+ }
173
+ previewSql(body) {
174
+ return body.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 200);
175
+ }
176
+ computeLineStarts() {
177
+ this.lineStarts = [0];
178
+ for (let i = 0; i < this.source.length; i++) {
179
+ if (this.source.charCodeAt(i) === 10)
180
+ this.lineStarts.push(i + 1);
181
+ }
182
+ }
183
+ getLineNumber(offset) {
184
+ // Binary search
185
+ let lo = 0;
186
+ let hi = this.lineStarts.length - 1;
187
+ while (lo < hi) {
188
+ const mid = (lo + hi + 1) >>> 1;
189
+ if (this.lineStarts[mid] <= offset)
190
+ lo = mid;
191
+ else
192
+ hi = mid - 1;
193
+ }
194
+ return lo + 1;
195
+ }
196
+ }
197
+ exports.MyBatisExtractor = MyBatisExtractor;
198
+ //# sourceMappingURL=mybatis-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mybatis-extractor.js","sourceRoot":"","sources":["../../src/extraction/mybatis-extractor.ts"],"names":[],"mappings":"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"}
@@ -104,6 +104,20 @@ export declare class TreeSitterExtractor {
104
104
  * Returns true if children should be skipped (struct/interface handled body visiting).
105
105
  */
106
106
  private extractTypeAlias;
107
+ /**
108
+ * Surface the members of a TypeScript `type X = { ... }` (or intersection
109
+ * thereof) as `property` / `method` nodes under the type-alias node. Only
110
+ * walks the immediate object_type / intersection operands so anonymous
111
+ * nested object types inside generic arguments (`Promise<{ ok: true }>`)
112
+ * don't produce phantom members.
113
+ */
114
+ private extractTsTypeAliasMembers;
115
+ /**
116
+ * `foo: () => T` → property_signature whose type_annotation contains a
117
+ * `function_type`. Treat that as a method-shaped contract member, since
118
+ * the call site `obj.foo()` has identical semantics to `bar(): T`.
119
+ */
120
+ private isTsFunctionTypedProperty;
107
121
  /**
108
122
  * Extract an import
109
123
  *
@@ -178,6 +192,25 @@ export declare class TreeSitterExtractor {
178
192
  * Creates 'references' edges for parameter types, return types, and field types.
179
193
  */
180
194
  private extractTypeAnnotations;
195
+ /**
196
+ * Extract C# type references from a node that owns a type position —
197
+ * a method/constructor declaration, a property declaration, or a
198
+ * field declaration (which wraps `variable_declaration → type`).
199
+ *
200
+ * Walks ONLY into known type fields, so parameter names like
201
+ * `request` in `Build(UserDto request)` are never mis-emitted as
202
+ * type references. Once inside a type subtree, `walkCsharpTypePosition`
203
+ * recognizes C#'s actual type-leaf node kinds (`identifier`,
204
+ * `qualified_name`, `generic_name`, `array_type`, `nullable_type`,
205
+ * `tuple_type`, …) — none of which are `type_identifier`. Closes #381.
206
+ */
207
+ private extractCsharpTypeRefs;
208
+ /**
209
+ * Walk a C# subtree that is KNOWN to be in a type position
210
+ * (return type, parameter type, property type, field type, generic
211
+ * argument). Identifiers here are type names, not parameter names.
212
+ */
213
+ private walkCsharpTypePosition;
181
214
  /**
182
215
  * Extract type references from a variable's type annotation.
183
216
  */
@@ -1 +1 @@
1
- {"version":3,"file":"tree-sitter.d.ts","sourceRoot":"","sources":["../../src/extraction/tree-sitter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tree-sitter.d.ts","sourceRoot":"","sources":["../../src/extraction/tree-sitter.ts"],"names":[],"mappings":"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"}
@@ -48,6 +48,7 @@ const liquid_extractor_1 = require("./liquid-extractor");
48
48
  const svelte_extractor_1 = require("./svelte-extractor");
49
49
  const dfm_extractor_1 = require("./dfm-extractor");
50
50
  const vue_extractor_1 = require("./vue-extractor");
51
+ const mybatis_extractor_1 = require("./mybatis-extractor");
51
52
  const frameworks_1 = require("../resolution/frameworks");
52
53
  // Re-export for backward compatibility
53
54
  var tree_sitter_helpers_2 = require("./tree-sitter-helpers");
@@ -395,6 +396,20 @@ class TreeSitterExtractor {
395
396
  else if (nodeType === 'impl_item') {
396
397
  this.extractRustImplItem(node);
397
398
  }
399
+ // TypeScript interface members: property_signature (`foo: T`, `foo?: T`)
400
+ // and method_signature (`foo(arg: A): R`) both carry type annotations the
401
+ // interface walker would otherwise drop. Extract them as `references`
402
+ // edges from the interface so resolvers can wire callers/impact for
403
+ // types that only appear in interface members.
404
+ else if ((nodeType === 'property_signature' || nodeType === 'method_signature') &&
405
+ this.isInsideClassLikeNode() &&
406
+ this.TYPE_ANNOTATION_LANGUAGES.has(this.language)) {
407
+ const parentId = this.nodeStack[this.nodeStack.length - 1];
408
+ if (parentId) {
409
+ this.extractTypeAnnotations(node, parentId);
410
+ }
411
+ // don't skipChildren — nested signatures still need traversal
412
+ }
398
413
  // Visit children (unless the extract method already visited them)
399
414
  if (!skipChildren) {
400
415
  for (let i = 0; i < node.namedChildCount; i++) {
@@ -651,6 +666,11 @@ class TreeSitterExtractor {
651
666
  // in inline objects). These are ephemeral and create noise (e.g., Svelte context
652
667
  // objects: `ctx.set({ get view() { ... } })`).
653
668
  if (node.parent?.type === 'object' || node.parent?.type === 'object_expression') {
669
+ const body = this.extractor.resolveBody?.(node, this.extractor.bodyField)
670
+ ?? (0, tree_sitter_helpers_1.getChildByField)(node, this.extractor.bodyField);
671
+ if (body) {
672
+ this.visitFunctionBody(body, '');
673
+ }
654
674
  return;
655
675
  }
656
676
  // Not inside a class-like node and no receiver type, treat as function
@@ -875,6 +895,10 @@ class TreeSitterExtractor {
875
895
  // decorator->target relationship for class properties too.
876
896
  if (propNode) {
877
897
  this.extractDecoratorsFor(node, propNode.id);
898
+ // Emit `references` edges from the property to types named in its
899
+ // type annotation (#381). The generic walker handles TS-style
900
+ // `type_annotation` children; the C# branch walks the `type` field.
901
+ this.extractTypeAnnotations(node, propNode.id);
878
902
  }
879
903
  }
880
904
  /**
@@ -947,8 +971,15 @@ class TreeSitterExtractor {
947
971
  });
948
972
  // Java/Kotlin annotations / TS field decorators sit on the
949
973
  // outer field_declaration, not on the individual declarator.
950
- if (fieldNode)
974
+ if (fieldNode) {
951
975
  this.extractDecoratorsFor(node, fieldNode.id);
976
+ // Same as properties: emit `references` to the field's annotated
977
+ // type. The outer `field_declaration` is the right scope to
978
+ // search from — C# carries the `type` inside `variable_declaration`
979
+ // and the language-aware path in `extractTypeAnnotations` descends
980
+ // into that wrapper (#381).
981
+ this.extractTypeAnnotations(node, fieldNode.id);
982
+ }
952
983
  }
953
984
  }
954
985
  else {
@@ -1016,6 +1047,11 @@ class TreeSitterExtractor {
1016
1047
  if (varNode) {
1017
1048
  this.extractVariableTypeAnnotation(child, varNode.id);
1018
1049
  }
1050
+ if (valueNode &&
1051
+ valueNode.type !== 'object' &&
1052
+ valueNode.type !== 'object_expression') {
1053
+ this.visitFunctionBody(valueNode, '');
1054
+ }
1019
1055
  // Exported const object-of-functions: `export const actions =
1020
1056
  // { default: async () => {} }` (SvelteKit form actions / handler maps
1021
1057
  // / route tables). Extract each function-valued property as a function
@@ -1221,10 +1257,89 @@ class TreeSitterExtractor {
1221
1257
  const value = (0, tree_sitter_helpers_1.getChildByField)(node, 'value');
1222
1258
  if (value) {
1223
1259
  this.extractTypeRefsFromSubtree(value, typeAliasNode.id);
1260
+ // `type X = { foo: T; bar(): T }` — make the members first-class
1261
+ // property/method nodes under the type alias so `recorder.stop()`
1262
+ // can attach the call edge to `RecorderHandle.stop` instead of
1263
+ // an unrelated class method picked by path-proximity (#359).
1264
+ if (this.language === 'typescript' || this.language === 'tsx') {
1265
+ this.extractTsTypeAliasMembers(value, typeAliasNode);
1266
+ }
1224
1267
  }
1225
1268
  }
1226
1269
  return false;
1227
1270
  }
1271
+ /**
1272
+ * Surface the members of a TypeScript `type X = { ... }` (or intersection
1273
+ * thereof) as `property` / `method` nodes under the type-alias node. Only
1274
+ * walks the immediate object_type / intersection operands so anonymous
1275
+ * nested object types inside generic arguments (`Promise<{ ok: true }>`)
1276
+ * don't produce phantom members.
1277
+ */
1278
+ extractTsTypeAliasMembers(value, typeAliasNode) {
1279
+ const objectTypes = [];
1280
+ if (value.type === 'object_type') {
1281
+ objectTypes.push(value);
1282
+ }
1283
+ else if (value.type === 'intersection_type') {
1284
+ for (let i = 0; i < value.namedChildCount; i++) {
1285
+ const op = value.namedChild(i);
1286
+ if (op && op.type === 'object_type')
1287
+ objectTypes.push(op);
1288
+ }
1289
+ }
1290
+ else {
1291
+ return;
1292
+ }
1293
+ this.nodeStack.push(typeAliasNode.id);
1294
+ for (const objType of objectTypes) {
1295
+ for (let i = 0; i < objType.namedChildCount; i++) {
1296
+ const child = objType.namedChild(i);
1297
+ if (!child)
1298
+ continue;
1299
+ if (child.type !== 'property_signature' && child.type !== 'method_signature')
1300
+ continue;
1301
+ const nameNode = (0, tree_sitter_helpers_1.getChildByField)(child, 'name');
1302
+ const memberName = nameNode ? (0, tree_sitter_helpers_1.getNodeText)(nameNode, this.source) : '';
1303
+ if (!memberName)
1304
+ continue;
1305
+ // `foo: () => T` and `foo(): T` are functionally a method on the
1306
+ // type contract. Treat the property_signature with a function-typed
1307
+ // annotation as a method too so call sites can resolve to it.
1308
+ const memberKind = child.type === 'method_signature'
1309
+ ? 'method'
1310
+ : this.isTsFunctionTypedProperty(child) ? 'method' : 'property';
1311
+ const docstring = (0, tree_sitter_helpers_1.getPrecedingDocstring)(child, this.source);
1312
+ const signature = (0, tree_sitter_helpers_1.getNodeText)(child, this.source);
1313
+ this.createNode(memberKind, memberName, child, {
1314
+ docstring,
1315
+ signature,
1316
+ qualifiedName: `${typeAliasNode.name}::${memberName}`,
1317
+ });
1318
+ // Emit `references` edges from the type alias to types named in the
1319
+ // member's signature, matching the interface-member behavior added in
1320
+ // #432. We attach refs to the type-alias parent (consistent with
1321
+ // interface property_signature treatment).
1322
+ this.extractTypeAnnotations(child, typeAliasNode.id);
1323
+ }
1324
+ }
1325
+ this.nodeStack.pop();
1326
+ }
1327
+ /**
1328
+ * `foo: () => T` → property_signature whose type_annotation contains a
1329
+ * `function_type`. Treat that as a method-shaped contract member, since
1330
+ * the call site `obj.foo()` has identical semantics to `bar(): T`.
1331
+ */
1332
+ isTsFunctionTypedProperty(propertySignature) {
1333
+ const typeAnno = (0, tree_sitter_helpers_1.getChildByField)(propertySignature, 'type');
1334
+ if (!typeAnno)
1335
+ return false;
1336
+ for (let i = 0; i < typeAnno.namedChildCount; i++) {
1337
+ const inner = typeAnno.namedChild(i);
1338
+ if (inner && inner.type === 'function_type')
1339
+ return true;
1340
+ }
1341
+ return false;
1342
+ }
1228
1343
  // extractExportedVariables removed — the walker now descends into
1229
1344
  // export_statement children and the inner declaration's dedicated
1230
1345
  // extractor (extractVariable, extractFunction, extractClass, etc.)
@@ -1373,7 +1488,25 @@ class TreeSitterExtractor {
1373
1488
  if (nameField && objectField && (node.type === 'method_invocation' || node.type === 'member_call_expression' || node.type === 'scoped_call_expression')) {
1374
1489
  // Method call with explicit receiver: receiver.method() / $receiver->method() / ClassName::method()
1375
1490
  const methodName = (0, tree_sitter_helpers_1.getNodeText)(nameField, this.source);
1376
- let receiverName = (0, tree_sitter_helpers_1.getNodeText)(objectField, this.source);
1491
+ // Java `this.userbo.toLogin2()` parses as method_invocation(object=field_access(this, userbo)).
1492
+ // Without unwrapping, receiverName is `this.userbo` and the name-matcher's
1493
+ // single-dot receiver regex fails. Pull out the immediate field after `this.`
1494
+ // so the receiver is the field name (`userbo`), which the resolver can then
1495
+ // look up in the enclosing class's field declarations.
1496
+ let receiverName;
1497
+ if (objectField.type === 'field_access') {
1498
+ const inner = (0, tree_sitter_helpers_1.getChildByField)(objectField, 'object');
1499
+ const fld = (0, tree_sitter_helpers_1.getChildByField)(objectField, 'field');
1500
+ if (inner && fld && (inner.type === 'this' || inner.type === 'this_expression')) {
1501
+ receiverName = (0, tree_sitter_helpers_1.getNodeText)(fld, this.source);
1502
+ }
1503
+ else {
1504
+ receiverName = (0, tree_sitter_helpers_1.getNodeText)(objectField, this.source);
1505
+ }
1506
+ }
1507
+ else {
1508
+ receiverName = (0, tree_sitter_helpers_1.getNodeText)(objectField, this.source);
1509
+ }
1377
1510
  // Strip PHP $ prefix from variable names
1378
1511
  receiverName = receiverName.replace(/^\$/, '');
1379
1512
  if (methodName) {
@@ -1427,10 +1560,11 @@ class TreeSitterExtractor {
1427
1560
  else {
1428
1561
  const func = (0, tree_sitter_helpers_1.getChildByField)(node, 'function') || node.namedChild(0);
1429
1562
  if (func) {
1430
- if (func.type === 'member_expression' || func.type === 'attribute' || func.type === 'selector_expression' || func.type === 'navigation_expression') {
1563
+ if (func.type === 'member_expression' || func.type === 'attribute' || func.type === 'selector_expression' || func.type === 'navigation_expression' || func.type === 'field_expression') {
1431
1564
  // Method call: obj.method() or obj.field.method()
1432
1565
  // Go uses selector_expression with 'field', JS/TS uses member_expression with 'property'
1433
1566
  // Kotlin uses navigation_expression with navigation_suffix > simple_identifier
1567
+ // C/C++ use field_expression for both `obj.method()` and `ptr->method()`
1434
1568
  let property = (0, tree_sitter_helpers_1.getChildByField)(func, 'property') || (0, tree_sitter_helpers_1.getChildByField)(func, 'field');
1435
1569
  if (!property) {
1436
1570
  const child1 = func.namedChild(1);
@@ -1448,9 +1582,12 @@ class TreeSitterExtractor {
1448
1582
  // This helps the resolver distinguish method calls from bare function calls
1449
1583
  // (e.g., Python's console.print() vs builtin print())
1450
1584
  // Skip self/this/cls as they don't aid resolution
1451
- const receiver = (0, tree_sitter_helpers_1.getChildByField)(func, 'object') || (0, tree_sitter_helpers_1.getChildByField)(func, 'operand') || func.namedChild(0);
1585
+ const receiver = (0, tree_sitter_helpers_1.getChildByField)(func, 'object') ||
1586
+ (0, tree_sitter_helpers_1.getChildByField)(func, 'operand') ||
1587
+ (0, tree_sitter_helpers_1.getChildByField)(func, 'argument') ||
1588
+ func.namedChild(0);
1452
1589
  const SKIP_RECEIVERS = new Set(['self', 'this', 'cls', 'super']);
1453
- if (receiver && (receiver.type === 'identifier' || receiver.type === 'simple_identifier')) {
1590
+ if (receiver && (receiver.type === 'identifier' || receiver.type === 'simple_identifier' || receiver.type === 'field_identifier')) {
1454
1591
  const receiverName = (0, tree_sitter_helpers_1.getNodeText)(receiver, this.source);
1455
1592
  if (!SKIP_RECEIVERS.has(receiverName)) {
1456
1593
  calleeName = `${receiverName}.${methodName}`;
@@ -2083,6 +2220,16 @@ class TreeSitterExtractor {
2083
2220
  return;
2084
2221
  if (!this.TYPE_ANNOTATION_LANGUAGES.has(this.language))
2085
2222
  return;
2223
+ // C# tree-sitter doesn't produce `type_identifier` leaves — it uses
2224
+ // `identifier`, `predefined_type`, `qualified_name`, `generic_name`,
2225
+ // etc. — so the generic walker below emits zero references for it.
2226
+ // Dispatch to a C#-aware path that only walks type-position subtrees
2227
+ // (the `type` field of a parameter/method/property/field), so
2228
+ // parameter NAMES never accidentally surface as type refs (#381).
2229
+ if (this.language === 'csharp') {
2230
+ this.extractCsharpTypeRefs(node, nodeId);
2231
+ return;
2232
+ }
2086
2233
  // Extract parameter type annotations
2087
2234
  const params = (0, tree_sitter_helpers_1.getChildByField)(node, this.extractor.paramsField || 'parameters');
2088
2235
  if (params) {
@@ -2099,6 +2246,112 @@ class TreeSitterExtractor {
2099
2246
  this.extractTypeRefsFromSubtree(typeAnnotation, nodeId);
2100
2247
  }
2101
2248
  }
2249
+ /**
2250
+ * Extract C# type references from a node that owns a type position —
2251
+ * a method/constructor declaration, a property declaration, or a
2252
+ * field declaration (which wraps `variable_declaration → type`).
2253
+ *
2254
+ * Walks ONLY into known type fields, so parameter names like
2255
+ * `request` in `Build(UserDto request)` are never mis-emitted as
2256
+ * type references. Once inside a type subtree, `walkCsharpTypePosition`
2257
+ * recognizes C#'s actual type-leaf node kinds (`identifier`,
2258
+ * `qualified_name`, `generic_name`, `array_type`, `nullable_type`,
2259
+ * `tuple_type`, …) — none of which are `type_identifier`. Closes #381.
2260
+ */
2261
+ extractCsharpTypeRefs(node, nodeId) {
2262
+ // Return type / property type — the field is named `type`.
2263
+ const directType = (0, tree_sitter_helpers_1.getChildByField)(node, 'type');
2264
+ if (directType)
2265
+ this.walkCsharpTypePosition(directType, nodeId);
2266
+ // Field declarations wrap declarators in a `variable_declaration`
2267
+ // whose `type` field carries the type. The outer `field_declaration`
2268
+ // has no `type` field of its own, so the call above is a no-op here
2269
+ // and we descend one level.
2270
+ const varDecl = node.namedChildren.find((c) => c.type === 'variable_declaration');
2271
+ if (varDecl) {
2272
+ const vdType = (0, tree_sitter_helpers_1.getChildByField)(varDecl, 'type');
2273
+ if (vdType)
2274
+ this.walkCsharpTypePosition(vdType, nodeId);
2275
+ }
2276
+ // Method / constructor parameters. The field name on
2277
+ // `method_declaration` is `parameters`; it points at a
2278
+ // `parameter_list` whose `parameter` children each have their own
2279
+ // `type` field. Walking ONLY the type field skips parameter NAMES,
2280
+ // which would otherwise mis-emit as type references.
2281
+ const params = (0, tree_sitter_helpers_1.getChildByField)(node, 'parameters');
2282
+ if (params) {
2283
+ for (let i = 0; i < params.namedChildCount; i++) {
2284
+ const child = params.namedChild(i);
2285
+ if (!child || child.type !== 'parameter')
2286
+ continue;
2287
+ const paramType = (0, tree_sitter_helpers_1.getChildByField)(child, 'type');
2288
+ if (paramType)
2289
+ this.walkCsharpTypePosition(paramType, nodeId);
2290
+ }
2291
+ }
2292
+ }
2293
+ /**
2294
+ * Walk a C# subtree that is KNOWN to be in a type position
2295
+ * (return type, parameter type, property type, field type, generic
2296
+ * argument). Identifiers here are type names, not parameter names.
2297
+ */
2298
+ walkCsharpTypePosition(node, fromNodeId) {
2299
+ // `predefined_type` is int/string/bool/etc. — never a project ref.
2300
+ if (node.type === 'predefined_type')
2301
+ return;
2302
+ // Bare type name: `Foo` in `Foo bar`, or the `Foo` inside `List<Foo>`.
2303
+ if (node.type === 'identifier') {
2304
+ const name = (0, tree_sitter_helpers_1.getNodeText)(node, this.source);
2305
+ if (name && !this.BUILTIN_TYPES.has(name)) {
2306
+ this.unresolvedReferences.push({
2307
+ fromNodeId,
2308
+ referenceName: name,
2309
+ referenceKind: 'references',
2310
+ line: node.startPosition.row + 1,
2311
+ column: node.startPosition.column,
2312
+ });
2313
+ }
2314
+ return;
2315
+ }
2316
+ // `Namespace.Foo` → the rightmost identifier is the type. Emit the
2317
+ // full qualified name as the reference; the resolver can still match
2318
+ // on the trailing simple name when needed.
2319
+ if (node.type === 'qualified_name') {
2320
+ const text = (0, tree_sitter_helpers_1.getNodeText)(node, this.source);
2321
+ const last = text.split('.').pop() ?? text;
2322
+ if (last && !this.BUILTIN_TYPES.has(last)) {
2323
+ this.unresolvedReferences.push({
2324
+ fromNodeId,
2325
+ referenceName: last,
2326
+ referenceKind: 'references',
2327
+ line: node.startPosition.row + 1,
2328
+ column: node.startPosition.column,
2329
+ });
2330
+ }
2331
+ return;
2332
+ }
2333
+ // `(int Code, Foo Payload)` — tuple element has BOTH a `type` and a
2334
+ // `name` field; descending into all named children would mis-emit
2335
+ // the element name (`Code`, `Payload`) as a type ref. Walk only the
2336
+ // type field.
2337
+ if (node.type === 'tuple_element') {
2338
+ const t = (0, tree_sitter_helpers_1.getChildByField)(node, 'type');
2339
+ if (t)
2340
+ this.walkCsharpTypePosition(t, fromNodeId);
2341
+ return;
2342
+ }
2343
+ // Composite type nodes — recurse into named children. Covers
2344
+ // `generic_name` (head identifier + `type_argument_list`),
2345
+ // `nullable_type`, `array_type`, `pointer_type`, `tuple_type`,
2346
+ // `ref_type`, and any newer wrapping shapes the grammar adds.
2347
+ // Identifiers reached here are all type-positional (parameter/field
2348
+ // names are gated out before we descend).
2349
+ for (let i = 0; i < node.namedChildCount; i++) {
2350
+ const child = node.namedChild(i);
2351
+ if (child)
2352
+ this.walkCsharpTypePosition(child, fromNodeId);
2353
+ }
2354
+ }
2102
2355
  /**
2103
2356
  * Extract type references from a variable's type annotation.
2104
2357
  */
@@ -2535,10 +2788,17 @@ function extractFromSource(filePath, source, language, frameworkNames) {
2535
2788
  const extractor = new liquid_extractor_1.LiquidExtractor(filePath, source);
2536
2789
  result = extractor.extract();
2537
2790
  }
2538
- else if (detectedLanguage === 'yaml' || detectedLanguage === 'twig') {
2539
- // No symbol extraction file is tracked at the file-record level only.
2540
- // Framework extractors (e.g. Drupal routing resolver) run below and may
2541
- // add route nodes / references for yaml files such as *.routing.yml.
2791
+ else if (detectedLanguage === 'xml') {
2792
+ // Custom extractor for MyBatis mapper XML. Non-mapper XML returns just a
2793
+ // file node so the watcher tracks it without emitting symbols.
2794
+ const extractor = new mybatis_extractor_1.MyBatisExtractor(filePath, source);
2795
+ result = extractor.extract();
2796
+ }
2797
+ else if (detectedLanguage === 'yaml' || detectedLanguage === 'twig' || detectedLanguage === 'properties') {
2798
+ // No symbol extraction at this stage — files are tracked at the file-record
2799
+ // level only. Framework extractors (Drupal routing yml, Spring `@Value`
2800
+ // resolution against application.yml/application.properties) run later and
2801
+ // add per-file nodes/references when they apply.
2542
2802
  result = { nodes: [], edges: [], unresolvedReferences: [], errors: [], durationMs: 0 };
2543
2803
  }
2544
2804
  else if (detectedLanguage === 'pascal' &&