@openrewrite/rewrite 8.67.0-20251108-160259 → 8.67.0-20251109-183700

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.
@@ -16,7 +16,7 @@
16
16
  import {Cursor} from '../..';
17
17
  import {J} from '../../java';
18
18
  import {Any, Capture, PatternOptions} from './types';
19
- import {CAPTURE_CAPTURING_SYMBOL, CAPTURE_NAME_SYMBOL, CaptureImpl} from './capture';
19
+ import {CAPTURE_CAPTURING_SYMBOL, CAPTURE_NAME_SYMBOL, CaptureImpl, RAW_CODE_SYMBOL, RawCode} from './capture';
20
20
  import {PatternMatchingComparator} from './comparator';
21
21
  import {CaptureMarker, CaptureStorageValue, generateCacheKey, globalAstCache, WRAPPERS_MAP_SYMBOL} from './utils';
22
22
  import {TemplateEngine} from './engine';
@@ -48,7 +48,7 @@ import {TemplateEngine} from './engine';
48
48
  */
49
49
  export class PatternBuilder {
50
50
  private parts: string[] = [];
51
- private captures: (Capture | Any<any>)[] = [];
51
+ private captures: (Capture | Any<any> | RawCode)[] = [];
52
52
 
53
53
  /**
54
54
  * Adds a static string part to the pattern.
@@ -73,15 +73,15 @@ export class PatternBuilder {
73
73
  /**
74
74
  * Adds a capture to the pattern.
75
75
  *
76
- * @param value The capture object (Capture or Any) or string name
76
+ * @param value The capture object (Capture, Any, or RawCode) or string name
77
77
  * @returns This builder for chaining
78
78
  */
79
- capture(value: Capture | Any<any> | string): this {
79
+ capture(value: Capture | Any<any> | RawCode | string): this {
80
80
  // Ensure we have a part for after this capture
81
81
  if (this.parts.length === 0) {
82
82
  this.parts.push('');
83
83
  }
84
- // Convert string to Capture if needed
84
+ // Convert string to Capture if needed, or use value as-is for RawCode
85
85
  const captureObj = typeof value === 'string' ? new CaptureImpl(value) : value;
86
86
  this.captures.push(captureObj as any);
87
87
  // Add an empty string for the next part
@@ -150,11 +150,11 @@ export class Pattern {
150
150
  * Creates a new pattern from template parts and captures.
151
151
  *
152
152
  * @param templateParts The string parts of the template
153
- * @param captures The captures between the string parts (can be Capture or Any)
153
+ * @param captures The captures between the string parts (can be Capture, Any, or RawCode)
154
154
  */
155
155
  constructor(
156
156
  public readonly templateParts: TemplateStringsArray,
157
- public readonly captures: (Capture | Any<any>)[]
157
+ public readonly captures: (Capture | Any<any> | RawCode)[]
158
158
  ) {
159
159
  }
160
160
 
@@ -194,10 +194,17 @@ export class Pattern {
194
194
  }
195
195
 
196
196
  // Generate cache key for global lookup
197
+ // Include raw code values in the key since they affect the generated AST
197
198
  const contextStatements = this._options.context || this._options.imports || [];
199
+ const capturesKey = this.captures.map(c => {
200
+ if (c instanceof RawCode || (c && typeof c === 'object' && (c as any)[RAW_CODE_SYMBOL])) {
201
+ return `raw:${(c as RawCode).code}`;
202
+ }
203
+ return c.getName();
204
+ }).join(',');
198
205
  const cacheKey = generateCacheKey(
199
206
  this.templateParts,
200
- this.captures.map(c => c.getName()).join(','),
207
+ capturesKey,
201
208
  contextStatements,
202
209
  this._options.dependencies || {}
203
210
  );
@@ -476,7 +483,11 @@ class Matcher {
476
483
 
477
484
  // Find the original capture object to get capturing flag
478
485
  // Note: Constraints are now evaluated in PatternMatchingComparator where cursor is correctly positioned
479
- const captureObj = this.pattern.captures.find(c => c.getName() === captureName);
486
+ // Filter out RawCode since it doesn't have getName()
487
+ const captureObj = this.pattern.captures.find(c =>
488
+ !(c instanceof RawCode || (c && typeof c === 'object' && (c as any)[RAW_CODE_SYMBOL])) &&
489
+ c.getName() === captureName
490
+ );
480
491
 
481
492
  // Only store the binding if this is a capturing placeholder
482
493
  const capturing = (captureObj as any)?.[CAPTURE_CAPTURING_SYMBOL] ?? true;
@@ -505,7 +516,11 @@ class Matcher {
505
516
 
506
517
  // Find the original capture object to get capturing flag
507
518
  // Note: Constraints are now evaluated in PatternMatchingComparator where cursor is correctly positioned
508
- const captureObj = this.pattern.captures.find(c => c.getName() === captureName);
519
+ // Filter out RawCode since it doesn't have getName()
520
+ const captureObj = this.pattern.captures.find(c =>
521
+ !(c instanceof RawCode || (c && typeof c === 'object' && (c as any)[RAW_CODE_SYMBOL])) &&
522
+ c.getName() === captureName
523
+ );
509
524
 
510
525
  // Only store the binding if this is a capturing placeholder
511
526
  const capturing = (captureObj as any)?.[CAPTURE_CAPTURING_SYMBOL] ?? true;
@@ -526,7 +541,7 @@ class Matcher {
526
541
  * Tagged template function for creating patterns.
527
542
  *
528
543
  * @param strings The string parts of the template
529
- * @param captures The captures between the string parts (Capture, Any, or string names)
544
+ * @param captures The captures between the string parts (Capture, Any, RawCode, or string names)
530
545
  * @returns A Pattern object
531
546
  *
532
547
  * @example
@@ -537,15 +552,28 @@ class Matcher {
537
552
  * @example
538
553
  * // Using any() for non-capturing matches
539
554
  * const pat = pattern`foo(${any()})`;
555
+ *
556
+ * @example
557
+ * // Using raw() for dynamic pattern construction
558
+ * const operator = '===';
559
+ * const pat = pattern`x ${raw(operator)} y`;
540
560
  */
541
- export function pattern(strings: TemplateStringsArray, ...captures: (Capture | Any<any> | string)[]): Pattern {
561
+ export function pattern(strings: TemplateStringsArray, ...captures: (Capture | Any<any> | RawCode | string)[]): Pattern {
542
562
  const capturesByName = captures.reduce((map, c) => {
563
+ // Skip raw code - it's not a capture
564
+ if (c instanceof RawCode || (typeof c === 'object' && c && (c as any)[RAW_CODE_SYMBOL])) {
565
+ return map;
566
+ }
543
567
  const capture = typeof c === "string" ? new CaptureImpl(c) : c;
544
568
  // Use symbol to get internal name without triggering Proxy
545
569
  const name = (capture as any)[CAPTURE_NAME_SYMBOL] || capture.getName();
546
570
  return map.set(name, capture);
547
571
  }, new Map<string, Capture | Any<any>>());
548
572
  return new Pattern(strings, captures.map(c => {
573
+ // Return raw code as-is
574
+ if (c instanceof RawCode || (typeof c === 'object' && c && (c as any)[RAW_CODE_SYMBOL])) {
575
+ return c as RawCode;
576
+ }
549
577
  // Use symbol to get internal name without triggering Proxy
550
578
  const name = typeof c === "string" ? c : ((c as any)[CAPTURE_NAME_SYMBOL] || c.getName());
551
579
  return capturesByName.get(name)!;