@ts-for-gir/lib
Version:
Typescript .d.ts generator from GIR for gjs
147 lines • 5.68 kB
JavaScript
import { DefaultFormatter } from "../formatters/default.js";
import { JSONFormatter } from "../formatters/json.js";
import { JsonGenerator } from "../generators/json.js";
import { generify } from "../generics/generify.js";
import { inject } from "../injections/inject.js";
import { TwoKeyMap } from "../util.js";
import { ClassVisitor } from "../validators/class.js";
import { InterfaceVisitor } from "../validators/interface.js";
import { DtsModuleGenerator } from "../generators/dts-modules.js";
import { DtsInlineGenerator } from "../generators/dts-inline.js";
import { FunctionParametersVisitor } from "../validators/function-parameters.js";
export class NSRegistry {
mapping = new TwoKeyMap();
formatters = new Map();
generators = new Map();
c_mapping = new Map();
transformations = [];
subtypes = new TwoKeyMap();
constructor() {
this.formatters.set("json", new JSONFormatter());
}
registerTransformation(visitor) {
this.transformations.push(visitor);
// Apply transformations to already built namespaces.
this.mapping.forEach(n => {
n.accept(visitor);
});
}
registerFormatter(output, formatter) {
this.formatters.set(output, formatter);
}
getFormatter(output) {
return this.formatters.get(output) ?? new DefaultFormatter();
}
registerGenerator(output, generator) {
this.generators.set(output, generator);
}
async getGenerator(output) {
if (output === "dts") {
return DtsModuleGenerator;
}
if (output === "dts-inline") {
return DtsInlineGenerator;
}
if (output === "json") {
return JsonGenerator;
}
// Handle loading external generators...
if (!this.generators.has(output)) {
let Generator;
try {
Generator = (await import(`.ts/generator-${output}`));
if (Generator) {
console.log(`Loading generator "@gi.ts/generator-${output}"...`);
this.generators.set(output, Generator.default);
return;
}
}
catch {
try {
Generator = (await import(`gi-ts-generator-${output}`));
console.log(`Loading generator "gi-ts-generator-${output}"...`);
this.generators.set(output, Generator.default);
return;
}
catch {
try {
Generator = (await import(`${output}`));
console.log(`Loading generator "${output}"...`);
this.generators.set(output, Generator.default);
return;
}
catch { }
}
}
}
return this.generators.get(output);
}
_transformNamespace(namespace) {
this.transformations.forEach(t => {
namespace.accept(t);
});
}
namespace(name, version) {
const namespace = this.mapping.get(name, version);
return namespace ?? null;
}
namespacesForPrefix(c_prefix) {
return (this.c_mapping.get(c_prefix) ?? []).map(c_mapping => this.assertNamespace(c_mapping.name, c_mapping.version));
}
transform(options) {
const GLib = this.assertNamespace("GLib", "2.0");
const Gio = this.assertNamespace("Gio", "2.0");
const GObject = this.assertNamespace("GObject", "2.0");
// These follow the GLib version.
Gio.package_version = [...GLib.package_version];
GObject.package_version = [...GLib.package_version];
const interfaceVisitor = new InterfaceVisitor();
this.registerTransformation(interfaceVisitor);
const classVisitor = new ClassVisitor();
this.registerTransformation(classVisitor);
const enumParamsVisitor = new FunctionParametersVisitor();
this.registerTransformation(enumParamsVisitor);
console.log("Adding generics...");
generify(this, options.inferGenerics);
console.log("Injecting types...");
inject(this);
}
defaultVersionOf(name) {
// GJS has a hard dependency on these versions.
if (name === "GLib" || name === "Gio" || name === "GObject") {
return "2.0";
}
const meta = this.mapping.getIfOnly(name);
if (meta) {
return meta[0];
}
return null;
}
assertDefaultVersionOf(name) {
const version = this.defaultVersionOf(name);
if (version) {
return version;
}
// This mirrors GJS' and GI's default behavior.
// If we can't find a single version of an unspecified dependency, we throw an error.
throw new Error(`No single version found for unspecified dependency: ${JSON.stringify(name)}.`);
}
assertNamespace(name, version) {
const namespace = this.mapping.get(name, version) ?? null;
if (!namespace) {
throw new Error(`Namespace '${name}' not found.`);
}
return namespace;
}
register(namespace) {
this.mapping.set(namespace.namespace, namespace.version, namespace);
namespace.c_prefixes.forEach(c_prefix => {
const c_map = this.c_mapping.get(c_prefix) || [];
c_map.push({ name: namespace.namespace, version: namespace.version });
this.c_mapping.set(c_prefix, c_map);
});
this._transformNamespace(namespace);
return namespace;
}
}
//# sourceMappingURL=registry.js.map