projscan 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/README.md +56 -19
  2. package/dist/analyzers/unusedDependencyCheck.js +69 -17
  3. package/dist/analyzers/unusedDependencyCheck.js.map +1 -1
  4. package/dist/cli/_shared.d.ts +16 -0
  5. package/dist/cli/_shared.js +210 -0
  6. package/dist/cli/_shared.js.map +1 -0
  7. package/dist/cli/commands/analyze.d.ts +1 -0
  8. package/dist/cli/commands/analyze.js +87 -0
  9. package/dist/cli/commands/analyze.js.map +1 -0
  10. package/dist/cli/commands/audit.d.ts +1 -0
  11. package/dist/cli/commands/audit.js +47 -0
  12. package/dist/cli/commands/audit.js.map +1 -0
  13. package/dist/cli/commands/badge.d.ts +1 -0
  14. package/dist/cli/commands/badge.js +45 -0
  15. package/dist/cli/commands/badge.js.map +1 -0
  16. package/dist/cli/commands/ci.d.ts +1 -0
  17. package/dist/cli/commands/ci.js +57 -0
  18. package/dist/cli/commands/ci.js.map +1 -0
  19. package/dist/cli/commands/coupling.d.ts +1 -0
  20. package/dist/cli/commands/coupling.js +83 -0
  21. package/dist/cli/commands/coupling.js.map +1 -0
  22. package/dist/cli/commands/coverage.d.ts +1 -0
  23. package/dist/cli/commands/coverage.js +63 -0
  24. package/dist/cli/commands/coverage.js.map +1 -0
  25. package/dist/cli/commands/dependencies.d.ts +1 -0
  26. package/dist/cli/commands/dependencies.js +45 -0
  27. package/dist/cli/commands/dependencies.js.map +1 -0
  28. package/dist/cli/commands/diagram.d.ts +1 -0
  29. package/dist/cli/commands/diagram.js +45 -0
  30. package/dist/cli/commands/diagram.js.map +1 -0
  31. package/dist/cli/commands/diff.d.ts +1 -0
  32. package/dist/cli/commands/diff.js +70 -0
  33. package/dist/cli/commands/diff.js.map +1 -0
  34. package/dist/cli/commands/doctor.d.ts +1 -0
  35. package/dist/cli/commands/doctor.js +62 -0
  36. package/dist/cli/commands/doctor.js.map +1 -0
  37. package/dist/cli/commands/explain.d.ts +1 -0
  38. package/dist/cli/commands/explain.js +42 -0
  39. package/dist/cli/commands/explain.js.map +1 -0
  40. package/dist/cli/commands/file.d.ts +1 -0
  41. package/dist/cli/commands/file.js +45 -0
  42. package/dist/cli/commands/file.js.map +1 -0
  43. package/dist/cli/commands/fix.d.ts +1 -0
  44. package/dist/cli/commands/fix.js +70 -0
  45. package/dist/cli/commands/fix.js.map +1 -0
  46. package/dist/cli/commands/help.d.ts +1 -0
  47. package/dist/cli/commands/help.js +11 -0
  48. package/dist/cli/commands/help.js.map +1 -0
  49. package/dist/cli/commands/hotspots.d.ts +1 -0
  50. package/dist/cli/commands/hotspots.js +74 -0
  51. package/dist/cli/commands/hotspots.js.map +1 -0
  52. package/dist/cli/commands/mcp.d.ts +1 -0
  53. package/dist/cli/commands/mcp.js +21 -0
  54. package/dist/cli/commands/mcp.js.map +1 -0
  55. package/dist/cli/commands/outdated.d.ts +1 -0
  56. package/dist/cli/commands/outdated.js +51 -0
  57. package/dist/cli/commands/outdated.js.map +1 -0
  58. package/dist/cli/commands/prDiff.d.ts +1 -0
  59. package/dist/cli/commands/prDiff.js +59 -0
  60. package/dist/cli/commands/prDiff.js.map +1 -0
  61. package/dist/cli/commands/search.d.ts +1 -0
  62. package/dist/cli/commands/search.js +233 -0
  63. package/dist/cli/commands/search.js.map +1 -0
  64. package/dist/cli/commands/structure.d.ts +1 -0
  65. package/dist/cli/commands/structure.js +58 -0
  66. package/dist/cli/commands/structure.js.map +1 -0
  67. package/dist/cli/commands/upgrade.d.ts +1 -0
  68. package/dist/cli/commands/upgrade.js +44 -0
  69. package/dist/cli/commands/upgrade.js.map +1 -0
  70. package/dist/cli/commands/workspaces.d.ts +1 -0
  71. package/dist/cli/commands/workspaces.js +35 -0
  72. package/dist/cli/commands/workspaces.js.map +1 -0
  73. package/dist/cli/index.js +45 -1132
  74. package/dist/cli/index.js.map +1 -1
  75. package/dist/core/ast.d.ts +2 -0
  76. package/dist/core/ast.js +35 -2
  77. package/dist/core/ast.js.map +1 -1
  78. package/dist/core/codeGraph.d.ts +2 -0
  79. package/dist/core/codeGraph.js +2 -0
  80. package/dist/core/codeGraph.js.map +1 -1
  81. package/dist/core/couplingAnalyzer.d.ts +18 -0
  82. package/dist/core/couplingAnalyzer.js +174 -0
  83. package/dist/core/couplingAnalyzer.js.map +1 -0
  84. package/dist/core/fileInspector.d.ts +1 -1
  85. package/dist/core/fileInspector.js +31 -1
  86. package/dist/core/fileInspector.js.map +1 -1
  87. package/dist/core/hotspotAnalyzer.d.ts +13 -0
  88. package/dist/core/hotspotAnalyzer.js +29 -6
  89. package/dist/core/hotspotAnalyzer.js.map +1 -1
  90. package/dist/core/indexCache.js +6 -3
  91. package/dist/core/indexCache.js.map +1 -1
  92. package/dist/core/languages/LanguageAdapter.d.ts +1 -1
  93. package/dist/core/languages/goAdapter.d.ts +2 -0
  94. package/dist/core/languages/goAdapter.js +138 -0
  95. package/dist/core/languages/goAdapter.js.map +1 -0
  96. package/dist/core/languages/goCallSites.d.ts +20 -0
  97. package/dist/core/languages/goCallSites.js +42 -0
  98. package/dist/core/languages/goCallSites.js.map +1 -0
  99. package/dist/core/languages/goCyclomatic.d.ts +21 -0
  100. package/dist/core/languages/goCyclomatic.js +55 -0
  101. package/dist/core/languages/goCyclomatic.js.map +1 -0
  102. package/dist/core/languages/goExports.d.ts +26 -0
  103. package/dist/core/languages/goExports.js +89 -0
  104. package/dist/core/languages/goExports.js.map +1 -0
  105. package/dist/core/languages/goImports.d.ts +26 -0
  106. package/dist/core/languages/goImports.js +64 -0
  107. package/dist/core/languages/goImports.js.map +1 -0
  108. package/dist/core/languages/goManifests.d.ts +19 -0
  109. package/dist/core/languages/goManifests.js +56 -0
  110. package/dist/core/languages/goManifests.js.map +1 -0
  111. package/dist/core/languages/javaAdapter.d.ts +2 -0
  112. package/dist/core/languages/javaAdapter.js +148 -0
  113. package/dist/core/languages/javaAdapter.js.map +1 -0
  114. package/dist/core/languages/javaCallSites.d.ts +16 -0
  115. package/dist/core/languages/javaCallSites.js +45 -0
  116. package/dist/core/languages/javaCallSites.js.map +1 -0
  117. package/dist/core/languages/javaCyclomatic.d.ts +21 -0
  118. package/dist/core/languages/javaCyclomatic.js +49 -0
  119. package/dist/core/languages/javaCyclomatic.js.map +1 -0
  120. package/dist/core/languages/javaExports.d.ts +25 -0
  121. package/dist/core/languages/javaExports.js +80 -0
  122. package/dist/core/languages/javaExports.js.map +1 -0
  123. package/dist/core/languages/javaImports.d.ts +25 -0
  124. package/dist/core/languages/javaImports.js +49 -0
  125. package/dist/core/languages/javaImports.js.map +1 -0
  126. package/dist/core/languages/javaManifests.d.ts +25 -0
  127. package/dist/core/languages/javaManifests.js +86 -0
  128. package/dist/core/languages/javaManifests.js.map +1 -0
  129. package/dist/core/languages/pythonAdapter.js +8 -1
  130. package/dist/core/languages/pythonAdapter.js.map +1 -1
  131. package/dist/core/languages/pythonCallSites.d.ts +19 -0
  132. package/dist/core/languages/pythonCallSites.js +40 -0
  133. package/dist/core/languages/pythonCallSites.js.map +1 -0
  134. package/dist/core/languages/pythonCyclomatic.d.ts +18 -0
  135. package/dist/core/languages/pythonCyclomatic.js +45 -0
  136. package/dist/core/languages/pythonCyclomatic.js.map +1 -0
  137. package/dist/core/languages/registry.js +4 -1
  138. package/dist/core/languages/registry.js.map +1 -1
  139. package/dist/core/languages/rubyAdapter.d.ts +2 -0
  140. package/dist/core/languages/rubyAdapter.js +131 -0
  141. package/dist/core/languages/rubyAdapter.js.map +1 -0
  142. package/dist/core/languages/rubyCallSites.d.ts +16 -0
  143. package/dist/core/languages/rubyCallSites.js +34 -0
  144. package/dist/core/languages/rubyCallSites.js.map +1 -0
  145. package/dist/core/languages/rubyCyclomatic.d.ts +19 -0
  146. package/dist/core/languages/rubyCyclomatic.js +47 -0
  147. package/dist/core/languages/rubyCyclomatic.js.map +1 -0
  148. package/dist/core/languages/rubyExports.d.ts +24 -0
  149. package/dist/core/languages/rubyExports.js +53 -0
  150. package/dist/core/languages/rubyExports.js.map +1 -0
  151. package/dist/core/languages/rubyImports.d.ts +12 -0
  152. package/dist/core/languages/rubyImports.js +75 -0
  153. package/dist/core/languages/rubyImports.js.map +1 -0
  154. package/dist/core/languages/rubyManifests.d.ts +20 -0
  155. package/dist/core/languages/rubyManifests.js +55 -0
  156. package/dist/core/languages/rubyManifests.js.map +1 -0
  157. package/dist/core/languages/treeSitterLoader.js +4 -1
  158. package/dist/core/languages/treeSitterLoader.js.map +1 -1
  159. package/dist/core/monorepo.d.ts +20 -0
  160. package/dist/core/monorepo.js +270 -0
  161. package/dist/core/monorepo.js.map +1 -0
  162. package/dist/core/outdatedDetector.d.ts +13 -2
  163. package/dist/core/outdatedDetector.js +86 -16
  164. package/dist/core/outdatedDetector.js.map +1 -1
  165. package/dist/core/prDiff.d.ts +43 -0
  166. package/dist/core/prDiff.js +298 -0
  167. package/dist/core/prDiff.js.map +1 -0
  168. package/dist/core/telemetry.d.ts +90 -0
  169. package/dist/core/telemetry.js +199 -0
  170. package/dist/core/telemetry.js.map +1 -0
  171. package/dist/grammars/tree-sitter-go.wasm +0 -0
  172. package/dist/grammars/tree-sitter-java.wasm +0 -0
  173. package/dist/grammars/tree-sitter-ruby.wasm +0 -0
  174. package/dist/mcp/tools/_shared.d.ts +24 -0
  175. package/dist/mcp/tools/_shared.js +82 -0
  176. package/dist/mcp/tools/_shared.js.map +1 -0
  177. package/dist/mcp/tools/analyze.d.ts +2 -0
  178. package/dist/mcp/tools/analyze.js +55 -0
  179. package/dist/mcp/tools/analyze.js.map +1 -0
  180. package/dist/mcp/tools/audit.d.ts +2 -0
  181. package/dist/mcp/tools/audit.js +32 -0
  182. package/dist/mcp/tools/audit.js.map +1 -0
  183. package/dist/mcp/tools/coupling.d.ts +2 -0
  184. package/dist/mcp/tools/coupling.js +67 -0
  185. package/dist/mcp/tools/coupling.js.map +1 -0
  186. package/dist/mcp/tools/coverage.d.ts +2 -0
  187. package/dist/mcp/tools/coverage.js +53 -0
  188. package/dist/mcp/tools/coverage.js.map +1 -0
  189. package/dist/mcp/tools/dependencies.d.ts +2 -0
  190. package/dist/mcp/tools/dependencies.js +16 -0
  191. package/dist/mcp/tools/dependencies.js.map +1 -0
  192. package/dist/mcp/tools/doctor.d.ts +2 -0
  193. package/dist/mcp/tools/doctor.js +30 -0
  194. package/dist/mcp/tools/doctor.js.map +1 -0
  195. package/dist/mcp/tools/explain.d.ts +2 -0
  196. package/dist/mcp/tools/explain.js +30 -0
  197. package/dist/mcp/tools/explain.js.map +1 -0
  198. package/dist/mcp/tools/file.d.ts +2 -0
  199. package/dist/mcp/tools/file.js +22 -0
  200. package/dist/mcp/tools/file.js.map +1 -0
  201. package/dist/mcp/tools/graph.d.ts +2 -0
  202. package/dist/mcp/tools/graph.js +69 -0
  203. package/dist/mcp/tools/graph.js.map +1 -0
  204. package/dist/mcp/tools/hotspots.d.ts +2 -0
  205. package/dist/mcp/tools/hotspots.js +64 -0
  206. package/dist/mcp/tools/hotspots.js.map +1 -0
  207. package/dist/mcp/tools/outdated.d.ts +2 -0
  208. package/dist/mcp/tools/outdated.js +36 -0
  209. package/dist/mcp/tools/outdated.js.map +1 -0
  210. package/dist/mcp/tools/prDiff.d.ts +2 -0
  211. package/dist/mcp/tools/prDiff.js +38 -0
  212. package/dist/mcp/tools/prDiff.js.map +1 -0
  213. package/dist/mcp/tools/search.d.ts +2 -0
  214. package/dist/mcp/tools/search.js +167 -0
  215. package/dist/mcp/tools/search.js.map +1 -0
  216. package/dist/mcp/tools/structure.d.ts +2 -0
  217. package/dist/mcp/tools/structure.js +34 -0
  218. package/dist/mcp/tools/structure.js.map +1 -0
  219. package/dist/mcp/tools/upgrade.d.ts +2 -0
  220. package/dist/mcp/tools/upgrade.js +38 -0
  221. package/dist/mcp/tools/upgrade.js.map +1 -0
  222. package/dist/mcp/tools/workspaces.d.ts +2 -0
  223. package/dist/mcp/tools/workspaces.js +13 -0
  224. package/dist/mcp/tools/workspaces.js.map +1 -0
  225. package/dist/mcp/tools.d.ts +12 -6
  226. package/dist/mcp/tools.js +40 -605
  227. package/dist/mcp/tools.js.map +1 -1
  228. package/dist/reporters/consoleReporter.d.ts +4 -1
  229. package/dist/reporters/consoleReporter.js +113 -0
  230. package/dist/reporters/consoleReporter.js.map +1 -1
  231. package/dist/reporters/jsonReporter.d.ts +4 -1
  232. package/dist/reporters/jsonReporter.js +9 -0
  233. package/dist/reporters/jsonReporter.js.map +1 -1
  234. package/dist/reporters/markdownReporter.d.ts +4 -1
  235. package/dist/reporters/markdownReporter.js +103 -3
  236. package/dist/reporters/markdownReporter.js.map +1 -1
  237. package/dist/tool-manifest.json +358 -0
  238. package/dist/types.d.ts +115 -0
  239. package/dist/utils/cache.d.ts +3 -0
  240. package/dist/utils/cache.js +51 -0
  241. package/dist/utils/cache.js.map +1 -0
  242. package/package.json +7 -3
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Extract package-level "exports" from a Java AST.
3
+ *
4
+ * Java visibility rules:
5
+ * public - visible everywhere
6
+ * protected - visible to package + subclasses
7
+ * (none) - package-private
8
+ * private - file-only
9
+ *
10
+ * We treat `public` as the export surface (the typical "API") and skip
11
+ * everything else. Top-level declarations only - nested types are part of
12
+ * their enclosing class's surface, not separate exports.
13
+ */
14
+ export function extractJavaExports(root) {
15
+ const out = [];
16
+ for (const child of root.namedChildren) {
17
+ visitTopLevel(child, out);
18
+ }
19
+ return out;
20
+ }
21
+ function visitTopLevel(node, out) {
22
+ switch (node.type) {
23
+ case 'class_declaration':
24
+ addPublic(node, 'class', out);
25
+ return;
26
+ case 'interface_declaration':
27
+ addPublic(node, 'interface', out);
28
+ return;
29
+ case 'enum_declaration':
30
+ addPublic(node, 'enum', out);
31
+ return;
32
+ case 'record_declaration':
33
+ // Java 14+ records - treat as a class for our purposes.
34
+ addPublic(node, 'class', out);
35
+ return;
36
+ case 'annotation_type_declaration':
37
+ addPublic(node, 'type', out);
38
+ return;
39
+ default:
40
+ return;
41
+ }
42
+ }
43
+ function addPublic(node, kind, out) {
44
+ if (!hasModifier(node, 'public'))
45
+ return;
46
+ const nameNode = node.childForFieldName?.('name') ?? findChild(node, 'identifier');
47
+ if (!nameNode)
48
+ return;
49
+ out.push({
50
+ name: nameNode.text,
51
+ kind,
52
+ typeOnly: false,
53
+ line: node.startPosition.row + 1,
54
+ });
55
+ }
56
+ function hasModifier(node, mod) {
57
+ const modsNode = findChild(node, 'modifiers');
58
+ if (!modsNode)
59
+ return false;
60
+ // tree-sitter-java emits keyword modifiers (`public`, `private`, etc.) as
61
+ // anonymous children - they're not in `namedChildren`. Walk the full child
62
+ // list and match by token type or text.
63
+ for (const c of modsNode.namedChildren) {
64
+ if (c.type === mod || c.text === mod)
65
+ return true;
66
+ }
67
+ // Anonymous-keyword fallback: scan tokens via text match. Modifiers contain
68
+ // only the keyword tokens plus annotations; annotations start with `@` so
69
+ // exact-match against `mod` is unambiguous.
70
+ const tokens = modsNode.text.split(/\s+/);
71
+ return tokens.includes(mod);
72
+ }
73
+ function findChild(node, type) {
74
+ for (const c of node.namedChildren) {
75
+ if (c.type === type)
76
+ return c;
77
+ }
78
+ return null;
79
+ }
80
+ //# sourceMappingURL=javaExports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"javaExports.js","sourceRoot":"","sources":["../../../src/core/languages/javaExports.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvC,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,GAAgB;IACnD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,mBAAmB;YACtB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;QACT,KAAK,uBAAuB;YAC1B,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;YAClC,OAAO;QACT,KAAK,kBAAkB;YACrB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAC7B,OAAO;QACT,KAAK,oBAAoB;YACvB,wDAAwD;YACxD,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO;QACT,KAAK,6BAA6B;YAChC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAC7B,OAAO;QACT;YACE,OAAO;IACX,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAgB,EAAE,GAAgB;IACjE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAAE,OAAO;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACnF,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,GAAG,CAAC,IAAI,CAAC;QACP,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,IAAI;QACJ,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;KACjC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,GAAW;IAC5C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,0EAA0E;IAC1E,2EAA2E;IAC3E,wCAAwC;IACxC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QACvC,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;IACpD,CAAC;IACD,4EAA4E;IAC5E,0EAA0E;IAC1E,4CAA4C;IAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { AstImport } from '../ast.js';
2
+ interface TsNode {
3
+ type: string;
4
+ text: string;
5
+ startPosition: {
6
+ row: number;
7
+ };
8
+ namedChildren: TsNode[];
9
+ }
10
+ /**
11
+ * Extract import declarations from a tree-sitter-java AST.
12
+ *
13
+ * Java imports come in three shapes:
14
+ * import java.util.List;
15
+ * import java.util.*; // wildcard
16
+ * import static foo.Bar.X; // static
17
+ *
18
+ * The grammar emits `import_declaration` at the top level. The dotted path is
19
+ * captured as `scoped_identifier`; a wildcard appears as an `asterisk` child.
20
+ * We record the package portion (everything before the last segment for type
21
+ * imports, the whole path for wildcards/static imports) as the import source -
22
+ * matching how a resolver will look up the target.
23
+ */
24
+ export declare function extractJavaImports(root: TsNode): AstImport[];
25
+ export {};
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Extract import declarations from a tree-sitter-java AST.
3
+ *
4
+ * Java imports come in three shapes:
5
+ * import java.util.List;
6
+ * import java.util.*; // wildcard
7
+ * import static foo.Bar.X; // static
8
+ *
9
+ * The grammar emits `import_declaration` at the top level. The dotted path is
10
+ * captured as `scoped_identifier`; a wildcard appears as an `asterisk` child.
11
+ * We record the package portion (everything before the last segment for type
12
+ * imports, the whole path for wildcards/static imports) as the import source -
13
+ * matching how a resolver will look up the target.
14
+ */
15
+ export function extractJavaImports(root) {
16
+ const out = [];
17
+ for (const child of root.namedChildren) {
18
+ if (child.type === 'import_declaration') {
19
+ handleImport(child, out);
20
+ }
21
+ }
22
+ return out;
23
+ }
24
+ function handleImport(node, out) {
25
+ const line = node.startPosition.row + 1;
26
+ // Collect the dotted path text. With wildcards the asterisk node sits next
27
+ // to the scoped_identifier; we keep `.*` on the source so the resolver can
28
+ // distinguish.
29
+ let path = null;
30
+ let wildcard = false;
31
+ for (const c of node.namedChildren) {
32
+ if (c.type === 'scoped_identifier' || c.type === 'identifier') {
33
+ path = c.text;
34
+ }
35
+ else if (c.type === 'asterisk') {
36
+ wildcard = true;
37
+ }
38
+ }
39
+ if (!path)
40
+ return;
41
+ out.push({
42
+ source: wildcard ? `${path}.*` : path,
43
+ kind: 'static',
44
+ specifiers: [],
45
+ typeOnly: false,
46
+ line,
47
+ });
48
+ }
49
+ //# sourceMappingURL=javaImports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"javaImports.js","sourceRoot":"","sources":["../../../src/core/languages/javaImports.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;YACxC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAgB;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;IACxC,2EAA2E;IAC3E,2EAA2E;IAC3E,eAAe;IACf,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC9D,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QAChB,CAAC;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACjC,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,GAAG,CAAC,IAAI,CAAC;QACP,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;QACrC,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,KAAK;QACf,IAAI;KACL,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { FileEntry } from '../../types.js';
2
+ export interface JavaProjectInfo {
3
+ /** Absolute paths to source roots - directories under which `package` paths resolve. */
4
+ sourceRoots: string[];
5
+ /** Build system detected, if any. Informational only. */
6
+ buildSystem: 'maven' | 'gradle' | 'unknown';
7
+ }
8
+ /**
9
+ * Detect a Java project layout.
10
+ *
11
+ * Maven: presence of `pom.xml`. Default source roots are
12
+ * src/main/java/, src/test/java/.
13
+ * Gradle: presence of `build.gradle` or `build.gradle.kts`. Same defaults.
14
+ *
15
+ * Real projects may override the source root via Maven's <sourceDirectory>
16
+ * or Gradle's `sourceSets`. Parsing those out is deferred - the conventional
17
+ * defaults cover ≈95% of repos. Custom roots can still be picked up because
18
+ * `inferRootsFromFiles` walks the file list and takes any directory that
19
+ * contains a top-level `.java` file with a `package` declaration matching its
20
+ * directory path.
21
+ *
22
+ * Returns `null` only when no `.java` files exist and no build manifest is
23
+ * found - i.e. this is not a Java project.
24
+ */
25
+ export declare function detectJavaProject(rootPath: string, files: FileEntry[]): Promise<JavaProjectInfo | null>;
@@ -0,0 +1,86 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const MAVEN_DEFAULT_ROOTS = ['src/main/java', 'src/test/java'];
4
+ const GRADLE_DEFAULT_ROOTS = ['src/main/java', 'src/test/java'];
5
+ /**
6
+ * Detect a Java project layout.
7
+ *
8
+ * Maven: presence of `pom.xml`. Default source roots are
9
+ * src/main/java/, src/test/java/.
10
+ * Gradle: presence of `build.gradle` or `build.gradle.kts`. Same defaults.
11
+ *
12
+ * Real projects may override the source root via Maven's <sourceDirectory>
13
+ * or Gradle's `sourceSets`. Parsing those out is deferred - the conventional
14
+ * defaults cover ≈95% of repos. Custom roots can still be picked up because
15
+ * `inferRootsFromFiles` walks the file list and takes any directory that
16
+ * contains a top-level `.java` file with a `package` declaration matching its
17
+ * directory path.
18
+ *
19
+ * Returns `null` only when no `.java` files exist and no build manifest is
20
+ * found - i.e. this is not a Java project.
21
+ */
22
+ export async function detectJavaProject(rootPath, files) {
23
+ const hasPom = await fileExists(path.join(rootPath, 'pom.xml'));
24
+ const hasGradle = (await fileExists(path.join(rootPath, 'build.gradle'))) ||
25
+ (await fileExists(path.join(rootPath, 'build.gradle.kts')));
26
+ const javaFiles = files.filter((f) => f.relativePath.endsWith('.java'));
27
+ if (!hasPom && !hasGradle && javaFiles.length === 0)
28
+ return null;
29
+ const buildSystem = hasPom
30
+ ? 'maven'
31
+ : hasGradle
32
+ ? 'gradle'
33
+ : 'unknown';
34
+ // Start with conventional roots (only the ones that actually exist).
35
+ const conventional = hasPom ? MAVEN_DEFAULT_ROOTS : GRADLE_DEFAULT_ROOTS;
36
+ const roots = new Set();
37
+ for (const r of conventional) {
38
+ if (await fileExists(path.join(rootPath, r))) {
39
+ roots.add(r);
40
+ }
41
+ }
42
+ // If neither convention exists, fall back to inferring from file layout.
43
+ if (roots.size === 0) {
44
+ const inferred = inferRootsFromFiles(javaFiles);
45
+ for (const r of inferred)
46
+ roots.add(r);
47
+ if (roots.size === 0)
48
+ roots.add('.');
49
+ }
50
+ return {
51
+ sourceRoots: [...roots].map((r) => path.join(rootPath, r)),
52
+ buildSystem,
53
+ };
54
+ }
55
+ /**
56
+ * Best-effort source-root inference: for each .java file, scan its content
57
+ * for a `package` declaration and back out the source root by stripping the
58
+ * package path from the file's directory. We can't read content here cheaply
59
+ * (FileEntry doesn't carry it), so we approximate by looking at the deepest
60
+ * common prefix of `.java` directories.
61
+ */
62
+ function inferRootsFromFiles(files) {
63
+ if (files.length === 0)
64
+ return [];
65
+ const dirs = new Set(files.map((f) => path.posix.dirname(f.relativePath)));
66
+ // Find the shortest directory - that's the most likely package root.
67
+ let shortest = '';
68
+ let shortestLen = Infinity;
69
+ for (const d of dirs) {
70
+ if (d.length < shortestLen) {
71
+ shortest = d;
72
+ shortestLen = d.length;
73
+ }
74
+ }
75
+ return [shortest || '.'];
76
+ }
77
+ async function fileExists(p) {
78
+ try {
79
+ await fs.access(p);
80
+ return true;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ //# sourceMappingURL=javaManifests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"javaManifests.js","sourceRoot":"","sources":["../../../src/core/languages/javaManifests.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,8 @@ import path from 'node:path';
2
2
  import { createParserFor } from './treeSitterLoader.js';
3
3
  import { extractPythonImports } from './pythonImports.js';
4
4
  import { extractPythonExports } from './pythonExports.js';
5
+ import { extractPythonCyclomatic } from './pythonCyclomatic.js';
6
+ import { extractPythonCallSites } from './pythonCallSites.js';
5
7
  import { detectPythonProject } from './pythonManifests.js';
6
8
  // Pinned grammar: tree-sitter-python 0.25.0. See treeSitterLoader.ts.
7
9
  const PY_EXTENSIONS = new Set(['.py', '.pyw', '.pyi']);
@@ -34,16 +36,20 @@ export const pythonAdapter = {
34
36
  exports: [],
35
37
  callSites: [],
36
38
  lineCount: content ? content.split('\n').length : 0,
39
+ cyclomaticComplexity: 0,
37
40
  };
38
41
  }
39
42
  const imports = extractPythonImports(tree.rootNode);
40
43
  const exports = extractPythonExports(tree.rootNode);
44
+ const cyclomaticComplexity = extractPythonCyclomatic(tree.rootNode);
45
+ const callSites = extractPythonCallSites(tree.rootNode);
41
46
  return {
42
47
  ok: true,
43
48
  imports,
44
49
  exports,
45
- callSites: [],
50
+ callSites,
46
51
  lineCount: content ? content.split('\n').length : 0,
52
+ cyclomaticComplexity,
47
53
  };
48
54
  }
49
55
  catch (err) {
@@ -55,6 +61,7 @@ export const pythonAdapter = {
55
61
  exports: [],
56
62
  callSites: [],
57
63
  lineCount: content ? content.split('\n').length : 0,
64
+ cyclomaticComplexity: 0,
58
65
  };
59
66
  }
60
67
  },
@@ -1 +1 @@
1
- {"version":3,"file":"pythonAdapter.js","sourceRoot":"","sources":["../../../src/core/languages/pythonAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pythonAdapter.js","sourceRoot":"","sources":["../../../src/core/languages/pythonAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Extract call-site identifiers from a tree-sitter-python AST.
3
+ *
4
+ * For `foo(...)` we record `foo`. For `obj.method(...)` (attribute call) we
5
+ * record `method` (the rightmost name). For more complex callees (subscripts,
6
+ * lambdas-immediately-invoked, decorators acting as callees, etc.) we skip -
7
+ * a name is needed to be useful for "who calls X" lookups.
8
+ *
9
+ * Mirrors the JS/TS behaviour in `src/core/ast.ts`: identifiers and the final
10
+ * member-property name; uniqued before return.
11
+ */
12
+ interface TsNode {
13
+ type: string;
14
+ text: string;
15
+ namedChildren: TsNode[];
16
+ childForFieldName?(name: string): TsNode | null;
17
+ }
18
+ export declare function extractPythonCallSites(root: TsNode): string[];
19
+ export {};
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Extract call-site identifiers from a tree-sitter-python AST.
3
+ *
4
+ * For `foo(...)` we record `foo`. For `obj.method(...)` (attribute call) we
5
+ * record `method` (the rightmost name). For more complex callees (subscripts,
6
+ * lambdas-immediately-invoked, decorators acting as callees, etc.) we skip -
7
+ * a name is needed to be useful for "who calls X" lookups.
8
+ *
9
+ * Mirrors the JS/TS behaviour in `src/core/ast.ts`: identifiers and the final
10
+ * member-property name; uniqued before return.
11
+ */
12
+ export function extractPythonCallSites(root) {
13
+ const seen = new Set();
14
+ walk(root, seen);
15
+ return [...seen];
16
+ }
17
+ function walk(node, out) {
18
+ if (node.type === 'call') {
19
+ const fn = node.childForFieldName?.('function') ?? null;
20
+ const name = nameFromCallee(fn);
21
+ if (name)
22
+ out.add(name);
23
+ }
24
+ for (const child of node.namedChildren)
25
+ walk(child, out);
26
+ }
27
+ function nameFromCallee(node) {
28
+ if (!node)
29
+ return null;
30
+ if (node.type === 'identifier')
31
+ return node.text;
32
+ if (node.type === 'attribute') {
33
+ // `obj.method` - the rightmost identifier is the called name.
34
+ const last = node.childForFieldName?.('attribute') ?? null;
35
+ if (last && last.type === 'identifier')
36
+ return last.text;
37
+ }
38
+ return null;
39
+ }
40
+ //# sourceMappingURL=pythonCallSites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pythonCallSites.js","sourceRoot":"","sources":["../../../src/core/languages/pythonCallSites.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjB,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,GAAgB;IAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;QACxD,MAAM,IAAI,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa;QAAE,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,cAAc,CAAC,IAAmB;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IACjD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC9B,8DAA8D;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;QAC3D,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IAC3D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,18 @@
1
+ /** Minimal tree-sitter node surface we depend on. Mirrors pythonImports.ts. */
2
+ interface TsNode {
3
+ type: string;
4
+ text: string;
5
+ namedChildren: TsNode[];
6
+ }
7
+ /**
8
+ * Compute file-level McCabe cyclomatic complexity from a tree-sitter-python
9
+ * AST. Counts decision points across the entire file (module + nested
10
+ * functions/classes) and returns count + 1.
11
+ *
12
+ * Decision points: if/elif, for, while, except, conditional expression,
13
+ * boolean operators (and/or each add one), and `if` clauses inside
14
+ * comprehensions. The plain `else` branch is the fall-through path and does
15
+ * not count.
16
+ */
17
+ export declare function extractPythonCyclomatic(root: TsNode): number;
18
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Compute file-level McCabe cyclomatic complexity from a tree-sitter-python
3
+ * AST. Counts decision points across the entire file (module + nested
4
+ * functions/classes) and returns count + 1.
5
+ *
6
+ * Decision points: if/elif, for, while, except, conditional expression,
7
+ * boolean operators (and/or each add one), and `if` clauses inside
8
+ * comprehensions. The plain `else` branch is the fall-through path and does
9
+ * not count.
10
+ */
11
+ export function extractPythonCyclomatic(root) {
12
+ let decisions = 0;
13
+ walk(root, (n) => {
14
+ if (isDecisionPoint(n))
15
+ decisions++;
16
+ });
17
+ return decisions + 1;
18
+ }
19
+ function isDecisionPoint(n) {
20
+ switch (n.type) {
21
+ case 'if_statement':
22
+ case 'elif_clause':
23
+ case 'for_statement':
24
+ case 'while_statement':
25
+ case 'except_clause':
26
+ case 'conditional_expression':
27
+ case 'for_in_clause': // comprehension `for`
28
+ case 'if_clause': // comprehension `if`
29
+ case 'case_clause': // match/case (Python 3.10+)
30
+ return true;
31
+ case 'boolean_operator':
32
+ // Each `and` / `or` introduces a branch. tree-sitter-python emits one
33
+ // boolean_operator node per logical operator, so each occurrence = +1.
34
+ return true;
35
+ default:
36
+ return false;
37
+ }
38
+ }
39
+ function walk(node, visit) {
40
+ visit(node);
41
+ for (const child of node.namedChildren) {
42
+ walk(child, visit);
43
+ }
44
+ }
45
+ //# sourceMappingURL=pythonCyclomatic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pythonCyclomatic.js","sourceRoot":"","sources":["../../../src/core/languages/pythonCyclomatic.ts"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QACf,IAAI,eAAe,CAAC,CAAC,CAAC;YAAE,SAAS,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,eAAe,CAAC,CAAS;IAChC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,cAAc,CAAC;QACpB,KAAK,aAAa,CAAC;QACnB,KAAK,eAAe,CAAC;QACrB,KAAK,iBAAiB,CAAC;QACvB,KAAK,eAAe,CAAC;QACrB,KAAK,wBAAwB,CAAC;QAC9B,KAAK,eAAe,CAAC,CAAC,sBAAsB;QAC5C,KAAK,WAAW,CAAC,CAAC,qBAAqB;QACvC,KAAK,aAAa,EAAE,4BAA4B;YAC9C,OAAO,IAAI,CAAC;QACd,KAAK,kBAAkB;YACrB,sEAAsE;YACtE,uEAAuE;YACvE,OAAO,IAAI,CAAC;QACd;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,KAA0B;IACpD,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACrB,CAAC;AACH,CAAC"}
@@ -1,7 +1,10 @@
1
1
  import path from 'node:path';
2
2
  import { javascriptAdapter } from './javascriptAdapter.js';
3
3
  import { pythonAdapter } from './pythonAdapter.js';
4
- const adapters = [javascriptAdapter, pythonAdapter];
4
+ import { goAdapter } from './goAdapter.js';
5
+ import { javaAdapter } from './javaAdapter.js';
6
+ import { rubyAdapter } from './rubyAdapter.js';
7
+ const adapters = [javascriptAdapter, pythonAdapter, goAdapter, javaAdapter, rubyAdapter];
5
8
  const byExtension = new Map();
6
9
  function rebuildIndex() {
7
10
  byExtension.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/languages/registry.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,QAAQ,GAAsB,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;AACvE,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEvD,SAAS,YAAY;IACnB,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AACD,YAAY,EAAE,CAAC;AAEf,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,YAAY,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/languages/registry.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,QAAQ,GAAsB,CAAC,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AAC5G,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEvD,SAAS,YAAY;IACnB,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AACD,YAAY,EAAE,CAAC;AAEf,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,YAAY,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { LanguageAdapter } from './LanguageAdapter.js';
2
+ export declare const rubyAdapter: LanguageAdapter;
@@ -0,0 +1,131 @@
1
+ import path from 'node:path';
2
+ import { createParserFor } from './treeSitterLoader.js';
3
+ import { extractRubyImports } from './rubyImports.js';
4
+ import { extractRubyExports } from './rubyExports.js';
5
+ import { extractRubyCyclomatic } from './rubyCyclomatic.js';
6
+ import { extractRubyCallSites } from './rubyCallSites.js';
7
+ import { detectRubyProject } from './rubyManifests.js';
8
+ const RUBY_EXTENSIONS = new Set(['.rb']);
9
+ const MAX_RUBY_FILE = 1024 * 1024;
10
+ let parserPromise = null;
11
+ async function getParser() {
12
+ if (!parserPromise)
13
+ parserPromise = createParserFor('tree-sitter-ruby.wasm');
14
+ return parserPromise;
15
+ }
16
+ export const rubyAdapter = {
17
+ id: 'ruby',
18
+ extensions: RUBY_EXTENSIONS,
19
+ sourceExtensions: RUBY_EXTENSIONS,
20
+ // Ruby has no barrel-file convention.
21
+ barrelBasenames: new Set(),
22
+ maxFileSize: MAX_RUBY_FILE,
23
+ async parse(_filePath, content) {
24
+ try {
25
+ const parser = await getParser();
26
+ const tree = parser.parse(content);
27
+ if (!tree || !tree.rootNode) {
28
+ return {
29
+ ok: false,
30
+ reason: 'tree-sitter returned null tree',
31
+ imports: [],
32
+ exports: [],
33
+ callSites: [],
34
+ lineCount: content ? content.split('\n').length : 0,
35
+ cyclomaticComplexity: 0,
36
+ };
37
+ }
38
+ const root = tree.rootNode;
39
+ const imports = extractRubyImports(root);
40
+ const exports = extractRubyExports(root);
41
+ const cyclomaticComplexity = extractRubyCyclomatic(root);
42
+ const callSites = extractRubyCallSites(root);
43
+ return {
44
+ ok: true,
45
+ imports,
46
+ exports,
47
+ callSites,
48
+ lineCount: content ? content.split('\n').length : 0,
49
+ cyclomaticComplexity,
50
+ };
51
+ }
52
+ catch (err) {
53
+ const msg = err instanceof Error ? err.message : String(err);
54
+ return {
55
+ ok: false,
56
+ reason: `ruby parse failure: ${msg.slice(0, 120)}`,
57
+ imports: [],
58
+ exports: [],
59
+ callSites: [],
60
+ lineCount: content ? content.split('\n').length : 0,
61
+ cyclomaticComplexity: 0,
62
+ };
63
+ }
64
+ },
65
+ resolveImport(importingFile, source, graphFiles, context) {
66
+ return resolveRubyImport(importingFile, source, graphFiles, context);
67
+ },
68
+ toPackageName(source) {
69
+ if (!source)
70
+ return null;
71
+ // `./foo` and `../foo` are clearly local; let resolveImport handle.
72
+ if (source.startsWith('./') || source.startsWith('../'))
73
+ return null;
74
+ // Otherwise treat the whole specifier as the gem name (e.g. `json`, `active_support/core_ext`).
75
+ // Take only the first path segment for ranking purposes.
76
+ return source.split('/')[0];
77
+ },
78
+ async preparePackageRoots(rootPath, files) {
79
+ const info = await detectRubyProject(rootPath, files);
80
+ if (!info)
81
+ return { packageRoots: [], meta: undefined };
82
+ return {
83
+ packageRoots: info.sourceRoots.map((r) => path.relative(rootPath, r) || '.'),
84
+ meta: { rubyProject: info },
85
+ };
86
+ },
87
+ };
88
+ /**
89
+ * Resolve a Ruby require / require_relative to a repo-local file path.
90
+ *
91
+ * require_relative 'sibling' → resolved against the importing file's dir.
92
+ * require_relative '../helpers' → walked up.
93
+ * require 'json' → null (stdlib / gem; no source-root match).
94
+ * require 'foo/bar' → for each sourceRoot, probe `foo/bar.rb`.
95
+ *
96
+ * Ruby `require` semantics depend on $LOAD_PATH at runtime; we approximate by
97
+ * checking sourceRoots (typically `lib/`). This catches the common case where
98
+ * a gem requires its own internal modules by their lib-relative path.
99
+ */
100
+ function resolveRubyImport(importingFile, source, graphFiles, context) {
101
+ if (!source)
102
+ return null;
103
+ // The original call site distinguishes require vs require_relative, but by
104
+ // the time we're here we only have the source string. Heuristic: if the
105
+ // string starts with `./` or `../`, treat as relative; otherwise probe BOTH
106
+ // relative-to-importer AND relative-to-each-source-root, and pick the first
107
+ // that resolves. This captures both `require_relative` AND `require` of a
108
+ // gem-internal lib path.
109
+ const sourceWithExt = source.endsWith('.rb') ? source : `${source}.rb`;
110
+ if (source.startsWith('./') || source.startsWith('../')) {
111
+ const dir = path.posix.dirname(importingFile);
112
+ const joined = path.posix.normalize(path.posix.join(dir, sourceWithExt));
113
+ return graphFiles.has(joined) ? joined : null;
114
+ }
115
+ // Try each source root.
116
+ const sourceRootsRel = context.packageRoots ?? ['.'];
117
+ for (const root of sourceRootsRel) {
118
+ const rootSegs = root === '.' || root === '' ? [] : root.split('/').filter(Boolean);
119
+ const candidate = [...rootSegs, sourceWithExt].join('/');
120
+ if (graphFiles.has(candidate))
121
+ return candidate;
122
+ }
123
+ // Also try treating the source as relative to the importing file's directory
124
+ // (require_relative without leading `./`). Some style guides drop the prefix.
125
+ const dir = path.posix.dirname(importingFile);
126
+ const joined = path.posix.normalize(path.posix.join(dir, sourceWithExt));
127
+ if (graphFiles.has(joined))
128
+ return joined;
129
+ return null;
130
+ }
131
+ //# sourceMappingURL=rubyAdapter.js.map