UNPKG

@ts-for-gir/lib

Version:

Typescript .d.ts generator from GIR for gjs

200 lines (172 loc) 5.38 kB
import { GirDirection } from "@gi.ts/parser"; import type { FormatGenerator } from "../generators/generator.ts"; import { ArrayType, type TypeExpression } from "../gir.ts"; import type { GirCallableParamElement } from "../index.ts"; import type { IntrospectedOptions, OptionsLoad } from "../types/index.ts"; import { getType, parseDoc, parseMetadata } from "../utils/gir-parsing.ts"; import { isIntrospectable } from "../utils/girs.ts"; import { isInvalid, sanitizeMemberName } from "../utils/naming.ts"; import type { GirVisitor } from "../visitor.ts"; import type { IntrospectedConstructor } from "./constructor.ts"; import type { IntrospectedDirectAllocationConstructor } from "./direct-allocation-constructor.ts"; import type { IntrospectedFunction } from "./function.ts"; import { IntrospectedBase } from "./introspected-base.ts"; import { IntrospectedBaseClass, type IntrospectedClassFunction } from "./introspected-classes.ts"; import { IntrospectedField } from "./property.ts"; import type { IntrospectedSignal } from "./signal.ts"; export class IntrospectedFunctionParameter extends IntrospectedBase< | IntrospectedClassFunction | IntrospectedFunction | IntrospectedSignal | IntrospectedConstructor | IntrospectedDirectAllocationConstructor | null > { readonly type: TypeExpression; readonly direction: GirDirection; readonly isVarArgs: boolean = false; readonly isOptional: boolean = false; readonly isNullable: boolean = false; constructor({ name, direction, type, parent, doc, isVarArgs = false, isOptional = false, isNullable = false, ...args }: IntrospectedOptions<{ name: string; parent?: | IntrospectedClassFunction | IntrospectedFunction | IntrospectedSignal | IntrospectedConstructor | IntrospectedDirectAllocationConstructor | null; type: TypeExpression; direction: GirDirection; doc?: string | null; isVarArgs?: boolean; isOptional?: boolean; isNullable?: boolean; }>) { super(name, parent ?? null, { ...args }); this.type = type; this.direction = direction; this.doc = doc; this.isVarArgs = isVarArgs; this.isOptional = isOptional; this.isNullable = isNullable; } get namespace() { if (!this.parent) throw new Error(`Failed to get namespace for ${this.name}`); return this.parent.namespace; } asField() { const { name, parent, isOptional: optional, type } = this; if (!(parent?.parent instanceof IntrospectedBaseClass)) { throw new Error("Can't convert parameter of non-class function to field"); } return new IntrospectedField({ name, parent: parent.parent, optional, type }); } copy( options: { parent?: | IntrospectedClassFunction | IntrospectedFunction | IntrospectedSignal | IntrospectedConstructor | IntrospectedDirectAllocationConstructor | null; type?: TypeExpression; isOptional?: boolean; isNullable?: boolean; } = { parent: this.parent, }, ): IntrospectedFunctionParameter { const { type, parent, direction, isVarArgs, isOptional, isNullable, name, doc } = this; return new IntrospectedFunctionParameter({ parent: options.parent ?? parent, name, direction, isVarArgs, isOptional: options.isOptional ?? isOptional, isNullable: options.isNullable ?? isNullable, type: options.type ?? type, doc, })._copyBaseProperties(this); } accept(visitor: GirVisitor): IntrospectedFunctionParameter { const node = this.copy({ type: visitor.visitType?.(this.type), }); return visitor.visitParameter?.(node) ?? node; } asString<T>(generator: FormatGenerator<T>): T { return generator.generateParameter(this); } static fromXML< Parent extends IntrospectedSignal | IntrospectedClassFunction | IntrospectedFunction | IntrospectedConstructor, >( parameter: GirCallableParamElement & { $: { name: string } }, parent: Parent, options: OptionsLoad, ): IntrospectedFunctionParameter { const ns = parent.namespace; let name = sanitizeMemberName(parameter.$.name); if (isInvalid(name)) { name = `_${name}`; } let isVarArgs = false; let isOptional = false; let isNullable = false; let type: TypeExpression; let direction: GirDirection; if ( !parameter.$.direction || parameter.$.direction === GirDirection.In || parameter.$.direction === GirDirection.Inout || parameter.$.direction === GirDirection.InOut ) { if (name === "...") { isVarArgs = true; name = "args"; } // Default to "in" direction direction = parameter.$.direction || GirDirection.In; const optional = parameter.$.optional === "1"; const nullable = parameter.$.nullable === "1"; if (optional) { isOptional = true; } if (nullable) { isNullable = true; } type = getType(ns, parameter); } else if (parameter.$.direction === GirDirection.Out) { direction = parameter.$.direction; type = getType(ns, parameter); } else { throw new Error(`Unknown parameter direction: ${parameter.$.direction as string}`); } const fp = new IntrospectedFunctionParameter({ isVarArgs, type: isVarArgs ? new ArrayType(type) : type, direction, parent: parent ?? undefined, isOptional, isNullable, name, isIntrospectable: isIntrospectable(parameter), }); if (options.loadDocs) { fp.doc = parseDoc(parameter); fp.metadata = parseMetadata(parameter); } return fp; } }