import * as TS from "typescript";
type MetaNode = TS.Node & {
    jsDoc?: TS.JSDoc[];
    _original?: MetaNode;
    original?: MetaNode;
    _symbol?: TS.Symbol;
    symbol?: TS.Symbol;
    _parent?: MetaNode;
    localSymbol?: TS.Symbol;
    emitNode?: {
        leadingComments?: TS.SynthesizedComment[];
        trailingComments?: TS.SynthesizedComment[];
    };
};
type NodeHookValue<T extends MetaNode, Key extends keyof T> = T[Key] extends TS.NodeArray<infer ElementTypeA> ? ElementTypeA[] | TS.NodeArray<ElementTypeA> : T[Key] extends TS.NodeArray<infer ElementTypeB> | undefined ? ElementTypeB[] | TS.NodeArray<ElementTypeB> | undefined : T[Key];
interface CloneNodeHookFactoryPayload {
    depth: number;
}
type CloneNodeHookCallback<T extends MetaNode, Key extends keyof T> = (value: NodeHookValue<T, Key>, oldValue: NodeHookValue<T, Key>) => NodeHookValue<T, Key>;
type CloneNodeFinalizerCallback<T extends MetaNode> = (newNode: T, oldNode: T, payload: CloneNodeHookFactoryPayload) => T | void | undefined;
type CloneNodeHook<T extends MetaNode> = {
    [Key in keyof T]?: CloneNodeHookCallback<T, Key>;
};
type CloneNodeHookFactory<T extends MetaNode> = (node: T, payload: CloneNodeHookFactoryPayload) => CloneNodeHook<T> | undefined;
interface CloneNodeOptions<T extends MetaNode = MetaNode> {
    hook: CloneNodeHookFactory<T>;
    finalize: CloneNodeFinalizerCallback<T>;
    typescript: typeof TS;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    factory: TS.NodeFactory;
    setParents: boolean;
    setOriginalNodes: boolean;
    preserveSymbols: boolean;
    preserveComments: boolean;
    debug: boolean;
}
type ParentPropertyName = "parent" | "_parent";
interface SetParentNodesOptions {
    propertyName: ParentPropertyName;
    deep: boolean;
    typescript: typeof TS;
}
declare function setParentNodes<T extends MetaNode>(node: T, options: Partial<SetParentNodesOptions>): T;
declare function preserveNode<T extends MetaNode>(node: T, oldNode: T, options?: Partial<CloneNodeOptions<T>>): T;
declare function preserveNode<T extends MetaNode>(node: undefined, oldNode: undefined, options?: Partial<CloneNodeOptions<T>>): undefined;
declare function preserveNode<T extends MetaNode>(node: T | undefined, oldNode: T | undefined, options?: Partial<CloneNodeOptions<T>>): T | undefined;
declare function cloneNode<T extends MetaNode>(node: T, options?: Partial<CloneNodeOptions<T>>): T;
declare function cloneNode<T extends MetaNode>(node: undefined, options?: Partial<CloneNodeOptions<T>>): undefined;
declare function cloneNode<T extends MetaNode>(node: T | undefined, options?: Partial<CloneNodeOptions<T>>): T | undefined;
export { cloneNode, preserveNode, setParentNodes, CloneNodeOptions, CloneNodeHook };
