import { Cursor, Tree } from "../tree"; import { J } from "../java"; import { JavaScriptVisitor } from "./visitor"; /** * Options for controlling LST debug output. * * @example * // Output to a file instead of console * const options: LstDebugOptions = { output: '/tmp/debug.txt' }; * * @example * // Minimal output - just the tree structure * const options: LstDebugOptions = { includeCursorMessages: false }; */ export interface LstDebugOptions { /** Include cursor messages (like indentContext) in output. Default: true */ includeCursorMessages?: boolean; /** Include markers in output. Default: false */ includeMarkers?: boolean; /** Include node IDs in output. Default: false */ includeIds?: boolean; /** Maximum depth to traverse (for print/recursive methods). Default: unlimited (-1) */ maxDepth?: number; /** Properties to always exclude (in addition to defaults like 'type'). */ excludeProperties?: string[]; /** Output destination: 'console' or a file path. Default: 'console' */ output?: 'console' | string; /** Indent string for nested output. Default: ' ' (2 spaces) */ indent?: string; } /** * Format whitespace string for readable debug output. * Uses compact notation with subscript counts: * - '\n' = 1 newline (implicit ₁) * - '\n₂' = 2 newlines * - '·₄' = 4 spaces * - '-₂' = 2 tabs * - '\n·₄' = newline + 4 spaces * - '\n·₄-₂' = newline + 4 spaces + 2 tabs */ export declare function formatWhitespace(whitespace: string | undefined): string; /** * Format a J.Space for debug output. * * Compact format: * - Empty space: `''` * - Whitespace only: `'\n·₄'` * - Comment only: `//comment` * - Comment with suffix: `//comment'\n'` * - Multiple comments: `//c1'\n' + //c2'\n·₄'` */ export declare function formatSpace(space: J.Space | undefined): string; /** * Format cursor messages for debug output. * Returns '' if no messages, otherwise returns '⟨key=value, ...⟩' */ export declare function formatCursorMessages(cursor: Cursor | undefined): string; /** * Find which property of the parent contains the given child element. * Returns the property name, or property name with array index if in an array. * Returns undefined if the relationship cannot be determined. * * @param cursor - The cursor at the current position * @param child - Optional: the actual child node being visited (for RightPadded/LeftPadded/Container visits where cursor.value is the parent) */ export declare function findPropertyPath(cursor: Cursor | undefined, child?: any): string | undefined; /** * LST Debug Printer - prints LST nodes in a readable format. * * This is a STATEFUL object that tracks cursor depth across calls to provide * proper indentation. Create one instance as a field in your visitor and reuse it. * * Two main methods: * - `log()`: Prints a single node WITHOUT recursing into children. Tracks cursor * hierarchy across calls to show proper indentation. * - `print()`: Prints a node AND all its children recursively. * * Usage from within a visitor (recommended pattern): * ```typescript * class TabsAndIndentsVisitor extends JavaScriptVisitor

{ * // Create as a field - it tracks state across calls * private debug = new LstDebugPrinter(); * * async visitBlock(block: J.Block, p: P) { * // Log this node with automatic indentation based on cursor depth * this.debug.log(block, this.cursor, "visiting block"); * return super.visitBlock(block, p); * } * * async visitMethodInvocation(mi: J.MethodInvocation, p: P) { * this.debug.log(mi, this.cursor); * return super.visitMethodInvocation(mi, p); * } * } * ``` * * Output will be properly indented based on tree depth: * ``` * CompilationUnit{prefix=''} * statements[0]: ClassDeclaration{name='Foo' prefix=''} * body: Block{prefix='·'} * // visiting block * statements[0]: MethodDeclaration{name='bar' prefix='\n·₄'} * ``` * * To reset indentation tracking (e.g., between files): * ```typescript * this.debug.reset(); * ``` * * To print an entire subtree with recursion: * ```typescript * this.debug.print(subtree, this.cursor, "dumping subtree"); * ``` */ export declare class LstDebugPrinter { private readonly options; private outputLines; /** * Cache of cursor depth to avoid recalculating. * Uses WeakMap so cursors can be garbage collected. */ private depthCache; constructor(options?: LstDebugOptions); /** * Clear the depth cache. Call this when starting a new tree * to free memory from previous traversals. */ reset(): void; /** * Log a single node WITHOUT recursing into children. * Use this from visitor methods to log individual nodes as they are visited. * * When called with a cursor, tracks the cursor hierarchy across calls to * provide proper indentation showing the tree structure. * * Output format: `// label` (if provided), then indented `TypeName{summary prefix=...}` * with cursor messages on a separate line if present. * * @param node The node to log * @param cursor Optional cursor for context, messages, and depth tracking * @param label Optional label to identify this log entry */ log(node: Tree | J.Container | J.LeftPadded | J.RightPadded, cursor?: Cursor, label?: string): void; /** * Print a tree node AND all its children recursively. * Use this to dump an entire subtree structure. * * @param tree The tree node to print * @param cursor Optional cursor for context * @param label Optional label to identify this debug output (shown as comment before output) */ print(tree: Tree | J.Container | J.LeftPadded | J.RightPadded, cursor?: Cursor, label?: string): void; /** * Print the cursor path from root to current position. */ printCursorPath(cursor: Cursor): void; /** * Calculate the depth of the cursor by counting parent chain length. * Uses caching to avoid repeated traversals. */ private calculateDepth; private printNode; private printJavaNode; private printNodeProperties; private printContainer; private printLeftPadded; private printRightPadded; private printGenericObject; private isSpace; private isContainer; private isLeftPadded; private isRightPadded; private indent; private flush; } /** * A visitor that prints the LST structure as it traverses, showing each node * with proper indentation to visualize the tree hierarchy. * * Use this to print an entire tree or subtree with full traversal. Each node * is printed as it's visited, with indentation showing the tree depth. * * For logging individual nodes from within your own visitor without recursion, * use `LstDebugPrinter.log()` or `debugLog()` instead. * * Usage: * ```typescript * // Print entire tree structure during traversal * const debugVisitor = new LstDebugVisitor(); * await debugVisitor.visit(tree, ctx); * * // With options * const debugVisitor = new LstDebugVisitor( * { includeCursorMessages: true }, * { printPreVisit: true, printPostVisit: false } * ); * await debugVisitor.visit(subtree, ctx); * ``` */ export declare class LstDebugVisitor

extends JavaScriptVisitor

{ private readonly printer; private readonly printPreVisit; private readonly printPostVisit; private depth; constructor(options?: LstDebugOptions, config?: { printPreVisit?: boolean; printPostVisit?: boolean; }); visitContainer(container: J.Container, p: P): Promise>; visitLeftPadded(left: J.LeftPadded, p: P): Promise | undefined>; visitRightPadded(right: J.RightPadded, p: P): Promise | undefined>; protected preVisit(tree: J, _p: P): Promise; protected postVisit(tree: J, _p: P): Promise; } /** * Convenience function to log a single node (no recursion). * Use this from visitor methods to log individual nodes as they are visited. * * @param node The node to log * @param cursor Optional cursor for context and messages * @param label Optional label to identify this log entry * @param options Optional debug options */ export declare function debugLog(node: Tree, cursor?: Cursor, label?: string, options?: LstDebugOptions): void; /** * Convenience function to print a tree node AND all its children recursively. * Use this to dump an entire subtree structure. * * @param tree The tree node to print * @param cursor Optional cursor for context * @param label Optional label to identify this debug output * @param options Optional debug options */ export declare function debugPrint(tree: Tree, cursor?: Cursor, label?: string, options?: LstDebugOptions): void; /** * Convenience function to print cursor path. */ export declare function debugPrintCursorPath(cursor: Cursor, options?: LstDebugOptions): void; /** * Create a debug printer if debugging is enabled, otherwise return undefined. * * This is useful for visitors that want to optionally enable debugging via * constructor parameters or configuration. * * @param enabled Whether debugging is enabled * @param options Debug options (including output file path) * @returns LstDebugPrinter if enabled, undefined otherwise * * @example * class MyVisitor extends JavaScriptVisitor

{ * private debug?: LstDebugPrinter; * * constructor(enableDebug?: boolean | LstDebugOptions) { * super(); * this.debug = createDebugPrinter(enableDebug); * } * * async visitBlock(block: J.Block, p: P) { * this.debug?.log(block, this.cursor); * return super.visitBlock(block, p); * } * } * * // Usage: * new MyVisitor(true); // Enable with defaults * new MyVisitor({ output: '/tmp/debug.txt' }); // Enable with options * new MyVisitor(false); // Disabled * new MyVisitor(); // Disabled (default) */ export declare function createDebugPrinter(enabled?: boolean | LstDebugOptions): LstDebugPrinter | undefined; //# sourceMappingURL=tree-debug.d.ts.map