@ts-for-gir/generator-typescript 4.0.0-beta.4 → 4.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -2
- package/package.json +15 -29
- package/src/generators/index.ts +2 -0
- package/src/generators/module-exporter.ts +88 -0
- package/src/generators/signal-generator.ts +254 -0
- package/src/index.ts +4 -0
- package/src/module-generator-example.ts +68 -0
- package/src/module-generator.ts +2058 -0
- package/src/npm-package.ts +115 -0
- package/src/overrides/glib.ts +13 -0
- package/src/overrides/gobject.ts +52 -0
- package/src/template-processor.ts +216 -0
- package/src/type-definition-generator.ts +171 -0
- package/src/utils.ts +7 -0
- package/lib/index.d.ts +0 -3
- package/lib/index.js +0 -4
- package/lib/index.js.map +0 -1
- package/lib/package-data-parser.d.ts +0 -13
- package/lib/package-data-parser.js +0 -67
- package/lib/package-data-parser.js.map +0 -1
- package/lib/template-processor.d.ts +0 -110
- package/lib/template-processor.js +0 -239
- package/lib/template-processor.js.map +0 -1
- package/lib/type-definition-generator.d.ts +0 -157
- package/lib/type-definition-generator.js +0 -1413
- package/lib/type-definition-generator.js.map +0 -1
- package/lib/utils.d.ts +0 -2
- package/lib/utils.js +0 -7
- package/lib/utils.js.map +0 -1
- package/packages.xml +0 -1213
- package/templates/README.md +0 -92
- package/templates/cogl-2-0.d.ts +0 -0
- package/templates/gjs/README-GJS.md +0 -133
- package/templates/gjs/ambient.d.ts +0 -19
- package/templates/gjs/ambient.js +0 -1
- package/templates/gjs/cairo-1.0.d.ts +0 -9
- package/templates/gjs/cairo.d.ts +0 -4
- package/templates/gjs/cairo.js +0 -4
- package/templates/gjs/dom.d.ts +0 -316
- package/templates/gjs/dom.js +0 -1
- package/templates/gjs/gettext.d.ts +0 -41
- package/templates/gjs/gettext.js +0 -4
- package/templates/gjs/gio-2.0.d.ts +0 -36
- package/templates/gjs/gjs.d.ts +0 -459
- package/templates/gjs/gjs.js +0 -4
- package/templates/gjs/gobject-2.0.d.ts +0 -227
- package/templates/gjs/module-ambient.d.ts +0 -23
- package/templates/gjs/module-ambient.js +0 -1
- package/templates/gjs/module-import.d.ts +0 -16
- package/templates/gjs/module-import.js +0 -2
- package/templates/gjs/module-noNamespace.d.ts +0 -7
- package/templates/gjs/module.append.d.ts +0 -1
- package/templates/gjs/module.d.ts +0 -13
- package/templates/gjs/module.js +0 -5
- package/templates/gjs/system.d.ts +0 -175
- package/templates/gjs/system.js +0 -4
- package/templates/granite-1.0.d.ts +0 -7
- package/templates/granite-7.0.d.ts +0 -7
- package/templates/gstbase-0.10.d.ts +0 -5
- package/templates/package.json +0 -95
- package/templates/rygelserver-2.6.d.ts +0 -3
- package/templates/tsconfig.json +0 -30
- package/templates/typedoc.json +0 -26
package/README.md
CHANGED
|
@@ -16,5 +16,22 @@
|
|
|
16
16
|
<img src="https://raw.githubusercontent.com/gjsify/ts-for-gir/main/.github/feeling.gif" />
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
|
-
# Generator
|
|
20
|
-
|
|
19
|
+
# TypeScript Generator
|
|
20
|
+
|
|
21
|
+
TypeScript-specific generator for `ts-for-gir`. This package implements the actual generation of TypeScript declaration files (.d.ts) from the processed GIR data. It transforms the intermediate representation of GObject types into TypeScript type definitions.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Generation of TypeScript declaration files (.d.ts) from GIR data
|
|
26
|
+
- Support for generating NPM packages with proper package.json configuration
|
|
27
|
+
- Template-based code generation using EJS templates
|
|
28
|
+
- Complete handling of complex type transformations:
|
|
29
|
+
- Classes, interfaces, and records
|
|
30
|
+
- Functions, methods, and constructors
|
|
31
|
+
- Properties, fields, and constants
|
|
32
|
+
- Enums and callbacks
|
|
33
|
+
- Signals and their event handlers
|
|
34
|
+
- Generation of proper JSDoc comments from GIR documentation
|
|
35
|
+
- Support for GJS-specific module formats and ambient type declarations
|
|
36
|
+
|
|
37
|
+
This package is responsible for the final output of the `ts-for-gir` toolchain, producing TypeScript definition files that can be used in GJS projects.
|
package/package.json
CHANGED
|
@@ -1,36 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-for-gir/generator-typescript",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.41",
|
|
4
4
|
"description": "TypeScript type definition generator for ts-for-gir",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"module": "src/index.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=18"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
|
-
".":
|
|
13
|
-
"types": "./lib/index.d.ts",
|
|
14
|
-
"import": "./lib/index.js"
|
|
15
|
-
}
|
|
12
|
+
".": "./src/index.ts"
|
|
16
13
|
},
|
|
17
14
|
"scripts": {
|
|
18
|
-
"
|
|
19
|
-
"build:ts": "tsc",
|
|
20
|
-
"clear": "yarn clear:build",
|
|
21
|
-
"clear:build": "rimraf ./lib",
|
|
22
|
-
"watch": "yarn build:ts --watch",
|
|
23
|
-
"lint": "eslint . --ext .ts,.tsx --fix"
|
|
15
|
+
"check": "tsc --noEmit"
|
|
24
16
|
},
|
|
25
17
|
"repository": {
|
|
26
18
|
"type": "git",
|
|
27
19
|
"url": "git+https://github.com/gjsify/ts-for-gir.git"
|
|
28
20
|
},
|
|
29
|
-
"author": "Pascal Garber <pascal@
|
|
21
|
+
"author": "Pascal Garber <pascal@mailfreun.de>",
|
|
30
22
|
"files": [
|
|
31
|
-
"
|
|
32
|
-
"templates",
|
|
33
|
-
"packages.xml"
|
|
23
|
+
"src"
|
|
34
24
|
],
|
|
35
25
|
"license": "Apache-2.0",
|
|
36
26
|
"bugs": {
|
|
@@ -41,22 +31,18 @@
|
|
|
41
31
|
"generator"
|
|
42
32
|
],
|
|
43
33
|
"devDependencies": {
|
|
34
|
+
"@ts-for-gir/tsconfig": "^4.0.0-beta.41",
|
|
44
35
|
"@types/ejs": "^3.1.5",
|
|
45
|
-
"@types/node": "^
|
|
36
|
+
"@types/node": "^24.12.0",
|
|
46
37
|
"@types/xml2js": "^0.4.14",
|
|
47
|
-
"
|
|
48
|
-
"@typescript-eslint/parser": "^7.8.0",
|
|
49
|
-
"eslint": "^8.57.0",
|
|
50
|
-
"eslint-config-prettier": "^9.1.0",
|
|
51
|
-
"eslint-plugin-prettier": "^5.1.3",
|
|
52
|
-
"prettier": "^3.2.5",
|
|
53
|
-
"rimraf": "^5.0.5",
|
|
54
|
-
"typescript": "^5.4.5"
|
|
38
|
+
"typescript": "^5.9.3"
|
|
55
39
|
},
|
|
56
40
|
"dependencies": {
|
|
57
|
-
"@ts
|
|
58
|
-
"@ts-for-gir/
|
|
59
|
-
"
|
|
41
|
+
"@gi.ts/parser": "^4.0.0-beta.41",
|
|
42
|
+
"@ts-for-gir/generator-base": "^4.0.0-beta.41",
|
|
43
|
+
"@ts-for-gir/lib": "^4.0.0-beta.41",
|
|
44
|
+
"@ts-for-gir/templates": "^4.0.0-beta.41",
|
|
45
|
+
"ejs": "^5.0.1",
|
|
60
46
|
"xml2js": "^0.6.2"
|
|
61
47
|
}
|
|
62
48
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { DependencyManager, GirModule, NSRegistry, OptionsGeneration, Reporter } from "@ts-for-gir/lib";
|
|
2
|
+
import type { ModuleGenerator } from "../module-generator.ts";
|
|
3
|
+
import { NpmPackage } from "../npm-package.ts";
|
|
4
|
+
import type { TemplateProcessor } from "../template-processor.ts";
|
|
5
|
+
|
|
6
|
+
/** Handles exporting generated modules to files. */
|
|
7
|
+
export class ModuleExporter {
|
|
8
|
+
constructor(private readonly core: ModuleGenerator) {}
|
|
9
|
+
|
|
10
|
+
private get config(): OptionsGeneration {
|
|
11
|
+
return this.core.config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private get log(): Reporter {
|
|
15
|
+
return this.core.log;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private get moduleTemplateProcessor(): TemplateProcessor {
|
|
19
|
+
return this.core.moduleTemplateProcessor;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private get dependencyManager(): DependencyManager {
|
|
23
|
+
return this.core.dependencyManager;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Export a template file to outdir or log its content. */
|
|
27
|
+
private async exportTemplate(template: string, target: string): Promise<void> {
|
|
28
|
+
if (this.config.outdir) {
|
|
29
|
+
await this.moduleTemplateProcessor.create(template, this.config.outdir, target);
|
|
30
|
+
} else {
|
|
31
|
+
const { append, prepend } = await this.moduleTemplateProcessor.load(template);
|
|
32
|
+
this.log.log(append + prepend);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async exportModuleTS(): Promise<void> {
|
|
37
|
+
const girModule = this.core.girNamespace;
|
|
38
|
+
const template = "module.d.ts";
|
|
39
|
+
const explicitTemplate = `${girModule.importName}.d.ts`;
|
|
40
|
+
const output = await this.core.generateModule(girModule);
|
|
41
|
+
|
|
42
|
+
if (!output) {
|
|
43
|
+
this.log.error("Failed to generate gir module");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (await this.moduleTemplateProcessor.exists(explicitTemplate)) {
|
|
48
|
+
const { append: appendExplicit, prepend: prependExplicit } =
|
|
49
|
+
await this.moduleTemplateProcessor.load(explicitTemplate);
|
|
50
|
+
output.unshift(prependExplicit);
|
|
51
|
+
output.push(appendExplicit);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { append, prepend } = await this.moduleTemplateProcessor.load(template);
|
|
55
|
+
output.unshift(prepend);
|
|
56
|
+
output.push(append);
|
|
57
|
+
|
|
58
|
+
if (this.config.outdir) {
|
|
59
|
+
await this.moduleTemplateProcessor.write(output.join("\n"), this.config.outdir, explicitTemplate);
|
|
60
|
+
} else {
|
|
61
|
+
this.log.log(output.join("\n"));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async exportModule(registry: NSRegistry, girModule: GirModule): Promise<void> {
|
|
66
|
+
await this.exportModuleTS();
|
|
67
|
+
|
|
68
|
+
if (this.config.package) {
|
|
69
|
+
const name = girModule.importName;
|
|
70
|
+
await this.exportTemplate("module.js", `${name}.js`);
|
|
71
|
+
await this.exportTemplate("index.d.ts", "index.d.ts");
|
|
72
|
+
await this.exportTemplate("index.js", "index.js");
|
|
73
|
+
await this.exportTemplate("module-ambient.d.ts", `${name}-ambient.d.ts`);
|
|
74
|
+
await this.exportTemplate("module-ambient.js", `${name}-ambient.js`);
|
|
75
|
+
await this.exportTemplate("module-import.d.ts", `${name}-import.d.ts`);
|
|
76
|
+
await this.exportTemplate("module-import.js", `${name}-import.js`);
|
|
77
|
+
|
|
78
|
+
const pkg = new NpmPackage(
|
|
79
|
+
this.config,
|
|
80
|
+
this.dependencyManager,
|
|
81
|
+
registry,
|
|
82
|
+
girModule,
|
|
83
|
+
girModule.transitiveDependencies,
|
|
84
|
+
);
|
|
85
|
+
await pkg.exportNPMPackage();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BinaryType,
|
|
3
|
+
BooleanType,
|
|
4
|
+
FilterBehavior,
|
|
5
|
+
filterConflicts,
|
|
6
|
+
type GirModule,
|
|
7
|
+
generateIndent,
|
|
8
|
+
type IntrospectedBaseClass,
|
|
9
|
+
IntrospectedClass,
|
|
10
|
+
IntrospectedClassFunction,
|
|
11
|
+
IntrospectedInterface,
|
|
12
|
+
type IntrospectedRecord,
|
|
13
|
+
mergeDescs,
|
|
14
|
+
NumberType,
|
|
15
|
+
type OptionsGeneration,
|
|
16
|
+
VoidType,
|
|
17
|
+
} from "@ts-for-gir/lib";
|
|
18
|
+
import type { ModuleGenerator } from "../module-generator.ts";
|
|
19
|
+
|
|
20
|
+
const SIGNAL_JSDOC = "/** @signal */";
|
|
21
|
+
|
|
22
|
+
/** Handles generation of GObject signal-related TypeScript definitions. */
|
|
23
|
+
export class SignalGenerator {
|
|
24
|
+
constructor(private readonly core: ModuleGenerator) {}
|
|
25
|
+
|
|
26
|
+
private get namespace(): GirModule {
|
|
27
|
+
return this.core.girNamespace;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private get config(): OptionsGeneration {
|
|
31
|
+
return this.core.config;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Generate SignalSignatures interface for type-safe signal handling.
|
|
36
|
+
*
|
|
37
|
+
* Creates a comprehensive mapping of signal names to their callback types,
|
|
38
|
+
* enabling TypeScript to provide proper type checking and IntelliSense for
|
|
39
|
+
* GObject signals using the centralized getAllSignals() method from the model.
|
|
40
|
+
*/
|
|
41
|
+
generateClassSignalInterfaces(girClass: IntrospectedClass, indentCount = 0): string[] {
|
|
42
|
+
const def: string[] = [];
|
|
43
|
+
const indent = generateIndent(indentCount);
|
|
44
|
+
|
|
45
|
+
def.push(`${indent}// Signal signatures`);
|
|
46
|
+
def.push(`${indent}interface SignalSignatures`);
|
|
47
|
+
|
|
48
|
+
const parentSignatures: string[] = [];
|
|
49
|
+
|
|
50
|
+
// Inherit signal signatures from parent class
|
|
51
|
+
const parentResolution = girClass.resolveParents().extends();
|
|
52
|
+
if (parentResolution && parentResolution.node instanceof IntrospectedClass) {
|
|
53
|
+
const parentClass = parentResolution.node as IntrospectedClass;
|
|
54
|
+
const parentTypeIdentifier = parentResolution.identifier
|
|
55
|
+
.resolveIdentifier(this.namespace, this.config)
|
|
56
|
+
?.print(this.namespace, this.config);
|
|
57
|
+
|
|
58
|
+
const hasSignalMethods = parentClass.signals?.length > 0;
|
|
59
|
+
const isNotTemplateWorkaround = !(
|
|
60
|
+
this.namespace.namespace === "Gimp" && ["ParamObject", "ParamItem", "ParamArray"].includes(parentClass.name)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (parentTypeIdentifier && (hasSignalMethods || isNotTemplateWorkaround)) {
|
|
64
|
+
parentSignatures.push(`${parentTypeIdentifier}.SignalSignatures`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Inherit signal signatures from implemented interfaces
|
|
69
|
+
const interfaceSignatures = girClass
|
|
70
|
+
.resolveParents()
|
|
71
|
+
.implements()
|
|
72
|
+
.filter((iface) => iface.node instanceof IntrospectedInterface)
|
|
73
|
+
.filter((iface) => {
|
|
74
|
+
const node = iface.node as unknown as { signals?: unknown[] };
|
|
75
|
+
return node.signals && node.signals.length > 0;
|
|
76
|
+
})
|
|
77
|
+
.map((iface) => {
|
|
78
|
+
const interfaceTypeIdentifier = iface.identifier
|
|
79
|
+
.resolveIdentifier(this.namespace, this.config)
|
|
80
|
+
?.print(this.namespace, this.config);
|
|
81
|
+
return interfaceTypeIdentifier ? `${interfaceTypeIdentifier}.SignalSignatures` : null;
|
|
82
|
+
})
|
|
83
|
+
.filter((sig): sig is string => !!sig);
|
|
84
|
+
|
|
85
|
+
parentSignatures.push(...interfaceSignatures);
|
|
86
|
+
|
|
87
|
+
if (parentSignatures.length > 0) {
|
|
88
|
+
def.push(` extends ${parentSignatures.join(", ")} {`);
|
|
89
|
+
} else {
|
|
90
|
+
const isGObjectObject = girClass.name === "Object" && girClass.namespace.namespace === "GObject";
|
|
91
|
+
|
|
92
|
+
if (isGObjectObject) {
|
|
93
|
+
def.push(" {");
|
|
94
|
+
} else {
|
|
95
|
+
const gobjectNamespace = this.namespace.assertInstalledImport("GObject");
|
|
96
|
+
const gobjectObjectClass = gobjectNamespace.assertClass("Object");
|
|
97
|
+
const gobjectRef = gobjectObjectClass
|
|
98
|
+
.getType()
|
|
99
|
+
.resolveIdentifier(this.namespace, this.config)
|
|
100
|
+
?.print(this.namespace, this.config);
|
|
101
|
+
|
|
102
|
+
const fallbackRef = gobjectRef ? `${gobjectRef}.SignalSignatures` : "GObject.Object.SignalSignatures";
|
|
103
|
+
def.push(` extends ${fallbackRef} {`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const allSignals = girClass.getAllSignals();
|
|
108
|
+
|
|
109
|
+
allSignals.forEach((signalInfo) => {
|
|
110
|
+
const signalKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(signalInfo.name) ? signalInfo.name : `"${signalInfo.name}"`;
|
|
111
|
+
|
|
112
|
+
let cbType: string;
|
|
113
|
+
|
|
114
|
+
if (signalInfo.isNotifySignal) {
|
|
115
|
+
const gobjectRef = this.namespace.namespace === "GObject" ? "" : "GObject.";
|
|
116
|
+
cbType = `(pspec: ${gobjectRef}ParamSpec) => void`;
|
|
117
|
+
} else if (signalInfo.signal) {
|
|
118
|
+
const paramTypes = signalInfo.signal.parameters
|
|
119
|
+
.map((p, idx) => `arg${idx}: ${this.core.generateType(p.type)}`)
|
|
120
|
+
.join(", ");
|
|
121
|
+
|
|
122
|
+
let returnType = signalInfo.signal.return_type;
|
|
123
|
+
if (signalInfo.signal.return_type.equals(BooleanType)) {
|
|
124
|
+
returnType = new BinaryType(BooleanType, VoidType);
|
|
125
|
+
}
|
|
126
|
+
const returnTypeStr = this.core.generateType(returnType);
|
|
127
|
+
|
|
128
|
+
cbType = `(${paramTypes}) => ${returnTypeStr}`;
|
|
129
|
+
} else {
|
|
130
|
+
const paramTypes = signalInfo.parameterTypes?.map((type, idx) => `arg${idx}: ${type}`) || [];
|
|
131
|
+
const returnTypeStr = signalInfo.returnType || "void";
|
|
132
|
+
cbType = `(${paramTypes.join(", ")}) => ${returnTypeStr}`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Add signal doc comment with @signal tag and signal-specific modifier tags
|
|
136
|
+
if (!signalInfo.isNotifySignal && signalInfo.signal) {
|
|
137
|
+
const signalTags = [
|
|
138
|
+
{ tagName: "signal", paramName: "", text: "" },
|
|
139
|
+
...this.namespace.getTsDocMetadataTags(signalInfo.signal.metadata),
|
|
140
|
+
];
|
|
141
|
+
if (signalInfo.signal.detailed) signalTags.push({ tagName: "detailed", paramName: "", text: "" });
|
|
142
|
+
if (signalInfo.signal.action) signalTags.push({ tagName: "action", paramName: "", text: "" });
|
|
143
|
+
if (signalInfo.signal.when)
|
|
144
|
+
signalTags.push({ tagName: `run-${signalInfo.signal.when}`, paramName: "", text: "" });
|
|
145
|
+
const comment = this.core.addGirDocComment(signalInfo.signal.doc, signalTags, indentCount + 1);
|
|
146
|
+
if (comment.length) {
|
|
147
|
+
def.push(...comment);
|
|
148
|
+
} else {
|
|
149
|
+
def.push(`${indent} /** @signal */`);
|
|
150
|
+
}
|
|
151
|
+
} else if (!signalInfo.isNotifySignal) {
|
|
152
|
+
def.push(`${indent} /** @signal */`);
|
|
153
|
+
}
|
|
154
|
+
def.push(`${indent} ${signalKey}: ${cbType};`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
def.push(`${indent}}`);
|
|
158
|
+
def.push("");
|
|
159
|
+
|
|
160
|
+
return def;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Generate signal methods section with header comment
|
|
165
|
+
*/
|
|
166
|
+
generateClassSignals(girClass: IntrospectedClass): string[] {
|
|
167
|
+
return mergeDescs(this.generateSignalMethods(girClass), "Signals", 1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Generate the $signals property for type-safe signal access
|
|
172
|
+
*/
|
|
173
|
+
generateClassSignalsProperty(girClass: IntrospectedClass | IntrospectedRecord, indentCount = 1): string[] {
|
|
174
|
+
const isGObjectObject = girClass.name === "Object" && girClass.namespace.namespace === "GObject";
|
|
175
|
+
const hasGObjectParent =
|
|
176
|
+
isGObjectObject ||
|
|
177
|
+
girClass.someParent((p: IntrospectedBaseClass) => p.namespace.namespace === "GObject" && p.name === "Object");
|
|
178
|
+
|
|
179
|
+
if (!hasGObjectParent) return [];
|
|
180
|
+
|
|
181
|
+
const indent = generateIndent(indentCount);
|
|
182
|
+
return [
|
|
183
|
+
"",
|
|
184
|
+
`${indent}/**`,
|
|
185
|
+
`${indent} * Compile-time signal type information.`,
|
|
186
|
+
`${indent} *`,
|
|
187
|
+
`${indent} * This instance property is generated only for TypeScript type checking.`,
|
|
188
|
+
`${indent} * It is not defined at runtime and should not be accessed in JS code.`,
|
|
189
|
+
`${indent} * @internal`,
|
|
190
|
+
`${indent} */`,
|
|
191
|
+
`${indent}$signals: ${girClass.name}.SignalSignatures;`,
|
|
192
|
+
"",
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Generate type-safe connect/connect_after/emit signal methods
|
|
198
|
+
*/
|
|
199
|
+
private generateSignalMethods(girClass: IntrospectedClass): string[] {
|
|
200
|
+
const signalFunctions = [
|
|
201
|
+
new IntrospectedClassFunction({
|
|
202
|
+
name: "connect",
|
|
203
|
+
parent: girClass,
|
|
204
|
+
parameters: [],
|
|
205
|
+
return_type: NumberType,
|
|
206
|
+
}),
|
|
207
|
+
new IntrospectedClassFunction({
|
|
208
|
+
name: "connect_after",
|
|
209
|
+
parent: girClass,
|
|
210
|
+
parameters: [],
|
|
211
|
+
return_type: NumberType,
|
|
212
|
+
}),
|
|
213
|
+
new IntrospectedClassFunction({
|
|
214
|
+
name: "emit",
|
|
215
|
+
parent: girClass,
|
|
216
|
+
parameters: [],
|
|
217
|
+
return_type: VoidType,
|
|
218
|
+
}),
|
|
219
|
+
];
|
|
220
|
+
|
|
221
|
+
const filteredFunctions = filterConflicts(girClass.namespace, girClass, signalFunctions, FilterBehavior.DELETE);
|
|
222
|
+
const allowedNames = new Set(filteredFunctions.map((f) => f.name));
|
|
223
|
+
|
|
224
|
+
const gobjectRef = this.namespace.namespace === "GObject" ? "" : "GObject.";
|
|
225
|
+
|
|
226
|
+
const methods: string[] = [];
|
|
227
|
+
|
|
228
|
+
if (allowedNames.has("connect")) {
|
|
229
|
+
methods.push(
|
|
230
|
+
SIGNAL_JSDOC,
|
|
231
|
+
`connect<K extends keyof ${girClass.name}.SignalSignatures>(signal: K, callback: ${gobjectRef}SignalCallback<this, ${girClass.name}.SignalSignatures[K]>): number;`,
|
|
232
|
+
"connect(signal: string, callback: (...args: any[]) => any): number;",
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (allowedNames.has("connect_after")) {
|
|
237
|
+
methods.push(
|
|
238
|
+
SIGNAL_JSDOC,
|
|
239
|
+
`connect_after<K extends keyof ${girClass.name}.SignalSignatures>(signal: K, callback: ${gobjectRef}SignalCallback<this, ${girClass.name}.SignalSignatures[K]>): number;`,
|
|
240
|
+
"connect_after(signal: string, callback: (...args: any[]) => any): number;",
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (allowedNames.has("emit")) {
|
|
245
|
+
methods.push(
|
|
246
|
+
SIGNAL_JSDOC,
|
|
247
|
+
`emit<K extends keyof ${girClass.name}.SignalSignatures>(signal: K, ...args: ${gobjectRef}GjsParameters<${girClass.name}.SignalSignatures[K]> extends [any, ...infer Q] ? Q : never): void;`,
|
|
248
|
+
"emit(signal: string, ...args: any[]): void;",
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return methods;
|
|
253
|
+
}
|
|
254
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example usage of the refactored ModuleGenerator
|
|
3
|
+
*
|
|
4
|
+
* This demonstrates how the unified ModuleGenerator now incorporates
|
|
5
|
+
* functionality from DtsGenerator and DtsModuleGenerator
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { GirModule, NSRegistry, OptionsGeneration } from "@ts-for-gir/lib";
|
|
9
|
+
import { ModuleGenerator } from "./module-generator.ts";
|
|
10
|
+
|
|
11
|
+
// Example: Using ModuleGenerator with different output formats
|
|
12
|
+
async function generateTypeDefinitions(girModule: GirModule, config: OptionsGeneration, registry: NSRegistry) {
|
|
13
|
+
// Create a ModuleGenerator instance
|
|
14
|
+
const generator = new ModuleGenerator(girModule, config, registry);
|
|
15
|
+
|
|
16
|
+
// 1. Generate as string array (default behavior)
|
|
17
|
+
const arrayOutput = await generator.generateModule(girModule);
|
|
18
|
+
console.log("String array output:", arrayOutput);
|
|
19
|
+
|
|
20
|
+
// 2. Generate as single string (DtsGenerator compatibility)
|
|
21
|
+
const stringOutput = await generator.generateModuleString(girModule);
|
|
22
|
+
console.log("String output:", stringOutput);
|
|
23
|
+
|
|
24
|
+
// 3. Generate as module declaration (DtsModuleGenerator compatibility)
|
|
25
|
+
const moduleDeclaration = await generator.generateModuleDeclaration(girModule);
|
|
26
|
+
console.log("Module declaration output:", moduleDeclaration);
|
|
27
|
+
|
|
28
|
+
// 4. Generate namespace as string
|
|
29
|
+
const namespaceString = await generator.generateNamespaceAsString(girModule);
|
|
30
|
+
console.log("Namespace string output:", namespaceString);
|
|
31
|
+
|
|
32
|
+
// 5. The AdvancedVariants feature is automatically applied
|
|
33
|
+
// when generating GLib or GObject modules (unless disabled with noAdvancedVariants option)
|
|
34
|
+
if (girModule.namespace === "GLib" && !config.noAdvancedVariants) {
|
|
35
|
+
console.log("GLib module will include advanced variant type definitions");
|
|
36
|
+
}
|
|
37
|
+
if (girModule.namespace === "GObject") {
|
|
38
|
+
console.log("GObject module will include registerClass overrides");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Example: Migrating from DtsGenerator
|
|
43
|
+
function migrateFromDtsGenerator(girModule: GirModule, config: OptionsGeneration, registry: NSRegistry) {
|
|
44
|
+
// Before (using DtsGenerator):
|
|
45
|
+
// const generator = new DtsGenerator(girModule, config);
|
|
46
|
+
// const output = await generator.generateNamespace(girModule);
|
|
47
|
+
|
|
48
|
+
// After (using ModuleGenerator):
|
|
49
|
+
const generator = new ModuleGenerator(girModule, config, registry);
|
|
50
|
+
const output = generator.generateNamespaceAsString(girModule);
|
|
51
|
+
|
|
52
|
+
return output;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Example: Migrating from DtsModuleGenerator
|
|
56
|
+
function migrateFromDtsModuleGenerator(girModule: GirModule, config: OptionsGeneration, registry: NSRegistry) {
|
|
57
|
+
// Before (using DtsModuleGenerator):
|
|
58
|
+
// const generator = new DtsModuleGenerator(girModule, config);
|
|
59
|
+
// const output = await generator.generateNamespace(girModule);
|
|
60
|
+
|
|
61
|
+
// After (using ModuleGenerator):
|
|
62
|
+
const generator = new ModuleGenerator(girModule, config, registry);
|
|
63
|
+
const output = generator.generateModuleDeclaration(girModule);
|
|
64
|
+
|
|
65
|
+
return output;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { generateTypeDefinitions, migrateFromDtsGenerator, migrateFromDtsModuleGenerator };
|