import { Cursor, Tree } from '../..'; import { J } from '../../java'; import { JS } from '../index'; import { JavaScriptSemanticComparatorVisitor } from '../comparator'; import { CaptureMarker, CaptureStorageValue } from './utils'; import { CaptureConstraintContext, DebugLogEntry, MatchExplanation } from './types'; /** * Debug callbacks for pattern matching. * These are always used together - either all present or all absent. * Part of Layer 1 (Core Instrumentation). */ export interface DebugCallbacks { log: (level: DebugLogEntry['level'], scope: DebugLogEntry['scope'], message: string, data?: any) => void; setExplanation: (reason: MatchExplanation['reason'], expected: string, actual: string, details?: string) => void; getExplanation: () => MatchExplanation | undefined; restoreExplanation: (explanation: MatchExplanation) => void; clearExplanation: () => void; pushPath: (name: string) => void; popPath: () => void; } /** * Snapshot of matcher state for backtracking. * Includes both capture storage and debug state. */ export interface MatcherState { storage: Map; debugState?: { explanation?: MatchExplanation; logLength: number; path: string[]; }; } /** * Callbacks for the matcher (debug and capture handling). * Part of Layer 1 (Core Instrumentation). */ export interface MatcherCallbacks { handleCapture: (capture: CaptureMarker, target: J, wrapper?: J.RightPadded) => boolean; handleVariadicCapture: (capture: CaptureMarker, targets: J[], wrappers?: J.RightPadded[]) => boolean; saveState: () => MatcherState; restoreState: (state: MatcherState) => void; debug?: DebugCallbacks; } /** * A comparator for pattern matching that is lenient about optional properties. * Allows patterns without type annotations to match actual code with type annotations. * Uses semantic comparison to match semantically equivalent code (e.g., isDate() and util.isDate()). */ export declare class PatternMatchingComparator extends JavaScriptSemanticComparatorVisitor { protected readonly matcher: MatcherCallbacks; constructor(matcher: MatcherCallbacks, lenientTypeMatching?: boolean); /** * Builds the constraint context with the cursor and current captures. * @param cursor The cursor to include in the context * @returns The constraint context for evaluating capture constraints */ protected buildConstraintContext(cursor: Cursor): CaptureConstraintContext; visit(j: Tree, p: J, parent?: Cursor): Promise; protected hasSameKind(j: J, other: J): boolean; /** * Additional specialized abort methods for pattern matching scenarios. */ protected constraintFailed(captureName: string, targetKind: string): any; protected captureConflict(captureName: string): any; /** * Override visitRightPadded to check if this wrapper has a CaptureMarker. * If so, capture the entire wrapper (to preserve markers like semicolons). */ visitRightPadded(right: J.RightPadded, p: J): Promise>; visitContainer(container: J.Container, p: J): Promise>; /** * Visit a single element in a container (for non-variadic matching). * Extracted to allow debug subclass to add path tracking. * * @param element The pattern element * @param otherElement The target element * @param index The index in the container * @returns true if matching should continue, false if it failed */ protected visitContainerElement(element: J.RightPadded, otherElement: J.RightPadded, index: number): Promise; visitMethodInvocation(methodInvocation: J.MethodInvocation, other: J): Promise; visitBlock(block: J.Block, other: J): Promise; visitJsCompilationUnit(compilationUnit: JS.CompilationUnit, other: J): Promise; /** * Matches argument lists, with special handling for variadic captures. * A variadic capture can match zero or more consecutive arguments. */ private matchArguments; /** * Generic sequence matching with variadic capture support. * Works for any sequence of JRightPadded elements (arguments, statements, etc.). * A variadic capture can match zero or more consecutive elements. * * Uses pivot detection to optimize matching, with backtracking as fallback. * * @param patternElements The pattern elements (JRightPadded) * @param targetElements The target elements to match against (JRightPadded) * @param filterEmpty Whether to filter out J.Empty elements when capturing (true for arguments, false for statements) * @returns true if the sequence matches, false otherwise */ protected matchSequence(patternElements: J.RightPadded[], targetElements: J.RightPadded[], filterEmpty: boolean): Promise; /** * Optimized sequence matcher with pivot detection and backtracking. * For variadic patterns, tries to detect pivots (where next pattern matches) to avoid * unnecessary backtracking. Falls back to full backtracking when pivots are ambiguous. * * @param patternElements The pattern elements (JRightPadded) * @param targetElements The target elements to match against (JRightPadded) * @param patternIdx Current position in pattern * @param targetIdx Current position in target * @param filterEmpty Whether to filter out J.Empty elements when capturing * @returns true if the remaining sequence matches, false otherwise */ protected matchSequenceOptimized(patternElements: J.RightPadded[], targetElements: J.RightPadded[], patternIdx: number, targetIdx: number, filterEmpty: boolean): Promise; /** * Visit a single element in a sequence during non-variadic matching. * Extracted to allow debug subclass to add path tracking. * * @param patternWrapper The pattern element * @param targetWrapper The target element * @param targetIdx The index in the target sequence * @returns true if matching succeeded, false otherwise */ protected visitSequenceElement(patternWrapper: J.RightPadded, targetWrapper: J.RightPadded, targetIdx: number): Promise; } /** * Debug-instrumented version of PatternMatchingComparator. * Overrides methods to add path tracking, logging, and explanation capture. * Zero cost when not instantiated - production code uses the base class. */ export declare class DebugPatternMatchingComparator extends PatternMatchingComparator { private get debug(); /** * Extracts the last segment of a kind string (after the last dot). * For example: "org.openrewrite.java.tree.J.MethodInvocation" -> "MethodInvocation" */ private formatKind; /** * Formats a value for display in error messages. */ private formatValue; /** * Override abort to capture explanation when debug is enabled. * Only sets explanation on the first abort call (when this.match is still true). * This preserves the most specific explanation closest to the actual mismatch. */ protected abort(t: T, reason?: string, propertyName?: string, expected?: any, actual?: any): T; /** * Override helper methods to extract detailed context from cursors. */ protected kindMismatch(): any; protected structuralMismatch(propertyName: string): any; protected arrayLengthMismatch(propertyName: string): any; protected valueMismatch(propertyName?: string, expected?: any, actual?: any): any; visit(j: Tree, p: J, parent?: Cursor): Promise; protected visitElement(j: T, other: T): Promise; visitRightPadded(right: J.RightPadded, p: J): Promise>; visitContainer(container: J.Container, p: J): Promise>; /** * Override visitContainerProperty to add path tracking with property context. */ protected visitContainerProperty(propertyName: string, container: J.Container, otherContainer: J.Container): Promise>; /** * Override visitRightPaddedProperty to add path tracking with property context. */ protected visitRightPaddedProperty(propertyName: string, rightPadded: J.RightPadded, otherRightPadded: J.RightPadded): Promise>; /** * Override visitLeftPaddedProperty to add path tracking with property context. */ protected visitLeftPaddedProperty(propertyName: string, leftPadded: J.LeftPadded, otherLeftPadded: J.LeftPadded): Promise>; protected visitContainerElement(element: J.RightPadded, otherElement: J.RightPadded, index: number): Promise; protected visitArrayProperty(parent: J, propertyName: string, array1: T[], array2: T[], visitor: (item1: T, item2: T, index: number) => Promise): Promise; protected matchSequence(patternElements: J.RightPadded[], targetElements: J.RightPadded[], filterEmpty: boolean): Promise; protected visitSequenceElement(patternWrapper: J.RightPadded, targetWrapper: J.RightPadded, targetIdx: number): Promise; protected matchSequenceOptimized(patternElements: J.RightPadded[], targetElements: J.RightPadded[], patternIdx: number, targetIdx: number, filterEmpty: boolean): Promise; } //# sourceMappingURL=comparator.d.ts.map