eff-u-code 2.0.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 (245) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -0
  3. package/bin/fuck-u-code-mcp.js +2 -0
  4. package/bin/fuck-u-code.js +2 -0
  5. package/bin/postinstall.js +53 -0
  6. package/dist/ai/index.d.ts +34 -0
  7. package/dist/ai/index.d.ts.map +1 -0
  8. package/dist/ai/index.js +227 -0
  9. package/dist/ai/index.js.map +1 -0
  10. package/dist/ai/prompts/code-review.d.ts +9 -0
  11. package/dist/ai/prompts/code-review.d.ts.map +1 -0
  12. package/dist/ai/prompts/code-review.js +61 -0
  13. package/dist/ai/prompts/code-review.js.map +1 -0
  14. package/dist/ai/providers/anthropic.d.ts +11 -0
  15. package/dist/ai/providers/anthropic.d.ts.map +1 -0
  16. package/dist/ai/providers/anthropic.js +60 -0
  17. package/dist/ai/providers/anthropic.js.map +1 -0
  18. package/dist/ai/providers/fetch.d.ts +10 -0
  19. package/dist/ai/providers/fetch.d.ts.map +1 -0
  20. package/dist/ai/providers/fetch.js +50 -0
  21. package/dist/ai/providers/fetch.js.map +1 -0
  22. package/dist/ai/providers/gemini.d.ts +12 -0
  23. package/dist/ai/providers/gemini.d.ts.map +1 -0
  24. package/dist/ai/providers/gemini.js +66 -0
  25. package/dist/ai/providers/gemini.js.map +1 -0
  26. package/dist/ai/providers/ollama.d.ts +11 -0
  27. package/dist/ai/providers/ollama.d.ts.map +1 -0
  28. package/dist/ai/providers/ollama.js +54 -0
  29. package/dist/ai/providers/ollama.js.map +1 -0
  30. package/dist/ai/providers/openai.d.ts +11 -0
  31. package/dist/ai/providers/openai.d.ts.map +1 -0
  32. package/dist/ai/providers/openai.js +52 -0
  33. package/dist/ai/providers/openai.js.map +1 -0
  34. package/dist/ai/selector.d.ts +19 -0
  35. package/dist/ai/selector.d.ts.map +1 -0
  36. package/dist/ai/selector.js +145 -0
  37. package/dist/ai/selector.js.map +1 -0
  38. package/dist/ai/types.d.ts +120 -0
  39. package/dist/ai/types.d.ts.map +1 -0
  40. package/dist/ai/types.js +6 -0
  41. package/dist/ai/types.js.map +1 -0
  42. package/dist/analyzer/concurrent-analyzer.d.ts +11 -0
  43. package/dist/analyzer/concurrent-analyzer.d.ts.map +1 -0
  44. package/dist/analyzer/concurrent-analyzer.js +67 -0
  45. package/dist/analyzer/concurrent-analyzer.js.map +1 -0
  46. package/dist/analyzer/file-discovery.d.ts +23 -0
  47. package/dist/analyzer/file-discovery.d.ts.map +1 -0
  48. package/dist/analyzer/file-discovery.js +64 -0
  49. package/dist/analyzer/file-discovery.js.map +1 -0
  50. package/dist/analyzer/index.d.ts +27 -0
  51. package/dist/analyzer/index.d.ts.map +1 -0
  52. package/dist/analyzer/index.js +64 -0
  53. package/dist/analyzer/index.js.map +1 -0
  54. package/dist/cli/commands/ai-review.d.ts +6 -0
  55. package/dist/cli/commands/ai-review.d.ts.map +1 -0
  56. package/dist/cli/commands/ai-review.js +213 -0
  57. package/dist/cli/commands/ai-review.js.map +1 -0
  58. package/dist/cli/commands/analyze.d.ts +6 -0
  59. package/dist/cli/commands/analyze.d.ts.map +1 -0
  60. package/dist/cli/commands/analyze.js +145 -0
  61. package/dist/cli/commands/analyze.js.map +1 -0
  62. package/dist/cli/commands/config.d.ts +6 -0
  63. package/dist/cli/commands/config.d.ts.map +1 -0
  64. package/dist/cli/commands/config.js +147 -0
  65. package/dist/cli/commands/config.js.map +1 -0
  66. package/dist/cli/commands/mcp-install.d.ts +9 -0
  67. package/dist/cli/commands/mcp-install.d.ts.map +1 -0
  68. package/dist/cli/commands/mcp-install.js +102 -0
  69. package/dist/cli/commands/mcp-install.js.map +1 -0
  70. package/dist/cli/index.d.ts +7 -0
  71. package/dist/cli/index.d.ts.map +1 -0
  72. package/dist/cli/index.js +69 -0
  73. package/dist/cli/index.js.map +1 -0
  74. package/dist/cli/output/ai-review-output.d.ts +20 -0
  75. package/dist/cli/output/ai-review-output.d.ts.map +1 -0
  76. package/dist/cli/output/ai-review-output.js +324 -0
  77. package/dist/cli/output/ai-review-output.js.map +1 -0
  78. package/dist/cli/output/console.d.ts +31 -0
  79. package/dist/cli/output/console.d.ts.map +1 -0
  80. package/dist/cli/output/console.js +571 -0
  81. package/dist/cli/output/console.js.map +1 -0
  82. package/dist/cli/output/html.d.ts +20 -0
  83. package/dist/cli/output/html.d.ts.map +1 -0
  84. package/dist/cli/output/html.js +339 -0
  85. package/dist/cli/output/html.js.map +1 -0
  86. package/dist/cli/output/json.d.ts +8 -0
  87. package/dist/cli/output/json.d.ts.map +1 -0
  88. package/dist/cli/output/json.js +46 -0
  89. package/dist/cli/output/json.js.map +1 -0
  90. package/dist/cli/output/markdown.d.ts +17 -0
  91. package/dist/cli/output/markdown.d.ts.map +1 -0
  92. package/dist/cli/output/markdown.js +323 -0
  93. package/dist/cli/output/markdown.js.map +1 -0
  94. package/dist/cli/output/stats.d.ts +35 -0
  95. package/dist/cli/output/stats.d.ts.map +1 -0
  96. package/dist/cli/output/stats.js +63 -0
  97. package/dist/cli/output/stats.js.map +1 -0
  98. package/dist/cli/output/terminal-markdown.d.ts +23 -0
  99. package/dist/cli/output/terminal-markdown.d.ts.map +1 -0
  100. package/dist/cli/output/terminal-markdown.js +159 -0
  101. package/dist/cli/output/terminal-markdown.js.map +1 -0
  102. package/dist/config/index.d.ts +27 -0
  103. package/dist/config/index.d.ts.map +1 -0
  104. package/dist/config/index.js +266 -0
  105. package/dist/config/index.js.map +1 -0
  106. package/dist/config/schema.d.ts +179 -0
  107. package/dist/config/schema.d.ts.map +1 -0
  108. package/dist/config/schema.js +85 -0
  109. package/dist/config/schema.js.map +1 -0
  110. package/dist/gitignore/index.d.ts +5 -0
  111. package/dist/gitignore/index.d.ts.map +1 -0
  112. package/dist/gitignore/index.js +5 -0
  113. package/dist/gitignore/index.js.map +1 -0
  114. package/dist/gitignore/parser.d.ts +32 -0
  115. package/dist/gitignore/parser.d.ts.map +1 -0
  116. package/dist/gitignore/parser.js +110 -0
  117. package/dist/gitignore/parser.js.map +1 -0
  118. package/dist/gitignore/parser.test.d.ts +2 -0
  119. package/dist/gitignore/parser.test.d.ts.map +1 -0
  120. package/dist/gitignore/parser.test.js +217 -0
  121. package/dist/gitignore/parser.test.js.map +1 -0
  122. package/dist/i18n/index.d.ts +19 -0
  123. package/dist/i18n/index.d.ts.map +1 -0
  124. package/dist/i18n/index.js +43 -0
  125. package/dist/i18n/index.js.map +1 -0
  126. package/dist/i18n/locales/en.json +320 -0
  127. package/dist/i18n/locales/ru.json +320 -0
  128. package/dist/i18n/locales/zh.json +320 -0
  129. package/dist/index.d.ts +5 -0
  130. package/dist/index.d.ts.map +1 -0
  131. package/dist/index.js +10 -0
  132. package/dist/index.js.map +1 -0
  133. package/dist/mcp/server.d.ts +9 -0
  134. package/dist/mcp/server.d.ts.map +1 -0
  135. package/dist/mcp/server.js +156 -0
  136. package/dist/mcp/server.js.map +1 -0
  137. package/dist/metrics/complexity/cognitive.d.ts +25 -0
  138. package/dist/metrics/complexity/cognitive.d.ts.map +1 -0
  139. package/dist/metrics/complexity/cognitive.js +109 -0
  140. package/dist/metrics/complexity/cognitive.js.map +1 -0
  141. package/dist/metrics/complexity/cyclomatic.d.ts +21 -0
  142. package/dist/metrics/complexity/cyclomatic.d.ts.map +1 -0
  143. package/dist/metrics/complexity/cyclomatic.js +111 -0
  144. package/dist/metrics/complexity/cyclomatic.js.map +1 -0
  145. package/dist/metrics/complexity/nesting-depth.d.ts +19 -0
  146. package/dist/metrics/complexity/nesting-depth.d.ts.map +1 -0
  147. package/dist/metrics/complexity/nesting-depth.js +97 -0
  148. package/dist/metrics/complexity/nesting-depth.js.map +1 -0
  149. package/dist/metrics/documentation/comment-ratio.d.ts +21 -0
  150. package/dist/metrics/documentation/comment-ratio.d.ts.map +1 -0
  151. package/dist/metrics/documentation/comment-ratio.js +91 -0
  152. package/dist/metrics/documentation/comment-ratio.js.map +1 -0
  153. package/dist/metrics/duplication/code-duplication.d.ts +24 -0
  154. package/dist/metrics/duplication/code-duplication.d.ts.map +1 -0
  155. package/dist/metrics/duplication/code-duplication.js +167 -0
  156. package/dist/metrics/duplication/code-duplication.js.map +1 -0
  157. package/dist/metrics/duplication/code-duplication.test.d.ts +2 -0
  158. package/dist/metrics/duplication/code-duplication.test.d.ts.map +1 -0
  159. package/dist/metrics/duplication/code-duplication.test.js +612 -0
  160. package/dist/metrics/duplication/code-duplication.test.js.map +1 -0
  161. package/dist/metrics/error/error-handling.d.ts +23 -0
  162. package/dist/metrics/error/error-handling.d.ts.map +1 -0
  163. package/dist/metrics/error/error-handling.js +164 -0
  164. package/dist/metrics/error/error-handling.js.map +1 -0
  165. package/dist/metrics/error/error-handling.test.d.ts +2 -0
  166. package/dist/metrics/error/error-handling.test.d.ts.map +1 -0
  167. package/dist/metrics/error/error-handling.test.js +349 -0
  168. package/dist/metrics/error/error-handling.test.js.map +1 -0
  169. package/dist/metrics/index.d.ts +21 -0
  170. package/dist/metrics/index.d.ts.map +1 -0
  171. package/dist/metrics/index.js +50 -0
  172. package/dist/metrics/index.js.map +1 -0
  173. package/dist/metrics/naming/convention.d.ts +22 -0
  174. package/dist/metrics/naming/convention.d.ts.map +1 -0
  175. package/dist/metrics/naming/convention.js +117 -0
  176. package/dist/metrics/naming/convention.js.map +1 -0
  177. package/dist/metrics/size/file-length.d.ts +19 -0
  178. package/dist/metrics/size/file-length.d.ts.map +1 -0
  179. package/dist/metrics/size/file-length.js +68 -0
  180. package/dist/metrics/size/file-length.js.map +1 -0
  181. package/dist/metrics/size/function-length.d.ts +20 -0
  182. package/dist/metrics/size/function-length.d.ts.map +1 -0
  183. package/dist/metrics/size/function-length.js +101 -0
  184. package/dist/metrics/size/function-length.js.map +1 -0
  185. package/dist/metrics/size/parameter-count.d.ts +19 -0
  186. package/dist/metrics/size/parameter-count.d.ts.map +1 -0
  187. package/dist/metrics/size/parameter-count.js +97 -0
  188. package/dist/metrics/size/parameter-count.js.map +1 -0
  189. package/dist/metrics/structure/structure-analysis.d.ts +24 -0
  190. package/dist/metrics/structure/structure-analysis.d.ts.map +1 -0
  191. package/dist/metrics/structure/structure-analysis.js +223 -0
  192. package/dist/metrics/structure/structure-analysis.js.map +1 -0
  193. package/dist/metrics/structure/structure-analysis.test.d.ts +2 -0
  194. package/dist/metrics/structure/structure-analysis.test.d.ts.map +1 -0
  195. package/dist/metrics/structure/structure-analysis.test.js +342 -0
  196. package/dist/metrics/structure/structure-analysis.test.js.map +1 -0
  197. package/dist/metrics/types.d.ts +71 -0
  198. package/dist/metrics/types.d.ts.map +1 -0
  199. package/dist/metrics/types.js +5 -0
  200. package/dist/metrics/types.js.map +1 -0
  201. package/dist/parser/generic-parser.d.ts +28 -0
  202. package/dist/parser/generic-parser.d.ts.map +1 -0
  203. package/dist/parser/generic-parser.js +218 -0
  204. package/dist/parser/generic-parser.js.map +1 -0
  205. package/dist/parser/index.d.ts +19 -0
  206. package/dist/parser/index.d.ts.map +1 -0
  207. package/dist/parser/index.js +52 -0
  208. package/dist/parser/index.js.map +1 -0
  209. package/dist/parser/regex-parser.d.ts +46 -0
  210. package/dist/parser/regex-parser.d.ts.map +1 -0
  211. package/dist/parser/regex-parser.js +560 -0
  212. package/dist/parser/regex-parser.js.map +1 -0
  213. package/dist/parser/tree-sitter-parser.d.ts +50 -0
  214. package/dist/parser/tree-sitter-parser.d.ts.map +1 -0
  215. package/dist/parser/tree-sitter-parser.js +707 -0
  216. package/dist/parser/tree-sitter-parser.js.map +1 -0
  217. package/dist/parser/types.d.ts +52 -0
  218. package/dist/parser/types.d.ts.map +1 -0
  219. package/dist/parser/types.js +49 -0
  220. package/dist/parser/types.js.map +1 -0
  221. package/dist/scoring/index.d.ts +14 -0
  222. package/dist/scoring/index.d.ts.map +1 -0
  223. package/dist/scoring/index.js +80 -0
  224. package/dist/scoring/index.js.map +1 -0
  225. package/dist/utils/fs.d.ts +24 -0
  226. package/dist/utils/fs.d.ts.map +1 -0
  227. package/dist/utils/fs.js +61 -0
  228. package/dist/utils/fs.js.map +1 -0
  229. package/dist/utils/logger.d.ts +13 -0
  230. package/dist/utils/logger.d.ts.map +1 -0
  231. package/dist/utils/logger.js +43 -0
  232. package/dist/utils/logger.js.map +1 -0
  233. package/dist/utils/markdown.d.ts +16 -0
  234. package/dist/utils/markdown.d.ts.map +1 -0
  235. package/dist/utils/markdown.js +303 -0
  236. package/dist/utils/markdown.js.map +1 -0
  237. package/dist/utils/progress.d.ts +24 -0
  238. package/dist/utils/progress.d.ts.map +1 -0
  239. package/dist/utils/progress.js +79 -0
  240. package/dist/utils/progress.js.map +1 -0
  241. package/dist/utils/terminal.d.ts +62 -0
  242. package/dist/utils/terminal.d.ts.map +1 -0
  243. package/dist/utils/terminal.js +207 -0
  244. package/dist/utils/terminal.js.map +1 -0
  245. package/package.json +77 -0
@@ -0,0 +1,707 @@
1
+ /**
2
+ * Tree-sitter AST-based parser
3
+ * Uses web-tree-sitter WASM bindings for precise code analysis
4
+ */
5
+ import Parser from 'web-tree-sitter';
6
+ import { resolve, dirname } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ const LANG_CONFIGS = {
10
+ go: {
11
+ wasmFile: 'tree-sitter-go.wasm',
12
+ functionNodeTypes: ['function_declaration', 'method_declaration'],
13
+ classNodeTypes: ['type_declaration'],
14
+ importNodeTypes: ['import_declaration'],
15
+ complexityNodeTypes: [
16
+ 'if_statement',
17
+ 'for_statement',
18
+ 'expression_switch_statement',
19
+ 'type_switch_statement',
20
+ 'select_statement',
21
+ 'expression_case',
22
+ 'type_case',
23
+ 'default_case',
24
+ ],
25
+ nestingNodeTypes: [
26
+ 'if_statement',
27
+ 'for_statement',
28
+ 'expression_switch_statement',
29
+ 'type_switch_statement',
30
+ 'select_statement',
31
+ 'func_literal',
32
+ ],
33
+ commentNodeTypes: ['comment'],
34
+ functionNameField: 'name',
35
+ functionParamsField: 'parameters',
36
+ functionBodyField: 'body',
37
+ classNameField: 'name',
38
+ classBodyField: 'type',
39
+ methodNodeTypes: ['method_declaration'],
40
+ fieldNodeTypes: ['field_declaration'],
41
+ },
42
+ javascript: {
43
+ wasmFile: 'tree-sitter-javascript.wasm',
44
+ functionNodeTypes: [
45
+ 'function_declaration',
46
+ 'method_definition',
47
+ 'arrow_function',
48
+ 'generator_function_declaration',
49
+ ],
50
+ classNodeTypes: ['class_declaration'],
51
+ importNodeTypes: ['import_statement'],
52
+ complexityNodeTypes: [
53
+ 'if_statement',
54
+ 'for_statement',
55
+ 'for_in_statement',
56
+ 'while_statement',
57
+ 'do_statement',
58
+ 'switch_case',
59
+ 'catch_clause',
60
+ 'ternary_expression',
61
+ ],
62
+ nestingNodeTypes: [
63
+ 'if_statement',
64
+ 'for_statement',
65
+ 'for_in_statement',
66
+ 'while_statement',
67
+ 'do_statement',
68
+ 'switch_statement',
69
+ 'arrow_function',
70
+ 'function',
71
+ ],
72
+ commentNodeTypes: ['comment'],
73
+ functionNameField: 'name',
74
+ functionParamsField: 'parameters',
75
+ functionBodyField: 'body',
76
+ classNameField: 'name',
77
+ classBodyField: 'body',
78
+ methodNodeTypes: ['method_definition'],
79
+ fieldNodeTypes: ['field_definition', 'public_field_definition'],
80
+ },
81
+ typescript: {
82
+ wasmFile: 'tree-sitter-typescript.wasm',
83
+ functionNodeTypes: [
84
+ 'function_declaration',
85
+ 'method_definition',
86
+ 'arrow_function',
87
+ 'generator_function_declaration',
88
+ ],
89
+ classNodeTypes: ['class_declaration', 'interface_declaration'],
90
+ importNodeTypes: ['import_statement'],
91
+ complexityNodeTypes: [
92
+ 'if_statement',
93
+ 'for_statement',
94
+ 'for_in_statement',
95
+ 'while_statement',
96
+ 'do_statement',
97
+ 'switch_case',
98
+ 'catch_clause',
99
+ 'ternary_expression',
100
+ ],
101
+ nestingNodeTypes: [
102
+ 'if_statement',
103
+ 'for_statement',
104
+ 'for_in_statement',
105
+ 'while_statement',
106
+ 'do_statement',
107
+ 'switch_statement',
108
+ 'arrow_function',
109
+ 'function',
110
+ ],
111
+ commentNodeTypes: ['comment'],
112
+ functionNameField: 'name',
113
+ functionParamsField: 'parameters',
114
+ functionBodyField: 'body',
115
+ classNameField: 'name',
116
+ classBodyField: 'body',
117
+ methodNodeTypes: ['method_definition', 'method_signature'],
118
+ fieldNodeTypes: ['public_field_definition', 'property_signature'],
119
+ },
120
+ python: {
121
+ wasmFile: 'tree-sitter-python.wasm',
122
+ functionNodeTypes: ['function_definition'],
123
+ classNodeTypes: ['class_definition'],
124
+ importNodeTypes: ['import_statement', 'import_from_statement'],
125
+ complexityNodeTypes: [
126
+ 'if_statement',
127
+ 'elif_clause',
128
+ 'for_statement',
129
+ 'while_statement',
130
+ 'except_clause',
131
+ 'with_statement',
132
+ 'conditional_expression',
133
+ 'boolean_operator',
134
+ ],
135
+ nestingNodeTypes: [
136
+ 'if_statement',
137
+ 'for_statement',
138
+ 'while_statement',
139
+ 'with_statement',
140
+ 'try_statement',
141
+ 'function_definition',
142
+ 'class_definition',
143
+ ],
144
+ commentNodeTypes: ['comment'],
145
+ functionNameField: 'name',
146
+ functionParamsField: 'parameters',
147
+ functionBodyField: 'body',
148
+ classNameField: 'name',
149
+ classBodyField: 'body',
150
+ methodNodeTypes: ['function_definition'],
151
+ fieldNodeTypes: ['expression_statement'],
152
+ },
153
+ java: {
154
+ wasmFile: 'tree-sitter-java.wasm',
155
+ functionNodeTypes: ['method_declaration', 'constructor_declaration'],
156
+ classNodeTypes: ['class_declaration', 'interface_declaration', 'enum_declaration'],
157
+ importNodeTypes: ['import_declaration'],
158
+ complexityNodeTypes: [
159
+ 'if_statement',
160
+ 'for_statement',
161
+ 'enhanced_for_statement',
162
+ 'while_statement',
163
+ 'do_statement',
164
+ 'switch_expression',
165
+ 'catch_clause',
166
+ 'ternary_expression',
167
+ ],
168
+ nestingNodeTypes: [
169
+ 'if_statement',
170
+ 'for_statement',
171
+ 'enhanced_for_statement',
172
+ 'while_statement',
173
+ 'do_statement',
174
+ 'switch_expression',
175
+ 'try_statement',
176
+ 'lambda_expression',
177
+ ],
178
+ commentNodeTypes: ['line_comment', 'block_comment'],
179
+ functionNameField: 'name',
180
+ functionParamsField: 'parameters',
181
+ functionBodyField: 'body',
182
+ classNameField: 'name',
183
+ classBodyField: 'body',
184
+ methodNodeTypes: ['method_declaration', 'constructor_declaration'],
185
+ fieldNodeTypes: ['field_declaration'],
186
+ },
187
+ c: {
188
+ wasmFile: 'tree-sitter-c.wasm',
189
+ functionNodeTypes: ['function_definition'],
190
+ classNodeTypes: ['struct_specifier', 'enum_specifier', 'union_specifier'],
191
+ importNodeTypes: ['preproc_include'],
192
+ complexityNodeTypes: [
193
+ 'if_statement',
194
+ 'for_statement',
195
+ 'while_statement',
196
+ 'do_statement',
197
+ 'case_statement',
198
+ 'conditional_expression',
199
+ ],
200
+ nestingNodeTypes: [
201
+ 'if_statement',
202
+ 'for_statement',
203
+ 'while_statement',
204
+ 'do_statement',
205
+ 'switch_statement',
206
+ ],
207
+ commentNodeTypes: ['comment'],
208
+ functionNameField: 'declarator',
209
+ functionParamsField: 'declarator',
210
+ functionBodyField: 'body',
211
+ classNameField: 'name',
212
+ classBodyField: 'body',
213
+ methodNodeTypes: [],
214
+ fieldNodeTypes: ['field_declaration'],
215
+ },
216
+ cpp: {
217
+ wasmFile: 'tree-sitter-cpp.wasm',
218
+ functionNodeTypes: ['function_definition'],
219
+ classNodeTypes: ['class_specifier', 'struct_specifier', 'enum_specifier'],
220
+ importNodeTypes: ['preproc_include'],
221
+ complexityNodeTypes: [
222
+ 'if_statement',
223
+ 'for_statement',
224
+ 'for_range_loop',
225
+ 'while_statement',
226
+ 'do_statement',
227
+ 'case_statement',
228
+ 'catch_clause',
229
+ 'conditional_expression',
230
+ ],
231
+ nestingNodeTypes: [
232
+ 'if_statement',
233
+ 'for_statement',
234
+ 'for_range_loop',
235
+ 'while_statement',
236
+ 'do_statement',
237
+ 'switch_statement',
238
+ 'try_statement',
239
+ 'lambda_expression',
240
+ ],
241
+ commentNodeTypes: ['comment'],
242
+ functionNameField: 'declarator',
243
+ functionParamsField: 'declarator',
244
+ functionBodyField: 'body',
245
+ classNameField: 'name',
246
+ classBodyField: 'body',
247
+ methodNodeTypes: ['function_definition'],
248
+ fieldNodeTypes: ['field_declaration'],
249
+ },
250
+ rust: {
251
+ wasmFile: 'tree-sitter-rust.wasm',
252
+ functionNodeTypes: ['function_item'],
253
+ classNodeTypes: ['struct_item', 'enum_item', 'impl_item', 'trait_item'],
254
+ importNodeTypes: ['use_declaration'],
255
+ complexityNodeTypes: [
256
+ 'if_expression',
257
+ 'for_expression',
258
+ 'while_expression',
259
+ 'loop_expression',
260
+ 'match_arm',
261
+ 'closure_expression',
262
+ ],
263
+ nestingNodeTypes: [
264
+ 'if_expression',
265
+ 'for_expression',
266
+ 'while_expression',
267
+ 'loop_expression',
268
+ 'match_expression',
269
+ 'closure_expression',
270
+ ],
271
+ commentNodeTypes: ['line_comment', 'block_comment'],
272
+ functionNameField: 'name',
273
+ functionParamsField: 'parameters',
274
+ functionBodyField: 'body',
275
+ classNameField: 'name',
276
+ classBodyField: 'body',
277
+ methodNodeTypes: ['function_item'],
278
+ fieldNodeTypes: ['field_declaration'],
279
+ },
280
+ csharp: {
281
+ wasmFile: 'tree-sitter-c_sharp.wasm',
282
+ functionNodeTypes: [
283
+ 'method_declaration',
284
+ 'constructor_declaration',
285
+ 'local_function_statement',
286
+ ],
287
+ classNodeTypes: [
288
+ 'class_declaration',
289
+ 'interface_declaration',
290
+ 'struct_declaration',
291
+ 'enum_declaration',
292
+ ],
293
+ importNodeTypes: ['using_directive'],
294
+ complexityNodeTypes: [
295
+ 'if_statement',
296
+ 'for_statement',
297
+ 'for_each_statement',
298
+ 'while_statement',
299
+ 'do_statement',
300
+ 'switch_section',
301
+ 'catch_clause',
302
+ 'conditional_expression',
303
+ ],
304
+ nestingNodeTypes: [
305
+ 'if_statement',
306
+ 'for_statement',
307
+ 'for_each_statement',
308
+ 'while_statement',
309
+ 'do_statement',
310
+ 'switch_statement',
311
+ 'try_statement',
312
+ 'lambda_expression',
313
+ ],
314
+ commentNodeTypes: ['comment'],
315
+ functionNameField: 'name',
316
+ functionParamsField: 'parameters',
317
+ functionBodyField: 'body',
318
+ classNameField: 'name',
319
+ classBodyField: 'body',
320
+ methodNodeTypes: ['method_declaration', 'constructor_declaration'],
321
+ fieldNodeTypes: ['field_declaration', 'property_declaration'],
322
+ },
323
+ lua: {
324
+ wasmFile: 'tree-sitter-lua.wasm',
325
+ functionNodeTypes: ['function_definition_statement', 'local_function_definition_statement'],
326
+ classNodeTypes: [],
327
+ importNodeTypes: [],
328
+ complexityNodeTypes: [
329
+ 'if_statement',
330
+ 'elseif_clause',
331
+ 'for_statement',
332
+ 'for_in_statement',
333
+ 'while_statement',
334
+ 'repeat_statement',
335
+ ],
336
+ nestingNodeTypes: [
337
+ 'if_statement',
338
+ 'for_statement',
339
+ 'for_in_statement',
340
+ 'while_statement',
341
+ 'repeat_statement',
342
+ 'function_definition_statement',
343
+ ],
344
+ commentNodeTypes: ['comment'],
345
+ functionNameField: 'name',
346
+ functionParamsField: 'parameters',
347
+ functionBodyField: 'body',
348
+ classNameField: 'name',
349
+ classBodyField: 'body',
350
+ methodNodeTypes: [],
351
+ fieldNodeTypes: [],
352
+ },
353
+ };
354
+ /** Resolve WASM file path */
355
+ function resolveWasmPath(wasmFile) {
356
+ return resolve(__dirname, '..', '..', 'node_modules', 'tree-sitter-wasms', 'out', wasmFile);
357
+ }
358
+ let parserInitialized = false;
359
+ const languageCache = new Map();
360
+ async function ensureParserInit() {
361
+ if (parserInitialized)
362
+ return;
363
+ await Parser.init();
364
+ parserInitialized = true;
365
+ }
366
+ async function loadLanguage(wasmFile) {
367
+ const cached = languageCache.get(wasmFile);
368
+ if (cached)
369
+ return cached;
370
+ const wasmPath = resolveWasmPath(wasmFile);
371
+ const lang = await Parser.Language.load(wasmPath);
372
+ languageCache.set(wasmFile, lang);
373
+ return lang;
374
+ }
375
+ /**
376
+ * Get the LanguageQueryConfig for a given language, or null if unsupported
377
+ */
378
+ export function getLanguageConfig(language) {
379
+ return LANG_CONFIGS[language] ?? null;
380
+ }
381
+ /**
382
+ * Tree-sitter AST-based parser.
383
+ * Provides precise function/class extraction, complexity calculation,
384
+ * and nesting depth analysis via real AST traversal.
385
+ */
386
+ export class TreeSitterParser {
387
+ language;
388
+ config;
389
+ constructor(language, config) {
390
+ this.language = language;
391
+ this.config = config;
392
+ }
393
+ async parse(filePath, content) {
394
+ await ensureParserInit();
395
+ const tsLang = await loadLanguage(this.config.wasmFile);
396
+ const parser = new Parser();
397
+ parser.setLanguage(tsLang);
398
+ const tree = parser.parse(content);
399
+ const rootNode = tree.rootNode;
400
+ const functions = this.extractFunctions(rootNode);
401
+ const classes = this.extractClasses(rootNode);
402
+ const imports = this.extractImports(rootNode);
403
+ const { commentLines, blankLines, codeLines, totalLines } = this.countLines(rootNode, content);
404
+ parser.delete();
405
+ tree.delete();
406
+ return {
407
+ filePath,
408
+ language: this.language,
409
+ totalLines,
410
+ codeLines,
411
+ commentLines,
412
+ blankLines,
413
+ functions,
414
+ classes,
415
+ imports,
416
+ errors: [],
417
+ };
418
+ }
419
+ supportedLanguages() {
420
+ return Object.keys(LANG_CONFIGS);
421
+ }
422
+ countLines(rootNode, content) {
423
+ const lines = content.split('\n');
424
+ const totalLines = lines.length;
425
+ const commentLineSet = new Set();
426
+ this.collectNodesByTypes(rootNode, this.config.commentNodeTypes, (node) => {
427
+ for (let row = node.startPosition.row; row <= node.endPosition.row; row++) {
428
+ commentLineSet.add(row);
429
+ }
430
+ });
431
+ let blankLines = 0;
432
+ let commentLines = 0;
433
+ for (const [i, line] of lines.entries()) {
434
+ const trimmed = line.trim();
435
+ if (trimmed === '') {
436
+ blankLines++;
437
+ }
438
+ else if (commentLineSet.has(i)) {
439
+ commentLines++;
440
+ }
441
+ }
442
+ const codeLines = totalLines - commentLines - blankLines;
443
+ return { commentLines, blankLines, codeLines, totalLines };
444
+ }
445
+ extractImports(rootNode) {
446
+ const imports = [];
447
+ this.collectNodesByTypes(rootNode, this.config.importNodeTypes, (node) => {
448
+ const stringNode = node.descendantsOfType('interpreted_string_literal')[0] ??
449
+ node.descendantsOfType('string')[0] ??
450
+ node.descendantsOfType('string_literal')[0] ??
451
+ node.descendantsOfType('dotted_name')[0] ??
452
+ node.descendantsOfType('scoped_identifier')[0] ??
453
+ node.descendantsOfType('qualified_name')[0] ??
454
+ node.descendantsOfType('identifier')[0] ??
455
+ node.childForFieldName('path') ??
456
+ node.childForFieldName('source') ??
457
+ node.childForFieldName('name');
458
+ if (stringNode) {
459
+ const text = stringNode.text.replace(/^["'`]|["'`]$/g, '');
460
+ if (text)
461
+ imports.push(text);
462
+ }
463
+ });
464
+ return imports;
465
+ }
466
+ extractFunctions(rootNode) {
467
+ const functions = [];
468
+ this.collectNodesByTypes(rootNode, this.config.functionNodeTypes, (node) => {
469
+ const name = this.extractFunctionName(node);
470
+ if (!name)
471
+ return;
472
+ const startLine = node.startPosition.row + 1;
473
+ const endLine = node.endPosition.row + 1;
474
+ const lineCount = endLine - startLine + 1;
475
+ const parameterCount = this.countParameters(node);
476
+ const bodyNode = node.childForFieldName(this.config.functionBodyField);
477
+ const complexity = bodyNode ? this.calculateComplexity(bodyNode) + 1 : 1;
478
+ const nestingDepth = bodyNode ? this.calculateMaxNesting(bodyNode, 0) : 0;
479
+ const hasDocstring = this.hasDocstring(node);
480
+ functions.push({
481
+ name,
482
+ startLine,
483
+ endLine,
484
+ lineCount,
485
+ complexity,
486
+ parameterCount,
487
+ nestingDepth,
488
+ hasDocstring,
489
+ });
490
+ });
491
+ return functions;
492
+ }
493
+ extractFunctionName(node) {
494
+ const nameNode = node.childForFieldName(this.config.functionNameField);
495
+ if (nameNode) {
496
+ // C/C++: name field points to function_declarator wrapping the identifier
497
+ if (nameNode.type === 'function_declarator' || nameNode.type === 'pointer_declarator') {
498
+ const inner = nameNode.childForFieldName('declarator') ?? nameNode.namedChildren[0];
499
+ if (inner) {
500
+ if (inner.type === 'qualified_identifier') {
501
+ return inner.childForFieldName('name')?.text ?? inner.text;
502
+ }
503
+ return inner.text;
504
+ }
505
+ }
506
+ return nameNode.text || null;
507
+ }
508
+ // Arrow functions / anonymous functions assigned to variables:
509
+ // parent is variable_declarator with a name field
510
+ const parent = node.parent;
511
+ if (parent?.type === 'variable_declarator') {
512
+ return parent.childForFieldName('name')?.text ?? null;
513
+ }
514
+ return null;
515
+ }
516
+ extractClasses(rootNode) {
517
+ const classes = [];
518
+ this.collectNodesByTypes(rootNode, this.config.classNodeTypes, (node) => {
519
+ let name = null;
520
+ let bodyNode = null;
521
+ // Go: type_declaration wraps type_spec
522
+ if (this.language === 'go' && node.type === 'type_declaration') {
523
+ const typeSpec = node.namedChildren.find((c) => c.type === 'type_spec');
524
+ if (typeSpec) {
525
+ name = typeSpec.childForFieldName('name')?.text ?? null;
526
+ bodyNode = typeSpec.childForFieldName('type');
527
+ }
528
+ }
529
+ else {
530
+ name = node.childForFieldName(this.config.classNameField)?.text ?? null;
531
+ bodyNode = node.childForFieldName(this.config.classBodyField);
532
+ }
533
+ if (!name)
534
+ return;
535
+ const startLine = node.startPosition.row + 1;
536
+ const endLine = node.endPosition.row + 1;
537
+ let methodCount = 0;
538
+ let fieldCount = 0;
539
+ if (bodyNode) {
540
+ // Scan body for methods and fields, recursing into wrapper nodes
541
+ // (e.g., Go's field_declaration_list, Rust's declaration_list)
542
+ const scan = (n) => {
543
+ for (const child of n.namedChildren) {
544
+ if (this.config.methodNodeTypes.includes(child.type)) {
545
+ methodCount++;
546
+ }
547
+ else if (this.config.fieldNodeTypes.includes(child.type)) {
548
+ fieldCount++;
549
+ }
550
+ else if (child.type.includes('_list') ||
551
+ child.type.includes('_body') ||
552
+ child.type === 'declaration_list') {
553
+ scan(child);
554
+ }
555
+ }
556
+ };
557
+ scan(bodyNode);
558
+ }
559
+ classes.push({ name, startLine, endLine, methodCount, fieldCount });
560
+ });
561
+ return classes;
562
+ }
563
+ countParameters(funcNode) {
564
+ let paramsNode = null;
565
+ if (this.config.functionParamsField === 'declarator') {
566
+ // C/C++: parameters inside function_declarator
567
+ const declarator = funcNode.childForFieldName('declarator');
568
+ if (declarator) {
569
+ paramsNode =
570
+ declarator.childForFieldName('parameters') ??
571
+ declarator.descendantsOfType('parameter_list')[0] ??
572
+ null;
573
+ }
574
+ }
575
+ else {
576
+ paramsNode = funcNode.childForFieldName(this.config.functionParamsField);
577
+ }
578
+ if (!paramsNode)
579
+ return 0;
580
+ // Go: parameter_declaration can group multiple params (e.g., a, b int)
581
+ // Count identifier children inside each declaration instead of counting declarations
582
+ if (this.language === 'go') {
583
+ let count = 0;
584
+ for (const child of paramsNode.namedChildren) {
585
+ if (child.type === 'parameter_declaration' ||
586
+ child.type === 'variadic_parameter_declaration') {
587
+ for (const inner of child.namedChildren) {
588
+ if (inner.type === 'identifier')
589
+ count++;
590
+ }
591
+ }
592
+ }
593
+ return count;
594
+ }
595
+ const paramTypes = new Set([
596
+ 'parameter_declaration',
597
+ 'parameter',
598
+ 'formal_parameter',
599
+ 'required_parameter',
600
+ 'optional_parameter',
601
+ 'rest_parameter',
602
+ 'typed_parameter',
603
+ 'typed_default_parameter',
604
+ 'default_parameter',
605
+ 'identifier',
606
+ 'variadic_parameter_declaration',
607
+ 'variadic_parameter',
608
+ 'spread_parameter',
609
+ ]);
610
+ let count = 0;
611
+ for (const child of paramsNode.namedChildren) {
612
+ if (paramTypes.has(child.type))
613
+ count++;
614
+ }
615
+ return count;
616
+ }
617
+ hasDocstring(funcNode) {
618
+ const prev = funcNode.previousNamedSibling;
619
+ if (prev && this.config.commentNodeTypes.includes(prev.type)) {
620
+ const text = prev.text;
621
+ if (text.startsWith('/**') ||
622
+ text.startsWith('///') ||
623
+ text.startsWith('"""') ||
624
+ text.startsWith("'''") ||
625
+ text.startsWith('--[')) {
626
+ return true;
627
+ }
628
+ // Single-line comment directly above
629
+ if (prev.endPosition.row === funcNode.startPosition.row - 1) {
630
+ return true;
631
+ }
632
+ }
633
+ // Python docstring: string expression as first statement in body
634
+ if (this.language === 'python') {
635
+ const body = funcNode.childForFieldName('body');
636
+ const firstStmt = body?.namedChildren[0];
637
+ if (firstStmt?.type === 'expression_statement') {
638
+ const expr = firstStmt.namedChildren[0];
639
+ if (expr?.type === 'string')
640
+ return true;
641
+ }
642
+ }
643
+ return false;
644
+ }
645
+ calculateComplexity(node) {
646
+ let complexity = 0;
647
+ const complexitySet = new Set(this.config.complexityNodeTypes);
648
+ const walk = (n) => {
649
+ if (complexitySet.has(n.type)) {
650
+ // For binary/boolean operators, only count logical operators
651
+ if (n.type === 'binary_expression' || n.type === 'boolean_operator') {
652
+ const op = n.childForFieldName('operator')?.text ?? '';
653
+ if (op === '&&' || op === '||' || op === 'and' || op === 'or') {
654
+ complexity++;
655
+ }
656
+ }
657
+ else {
658
+ complexity++;
659
+ }
660
+ }
661
+ for (const child of n.namedChildren) {
662
+ // Don't recurse into nested function definitions
663
+ if (!this.config.functionNodeTypes.includes(child.type)) {
664
+ walk(child);
665
+ }
666
+ }
667
+ };
668
+ walk(node);
669
+ return complexity;
670
+ }
671
+ calculateMaxNesting(node, currentDepth) {
672
+ let maxDepth = currentDepth;
673
+ const nestingSet = new Set(this.config.nestingNodeTypes);
674
+ for (const child of node.namedChildren) {
675
+ if (this.config.functionNodeTypes.includes(child.type))
676
+ continue;
677
+ if (nestingSet.has(child.type)) {
678
+ maxDepth = Math.max(maxDepth, this.calculateMaxNesting(child, currentDepth + 1));
679
+ }
680
+ else {
681
+ maxDepth = Math.max(maxDepth, this.calculateMaxNesting(child, currentDepth));
682
+ }
683
+ }
684
+ return maxDepth;
685
+ }
686
+ collectNodesByTypes(rootNode, nodeTypes, callback) {
687
+ if (nodeTypes.length === 0)
688
+ return;
689
+ const typeSet = new Set(nodeTypes);
690
+ const walk = (node) => {
691
+ if (typeSet.has(node.type)) {
692
+ callback(node);
693
+ // For comments, continue recursing; for functions/classes, don't
694
+ if (this.config.commentNodeTypes.includes(node.type) ||
695
+ this.config.importNodeTypes.includes(node.type)) {
696
+ for (const child of node.namedChildren)
697
+ walk(child);
698
+ }
699
+ return;
700
+ }
701
+ for (const child of node.namedChildren)
702
+ walk(child);
703
+ };
704
+ walk(rootNode);
705
+ }
706
+ }
707
+ //# sourceMappingURL=tree-sitter-parser.js.map