ts-json-schema-generator
Version:
Generate JSON schema from your Typescript sources
50 lines (42 loc) • 1.87 kB
text/typescript
import ts from "typescript";
import { UnknownNodeError } from "./Error/UnknownNodeError";
import { MutableParser } from "./MutableParser";
import { Context } from "./NodeParser";
import { SubNodeParser } from "./SubNodeParser";
import { BaseType } from "./Type/BaseType";
import { ReferenceType } from "./Type/ReferenceType";
export class ChainNodeParser implements SubNodeParser, MutableParser {
private readonly typeCaches = new WeakMap<ts.Node, Map<string, BaseType | undefined>>();
public constructor(private typeChecker: ts.TypeChecker, private nodeParsers: SubNodeParser[]) {}
public addNodeParser(nodeParser: SubNodeParser): this {
this.nodeParsers.push(nodeParser);
return this;
}
public supportsNode(node: ts.Node): boolean {
return this.nodeParsers.some((nodeParser) => nodeParser.supportsNode(node));
}
public createType(node: ts.Node, context: Context, reference?: ReferenceType): BaseType | undefined {
let typeCache = this.typeCaches.get(node);
if (typeCache == null) {
typeCache = new Map<string, BaseType | undefined>();
this.typeCaches.set(node, typeCache);
}
const contextCacheKey = context.getCacheKey();
let type = typeCache.get(contextCacheKey);
if (!type) {
type = this.getNodeParser(node, context).createType(node, context, reference);
if (!(type instanceof ReferenceType)) {
typeCache.set(contextCacheKey, type);
}
}
return type;
}
private getNodeParser(node: ts.Node, context: Context): SubNodeParser {
for (const nodeParser of this.nodeParsers) {
if (nodeParser.supportsNode(node)) {
return nodeParser;
}
}
throw new UnknownNodeError(node, context.getReference());
}
}