110 lines
2.7 KiB
TypeScript
110 lines
2.7 KiB
TypeScript
import ts from "typescript";
|
|
import { TypeRegistry } from "../registry.ts";
|
|
import { ParameterNode } from "./function.ts";
|
|
import { TypeReference } from "./reference.ts";
|
|
|
|
export class ClassNode {
|
|
private constructor(
|
|
public readonly name: string,
|
|
public readonly fields: FieldNode[],
|
|
public readonly methods: MethodNode[]
|
|
) {}
|
|
|
|
public static create(
|
|
registry: TypeRegistry,
|
|
node: ts.ClassDeclaration,
|
|
symbol?: ts.Symbol
|
|
) {
|
|
const fields: FieldNode[] = [];
|
|
const methods: MethodNode[] = [];
|
|
|
|
symbol?.members?.forEach((value) => {
|
|
const decl = value.declarations?.[0];
|
|
|
|
if (!decl) {
|
|
return;
|
|
}
|
|
|
|
if (ts.isPropertyDeclaration(decl) || ts.isParameter(decl)) {
|
|
fields.push(FieldNode.create(registry, decl));
|
|
} else if (
|
|
ts.isConstructorDeclaration(decl) ||
|
|
ts.isMethodDeclaration(decl)
|
|
) {
|
|
methods.push(MethodNode.create(registry, decl));
|
|
}
|
|
});
|
|
|
|
return new ClassNode(
|
|
symbol?.escapedName ?? node?.name?.escapedText ?? "",
|
|
fields,
|
|
methods
|
|
);
|
|
}
|
|
}
|
|
|
|
export type MemberVisibility = "public" | "private" | "protected";
|
|
|
|
/** Retrieve the visibility of a member based on the modifier flags */
|
|
function visibilityFrom(decl: ts.Declaration): MemberVisibility {
|
|
const modifiers = ts.getCombinedModifierFlags(decl);
|
|
|
|
if ((ts.ModifierFlags.Private & modifiers) === ts.ModifierFlags.Private) {
|
|
return "private";
|
|
}
|
|
|
|
if ((ts.ModifierFlags.Protected & modifiers) === ts.ModifierFlags.Protected) {
|
|
return "protected";
|
|
}
|
|
|
|
return "public";
|
|
}
|
|
|
|
export class FieldNode {
|
|
private constructor(
|
|
public readonly name: string,
|
|
public readonly type: TypeReference,
|
|
public readonly visibility: MemberVisibility,
|
|
public readonly optional: boolean
|
|
) {}
|
|
|
|
public static create(
|
|
registry: TypeRegistry,
|
|
decl: ts.PropertyDeclaration | ts.ParameterDeclaration
|
|
) {
|
|
return new FieldNode(
|
|
decl.name.getText(),
|
|
registry.getOrCreate(decl.type)!,
|
|
visibilityFrom(decl),
|
|
!!decl.questionToken // FIXME: or union with undefined
|
|
);
|
|
}
|
|
}
|
|
|
|
export class MethodNode {
|
|
static readonly ctorName = "__constructor";
|
|
|
|
public readonly isConstructor: boolean;
|
|
|
|
private constructor(
|
|
public readonly name: string,
|
|
public readonly visibility: MemberVisibility,
|
|
public readonly parameters: ParameterNode[],
|
|
public readonly returnType?: TypeReference
|
|
) {
|
|
this.isConstructor = name === MethodNode.ctorName;
|
|
}
|
|
|
|
public static create(
|
|
registry: TypeRegistry,
|
|
decl: ts.MethodDeclaration | ts.ConstructorDeclaration
|
|
) {
|
|
return new MethodNode(
|
|
decl?.name?.getText() ?? MethodNode.ctorName,
|
|
visibilityFrom(decl),
|
|
[],
|
|
registry.getOrCreate(decl.type)
|
|
);
|
|
}
|
|
}
|