@colbymchenry/codegraph-darwin-arm64 0.9.4 → 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 (199) hide show
  1. package/lib/dist/bin/codegraph.js +12 -0
  2. package/lib/dist/bin/codegraph.js.map +1 -1
  3. package/lib/dist/db/queries.d.ts +1 -0
  4. package/lib/dist/db/queries.d.ts.map +1 -1
  5. package/lib/dist/db/queries.js +31 -3
  6. package/lib/dist/db/queries.js.map +1 -1
  7. package/lib/dist/extraction/grammars.d.ts +1 -1
  8. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  9. package/lib/dist/extraction/grammars.js +29 -1
  10. package/lib/dist/extraction/grammars.js.map +1 -1
  11. package/lib/dist/extraction/index.d.ts +15 -2
  12. package/lib/dist/extraction/index.d.ts.map +1 -1
  13. package/lib/dist/extraction/index.js +170 -78
  14. package/lib/dist/extraction/index.js.map +1 -1
  15. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  16. package/lib/dist/extraction/languages/c-cpp.js +45 -0
  17. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  18. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
  19. package/lib/dist/extraction/languages/csharp.js +2 -1
  20. package/lib/dist/extraction/languages/csharp.js.map +1 -1
  21. package/lib/dist/extraction/languages/go.d.ts.map +1 -1
  22. package/lib/dist/extraction/languages/go.js +12 -0
  23. package/lib/dist/extraction/languages/go.js.map +1 -1
  24. package/lib/dist/extraction/languages/index.d.ts.map +1 -1
  25. package/lib/dist/extraction/languages/index.js +2 -0
  26. package/lib/dist/extraction/languages/index.js.map +1 -1
  27. package/lib/dist/extraction/languages/objc.d.ts +3 -0
  28. package/lib/dist/extraction/languages/objc.d.ts.map +1 -0
  29. package/lib/dist/extraction/languages/objc.js +133 -0
  30. package/lib/dist/extraction/languages/objc.js.map +1 -0
  31. package/lib/dist/extraction/mybatis-extractor.d.ts +48 -0
  32. package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  33. package/lib/dist/extraction/mybatis-extractor.js +198 -0
  34. package/lib/dist/extraction/mybatis-extractor.js.map +1 -0
  35. package/lib/dist/extraction/tree-sitter-types.d.ts +4 -0
  36. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  37. package/lib/dist/extraction/tree-sitter.d.ts +33 -0
  38. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  39. package/lib/dist/extraction/tree-sitter.js +351 -14
  40. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  41. package/lib/dist/index.d.ts +21 -2
  42. package/lib/dist/index.d.ts.map +1 -1
  43. package/lib/dist/index.js +53 -1
  44. package/lib/dist/index.js.map +1 -1
  45. package/lib/dist/installer/index.d.ts +1 -1
  46. package/lib/dist/installer/index.js +3 -3
  47. package/lib/dist/installer/index.js.map +1 -1
  48. package/lib/dist/installer/instructions-template.d.ts +2 -2
  49. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  50. package/lib/dist/installer/instructions-template.js +1 -1
  51. package/lib/dist/installer/targets/antigravity.d.ts +57 -0
  52. package/lib/dist/installer/targets/antigravity.d.ts.map +1 -0
  53. package/lib/dist/installer/targets/antigravity.js +307 -0
  54. package/lib/dist/installer/targets/antigravity.js.map +1 -0
  55. package/lib/dist/installer/targets/gemini.d.ts +26 -0
  56. package/lib/dist/installer/targets/gemini.d.ts.map +1 -0
  57. package/lib/dist/installer/targets/gemini.js +165 -0
  58. package/lib/dist/installer/targets/gemini.js.map +1 -0
  59. package/lib/dist/installer/targets/hermes.d.ts.map +1 -1
  60. package/lib/dist/installer/targets/hermes.js +57 -3
  61. package/lib/dist/installer/targets/hermes.js.map +1 -1
  62. package/lib/dist/installer/targets/kiro.d.ts +27 -0
  63. package/lib/dist/installer/targets/kiro.d.ts.map +1 -0
  64. package/lib/dist/installer/targets/kiro.js +196 -0
  65. package/lib/dist/installer/targets/kiro.js.map +1 -0
  66. package/lib/dist/installer/targets/registry.d.ts.map +1 -1
  67. package/lib/dist/installer/targets/registry.js +6 -0
  68. package/lib/dist/installer/targets/registry.js.map +1 -1
  69. package/lib/dist/installer/targets/types.d.ts +1 -1
  70. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  71. package/lib/dist/mcp/daemon-paths.d.ts +46 -0
  72. package/lib/dist/mcp/daemon-paths.d.ts.map +1 -0
  73. package/lib/dist/mcp/daemon-paths.js +125 -0
  74. package/lib/dist/mcp/daemon-paths.js.map +1 -0
  75. package/lib/dist/mcp/daemon.d.ts +161 -0
  76. package/lib/dist/mcp/daemon.d.ts.map +1 -0
  77. package/lib/dist/mcp/daemon.js +403 -0
  78. package/lib/dist/mcp/daemon.js.map +1 -0
  79. package/lib/dist/mcp/engine.d.ts +100 -0
  80. package/lib/dist/mcp/engine.d.ts.map +1 -0
  81. package/lib/dist/mcp/engine.js +291 -0
  82. package/lib/dist/mcp/engine.js.map +1 -0
  83. package/lib/dist/mcp/index.d.ts +64 -53
  84. package/lib/dist/mcp/index.d.ts.map +1 -1
  85. package/lib/dist/mcp/index.js +307 -387
  86. package/lib/dist/mcp/index.js.map +1 -1
  87. package/lib/dist/mcp/proxy.d.ts +46 -0
  88. package/lib/dist/mcp/proxy.d.ts.map +1 -0
  89. package/lib/dist/mcp/proxy.js +276 -0
  90. package/lib/dist/mcp/proxy.js.map +1 -0
  91. package/lib/dist/mcp/server-instructions.d.ts +1 -1
  92. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  93. package/lib/dist/mcp/server-instructions.js +1 -1
  94. package/lib/dist/mcp/session.d.ts +67 -0
  95. package/lib/dist/mcp/session.d.ts.map +1 -0
  96. package/lib/dist/mcp/session.js +276 -0
  97. package/lib/dist/mcp/session.js.map +1 -0
  98. package/lib/dist/mcp/tools.d.ts +49 -0
  99. package/lib/dist/mcp/tools.d.ts.map +1 -1
  100. package/lib/dist/mcp/tools.js +253 -17
  101. package/lib/dist/mcp/tools.js.map +1 -1
  102. package/lib/dist/mcp/transport.d.ts +111 -29
  103. package/lib/dist/mcp/transport.d.ts.map +1 -1
  104. package/lib/dist/mcp/transport.js +181 -71
  105. package/lib/dist/mcp/transport.js.map +1 -1
  106. package/lib/dist/mcp/version.d.ts +19 -0
  107. package/lib/dist/mcp/version.d.ts.map +1 -0
  108. package/lib/dist/mcp/version.js +71 -0
  109. package/lib/dist/mcp/version.js.map +1 -0
  110. package/lib/dist/resolution/callback-synthesizer.d.ts +3 -2
  111. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  112. package/lib/dist/resolution/callback-synthesizer.js +351 -3
  113. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  114. package/lib/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  115. package/lib/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  116. package/lib/dist/resolution/frameworks/expo-modules.js +143 -0
  117. package/lib/dist/resolution/frameworks/expo-modules.js.map +1 -0
  118. package/lib/dist/resolution/frameworks/fabric.d.ts +3 -0
  119. package/lib/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  120. package/lib/dist/resolution/frameworks/fabric.js +354 -0
  121. package/lib/dist/resolution/frameworks/fabric.js.map +1 -0
  122. package/lib/dist/resolution/frameworks/index.d.ts +4 -0
  123. package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
  124. package/lib/dist/resolution/frameworks/index.js +21 -1
  125. package/lib/dist/resolution/frameworks/index.js.map +1 -1
  126. package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
  127. package/lib/dist/resolution/frameworks/java.js +270 -1
  128. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  129. package/lib/dist/resolution/frameworks/nestjs.d.ts.map +1 -1
  130. package/lib/dist/resolution/frameworks/nestjs.js +324 -0
  131. package/lib/dist/resolution/frameworks/nestjs.js.map +1 -1
  132. package/lib/dist/resolution/frameworks/react-native.d.ts +3 -0
  133. package/lib/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  134. package/lib/dist/resolution/frameworks/react-native.js +360 -0
  135. package/lib/dist/resolution/frameworks/react-native.js.map +1 -0
  136. package/lib/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  137. package/lib/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  138. package/lib/dist/resolution/frameworks/swift-objc.js +252 -0
  139. package/lib/dist/resolution/frameworks/swift-objc.js.map +1 -0
  140. package/lib/dist/resolution/go-module.d.ts +26 -0
  141. package/lib/dist/resolution/go-module.d.ts.map +1 -0
  142. package/lib/dist/resolution/go-module.js +78 -0
  143. package/lib/dist/resolution/go-module.js.map +1 -0
  144. package/lib/dist/resolution/import-resolver.d.ts +18 -0
  145. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  146. package/lib/dist/resolution/import-resolver.js +538 -4
  147. package/lib/dist/resolution/import-resolver.js.map +1 -1
  148. package/lib/dist/resolution/index.d.ts +10 -0
  149. package/lib/dist/resolution/index.d.ts.map +1 -1
  150. package/lib/dist/resolution/index.js +102 -0
  151. package/lib/dist/resolution/index.js.map +1 -1
  152. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  153. package/lib/dist/resolution/name-matcher.js +212 -0
  154. package/lib/dist/resolution/name-matcher.js.map +1 -1
  155. package/lib/dist/resolution/swift-objc-bridge.d.ts +134 -0
  156. package/lib/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  157. package/lib/dist/resolution/swift-objc-bridge.js +256 -0
  158. package/lib/dist/resolution/swift-objc-bridge.js.map +1 -0
  159. package/lib/dist/resolution/types.d.ts +29 -0
  160. package/lib/dist/resolution/types.d.ts.map +1 -1
  161. package/lib/dist/sync/index.d.ts +3 -1
  162. package/lib/dist/sync/index.d.ts.map +1 -1
  163. package/lib/dist/sync/index.js +8 -1
  164. package/lib/dist/sync/index.js.map +1 -1
  165. package/lib/dist/sync/watcher.d.ts +119 -7
  166. package/lib/dist/sync/watcher.d.ts.map +1 -1
  167. package/lib/dist/sync/watcher.js +243 -37
  168. package/lib/dist/sync/watcher.js.map +1 -1
  169. package/lib/dist/sync/worktree.d.ts +54 -0
  170. package/lib/dist/sync/worktree.d.ts.map +1 -0
  171. package/lib/dist/sync/worktree.js +136 -0
  172. package/lib/dist/sync/worktree.js.map +1 -0
  173. package/lib/dist/types.d.ts +1 -1
  174. package/lib/dist/types.d.ts.map +1 -1
  175. package/lib/dist/types.js +3 -0
  176. package/lib/dist/types.js.map +1 -1
  177. package/lib/node_modules/.package-lock.json +29 -1
  178. package/lib/node_modules/chokidar/LICENSE +21 -0
  179. package/lib/node_modules/chokidar/README.md +305 -0
  180. package/lib/node_modules/chokidar/esm/handler.d.ts +90 -0
  181. package/lib/node_modules/chokidar/esm/handler.js +629 -0
  182. package/lib/node_modules/chokidar/esm/index.d.ts +215 -0
  183. package/lib/node_modules/chokidar/esm/index.js +798 -0
  184. package/lib/node_modules/chokidar/esm/package.json +1 -0
  185. package/lib/node_modules/chokidar/handler.d.ts +90 -0
  186. package/lib/node_modules/chokidar/handler.js +635 -0
  187. package/lib/node_modules/chokidar/index.d.ts +215 -0
  188. package/lib/node_modules/chokidar/index.js +804 -0
  189. package/lib/node_modules/chokidar/package.json +69 -0
  190. package/lib/node_modules/readdirp/LICENSE +21 -0
  191. package/lib/node_modules/readdirp/README.md +120 -0
  192. package/lib/node_modules/readdirp/esm/index.d.ts +108 -0
  193. package/lib/node_modules/readdirp/esm/index.js +257 -0
  194. package/lib/node_modules/readdirp/esm/package.json +1 -0
  195. package/lib/node_modules/readdirp/index.d.ts +108 -0
  196. package/lib/node_modules/readdirp/index.js +263 -0
  197. package/lib/node_modules/readdirp/package.json +70 -0
  198. package/lib/package.json +2 -1
  199. package/package.json +1 -1
@@ -39,10 +39,13 @@ var __importStar = (this && this.__importStar) || (function () {
39
39
  })();
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
41
  exports.resolveImportPath = resolveImportPath;
42
+ exports.clearCppIncludeDirCache = clearCppIncludeDirCache;
43
+ exports.loadCppIncludeDirs = loadCppIncludeDirs;
42
44
  exports.extractImportMappings = extractImportMappings;
43
45
  exports.clearImportMappingCache = clearImportMappingCache;
44
46
  exports.extractReExports = extractReExports;
45
47
  exports.resolveViaImport = resolveViaImport;
48
+ const fs = __importStar(require("fs"));
46
49
  const path = __importStar(require("path"));
47
50
  const path_aliases_1 = require("./path-aliases");
48
51
  /**
@@ -57,9 +60,12 @@ const EXTENSION_RESOLUTION = {
57
60
  go: ['.go'],
58
61
  rust: ['.rs', '/mod.rs'],
59
62
  java: ['.java'],
63
+ c: ['.h', '.c'],
64
+ cpp: ['.h', '.hpp', '.hxx', '.cpp', '.cc', '.cxx'],
60
65
  csharp: ['.cs'],
61
66
  php: ['.php'],
62
67
  ruby: ['.rb'],
68
+ objc: ['.h', '.m', '.mm'],
63
69
  };
64
70
  /**
65
71
  * Resolve an import path to an actual file
@@ -79,8 +85,53 @@ function resolveImportPath(importPath, fromFile, language, context) {
79
85
  return resolveRelativeImport(importPath, fromDir, language, context);
80
86
  }
81
87
  // Handle absolute/aliased imports (like @/ or src/)
82
- return resolveAliasedImport(importPath, projectRoot, language, context);
88
+ const aliased = resolveAliasedImport(importPath, projectRoot, language, context);
89
+ if (aliased)
90
+ return aliased;
91
+ // C/C++ include directory search: when neither relative nor aliased
92
+ // resolution found a match, search -I directories from
93
+ // compile_commands.json or heuristic probing.
94
+ if (language === 'c' || language === 'cpp') {
95
+ return resolveCppIncludePath(importPath, language, context);
96
+ }
97
+ return null;
83
98
  }
99
+ /**
100
+ * C and C++ standard library header names (without delimiters).
101
+ * Used by isExternalImport to filter system includes from resolution.
102
+ */
103
+ const C_CPP_STDLIB_HEADERS = new Set([
104
+ // C standard library headers
105
+ 'assert.h', 'complex.h', 'ctype.h', 'errno.h', 'fenv.h', 'float.h',
106
+ 'inttypes.h', 'iso646.h', 'limits.h', 'locale.h', 'math.h', 'setjmp.h',
107
+ 'signal.h', 'stdalign.h', 'stdarg.h', 'stdatomic.h', 'stdbool.h',
108
+ 'stddef.h', 'stdint.h', 'stdio.h', 'stdlib.h', 'stdnoreturn.h',
109
+ 'string.h', 'tgmath.h', 'threads.h', 'time.h', 'uchar.h', 'wchar.h',
110
+ 'wctype.h',
111
+ // C++ C-library wrappers (cname form)
112
+ 'cassert', 'ccomplex', 'cctype', 'cerrno', 'cfenv', 'cfloat',
113
+ 'cinttypes', 'ciso646', 'climits', 'clocale', 'cmath', 'csetjmp',
114
+ 'csignal', 'cstdalign', 'cstdarg', 'cstdbool', 'cstddef', 'cstdint',
115
+ 'cstdio', 'cstdlib', 'cstring', 'ctgmath', 'ctime', 'cuchar',
116
+ 'cwchar', 'cwctype',
117
+ // C++ STL headers
118
+ 'algorithm', 'any', 'array', 'atomic', 'barrier', 'bit', 'bitset',
119
+ 'charconv', 'chrono', 'codecvt', 'compare', 'complex', 'concepts',
120
+ 'condition_variable', 'coroutine', 'deque', 'exception', 'execution',
121
+ 'expected', 'filesystem', 'format', 'forward_list', 'fstream',
122
+ 'functional', 'future', 'generator', 'initializer_list', 'iomanip',
123
+ 'ios', 'iosfwd', 'iostream', 'istream', 'iterator', 'latch',
124
+ 'limits', 'list', 'locale', 'map', 'mdspan', 'memory', 'memory_resource',
125
+ 'mutex', 'new', 'numbers', 'numeric', 'optional', 'ostream', 'print',
126
+ 'queue', 'random', 'ranges', 'ratio', 'regex', 'scoped_allocator',
127
+ 'semaphore', 'set', 'shared_mutex', 'source_location', 'span',
128
+ 'spanstream', 'sstream', 'stack', 'stacktrace', 'stdexcept',
129
+ 'stdfloat', 'stop_token', 'streambuf', 'string', 'string_view',
130
+ 'strstream', 'syncstream', 'system_error', 'thread', 'tuple',
131
+ 'type_traits', 'typeindex', 'typeinfo', 'unordered_map',
132
+ 'unordered_set', 'utility', 'valarray', 'variant', 'vector',
133
+ 'version',
134
+ ]);
84
135
  /**
85
136
  * Check if an import is external (npm package, etc.)
86
137
  *
@@ -122,10 +173,35 @@ function isExternalImport(importPath, language, context) {
122
173
  }
123
174
  }
124
175
  if (language === 'go') {
125
- // Standard library or external packages
126
- if (!importPath.startsWith('.') && !importPath.includes('/internal/')) {
127
- return true;
176
+ // Relative imports (rare in idiomatic Go but the grammar allows them).
177
+ if (importPath.startsWith('.')) {
178
+ return false;
128
179
  }
180
+ // In-module imports look like `<module-path>/sub/pkg` — local to
181
+ // this project. Without the module-path check we'd flag every
182
+ // cross-package call in a Go monorepo as external (issue #388).
183
+ const mod = context?.getGoModule?.();
184
+ if (mod && (importPath === mod.modulePath || importPath.startsWith(mod.modulePath + '/'))) {
185
+ return false;
186
+ }
187
+ // `internal/` packages stay local even when go.mod is missing —
188
+ // preserves the pre-#388 escape hatch for repos without a parsed module path.
189
+ if (importPath.includes('/internal/')) {
190
+ return false;
191
+ }
192
+ // Anything else is the Go standard library or a third-party module.
193
+ return true;
194
+ }
195
+ if (language === 'c' || language === 'cpp') {
196
+ // C/C++ standard library headers — both C-style (<stdio.h>) and
197
+ // C++-style (<cstdio>, <vector>) forms. Checked against the import
198
+ // path (which the extractor strips of <> or "" delimiters).
199
+ if (C_CPP_STDLIB_HEADERS.has(importPath))
200
+ return true;
201
+ // C++ headers without .h extension (e.g. "vector", "string")
202
+ const withoutExt = importPath.replace(/\.h$/, '');
203
+ if (C_CPP_STDLIB_HEADERS.has(withoutExt))
204
+ return true;
129
205
  }
130
206
  return false;
131
207
  }
@@ -204,6 +280,215 @@ function resolveAliasedImport(importPath, projectRoot, language, context) {
204
280
  // 3. Direct path.
205
281
  return tryWithExt(importPath);
206
282
  }
283
+ /**
284
+ * C/C++ include directory cache (keyed by project root).
285
+ * Loaded once per resolver instance, shared across calls.
286
+ */
287
+ const cppIncludeDirCache = new Map();
288
+ /**
289
+ * Clear the C/C++ include directory cache (call between indexing runs)
290
+ */
291
+ function clearCppIncludeDirCache() {
292
+ cppIncludeDirCache.clear();
293
+ }
294
+ /**
295
+ * Discover C/C++ include search directories for a project.
296
+ *
297
+ * Strategy:
298
+ * 1. Look for compile_commands.json (Clang compilation database) in the
299
+ * project root and common build subdirectories. Parse -I and -isystem
300
+ * flags from compiler commands.
301
+ * 2. If no compilation database is found, probe for common convention
302
+ * directories (include/, src/, lib/, api/) and top-level directories
303
+ * containing .h/.hpp files.
304
+ *
305
+ * Returns paths relative to projectRoot.
306
+ */
307
+ function loadCppIncludeDirs(projectRoot) {
308
+ const cached = cppIncludeDirCache.get(projectRoot);
309
+ if (cached !== undefined)
310
+ return cached;
311
+ const dirs = loadCppIncludeDirsFromCompileDB(projectRoot)
312
+ || loadCppIncludeDirsHeuristic(projectRoot);
313
+ cppIncludeDirCache.set(projectRoot, dirs);
314
+ return dirs;
315
+ }
316
+ /**
317
+ * Try to load include directories from compile_commands.json.
318
+ * Returns null if no compilation database is found (so the heuristic
319
+ * fallback can run). Returns an array (possibly empty) otherwise.
320
+ */
321
+ function loadCppIncludeDirsFromCompileDB(projectRoot) {
322
+ const candidates = [
323
+ path.join(projectRoot, 'compile_commands.json'),
324
+ path.join(projectRoot, 'build', 'compile_commands.json'),
325
+ path.join(projectRoot, 'cmake-build-debug', 'compile_commands.json'),
326
+ path.join(projectRoot, 'cmake-build-release', 'compile_commands.json'),
327
+ path.join(projectRoot, 'out', 'compile_commands.json'),
328
+ ];
329
+ let dbPath;
330
+ for (const c of candidates) {
331
+ try {
332
+ if (fs.existsSync(c)) {
333
+ dbPath = c;
334
+ break;
335
+ }
336
+ }
337
+ catch {
338
+ // ignore
339
+ }
340
+ }
341
+ if (!dbPath)
342
+ return null;
343
+ try {
344
+ const content = fs.readFileSync(dbPath, 'utf-8');
345
+ const entries = JSON.parse(content);
346
+ if (!Array.isArray(entries))
347
+ return null;
348
+ const dirSet = new Set();
349
+ for (const entry of entries) {
350
+ const dir = entry.directory || projectRoot;
351
+ const args = entry.arguments || (entry.command ? shlexSplit(entry.command) : []);
352
+ for (let i = 0; i < args.length; i++) {
353
+ const arg = args[i];
354
+ let includeDir;
355
+ // -I<dir> (no space)
356
+ if (arg.startsWith('-I') && arg.length > 2) {
357
+ includeDir = arg.substring(2);
358
+ }
359
+ // -isystem <dir> (space-separated)
360
+ else if ((arg === '-isystem' || arg === '-I') && i + 1 < args.length) {
361
+ includeDir = args[i + 1];
362
+ i++; // skip next arg
363
+ }
364
+ if (includeDir) {
365
+ // Normalize: resolve relative to the compilation directory
366
+ const absPath = path.isAbsolute(includeDir)
367
+ ? includeDir
368
+ : path.resolve(dir, includeDir);
369
+ const relPath = path.relative(projectRoot, absPath).replace(/\\/g, '/');
370
+ // Skip system directories and paths outside the project
371
+ // (relative paths starting with .. or absolute paths like
372
+ // /usr/include or C:\usr on Windows)
373
+ if (!relPath.startsWith('..') && relPath.length > 0 && !path.isAbsolute(relPath)) {
374
+ dirSet.add(relPath);
375
+ }
376
+ }
377
+ }
378
+ }
379
+ return Array.from(dirSet);
380
+ }
381
+ catch {
382
+ return null;
383
+ }
384
+ }
385
+ /**
386
+ * Minimal shlex-style split for compiler command strings.
387
+ * Handles double-quoted and single-quoted arguments.
388
+ */
389
+ function shlexSplit(cmd) {
390
+ const result = [];
391
+ let i = 0;
392
+ while (i < cmd.length) {
393
+ // Skip whitespace
394
+ while (i < cmd.length && /\s/.test(cmd[i]))
395
+ i++;
396
+ if (i >= cmd.length)
397
+ break;
398
+ const ch = cmd[i];
399
+ if (ch === '"') {
400
+ i++;
401
+ let arg = '';
402
+ while (i < cmd.length && cmd[i] !== '"') {
403
+ if (cmd[i] === '\\' && i + 1 < cmd.length) {
404
+ i++;
405
+ arg += cmd[i];
406
+ }
407
+ else {
408
+ arg += cmd[i];
409
+ }
410
+ i++;
411
+ }
412
+ i++; // closing quote
413
+ result.push(arg);
414
+ }
415
+ else if (ch === "'") {
416
+ i++;
417
+ let arg = '';
418
+ while (i < cmd.length && cmd[i] !== "'") {
419
+ arg += cmd[i];
420
+ i++;
421
+ }
422
+ i++; // closing quote
423
+ result.push(arg);
424
+ }
425
+ else {
426
+ let arg = '';
427
+ while (i < cmd.length && !/\s/.test(cmd[i])) {
428
+ arg += cmd[i];
429
+ i++;
430
+ }
431
+ result.push(arg);
432
+ }
433
+ }
434
+ return result;
435
+ }
436
+ /**
437
+ * Heuristic include directory discovery when no compile_commands.json exists.
438
+ * Checks common convention directories and scans top-level dirs for headers.
439
+ */
440
+ function loadCppIncludeDirsHeuristic(projectRoot) {
441
+ const dirs = [];
442
+ const conventionDirs = ['include', 'src', 'lib', 'api', 'inc'];
443
+ try {
444
+ const entries = fs.readdirSync(projectRoot, { withFileTypes: true });
445
+ for (const entry of entries) {
446
+ if (!entry.isDirectory())
447
+ continue;
448
+ const name = entry.name;
449
+ // Convention directories
450
+ if (conventionDirs.includes(name.toLowerCase())) {
451
+ dirs.push(name);
452
+ continue;
453
+ }
454
+ // Any top-level directory containing .h or .hpp files
455
+ try {
456
+ const subFiles = fs.readdirSync(path.join(projectRoot, name));
457
+ if (subFiles.some(f => /\.(h|hpp|hxx|hh)$/i.test(f))) {
458
+ dirs.push(name);
459
+ }
460
+ }
461
+ catch {
462
+ // ignore permission errors
463
+ }
464
+ }
465
+ }
466
+ catch {
467
+ // ignore
468
+ }
469
+ return dirs;
470
+ }
471
+ /**
472
+ * Resolve a C/C++ include path by searching include directories.
473
+ * Called as a fallback after relative and aliased resolution fail.
474
+ */
475
+ function resolveCppIncludePath(importPath, language, context) {
476
+ const includeDirs = context.getCppIncludeDirs?.() ?? [];
477
+ const extensions = EXTENSION_RESOLUTION[language] ?? [];
478
+ for (const dir of includeDirs) {
479
+ const normalizedDir = dir.replace(/\\/g, '/');
480
+ for (const ext of extensions) {
481
+ const candidate = normalizedDir + '/' + importPath + ext;
482
+ if (context.fileExists(candidate))
483
+ return candidate;
484
+ }
485
+ // Try as-is (already has extension)
486
+ const candidate = normalizedDir + '/' + importPath;
487
+ if (context.fileExists(candidate))
488
+ return candidate;
489
+ }
490
+ return null;
491
+ }
207
492
  /**
208
493
  * Extract import mappings from a file
209
494
  */
@@ -218,9 +503,15 @@ function extractImportMappings(_filePath, content, language) {
218
503
  else if (language === 'go') {
219
504
  mappings.push(...extractGoImports(content));
220
505
  }
506
+ else if (language === 'java' || language === 'kotlin') {
507
+ mappings.push(...extractJavaImports(content));
508
+ }
221
509
  else if (language === 'php') {
222
510
  mappings.push(...extractPHPImports(content));
223
511
  }
512
+ else if (language === 'c' || language === 'cpp') {
513
+ mappings.push(...extractCppImports(content));
514
+ }
224
515
  return mappings;
225
516
  }
226
517
  /**
@@ -406,6 +697,50 @@ function extractGoImports(content) {
406
697
  }
407
698
  return mappings;
408
699
  }
700
+ /**
701
+ * Extract Java / Kotlin import mappings.
702
+ *
703
+ * Java/Kotlin imports carry the full qualified name of the imported
704
+ * symbol — `import com.example.dao.converter.FooConverter;` — which is
705
+ * exactly the disambiguation signal we need when two packages both
706
+ * declare a `FooConverter`. Pre-#314 the resolver had no Java branch
707
+ * here at all, so this mapping was empty and cross-module name
708
+ * collisions were resolved by file-path proximity (often wrongly).
709
+ *
710
+ * `import static com.example.Foo.bar;` is parsed as a local-name `bar`
711
+ * pointing at FQN `com.example.Foo.bar` so static-method call sites
712
+ * (`bar(...)`) can resolve through the same import lookup.
713
+ */
714
+ function extractJavaImports(content) {
715
+ const mappings = [];
716
+ // Strip line and block comments so `// import foo;` doesn't false-match.
717
+ const stripped = content
718
+ .replace(/\/\*[\s\S]*?\*\//g, '')
719
+ .replace(/\/\/[^\n]*/g, '');
720
+ // `import [static] <fqn>[.*];`
721
+ const re = /^\s*import\s+(static\s+)?([\w.]+(?:\.\*)?)\s*;/gm;
722
+ let match;
723
+ while ((match = re.exec(stripped)) !== null) {
724
+ const fqn = match[2];
725
+ // `import com.example.*;` — wildcard. We can't materialize a single
726
+ // local name; skip and let name-matching handle members reachable
727
+ // through the wildcard. (Future enhancement: enumerate package files.)
728
+ if (fqn.endsWith('.*'))
729
+ continue;
730
+ const parts = fqn.split('.');
731
+ const localName = parts[parts.length - 1];
732
+ if (!localName)
733
+ continue;
734
+ mappings.push({
735
+ localName,
736
+ exportedName: localName,
737
+ source: fqn,
738
+ isDefault: false,
739
+ isNamespace: false,
740
+ });
741
+ }
742
+ return mappings;
743
+ }
409
744
  /**
410
745
  * Extract PHP import mappings (use statements)
411
746
  */
@@ -427,6 +762,34 @@ function extractPHPImports(content) {
427
762
  }
428
763
  return mappings;
429
764
  }
765
+ /**
766
+ * Extract C/C++ import mappings from #include directives.
767
+ *
768
+ * #include brings all symbols from the included header into scope
769
+ * (namespace import), so each mapping uses isNamespace: true and
770
+ * exportedName: '*'. The localName is set to the header's basename
771
+ * without extension so that symbol references like `MyClass` can
772
+ * match against any include that might provide it.
773
+ */
774
+ function extractCppImports(content) {
775
+ const mappings = [];
776
+ // Match both #include <...> and #include "..."
777
+ const includeRegex = /^\s*#\s*include\s+[<"]([^>"]+)[>"]/gm;
778
+ let match;
779
+ while ((match = includeRegex.exec(content)) !== null) {
780
+ const modulePath = match[1];
781
+ // Basename without extension for localName matching
782
+ const basename = modulePath.split('/').pop().replace(/\.(h|hpp|hxx|hh|inl|ipp|cxx|cc|cpp)$/, '');
783
+ mappings.push({
784
+ localName: basename || modulePath,
785
+ exportedName: '*',
786
+ source: modulePath,
787
+ isDefault: false,
788
+ isNamespace: true,
789
+ });
790
+ }
791
+ return mappings;
792
+ }
430
793
  // Cache import mappings per file to avoid re-reading and re-parsing
431
794
  const importMappingCache = new Map();
432
795
  /**
@@ -434,6 +797,7 @@ const importMappingCache = new Map();
434
797
  */
435
798
  function clearImportMappingCache() {
436
799
  importMappingCache.clear();
800
+ cppIncludeDirCache.clear();
437
801
  }
438
802
  /**
439
803
  * Strip JS line + block comments from `content` while preserving
@@ -557,11 +921,55 @@ function extractReExports(content, language) {
557
921
  * Resolve a reference using import mappings
558
922
  */
559
923
  function resolveViaImport(ref, context) {
924
+ // C/C++ #include references — resolve directly to the included file
925
+ // (file→file edge), bypassing symbol lookup. The extractor emits these
926
+ // with `referenceKind: 'imports'` and `referenceName: <include path>`
927
+ // (e.g. "uint256.h" or "common/args.h"). Without this branch the
928
+ // include-dir scan path inside resolveImportPath never produces an
929
+ // edge — resolveViaImport's symbol lookup below would search the
930
+ // resolved file for a symbol named like the file extension and fail.
931
+ if ((ref.language === 'c' || ref.language === 'cpp') && ref.referenceKind === 'imports') {
932
+ const resolvedPath = resolveImportPath(ref.referenceName, ref.filePath, ref.language, context);
933
+ if (!resolvedPath)
934
+ return null;
935
+ const basename = resolvedPath.split('/').pop();
936
+ const fileNodes = context.getNodesByName(basename).filter((n) => n.kind === 'file');
937
+ const fileNode = fileNodes.find((n) => n.filePath === resolvedPath);
938
+ if (fileNode) {
939
+ return {
940
+ original: ref,
941
+ targetNodeId: fileNode.id,
942
+ confidence: 0.9,
943
+ resolvedBy: 'import',
944
+ };
945
+ }
946
+ return null;
947
+ }
560
948
  // Use cached import mappings (avoids re-reading and re-parsing per ref)
561
949
  const imports = context.getImportMappings(ref.filePath, ref.language);
562
950
  if (imports.length === 0 && !context.readFile(ref.filePath)) {
563
951
  return null;
564
952
  }
953
+ // Go cross-package calls: `pkga.FuncX(...)` extracts to referenceName
954
+ // `pkga.FuncX` and the import `github.com/example/myproject/pkga`
955
+ // maps to a *package directory* containing one or more .go files.
956
+ // The generic file-based lookup below can't follow that — issue #388.
957
+ if (ref.language === 'go') {
958
+ const goResult = resolveGoCrossPackageReference(ref, imports, context);
959
+ if (goResult)
960
+ return goResult;
961
+ }
962
+ // Java / Kotlin: imports are FQNs (`import com.example.Foo;`) — no
963
+ // resolvable file path the JS/TS-style chain below could follow. Look
964
+ // up the symbol by name and filter to the candidate whose file path
965
+ // matches the imported FQN. This is the disambiguation signal that
966
+ // breaks the same-name class collision the path-proximity matcher
967
+ // can't resolve (issue #314).
968
+ if (ref.language === 'java' || ref.language === 'kotlin') {
969
+ const javaResult = resolveJavaImportedReference(ref, imports, context);
970
+ if (javaResult)
971
+ return javaResult;
972
+ }
565
973
  // Check if the reference name matches any import
566
974
  for (const imp of imports) {
567
975
  if (imp.localName === ref.referenceName || ref.referenceName.startsWith(imp.localName + '.')) {
@@ -586,6 +994,132 @@ function resolveViaImport(ref, context) {
586
994
  }
587
995
  return null;
588
996
  }
997
+ /**
998
+ * Resolve a Java/Kotlin reference whose receiver is the simple name of
999
+ * an imported FQN: `Foo.bar(...)` where `import com.example.Foo;`. The
1000
+ * imported FQN converts to a file-path suffix (`com/example/Foo.java`
1001
+ * or `.kt`) which uniquely identifies the right symbol when multiple
1002
+ * classes share the same simple name.
1003
+ *
1004
+ * Also handles bare references to the imported class itself
1005
+ * (`new Foo()` extraction emits `Foo` as a `references`/`instantiates`
1006
+ * ref) and `import static <Foo>.bar` style imports of a single member.
1007
+ */
1008
+ function resolveJavaImportedReference(ref, imports, context) {
1009
+ if (imports.length === 0)
1010
+ return null;
1011
+ const ext = ref.language === 'kotlin' ? '.kt' : '.java';
1012
+ for (const imp of imports) {
1013
+ const matchesBare = imp.localName === ref.referenceName;
1014
+ const matchesQualified = ref.referenceName.startsWith(imp.localName + '.');
1015
+ if (!matchesBare && !matchesQualified)
1016
+ continue;
1017
+ // Convert FQN to a file-path suffix. `com.example.Foo` ->
1018
+ // `com/example/Foo.java` (or `.kt`). The actual file may live
1019
+ // under any source root (`src/main/java/`, `src/`, etc.), so match
1020
+ // by suffix rather than exact path.
1021
+ const fqnPath = imp.source.replace(/\./g, '/') + ext;
1022
+ // Which symbol name to look up: the class itself, or a member.
1023
+ const memberName = matchesBare
1024
+ ? imp.localName
1025
+ : ref.referenceName.substring(imp.localName.length + 1);
1026
+ const candidates = context.getNodesByName(memberName);
1027
+ for (const node of candidates) {
1028
+ if (node.language !== ref.language)
1029
+ continue;
1030
+ const fp = node.filePath.replace(/\\/g, '/');
1031
+ if (fp.endsWith(fqnPath) || fp.endsWith('/' + fqnPath)) {
1032
+ return {
1033
+ original: ref,
1034
+ targetNodeId: node.id,
1035
+ confidence: 0.9,
1036
+ resolvedBy: 'import',
1037
+ };
1038
+ }
1039
+ }
1040
+ // `import static com.example.Foo.bar;` — the FQN's tail is the
1041
+ // member name, the part before is the owner class. Look up the
1042
+ // member named `<imp.localName>` (e.g. `bar`) and prefer the
1043
+ // candidate whose file matches the parent FQN's path.
1044
+ if (matchesBare) {
1045
+ const dot = imp.source.lastIndexOf('.');
1046
+ if (dot > 0) {
1047
+ const ownerFqn = imp.source.substring(0, dot);
1048
+ const ownerPath = ownerFqn.replace(/\./g, '/') + ext;
1049
+ for (const node of candidates) {
1050
+ if (node.language !== ref.language)
1051
+ continue;
1052
+ const fp = node.filePath.replace(/\\/g, '/');
1053
+ if (fp.endsWith(ownerPath) || fp.endsWith('/' + ownerPath)) {
1054
+ return {
1055
+ original: ref,
1056
+ targetNodeId: node.id,
1057
+ confidence: 0.9,
1058
+ resolvedBy: 'import',
1059
+ };
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+ }
1065
+ return null;
1066
+ }
1067
+ /**
1068
+ * Resolve a Go cross-package qualified reference (`pkga.FuncX`) by matching
1069
+ * the package alias against an in-module import, stripping the module prefix
1070
+ * to a project-relative directory, and locating the exported symbol in any
1071
+ * `.go` file under that directory. Returns `null` for stdlib / third-party
1072
+ * imports (no `go.mod`-relative match) so the rest of `resolveViaImport`
1073
+ * can still try the file-based path.
1074
+ */
1075
+ function resolveGoCrossPackageReference(ref, imports, context) {
1076
+ const mod = context.getGoModule?.();
1077
+ if (!mod)
1078
+ return null;
1079
+ // Qualified call: receiver before `.`, member after. A bare reference
1080
+ // (no dot) is a same-file/in-package call — handled elsewhere.
1081
+ const dotIdx = ref.referenceName.indexOf('.');
1082
+ if (dotIdx <= 0)
1083
+ return null;
1084
+ const receiver = ref.referenceName.substring(0, dotIdx);
1085
+ const memberName = ref.referenceName.substring(dotIdx + 1);
1086
+ if (!memberName)
1087
+ return null;
1088
+ for (const imp of imports) {
1089
+ if (imp.localName !== receiver)
1090
+ continue;
1091
+ // Only in-module imports map to a known directory.
1092
+ if (imp.source !== mod.modulePath && !imp.source.startsWith(mod.modulePath + '/')) {
1093
+ continue;
1094
+ }
1095
+ const pkgDir = imp.source === mod.modulePath
1096
+ ? ''
1097
+ : imp.source.substring(mod.modulePath.length + 1);
1098
+ // Look up the member by name and pick the candidate whose file lives
1099
+ // directly in the package directory. Match the immediate parent dir
1100
+ // exactly so a call to `pkga.FuncX` doesn't accidentally land on a
1101
+ // `FuncX` declared in `pkga/subpkg/`.
1102
+ const candidates = context.getNodesByName(memberName);
1103
+ for (const node of candidates) {
1104
+ if (node.language !== 'go')
1105
+ continue;
1106
+ if (!node.isExported)
1107
+ continue;
1108
+ const fp = node.filePath.replace(/\\/g, '/');
1109
+ const lastSlash = fp.lastIndexOf('/');
1110
+ const fileDir = lastSlash >= 0 ? fp.substring(0, lastSlash) : '';
1111
+ if (fileDir === pkgDir) {
1112
+ return {
1113
+ original: ref,
1114
+ targetNodeId: node.id,
1115
+ confidence: 0.9,
1116
+ resolvedBy: 'import',
1117
+ };
1118
+ }
1119
+ }
1120
+ }
1121
+ return null;
1122
+ }
589
1123
  /** Recursive depth cap for re-export chain following. Real codebases
590
1124
  * rarely chain barrels more than 2–3 deep; 8 is a generous safety
591
1125
  * net that still bounds worst-case work. */