@blainehansen/macro-ts
Version:
An ergonomic typescript compiler that enables typesafe syntactic macros.
100 lines (99 loc) • 4.31 kB
TypeScript
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">;