import * as ts from "typescript";
import { Result } from "@ts-std/monads";
import { Dict, PickVariants } from "./utils";
import { SpanResult, SpanError, SpanWarning } from "./message";
export declare type Macro<S = undefined> = {
    type: "block";
    execute: BlockMacroFn;
} | {
    type: "function";
    execute: FunctionMacroFn;
} | {
    type: "decorator";
    execute: DecoratorMacroFn;
} | {
    type: "import";
    execute: ImportMacroFn<S>;
};
export declare type SourceChannel<S> = (sources: Dict<S>) => void;
export declare type MacroContext = {
    Ok: <T>(value: T, warnings?: SpanWarning[]) => SpanResult<T>;
    TsNodeErr: (node: ts.TextRange, title: string, ...paragraphs: string[]) => SpanResult<any>;
    Err: (fileName: string, title: string, ...paragraphs: string[]) => SpanResult<any>;
    tsNodeWarn: (node: ts.TextRange, title: string, ...paragraphs: string[]) => void;
    warn: (fileName: string, title: string, ...paragraphs: string[]) => void;
    subsume: <T>(result: SpanResult<T>) => Result<T, void>;
};
export declare class Transformer<S> {
    readonly macros: Dict<Macro<S>> | undefined;
    protected readonly cache: Map<string, string>;
    protected readonly factory: ts.TransformerFactory<ts.SourceFile>;
    protected errors: SpanError[];
    protected warnings: SpanWarning[];
    checkSuccess(): [Result<void, import("./utils").NonEmpty<Readonly<{
        region: string | Readonly<{
            file: Readonly<{
                source: string;
                filename?: string | undefined;
            }>;
            start: number;
            end: number;
            line: number;
            column: number;
        }>;
        title: string;
        message: string;
        error: true;
    }>>>, Readonly<{
        region: string | Readonly<{
            file: Readonly<{
                source: string;
                filename?: string | undefined;
            }>;
            start: number;
            end: number;
            line: number;
            column: number;
        }>;
        title: string;
        message: string;
        error: false;
    }>[]];
    constructor(macros: Dict<Macro<S>> | undefined, workingDir: string, sourceChannel: SourceChannel<S>, readFile: (path: string) => string | undefined, joinPath: (...paths: string[]) => string, dirMaker: (sourceFileName: string) => {
        currentDir: string;
        currentFile: string;
    });
    reset(): void;
    has(path: string): boolean;
    get(path: string): string | undefined;
    transformSourceFile(sourceFile: ts.SourceFile): string;
    transformSource(path: string, source: string): string;
}
export declare type BlockMacroFn = (ctx: MacroContext, args: ts.NodeArray<ts.Statement>) => BlockMacroResult;
export declare type BlockMacroResult = SpanResult<ts.Statement[]>;
export declare function BlockMacro(execute: BlockMacroFn): PickVariants<Macro, "type", "block">;
export declare type FunctionMacroFn = (ctx: MacroContext, args: ts.NodeArray<ts.Expression>, typeArgs: ts.NodeArray<ts.TypeNode> | undefined) => FunctionMacroResult;
export declare type FunctionMacroResult = SpanResult<{
    prepend?: ts.Statement[];
    expression: ts.Expression;
    append?: ts.Statement[];
}>;
export declare function FunctionMacro(execute: FunctionMacroFn): PickVariants<Macro, "type", "function">;
export declare type DecoratorMacroFn = (ctx: MacroContext, statement: ts.Statement, args: ts.NodeArray<ts.Expression>, typeArgs: ts.NodeArray<ts.TypeNode> | undefined) => DecoratorMacroResult;
export declare type DecoratorMacroResult = SpanResult<{
    prepend?: ts.Statement[];
    replacement: ts.Statement | undefined;
    append?: ts.Statement[];
}>;
export declare function DecoratorMacro(execute: DecoratorMacroFn): PickVariants<Macro, "type", "decorator">;
export declare type FileContext = {
    workingDir: string;
    currentDir: string;
    currentFile: string;
};
export declare type ImportMacroFn<S = undefined> = (ctx: MacroContext, targetSource: string, targetPath: string, file: FileContext) => ImportMacroResult<S>;
export declare type ImportMacroResult<S = undefined> = SpanResult<{
    statements: ts.Statement[];
    sources?: Dict<S>;
}>;
export declare function ImportMacro<S = undefined>(execute: ImportMacroFn<S>): PickVariants<Macro<S>, "type", "import">;
