@smeltjs/core 0.1.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 (199) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +55 -0
  3. package/THIRD-PARTY.md +140 -0
  4. package/dist/apply.d.ts +145 -0
  5. package/dist/apply.d.ts.map +1 -0
  6. package/dist/apply.js +244 -0
  7. package/dist/apply.js.map +1 -0
  8. package/dist/cache/prefix.d.ts +164 -0
  9. package/dist/cache/prefix.d.ts.map +1 -0
  10. package/dist/cache/prefix.js +361 -0
  11. package/dist/cache/prefix.js.map +1 -0
  12. package/dist/cli/args.d.ts +71 -0
  13. package/dist/cli/args.d.ts.map +1 -0
  14. package/dist/cli/args.js +308 -0
  15. package/dist/cli/args.js.map +1 -0
  16. package/dist/cli/bin.d.ts +3 -0
  17. package/dist/cli/bin.d.ts.map +1 -0
  18. package/dist/cli/bin.js +161 -0
  19. package/dist/cli/bin.js.map +1 -0
  20. package/dist/cli/config.d.ts +73 -0
  21. package/dist/cli/config.d.ts.map +1 -0
  22. package/dist/cli/config.js +144 -0
  23. package/dist/cli/config.js.map +1 -0
  24. package/dist/cli/init.d.ts +56 -0
  25. package/dist/cli/init.d.ts.map +1 -0
  26. package/dist/cli/init.js +449 -0
  27. package/dist/cli/init.js.map +1 -0
  28. package/dist/cli/report.d.ts +44 -0
  29. package/dist/cli/report.d.ts.map +1 -0
  30. package/dist/cli/report.js +113 -0
  31. package/dist/cli/report.js.map +1 -0
  32. package/dist/cli/resolve.d.ts +103 -0
  33. package/dist/cli/resolve.d.ts.map +1 -0
  34. package/dist/cli/resolve.js +106 -0
  35. package/dist/cli/resolve.js.map +1 -0
  36. package/dist/cli/run.d.ts +99 -0
  37. package/dist/cli/run.d.ts.map +1 -0
  38. package/dist/cli/run.js +351 -0
  39. package/dist/cli/run.js.map +1 -0
  40. package/dist/detect.d.ts +16 -0
  41. package/dist/detect.d.ts.map +1 -0
  42. package/dist/detect.js +18 -0
  43. package/dist/detect.js.map +1 -0
  44. package/dist/errors.d.ts +88 -0
  45. package/dist/errors.d.ts.map +1 -0
  46. package/dist/errors.js +107 -0
  47. package/dist/errors.js.map +1 -0
  48. package/dist/hash.d.ts +13 -0
  49. package/dist/hash.d.ts.map +1 -0
  50. package/dist/hash.js +16 -0
  51. package/dist/hash.js.map +1 -0
  52. package/dist/index.d.ts +121 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +93 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/lang/bash.d.ts +3 -0
  57. package/dist/lang/bash.d.ts.map +1 -0
  58. package/dist/lang/bash.js +28 -0
  59. package/dist/lang/bash.js.map +1 -0
  60. package/dist/lang/c.d.ts +3 -0
  61. package/dist/lang/c.d.ts.map +1 -0
  62. package/dist/lang/c.js +39 -0
  63. package/dist/lang/c.js.map +1 -0
  64. package/dist/lang/c_sharp.d.ts +3 -0
  65. package/dist/lang/c_sharp.d.ts.map +1 -0
  66. package/dist/lang/c_sharp.js +37 -0
  67. package/dist/lang/c_sharp.js.map +1 -0
  68. package/dist/lang/cpp.d.ts +3 -0
  69. package/dist/lang/cpp.d.ts.map +1 -0
  70. package/dist/lang/cpp.js +46 -0
  71. package/dist/lang/cpp.js.map +1 -0
  72. package/dist/lang/go.d.ts +3 -0
  73. package/dist/lang/go.d.ts.map +1 -0
  74. package/dist/lang/go.js +31 -0
  75. package/dist/lang/go.js.map +1 -0
  76. package/dist/lang/java.d.ts +3 -0
  77. package/dist/lang/java.d.ts.map +1 -0
  78. package/dist/lang/java.js +34 -0
  79. package/dist/lang/java.js.map +1 -0
  80. package/dist/lang/javascript.d.ts +3 -0
  81. package/dist/lang/javascript.d.ts.map +1 -0
  82. package/dist/lang/javascript.js +28 -0
  83. package/dist/lang/javascript.js.map +1 -0
  84. package/dist/lang/kotlin.d.ts +3 -0
  85. package/dist/lang/kotlin.d.ts.map +1 -0
  86. package/dist/lang/kotlin.js +37 -0
  87. package/dist/lang/kotlin.js.map +1 -0
  88. package/dist/lang/php.d.ts +3 -0
  89. package/dist/lang/php.d.ts.map +1 -0
  90. package/dist/lang/php.js +37 -0
  91. package/dist/lang/php.js.map +1 -0
  92. package/dist/lang/profile.d.ts +130 -0
  93. package/dist/lang/profile.d.ts.map +1 -0
  94. package/dist/lang/profile.js +2 -0
  95. package/dist/lang/profile.js.map +1 -0
  96. package/dist/lang/python.d.ts +3 -0
  97. package/dist/lang/python.d.ts.map +1 -0
  98. package/dist/lang/python.js +33 -0
  99. package/dist/lang/python.js.map +1 -0
  100. package/dist/lang/registry.d.ts +31 -0
  101. package/dist/lang/registry.d.ts.map +1 -0
  102. package/dist/lang/registry.js +89 -0
  103. package/dist/lang/registry.js.map +1 -0
  104. package/dist/lang/ruby.d.ts +3 -0
  105. package/dist/lang/ruby.d.ts.map +1 -0
  106. package/dist/lang/ruby.js +47 -0
  107. package/dist/lang/ruby.js.map +1 -0
  108. package/dist/lang/rust.d.ts +3 -0
  109. package/dist/lang/rust.d.ts.map +1 -0
  110. package/dist/lang/rust.js +45 -0
  111. package/dist/lang/rust.js.map +1 -0
  112. package/dist/lang/swift.d.ts +3 -0
  113. package/dist/lang/swift.d.ts.map +1 -0
  114. package/dist/lang/swift.js +34 -0
  115. package/dist/lang/swift.js.map +1 -0
  116. package/dist/lang/tsx.d.ts +4 -0
  117. package/dist/lang/tsx.d.ts.map +1 -0
  118. package/dist/lang/tsx.js +11 -0
  119. package/dist/lang/tsx.js.map +1 -0
  120. package/dist/lang/typescript.d.ts +18 -0
  121. package/dist/lang/typescript.d.ts.map +1 -0
  122. package/dist/lang/typescript.js +61 -0
  123. package/dist/lang/typescript.js.map +1 -0
  124. package/dist/net/policy.d.ts +49 -0
  125. package/dist/net/policy.d.ts.map +1 -0
  126. package/dist/net/policy.js +120 -0
  127. package/dist/net/policy.js.map +1 -0
  128. package/dist/plan/grammar.d.ts +38 -0
  129. package/dist/plan/grammar.d.ts.map +1 -0
  130. package/dist/plan/grammar.js +85 -0
  131. package/dist/plan/grammar.js.map +1 -0
  132. package/dist/plan/lexical.d.ts +51 -0
  133. package/dist/plan/lexical.d.ts.map +1 -0
  134. package/dist/plan/lexical.js +167 -0
  135. package/dist/plan/lexical.js.map +1 -0
  136. package/dist/plan/planners.d.ts +35 -0
  137. package/dist/plan/planners.d.ts.map +1 -0
  138. package/dist/plan/planners.js +26 -0
  139. package/dist/plan/planners.js.map +1 -0
  140. package/dist/plan/structural.d.ts +68 -0
  141. package/dist/plan/structural.d.ts.map +1 -0
  142. package/dist/plan/structural.js +458 -0
  143. package/dist/plan/structural.js.map +1 -0
  144. package/dist/repomap/cache.d.ts +53 -0
  145. package/dist/repomap/cache.d.ts.map +1 -0
  146. package/dist/repomap/cache.js +139 -0
  147. package/dist/repomap/cache.js.map +1 -0
  148. package/dist/repomap/map.d.ts +161 -0
  149. package/dist/repomap/map.d.ts.map +1 -0
  150. package/dist/repomap/map.js +302 -0
  151. package/dist/repomap/map.js.map +1 -0
  152. package/dist/repomap/rank.d.ts +52 -0
  153. package/dist/repomap/rank.d.ts.map +1 -0
  154. package/dist/repomap/rank.js +155 -0
  155. package/dist/repomap/rank.js.map +1 -0
  156. package/dist/repomap/tags.d.ts +47 -0
  157. package/dist/repomap/tags.d.ts.map +1 -0
  158. package/dist/repomap/tags.js +101 -0
  159. package/dist/repomap/tags.js.map +1 -0
  160. package/dist/retrieve.d.ts +14 -0
  161. package/dist/retrieve.d.ts.map +1 -0
  162. package/dist/retrieve.js +44 -0
  163. package/dist/retrieve.js.map +1 -0
  164. package/dist/stages.d.ts +22 -0
  165. package/dist/stages.d.ts.map +1 -0
  166. package/dist/stages.js +33 -0
  167. package/dist/stages.js.map +1 -0
  168. package/dist/stats.d.ts +40 -0
  169. package/dist/stats.d.ts.map +1 -0
  170. package/dist/stats.js +37 -0
  171. package/dist/stats.js.map +1 -0
  172. package/dist/store-dir.d.ts +98 -0
  173. package/dist/store-dir.d.ts.map +1 -0
  174. package/dist/store-dir.js +379 -0
  175. package/dist/store-dir.js.map +1 -0
  176. package/dist/store.d.ts +36 -0
  177. package/dist/store.d.ts.map +1 -0
  178. package/dist/store.js +56 -0
  179. package/dist/store.js.map +1 -0
  180. package/dist/types.d.ts +298 -0
  181. package/dist/types.d.ts.map +1 -0
  182. package/dist/types.js +2 -0
  183. package/dist/types.js.map +1 -0
  184. package/grammars/tree-sitter-bash.wasm +0 -0
  185. package/grammars/tree-sitter-c.wasm +0 -0
  186. package/grammars/tree-sitter-c_sharp.wasm +0 -0
  187. package/grammars/tree-sitter-cpp.wasm +0 -0
  188. package/grammars/tree-sitter-go.wasm +0 -0
  189. package/grammars/tree-sitter-java.wasm +0 -0
  190. package/grammars/tree-sitter-javascript.wasm +0 -0
  191. package/grammars/tree-sitter-kotlin.wasm +0 -0
  192. package/grammars/tree-sitter-php.wasm +0 -0
  193. package/grammars/tree-sitter-python.wasm +0 -0
  194. package/grammars/tree-sitter-ruby.wasm +0 -0
  195. package/grammars/tree-sitter-rust.wasm +0 -0
  196. package/grammars/tree-sitter-swift.wasm +0 -0
  197. package/grammars/tree-sitter-tsx.wasm +0 -0
  198. package/grammars/tree-sitter-typescript.wasm +0 -0
  199. package/package.json +68 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planners.d.ts","sourceRoot":"","sources":["../../src/plan/planners.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,wBAAwB,CAAC;CAChD;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ;gCACA,qBAAqB,KAAG,OAAO;mCAC5B,qBAAqB,KAAG,OAAO;CAEyB,CAAC;AAEjF,2FAA2F;AAC3F,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC;AAE7C,mFAAmF;AACnF,eAAO,MAAM,UAAU,EAA4B,SAAS,QAAQ,EAAE,CAAC;AAEvE,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D"}
@@ -0,0 +1,26 @@
1
+ import { LexicalPlanner } from './lexical.js';
2
+ import { StructuralPlanner } from './structural.js';
3
+ /**
4
+ * The one registry of planner strategies — string in, constructed {@link Planner} out.
5
+ *
6
+ * This object is the single place the strategy names live. `createSmelter` builds from
7
+ * it, `--strategy` and `smelt.config.json` validation accept exactly its keys, and the
8
+ * `--help` text renders its keys — so a strategy cannot exist in one of those faces and
9
+ * be missing from another. Before this registry the pair was restated in three places,
10
+ * which is how help text rots.
11
+ *
12
+ * `'structural'` parses every language named in {@link STRUCTURAL_LANGUAGES} with a
13
+ * bundled grammar and throws {@link GrammarUnavailableError} for anything else — never
14
+ * a silent lexical fallback. See {@link StructuralPlanner}.
15
+ */
16
+ export const PLANNERS = {
17
+ lexical: (options) => new LexicalPlanner(options.lexical ?? {}),
18
+ structural: (options) => new StructuralPlanner(options.structural ?? {}),
19
+ };
20
+ /** The registry's keys, in declaration order, for help text and error messages. */
21
+ export const STRATEGIES = Object.keys(PLANNERS);
22
+ /** The one membership test `--strategy` and config validation both use. */
23
+ export function isStrategy(value) {
24
+ return Object.hasOwn(PLANNERS, value);
25
+ }
26
+ //# sourceMappingURL=planners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planners.js","sourceRoot":"","sources":["../../src/plan/planners.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAYpD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,OAAO,EAAE,CAAC,OAA8B,EAAW,EAAE,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IAC/F,UAAU,EAAE,CAAC,OAA8B,EAAW,EAAE,CACtD,IAAI,iBAAiB,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;CAC6B,CAAC;AAKjF,mFAAmF;AACnF,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAwB,CAAC;AAEvE,2EAA2E;AAC3E,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { ElisionPlan, LanguageId, PlanInput, Planner } from '../types.ts';
2
+ export declare const STRUCTURAL_PLANNER_ID = "structural/v1";
3
+ /**
4
+ * The languages this planner actually parses — a derived view of the registry: every
5
+ * {@link LanguageProfile} that carries a `structure` section, in registry order. A
6
+ * language appears here only once its node kinds are mapped in its profile
7
+ * (`src/lang/<id>.ts`), because claiming a language before that would produce markers
8
+ * that mislabel what they collapsed.
9
+ *
10
+ * Exported for the totality guard (`test/guards/structural-totality.test.ts`): every
11
+ * language named here must have a fixture, a snapshot and a doc-comment case, so a
12
+ * language cannot be claimed without tests.
13
+ */
14
+ export declare const STRUCTURAL_LANGUAGES: readonly LanguageId[];
15
+ /**
16
+ * Historically the union of the claimed ids; every `LanguageId` carries a profile
17
+ * now, so the compile-time totality this type enforced lives on the registry
18
+ * (`Record<LanguageId, LanguageProfile>`) instead.
19
+ */
20
+ export type StructuralLanguage = LanguageId;
21
+ export interface StructuralPlannerOptions {
22
+ /**
23
+ * Never collapse a sibling group smaller than this. Defaults to 1 — the byte
24
+ * profitability check already refuses collapses that would not pay for their marker.
25
+ */
26
+ readonly minSiblings?: number;
27
+ /** Focus matching is substring, case-insensitive by default — same as lexical. */
28
+ readonly caseSensitive?: boolean;
29
+ }
30
+ /**
31
+ * The structural planner — the reason smelt exists.
32
+ *
33
+ * It parses with the language's tree-sitter grammar, finds the top-level declarations
34
+ * whose text matches the caller's focus, keeps each match whole — signature line,
35
+ * attached doc comment, body — and collapses each contiguous run of non-matching
36
+ * *siblings* into one marker that names them from the parse tree: `collapsed 3 sibling
37
+ * functions`. Structure is what makes that explanation possible; a line window can only
38
+ * ever say "collapsed 40 lines".
39
+ *
40
+ * It throws {@link GrammarUnavailableError} rather than falling back to the lexical
41
+ * planner, and that is the deliberate part. A silent fallback would mean a caller who
42
+ * asked for structural planning, and whose grammar failed to load, gets line-window
43
+ * output labelled `structural/v1` — plausible, wrong, and undetectable from the
44
+ * outside. A caller who wants the fallback asks for it, by planning lexically itself.
45
+ */
46
+ export declare class StructuralPlanner implements Planner {
47
+ readonly id = "structural/v1";
48
+ readonly options: StructuralPlannerOptions;
49
+ constructor(options?: StructuralPlannerOptions);
50
+ plan(input: PlanInput): Promise<ElisionPlan>;
51
+ }
52
+ /**
53
+ * The planner as a function, exported like {@link planLexical} so it can be tested and
54
+ * reused directly. Deterministic: same text, same language, same focus, same options —
55
+ * byte-identical plan.
56
+ *
57
+ * `budgetBytes` is a target, not a guarantee, for the same reason it is in the lexical
58
+ * planner: once every non-matching sibling run is collapsed there is nothing left to
59
+ * cut except the declarations the caller asked to keep, and an optimizer that silently
60
+ * drops the thing you searched for is the exact failure this design refuses. Callers
61
+ * who need a hard ceiling check `outputBytes` and decide.
62
+ *
63
+ * @throws {GrammarUnavailableError} when the language is not one this planner parses,
64
+ * when the grammar cannot be loaded, or when the parser produces no tree. Never a
65
+ * lexical fallback.
66
+ */
67
+ export declare function planStructural(input: PlanInput, options?: StructuralPlannerOptions): Promise<ElisionPlan>;
68
+ //# sourceMappingURL=structural.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural.d.ts","sourceRoot":"","sources":["../../src/plan/structural.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EAEV,SAAS,EAET,OAAO,EACR,MAAM,aAAa,CAAC;AAIrB,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,UAAU,EAA0B,CAAC;AAEjF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAQ5C,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,kFAAkF;IAClF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,QAAQ,CAAC,EAAE,mBAAyB;IACpC,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAC;IAE3C,YAAY,OAAO,GAAE,wBAA6B,EAEjD;IAED,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAE3C;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,WAAW,CAAC,CA8BtB"}
@@ -0,0 +1,458 @@
1
+ import { Parser } from 'web-tree-sitter';
2
+ import { GrammarUnavailableError, MissingMarkerPricingError } from '../errors.js';
3
+ import { profileFor, structuralLanguages } from '../lang/registry.js';
4
+ import { loadGrammar } from './grammar.js';
5
+ export const STRUCTURAL_PLANNER_ID = 'structural/v1';
6
+ /**
7
+ * The languages this planner actually parses — a derived view of the registry: every
8
+ * {@link LanguageProfile} that carries a `structure` section, in registry order. A
9
+ * language appears here only once its node kinds are mapped in its profile
10
+ * (`src/lang/<id>.ts`), because claiming a language before that would produce markers
11
+ * that mislabel what they collapsed.
12
+ *
13
+ * Exported for the totality guard (`test/guards/structural-totality.test.ts`): every
14
+ * language named here must have a fixture, a snapshot and a doc-comment case, so a
15
+ * language cannot be claimed without tests.
16
+ */
17
+ export const STRUCTURAL_LANGUAGES = structuralLanguages();
18
+ /**
19
+ * Every elision this planner produces carries this rule id, and the profitability
20
+ * check below prices the marker that rule would earn — so the two must not drift.
21
+ */
22
+ const SIBLING_COLLAPSE_RULE = 'sibling-collapse';
23
+ /**
24
+ * The structural planner — the reason smelt exists.
25
+ *
26
+ * It parses with the language's tree-sitter grammar, finds the top-level declarations
27
+ * whose text matches the caller's focus, keeps each match whole — signature line,
28
+ * attached doc comment, body — and collapses each contiguous run of non-matching
29
+ * *siblings* into one marker that names them from the parse tree: `collapsed 3 sibling
30
+ * functions`. Structure is what makes that explanation possible; a line window can only
31
+ * ever say "collapsed 40 lines".
32
+ *
33
+ * It throws {@link GrammarUnavailableError} rather than falling back to the lexical
34
+ * planner, and that is the deliberate part. A silent fallback would mean a caller who
35
+ * asked for structural planning, and whose grammar failed to load, gets line-window
36
+ * output labelled `structural/v1` — plausible, wrong, and undetectable from the
37
+ * outside. A caller who wants the fallback asks for it, by planning lexically itself.
38
+ */
39
+ export class StructuralPlanner {
40
+ id = STRUCTURAL_PLANNER_ID;
41
+ options;
42
+ constructor(options = {}) {
43
+ this.options = options;
44
+ }
45
+ plan(input) {
46
+ return planStructural(input, this.options);
47
+ }
48
+ }
49
+ /**
50
+ * The planner as a function, exported like {@link planLexical} so it can be tested and
51
+ * reused directly. Deterministic: same text, same language, same focus, same options —
52
+ * byte-identical plan.
53
+ *
54
+ * `budgetBytes` is a target, not a guarantee, for the same reason it is in the lexical
55
+ * planner: once every non-matching sibling run is collapsed there is nothing left to
56
+ * cut except the declarations the caller asked to keep, and an optimizer that silently
57
+ * drops the thing you searched for is the exact failure this design refuses. Callers
58
+ * who need a hard ceiling check `outputBytes` and decide.
59
+ *
60
+ * @throws {GrammarUnavailableError} when the language is not one this planner parses,
61
+ * when the grammar cannot be loaded, or when the parser produces no tree. Never a
62
+ * lexical fallback.
63
+ */
64
+ export async function planStructural(input, options = {}) {
65
+ const language = assertStructuralLanguage(input.language);
66
+ // The runtime backstop for JS callers: TypeScript makes `pricing` required, but a
67
+ // JS caller can omit it, and the honest answer is a named refusal rather than the
68
+ // planner quietly pricing markers itself — the inversion the seam removed.
69
+ const pricing = input.pricing;
70
+ if (pricing === undefined)
71
+ throw new MissingMarkerPricingError(STRUCTURAL_PLANNER_ID);
72
+ const grammar = await loadGrammar(language);
73
+ const parser = new Parser();
74
+ let tree = null;
75
+ try {
76
+ parser.setLanguage(grammar);
77
+ tree = parser.parse(input.text);
78
+ if (tree === null) {
79
+ throw new GrammarUnavailableError(`smelt: the ${language} parser returned no tree. Structural planning cannot ` +
80
+ `proceed, and it does not fall back to lexical — a caller who wants the ` +
81
+ `fallback plans lexically itself.`);
82
+ }
83
+ return {
84
+ planner: STRUCTURAL_PLANNER_ID,
85
+ language: input.language,
86
+ elisions: planFromTree(tree, input, options, language),
87
+ };
88
+ }
89
+ finally {
90
+ tree?.delete();
91
+ parser.delete();
92
+ }
93
+ }
94
+ function assertStructuralLanguage(language) {
95
+ for (const supported of STRUCTURAL_LANGUAGES) {
96
+ if (language === supported)
97
+ return supported;
98
+ }
99
+ const named = `${STRUCTURAL_LANGUAGES.slice(0, -1).join(', ')} and ${STRUCTURAL_LANGUAGES[STRUCTURAL_LANGUAGES.length - 1]}`;
100
+ throw new GrammarUnavailableError(`smelt: structural planning covers ${named} in this ` +
101
+ `slice; got "${language}". It does not fall back to the lexical planner — output ` +
102
+ `labelled structural/v1 that is really line windows would be undetectable from ` +
103
+ `the outside. Use the lexical planner explicitly if that is what you want.`);
104
+ }
105
+ function planFromTree(tree, input, options, language) {
106
+ const profile = profileFor(language);
107
+ // assertStructuralLanguage admits only languages whose profile carries a
108
+ // `structure` section — that is the definition of a structural language — so the
109
+ // assertion states a fact the seam already proved.
110
+ const structure = profile.structure;
111
+ const pricing = input.pricing;
112
+ // The marker lands as a line comment in every structural language (the profile's
113
+ // markerLeader), and a line comment comments out everything to the end of its
114
+ // line — so a collapse is only legal where nothing kept follows on the marker's
115
+ // own line. See the flush below.
116
+ const markerIsLineComment = profile.markerLeader !== undefined;
117
+ const units = unitsOf(tree.rootNode, input.text, structure);
118
+ const matched = matchUnits(units, input, options);
119
+ const minSiblings = options.minSiblings ?? 1;
120
+ const toByte = utf8OffsetIndex(input.text, units.flatMap((unit) => [unit.start, unit.end]));
121
+ const elisions = [];
122
+ let run = [];
123
+ const flush = () => {
124
+ if (run.length === 0)
125
+ return;
126
+ const group = run;
127
+ run = [];
128
+ if (group.length < minSiblings)
129
+ return;
130
+ // A line-comment marker swallows the rest of its line. When the run's last unit
131
+ // ends mid-line — python's `stmt_a(); stmt_b()` puts two top-level statements on
132
+ // one line — the marker's `# ` leader would comment out the *kept* code after it.
133
+ // Refusing the collapse is the honest move; extending the range would elide code
134
+ // no unit accounted for.
135
+ if (markerIsLineComment && !restOfLineIsBlank(input.text, group[group.length - 1].end)) {
136
+ return;
137
+ }
138
+ const start = toByte.get(group[0].start);
139
+ const end = toByte.get(group[group.length - 1].end);
140
+ const cutBytes = end - start;
141
+ const explanation = explain(group);
142
+ // Profitability, priced rather than estimated: ask the MarkerPricing seam for the
143
+ // exact cost of the marker this cut would earn — the explanation's length varies
144
+ // with kind diversity, and the pricing carries the language's comment leader (or a
145
+ // caller's custom builder), so a fixed estimate can pass a cut whose marker is
146
+ // bigger than what it removes, and a marker that costs more than it removes grows
147
+ // the output.
148
+ const markerBytes = pricing.costBytes({ rule: SIBLING_COLLAPSE_RULE, explanation }, cutBytes);
149
+ if (cutBytes <= markerBytes)
150
+ return;
151
+ elisions.push({
152
+ range: { start, end },
153
+ reason: { rule: SIBLING_COLLAPSE_RULE, explanation },
154
+ });
155
+ };
156
+ for (let i = 0; i < units.length; i += 1) {
157
+ if (matched[i] === true || units[i].pinned === true) {
158
+ flush();
159
+ }
160
+ else {
161
+ run.push(units[i]);
162
+ }
163
+ }
164
+ flush();
165
+ return elisions;
166
+ }
167
+ /** True when nothing but whitespace follows `index` on its own line. */
168
+ function restOfLineIsBlank(text, index) {
169
+ for (let i = index; i < text.length; i += 1) {
170
+ const ch = text[i];
171
+ if (ch === '\n')
172
+ return true;
173
+ if (!/\s/.test(ch))
174
+ return false;
175
+ }
176
+ return true;
177
+ }
178
+ /**
179
+ * Group the root's named children into units: each declaration plus the comment block
180
+ * — and, in rust, the outer attributes — attached to it. A comment attaches when only
181
+ * blank-free whitespace separates it from what follows — one newline at most — so a doc
182
+ * comment travels with its declaration, while a comment left floating above a blank
183
+ * line stands alone.
184
+ *
185
+ * Attributes attach *unconditionally*: tree-sitter-rust parses `#[inline]` as a
186
+ * top-level sibling of the item it decorates, but the language's own rule is that an
187
+ * outer attribute modifies the next item, blank lines or not. So once an attribute is
188
+ * pending, the whole pending prefix (doc comments included) rides forward to the next
189
+ * declaration — treating it as its own unit would let a collapse strip `#[derive(…)]`
190
+ * and the doc comment above it off a kept declaration.
191
+ */
192
+ function unitsOf(root, text, structure) {
193
+ const units = [];
194
+ /** Comments and attributes waiting to attach to the next declaration. */
195
+ let pending = [];
196
+ /** Once true, blank lines no longer detach the pending prefix — see above. */
197
+ let pendingHasAttribute = false;
198
+ const flushPending = () => {
199
+ if (pending.length === 0)
200
+ return;
201
+ units.push({
202
+ start: pending[0].startIndex,
203
+ end: pending[pending.length - 1].endIndex,
204
+ kind: pendingHasAttribute ? 'attribute' : 'comment',
205
+ pinned: !pendingHasAttribute && pending.some((node) => pinnedComment(node, text, structure)),
206
+ });
207
+ pending = [];
208
+ pendingHasAttribute = false;
209
+ };
210
+ for (const child of root.namedChildren) {
211
+ if (child === null)
212
+ continue;
213
+ if (structure.ridesBackwardTypes?.has(child.type) === true && units.length > 0) {
214
+ // A node that is grammatically part of the *previous* statement, parsed as a
215
+ // top-level sibling: tree-sitter-ruby emits a heredoc's body as a sibling of
216
+ // the statement holding its `<<~SQL` opener. Splitting them lets a collapse
217
+ // keep the opener and cut the body — an unterminated heredoc that swallows
218
+ // every kept declaration after it, without a single ERROR node to show for
219
+ // it. The body extends the preceding unit instead, so opener and body are
220
+ // kept whole or collapsed whole, always.
221
+ flushPending();
222
+ const last = units[units.length - 1];
223
+ units[units.length - 1] = { ...last, end: child.endIndex };
224
+ continue;
225
+ }
226
+ if (structure.pinnedTypes?.has(child.type) === true ||
227
+ pinnedDirective(child, text, structure)) {
228
+ // A pinned node (php's `<?php` tag, a `#!` shebang line, c's `#pragma once`)
229
+ // is its own uncollapsible unit — nothing attaches to it, and no run may
230
+ // swallow it.
231
+ flushPending();
232
+ units.push({
233
+ start: child.startIndex,
234
+ end: child.endIndex,
235
+ kind: kindOf(child, structure),
236
+ pinned: true,
237
+ });
238
+ continue;
239
+ }
240
+ const isComment = structure.commentTypes.has(child.type);
241
+ const isAttribute = structure.attributeTypes.has(child.type);
242
+ if (isComment || isAttribute) {
243
+ if (pending.length > 0 &&
244
+ !pendingHasAttribute &&
245
+ !adjacent(text, pending[pending.length - 1].endIndex, child.startIndex)) {
246
+ flushPending();
247
+ }
248
+ pending.push(child);
249
+ pendingHasAttribute ||= isAttribute;
250
+ continue;
251
+ }
252
+ // tree-sitter-kotlin extends the import_list node over a doc comment that
253
+ // follows it, so the KDoc of the first documented declaration after the imports
254
+ // would be collapsed *with the imports* — a kept declaration losing its attached
255
+ // doc comment. Split such trailing comments off: the unit ends at its last
256
+ // non-comment token, and the comments ride forward like any other pending block.
257
+ const { end: childEnd, trailing } = structure.trailingCommentSplitTypes?.has(child.type) === true
258
+ ? splitTrailingComments(child, structure)
259
+ : { end: child.endIndex, trailing: [] };
260
+ const attached = pending.length > 0 &&
261
+ (pendingHasAttribute ||
262
+ adjacent(text, pending[pending.length - 1].endIndex, child.startIndex));
263
+ if (attached && pending.some((node) => pinnedComment(node, text, structure))) {
264
+ // A pinned comment (`//go:build`) governs the file, not the declaration it
265
+ // happens to touch — keep it a standalone, uncollapsible unit either way.
266
+ flushPending();
267
+ units.push({
268
+ start: child.startIndex,
269
+ end: childEnd,
270
+ kind: kindOf(child, structure),
271
+ });
272
+ }
273
+ else if (attached) {
274
+ units.push({
275
+ start: pending[0].startIndex,
276
+ end: childEnd,
277
+ kind: kindOf(child, structure),
278
+ });
279
+ pending = [];
280
+ pendingHasAttribute = false;
281
+ }
282
+ else {
283
+ flushPending();
284
+ units.push({
285
+ start: child.startIndex,
286
+ end: childEnd,
287
+ kind: kindOf(child, structure),
288
+ });
289
+ }
290
+ for (const comment of trailing)
291
+ pending.push(comment);
292
+ }
293
+ flushPending();
294
+ return units;
295
+ }
296
+ /** Whether this comment node is one the language pins to the file. See {@link Unit}. */
297
+ function pinnedComment(node, text, structure) {
298
+ if (structure.pinnedCommentPattern === undefined)
299
+ return false;
300
+ if (!structure.commentTypes.has(node.type))
301
+ return false;
302
+ return structure.pinnedCommentPattern.test(text.slice(node.startIndex, node.endIndex));
303
+ }
304
+ /**
305
+ * Whether this non-comment node is pinned by a per-type text pattern. C's
306
+ * `#pragma once` is a `preproc_call` like any other pragma, but collapsing it
307
+ * silently changes header inclusion semantics — the same class as `//go:build`, on a
308
+ * node kind a comment pattern cannot reach.
309
+ */
310
+ function pinnedDirective(node, text, structure) {
311
+ const pattern = structure.pinnedPatternsByType?.[node.type];
312
+ if (pattern === undefined)
313
+ return false;
314
+ return pattern.test(text.slice(node.startIndex, node.endIndex));
315
+ }
316
+ /**
317
+ * The end of `node`'s last non-comment token, and every comment node after it. Used
318
+ * for node types the grammar extends over comments that belong to what follows —
319
+ * kotlin's import_list swallowing the next declaration's KDoc.
320
+ */
321
+ function splitTrailingComments(node, structure) {
322
+ const comments = [];
323
+ let end = node.startIndex;
324
+ const walk = (current) => {
325
+ if (structure.commentTypes.has(current.type)) {
326
+ comments.push(current);
327
+ return;
328
+ }
329
+ let hasChildren = false;
330
+ for (const child of current.children) {
331
+ if (child === null)
332
+ continue;
333
+ hasChildren = true;
334
+ walk(child);
335
+ }
336
+ if (!hasChildren && current.endIndex > end)
337
+ end = current.endIndex;
338
+ };
339
+ for (const child of node.children) {
340
+ if (child !== null)
341
+ walk(child);
342
+ }
343
+ return { end, trailing: comments.filter((comment) => comment.startIndex >= end) };
344
+ }
345
+ /** Nothing but whitespace between the two indices, and at most one newline. */
346
+ function adjacent(text, end, start) {
347
+ const between = text.slice(end, start);
348
+ if (!/^\s*$/.test(between))
349
+ return false;
350
+ return (between.match(/\n/g) ?? []).length <= 1;
351
+ }
352
+ function matchUnits(units, input, options) {
353
+ const caseSensitive = options.caseSensitive ?? false;
354
+ const focus = (input.focus ?? []).filter((term) => term.length > 0);
355
+ const needles = caseSensitive ? focus : focus.map((term) => term.toLowerCase());
356
+ return units.map((unit) => {
357
+ if (needles.length === 0)
358
+ return false;
359
+ const raw = input.text.slice(unit.start, unit.end);
360
+ const haystack = caseSensitive ? raw : raw.toLowerCase();
361
+ return needles.some((needle) => haystack.includes(needle));
362
+ });
363
+ }
364
+ /**
365
+ * Law 2, for this rule: the explanation names the *kind* and the *count*, read off the
366
+ * parse tree — `collapsed 3 sibling functions` — never a line count as the claim. A
367
+ * mixed run says what it mixed: `collapsed 4 sibling declarations (3 functions,
368
+ * 1 class)` — and when the run holds anything that is not a declaration (a statement,
369
+ * a floating comment, an unparsed region), the heading says `nodes`, because calling
370
+ * a parse error a declaration would be the marker lying about the tree.
371
+ */
372
+ function explain(group) {
373
+ const counts = new Map();
374
+ for (const unit of group)
375
+ counts.set(unit.kind, (counts.get(unit.kind) ?? 0) + 1);
376
+ const total = group.length;
377
+ if (counts.size === 1) {
378
+ const kind = group[0].kind;
379
+ return `collapsed ${String(total)} sibling ${countNoun(kind, total)}`;
380
+ }
381
+ const parts = [...counts.entries()].map(([kind, count]) => `${String(count)} ${countNoun(kind, count)}`);
382
+ const heading = [...counts.keys()].every((kind) => !NON_DECLARATION_KINDS.has(kind))
383
+ ? 'declarations'
384
+ : 'nodes';
385
+ return `collapsed ${String(total)} sibling ${heading} (${parts.join(', ')})`;
386
+ }
387
+ /** The kind labels that are not declarations, so a mixed heading never overclaims. */
388
+ const NON_DECLARATION_KINDS = new Set([
389
+ 'statement',
390
+ 'comment',
391
+ 'unparsed region',
392
+ 'package clause',
393
+ 'package header',
394
+ 'package declaration',
395
+ 'attribute',
396
+ 'command',
397
+ 'variable assignment',
398
+ 'include directive',
399
+ 'shebang',
400
+ 'php tag',
401
+ 'html section',
402
+ 'heredoc body',
403
+ 'preprocessor directive',
404
+ 'preprocessor conditional',
405
+ ]);
406
+ function countNoun(kind, count) {
407
+ if (count === 1)
408
+ return kind;
409
+ if (/[^aeiou]y$/.test(kind))
410
+ return `${kind.slice(0, -1)}ies`;
411
+ return /(?:s|sh|ch)$/.test(kind) ? `${kind}es` : `${kind}s`;
412
+ }
413
+ /**
414
+ * The kind of a declaration, unwrapping wrappers (`export …`, `@decorator`) so the
415
+ * marker names what it hides. What the language's map does not name is still labelled
416
+ * honestly — see {@link LanguageStructure.kindLabels} for the labelling rules.
417
+ */
418
+ function kindOf(node, structure) {
419
+ const wrapperFallback = structure.wrapperTypes[node.type];
420
+ if (wrapperFallback !== undefined) {
421
+ for (const child of node.namedChildren) {
422
+ if (child === null || structure.commentTypes.has(child.type))
423
+ continue;
424
+ const label = structure.kindLabels[child.type];
425
+ if (label !== undefined)
426
+ return label;
427
+ }
428
+ return wrapperFallback;
429
+ }
430
+ const label = structure.kindLabels[node.type];
431
+ if (label !== undefined)
432
+ return label;
433
+ if (node.type === 'ERROR')
434
+ return 'unparsed region';
435
+ if (node.type.endsWith('_statement') || node.type === 'statement_block')
436
+ return 'statement';
437
+ return 'declaration';
438
+ }
439
+ /**
440
+ *
441
+ * web-tree-sitter reports positions in code units of the JS string it parsed;
442
+ * {@link ElisionPlan} ranges are UTF-8 bytes. Because every converted index is a parse
443
+ * node boundary, a range can never split a multi-byte character — a node boundary is
444
+ * always a character boundary. One forward pass, so the conversion is linear.
445
+ */
446
+ function utf8OffsetIndex(text, indices) {
447
+ const sorted = [...new Set(indices)].toSorted((a, b) => a - b);
448
+ const map = new Map();
449
+ let previousIndex = 0;
450
+ let previousByte = 0;
451
+ for (const index of sorted) {
452
+ previousByte += Buffer.byteLength(text.slice(previousIndex, index), 'utf8');
453
+ previousIndex = index;
454
+ map.set(index, previousByte);
455
+ }
456
+ return map;
457
+ }
458
+ //# sourceMappingURL=structural.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/plan/structural.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type { FileTags } from './tags.ts';
2
+ import type { LanguageId } from '../types.ts';
3
+ /**
4
+ * The repo map's disk cache — per-file tags, keyed by content hash, JSON on disk.
5
+ *
6
+ * Modelled on Aider's repo-map tags cache (https://aider.chat/docs/repomap.html),
7
+ * with one deliberate substitution: Aider persists through SQLite; this repo ships
8
+ * zero new runtime dependencies, so entries are plain JSON files under a directory
9
+ * **the caller explicitly hands in**. smelt never writes outside a store or cache it
10
+ * was handed — no default location, no home-directory guessing.
11
+ *
12
+ * The key is a content hash over the tag-format version, the language, and the file's
13
+ * exact text. That is the whole invalidation story: edit a file and its key changes,
14
+ * so the stale entry is simply never looked up again. Nothing needs a timestamp.
15
+ *
16
+ * A corrupt entry — unparseable JSON, or JSON of the wrong shape — is **discarded
17
+ * loudly, never trusted**: the entry file is deleted, the tags are re-extracted from
18
+ * source, and the caller's result carries a warning naming the file. Trusting a
19
+ * damaged cache would silently drop symbols from the map, which is this project's
20
+ * signature failure mode.
21
+ */
22
+ /** The format name every cache entry carries. */
23
+ export declare const TAGS_CACHE_FORMAT = "smelt-repomap-tags";
24
+ /** Bump this when the tag shape changes: old entries then miss instead of misleading. */
25
+ export declare const TAGS_CACHE_VERSION = 1;
26
+ /**
27
+ * The cache key for one file's tags. The version and language are part of the hashed
28
+ * material, so a format bump or a re-detected language can never resurrect an entry
29
+ * extracted under different rules.
30
+ */
31
+ export declare function tagsCacheKey(language: LanguageId, content: string): string;
32
+ /** What `read()` reports about one lookup. */
33
+ export type TagsCacheLookup = FileTags | 'corrupt' | undefined;
34
+ export declare class TagsCache {
35
+ #private;
36
+ /** `dir` is the directory the caller handed in; entries live under `<dir>/tags/`. */
37
+ constructor(dir: string);
38
+ /**
39
+ * The cached tags under `key`, `undefined` on a miss, `'corrupt'` when an entry
40
+ * existed but could not be trusted — in which case it has already been deleted, so
41
+ * the corruption is reported exactly once and never re-read.
42
+ */
43
+ read(key: string): TagsCacheLookup;
44
+ /**
45
+ * Persist one file's tags. Written to a temp name and renamed into place, so a
46
+ * concurrent reader never sees a half-written entry; both writers of the same key
47
+ * are writing identical bytes (the key covers the content), so last-rename-wins is
48
+ * harmless. No fsync: unlike the elision store, every entry here is derivable from
49
+ * source, so losing one to a crash costs a re-parse, not a broken promise.
50
+ */
51
+ write(key: string, tags: FileTags): void;
52
+ }
53
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/repomap/cache.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAiB,QAAQ,EAAgB,MAAM,WAAW,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,8CAA8C;AAC9C,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAE/D,qBAAa,SAAS;;IAGpB,qFAAqF;IACrF,YAAY,GAAG,EAAE,MAAM,EAGtB;IAED;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAqBjC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CAWvC;CAeF"}