@ts-for-gir/lib
Version:
Typescript .d.ts generator from GIR for gjs
100 lines (82 loc) • 2.86 kB
text/typescript
import type { IntrospectedBaseClass } from "../gir/introspected-classes.ts";
import type { IntrospectedNamespace } from "../gir/namespace.ts";
import { Generic, GenericType, GenerifiedTypeIdentifier } from "../gir.ts";
import type { GtkConfig } from "../types/generics-config.ts";
function createGtkConfig(): GtkConfig {
return {
namespace: "Gtk",
version: "4.0",
modifier: (namespace: IntrospectedNamespace) => {
applyGtkGenerics(namespace);
},
};
}
function applyGtkGenerics(namespace: IntrospectedNamespace): void {
const classes = getGtkClasses(namespace);
const GObject = namespace.assertInstalledImport("GObject").assertClass("Object");
setupStringListGenerics(classes, GObject);
updateBindModelMethods(classes, GObject);
}
function getGtkClasses(namespace: IntrospectedNamespace) {
const requiredClasses = {
FlowBox: namespace.getClass("FlowBox"),
ListBox: namespace.getClass("ListBox"),
StringList: namespace.getClass("StringList"),
StringObject: namespace.getClass("StringObject"),
};
// Validate required classes exist
for (const [name, cls] of Object.entries(requiredClasses)) {
if (!cls) {
throw new Error(`Gtk.${name} not found.`);
}
}
return requiredClasses as Record<
keyof typeof requiredClasses,
NonNullable<(typeof requiredClasses)[keyof typeof requiredClasses]>
>;
}
function setupStringListGenerics(classes: ReturnType<typeof getGtkClasses>, GObject: IntrospectedBaseClass): void {
const { StringList, StringObject } = classes;
StringList.addGeneric({
default: StringObject.getType(),
constraint: GObject.getType(),
});
}
function updateBindModelMethods(classes: ReturnType<typeof getGtkClasses>, GObject: IntrospectedBaseClass): void {
const { FlowBox, ListBox } = classes;
const bindModelConfigs = [
{ cls: FlowBox, widgetFuncName: "FlowBoxCreateWidgetFunc" },
{ cls: ListBox, widgetFuncName: "ListBoxCreateWidgetFunc" },
];
for (const config of bindModelConfigs) {
updateBindModelMethod(config.cls, config.widgetFuncName, GObject);
}
}
function updateBindModelMethod(
cls: IntrospectedBaseClass,
widgetFuncName: string,
GObject: IntrospectedBaseClass,
): void {
cls.members = cls.members.map((member) => {
if (member.name !== "bind_model") {
return member;
}
member.generics.push(new Generic(new GenericType("A"), GObject.getType(), undefined, GObject.getType()));
return member.copy({
parameters: member.parameters.map((param) => {
if (param.name === "model") {
return param.copy({
type: new GenerifiedTypeIdentifier("ListModel", "Gio", [new GenericType("A")]),
});
}
if (param.name === "create_widget_func") {
return param.copy({
type: new GenerifiedTypeIdentifier(widgetFuncName, "Gtk", [new GenericType("A")]),
});
}
return param;
}),
});
});
}
export default createGtkConfig();