@openrewrite/rewrite 8.67.0-20251106-160325 → 8.67.0-20251107-103550
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.
- package/dist/java/tree.d.ts +2 -0
- package/dist/java/tree.d.ts.map +1 -1
- package/dist/java/tree.js +5 -1
- package/dist/java/tree.js.map +1 -1
- package/dist/javascript/assertions.js +2 -2
- package/dist/javascript/assertions.js.map +1 -1
- package/dist/javascript/format.js +1 -1
- package/dist/javascript/format.js.map +1 -1
- package/dist/javascript/templating/engine.d.ts +41 -25
- package/dist/javascript/templating/engine.d.ts.map +1 -1
- package/dist/javascript/templating/engine.js +378 -92
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/pattern.d.ts +11 -0
- package/dist/javascript/templating/pattern.d.ts.map +1 -1
- package/dist/javascript/templating/pattern.js +36 -295
- package/dist/javascript/templating/pattern.js.map +1 -1
- package/dist/javascript/templating/placeholder-replacement.d.ts +1 -1
- package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
- package/dist/javascript/templating/rewrite.d.ts +17 -11
- package/dist/javascript/templating/rewrite.d.ts.map +1 -1
- package/dist/javascript/templating/rewrite.js +17 -11
- package/dist/javascript/templating/rewrite.js.map +1 -1
- package/dist/javascript/templating/template.d.ts +17 -3
- package/dist/javascript/templating/template.d.ts.map +1 -1
- package/dist/javascript/templating/template.js +45 -5
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/templating/types.d.ts +36 -13
- package/dist/javascript/templating/types.d.ts.map +1 -1
- package/dist/javascript/templating/utils.d.ts +41 -22
- package/dist/javascript/templating/utils.d.ts.map +1 -1
- package/dist/javascript/templating/utils.js +111 -76
- package/dist/javascript/templating/utils.js.map +1 -1
- package/dist/version.txt +1 -1
- package/package.json +3 -1
- package/src/java/tree.ts +2 -0
- package/src/javascript/assertions.ts +1 -1
- package/src/javascript/format.ts +1 -1
- package/src/javascript/templating/engine.ts +439 -105
- package/src/javascript/templating/pattern.ts +55 -322
- package/src/javascript/templating/placeholder-replacement.ts +1 -1
- package/src/javascript/templating/rewrite.ts +17 -11
- package/src/javascript/templating/template.ts +66 -11
- package/src/javascript/templating/types.ts +37 -13
- package/src/javascript/templating/utils.ts +114 -81
|
@@ -13,15 +13,12 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import ts from 'typescript';
|
|
17
16
|
import {Cursor} from '../..';
|
|
18
17
|
import {J} from '../../java';
|
|
19
18
|
import {JS} from '../index';
|
|
20
|
-
import {JavaScriptParser} from '../parser';
|
|
21
|
-
import {DependencyWorkspace} from '../dependency-workspace';
|
|
22
19
|
import {Marker, Markers} from '../../markers';
|
|
23
20
|
import {randomId} from '../../uuid';
|
|
24
|
-
import {VariadicOptions
|
|
21
|
+
import {VariadicOptions} from './types';
|
|
25
22
|
|
|
26
23
|
/**
|
|
27
24
|
* Internal storage value type for pattern match captures.
|
|
@@ -38,102 +35,86 @@ export type CaptureStorageValue = J | J.RightPadded<J> | J[] | J.RightPadded<J>[
|
|
|
38
35
|
export const WRAPPERS_MAP_SYMBOL = Symbol('wrappersMap');
|
|
39
36
|
|
|
40
37
|
/**
|
|
41
|
-
*
|
|
38
|
+
* Shared wrapper function name used by both patterns and templates.
|
|
39
|
+
* Using the same name allows cache sharing when pattern and template code is identical.
|
|
42
40
|
*/
|
|
43
|
-
|
|
41
|
+
export const WRAPPER_FUNCTION_NAME = '__WRAPPER__';
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
|
-
*
|
|
44
|
+
* Simple LRU (Least Recently Used) cache implementation using Map's insertion order.
|
|
45
|
+
* JavaScript Map maintains insertion order, so the first entry is the oldest.
|
|
47
46
|
*
|
|
48
|
-
*
|
|
47
|
+
* Used by both Pattern and Template caching to provide bounded memory usage.
|
|
49
48
|
*/
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Cache for compiled templates and patterns.
|
|
56
|
-
* Stores parsed ASTs to avoid expensive re-parsing and dependency resolution.
|
|
57
|
-
*/
|
|
58
|
-
export class TemplateCache {
|
|
59
|
-
private cache = new Map<string, JS.CompilationUnit>();
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Generates a cache key from template string, captures, and options.
|
|
63
|
-
*/
|
|
64
|
-
private generateKey(
|
|
65
|
-
templateString: string,
|
|
66
|
-
captures: (Capture | Any<any>)[],
|
|
67
|
-
contextStatements: string[],
|
|
68
|
-
dependencies: Record<string, string>
|
|
69
|
-
): string {
|
|
70
|
-
// Use the actual template string (with placeholders) as the primary key
|
|
71
|
-
const templateKey = templateString;
|
|
72
|
-
|
|
73
|
-
// Capture names
|
|
74
|
-
const capturesKey = captures.map(c => c.getName()).join(',');
|
|
75
|
-
|
|
76
|
-
// Context statements
|
|
77
|
-
const contextKey = contextStatements.join(';');
|
|
78
|
-
|
|
79
|
-
// Dependencies
|
|
80
|
-
const depsKey = JSON.stringify(dependencies || {});
|
|
49
|
+
export class LRUCache<K, V> {
|
|
50
|
+
private cache = new Map<K, V>();
|
|
81
51
|
|
|
82
|
-
|
|
52
|
+
constructor(private maxSize: number) {
|
|
83
53
|
}
|
|
84
54
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
contextStatements: string[],
|
|
92
|
-
dependencies: Record<string, string>
|
|
93
|
-
): Promise<JS.CompilationUnit> {
|
|
94
|
-
const key = this.generateKey(templateString, captures, contextStatements, dependencies);
|
|
95
|
-
|
|
96
|
-
let cu = this.cache.get(key);
|
|
97
|
-
if (cu) {
|
|
98
|
-
return cu;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Create workspace if dependencies are provided
|
|
102
|
-
// DependencyWorkspace has its own cache, so multiple templates with
|
|
103
|
-
// the same dependencies will automatically share the same workspace
|
|
104
|
-
let workspaceDir: string | undefined;
|
|
105
|
-
if (dependencies && Object.keys(dependencies).length > 0) {
|
|
106
|
-
workspaceDir = await DependencyWorkspace.getOrCreateWorkspace(dependencies);
|
|
55
|
+
get(key: K): V | undefined {
|
|
56
|
+
const value = this.cache.get(key);
|
|
57
|
+
if (value !== undefined) {
|
|
58
|
+
// Move to end (most recently used)
|
|
59
|
+
this.cache.delete(key);
|
|
60
|
+
this.cache.set(key, value);
|
|
107
61
|
}
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
108
64
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
: templateString;
|
|
65
|
+
set(key: K, value: V): void {
|
|
66
|
+
// Remove if exists (to update position)
|
|
67
|
+
this.cache.delete(key);
|
|
113
68
|
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
const parser = new JavaScriptParser({
|
|
117
|
-
relativeTo: workspaceDir,
|
|
118
|
-
sourceFileCache: templateSourceFileCache
|
|
119
|
-
});
|
|
120
|
-
const parseGenerator = parser.parse({text: fullTemplateString, sourcePath: 'template.ts'});
|
|
121
|
-
cu = (await parseGenerator.next()).value as JS.CompilationUnit;
|
|
69
|
+
// Add to end
|
|
70
|
+
this.cache.set(key, value);
|
|
122
71
|
|
|
123
|
-
|
|
124
|
-
|
|
72
|
+
// Evict oldest if over capacity
|
|
73
|
+
if (this.cache.size > this.maxSize) {
|
|
74
|
+
const iterator = this.cache.keys();
|
|
75
|
+
const firstEntry = iterator.next();
|
|
76
|
+
if (!firstEntry.done) {
|
|
77
|
+
this.cache.delete(firstEntry.value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
125
80
|
}
|
|
126
81
|
|
|
127
|
-
/**
|
|
128
|
-
* Clears the cache.
|
|
129
|
-
*/
|
|
130
82
|
clear(): void {
|
|
131
83
|
this.cache.clear();
|
|
132
84
|
}
|
|
133
85
|
}
|
|
134
86
|
|
|
135
|
-
|
|
136
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Shared global LRU cache for both pattern and template ASTs.
|
|
89
|
+
* When pattern and template code is identical, they share the same cached AST.
|
|
90
|
+
* This mirrors JavaTemplate's unified approach in the Java implementation.
|
|
91
|
+
* Bounded to 100 entries using LRU eviction.
|
|
92
|
+
*/
|
|
93
|
+
export const globalAstCache = new LRUCache<string, J>(100);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Generates a cache key for template/pattern processing.
|
|
97
|
+
* Used by both Pattern and Template for consistent cache key generation.
|
|
98
|
+
*
|
|
99
|
+
* @param templateParts The template string parts
|
|
100
|
+
* @param itemsKey String representing the captures/parameters (comma-separated)
|
|
101
|
+
* @param contextStatements Context declarations
|
|
102
|
+
* @param dependencies NPM dependencies
|
|
103
|
+
* @returns A cache key string
|
|
104
|
+
*/
|
|
105
|
+
export function generateCacheKey(
|
|
106
|
+
templateParts: string[] | TemplateStringsArray,
|
|
107
|
+
itemsKey: string,
|
|
108
|
+
contextStatements: string[],
|
|
109
|
+
dependencies: Record<string, string>
|
|
110
|
+
): string {
|
|
111
|
+
return [
|
|
112
|
+
Array.from(templateParts).join('|'),
|
|
113
|
+
itemsKey,
|
|
114
|
+
contextStatements.join(';'),
|
|
115
|
+
JSON.stringify(dependencies)
|
|
116
|
+
].join('::');
|
|
117
|
+
}
|
|
137
118
|
|
|
138
119
|
/**
|
|
139
120
|
* Marker that stores capture metadata on pattern AST nodes.
|
|
@@ -262,4 +243,56 @@ export class PlaceholderUtils {
|
|
|
262
243
|
}
|
|
263
244
|
return undefined;
|
|
264
245
|
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Extracts the relevant AST node from a wrapper function.
|
|
249
|
+
* Used by both pattern and template processors to intelligently extract
|
|
250
|
+
* code from `function __WRAPPER__() { code }` wrappers.
|
|
251
|
+
*
|
|
252
|
+
* @param lastStatement The last statement from the compilation unit
|
|
253
|
+
* @param contextName Context name for error messages (e.g., 'Pattern', 'Template')
|
|
254
|
+
* @returns The extracted AST node
|
|
255
|
+
*/
|
|
256
|
+
static extractFromWrapper(lastStatement: J, contextName: string): J {
|
|
257
|
+
let extracted: J;
|
|
258
|
+
|
|
259
|
+
// Since we always wrap in function __WRAPPER__() { code }, look for it
|
|
260
|
+
if (lastStatement.kind === J.Kind.MethodDeclaration) {
|
|
261
|
+
const method = lastStatement as J.MethodDeclaration;
|
|
262
|
+
if (method.name?.simpleName === WRAPPER_FUNCTION_NAME && method.body) {
|
|
263
|
+
const body = method.body;
|
|
264
|
+
|
|
265
|
+
// Intelligently extract based on what's in the function body
|
|
266
|
+
if (body.statements.length === 0) {
|
|
267
|
+
throw new Error(`${contextName} function body is empty`);
|
|
268
|
+
} else if (body.statements.length === 1) {
|
|
269
|
+
const stmt = body.statements[0].element;
|
|
270
|
+
|
|
271
|
+
// Single expression statement → extract the expression
|
|
272
|
+
if (stmt.kind === JS.Kind.ExpressionStatement) {
|
|
273
|
+
extracted = (stmt as JS.ExpressionStatement).expression;
|
|
274
|
+
}
|
|
275
|
+
// Single block statement → keep the block
|
|
276
|
+
else if (stmt.kind === J.Kind.Block) {
|
|
277
|
+
extracted = stmt;
|
|
278
|
+
}
|
|
279
|
+
// Other single statement → keep it
|
|
280
|
+
else {
|
|
281
|
+
extracted = stmt;
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
// Multiple statements → keep the block
|
|
285
|
+
extracted = body;
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
// Not our wrapper function
|
|
289
|
+
extracted = lastStatement;
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
// Shouldn't happen with our wrapping strategy, but handle it
|
|
293
|
+
extracted = lastStatement;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return extracted;
|
|
297
|
+
}
|
|
265
298
|
}
|