claude-crap 0.1.2

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 (202) hide show
  1. package/CHANGELOG.md +308 -0
  2. package/LICENSE +21 -0
  3. package/README.md +550 -0
  4. package/bin/claude-crap.mjs +141 -0
  5. package/dist/adapters/bandit.d.ts +48 -0
  6. package/dist/adapters/bandit.d.ts.map +1 -0
  7. package/dist/adapters/bandit.js +145 -0
  8. package/dist/adapters/bandit.js.map +1 -0
  9. package/dist/adapters/common.d.ts +73 -0
  10. package/dist/adapters/common.d.ts.map +1 -0
  11. package/dist/adapters/common.js +78 -0
  12. package/dist/adapters/common.js.map +1 -0
  13. package/dist/adapters/eslint.d.ts +52 -0
  14. package/dist/adapters/eslint.d.ts.map +1 -0
  15. package/dist/adapters/eslint.js +142 -0
  16. package/dist/adapters/eslint.js.map +1 -0
  17. package/dist/adapters/index.d.ts +47 -0
  18. package/dist/adapters/index.d.ts.map +1 -0
  19. package/dist/adapters/index.js +64 -0
  20. package/dist/adapters/index.js.map +1 -0
  21. package/dist/adapters/semgrep.d.ts +30 -0
  22. package/dist/adapters/semgrep.d.ts.map +1 -0
  23. package/dist/adapters/semgrep.js +130 -0
  24. package/dist/adapters/semgrep.js.map +1 -0
  25. package/dist/adapters/stryker.d.ts +55 -0
  26. package/dist/adapters/stryker.d.ts.map +1 -0
  27. package/dist/adapters/stryker.js +165 -0
  28. package/dist/adapters/stryker.js.map +1 -0
  29. package/dist/ast/cyclomatic.d.ts +48 -0
  30. package/dist/ast/cyclomatic.d.ts.map +1 -0
  31. package/dist/ast/cyclomatic.js +106 -0
  32. package/dist/ast/cyclomatic.js.map +1 -0
  33. package/dist/ast/index.d.ts +26 -0
  34. package/dist/ast/index.d.ts.map +1 -0
  35. package/dist/ast/index.js +23 -0
  36. package/dist/ast/index.js.map +1 -0
  37. package/dist/ast/language-config.d.ts +70 -0
  38. package/dist/ast/language-config.d.ts.map +1 -0
  39. package/dist/ast/language-config.js +192 -0
  40. package/dist/ast/language-config.js.map +1 -0
  41. package/dist/ast/tree-sitter-engine.d.ts +133 -0
  42. package/dist/ast/tree-sitter-engine.d.ts.map +1 -0
  43. package/dist/ast/tree-sitter-engine.js +270 -0
  44. package/dist/ast/tree-sitter-engine.js.map +1 -0
  45. package/dist/config.d.ts +57 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +78 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/crap-config.d.ts +97 -0
  50. package/dist/crap-config.d.ts.map +1 -0
  51. package/dist/crap-config.js +144 -0
  52. package/dist/crap-config.js.map +1 -0
  53. package/dist/dashboard/server.d.ts +65 -0
  54. package/dist/dashboard/server.d.ts.map +1 -0
  55. package/dist/dashboard/server.js +147 -0
  56. package/dist/dashboard/server.js.map +1 -0
  57. package/dist/index.d.ts +32 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +574 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/metrics/crap.d.ts +71 -0
  62. package/dist/metrics/crap.d.ts.map +1 -0
  63. package/dist/metrics/crap.js +67 -0
  64. package/dist/metrics/crap.js.map +1 -0
  65. package/dist/metrics/index.d.ts +31 -0
  66. package/dist/metrics/index.d.ts.map +1 -0
  67. package/dist/metrics/index.js +27 -0
  68. package/dist/metrics/index.js.map +1 -0
  69. package/dist/metrics/score.d.ts +143 -0
  70. package/dist/metrics/score.d.ts.map +1 -0
  71. package/dist/metrics/score.js +224 -0
  72. package/dist/metrics/score.js.map +1 -0
  73. package/dist/metrics/tdr.d.ts +106 -0
  74. package/dist/metrics/tdr.d.ts.map +1 -0
  75. package/dist/metrics/tdr.js +117 -0
  76. package/dist/metrics/tdr.js.map +1 -0
  77. package/dist/metrics/workspace-walker.d.ts +43 -0
  78. package/dist/metrics/workspace-walker.d.ts.map +1 -0
  79. package/dist/metrics/workspace-walker.js +137 -0
  80. package/dist/metrics/workspace-walker.js.map +1 -0
  81. package/dist/sarif/index.d.ts +21 -0
  82. package/dist/sarif/index.d.ts.map +1 -0
  83. package/dist/sarif/index.js +19 -0
  84. package/dist/sarif/index.js.map +1 -0
  85. package/dist/sarif/sarif-builder.d.ts +128 -0
  86. package/dist/sarif/sarif-builder.d.ts.map +1 -0
  87. package/dist/sarif/sarif-builder.js +79 -0
  88. package/dist/sarif/sarif-builder.js.map +1 -0
  89. package/dist/sarif/sarif-store.d.ts +205 -0
  90. package/dist/sarif/sarif-store.d.ts.map +1 -0
  91. package/dist/sarif/sarif-store.js +246 -0
  92. package/dist/sarif/sarif-store.js.map +1 -0
  93. package/dist/sarif/sarif-validator.d.ts +45 -0
  94. package/dist/sarif/sarif-validator.d.ts.map +1 -0
  95. package/dist/sarif/sarif-validator.js +138 -0
  96. package/dist/sarif/sarif-validator.js.map +1 -0
  97. package/dist/schemas/tool-schemas.d.ts +216 -0
  98. package/dist/schemas/tool-schemas.d.ts.map +1 -0
  99. package/dist/schemas/tool-schemas.js +208 -0
  100. package/dist/schemas/tool-schemas.js.map +1 -0
  101. package/dist/sdk.d.ts +45 -0
  102. package/dist/sdk.d.ts.map +1 -0
  103. package/dist/sdk.js +44 -0
  104. package/dist/sdk.js.map +1 -0
  105. package/dist/tools/index.d.ts +24 -0
  106. package/dist/tools/index.d.ts.map +1 -0
  107. package/dist/tools/index.js +23 -0
  108. package/dist/tools/index.js.map +1 -0
  109. package/dist/tools/test-harness.d.ts +75 -0
  110. package/dist/tools/test-harness.d.ts.map +1 -0
  111. package/dist/tools/test-harness.js +137 -0
  112. package/dist/tools/test-harness.js.map +1 -0
  113. package/dist/workspace-guard.d.ts +53 -0
  114. package/dist/workspace-guard.d.ts.map +1 -0
  115. package/dist/workspace-guard.js +61 -0
  116. package/dist/workspace-guard.js.map +1 -0
  117. package/package.json +133 -0
  118. package/plugin/.claude-plugin/plugin.json +29 -0
  119. package/plugin/.mcp.json +18 -0
  120. package/plugin/CLAUDE.md +143 -0
  121. package/plugin/bundle/dashboard/public/index.html +368 -0
  122. package/plugin/bundle/dashboard/public/vendor/vue.global.prod.js +9 -0
  123. package/plugin/bundle/mcp-server.mjs +8718 -0
  124. package/plugin/bundle/mcp-server.mjs.map +7 -0
  125. package/plugin/bundle/tdr-engine.mjs +50 -0
  126. package/plugin/bundle/tdr-engine.mjs.map +7 -0
  127. package/plugin/hooks/hooks.json +62 -0
  128. package/plugin/hooks/lib/crap-config.mjs +152 -0
  129. package/plugin/hooks/lib/gatekeeper-rules.mjs +257 -0
  130. package/plugin/hooks/lib/hook-io.mjs +151 -0
  131. package/plugin/hooks/lib/quality-gate.mjs +329 -0
  132. package/plugin/hooks/lib/test-harness.mjs +152 -0
  133. package/plugin/hooks/post-tool-use.mjs +245 -0
  134. package/plugin/hooks/pre-tool-use.mjs +290 -0
  135. package/plugin/hooks/session-start.mjs +109 -0
  136. package/plugin/hooks/stop-quality-gate.mjs +226 -0
  137. package/plugin/package.json +18 -0
  138. package/plugin/skills/adopt/SKILL.md +74 -0
  139. package/plugin/skills/analyze/SKILL.md +77 -0
  140. package/plugin/skills/check-test/SKILL.md +50 -0
  141. package/plugin/skills/score/SKILL.md +31 -0
  142. package/scripts/bug-report.mjs +328 -0
  143. package/scripts/build-fast.mjs +130 -0
  144. package/scripts/bundle-plugin.mjs +74 -0
  145. package/scripts/doctor.mjs +320 -0
  146. package/scripts/install.mjs +192 -0
  147. package/scripts/lib/cli-ui.mjs +122 -0
  148. package/scripts/postinstall.mjs +127 -0
  149. package/scripts/run-tests.mjs +95 -0
  150. package/scripts/status.mjs +110 -0
  151. package/scripts/uninstall.mjs +72 -0
  152. package/src/adapters/bandit.ts +191 -0
  153. package/src/adapters/common.ts +133 -0
  154. package/src/adapters/eslint.ts +187 -0
  155. package/src/adapters/index.ts +78 -0
  156. package/src/adapters/semgrep.ts +150 -0
  157. package/src/adapters/stryker.ts +218 -0
  158. package/src/ast/cyclomatic.ts +131 -0
  159. package/src/ast/index.ts +33 -0
  160. package/src/ast/language-config.ts +231 -0
  161. package/src/ast/tree-sitter-engine.ts +385 -0
  162. package/src/config.ts +109 -0
  163. package/src/crap-config.ts +196 -0
  164. package/src/dashboard/public/index.html +368 -0
  165. package/src/dashboard/public/vendor/vue.global.prod.js +9 -0
  166. package/src/dashboard/server.ts +205 -0
  167. package/src/index.ts +696 -0
  168. package/src/metrics/crap.ts +101 -0
  169. package/src/metrics/index.ts +51 -0
  170. package/src/metrics/score.ts +329 -0
  171. package/src/metrics/tdr.ts +155 -0
  172. package/src/metrics/workspace-walker.ts +146 -0
  173. package/src/sarif/index.ts +31 -0
  174. package/src/sarif/sarif-builder.ts +139 -0
  175. package/src/sarif/sarif-store.ts +347 -0
  176. package/src/sarif/sarif-validator.ts +145 -0
  177. package/src/schemas/tool-schemas.ts +225 -0
  178. package/src/sdk.ts +110 -0
  179. package/src/tests/adapters/bandit.test.ts +111 -0
  180. package/src/tests/adapters/dispatch.test.ts +100 -0
  181. package/src/tests/adapters/eslint.test.ts +138 -0
  182. package/src/tests/adapters/semgrep.test.ts +125 -0
  183. package/src/tests/adapters/stryker.test.ts +103 -0
  184. package/src/tests/crap-config.test.ts +228 -0
  185. package/src/tests/crap.test.ts +59 -0
  186. package/src/tests/cyclomatic.test.ts +87 -0
  187. package/src/tests/dashboard-http.test.ts +108 -0
  188. package/src/tests/dashboard-integrity.test.ts +128 -0
  189. package/src/tests/integration/mcp-server.integration.test.ts +352 -0
  190. package/src/tests/pre-tool-use-hook.test.ts +178 -0
  191. package/src/tests/sarif-store.test.ts +241 -0
  192. package/src/tests/sarif-validator.test.ts +164 -0
  193. package/src/tests/score.test.ts +260 -0
  194. package/src/tests/skills-frontmatter.test.ts +172 -0
  195. package/src/tests/stop-quality-gate-strictness.test.ts +243 -0
  196. package/src/tests/tdr.test.ts +86 -0
  197. package/src/tests/test-harness.test.ts +153 -0
  198. package/src/tests/workspace-guard.test.ts +111 -0
  199. package/src/tools/index.ts +24 -0
  200. package/src/tools/test-harness.ts +158 -0
  201. package/src/workspace-guard.ts +64 -0
  202. package/tsconfig.json +27 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ast/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC9D,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Public SDK entry point for the tree-sitter based AST engine and the
3
+ * cyclomatic complexity walker.
4
+ *
5
+ * Usage:
6
+ *
7
+ * ```ts
8
+ * import {
9
+ * TreeSitterEngine,
10
+ * computeCyclomaticComplexity,
11
+ * detectLanguageFromPath,
12
+ * type FileMetrics,
13
+ * type FunctionMetrics,
14
+ * type SupportedLanguage,
15
+ * } from "claude-crap/ast";
16
+ * ```
17
+ *
18
+ * @module ast
19
+ */
20
+ export { TreeSitterEngine } from "./tree-sitter-engine.js";
21
+ export { computeCyclomaticComplexity } from "./cyclomatic.js";
22
+ export { LANGUAGE_TABLE, detectLanguageFromPath } from "./language-config.js";
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ast/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAQ3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Per-language tree-sitter node classification tables.
3
+ *
4
+ * Every language grammar exposes a different set of node type names. To
5
+ * keep the AST engine language-agnostic we encode, for each supported
6
+ * language, three sets:
7
+ *
8
+ * - `functionNodeTypes` — nodes that represent a function/method/lambda.
9
+ * These are the units we report metrics for.
10
+ * - `branchingNodeTypes` — nodes that add one independent path through
11
+ * the function. Used to compute cyclomatic
12
+ * complexity by counting occurrences.
13
+ * - `nameField` — the tree-sitter field name that holds the
14
+ * function's identifier, used to extract the
15
+ * function name for reporting.
16
+ *
17
+ * We also define which WASM grammar file to load per language. The paths
18
+ * are resolved at runtime against the `tree-sitter-wasms` package, but
19
+ * can be overridden via the engine constructor if you want to ship your
20
+ * own grammars.
21
+ *
22
+ * @module ast/language-config
23
+ */
24
+ /**
25
+ * Languages currently supported by the AST engine. This is the same
26
+ * `enum` that appears in the `analyze_file_ast` tool schema — keep them
27
+ * in sync when adding a new language.
28
+ */
29
+ export type SupportedLanguage = "csharp" | "javascript" | "typescript" | "python" | "java";
30
+ /**
31
+ * Per-language classification record. Immutable by convention.
32
+ */
33
+ export interface LanguageConfig {
34
+ /** Canonical language identifier (stable across releases). */
35
+ readonly id: SupportedLanguage;
36
+ /** WASM grammar filename inside `tree-sitter-wasms/out/`. */
37
+ readonly wasmName: string;
38
+ /** File extensions that should map to this language. */
39
+ readonly extensions: ReadonlyArray<string>;
40
+ /** Tree-sitter node types that represent callable units. */
41
+ readonly functionNodeTypes: ReadonlySet<string>;
42
+ /** Tree-sitter node types that add +1 to cyclomatic complexity. */
43
+ readonly branchingNodeTypes: ReadonlySet<string>;
44
+ /**
45
+ * Boolean / short-circuit operator node types. These are counted only
46
+ * when the node is an `"&&"`, `"||"`, `"??"` (etc.) operator, so the
47
+ * walker inspects the operator text on top of the node type.
48
+ */
49
+ readonly booleanOperators: ReadonlyArray<string>;
50
+ /**
51
+ * Child-field names we try in order to extract the function name. The
52
+ * walker reads the first non-empty match.
53
+ */
54
+ readonly nameFieldCandidates: ReadonlyArray<string>;
55
+ }
56
+ /**
57
+ * Complete language table. Look up by {@link SupportedLanguage} identifier.
58
+ */
59
+ export declare const LANGUAGE_TABLE: Readonly<Record<SupportedLanguage, LanguageConfig>>;
60
+ /**
61
+ * Infer a {@link SupportedLanguage} from a file path by matching its
62
+ * extension. Returns `null` when no known language matches. Useful when
63
+ * the caller does not already know the language and wants the engine to
64
+ * pick one automatically.
65
+ *
66
+ * @param filePath File path (absolute or relative).
67
+ * @returns The detected language or `null`.
68
+ */
69
+ export declare function detectLanguageFromPath(filePath: string): SupportedLanguage | null;
70
+ //# sourceMappingURL=language-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language-config.d.ts","sourceRoot":"","sources":["../../src/ast/language-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE3F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,4DAA4D;IAC5D,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,mEAAmE;IACnE,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACrD;AAkJD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAM9E,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAQjF"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Per-language tree-sitter node classification tables.
3
+ *
4
+ * Every language grammar exposes a different set of node type names. To
5
+ * keep the AST engine language-agnostic we encode, for each supported
6
+ * language, three sets:
7
+ *
8
+ * - `functionNodeTypes` — nodes that represent a function/method/lambda.
9
+ * These are the units we report metrics for.
10
+ * - `branchingNodeTypes` — nodes that add one independent path through
11
+ * the function. Used to compute cyclomatic
12
+ * complexity by counting occurrences.
13
+ * - `nameField` — the tree-sitter field name that holds the
14
+ * function's identifier, used to extract the
15
+ * function name for reporting.
16
+ *
17
+ * We also define which WASM grammar file to load per language. The paths
18
+ * are resolved at runtime against the `tree-sitter-wasms` package, but
19
+ * can be overridden via the engine constructor if you want to ship your
20
+ * own grammars.
21
+ *
22
+ * @module ast/language-config
23
+ */
24
+ // -----------------------------------------------------------------------------
25
+ // C#
26
+ // -----------------------------------------------------------------------------
27
+ // Grammar: https://github.com/tree-sitter/tree-sitter-c-sharp
28
+ const CSHARP = {
29
+ id: "csharp",
30
+ wasmName: "tree-sitter-c_sharp.wasm",
31
+ extensions: [".cs"],
32
+ functionNodeTypes: new Set([
33
+ "method_declaration",
34
+ "local_function_statement",
35
+ "lambda_expression",
36
+ "anonymous_method_expression",
37
+ "constructor_declaration",
38
+ "destructor_declaration",
39
+ "operator_declaration",
40
+ "conversion_operator_declaration",
41
+ "accessor_declaration",
42
+ ]),
43
+ branchingNodeTypes: new Set([
44
+ "if_statement",
45
+ "else_clause",
46
+ "while_statement",
47
+ "do_statement",
48
+ "for_statement",
49
+ "for_each_statement",
50
+ "case_switch_label",
51
+ "case_pattern_switch_label",
52
+ "switch_expression_arm",
53
+ "catch_clause",
54
+ "conditional_expression",
55
+ "conditional_access_expression",
56
+ "when_clause",
57
+ ]),
58
+ booleanOperators: ["&&", "||", "??"],
59
+ nameFieldCandidates: ["name"],
60
+ };
61
+ // -----------------------------------------------------------------------------
62
+ // JavaScript
63
+ // -----------------------------------------------------------------------------
64
+ // Grammar: https://github.com/tree-sitter/tree-sitter-javascript
65
+ const JAVASCRIPT = {
66
+ id: "javascript",
67
+ wasmName: "tree-sitter-javascript.wasm",
68
+ extensions: [".js", ".jsx", ".mjs", ".cjs"],
69
+ functionNodeTypes: new Set([
70
+ "function_declaration",
71
+ "function_expression",
72
+ "arrow_function",
73
+ "method_definition",
74
+ "generator_function",
75
+ "generator_function_declaration",
76
+ ]),
77
+ branchingNodeTypes: new Set([
78
+ "if_statement",
79
+ "else_clause",
80
+ "while_statement",
81
+ "do_statement",
82
+ "for_statement",
83
+ "for_in_statement",
84
+ "for_of_statement",
85
+ "switch_case",
86
+ "catch_clause",
87
+ "ternary_expression",
88
+ ]),
89
+ booleanOperators: ["&&", "||", "??"],
90
+ nameFieldCandidates: ["name"],
91
+ };
92
+ // -----------------------------------------------------------------------------
93
+ // TypeScript
94
+ // -----------------------------------------------------------------------------
95
+ // Grammar: https://github.com/tree-sitter/tree-sitter-typescript
96
+ // The TypeScript grammar inherits most node types from JavaScript, so we
97
+ // extend the JS tables rather than re-declaring them from scratch.
98
+ const TYPESCRIPT = {
99
+ id: "typescript",
100
+ wasmName: "tree-sitter-typescript.wasm",
101
+ extensions: [".ts", ".tsx", ".mts", ".cts"],
102
+ functionNodeTypes: new Set([
103
+ ...JAVASCRIPT.functionNodeTypes,
104
+ "function_signature",
105
+ "method_signature",
106
+ "abstract_method_signature",
107
+ ]),
108
+ branchingNodeTypes: new Set([...JAVASCRIPT.branchingNodeTypes]),
109
+ booleanOperators: [...JAVASCRIPT.booleanOperators],
110
+ nameFieldCandidates: ["name"],
111
+ };
112
+ // -----------------------------------------------------------------------------
113
+ // Python
114
+ // -----------------------------------------------------------------------------
115
+ // Grammar: https://github.com/tree-sitter/tree-sitter-python
116
+ const PYTHON = {
117
+ id: "python",
118
+ wasmName: "tree-sitter-python.wasm",
119
+ extensions: [".py", ".pyi"],
120
+ functionNodeTypes: new Set(["function_definition", "lambda"]),
121
+ branchingNodeTypes: new Set([
122
+ "if_statement",
123
+ "elif_clause",
124
+ "else_clause",
125
+ "while_statement",
126
+ "for_statement",
127
+ "try_statement",
128
+ "except_clause",
129
+ "conditional_expression",
130
+ "match_statement",
131
+ "case_clause",
132
+ ]),
133
+ booleanOperators: ["and", "or"],
134
+ nameFieldCandidates: ["name"],
135
+ };
136
+ // -----------------------------------------------------------------------------
137
+ // Java
138
+ // -----------------------------------------------------------------------------
139
+ // Grammar: https://github.com/tree-sitter/tree-sitter-java
140
+ const JAVA = {
141
+ id: "java",
142
+ wasmName: "tree-sitter-java.wasm",
143
+ extensions: [".java"],
144
+ functionNodeTypes: new Set([
145
+ "method_declaration",
146
+ "constructor_declaration",
147
+ "lambda_expression",
148
+ ]),
149
+ branchingNodeTypes: new Set([
150
+ "if_statement",
151
+ "while_statement",
152
+ "do_statement",
153
+ "for_statement",
154
+ "enhanced_for_statement",
155
+ "switch_label",
156
+ "switch_rule",
157
+ "catch_clause",
158
+ "ternary_expression",
159
+ ]),
160
+ booleanOperators: ["&&", "||"],
161
+ nameFieldCandidates: ["name"],
162
+ };
163
+ /**
164
+ * Complete language table. Look up by {@link SupportedLanguage} identifier.
165
+ */
166
+ export const LANGUAGE_TABLE = {
167
+ csharp: CSHARP,
168
+ javascript: JAVASCRIPT,
169
+ typescript: TYPESCRIPT,
170
+ python: PYTHON,
171
+ java: JAVA,
172
+ };
173
+ /**
174
+ * Infer a {@link SupportedLanguage} from a file path by matching its
175
+ * extension. Returns `null` when no known language matches. Useful when
176
+ * the caller does not already know the language and wants the engine to
177
+ * pick one automatically.
178
+ *
179
+ * @param filePath File path (absolute or relative).
180
+ * @returns The detected language or `null`.
181
+ */
182
+ export function detectLanguageFromPath(filePath) {
183
+ const lower = filePath.toLowerCase();
184
+ for (const config of Object.values(LANGUAGE_TABLE)) {
185
+ for (const ext of config.extensions) {
186
+ if (lower.endsWith(ext))
187
+ return config.id;
188
+ }
189
+ }
190
+ return null;
191
+ }
192
+ //# sourceMappingURL=language-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language-config.js","sourceRoot":"","sources":["../../src/ast/language-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Tree-sitter based AST analysis engine.
3
+ *
4
+ * This module wraps `web-tree-sitter` (the WASM build of tree-sitter) to
5
+ * parse source files and extract deterministic per-function metrics. The
6
+ * WASM variant is used instead of the native bindings so that `npm install`
7
+ * never has to invoke a C compiler — matching the plugin's "zero install
8
+ * friction" promise.
9
+ *
10
+ * The engine is lazy:
11
+ *
12
+ * - `web-tree-sitter` is initialized only on first use.
13
+ * - Grammar WASM files are loaded on demand and cached per language.
14
+ *
15
+ * This keeps MCP server startup fast (crucial because Claude Code will
16
+ * spin the server up and tear it down across sessions).
17
+ *
18
+ * Usage:
19
+ *
20
+ * ```ts
21
+ * const engine = new TreeSitterEngine();
22
+ * const result = await engine.analyzeFile({
23
+ * filePath: "src/foo.ts",
24
+ * language: "typescript",
25
+ * });
26
+ * console.log(result.functions);
27
+ * ```
28
+ *
29
+ * @module ast/tree-sitter-engine
30
+ */
31
+ import { type SupportedLanguage } from "./language-config.js";
32
+ /**
33
+ * Per-function metrics returned by the engine.
34
+ */
35
+ export interface FunctionMetrics {
36
+ /** Human-readable function name, or `"<anonymous>"` when not available. */
37
+ readonly name: string;
38
+ /** 1-based line where the function body starts. */
39
+ readonly startLine: number;
40
+ /** 1-based line where the function body ends. */
41
+ readonly endLine: number;
42
+ /** McCabe cyclomatic complexity (always ≥ 1). */
43
+ readonly cyclomaticComplexity: number;
44
+ /** Physical lines of code covered by the function (endLine - startLine + 1). */
45
+ readonly lineCount: number;
46
+ }
47
+ /**
48
+ * File-level metrics returned by the engine.
49
+ */
50
+ export interface FileMetrics {
51
+ /** File path that was analyzed, echoed from the request for traceability. */
52
+ readonly filePath: string;
53
+ /** Language the file was parsed as. */
54
+ readonly language: SupportedLanguage;
55
+ /** Total physical lines in the file, including blanks and comments. */
56
+ readonly physicalLoc: number;
57
+ /** Physical lines that contain at least one non-whitespace character. */
58
+ readonly logicalLoc: number;
59
+ /** Per-function metrics sorted by starting line. */
60
+ readonly functions: ReadonlyArray<FunctionMetrics>;
61
+ }
62
+ /**
63
+ * Request accepted by {@link TreeSitterEngine.analyzeFile}.
64
+ */
65
+ export interface AnalyzeFileRequest {
66
+ readonly filePath: string;
67
+ readonly language: SupportedLanguage;
68
+ }
69
+ /**
70
+ * Options accepted by the engine constructor. All fields are optional and
71
+ * safe defaults are used when omitted.
72
+ */
73
+ export interface TreeSitterEngineOptions {
74
+ /**
75
+ * Directory where the language grammar WASM files live (one per
76
+ * language, e.g. `tree-sitter-typescript.wasm`). Defaults to the
77
+ * `tree-sitter-wasms/out` directory inside `node_modules`.
78
+ */
79
+ readonly grammarsDir?: string;
80
+ /**
81
+ * Directory where the `web-tree-sitter` runtime WASM (`tree-sitter.wasm`)
82
+ * lives. This is a different package from the grammars — the runtime
83
+ * ships with `web-tree-sitter` itself. Defaults to that package's
84
+ * install directory inside `node_modules`.
85
+ */
86
+ readonly runtimeDir?: string;
87
+ /**
88
+ * Override the WASM loader for tests. Receives the grammar filename
89
+ * and must return the raw bytes.
90
+ */
91
+ readonly loadGrammar?: (wasmPath: string) => Promise<Uint8Array>;
92
+ }
93
+ /**
94
+ * High-level AST engine. Instances are meant to be long-lived — create
95
+ * one at server startup and reuse it for every analysis request.
96
+ */
97
+ export declare class TreeSitterEngine {
98
+ private parserCtor;
99
+ private readonly loadedLanguages;
100
+ private readonly grammarsDir;
101
+ private readonly runtimeDir;
102
+ private readonly loadGrammar;
103
+ private initPromise;
104
+ constructor(options?: TreeSitterEngineOptions);
105
+ /**
106
+ * Analyze a source file and return per-function and file-level metrics.
107
+ *
108
+ * @param req The analysis request.
109
+ * @returns A {@link FileMetrics} snapshot ready to be serialized.
110
+ * @throws When the file cannot be read or the grammar cannot be loaded.
111
+ */
112
+ analyzeFile(req: AnalyzeFileRequest): Promise<FileMetrics>;
113
+ /**
114
+ * Ensure a parser with the requested language grammar bound is ready.
115
+ * Both the Parser class and the grammar are initialized lazily and
116
+ * cached on first use.
117
+ *
118
+ * @param config Language configuration for the requested grammar.
119
+ * @returns A fresh parser instance configured for the language.
120
+ */
121
+ private ensureParserFor;
122
+ /**
123
+ * Import and initialize `web-tree-sitter`. Isolated in its own method
124
+ * so the dynamic import runs exactly once per engine instance.
125
+ *
126
+ * `web-tree-sitter` uses `export = Parser` so under ESM interop the
127
+ * Parser class arrives on the `default` property of the imported
128
+ * namespace. `Parser.init()` is a STATIC method on the class, not a
129
+ * top-level module function.
130
+ */
131
+ private initParserModule;
132
+ }
133
+ //# sourceMappingURL=tree-sitter-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-sitter-engine.d.ts","sourceRoot":"","sources":["../../src/ast/tree-sitter-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAQH,OAAO,EAAuC,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AA2BnG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyC;IACzE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4C;IACxE,OAAO,CAAC,WAAW,CAA8B;gBAErC,OAAO,GAAE,uBAA4B;IAMjD;;;;;;OAMG;IACG,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAsBhE;;;;;;;OAOG;YACW,eAAe;IAyB7B;;;;;;;;OAQG;YACW,gBAAgB;CAsB/B"}