1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 */
16- import { Cursor , isTree , Tree } from '../..' ;
16+ import { Cursor , Tree } from '../..' ;
1717import { J } from '../../java' ;
1818import { JS } from '../index' ;
1919import { JavaScriptSemanticComparatorVisitor } from '../comparator' ;
20- import { PlaceholderUtils , CaptureStorageValue } from './utils' ;
20+ import { CaptureMarker , CaptureStorageValue , PlaceholderUtils } from './utils' ;
2121
2222/**
2323 * A comparator for pattern matching that is lenient about optional properties.
@@ -27,8 +27,8 @@ import {PlaceholderUtils, CaptureStorageValue} from './utils';
2727export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisitor {
2828 constructor (
2929 private readonly matcher : {
30- handleCapture : ( pattern : J , target : J , wrapper ?: J . RightPadded < J > ) => boolean ;
31- handleVariadicCapture : ( pattern : J , targets : J [ ] , wrappers ?: J . RightPadded < J > [ ] ) => boolean ;
30+ handleCapture : ( capture : CaptureMarker , target : J , wrapper ?: J . RightPadded < J > ) => boolean ;
31+ handleVariadicCapture : ( capture : CaptureMarker , targets : J [ ] , wrappers ?: J . RightPadded < J > [ ] ) => boolean ;
3232 saveState : ( ) => Map < string , CaptureStorageValue > ;
3333 restoreState : ( state : Map < string , CaptureStorageValue > ) => void ;
3434 } ,
@@ -42,7 +42,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
4242 // Check if the pattern node is a capture - this handles unwrapped captures
4343 // (Wrapped captures in J.RightPadded are handled by visitRightPadded override)
4444 if ( PlaceholderUtils . isCapture ( j as J ) ) {
45- const success = this . matcher . handleCapture ( j as J , p , undefined ) ;
45+ const success = this . matcher . handleCapture ( PlaceholderUtils . getCaptureMarker ( j ) ! , p , undefined ) ;
4646 if ( ! success ) {
4747 return this . abort ( j ) as R ;
4848 }
@@ -70,27 +70,17 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
7070 return right ;
7171 }
7272
73- // Check if this RightPadded or its element has a CaptureMarker (attached during pattern construction)
74- const element = right . element ;
75- let captureMarker = undefined ;
76-
77- // Check RightPadded itself
78- if ( right . markers ) {
79- captureMarker = PlaceholderUtils . getCaptureMarker ( right ) ;
80- }
81-
82- // Check element if it's a J node
83- if ( ! captureMarker && isTree ( element ) ) {
84- captureMarker = PlaceholderUtils . getCaptureMarker ( element ) ;
85- }
73+ // Check if this RightPadded has a CaptureMarker (attached during pattern construction)
74+ // Note: Markers are now only at the wrapper level, not at the element level
75+ const captureMarker = PlaceholderUtils . getCaptureMarker ( right ) ;
8676 if ( captureMarker ) {
8777 // Extract the target wrapper if it's also a RightPadded
8878 const isRightPadded = ( p as any ) . kind === J . Kind . RightPadded ;
8979 const targetWrapper = isRightPadded ? ( p as unknown ) as J . RightPadded < T > : undefined ;
9080 const targetElement = isRightPadded ? targetWrapper ! . element : p ;
9181
9282 // Handle the capture with the wrapper - use the element for pattern matching
93- const success = this . matcher . handleCapture ( element as J , targetElement as J , targetWrapper as J . RightPadded < J > | undefined ) ;
83+ const success = this . matcher . handleCapture ( captureMarker , targetElement as J , targetWrapper as J . RightPadded < J > | undefined ) ;
9484 if ( ! success ) {
9585 return this . abort ( right ) ;
9686 }
@@ -141,9 +131,9 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
141131 return this . abort ( methodInvocation ) ;
142132 }
143133
144- // Visit each type parameter in lock step
134+ // Visit each type parameter in lock step (visit RightPadded to check for markers)
145135 for ( let i = 0 ; i < methodInvocation . typeParameters . elements . length ; i ++ ) {
146- await this . visit ( methodInvocation . typeParameters . elements [ i ] . element , otherMethodInvocation . typeParameters . elements [ i ] . element ) ;
136+ await this . visitRightPadded ( methodInvocation . typeParameters . elements [ i ] , otherMethodInvocation . typeParameters . elements [ i ] as any ) ;
147137 if ( ! this . match ) return methodInvocation ;
148138 }
149139 }
@@ -163,7 +153,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
163153 override async visitBlock ( block : J . Block , other : J ) : Promise < J | undefined > {
164154 // Check if any statements have CaptureMarker indicating they're variadic
165155 const hasVariadicCapture = block . statements . some ( stmt => {
166- const captureMarker = PlaceholderUtils . getCaptureMarker ( stmt . element ) ;
156+ const captureMarker = PlaceholderUtils . getCaptureMarker ( stmt ) ;
167157 return captureMarker ?. variadicOptions !== undefined ;
168158 } ) ;
169159
@@ -261,8 +251,9 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
261251 return targetIdx >= targetElements . length ; // Success if all targets consumed
262252 }
263253
264- const patternElement = patternElements [ patternIdx ] . element ;
265- const captureMarker = PlaceholderUtils . getCaptureMarker ( patternElement ) ;
254+ // Check for markers at wrapper level only (markers are now only at the outermost level)
255+ const patternWrapper = patternElements [ patternIdx ] ;
256+ const captureMarker = PlaceholderUtils . getCaptureMarker ( patternWrapper ) ;
266257 const isVariadic = captureMarker ?. variadicOptions !== undefined ;
267258
268259 if ( isVariadic ) {
@@ -274,8 +265,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
274265 // Calculate maximum possible consumption
275266 let nonVariadicRemainingPatterns = 0 ;
276267 for ( let i = patternIdx + 1 ; i < patternElements . length ; i ++ ) {
277- const nextPatternElement = patternElements [ i ] . element ;
278- const nextCaptureMarker = PlaceholderUtils . getCaptureMarker ( nextPatternElement ) ;
268+ const nextCaptureMarker = PlaceholderUtils . getCaptureMarker ( patternElements [ i ] ) ;
279269 const nextIsVariadic = nextCaptureMarker ?. variadicOptions !== undefined ;
280270 if ( ! nextIsVariadic ) {
281271 nonVariadicRemainingPatterns ++ ;
@@ -290,24 +280,24 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
290280 let pivotAt = - 1 ;
291281
292282 if ( patternIdx + 1 < patternElements . length && min <= maxPossible ) {
293- const nextPattern = patternElements [ patternIdx + 1 ] . element ;
283+ const nextPattern = patternElements [ patternIdx + 1 ] ;
294284
295285 // Scan through possible consumption amounts starting from min
296286 for ( let tryConsume = min ; tryConsume <= maxPossible ; tryConsume ++ ) {
297287 // Check if element after our consumption would match next pattern
298288 if ( targetIdx + tryConsume < targetElements . length ) {
299- const candidateElement = targetElements [ targetIdx + tryConsume ] . element ;
289+ const candidateElement = targetElements [ targetIdx + tryConsume ] ;
300290
301291 // Skip J.Empty for arguments
302- if ( filterEmpty && candidateElement . kind === J . Kind . Empty ) {
292+ if ( filterEmpty && candidateElement . element . kind === J . Kind . Empty ) {
303293 continue ;
304294 }
305295
306296 // Test if next pattern matches this element
307297 const savedMatch = this . match ;
308298 const savedState = this . matcher . saveState ( ) ;
309299
310- await this . visit ( nextPattern , candidateElement ) ;
300+ await this . visitRightPadded ( nextPattern , candidateElement as any ) ;
311301 const matchesNext = this . match ;
312302
313303 this . match = savedMatch ;
@@ -366,7 +356,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
366356 const savedState = this . matcher . saveState ( ) ;
367357
368358 // Handle the variadic capture
369- const success = this . matcher . handleVariadicCapture ( patternElement , capturedElements , capturedWrappers ) ;
359+ const success = this . matcher . handleVariadicCapture ( captureMarker , capturedElements , capturedWrappers ) ;
370360 if ( ! success ) {
371361 // Restore state and try next amount
372362 this . matcher . restoreState ( savedState ) ;
@@ -409,7 +399,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
409399 const savedMatch = this . match ;
410400 const savedState = this . matcher . saveState ( ) ;
411401
412- await this . visit ( patternElement , targetElement ) ;
402+ await this . visitRightPadded ( patternWrapper , targetWrapper as any ) ;
413403
414404 if ( ! this . match ) {
415405 // Restore state on match failure
0 commit comments