typia
Version:
Superfast runtime validators with only one line
98 lines (82 loc) • 2.7 kB
text/typescript
import ts from "typescript";
import { IdentifierFactory } from "../../factories/IdentifierFactory";
import { StatementFactory } from "../../factories/StatementFactory";
import { TypeFactory } from "../../factories/TypeFactory";
export class FunctionImporter {
private readonly used_: Set<string> = new Set();
private readonly local_: Set<string> = new Set();
private readonly unions_: Map<string, [string, ts.ArrowFunction]> = new Map();
private readonly variables_: Map<string, ts.Expression> = new Map();
private sequence_: number = 0;
public constructor(public readonly method: string) {}
public empty(): boolean {
return this.used_.size === 0;
}
public use(name: string): ts.Identifier {
this.used_.add(name);
return ts.factory.createIdentifier("$" + name);
}
public useLocal(name: string): string {
this.local_.add(name);
return name;
}
public hasLocal(name: string): boolean {
return this.local_.has(name);
}
public declare(
modulo: ts.LeftHandSideExpression,
includeUnions: boolean = true,
): ts.Statement[] {
return [
...[...this.used_].map((name) =>
StatementFactory.constant(
"$" + name,
IdentifierFactory.access(
ts.factory.createParenthesizedExpression(
ts.factory.createAsExpression(modulo, TypeFactory.keyword("any")),
),
)(name),
),
),
...[...this.variables_.entries()].map(([key, value]) =>
StatementFactory.constant(key, value),
),
...(includeUnions === true
? [...this.unions_.values()].map(([key, arrow]) =>
StatementFactory.constant(key, arrow),
)
: []),
];
}
public declareUnions(): ts.Statement[] {
return [...this.unions_.values()].map(([key, arrow]) =>
StatementFactory.constant(key, arrow),
);
}
public increment(): number {
return ++this.sequence_;
}
public emplaceUnion(
prefix: string,
name: string,
factory: () => ts.ArrowFunction,
): string {
const key: string = `${prefix}::${name}`;
const oldbie = this.unions_.get(key);
if (oldbie) return oldbie[0];
const index: number = this.unions_.size;
const accessor: string = `${prefix}p${index}`;
const tuple: [string, ReturnType<typeof factory>] = [accessor, null!];
this.unions_.set(key, tuple);
tuple[1] = factory();
return accessor;
}
public emplaceVariable(name: string, value: ts.Expression): ts.Expression {
this.variables_.set(name, value);
return ts.factory.createIdentifier(name);
}
public trace(): void {
console.log(...this.used_);
console.log(...this.local_);
}
}