codedev-mcp 3.2.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 (229) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/LICENSE +21 -0
  3. package/README.md +760 -0
  4. package/dist/analyzers/api-contract.d.ts +46 -0
  5. package/dist/analyzers/api-contract.d.ts.map +1 -0
  6. package/dist/analyzers/api-contract.js +319 -0
  7. package/dist/analyzers/api-contract.js.map +1 -0
  8. package/dist/analyzers/architecture.d.ts +37 -0
  9. package/dist/analyzers/architecture.d.ts.map +1 -0
  10. package/dist/analyzers/architecture.js +149 -0
  11. package/dist/analyzers/architecture.js.map +1 -0
  12. package/dist/analyzers/branch-compare.d.ts +46 -0
  13. package/dist/analyzers/branch-compare.d.ts.map +1 -0
  14. package/dist/analyzers/branch-compare.js +128 -0
  15. package/dist/analyzers/branch-compare.js.map +1 -0
  16. package/dist/analyzers/cicd.d.ts +42 -0
  17. package/dist/analyzers/cicd.d.ts.map +1 -0
  18. package/dist/analyzers/cicd.js +237 -0
  19. package/dist/analyzers/cicd.js.map +1 -0
  20. package/dist/analyzers/codebase.d.ts +64 -0
  21. package/dist/analyzers/codebase.d.ts.map +1 -0
  22. package/dist/analyzers/codebase.js +354 -0
  23. package/dist/analyzers/codebase.js.map +1 -0
  24. package/dist/analyzers/complexity-heatmap.d.ts +50 -0
  25. package/dist/analyzers/complexity-heatmap.d.ts.map +1 -0
  26. package/dist/analyzers/complexity-heatmap.js +156 -0
  27. package/dist/analyzers/complexity-heatmap.js.map +1 -0
  28. package/dist/analyzers/context-pack.d.ts +43 -0
  29. package/dist/analyzers/context-pack.d.ts.map +1 -0
  30. package/dist/analyzers/context-pack.js +232 -0
  31. package/dist/analyzers/context-pack.js.map +1 -0
  32. package/dist/analyzers/coverage.d.ts +70 -0
  33. package/dist/analyzers/coverage.d.ts.map +1 -0
  34. package/dist/analyzers/coverage.js +313 -0
  35. package/dist/analyzers/coverage.js.map +1 -0
  36. package/dist/analyzers/db-schema.d.ts +55 -0
  37. package/dist/analyzers/db-schema.d.ts.map +1 -0
  38. package/dist/analyzers/db-schema.js +237 -0
  39. package/dist/analyzers/db-schema.js.map +1 -0
  40. package/dist/analyzers/dead-code.d.ts +34 -0
  41. package/dist/analyzers/dead-code.d.ts.map +1 -0
  42. package/dist/analyzers/dead-code.js +131 -0
  43. package/dist/analyzers/dead-code.js.map +1 -0
  44. package/dist/analyzers/dep-vuln.d.ts +36 -0
  45. package/dist/analyzers/dep-vuln.d.ts.map +1 -0
  46. package/dist/analyzers/dep-vuln.js +342 -0
  47. package/dist/analyzers/dep-vuln.js.map +1 -0
  48. package/dist/analyzers/docs.d.ts +47 -0
  49. package/dist/analyzers/docs.d.ts.map +1 -0
  50. package/dist/analyzers/docs.js +473 -0
  51. package/dist/analyzers/docs.js.map +1 -0
  52. package/dist/analyzers/git.d.ts +115 -0
  53. package/dist/analyzers/git.d.ts.map +1 -0
  54. package/dist/analyzers/git.js +214 -0
  55. package/dist/analyzers/git.js.map +1 -0
  56. package/dist/analyzers/iac.d.ts +39 -0
  57. package/dist/analyzers/iac.d.ts.map +1 -0
  58. package/dist/analyzers/iac.js +233 -0
  59. package/dist/analyzers/iac.js.map +1 -0
  60. package/dist/analyzers/impact.d.ts +51 -0
  61. package/dist/analyzers/impact.d.ts.map +1 -0
  62. package/dist/analyzers/impact.js +235 -0
  63. package/dist/analyzers/impact.js.map +1 -0
  64. package/dist/analyzers/monorepo.d.ts +36 -0
  65. package/dist/analyzers/monorepo.d.ts.map +1 -0
  66. package/dist/analyzers/monorepo.js +233 -0
  67. package/dist/analyzers/monorepo.js.map +1 -0
  68. package/dist/analyzers/notebook.d.ts +53 -0
  69. package/dist/analyzers/notebook.d.ts.map +1 -0
  70. package/dist/analyzers/notebook.js +149 -0
  71. package/dist/analyzers/notebook.js.map +1 -0
  72. package/dist/analyzers/perf-profile.d.ts +39 -0
  73. package/dist/analyzers/perf-profile.d.ts.map +1 -0
  74. package/dist/analyzers/perf-profile.js +222 -0
  75. package/dist/analyzers/perf-profile.js.map +1 -0
  76. package/dist/analyzers/scaffold.d.ts +46 -0
  77. package/dist/analyzers/scaffold.d.ts.map +1 -0
  78. package/dist/analyzers/scaffold.js +313 -0
  79. package/dist/analyzers/scaffold.js.map +1 -0
  80. package/dist/analyzers/security.d.ts +42 -0
  81. package/dist/analyzers/security.d.ts.map +1 -0
  82. package/dist/analyzers/security.js +281 -0
  83. package/dist/analyzers/security.js.map +1 -0
  84. package/dist/analyzers/symbols.d.ts +49 -0
  85. package/dist/analyzers/symbols.d.ts.map +1 -0
  86. package/dist/analyzers/symbols.js +212 -0
  87. package/dist/analyzers/symbols.js.map +1 -0
  88. package/dist/analyzers/tree-sitter.d.ts +71 -0
  89. package/dist/analyzers/tree-sitter.d.ts.map +1 -0
  90. package/dist/analyzers/tree-sitter.js +333 -0
  91. package/dist/analyzers/tree-sitter.js.map +1 -0
  92. package/dist/analyzers/type-flow.d.ts +39 -0
  93. package/dist/analyzers/type-flow.d.ts.map +1 -0
  94. package/dist/analyzers/type-flow.js +75 -0
  95. package/dist/analyzers/type-flow.js.map +1 -0
  96. package/dist/cache/memory-cache.d.ts +130 -0
  97. package/dist/cache/memory-cache.d.ts.map +1 -0
  98. package/dist/cache/memory-cache.js +273 -0
  99. package/dist/cache/memory-cache.js.map +1 -0
  100. package/dist/config.d.ts +32 -0
  101. package/dist/config.d.ts.map +1 -0
  102. package/dist/config.js +57 -0
  103. package/dist/config.js.map +1 -0
  104. package/dist/constants/instructions.d.ts +2 -0
  105. package/dist/constants/instructions.d.ts.map +1 -0
  106. package/dist/constants/instructions.js +82 -0
  107. package/dist/constants/instructions.js.map +1 -0
  108. package/dist/db/connection.d.ts +12 -0
  109. package/dist/db/connection.d.ts.map +1 -0
  110. package/dist/db/connection.js +34 -0
  111. package/dist/db/connection.js.map +1 -0
  112. package/dist/db/json-store.d.ts +111 -0
  113. package/dist/db/json-store.d.ts.map +1 -0
  114. package/dist/db/json-store.js +201 -0
  115. package/dist/db/json-store.js.map +1 -0
  116. package/dist/db/sqlite-store.d.ts +153 -0
  117. package/dist/db/sqlite-store.d.ts.map +1 -0
  118. package/dist/db/sqlite-store.js +388 -0
  119. package/dist/db/sqlite-store.js.map +1 -0
  120. package/dist/index.d.ts +17 -0
  121. package/dist/index.d.ts.map +1 -0
  122. package/dist/index.js +116 -0
  123. package/dist/index.js.map +1 -0
  124. package/dist/resources/health.d.ts +35 -0
  125. package/dist/resources/health.d.ts.map +1 -0
  126. package/dist/resources/health.js +81 -0
  127. package/dist/resources/health.js.map +1 -0
  128. package/dist/schemas/output-schemas.d.ts +517 -0
  129. package/dist/schemas/output-schemas.d.ts.map +1 -0
  130. package/dist/schemas/output-schemas.js +296 -0
  131. package/dist/schemas/output-schemas.js.map +1 -0
  132. package/dist/search/fast-search.d.ts +90 -0
  133. package/dist/search/fast-search.d.ts.map +1 -0
  134. package/dist/search/fast-search.js +387 -0
  135. package/dist/search/fast-search.js.map +1 -0
  136. package/dist/search/semantic.d.ts +26 -0
  137. package/dist/search/semantic.d.ts.map +1 -0
  138. package/dist/search/semantic.js +458 -0
  139. package/dist/search/semantic.js.map +1 -0
  140. package/dist/tools/analysis.d.ts +7 -0
  141. package/dist/tools/analysis.d.ts.map +1 -0
  142. package/dist/tools/analysis.js +491 -0
  143. package/dist/tools/analysis.js.map +1 -0
  144. package/dist/tools/architecture.d.ts +7 -0
  145. package/dist/tools/architecture.d.ts.map +1 -0
  146. package/dist/tools/architecture.js +176 -0
  147. package/dist/tools/architecture.js.map +1 -0
  148. package/dist/tools/devops.d.ts +7 -0
  149. package/dist/tools/devops.d.ts.map +1 -0
  150. package/dist/tools/devops.js +179 -0
  151. package/dist/tools/devops.js.map +1 -0
  152. package/dist/tools/docs.d.ts +7 -0
  153. package/dist/tools/docs.d.ts.map +1 -0
  154. package/dist/tools/docs.js +102 -0
  155. package/dist/tools/docs.js.map +1 -0
  156. package/dist/tools/git.d.ts +7 -0
  157. package/dist/tools/git.d.ts.map +1 -0
  158. package/dist/tools/git.js +475 -0
  159. package/dist/tools/git.js.map +1 -0
  160. package/dist/tools/nav.d.ts +7 -0
  161. package/dist/tools/nav.d.ts.map +1 -0
  162. package/dist/tools/nav.js +275 -0
  163. package/dist/tools/nav.js.map +1 -0
  164. package/dist/tools/notebook.d.ts +7 -0
  165. package/dist/tools/notebook.d.ts.map +1 -0
  166. package/dist/tools/notebook.js +102 -0
  167. package/dist/tools/notebook.js.map +1 -0
  168. package/dist/tools/performance.d.ts +7 -0
  169. package/dist/tools/performance.d.ts.map +1 -0
  170. package/dist/tools/performance.js +59 -0
  171. package/dist/tools/performance.js.map +1 -0
  172. package/dist/tools/quality.d.ts +7 -0
  173. package/dist/tools/quality.d.ts.map +1 -0
  174. package/dist/tools/quality.js +279 -0
  175. package/dist/tools/quality.js.map +1 -0
  176. package/dist/tools/scaffold.d.ts +7 -0
  177. package/dist/tools/scaffold.d.ts.map +1 -0
  178. package/dist/tools/scaffold.js +80 -0
  179. package/dist/tools/scaffold.js.map +1 -0
  180. package/dist/tools/search.d.ts +7 -0
  181. package/dist/tools/search.d.ts.map +1 -0
  182. package/dist/tools/search.js +308 -0
  183. package/dist/tools/search.js.map +1 -0
  184. package/dist/tools/security.d.ts +7 -0
  185. package/dist/tools/security.d.ts.map +1 -0
  186. package/dist/tools/security.js +138 -0
  187. package/dist/tools/security.js.map +1 -0
  188. package/dist/utils/analytics.d.ts +69 -0
  189. package/dist/utils/analytics.d.ts.map +1 -0
  190. package/dist/utils/analytics.js +144 -0
  191. package/dist/utils/analytics.js.map +1 -0
  192. package/dist/utils/concurrency.d.ts +43 -0
  193. package/dist/utils/concurrency.d.ts.map +1 -0
  194. package/dist/utils/concurrency.js +78 -0
  195. package/dist/utils/concurrency.js.map +1 -0
  196. package/dist/utils/fallback.d.ts +52 -0
  197. package/dist/utils/fallback.d.ts.map +1 -0
  198. package/dist/utils/fallback.js +137 -0
  199. package/dist/utils/fallback.js.map +1 -0
  200. package/dist/utils/git-hooks.d.ts +24 -0
  201. package/dist/utils/git-hooks.d.ts.map +1 -0
  202. package/dist/utils/git-hooks.js +108 -0
  203. package/dist/utils/git-hooks.js.map +1 -0
  204. package/dist/utils/languages.d.ts +72 -0
  205. package/dist/utils/languages.d.ts.map +1 -0
  206. package/dist/utils/languages.js +463 -0
  207. package/dist/utils/languages.js.map +1 -0
  208. package/dist/utils/logger.d.ts +13 -0
  209. package/dist/utils/logger.d.ts.map +1 -0
  210. package/dist/utils/logger.js +34 -0
  211. package/dist/utils/logger.js.map +1 -0
  212. package/dist/utils/plugins.d.ts +105 -0
  213. package/dist/utils/plugins.d.ts.map +1 -0
  214. package/dist/utils/plugins.js +325 -0
  215. package/dist/utils/plugins.js.map +1 -0
  216. package/dist/utils/security.d.ts +17 -0
  217. package/dist/utils/security.d.ts.map +1 -0
  218. package/dist/utils/security.js +48 -0
  219. package/dist/utils/security.js.map +1 -0
  220. package/dist/utils/streaming.d.ts +56 -0
  221. package/dist/utils/streaming.d.ts.map +1 -0
  222. package/dist/utils/streaming.js +95 -0
  223. package/dist/utils/streaming.js.map +1 -0
  224. package/dist/version.d.ts +3 -0
  225. package/dist/version.d.ts.map +1 -0
  226. package/dist/version.js +3 -0
  227. package/dist/version.js.map +1 -0
  228. package/mcp.json +100 -0
  229. package/package.json +89 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Symbol Extraction & Code Analysis
3
+ * Language-agnostic symbol detection for 40+ languages
4
+ */
5
+ export interface Symbol {
6
+ name: string;
7
+ kind: 'function' | 'class' | 'interface' | 'type' | 'constant' | 'export';
8
+ line: number;
9
+ language: string;
10
+ signature?: string;
11
+ }
12
+ export interface FileAnalysis {
13
+ path: string;
14
+ language: string;
15
+ size: number;
16
+ lines: number;
17
+ codeLines: number;
18
+ commentLines: number;
19
+ blankLines: number;
20
+ symbols: Symbol[];
21
+ imports: string[];
22
+ /** Rough cyclomatic complexity estimate */
23
+ complexity: number;
24
+ }
25
+ /**
26
+ * Extract all symbols from a file.
27
+ * @param filePath - Path to the source file
28
+ * @returns Array of symbols found in the file
29
+ */
30
+ export declare function extractSymbols(filePath: string): Promise<Symbol[]>;
31
+ /**
32
+ * Extract imports from a file.
33
+ * @param filePath - Path to the source file
34
+ * @returns Array of imported module names
35
+ */
36
+ export declare function extractImports(filePath: string): Promise<string[]>;
37
+ /**
38
+ * Full file analysis.
39
+ * @param filePath - Path to the source file
40
+ * @returns Complete file analysis with symbols, imports, and metrics
41
+ */
42
+ export declare function analyzeFile(filePath: string): Promise<FileAnalysis>;
43
+ /**
44
+ * Generate a concise outline of a file's structure.
45
+ * @param analysis - The file analysis result
46
+ * @returns Formatted string outline of the file
47
+ */
48
+ export declare function formatFileOutline(analysis: FileAnalysis): string;
49
+ //# sourceMappingURL=symbols.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/analyzers/symbols.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAiDxE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAexE;AAyFD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAsBzE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAgChE"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Symbol Extraction & Code Analysis
3
+ * Language-agnostic symbol detection for 40+ languages
4
+ */
5
+ import { readFile, stat } from 'node:fs/promises';
6
+ import { detectLanguage, getSymbolPatterns, getImportPatterns, getCommentStyle } from '../utils/languages.js';
7
+ /**
8
+ * Extract all symbols from a file.
9
+ * @param filePath - Path to the source file
10
+ * @returns Array of symbols found in the file
11
+ */
12
+ export async function extractSymbols(filePath) {
13
+ const content = await readFile(filePath, 'utf-8');
14
+ const language = detectLanguage(filePath);
15
+ const patterns = getSymbolPatterns(language);
16
+ const symbols = [];
17
+ const lines = content.split('\n');
18
+ const kinds = [
19
+ { key: 'functions', kind: 'function' },
20
+ { key: 'classes', kind: 'class' },
21
+ { key: 'interfaces', kind: 'interface' },
22
+ { key: 'types', kind: 'type' },
23
+ { key: 'constants', kind: 'constant' },
24
+ { key: 'exports', kind: 'export' },
25
+ ];
26
+ for (const { key, kind } of kinds) {
27
+ for (const pattern of patterns[key]) {
28
+ // Reset regex state
29
+ const regex = new RegExp(pattern.source, pattern.flags);
30
+ let match;
31
+ while ((match = regex.exec(content)) !== null) {
32
+ const name = match[1];
33
+ if (!name || name.length < 2)
34
+ continue;
35
+ // Deduplicate
36
+ if (symbols.some((s) => s.name === name && s.kind === kind))
37
+ continue;
38
+ // Find line number
39
+ const beforeMatch = content.slice(0, match.index);
40
+ const line = beforeMatch.split('\n').length;
41
+ // Get signature (the full matched line)
42
+ const lineContent = lines[line - 1]?.trim() || '';
43
+ symbols.push({
44
+ name,
45
+ kind,
46
+ line,
47
+ language,
48
+ // Truncate long lines
49
+ signature: lineContent.slice(0, 200),
50
+ });
51
+ }
52
+ }
53
+ }
54
+ // Sort by line number
55
+ symbols.sort((a, b) => a.line - b.line);
56
+ return symbols;
57
+ }
58
+ /**
59
+ * Extract imports from a file.
60
+ * @param filePath - Path to the source file
61
+ * @returns Array of imported module names
62
+ */
63
+ export async function extractImports(filePath) {
64
+ const content = await readFile(filePath, 'utf-8');
65
+ const language = detectLanguage(filePath);
66
+ const patterns = getImportPatterns(language);
67
+ const imports = new Set();
68
+ for (const pattern of patterns) {
69
+ const regex = new RegExp(pattern.source, pattern.flags);
70
+ let match;
71
+ while ((match = regex.exec(content)) !== null) {
72
+ if (match[1])
73
+ imports.add(match[1]);
74
+ }
75
+ }
76
+ return [...imports];
77
+ }
78
+ /**
79
+ * Count code, comment, and blank lines.
80
+ * @param content - The file content
81
+ * @param language - The programming language
82
+ * @returns Line counts by type
83
+ */
84
+ function countLineTypes(content, language) {
85
+ const lines = content.split('\n');
86
+ const style = getCommentStyle(language);
87
+ let code = 0, comment = 0, blank = 0;
88
+ let inMultiLineComment = false;
89
+ for (const line of lines) {
90
+ const trimmed = line.trim();
91
+ if (trimmed === '') {
92
+ blank++;
93
+ continue;
94
+ }
95
+ if (inMultiLineComment) {
96
+ comment++;
97
+ if (style.multiEnd && trimmed.includes(style.multiEnd)) {
98
+ inMultiLineComment = false;
99
+ }
100
+ continue;
101
+ }
102
+ if (style.multiStart && trimmed.startsWith(style.multiStart)) {
103
+ comment++;
104
+ if (!style.multiEnd || !trimmed.includes(style.multiEnd, style.multiStart.length)) {
105
+ inMultiLineComment = true;
106
+ }
107
+ continue;
108
+ }
109
+ if (style.single && trimmed.startsWith(style.single)) {
110
+ comment++;
111
+ continue;
112
+ }
113
+ code++;
114
+ }
115
+ return { code, comment, blank };
116
+ }
117
+ /**
118
+ * Rough cyclomatic complexity estimate.
119
+ * @param content - The file content
120
+ * @returns Estimated cyclomatic complexity score
121
+ */
122
+ function estimateComplexity(content) {
123
+ // Count decision points
124
+ const decisionKeywords = [
125
+ /\bif\b/g,
126
+ /\belse\s+if\b/g,
127
+ /\belif\b/g,
128
+ /\bfor\b/g,
129
+ /\bwhile\b/g,
130
+ /\bdo\b/g,
131
+ /\bswitch\b/g,
132
+ /\bcase\b/g,
133
+ /\bmatch\b/g,
134
+ /\bcatch\b/g,
135
+ /\bexcept\b/g,
136
+ /\brescue\b/g,
137
+ /\?\?/g,
138
+ /\?\./g,
139
+ /&&/g,
140
+ /\|\|/g,
141
+ /\bwhen\b/g,
142
+ /\bguard\b/g,
143
+ ];
144
+ // Base complexity
145
+ let complexity = 1;
146
+ for (const pattern of decisionKeywords) {
147
+ const matches = content.match(pattern);
148
+ if (matches)
149
+ complexity += matches.length;
150
+ }
151
+ return complexity;
152
+ }
153
+ /**
154
+ * Full file analysis.
155
+ * @param filePath - Path to the source file
156
+ * @returns Complete file analysis with symbols, imports, and metrics
157
+ */
158
+ export async function analyzeFile(filePath) {
159
+ const content = await readFile(filePath, 'utf-8');
160
+ const fileStat = await stat(filePath);
161
+ const language = detectLanguage(filePath);
162
+ const lines = content.split('\n').length;
163
+ const lineCounts = countLineTypes(content, language);
164
+ const symbols = await extractSymbols(filePath);
165
+ const imports = await extractImports(filePath);
166
+ const complexity = estimateComplexity(content);
167
+ return {
168
+ path: filePath,
169
+ language,
170
+ size: fileStat.size,
171
+ lines,
172
+ codeLines: lineCounts.code,
173
+ commentLines: lineCounts.comment,
174
+ blankLines: lineCounts.blank,
175
+ symbols,
176
+ imports,
177
+ complexity,
178
+ };
179
+ }
180
+ /**
181
+ * Generate a concise outline of a file's structure.
182
+ * @param analysis - The file analysis result
183
+ * @returns Formatted string outline of the file
184
+ */
185
+ export function formatFileOutline(analysis) {
186
+ const parts = [];
187
+ parts.push(`📄 ${analysis.path}`);
188
+ parts.push(` Language: ${analysis.language} | Lines: ${analysis.lines} (code: ${analysis.codeLines}, comments: ${analysis.commentLines}) | Complexity: ${analysis.complexity}`);
189
+ if (analysis.imports.length > 0) {
190
+ parts.push(` 📦 Imports: ${analysis.imports.join(', ')}`);
191
+ }
192
+ const grouped = {};
193
+ for (const sym of analysis.symbols) {
194
+ if (!grouped[sym.kind])
195
+ grouped[sym.kind] = [];
196
+ grouped[sym.kind].push(sym);
197
+ }
198
+ const icons = {
199
+ class: '🏗️',
200
+ interface: '📋',
201
+ type: '🔷',
202
+ function: 'ƒ',
203
+ constant: '🔒',
204
+ export: '📤',
205
+ };
206
+ for (const [kind, syms] of Object.entries(grouped)) {
207
+ const icon = icons[kind] || '•';
208
+ parts.push(` ${icon} ${kind}s: ${syms.map((s) => `${s.name}:${s.line}`).join(', ')}`);
209
+ }
210
+ return parts.join('\n');
211
+ }
212
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/analyzers/symbols.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Tree-sitter AST parsing for accurate code analysis.
3
+ * Uses web-tree-sitter (WASM-based, no native compilation).
4
+ * Falls back to regex-based parsing if grammars unavailable.
5
+ *
6
+ * Supported languages: TypeScript, JavaScript, Python, Go, Java, Rust, C/C++
7
+ */
8
+ export interface ASTSymbol {
9
+ name: string;
10
+ type: 'function' | 'class' | 'method' | 'interface' | 'enum' | 'variable' | 'type' | 'module' | 'struct' | 'trait';
11
+ startLine: number;
12
+ endLine: number;
13
+ exported: boolean;
14
+ params?: string[];
15
+ returnType?: string;
16
+ docComment?: string;
17
+ /** Methods inside classes, etc. */
18
+ children?: ASTSymbol[];
19
+ }
20
+ export interface CallGraphEntry {
21
+ caller: string;
22
+ callee: string;
23
+ file: string;
24
+ line: number;
25
+ }
26
+ export interface ScopeInfo {
27
+ name: string;
28
+ type: string;
29
+ startLine: number;
30
+ endLine: number;
31
+ variables: string[];
32
+ children: ScopeInfo[];
33
+ }
34
+ /**
35
+ * Initialize tree-sitter. Call once at startup.
36
+ * @returns True if initialization succeeded
37
+ */
38
+ export declare function initTreeSitter(): Promise<boolean>;
39
+ /**
40
+ * Check if tree-sitter is available and ready.
41
+ * @returns True if tree-sitter has been initialized
42
+ */
43
+ export declare function isTreeSitterReady(): boolean;
44
+ /**
45
+ * Get supported languages for tree-sitter.
46
+ * @returns Array of supported language names
47
+ */
48
+ export declare function getTreeSitterLanguages(): string[];
49
+ /**
50
+ * Parse a file into an AST and extract symbols.
51
+ * Falls back to null if tree-sitter isn't available for this language.
52
+ * @param filePath - Path to the source file
53
+ * @param language - The programming language
54
+ * @returns Array of AST symbols or null if parsing unavailable
55
+ */
56
+ export declare function parseAST(filePath: string, language: string): Promise<ASTSymbol[] | null>;
57
+ /**
58
+ * Extract call graph from a file -- which functions call which.
59
+ * @param filePath - Path to the source file
60
+ * @param language - The programming language
61
+ * @returns Array of call graph entries or null if parsing unavailable
62
+ */
63
+ export declare function extractCallGraph(filePath: string, language: string): Promise<CallGraphEntry[] | null>;
64
+ /**
65
+ * Extract scope information from a file.
66
+ * @param filePath - Path to the source file
67
+ * @param language - The programming language
68
+ * @returns Array of scope information or null if parsing unavailable
69
+ */
70
+ export declare function extractScopes(filePath: string, language: string): Promise<ScopeInfo[] | null>;
71
+ //# sourceMappingURL=tree-sitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-sitter.d.ts","sourceRoot":"","sources":["../../src/analyzers/tree-sitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA6CH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnH,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAavD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD;AAsCD;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAoB9F;AA4GD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,CAwD3G;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAmEnG"}
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Tree-sitter AST parsing for accurate code analysis.
3
+ * Uses web-tree-sitter (WASM-based, no native compilation).
4
+ * Falls back to regex-based parsing if grammars unavailable.
5
+ *
6
+ * Supported languages: TypeScript, JavaScript, Python, Go, Java, Rust, C/C++
7
+ */
8
+ import path from 'node:path';
9
+ import { readFile } from 'node:fs/promises';
10
+ // Dynamic import for web-tree-sitter (may not be available)
11
+ let Parser = null;
12
+ let treeSitterReady = false;
13
+ const loadedLanguages = new Map();
14
+ // Grammar file locations (downloaded on first use)
15
+ const GRAMMAR_URLS = {
16
+ typescript: 'tree-sitter-typescript.wasm',
17
+ javascript: 'tree-sitter-javascript.wasm',
18
+ python: 'tree-sitter-python.wasm',
19
+ go: 'tree-sitter-go.wasm',
20
+ java: 'tree-sitter-java.wasm',
21
+ rust: 'tree-sitter-rust.wasm',
22
+ c: 'tree-sitter-c.wasm',
23
+ cpp: 'tree-sitter-cpp.wasm',
24
+ };
25
+ /**
26
+ * Initialize tree-sitter. Call once at startup.
27
+ * @returns True if initialization succeeded
28
+ */
29
+ export async function initTreeSitter() {
30
+ try {
31
+ const TreeSitter = await import('web-tree-sitter');
32
+ const TreeSitterModule = TreeSitter.default || TreeSitter;
33
+ // Type assertion needed because web-tree-sitter types don't match our interface exactly
34
+ Parser = TreeSitterModule;
35
+ await Parser.init();
36
+ treeSitterReady = true;
37
+ return true;
38
+ }
39
+ catch {
40
+ treeSitterReady = false;
41
+ return false;
42
+ }
43
+ }
44
+ /**
45
+ * Check if tree-sitter is available and ready.
46
+ * @returns True if tree-sitter has been initialized
47
+ */
48
+ export function isTreeSitterReady() {
49
+ return treeSitterReady;
50
+ }
51
+ /**
52
+ * Get supported languages for tree-sitter.
53
+ * @returns Array of supported language names
54
+ */
55
+ export function getTreeSitterLanguages() {
56
+ return Object.keys(GRAMMAR_URLS);
57
+ }
58
+ /**
59
+ * Load a language grammar. Returns null if not available.
60
+ * @param language - The language name to load
61
+ * @returns The loaded language grammar or null
62
+ */
63
+ async function loadLanguage(language) {
64
+ if (!treeSitterReady || !Parser)
65
+ return null;
66
+ if (loadedLanguages.has(language))
67
+ return loadedLanguages.get(language);
68
+ const grammarFile = GRAMMAR_URLS[language];
69
+ if (!grammarFile)
70
+ return null;
71
+ try {
72
+ // Try loading from node_modules or local cache
73
+ const possiblePaths = [
74
+ path.join(process.cwd(), 'grammars', grammarFile),
75
+ path.join(process.cwd(), '.codedev-mcp', 'grammars', grammarFile),
76
+ path.join(process.env.HOME || '', '.codedev-mcp', 'grammars', grammarFile),
77
+ ];
78
+ for (const p of possiblePaths) {
79
+ try {
80
+ const lang = await Parser.Language.load(p);
81
+ loadedLanguages.set(language, lang);
82
+ return lang;
83
+ }
84
+ catch {
85
+ continue;
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Parse a file into an AST and extract symbols.
96
+ * Falls back to null if tree-sitter isn't available for this language.
97
+ * @param filePath - Path to the source file
98
+ * @param language - The programming language
99
+ * @returns Array of AST symbols or null if parsing unavailable
100
+ */
101
+ export async function parseAST(filePath, language) {
102
+ const lang = await loadLanguage(language);
103
+ if (!lang || !Parser)
104
+ return null;
105
+ try {
106
+ const content = await readFile(filePath, 'utf-8');
107
+ const parser = new Parser();
108
+ parser.setLanguage(lang);
109
+ const tree = parser.parse(content);
110
+ const symbols = [];
111
+ extractSymbolsFromNode(tree.rootNode, symbols, content, language);
112
+ parser.delete();
113
+ tree.delete();
114
+ return symbols;
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ /**
121
+ * Recursively extract symbols from AST nodes.
122
+ * @param node - The current AST node
123
+ * @param symbols - Accumulator for found symbols
124
+ * @param source - The full source code
125
+ * @param language - The programming language
126
+ * @param depth - Current recursion depth
127
+ */
128
+ function extractSymbolsFromNode(node, symbols, source, language, depth = 0) {
129
+ // Prevent infinite recursion
130
+ if (depth > 10)
131
+ return;
132
+ const symbolTypes = {
133
+ function_declaration: 'function',
134
+ function_definition: 'function',
135
+ method_definition: 'method',
136
+ method_declaration: 'method',
137
+ class_declaration: 'class',
138
+ class_definition: 'class',
139
+ interface_declaration: 'interface',
140
+ type_alias_declaration: 'type',
141
+ enum_declaration: 'enum',
142
+ struct_item: 'struct',
143
+ impl_item: 'module',
144
+ trait_item: 'trait',
145
+ variable_declaration: 'variable',
146
+ lexical_declaration: 'variable',
147
+ };
148
+ const nodeType = symbolTypes[node.type];
149
+ if (nodeType) {
150
+ const nameNode = node.childForFieldName?.('name') ||
151
+ node.children?.find((c) => c.type === 'identifier' || c.type === 'type_identifier');
152
+ if (nameNode) {
153
+ const symbol = {
154
+ name: nameNode.text,
155
+ type: nodeType,
156
+ startLine: node.startPosition.row + 1,
157
+ endLine: node.endPosition.row + 1,
158
+ exported: isExported(node, source),
159
+ children: [],
160
+ };
161
+ // Extract params for functions
162
+ const params = node.childForFieldName?.('parameters') || node.childForFieldName?.('formal_parameters');
163
+ if (params) {
164
+ symbol.params = extractParams(params);
165
+ }
166
+ // Extract return type
167
+ const returnType = node.childForFieldName?.('return_type') || node.childForFieldName?.('result');
168
+ if (returnType) {
169
+ symbol.returnType = returnType.text;
170
+ }
171
+ // Extract doc comment (preceding comment node)
172
+ const prevSibling = node.previousNamedSibling;
173
+ if (prevSibling && (prevSibling.type === 'comment' || prevSibling.type === 'block_comment')) {
174
+ symbol.docComment = prevSibling.text;
175
+ }
176
+ // Extract children (methods inside classes)
177
+ if (nodeType === 'class' || nodeType === 'struct' || nodeType === 'trait') {
178
+ const body = node.childForFieldName?.('body');
179
+ if (body) {
180
+ const childSymbols = [];
181
+ for (const child of body.children || []) {
182
+ extractSymbolsFromNode(child, childSymbols, source, language, depth + 1);
183
+ }
184
+ symbol.children = childSymbols;
185
+ }
186
+ }
187
+ symbols.push(symbol);
188
+ // Don't recurse into the same symbol
189
+ return;
190
+ }
191
+ }
192
+ // Recurse into children
193
+ for (const child of node.children || []) {
194
+ extractSymbolsFromNode(child, symbols, source, language, depth + 1);
195
+ }
196
+ }
197
+ function isExported(node, source) {
198
+ const lineStart = source.lastIndexOf('\n', node.startIndex) + 1;
199
+ const lineText = source.slice(lineStart, node.startIndex + 50);
200
+ return /export\s/.test(lineText) || /^pub\s/.test(lineText);
201
+ }
202
+ function extractParams(paramsNode) {
203
+ return (paramsNode.children || [])
204
+ .filter((c) => c.type !== '(' && c.type !== ')' && c.type !== ',')
205
+ .map((c) => c.text)
206
+ .filter((t) => t.trim().length > 0);
207
+ }
208
+ /**
209
+ * Extract call graph from a file -- which functions call which.
210
+ * @param filePath - Path to the source file
211
+ * @param language - The programming language
212
+ * @returns Array of call graph entries or null if parsing unavailable
213
+ */
214
+ export async function extractCallGraph(filePath, language) {
215
+ const lang = await loadLanguage(language);
216
+ if (!lang || !Parser)
217
+ return null;
218
+ try {
219
+ const content = await readFile(filePath, 'utf-8');
220
+ const parser = new Parser();
221
+ parser.setLanguage(lang);
222
+ const tree = parser.parse(content);
223
+ const calls = [];
224
+ const funcStack = [];
225
+ function walkForCalls(node) {
226
+ // Track function scope
227
+ const isFuncDef = ['function_declaration', 'function_definition', 'method_definition', 'arrow_function'].includes(node.type);
228
+ if (isFuncDef) {
229
+ const nameNode = node.childForFieldName?.('name');
230
+ if (nameNode)
231
+ funcStack.push(nameNode.text);
232
+ }
233
+ // Detect function calls
234
+ if (node.type === 'call_expression') {
235
+ const funcNode = node.childForFieldName?.('function') || node.children?.[0];
236
+ if (funcNode) {
237
+ const callee = funcNode.text;
238
+ const caller = funcStack.length > 0 ? funcStack[funcStack.length - 1] : '<module>';
239
+ calls.push({
240
+ caller,
241
+ callee,
242
+ file: filePath,
243
+ line: node.startPosition.row + 1,
244
+ });
245
+ }
246
+ }
247
+ for (const child of node.children || []) {
248
+ walkForCalls(child);
249
+ }
250
+ if (isFuncDef && node.childForFieldName?.('name')) {
251
+ funcStack.pop();
252
+ }
253
+ }
254
+ walkForCalls(tree.rootNode);
255
+ parser.delete();
256
+ tree.delete();
257
+ return calls;
258
+ }
259
+ catch {
260
+ return null;
261
+ }
262
+ }
263
+ /**
264
+ * Extract scope information from a file.
265
+ * @param filePath - Path to the source file
266
+ * @param language - The programming language
267
+ * @returns Array of scope information or null if parsing unavailable
268
+ */
269
+ export async function extractScopes(filePath, language) {
270
+ const lang = await loadLanguage(language);
271
+ if (!lang || !Parser)
272
+ return null;
273
+ try {
274
+ const content = await readFile(filePath, 'utf-8');
275
+ const parser = new Parser();
276
+ parser.setLanguage(lang);
277
+ const tree = parser.parse(content);
278
+ const scopes = [];
279
+ function walkForScopes(node, parent) {
280
+ const scopeTypes = [
281
+ 'function_declaration',
282
+ 'function_definition',
283
+ 'method_definition',
284
+ 'class_declaration',
285
+ 'class_definition',
286
+ 'block',
287
+ 'if_statement',
288
+ 'for_statement',
289
+ 'while_statement',
290
+ 'try_statement',
291
+ ];
292
+ if (scopeTypes.includes(node.type)) {
293
+ const nameNode = node.childForFieldName?.('name');
294
+ const scope = {
295
+ name: nameNode?.text || `<${node.type}>`,
296
+ type: node.type,
297
+ startLine: node.startPosition.row + 1,
298
+ endLine: node.endPosition.row + 1,
299
+ variables: [],
300
+ children: [],
301
+ };
302
+ // Extract variable declarations within this scope
303
+ for (const child of node.children || []) {
304
+ if (['variable_declaration', 'lexical_declaration', 'assignment'].includes(child.type)) {
305
+ const varName = child.childForFieldName?.('name');
306
+ if (varName)
307
+ scope.variables.push(varName.text);
308
+ }
309
+ }
310
+ if (parent)
311
+ parent.children.push(scope);
312
+ else
313
+ scopes.push(scope);
314
+ for (const child of node.children || []) {
315
+ walkForScopes(child, scope);
316
+ }
317
+ }
318
+ else {
319
+ for (const child of node.children || []) {
320
+ walkForScopes(child, parent);
321
+ }
322
+ }
323
+ }
324
+ walkForScopes(tree.rootNode, null);
325
+ parser.delete();
326
+ tree.delete();
327
+ return scopes;
328
+ }
329
+ catch {
330
+ return null;
331
+ }
332
+ }
333
+ //# sourceMappingURL=tree-sitter.js.map