@openrewrite/rewrite 8.66.0 → 8.66.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 (113) hide show
  1. package/dist/java/tree.d.ts +10 -1
  2. package/dist/java/tree.d.ts.map +1 -1
  3. package/dist/java/tree.js +21 -5
  4. package/dist/java/tree.js.map +1 -1
  5. package/dist/java/type-visitor.d.ts +1 -1
  6. package/dist/java/type-visitor.d.ts.map +1 -1
  7. package/dist/java/visitor.d.ts +2 -2
  8. package/dist/java/visitor.d.ts.map +1 -1
  9. package/dist/java/visitor.js +8 -2
  10. package/dist/java/visitor.js.map +1 -1
  11. package/dist/javascript/assertions.d.ts +6 -0
  12. package/dist/javascript/assertions.d.ts.map +1 -1
  13. package/dist/javascript/assertions.js +14 -6
  14. package/dist/javascript/assertions.js.map +1 -1
  15. package/dist/javascript/comparator.d.ts +217 -7
  16. package/dist/javascript/comparator.d.ts.map +1 -1
  17. package/dist/javascript/comparator.js +1020 -2848
  18. package/dist/javascript/comparator.js.map +1 -1
  19. package/dist/javascript/format.d.ts +5 -3
  20. package/dist/javascript/format.d.ts.map +1 -1
  21. package/dist/javascript/format.js +87 -44
  22. package/dist/javascript/format.js.map +1 -1
  23. package/dist/javascript/index.d.ts +2 -1
  24. package/dist/javascript/index.d.ts.map +1 -1
  25. package/dist/javascript/index.js +2 -1
  26. package/dist/javascript/index.js.map +1 -1
  27. package/dist/javascript/parser.d.ts +2 -1
  28. package/dist/javascript/parser.d.ts.map +1 -1
  29. package/dist/javascript/parser.js +54 -43
  30. package/dist/javascript/parser.js.map +1 -1
  31. package/dist/javascript/templating/capture.d.ts +293 -0
  32. package/dist/javascript/templating/capture.d.ts.map +1 -0
  33. package/dist/javascript/templating/capture.js +461 -0
  34. package/dist/javascript/templating/capture.js.map +1 -0
  35. package/dist/javascript/templating/comparator.d.ts +171 -0
  36. package/dist/javascript/templating/comparator.d.ts.map +1 -0
  37. package/dist/javascript/templating/comparator.js +1221 -0
  38. package/dist/javascript/templating/comparator.js.map +1 -0
  39. package/dist/javascript/templating/engine.d.ts +108 -0
  40. package/dist/javascript/templating/engine.d.ts.map +1 -0
  41. package/dist/javascript/templating/engine.js +661 -0
  42. package/dist/javascript/templating/engine.js.map +1 -0
  43. package/dist/javascript/templating/index.d.ts +6 -0
  44. package/dist/javascript/templating/index.d.ts.map +1 -0
  45. package/dist/javascript/templating/index.js +44 -0
  46. package/dist/javascript/templating/index.js.map +1 -0
  47. package/dist/javascript/templating/pattern.d.ts +276 -0
  48. package/dist/javascript/templating/pattern.d.ts.map +1 -0
  49. package/dist/javascript/templating/pattern.js +952 -0
  50. package/dist/javascript/templating/pattern.js.map +1 -0
  51. package/dist/javascript/templating/placeholder-replacement.d.ts +83 -0
  52. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -0
  53. package/dist/javascript/templating/placeholder-replacement.js +467 -0
  54. package/dist/javascript/templating/placeholder-replacement.js.map +1 -0
  55. package/dist/javascript/templating/rewrite.d.ts +84 -0
  56. package/dist/javascript/templating/rewrite.d.ts.map +1 -0
  57. package/dist/javascript/templating/rewrite.js +208 -0
  58. package/dist/javascript/templating/rewrite.js.map +1 -0
  59. package/dist/javascript/templating/template.d.ts +230 -0
  60. package/dist/javascript/templating/template.d.ts.map +1 -0
  61. package/dist/javascript/templating/template.js +367 -0
  62. package/dist/javascript/templating/template.js.map +1 -0
  63. package/dist/javascript/templating/types.d.ts +610 -0
  64. package/dist/javascript/templating/types.d.ts.map +1 -0
  65. package/dist/javascript/templating/types.js +3 -0
  66. package/dist/javascript/templating/types.js.map +1 -0
  67. package/dist/javascript/templating/utils.d.ts +135 -0
  68. package/dist/javascript/templating/utils.d.ts.map +1 -0
  69. package/dist/javascript/templating/utils.js +251 -0
  70. package/dist/javascript/templating/utils.js.map +1 -0
  71. package/dist/javascript/type-mapping.d.ts.map +1 -1
  72. package/dist/javascript/type-mapping.js +21 -11
  73. package/dist/javascript/type-mapping.js.map +1 -1
  74. package/dist/json/rpc.js +2 -2
  75. package/dist/json/rpc.js.map +1 -1
  76. package/dist/recipe/order-imports.js.map +1 -1
  77. package/dist/test/rewrite-test.d.ts.map +1 -1
  78. package/dist/test/rewrite-test.js +10 -6
  79. package/dist/test/rewrite-test.js.map +1 -1
  80. package/dist/version.txt +1 -1
  81. package/dist/visitor.d.ts +4 -4
  82. package/dist/visitor.d.ts.map +1 -1
  83. package/dist/visitor.js +8 -3
  84. package/dist/visitor.js.map +1 -1
  85. package/package.json +5 -2
  86. package/src/java/tree.ts +10 -3
  87. package/src/java/type-visitor.ts +1 -1
  88. package/src/java/visitor.ts +11 -5
  89. package/src/javascript/assertions.ts +9 -3
  90. package/src/javascript/comparator.ts +1095 -3373
  91. package/src/javascript/format.ts +72 -33
  92. package/src/javascript/index.ts +2 -1
  93. package/src/javascript/parser.ts +67 -45
  94. package/src/javascript/templating/capture.ts +595 -0
  95. package/src/javascript/templating/comparator.ts +1383 -0
  96. package/src/javascript/templating/engine.ts +750 -0
  97. package/src/javascript/templating/index.ts +67 -0
  98. package/src/javascript/templating/pattern.ts +1101 -0
  99. package/src/javascript/templating/placeholder-replacement.ts +475 -0
  100. package/src/javascript/templating/rewrite.ts +229 -0
  101. package/src/javascript/templating/template.ts +414 -0
  102. package/src/javascript/templating/types.ts +674 -0
  103. package/src/javascript/templating/utils.ts +298 -0
  104. package/src/javascript/type-mapping.ts +20 -11
  105. package/src/json/rpc.ts +2 -2
  106. package/src/recipe/order-imports.ts +1 -1
  107. package/src/test/rewrite-test.ts +12 -7
  108. package/src/visitor.ts +14 -6
  109. package/dist/javascript/templating.d.ts +0 -265
  110. package/dist/javascript/templating.d.ts.map +0 -1
  111. package/dist/javascript/templating.js +0 -1027
  112. package/dist/javascript/templating.js.map +0 -1
  113. package/src/javascript/templating.ts +0 -1226
@@ -0,0 +1,84 @@
1
+ import { ExecutionContext, Recipe } from '../..';
2
+ import { RewriteRule, RewriteConfig } from './types';
3
+ /**
4
+ * Creates a replacement rule using a capture context and configuration.
5
+ *
6
+ * @param builderFn Function that takes a capture context and returns before/after configuration
7
+ * @returns A replacement rule that can be applied to AST nodes
8
+ *
9
+ * @example
10
+ * // Single pattern
11
+ * const swapOperands = rewrite(() => {
12
+ * const { left, right } = { left: capture(), right: capture() };
13
+ * return {
14
+ * before: pattern`${left} + ${right}`,
15
+ * after: template`${right} + ${left}`
16
+ * };
17
+ * });
18
+ *
19
+ * @example
20
+ * // Multiple patterns
21
+ * const normalizeComparisons = rewrite(() => {
22
+ * const { left, right } = { left: capture(), right: capture() };
23
+ * return {
24
+ * before: [
25
+ * pattern`${left} == ${right}`,
26
+ * pattern`${left} === ${right}`
27
+ * ],
28
+ * after: template`${left} === ${right}`
29
+ * };
30
+ * });
31
+ *
32
+ * @example
33
+ * // Using in a visitor - IMPORTANT: use `|| node` to handle undefined when no match
34
+ * class MyVisitor extends JavaScriptVisitor<any> {
35
+ * override async visitBinary(binary: J.Binary, p: any): Promise<J | undefined> {
36
+ * const rule = rewrite(() => ({
37
+ * before: pattern`${capture('a')} + ${capture('b')}`,
38
+ * after: template`${capture('b')} + ${capture('a')}`
39
+ * }));
40
+ * // tryOn() returns undefined if no pattern matches, so always use || node
41
+ * return await rule.tryOn(this.cursor, binary) || binary;
42
+ * }
43
+ * }
44
+ */
45
+ export declare function rewrite(builderFn: () => RewriteConfig): RewriteRule;
46
+ /**
47
+ * Creates a RewriteRule from a Recipe by using its editor visitor.
48
+ *
49
+ * This allows recipes to be used in the same chaining pattern as other rewrite rules,
50
+ * enabling composition with `andThen()`.
51
+ *
52
+ * @param recipe The recipe whose editor will be used to transform nodes
53
+ * @param ctx The execution context to pass to the recipe's editor
54
+ * @returns A RewriteRule that applies the recipe's editor to nodes
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * class MyRecipe extends Recipe {
59
+ * name = "my.recipe";
60
+ * displayName = "My Recipe";
61
+ * description = "Transforms code.";
62
+ *
63
+ * async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
64
+ * return new MyVisitor();
65
+ * }
66
+ * }
67
+ *
68
+ * // In a visitor:
69
+ * override async visitBinary(binary: J.Binary, p: ExecutionContext): Promise<J | undefined> {
70
+ * const rule1 = rewrite(() => ({
71
+ * before: pattern`${capture('a')} + ${capture('b')}`,
72
+ * after: template`${capture('b')} + ${capture('a')}`
73
+ * }));
74
+ *
75
+ * const rule2 = fromRecipe(new MyRecipe(), p);
76
+ *
77
+ * // Chain the pattern-based rule with the recipe
78
+ * const combined = rule1.andThen(rule2);
79
+ * return await combined.tryOn(this.cursor, binary) || binary;
80
+ * }
81
+ * ```
82
+ */
83
+ export declare const fromRecipe: (recipe: Recipe, ctx: ExecutionContext) => RewriteRule;
84
+ //# sourceMappingURL=rewrite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../../../src/javascript/templating/rewrite.ts"],"names":[],"mappings":"AAeA,OAAO,EAAS,gBAAgB,EAAE,MAAM,EAAC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,SAAS,CAAC;AAkGnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,OAAO,CACnB,SAAS,EAAE,MAAM,aAAa,GAC/B,WAAW,CAcb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,EAAE,KAAK,gBAAgB,KAAG,WAgBlE,CAAA"}
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.fromRecipe = void 0;
13
+ exports.rewrite = rewrite;
14
+ /**
15
+ * Implementation of a replacement rule.
16
+ */
17
+ class RewriteRuleImpl {
18
+ constructor(before, after, where, whereNot) {
19
+ this.before = before;
20
+ this.after = after;
21
+ this.where = where;
22
+ this.whereNot = whereNot;
23
+ }
24
+ tryOn(cursor, node) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ for (const pattern of this.before) {
27
+ // Pass cursor to pattern.match() for context-aware capture constraints
28
+ const match = yield pattern.match(node, cursor);
29
+ if (match) {
30
+ // Evaluate context predicates after structural match
31
+ if (this.where) {
32
+ const whereResult = yield this.where(node, cursor);
33
+ if (!whereResult) {
34
+ continue; // Pattern matched but context doesn't, try next pattern
35
+ }
36
+ }
37
+ if (this.whereNot) {
38
+ const whereNotResult = yield this.whereNot(node, cursor);
39
+ if (whereNotResult) {
40
+ continue; // Pattern matched but context is excluded, try next pattern
41
+ }
42
+ }
43
+ // Apply transformation
44
+ let result;
45
+ if (typeof this.after === 'function') {
46
+ // Call the function to get a template, then apply it
47
+ const template = this.after(match);
48
+ result = yield template.apply(cursor, node, match);
49
+ }
50
+ else {
51
+ // Use template.apply() as before
52
+ result = yield this.after.apply(cursor, node, match);
53
+ }
54
+ if (result) {
55
+ return result;
56
+ }
57
+ }
58
+ }
59
+ // Return undefined if no patterns match or all context checks failed
60
+ return undefined;
61
+ });
62
+ }
63
+ andThen(next) {
64
+ const first = this;
65
+ return new (class extends RewriteRuleImpl {
66
+ constructor() {
67
+ // Pass empty patterns and a function that will never be called
68
+ // since we override tryOn
69
+ super([], () => undefined);
70
+ }
71
+ tryOn(cursor, node) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ const firstResult = yield first.tryOn(cursor, node);
74
+ if (firstResult !== undefined) {
75
+ const secondResult = yield next.tryOn(cursor, firstResult);
76
+ return secondResult !== null && secondResult !== void 0 ? secondResult : firstResult;
77
+ }
78
+ return undefined;
79
+ });
80
+ }
81
+ })();
82
+ }
83
+ orElse(alternative) {
84
+ const first = this;
85
+ return new (class extends RewriteRuleImpl {
86
+ constructor() {
87
+ // Pass empty patterns and a function that will never be called
88
+ // since we override tryOn
89
+ super([], () => undefined);
90
+ }
91
+ tryOn(cursor, node) {
92
+ return __awaiter(this, void 0, void 0, function* () {
93
+ const firstResult = yield first.tryOn(cursor, node);
94
+ if (firstResult !== undefined) {
95
+ return firstResult;
96
+ }
97
+ return yield alternative.tryOn(cursor, node);
98
+ });
99
+ }
100
+ })();
101
+ }
102
+ }
103
+ /**
104
+ * Creates a replacement rule using a capture context and configuration.
105
+ *
106
+ * @param builderFn Function that takes a capture context and returns before/after configuration
107
+ * @returns A replacement rule that can be applied to AST nodes
108
+ *
109
+ * @example
110
+ * // Single pattern
111
+ * const swapOperands = rewrite(() => {
112
+ * const { left, right } = { left: capture(), right: capture() };
113
+ * return {
114
+ * before: pattern`${left} + ${right}`,
115
+ * after: template`${right} + ${left}`
116
+ * };
117
+ * });
118
+ *
119
+ * @example
120
+ * // Multiple patterns
121
+ * const normalizeComparisons = rewrite(() => {
122
+ * const { left, right } = { left: capture(), right: capture() };
123
+ * return {
124
+ * before: [
125
+ * pattern`${left} == ${right}`,
126
+ * pattern`${left} === ${right}`
127
+ * ],
128
+ * after: template`${left} === ${right}`
129
+ * };
130
+ * });
131
+ *
132
+ * @example
133
+ * // Using in a visitor - IMPORTANT: use `|| node` to handle undefined when no match
134
+ * class MyVisitor extends JavaScriptVisitor<any> {
135
+ * override async visitBinary(binary: J.Binary, p: any): Promise<J | undefined> {
136
+ * const rule = rewrite(() => ({
137
+ * before: pattern`${capture('a')} + ${capture('b')}`,
138
+ * after: template`${capture('b')} + ${capture('a')}`
139
+ * }));
140
+ * // tryOn() returns undefined if no pattern matches, so always use || node
141
+ * return await rule.tryOn(this.cursor, binary) || binary;
142
+ * }
143
+ * }
144
+ */
145
+ function rewrite(builderFn) {
146
+ const config = builderFn();
147
+ // Ensure we have valid before and after properties
148
+ if (!config.before || !config.after) {
149
+ throw new Error('Builder function must return an object with before and after properties');
150
+ }
151
+ return new RewriteRuleImpl(Array.isArray(config.before) ? config.before : [config.before], config.after, config.where, config.whereNot);
152
+ }
153
+ /**
154
+ * Creates a RewriteRule from a Recipe by using its editor visitor.
155
+ *
156
+ * This allows recipes to be used in the same chaining pattern as other rewrite rules,
157
+ * enabling composition with `andThen()`.
158
+ *
159
+ * @param recipe The recipe whose editor will be used to transform nodes
160
+ * @param ctx The execution context to pass to the recipe's editor
161
+ * @returns A RewriteRule that applies the recipe's editor to nodes
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * class MyRecipe extends Recipe {
166
+ * name = "my.recipe";
167
+ * displayName = "My Recipe";
168
+ * description = "Transforms code.";
169
+ *
170
+ * async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
171
+ * return new MyVisitor();
172
+ * }
173
+ * }
174
+ *
175
+ * // In a visitor:
176
+ * override async visitBinary(binary: J.Binary, p: ExecutionContext): Promise<J | undefined> {
177
+ * const rule1 = rewrite(() => ({
178
+ * before: pattern`${capture('a')} + ${capture('b')}`,
179
+ * after: template`${capture('b')} + ${capture('a')}`
180
+ * }));
181
+ *
182
+ * const rule2 = fromRecipe(new MyRecipe(), p);
183
+ *
184
+ * // Chain the pattern-based rule with the recipe
185
+ * const combined = rule1.andThen(rule2);
186
+ * return await combined.tryOn(this.cursor, binary) || binary;
187
+ * }
188
+ * ```
189
+ */
190
+ const fromRecipe = (recipe, ctx) => {
191
+ return new (class extends RewriteRuleImpl {
192
+ constructor() {
193
+ // Pass empty patterns and a function that will never be called
194
+ // since we override tryOn
195
+ super([], () => undefined);
196
+ }
197
+ tryOn(cursor, tree) {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ const visitor = yield recipe.editor();
200
+ const result = yield visitor.visit(tree, ctx, cursor);
201
+ // Return undefined if the visitor didn't change the node
202
+ return result !== tree ? result : undefined;
203
+ });
204
+ }
205
+ })();
206
+ };
207
+ exports.fromRecipe = fromRecipe;
208
+ //# sourceMappingURL=rewrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewrite.js","sourceRoot":"","sources":["../../../src/javascript/templating/rewrite.ts"],"names":[],"mappings":";;;;;;;;;;;;AA6JA,0BAgBC;AAxJD;;GAEG;AACH,MAAM,eAAe;IACjB,YACqB,MAAiB,EACjB,KAAoD,EACpD,KAA+D,EAC/D,QAAkE;QAHlE,WAAM,GAAN,MAAM,CAAW;QACjB,UAAK,GAAL,KAAK,CAA+C;QACpD,UAAK,GAAL,KAAK,CAA0D;QAC/D,aAAQ,GAAR,QAAQ,CAA0D;IAEvF,CAAC;IAEK,KAAK,CAAC,MAAc,EAAE,IAAO;;YAC/B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChC,uEAAuE;gBACvE,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,IAAI,KAAK,EAAE,CAAC;oBACR,qDAAqD;oBACrD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;wBACb,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;wBACnD,IAAI,CAAC,WAAW,EAAE,CAAC;4BACf,SAAS,CAAC,wDAAwD;wBACtE,CAAC;oBACL,CAAC;oBAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAChB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;wBACzD,IAAI,cAAc,EAAE,CAAC;4BACjB,SAAS,CAAC,4DAA4D;wBAC1E,CAAC;oBACL,CAAC;oBAED,uBAAuB;oBACvB,IAAI,MAAqB,CAAC;oBAE1B,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;wBACnC,qDAAqD;wBACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;wBACnC,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;oBACvD,CAAC;yBAAM,CAAC;wBACJ,iCAAiC;wBACjC,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;oBACzD,CAAC;oBAED,IAAI,MAAM,EAAE,CAAC;wBACT,OAAO,MAAM,CAAC;oBAClB,CAAC;gBACL,CAAC;YACL,CAAC;YAED,qEAAqE;YACrE,OAAO,SAAS,CAAC;QACrB,CAAC;KAAA;IAED,OAAO,CAAC,IAAiB;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC;QACnB,OAAO,IAAI,CAAC,KAAM,SAAQ,eAAe;YACrC;gBACI,+DAA+D;gBAC/D,0BAA0B;gBAC1B,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAgC,CAAC,CAAC;YACtD,CAAC;YAEK,KAAK,CAAC,MAAc,EAAE,IAAO;;oBAC/B,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBACpD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;wBAC5B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;wBAC3D,OAAO,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,WAAW,CAAC;oBACvC,CAAC;oBACD,OAAO,SAAS,CAAC;gBACrB,CAAC;aAAA;SACJ,CAAC,EAAE,CAAC;IACT,CAAC;IAED,MAAM,CAAC,WAAwB;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC;QACnB,OAAO,IAAI,CAAC,KAAM,SAAQ,eAAe;YACrC;gBACI,+DAA+D;gBAC/D,0BAA0B;gBAC1B,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAgC,CAAC,CAAC;YACtD,CAAC;YAEK,KAAK,CAAC,MAAc,EAAE,IAAO;;oBAC/B,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBACpD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;wBAC5B,OAAO,WAAW,CAAC;oBACvB,CAAC;oBACD,OAAO,MAAM,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACjD,CAAC;aAAA;SACJ,CAAC,EAAE,CAAC;IACT,CAAC;CACJ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,SAAgB,OAAO,CACnB,SAA8B;IAE9B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,mDAAmD;IACnD,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC/F,CAAC;IAED,OAAO,IAAI,eAAe,CACtB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAC9D,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,QAAQ,CAClB,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACI,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,GAAqB,EAAe,EAAE;IAC7E,OAAO,IAAI,CAAC,KAAM,SAAQ,eAAe;QACrC;YACI,+DAA+D;YAC/D,0BAA0B;YAC1B,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAgC,CAAC,CAAC;QACtD,CAAC;QAEK,KAAK,CAAC,MAAc,EAAE,IAAO;;gBAC/B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;gBACtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAI,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBAEzD,yDAAyD;gBACzD,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YAChD,CAAC;SAAA;KACJ,CAAC,EAAE,CAAC;AACT,CAAC,CAAA;AAhBY,QAAA,UAAU,cAgBtB"}
@@ -0,0 +1,230 @@
1
+ import { Cursor, Tree } from '../..';
2
+ import { J } from '../../java';
3
+ import { Capture, Parameter, TemplateOptions, TemplateParameter } from './types';
4
+ import { JS } from '..';
5
+ /**
6
+ * Coordinates for template application.
7
+ */
8
+ type JavaCoordinates = {
9
+ tree?: Tree;
10
+ loc?: JavaCoordinates.Location;
11
+ mode?: JavaCoordinates.Mode;
12
+ };
13
+ declare namespace JavaCoordinates {
14
+ type Location = 'EXPRESSION_PREFIX' | 'STATEMENT_PREFIX' | 'BLOCK_END';
15
+ enum Mode {
16
+ Before = 0,
17
+ After = 1,
18
+ Replace = 2
19
+ }
20
+ }
21
+ /**
22
+ * Builder for creating templates programmatically.
23
+ * Use when template structure is not known at compile time.
24
+ *
25
+ * @example
26
+ * // Conditional construction
27
+ * const builder = Template.builder().code('function foo(x) {');
28
+ * if (needsValidation) {
29
+ * builder.code('if (typeof x !== "number") throw new Error("Invalid");');
30
+ * }
31
+ * builder.code('return x * 2; }');
32
+ * const tmpl = builder.build();
33
+ *
34
+ * @example
35
+ * // Composition from fragments
36
+ * function createWrapper(innerBody: Capture): Template {
37
+ * return Template.builder()
38
+ * .code('function wrapper() { try { ')
39
+ * .param(innerBody)
40
+ * .code(' } catch(e) { console.error(e); } }')
41
+ * .build();
42
+ * }
43
+ */
44
+ export declare class TemplateBuilder {
45
+ private parts;
46
+ private params;
47
+ /**
48
+ * Adds a static string part to the template.
49
+ *
50
+ * @param str The string to add
51
+ * @returns This builder for chaining
52
+ */
53
+ code(str: string): this;
54
+ /**
55
+ * Adds a parameter to the template.
56
+ *
57
+ * @param value The parameter value (Capture, Tree, or primitive)
58
+ * @returns This builder for chaining
59
+ */
60
+ param(value: TemplateParameter): this;
61
+ /**
62
+ * Builds the template from accumulated parts and parameters.
63
+ *
64
+ * @returns A Template instance
65
+ */
66
+ build(): Template;
67
+ }
68
+ /**
69
+ * Template for creating AST nodes.
70
+ *
71
+ * This class provides the public API for template generation.
72
+ * The actual templating logic is handled by the internal TemplateEngine.
73
+ *
74
+ * Templates can reference captures from patterns, and you can access properties
75
+ * of captured nodes using dot notation. This allows you to extract and insert
76
+ * specific subtrees from matched AST nodes.
77
+ *
78
+ * @example
79
+ * // Generate a literal AST node
80
+ * const result = template`2`.apply(cursor, coordinates);
81
+ *
82
+ * @example
83
+ * // Generate an AST node with a parameter
84
+ * const result = template`${capture()}`.apply(cursor, coordinates);
85
+ *
86
+ * @example
87
+ * // Access properties of captured nodes in templates
88
+ * const method = capture<J.MethodInvocation>('method');
89
+ * const pat = pattern`foo(${method})`;
90
+ * const tmpl = template`bar(${method.name})`; // Access the 'name' property
91
+ *
92
+ * const match = await pat.match(someNode);
93
+ * if (match) {
94
+ * // The template will insert just the 'name' subtree from the captured method
95
+ * const result = await tmpl.apply(cursor, someNode, match);
96
+ * }
97
+ *
98
+ * @example
99
+ * // Deep property access chains
100
+ * const method = capture<J.MethodInvocation>('method');
101
+ * template`console.log(${method.name.simpleName})` // Navigate multiple properties
102
+ *
103
+ * @example
104
+ * // Array element access
105
+ * const invocation = capture<J.MethodInvocation>('invocation');
106
+ * template`bar(${invocation.arguments.elements[0].element})` // Access array elements
107
+ */
108
+ export declare class Template {
109
+ private readonly templateParts;
110
+ private readonly parameters;
111
+ private options;
112
+ private _cachedTemplate?;
113
+ /**
114
+ * Creates a new builder for constructing templates programmatically.
115
+ *
116
+ * @returns A new TemplateBuilder instance
117
+ *
118
+ * @example
119
+ * const tmpl = Template.builder()
120
+ * .code('function foo() {')
121
+ * .code('return ')
122
+ * .param(capture('value'))
123
+ * .code('; }')
124
+ * .build();
125
+ */
126
+ static builder(): TemplateBuilder;
127
+ /**
128
+ * Creates a new template.
129
+ *
130
+ * @param templateParts The string parts of the template
131
+ * @param parameters The parameters between the string parts
132
+ */
133
+ constructor(templateParts: TemplateStringsArray, parameters: Parameter[]);
134
+ /**
135
+ * Configures this template with additional options.
136
+ *
137
+ * @param options Configuration options
138
+ * @returns This template for method chaining
139
+ *
140
+ * @example
141
+ * template`isDate(${capture('date')})`
142
+ * .configure({
143
+ * context: ['import { isDate } from "util"'],
144
+ * dependencies: { 'util': '^1.0.0' }
145
+ * })
146
+ */
147
+ configure(options: TemplateOptions): Template;
148
+ /**
149
+ * Gets the template tree for this template, using two-level caching:
150
+ * - Level 1: Instance cache (this._cachedTemplate) - fastest, no lookup needed
151
+ * - Level 2: Global cache (globalAstCache) - fast, shared across all templates
152
+ * - Level 3: TemplateEngine - slow, parses and processes the template
153
+ *
154
+ * Most parameters use placeholders that are replaced during application, so templates
155
+ * with the same structure share cached ASTs. However, raw() parameters are spliced at
156
+ * construction time, so their values must be included in the cache key.
157
+ *
158
+ * @returns The cached or newly computed template tree
159
+ * @internal
160
+ */
161
+ getTemplateTree(): Promise<JS.CompilationUnit>;
162
+ /**
163
+ * Applies this template and returns the resulting tree.
164
+ *
165
+ * @param cursor The cursor pointing to the current location in the AST
166
+ * @param tree Input tree
167
+ * @param values values for parameters in template
168
+ * @returns A Promise resolving to the generated AST node
169
+ */
170
+ apply(cursor: Cursor, tree: J, values?: Map<Capture | string, J> | Pick<Map<string, J>, 'get'> | Record<string, J>): Promise<J | undefined>;
171
+ }
172
+ /**
173
+ * Tagged template function for creating templates that generate AST nodes.
174
+ *
175
+ * Templates support property access on captures from patterns, allowing you to
176
+ * extract and insert specific subtrees from matched AST nodes. Use dot notation
177
+ * to navigate properties (e.g., `method.name`) or array bracket notation to
178
+ * access array elements (e.g., `args.elements[0].element`).
179
+ *
180
+ * Templates can also accept AST wrapper types directly:
181
+ * - J.RightPadded<T>: The element will be extracted and inserted
182
+ * - J.RightPadded<T>[]: Elements will be expanded in place
183
+ * - J.Container<T>: Elements will be expanded in place
184
+ *
185
+ * @param strings The string parts of the template
186
+ * @param parameters The parameters between the string parts (Capture, CaptureValue, TemplateParam, Tree, Tree[], J.RightPadded, J.RightPadded[], or J.Container)
187
+ * @returns A Template object that can be applied to generate AST nodes
188
+ *
189
+ * @example
190
+ * // Simple template with literal
191
+ * const tmpl = template`console.log("hello")`;
192
+ * const result = await tmpl.apply(cursor, node);
193
+ *
194
+ * @example
195
+ * // Template with capture - matches captured value from pattern
196
+ * const expr = capture('expr');
197
+ * const pat = pattern`foo(${expr})`;
198
+ * const tmpl = template`bar(${expr})`;
199
+ *
200
+ * const match = await pat.match(node);
201
+ * if (match) {
202
+ * const result = await tmpl.apply(cursor, node, match);
203
+ * }
204
+ *
205
+ * @example
206
+ * // Property access on captures - extract subtrees
207
+ * const method = capture<J.MethodInvocation>('method');
208
+ * const pat = pattern`foo(${method})`;
209
+ * // Access the 'name' property of the captured method invocation
210
+ * const tmpl = template`bar(${method.name})`;
211
+ *
212
+ * @example
213
+ * // Deep property chains
214
+ * const method = capture<J.MethodInvocation>('method');
215
+ * template`console.log(${method.name.simpleName})`
216
+ *
217
+ * @example
218
+ * // Array element access
219
+ * const invocation = capture<J.MethodInvocation>('invocation');
220
+ * template`bar(${invocation.arguments.elements[0].element})`
221
+ *
222
+ * @example
223
+ * // Using J.RightPadded and J.Container directly
224
+ * const selectExpr = method.select; // J.RightPadded<Expression>
225
+ * const args = method.arguments; // J.Container<Expression>
226
+ * template`${selectExpr}.newMethod(${args})`
227
+ */
228
+ export declare function template(strings: TemplateStringsArray, ...parameters: TemplateParameter[]): Template;
229
+ export type { JavaCoordinates };
230
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/javascript/templating/template.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,OAAO,CAAC;AACnC,OAAO,EAAC,CAAC,EAAC,MAAM,YAAY,CAAC;AAC7B,OAAO,EAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAK/E,OAAO,EAAC,EAAE,EAAC,MAAM,IAAI,CAAC;AAEtB;;GAEG;AACH,KAAK,eAAe,GAAG;IACnB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,GAAG,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,EAAE,eAAe,CAAC,IAAI,CAAC;CAC/B,CAAC;AAEF,kBAAU,eAAe,CAAC;IAEtB,KAAY,QAAQ,GAAG,mBAAmB,GAAG,kBAAkB,GAAG,WAAW,CAAC;IAE9E,KAAY,IAAI;QACZ,MAAM,IAAA;QACN,KAAK,IAAA;QACL,OAAO,IAAA;KACV;CACJ;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,eAAe;IACxB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAA2B;IAEzC;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAcvB;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAWrC;;;;OAIG;IACH,KAAK,IAAI,QAAQ;CAiBpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,QAAQ;IA4Bb,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU;IA5B/B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,eAAe,CAAC,CAAI;IAE5B;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,OAAO,IAAI,eAAe;IAIjC;;;;;OAKG;gBAEkB,aAAa,EAAE,oBAAoB,EACnC,UAAU,EAAE,SAAS,EAAE;IAI5C;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ;IAO7C;;;;;;;;;;;;OAYG;IACG,eAAe,IAAI,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC;IA+CpD;;;;;;;OAOG;IACG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;CAoDpJ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,UAAU,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAQpG;AAED,YAAY,EAAC,eAAe,EAAC,CAAC"}