@colbymchenry/codegraph-darwin-x64 0.9.5 → 0.9.7

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 (163) hide show
  1. package/lib/dist/bin/codegraph.js +10 -25
  2. package/lib/dist/bin/codegraph.js.map +1 -1
  3. package/lib/dist/context/formatter.d.ts.map +1 -1
  4. package/lib/dist/context/formatter.js +25 -6
  5. package/lib/dist/context/formatter.js.map +1 -1
  6. package/lib/dist/context/index.d.ts.map +1 -1
  7. package/lib/dist/context/index.js +31 -0
  8. package/lib/dist/context/index.js.map +1 -1
  9. package/lib/dist/db/queries.d.ts +75 -0
  10. package/lib/dist/db/queries.d.ts.map +1 -1
  11. package/lib/dist/db/queries.js +213 -3
  12. package/lib/dist/db/queries.js.map +1 -1
  13. package/lib/dist/extraction/generated-detection.d.ts +30 -0
  14. package/lib/dist/extraction/generated-detection.d.ts.map +1 -0
  15. package/lib/dist/extraction/generated-detection.js +80 -0
  16. package/lib/dist/extraction/generated-detection.js.map +1 -0
  17. package/lib/dist/extraction/grammars.d.ts +1 -1
  18. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  19. package/lib/dist/extraction/grammars.js +15 -0
  20. package/lib/dist/extraction/grammars.js.map +1 -1
  21. package/lib/dist/extraction/index.js +4 -4
  22. package/lib/dist/extraction/index.js.map +1 -1
  23. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  24. package/lib/dist/extraction/languages/c-cpp.js +45 -0
  25. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  26. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
  27. package/lib/dist/extraction/languages/csharp.js +2 -1
  28. package/lib/dist/extraction/languages/csharp.js.map +1 -1
  29. package/lib/dist/extraction/languages/go.d.ts.map +1 -1
  30. package/lib/dist/extraction/languages/go.js +12 -0
  31. package/lib/dist/extraction/languages/go.js.map +1 -1
  32. package/lib/dist/extraction/languages/java.d.ts.map +1 -1
  33. package/lib/dist/extraction/languages/java.js +6 -0
  34. package/lib/dist/extraction/languages/java.js.map +1 -1
  35. package/lib/dist/extraction/languages/kotlin.d.ts.map +1 -1
  36. package/lib/dist/extraction/languages/kotlin.js +6 -0
  37. package/lib/dist/extraction/languages/kotlin.js.map +1 -1
  38. package/lib/dist/extraction/mybatis-extractor.d.ts +48 -0
  39. package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  40. package/lib/dist/extraction/mybatis-extractor.js +198 -0
  41. package/lib/dist/extraction/mybatis-extractor.js.map +1 -0
  42. package/lib/dist/extraction/tree-sitter-types.d.ts +10 -0
  43. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  44. package/lib/dist/extraction/tree-sitter.d.ts +58 -0
  45. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  46. package/lib/dist/extraction/tree-sitter.js +393 -9
  47. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  48. package/lib/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
  49. package/lib/dist/extraction/wasm-runtime-flags.js +1 -0
  50. package/lib/dist/extraction/wasm-runtime-flags.js.map +1 -1
  51. package/lib/dist/index.d.ts +32 -1
  52. package/lib/dist/index.d.ts.map +1 -1
  53. package/lib/dist/index.js +49 -1
  54. package/lib/dist/index.js.map +1 -1
  55. package/lib/dist/installer/config-writer.d.ts +7 -8
  56. package/lib/dist/installer/config-writer.d.ts.map +1 -1
  57. package/lib/dist/installer/config-writer.js +7 -27
  58. package/lib/dist/installer/config-writer.js.map +1 -1
  59. package/lib/dist/installer/index.d.ts +3 -20
  60. package/lib/dist/installer/index.d.ts.map +1 -1
  61. package/lib/dist/installer/index.js +8 -39
  62. package/lib/dist/installer/index.js.map +1 -1
  63. package/lib/dist/installer/instructions-template.d.ts +11 -21
  64. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  65. package/lib/dist/installer/instructions-template.js +12 -56
  66. package/lib/dist/installer/instructions-template.js.map +1 -1
  67. package/lib/dist/installer/targets/antigravity.d.ts +57 -0
  68. package/lib/dist/installer/targets/antigravity.d.ts.map +1 -0
  69. package/lib/dist/installer/targets/antigravity.js +308 -0
  70. package/lib/dist/installer/targets/antigravity.js.map +1 -0
  71. package/lib/dist/installer/targets/claude.d.ts +10 -1
  72. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  73. package/lib/dist/installer/targets/claude.js +25 -40
  74. package/lib/dist/installer/targets/claude.js.map +1 -1
  75. package/lib/dist/installer/targets/codex.d.ts.map +1 -1
  76. package/lib/dist/installer/targets/codex.js +15 -13
  77. package/lib/dist/installer/targets/codex.js.map +1 -1
  78. package/lib/dist/installer/targets/cursor.d.ts.map +1 -1
  79. package/lib/dist/installer/targets/cursor.js +9 -38
  80. package/lib/dist/installer/targets/cursor.js.map +1 -1
  81. package/lib/dist/installer/targets/gemini.d.ts +26 -0
  82. package/lib/dist/installer/targets/gemini.d.ts.map +1 -0
  83. package/lib/dist/installer/targets/gemini.js +167 -0
  84. package/lib/dist/installer/targets/gemini.js.map +1 -0
  85. package/lib/dist/installer/targets/hermes.d.ts.map +1 -1
  86. package/lib/dist/installer/targets/hermes.js +57 -3
  87. package/lib/dist/installer/targets/hermes.js.map +1 -1
  88. package/lib/dist/installer/targets/kiro.d.ts +27 -0
  89. package/lib/dist/installer/targets/kiro.d.ts.map +1 -0
  90. package/lib/dist/installer/targets/kiro.js +178 -0
  91. package/lib/dist/installer/targets/kiro.js.map +1 -0
  92. package/lib/dist/installer/targets/opencode.d.ts.map +1 -1
  93. package/lib/dist/installer/targets/opencode.js +15 -13
  94. package/lib/dist/installer/targets/opencode.js.map +1 -1
  95. package/lib/dist/installer/targets/registry.d.ts.map +1 -1
  96. package/lib/dist/installer/targets/registry.js +6 -0
  97. package/lib/dist/installer/targets/registry.js.map +1 -1
  98. package/lib/dist/installer/targets/types.d.ts +1 -16
  99. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  100. package/lib/dist/mcp/engine.d.ts +6 -1
  101. package/lib/dist/mcp/engine.d.ts.map +1 -1
  102. package/lib/dist/mcp/engine.js +9 -4
  103. package/lib/dist/mcp/engine.js.map +1 -1
  104. package/lib/dist/mcp/server-instructions.d.ts +1 -1
  105. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  106. package/lib/dist/mcp/server-instructions.js +2 -0
  107. package/lib/dist/mcp/server-instructions.js.map +1 -1
  108. package/lib/dist/mcp/tools.d.ts +31 -0
  109. package/lib/dist/mcp/tools.d.ts.map +1 -1
  110. package/lib/dist/mcp/tools.js +556 -55
  111. package/lib/dist/mcp/tools.js.map +1 -1
  112. package/lib/dist/resolution/callback-synthesizer.d.ts +2 -2
  113. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  114. package/lib/dist/resolution/callback-synthesizer.js +235 -29
  115. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  116. package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
  117. package/lib/dist/resolution/frameworks/java.js +270 -1
  118. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  119. package/lib/dist/resolution/frameworks/nestjs.d.ts.map +1 -1
  120. package/lib/dist/resolution/frameworks/nestjs.js +324 -0
  121. package/lib/dist/resolution/frameworks/nestjs.js.map +1 -1
  122. package/lib/dist/resolution/go-module.d.ts +26 -0
  123. package/lib/dist/resolution/go-module.d.ts.map +1 -0
  124. package/lib/dist/resolution/go-module.js +78 -0
  125. package/lib/dist/resolution/go-module.js.map +1 -0
  126. package/lib/dist/resolution/import-resolver.d.ts +28 -0
  127. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  128. package/lib/dist/resolution/import-resolver.js +571 -4
  129. package/lib/dist/resolution/import-resolver.js.map +1 -1
  130. package/lib/dist/resolution/index.d.ts +10 -0
  131. package/lib/dist/resolution/index.d.ts.map +1 -1
  132. package/lib/dist/resolution/index.js +117 -0
  133. package/lib/dist/resolution/index.js.map +1 -1
  134. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  135. package/lib/dist/resolution/name-matcher.js +212 -0
  136. package/lib/dist/resolution/name-matcher.js.map +1 -1
  137. package/lib/dist/resolution/types.d.ts +29 -0
  138. package/lib/dist/resolution/types.d.ts.map +1 -1
  139. package/lib/dist/sync/git-hooks.d.ts.map +1 -1
  140. package/lib/dist/sync/git-hooks.js +2 -0
  141. package/lib/dist/sync/git-hooks.js.map +1 -1
  142. package/lib/dist/sync/index.d.ts +1 -1
  143. package/lib/dist/sync/index.d.ts.map +1 -1
  144. package/lib/dist/sync/index.js +2 -1
  145. package/lib/dist/sync/index.js.map +1 -1
  146. package/lib/dist/sync/watcher.d.ts +10 -0
  147. package/lib/dist/sync/watcher.d.ts.map +1 -1
  148. package/lib/dist/sync/watcher.js +28 -4
  149. package/lib/dist/sync/watcher.js.map +1 -1
  150. package/lib/dist/sync/worktree.d.ts.map +1 -1
  151. package/lib/dist/sync/worktree.js +1 -0
  152. package/lib/dist/sync/worktree.js.map +1 -1
  153. package/lib/dist/types.d.ts +1 -1
  154. package/lib/dist/types.d.ts.map +1 -1
  155. package/lib/dist/types.js +2 -0
  156. package/lib/dist/types.js.map +1 -1
  157. package/lib/node_modules/.package-lock.json +1 -1
  158. package/lib/package.json +1 -1
  159. package/package.json +1 -1
  160. package/lib/dist/installer/claude-md-template.d.ts +0 -14
  161. package/lib/dist/installer/claude-md-template.d.ts.map +0 -1
  162. package/lib/dist/installer/claude-md-template.js +0 -21
  163. package/lib/dist/installer/claude-md-template.js.map +0 -1
@@ -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");
@@ -221,7 +222,16 @@ class TreeSitterExtractor {
221
222
  this.nodes.push(fileNode);
222
223
  // Push file node onto stack so top-level declarations get contains edges
223
224
  this.nodeStack.push(fileNode.id);
225
+ // File-level package declaration (Kotlin/Java). Creates an implicit
226
+ // `namespace` node wrapping every top-level declaration so their
227
+ // qualifiedName carries the FQN — required for cross-file import
228
+ // resolution on JVM languages where filename ≠ class name.
229
+ const packageNodeId = this.extractFilePackage(this.tree.rootNode);
230
+ if (packageNodeId)
231
+ this.nodeStack.push(packageNodeId);
224
232
  this.visitNode(this.tree.rootNode);
233
+ if (packageNodeId)
234
+ this.nodeStack.pop();
225
235
  this.nodeStack.pop();
226
236
  }
227
237
  catch (error) {
@@ -386,6 +396,17 @@ class TreeSitterExtractor {
386
396
  // their own `calls` refs.
387
397
  else if (INSTANTIATION_KINDS.has(nodeType)) {
388
398
  this.extractInstantiation(node);
399
+ // Java/C# `new T(...) { ... }` — anonymous class with body. Without
400
+ // extracting it as a class node + its methods, the interface→impl
401
+ // synthesizer (Phase 5.5) can't bridge T's abstract methods to the
402
+ // anonymous overrides, and an agent investigating a call through T
403
+ // (`strategy.iterator(...)` where strategy is a Strategy lambda body)
404
+ // has to Read the file to find the actual implementation.
405
+ const anonBody = this.findAnonymousClassBody(node);
406
+ if (anonBody) {
407
+ this.extractAnonymousClass(node, anonBody);
408
+ skipChildren = true;
409
+ }
389
410
  }
390
411
  // (Decorator handling lives inside the symbol-creating extractors
391
412
  // — extractClass / extractFunction / extractProperty — because the
@@ -395,6 +416,20 @@ class TreeSitterExtractor {
395
416
  else if (nodeType === 'impl_item') {
396
417
  this.extractRustImplItem(node);
397
418
  }
419
+ // TypeScript interface members: property_signature (`foo: T`, `foo?: T`)
420
+ // and method_signature (`foo(arg: A): R`) both carry type annotations the
421
+ // interface walker would otherwise drop. Extract them as `references`
422
+ // edges from the interface so resolvers can wire callers/impact for
423
+ // types that only appear in interface members.
424
+ else if ((nodeType === 'property_signature' || nodeType === 'method_signature') &&
425
+ this.isInsideClassLikeNode() &&
426
+ this.TYPE_ANNOTATION_LANGUAGES.has(this.language)) {
427
+ const parentId = this.nodeStack[this.nodeStack.length - 1];
428
+ if (parentId) {
429
+ this.extractTypeAnnotations(node, parentId);
430
+ }
431
+ // don't skipChildren — nested signatures still need traversal
432
+ }
398
433
  // Visit children (unless the extract method already visited them)
399
434
  if (!skipChildren) {
400
435
  for (let i = 0; i < node.namedChildCount; i++) {
@@ -468,6 +503,32 @@ class TreeSitterExtractor {
468
503
  }
469
504
  return null;
470
505
  }
506
+ /**
507
+ * Find a `packageTypes` child under the root, create a `namespace` node
508
+ * for it, and return its id so the caller can scope top-level
509
+ * declarations underneath. Returns null when no package header is
510
+ * present (script files, .kts without a package).
511
+ */
512
+ extractFilePackage(rootNode) {
513
+ const types = this.extractor?.packageTypes;
514
+ if (!types || types.length === 0 || !this.extractor?.extractPackage)
515
+ return null;
516
+ let pkgNode = null;
517
+ for (let i = 0; i < rootNode.namedChildCount; i++) {
518
+ const child = rootNode.namedChild(i);
519
+ if (child && types.includes(child.type)) {
520
+ pkgNode = child;
521
+ break;
522
+ }
523
+ }
524
+ if (!pkgNode)
525
+ return null;
526
+ const pkgName = this.extractor.extractPackage(pkgNode, this.source);
527
+ if (!pkgName)
528
+ return null;
529
+ const ns = this.createNode('namespace', pkgName, pkgNode);
530
+ return ns?.id ?? null;
531
+ }
471
532
  /**
472
533
  * Build qualified name from node stack
473
534
  */
@@ -651,6 +712,11 @@ class TreeSitterExtractor {
651
712
  // in inline objects). These are ephemeral and create noise (e.g., Svelte context
652
713
  // objects: `ctx.set({ get view() { ... } })`).
653
714
  if (node.parent?.type === 'object' || node.parent?.type === 'object_expression') {
715
+ const body = this.extractor.resolveBody?.(node, this.extractor.bodyField)
716
+ ?? (0, tree_sitter_helpers_1.getChildByField)(node, this.extractor.bodyField);
717
+ if (body) {
718
+ this.visitFunctionBody(body, '');
719
+ }
654
720
  return;
655
721
  }
656
722
  // Not inside a class-like node and no receiver type, treat as function
@@ -875,6 +941,10 @@ class TreeSitterExtractor {
875
941
  // decorator->target relationship for class properties too.
876
942
  if (propNode) {
877
943
  this.extractDecoratorsFor(node, propNode.id);
944
+ // Emit `references` edges from the property to types named in its
945
+ // type annotation (#381). The generic walker handles TS-style
946
+ // `type_annotation` children; the C# branch walks the `type` field.
947
+ this.extractTypeAnnotations(node, propNode.id);
878
948
  }
879
949
  }
880
950
  /**
@@ -947,8 +1017,15 @@ class TreeSitterExtractor {
947
1017
  });
948
1018
  // Java/Kotlin annotations / TS field decorators sit on the
949
1019
  // outer field_declaration, not on the individual declarator.
950
- if (fieldNode)
1020
+ if (fieldNode) {
951
1021
  this.extractDecoratorsFor(node, fieldNode.id);
1022
+ // Same as properties: emit `references` to the field's annotated
1023
+ // type. The outer `field_declaration` is the right scope to
1024
+ // search from — C# carries the `type` inside `variable_declaration`
1025
+ // and the language-aware path in `extractTypeAnnotations` descends
1026
+ // into that wrapper (#381).
1027
+ this.extractTypeAnnotations(node, fieldNode.id);
1028
+ }
952
1029
  }
953
1030
  }
954
1031
  else {
@@ -1016,6 +1093,11 @@ class TreeSitterExtractor {
1016
1093
  if (varNode) {
1017
1094
  this.extractVariableTypeAnnotation(child, varNode.id);
1018
1095
  }
1096
+ if (valueNode &&
1097
+ valueNode.type !== 'object' &&
1098
+ valueNode.type !== 'object_expression') {
1099
+ this.visitFunctionBody(valueNode, '');
1100
+ }
1019
1101
  // Exported const object-of-functions: `export const actions =
1020
1102
  // { default: async () => {} }` (SvelteKit form actions / handler maps
1021
1103
  // / route tables). Extract each function-valued property as a function
@@ -1221,8 +1303,87 @@ class TreeSitterExtractor {
1221
1303
  const value = (0, tree_sitter_helpers_1.getChildByField)(node, 'value');
1222
1304
  if (value) {
1223
1305
  this.extractTypeRefsFromSubtree(value, typeAliasNode.id);
1306
+ // `type X = { foo: T; bar(): T }` — make the members first-class
1307
+ // property/method nodes under the type alias so `recorder.stop()`
1308
+ // can attach the call edge to `RecorderHandle.stop` instead of
1309
+ // an unrelated class method picked by path-proximity (#359).
1310
+ if (this.language === 'typescript' || this.language === 'tsx') {
1311
+ this.extractTsTypeAliasMembers(value, typeAliasNode);
1312
+ }
1313
+ }
1314
+ }
1315
+ return false;
1316
+ }
1317
+ /**
1318
+ * Surface the members of a TypeScript `type X = { ... }` (or intersection
1319
+ * thereof) as `property` / `method` nodes under the type-alias node. Only
1320
+ * walks the immediate object_type / intersection operands so anonymous
1321
+ * nested object types inside generic arguments (`Promise<{ ok: true }>`)
1322
+ * don't produce phantom members.
1323
+ */
1324
+ extractTsTypeAliasMembers(value, typeAliasNode) {
1325
+ const objectTypes = [];
1326
+ if (value.type === 'object_type') {
1327
+ objectTypes.push(value);
1328
+ }
1329
+ else if (value.type === 'intersection_type') {
1330
+ for (let i = 0; i < value.namedChildCount; i++) {
1331
+ const op = value.namedChild(i);
1332
+ if (op && op.type === 'object_type')
1333
+ objectTypes.push(op);
1334
+ }
1335
+ }
1336
+ else {
1337
+ return;
1338
+ }
1339
+ this.nodeStack.push(typeAliasNode.id);
1340
+ for (const objType of objectTypes) {
1341
+ for (let i = 0; i < objType.namedChildCount; i++) {
1342
+ const child = objType.namedChild(i);
1343
+ if (!child)
1344
+ continue;
1345
+ if (child.type !== 'property_signature' && child.type !== 'method_signature')
1346
+ continue;
1347
+ const nameNode = (0, tree_sitter_helpers_1.getChildByField)(child, 'name');
1348
+ const memberName = nameNode ? (0, tree_sitter_helpers_1.getNodeText)(nameNode, this.source) : '';
1349
+ if (!memberName)
1350
+ continue;
1351
+ // `foo: () => T` and `foo(): T` are functionally a method on the
1352
+ // type contract. Treat the property_signature with a function-typed
1353
+ // annotation as a method too so call sites can resolve to it.
1354
+ const memberKind = child.type === 'method_signature'
1355
+ ? 'method'
1356
+ : this.isTsFunctionTypedProperty(child) ? 'method' : 'property';
1357
+ const docstring = (0, tree_sitter_helpers_1.getPrecedingDocstring)(child, this.source);
1358
+ const signature = (0, tree_sitter_helpers_1.getNodeText)(child, this.source);
1359
+ this.createNode(memberKind, memberName, child, {
1360
+ docstring,
1361
+ signature,
1362
+ qualifiedName: `${typeAliasNode.name}::${memberName}`,
1363
+ });
1364
+ // Emit `references` edges from the type alias to types named in the
1365
+ // member's signature, matching the interface-member behavior added in
1366
+ // #432. We attach refs to the type-alias parent (consistent with
1367
+ // interface property_signature treatment).
1368
+ this.extractTypeAnnotations(child, typeAliasNode.id);
1224
1369
  }
1225
1370
  }
1371
+ this.nodeStack.pop();
1372
+ }
1373
+ /**
1374
+ * `foo: () => T` → property_signature whose type_annotation contains a
1375
+ * `function_type`. Treat that as a method-shaped contract member, since
1376
+ * the call site `obj.foo()` has identical semantics to `bar(): T`.
1377
+ */
1378
+ isTsFunctionTypedProperty(propertySignature) {
1379
+ const typeAnno = (0, tree_sitter_helpers_1.getChildByField)(propertySignature, 'type');
1380
+ if (!typeAnno)
1381
+ return false;
1382
+ for (let i = 0; i < typeAnno.namedChildCount; i++) {
1383
+ const inner = typeAnno.namedChild(i);
1384
+ if (inner && inner.type === 'function_type')
1385
+ return true;
1386
+ }
1226
1387
  return false;
1227
1388
  }
1228
1389
  // extractExportedVariables removed — the walker now descends into
@@ -1373,7 +1534,25 @@ class TreeSitterExtractor {
1373
1534
  if (nameField && objectField && (node.type === 'method_invocation' || node.type === 'member_call_expression' || node.type === 'scoped_call_expression')) {
1374
1535
  // Method call with explicit receiver: receiver.method() / $receiver->method() / ClassName::method()
1375
1536
  const methodName = (0, tree_sitter_helpers_1.getNodeText)(nameField, this.source);
1376
- let receiverName = (0, tree_sitter_helpers_1.getNodeText)(objectField, this.source);
1537
+ // Java `this.userbo.toLogin2()` parses as method_invocation(object=field_access(this, userbo)).
1538
+ // Without unwrapping, receiverName is `this.userbo` and the name-matcher's
1539
+ // single-dot receiver regex fails. Pull out the immediate field after `this.`
1540
+ // so the receiver is the field name (`userbo`), which the resolver can then
1541
+ // look up in the enclosing class's field declarations.
1542
+ let receiverName;
1543
+ if (objectField.type === 'field_access') {
1544
+ const inner = (0, tree_sitter_helpers_1.getChildByField)(objectField, 'object');
1545
+ const fld = (0, tree_sitter_helpers_1.getChildByField)(objectField, 'field');
1546
+ if (inner && fld && (inner.type === 'this' || inner.type === 'this_expression')) {
1547
+ receiverName = (0, tree_sitter_helpers_1.getNodeText)(fld, this.source);
1548
+ }
1549
+ else {
1550
+ receiverName = (0, tree_sitter_helpers_1.getNodeText)(objectField, this.source);
1551
+ }
1552
+ }
1553
+ else {
1554
+ receiverName = (0, tree_sitter_helpers_1.getNodeText)(objectField, this.source);
1555
+ }
1377
1556
  // Strip PHP $ prefix from variable names
1378
1557
  receiverName = receiverName.replace(/^\$/, '');
1379
1558
  if (methodName) {
@@ -1427,10 +1606,11 @@ class TreeSitterExtractor {
1427
1606
  else {
1428
1607
  const func = (0, tree_sitter_helpers_1.getChildByField)(node, 'function') || node.namedChild(0);
1429
1608
  if (func) {
1430
- if (func.type === 'member_expression' || func.type === 'attribute' || func.type === 'selector_expression' || func.type === 'navigation_expression') {
1609
+ if (func.type === 'member_expression' || func.type === 'attribute' || func.type === 'selector_expression' || func.type === 'navigation_expression' || func.type === 'field_expression') {
1431
1610
  // Method call: obj.method() or obj.field.method()
1432
1611
  // Go uses selector_expression with 'field', JS/TS uses member_expression with 'property'
1433
1612
  // Kotlin uses navigation_expression with navigation_suffix > simple_identifier
1613
+ // C/C++ use field_expression for both `obj.method()` and `ptr->method()`
1434
1614
  let property = (0, tree_sitter_helpers_1.getChildByField)(func, 'property') || (0, tree_sitter_helpers_1.getChildByField)(func, 'field');
1435
1615
  if (!property) {
1436
1616
  const child1 = func.namedChild(1);
@@ -1448,9 +1628,12 @@ class TreeSitterExtractor {
1448
1628
  // This helps the resolver distinguish method calls from bare function calls
1449
1629
  // (e.g., Python's console.print() vs builtin print())
1450
1630
  // 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);
1631
+ const receiver = (0, tree_sitter_helpers_1.getChildByField)(func, 'object') ||
1632
+ (0, tree_sitter_helpers_1.getChildByField)(func, 'operand') ||
1633
+ (0, tree_sitter_helpers_1.getChildByField)(func, 'argument') ||
1634
+ func.namedChild(0);
1452
1635
  const SKIP_RECEIVERS = new Set(['self', 'this', 'cls', 'super']);
1453
- if (receiver && (receiver.type === 'identifier' || receiver.type === 'simple_identifier')) {
1636
+ if (receiver && (receiver.type === 'identifier' || receiver.type === 'simple_identifier' || receiver.type === 'field_identifier')) {
1454
1637
  const receiverName = (0, tree_sitter_helpers_1.getNodeText)(receiver, this.source);
1455
1638
  if (!SKIP_RECEIVERS.has(receiverName)) {
1456
1639
  calleeName = `${receiverName}.${methodName}`;
@@ -1531,6 +1714,76 @@ class TreeSitterExtractor {
1531
1714
  });
1532
1715
  }
1533
1716
  }
1717
+ /**
1718
+ * Find a `class_body` child of an `object_creation_expression` — the
1719
+ * marker for an anonymous class (`new T() { ... }`). Returns the body
1720
+ * node so the caller can walk it as the anon class's members.
1721
+ */
1722
+ findAnonymousClassBody(node) {
1723
+ for (let i = 0; i < node.namedChildCount; i++) {
1724
+ const child = node.namedChild(i);
1725
+ // Java: `class_body`. C# uses the same node kind.
1726
+ if (child && (child.type === 'class_body' || child.type === 'declaration_list')) {
1727
+ return child;
1728
+ }
1729
+ }
1730
+ return null;
1731
+ }
1732
+ /**
1733
+ * Extract a Java/C# anonymous class — `new T() { ...members }`. Emits a
1734
+ * `class` node named `<T$anon@line>`, an `extends` reference to T (so
1735
+ * Phase 5.5 interface-impl can bridge), and walks the body so its
1736
+ * `method_declaration` members become method nodes under the anon class.
1737
+ *
1738
+ * Why this matters: without anon-class extraction, the overrides inside
1739
+ * a lambda-returned `new T() { @Override int foo(){...} }` are not nodes,
1740
+ * so a call through T.foo (the abstract parent method) has no static
1741
+ * target — the agent has to Read the file to find the implementation.
1742
+ */
1743
+ extractAnonymousClass(node, body) {
1744
+ if (!this.extractor)
1745
+ return;
1746
+ // The instantiated type sits in the same field/position that
1747
+ // extractInstantiation reads from. Use the same lookup so the anon
1748
+ // class's `extends` target matches the `instantiates` edge.
1749
+ const typeNode = (0, tree_sitter_helpers_1.getChildByField)(node, 'constructor') ||
1750
+ (0, tree_sitter_helpers_1.getChildByField)(node, 'type') ||
1751
+ (0, tree_sitter_helpers_1.getChildByField)(node, 'name') ||
1752
+ node.namedChild(0);
1753
+ let typeName = typeNode ? (0, tree_sitter_helpers_1.getNodeText)(typeNode, this.source) : 'Object';
1754
+ const ltIdx = typeName.indexOf('<');
1755
+ if (ltIdx > 0)
1756
+ typeName = typeName.slice(0, ltIdx);
1757
+ const lastDot = Math.max(typeName.lastIndexOf('.'), typeName.lastIndexOf('::'));
1758
+ if (lastDot >= 0)
1759
+ typeName = typeName.slice(lastDot + 1).replace(/^[:.]/, '');
1760
+ typeName = typeName.trim() || 'Object';
1761
+ const anonName = `<${typeName}$anon@${node.startPosition.row + 1}>`;
1762
+ const classNode = this.createNode('class', anonName, node, {});
1763
+ if (!classNode)
1764
+ return;
1765
+ // The anonymous class implicitly extends/implements the named type.
1766
+ // We can't tell at extraction time whether T is a class or an interface,
1767
+ // so emit `extends`. Resolution will still bind T to whatever it is, and
1768
+ // Phase 5.5 (which already handles both `extends` and `implements`) will
1769
+ // bridge T's methods to the override names found in the anon body.
1770
+ this.unresolvedReferences.push({
1771
+ fromNodeId: classNode.id,
1772
+ referenceName: typeName,
1773
+ referenceKind: 'extends',
1774
+ line: typeNode?.startPosition.row ?? node.startPosition.row,
1775
+ column: typeNode?.startPosition.column ?? node.startPosition.column,
1776
+ });
1777
+ // Walk the body's children so method_declaration nodes inside become
1778
+ // method nodes scoped to the anon class.
1779
+ this.nodeStack.push(classNode.id);
1780
+ for (let i = 0; i < body.namedChildCount; i++) {
1781
+ const child = body.namedChild(i);
1782
+ if (child)
1783
+ this.visitNode(child);
1784
+ }
1785
+ this.nodeStack.pop();
1786
+ }
1534
1787
  /**
1535
1788
  * Scan `declNode` and its preceding siblings (within the parent's
1536
1789
  * named children) for decorator nodes, emitting a `decorates`
@@ -1661,6 +1914,14 @@ class TreeSitterExtractor {
1661
1914
  // about `call_expression`, so constructor invocations
1662
1915
  // produced no graph edges at all.
1663
1916
  this.extractInstantiation(node);
1917
+ // Anonymous class with body: `new T() { ... }` (Java/C#). Extract as
1918
+ // a class so interface-impl synthesis (Phase 5.5) can bridge T's
1919
+ // methods to the overrides — same rationale as in visitNode.
1920
+ const anonBody = this.findAnonymousClassBody(node);
1921
+ if (anonBody) {
1922
+ this.extractAnonymousClass(node, anonBody);
1923
+ return;
1924
+ }
1664
1925
  }
1665
1926
  else if (this.extractor.extractBareCall) {
1666
1927
  const calleeName = this.extractor.extractBareCall(node, this.source);
@@ -2083,6 +2344,16 @@ class TreeSitterExtractor {
2083
2344
  return;
2084
2345
  if (!this.TYPE_ANNOTATION_LANGUAGES.has(this.language))
2085
2346
  return;
2347
+ // C# tree-sitter doesn't produce `type_identifier` leaves — it uses
2348
+ // `identifier`, `predefined_type`, `qualified_name`, `generic_name`,
2349
+ // etc. — so the generic walker below emits zero references for it.
2350
+ // Dispatch to a C#-aware path that only walks type-position subtrees
2351
+ // (the `type` field of a parameter/method/property/field), so
2352
+ // parameter NAMES never accidentally surface as type refs (#381).
2353
+ if (this.language === 'csharp') {
2354
+ this.extractCsharpTypeRefs(node, nodeId);
2355
+ return;
2356
+ }
2086
2357
  // Extract parameter type annotations
2087
2358
  const params = (0, tree_sitter_helpers_1.getChildByField)(node, this.extractor.paramsField || 'parameters');
2088
2359
  if (params) {
@@ -2099,6 +2370,112 @@ class TreeSitterExtractor {
2099
2370
  this.extractTypeRefsFromSubtree(typeAnnotation, nodeId);
2100
2371
  }
2101
2372
  }
2373
+ /**
2374
+ * Extract C# type references from a node that owns a type position —
2375
+ * a method/constructor declaration, a property declaration, or a
2376
+ * field declaration (which wraps `variable_declaration → type`).
2377
+ *
2378
+ * Walks ONLY into known type fields, so parameter names like
2379
+ * `request` in `Build(UserDto request)` are never mis-emitted as
2380
+ * type references. Once inside a type subtree, `walkCsharpTypePosition`
2381
+ * recognizes C#'s actual type-leaf node kinds (`identifier`,
2382
+ * `qualified_name`, `generic_name`, `array_type`, `nullable_type`,
2383
+ * `tuple_type`, …) — none of which are `type_identifier`. Closes #381.
2384
+ */
2385
+ extractCsharpTypeRefs(node, nodeId) {
2386
+ // Return type / property type — the field is named `type`.
2387
+ const directType = (0, tree_sitter_helpers_1.getChildByField)(node, 'type');
2388
+ if (directType)
2389
+ this.walkCsharpTypePosition(directType, nodeId);
2390
+ // Field declarations wrap declarators in a `variable_declaration`
2391
+ // whose `type` field carries the type. The outer `field_declaration`
2392
+ // has no `type` field of its own, so the call above is a no-op here
2393
+ // and we descend one level.
2394
+ const varDecl = node.namedChildren.find((c) => c.type === 'variable_declaration');
2395
+ if (varDecl) {
2396
+ const vdType = (0, tree_sitter_helpers_1.getChildByField)(varDecl, 'type');
2397
+ if (vdType)
2398
+ this.walkCsharpTypePosition(vdType, nodeId);
2399
+ }
2400
+ // Method / constructor parameters. The field name on
2401
+ // `method_declaration` is `parameters`; it points at a
2402
+ // `parameter_list` whose `parameter` children each have their own
2403
+ // `type` field. Walking ONLY the type field skips parameter NAMES,
2404
+ // which would otherwise mis-emit as type references.
2405
+ const params = (0, tree_sitter_helpers_1.getChildByField)(node, 'parameters');
2406
+ if (params) {
2407
+ for (let i = 0; i < params.namedChildCount; i++) {
2408
+ const child = params.namedChild(i);
2409
+ if (!child || child.type !== 'parameter')
2410
+ continue;
2411
+ const paramType = (0, tree_sitter_helpers_1.getChildByField)(child, 'type');
2412
+ if (paramType)
2413
+ this.walkCsharpTypePosition(paramType, nodeId);
2414
+ }
2415
+ }
2416
+ }
2417
+ /**
2418
+ * Walk a C# subtree that is KNOWN to be in a type position
2419
+ * (return type, parameter type, property type, field type, generic
2420
+ * argument). Identifiers here are type names, not parameter names.
2421
+ */
2422
+ walkCsharpTypePosition(node, fromNodeId) {
2423
+ // `predefined_type` is int/string/bool/etc. — never a project ref.
2424
+ if (node.type === 'predefined_type')
2425
+ return;
2426
+ // Bare type name: `Foo` in `Foo bar`, or the `Foo` inside `List<Foo>`.
2427
+ if (node.type === 'identifier') {
2428
+ const name = (0, tree_sitter_helpers_1.getNodeText)(node, this.source);
2429
+ if (name && !this.BUILTIN_TYPES.has(name)) {
2430
+ this.unresolvedReferences.push({
2431
+ fromNodeId,
2432
+ referenceName: name,
2433
+ referenceKind: 'references',
2434
+ line: node.startPosition.row + 1,
2435
+ column: node.startPosition.column,
2436
+ });
2437
+ }
2438
+ return;
2439
+ }
2440
+ // `Namespace.Foo` → the rightmost identifier is the type. Emit the
2441
+ // full qualified name as the reference; the resolver can still match
2442
+ // on the trailing simple name when needed.
2443
+ if (node.type === 'qualified_name') {
2444
+ const text = (0, tree_sitter_helpers_1.getNodeText)(node, this.source);
2445
+ const last = text.split('.').pop() ?? text;
2446
+ if (last && !this.BUILTIN_TYPES.has(last)) {
2447
+ this.unresolvedReferences.push({
2448
+ fromNodeId,
2449
+ referenceName: last,
2450
+ referenceKind: 'references',
2451
+ line: node.startPosition.row + 1,
2452
+ column: node.startPosition.column,
2453
+ });
2454
+ }
2455
+ return;
2456
+ }
2457
+ // `(int Code, Foo Payload)` — tuple element has BOTH a `type` and a
2458
+ // `name` field; descending into all named children would mis-emit
2459
+ // the element name (`Code`, `Payload`) as a type ref. Walk only the
2460
+ // type field.
2461
+ if (node.type === 'tuple_element') {
2462
+ const t = (0, tree_sitter_helpers_1.getChildByField)(node, 'type');
2463
+ if (t)
2464
+ this.walkCsharpTypePosition(t, fromNodeId);
2465
+ return;
2466
+ }
2467
+ // Composite type nodes — recurse into named children. Covers
2468
+ // `generic_name` (head identifier + `type_argument_list`),
2469
+ // `nullable_type`, `array_type`, `pointer_type`, `tuple_type`,
2470
+ // `ref_type`, and any newer wrapping shapes the grammar adds.
2471
+ // Identifiers reached here are all type-positional (parameter/field
2472
+ // names are gated out before we descend).
2473
+ for (let i = 0; i < node.namedChildCount; i++) {
2474
+ const child = node.namedChild(i);
2475
+ if (child)
2476
+ this.walkCsharpTypePosition(child, fromNodeId);
2477
+ }
2478
+ }
2102
2479
  /**
2103
2480
  * Extract type references from a variable's type annotation.
2104
2481
  */
@@ -2535,10 +2912,17 @@ function extractFromSource(filePath, source, language, frameworkNames) {
2535
2912
  const extractor = new liquid_extractor_1.LiquidExtractor(filePath, source);
2536
2913
  result = extractor.extract();
2537
2914
  }
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.
2915
+ else if (detectedLanguage === 'xml') {
2916
+ // Custom extractor for MyBatis mapper XML. Non-mapper XML returns just a
2917
+ // file node so the watcher tracks it without emitting symbols.
2918
+ const extractor = new mybatis_extractor_1.MyBatisExtractor(filePath, source);
2919
+ result = extractor.extract();
2920
+ }
2921
+ else if (detectedLanguage === 'yaml' || detectedLanguage === 'twig' || detectedLanguage === 'properties') {
2922
+ // No symbol extraction at this stage — files are tracked at the file-record
2923
+ // level only. Framework extractors (Drupal routing yml, Spring `@Value`
2924
+ // resolution against application.yml/application.properties) run later and
2925
+ // add per-file nodes/references when they apply.
2542
2926
  result = { nodes: [], edges: [], unresolvedReferences: [], errors: [], durationMs: 0 };
2543
2927
  }
2544
2928
  else if (detectedLanguage === 'pascal' &&