UNPKG

@blainehansen/macro-ts

Version:

An ergonomic typescript compiler that enables typesafe syntactic macros.

100 lines (99 loc) 4.31 kB
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">;