@ts-for-gir/lib 4.0.0-beta.40 → 4.0.0-beta.42
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/package.json +7 -6
- package/src/constants.ts +13 -47
- package/src/gir/alias.ts +2 -2
- package/src/gir/introspected-classes.ts +32 -69
- package/src/gir/record.ts +1 -1
- package/src/gir/registry.ts +0 -1
- package/src/gir/signal.ts +32 -0
- package/src/gir-module.ts +125 -165
- package/src/gir.ts +15 -39
- package/src/injections/gio.ts +14 -1
- package/src/injections/glib.ts +5 -0
- package/src/injections/gobject.ts +5 -0
- package/src/types/options-generation.ts +12 -0
- package/src/types/user-config.ts +12 -0
- package/src/utils/conflicts.ts +11 -45
- package/src/utils/documentation.ts +437 -27
- package/src/utils/gir-parsing.ts +31 -12
- package/src/utils/types.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-for-gir/lib",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.42",
|
|
4
4
|
"description": "Typescript .d.ts generator from GIR for gjs",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -41,18 +41,19 @@
|
|
|
41
41
|
"type definitions"
|
|
42
42
|
],
|
|
43
43
|
"devDependencies": {
|
|
44
|
+
"@ts-for-gir/tsconfig": "^4.0.0-beta.42",
|
|
44
45
|
"@types/ejs": "^3.1.5",
|
|
45
46
|
"@types/lodash": "^4.17.24",
|
|
46
|
-
"@types/node": "^24.
|
|
47
|
+
"@types/node": "^24.12.0",
|
|
47
48
|
"rimraf": "^6.1.3",
|
|
48
49
|
"typescript": "^5.9.3"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
51
|
-
"@gi.ts/parser": "^4.0.0-beta.
|
|
52
|
-
"@ts-for-gir/reporter": "^4.0.0-beta.
|
|
53
|
-
"@ts-for-gir/templates": "^4.0.0-beta.
|
|
52
|
+
"@gi.ts/parser": "^4.0.0-beta.42",
|
|
53
|
+
"@ts-for-gir/reporter": "^4.0.0-beta.42",
|
|
54
|
+
"@ts-for-gir/templates": "^4.0.0-beta.42",
|
|
54
55
|
"colorette": "^2.0.20",
|
|
55
|
-
"ejs": "^
|
|
56
|
+
"ejs": "^5.0.1",
|
|
56
57
|
"glob": "^13.0.6",
|
|
57
58
|
"lodash": "^4.17.23"
|
|
58
59
|
}
|
package/src/constants.ts
CHANGED
|
@@ -8,61 +8,27 @@ export const PARAM_REG_EXP = /[0-9a-zA-Z_]*:/g;
|
|
|
8
8
|
export const OPT_PARAM_REG_EXP = /[0-9a-zA-Z_]*\?:/g;
|
|
9
9
|
export const NEW_LINE_REG_EXP = /[\n\r]+/g;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
* Package information interface for package.json
|
|
13
|
-
*/
|
|
14
|
-
interface Package {
|
|
15
|
-
name: string;
|
|
16
|
-
version: string;
|
|
17
|
-
description: string;
|
|
18
|
-
license: string;
|
|
19
|
-
homepage: string;
|
|
20
|
-
author: string;
|
|
21
|
-
}
|
|
11
|
+
declare const __TS_FOR_GIR_VERSION__: string;
|
|
22
12
|
|
|
23
13
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* Works both in workspace and after publishing
|
|
14
|
+
* Reads the package version, using the build-time injected value when bundled
|
|
15
|
+
* or falling back to reading package.json in development mode.
|
|
27
16
|
*/
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const currentModulePath = fileURLToPath(import.meta.url);
|
|
32
|
-
const currentDir = dirname(currentModulePath);
|
|
33
|
-
|
|
34
|
-
// Go up to the package root (src/ -> package root)
|
|
35
|
-
const packageRoot = join(currentDir, "..");
|
|
36
|
-
const packageJsonPath = join(packageRoot, "package.json");
|
|
37
|
-
|
|
38
|
-
return packageJsonPath;
|
|
39
|
-
} catch (error) {
|
|
40
|
-
throw new Error(`Unable to resolve package.json path: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
17
|
+
function getPackageVersion(): string {
|
|
18
|
+
if (typeof __TS_FOR_GIR_VERSION__ !== "undefined") {
|
|
19
|
+
return __TS_FOR_GIR_VERSION__;
|
|
41
20
|
}
|
|
21
|
+
const currentModulePath = fileURLToPath(import.meta.url);
|
|
22
|
+
const currentDir = dirname(currentModulePath);
|
|
23
|
+
const packageJsonPath = join(currentDir, "..", "package.json");
|
|
24
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
25
|
+
return (JSON.parse(content) as { version: string }).version;
|
|
42
26
|
}
|
|
43
27
|
|
|
44
|
-
/**
|
|
45
|
-
* Reads and parses the current package's package.json file synchronously
|
|
46
|
-
* Contains version and metadata for this specific package
|
|
47
|
-
*/
|
|
48
|
-
function readPackageSync(): Package {
|
|
49
|
-
try {
|
|
50
|
-
const packagePath = resolvePackageJson();
|
|
51
|
-
const content = readFileSync(packagePath, "utf-8");
|
|
52
|
-
return JSON.parse(content) as Package;
|
|
53
|
-
} catch (error) {
|
|
54
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
55
|
-
throw new Error(`Failed to read package.json: ${message}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Read package information once at module load
|
|
60
|
-
export const PACKAGE = readPackageSync();
|
|
61
|
-
|
|
62
28
|
export const APP_NAME = "ts-for-gir";
|
|
63
29
|
export const APP_USAGE = "TypeScript type definition generator for GObject introspection GIR files";
|
|
64
30
|
export const APP_SOURCE = "https://github.com/gjsify/ts-for-gir";
|
|
65
|
-
export const APP_VERSION =
|
|
31
|
+
export const APP_VERSION = getPackageVersion();
|
|
66
32
|
|
|
67
33
|
export const PACKAGE_DESC = (packageName: string, libraryVersion?: LibraryVersion) => {
|
|
68
34
|
if (libraryVersion) {
|
|
@@ -149,4 +115,4 @@ export const RESERVED_CLASS_NAMES = [
|
|
|
149
115
|
|
|
150
116
|
export const RESERVED_FUNCTION_NAMES = ["false", "true", "break"];
|
|
151
117
|
|
|
152
|
-
export const RESERVED_NAMESPACE_NAMES = {};
|
|
118
|
+
export const RESERVED_NAMESPACE_NAMES: Record<string, boolean> = {};
|
package/src/gir/alias.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { FormatGenerator, GenericDescriptor } from "../generators/generator
|
|
|
2
2
|
import type { TypeExpression } from "../gir.ts";
|
|
3
3
|
import type { GirAliasElement } from "../index.ts";
|
|
4
4
|
import type { IntrospectedOptions, OptionsLoad } from "../types/index.ts";
|
|
5
|
-
import { parseDoc, parseMetadata } from "../utils/gir-parsing.ts";
|
|
5
|
+
import { girParsingReporter, parseDoc, parseMetadata } from "../utils/gir-parsing.ts";
|
|
6
6
|
import { isIntrospectable } from "../utils/girs.ts";
|
|
7
7
|
import { sanitizeIdentifierName } from "../utils/naming.ts";
|
|
8
8
|
import { getAliasType } from "../utils/types.ts";
|
|
@@ -52,7 +52,7 @@ export class IntrospectedAlias extends IntrospectedNamespaceMember {
|
|
|
52
52
|
|
|
53
53
|
static fromXML(element: GirAliasElement, ns: IntrospectedNamespace, options: OptionsLoad): IntrospectedAlias | null {
|
|
54
54
|
if (!element.$.name) {
|
|
55
|
-
|
|
55
|
+
girParsingReporter.get().reportParsingFailure("alias", "alias", ns.namespace, "Alias lacks name attribute");
|
|
56
56
|
return null;
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -72,6 +72,8 @@ export class IntrospectedClassFunction<
|
|
|
72
72
|
protected _generify: boolean = false;
|
|
73
73
|
interfaceParent: IntrospectedBaseClass | IntrospectedEnum | null = null;
|
|
74
74
|
returnTypeDoc?: string | null;
|
|
75
|
+
/** If this function was generated from a signal, stores the signal name. */
|
|
76
|
+
signalOrigin?: string;
|
|
75
77
|
|
|
76
78
|
generics: Generic[] = [];
|
|
77
79
|
|
|
@@ -794,105 +796,66 @@ export class IntrospectedClass extends IntrospectedBaseClass {
|
|
|
794
796
|
);
|
|
795
797
|
}
|
|
796
798
|
|
|
797
|
-
|
|
799
|
+
private collectImplementedItems<T extends { name: string }>(
|
|
800
|
+
getItems: (node: IntrospectedBaseClass) => T[],
|
|
801
|
+
validate: (item: T) => boolean,
|
|
802
|
+
): Map<string, T> {
|
|
798
803
|
const resolution = this.resolveParents();
|
|
799
804
|
const implementedOnParent = [...(resolution.extends() ?? [])].flatMap((r) => r.implements());
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
const validateProp = (prop: IntrospectedProperty) =>
|
|
803
|
-
!this.hasInstanceSymbol(prop) &&
|
|
804
|
-
!properties.has(prop.name) &&
|
|
805
|
-
potentialConflicts.every((p) => prop.name !== p.name);
|
|
805
|
+
const items = new Map<string, T>();
|
|
806
806
|
|
|
807
807
|
for (const implemented of resolution.implements()) {
|
|
808
808
|
if (implemented.node instanceof IntrospectedClass) continue;
|
|
809
|
-
|
|
810
809
|
if (implementedOnParent.find((p) => p.identifier.equals(implemented.identifier))?.node?.generics?.length === 0)
|
|
811
810
|
continue;
|
|
812
|
-
for (const
|
|
813
|
-
if (!
|
|
814
|
-
|
|
811
|
+
for (const item of getItems(implemented.node)) {
|
|
812
|
+
if (items.has(item.name) || !validate(item)) continue;
|
|
813
|
+
items.set(item.name, item);
|
|
815
814
|
}
|
|
816
815
|
}
|
|
817
816
|
|
|
818
817
|
for (const implemented of resolution.implements()) {
|
|
819
818
|
[...implemented].forEach((e) => {
|
|
820
819
|
if (e.node instanceof IntrospectedClass) return;
|
|
821
|
-
|
|
822
820
|
if (implementedOnParent.find((p) => p.identifier.equals(e.identifier))?.node.generics.length === 0) return;
|
|
823
|
-
for (const
|
|
824
|
-
if (!
|
|
825
|
-
|
|
826
|
-
properties.set(prop.name, prop);
|
|
821
|
+
for (const item of getItems(e.node)) {
|
|
822
|
+
if (items.has(item.name) || !validate(item)) continue;
|
|
823
|
+
items.set(item.name, item);
|
|
827
824
|
}
|
|
828
825
|
});
|
|
829
826
|
}
|
|
830
827
|
|
|
831
828
|
// If an interface inherits from a class (such as Gtk.Widget)
|
|
832
|
-
// we need to pull in every
|
|
829
|
+
// we need to pull in every item from that class...
|
|
833
830
|
for (const implemented of resolution.implements()) {
|
|
834
831
|
const extended = implemented.extends();
|
|
835
|
-
|
|
836
832
|
if (extended?.node instanceof IntrospectedClass) {
|
|
837
|
-
for (const
|
|
838
|
-
if (!
|
|
839
|
-
|
|
840
|
-
properties.set(prop.name, prop);
|
|
833
|
+
for (const item of getItems(extended.node)) {
|
|
834
|
+
if (items.has(item.name) || !validate(item)) continue;
|
|
835
|
+
items.set(item.name, item);
|
|
841
836
|
}
|
|
842
837
|
}
|
|
843
838
|
}
|
|
844
839
|
|
|
840
|
+
return items;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
implementedProperties(potentialConflicts: IntrospectedBase<never>[] = []) {
|
|
844
|
+
const properties = this.collectImplementedItems(
|
|
845
|
+
(node) => node.props,
|
|
846
|
+
(prop) => !this.hasInstanceSymbol(prop) && potentialConflicts.every((p) => prop.name !== p.name),
|
|
847
|
+
);
|
|
845
848
|
return [...properties.values()];
|
|
846
849
|
}
|
|
847
850
|
|
|
848
851
|
implementedMethods(potentialConflicts: ClassMember[] = []) {
|
|
849
|
-
const
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
!methods.has(method.name) &&
|
|
857
|
-
potentialConflicts.every((m) => method.name !== m.name);
|
|
858
|
-
|
|
859
|
-
for (const implemented of resolution.implements()) {
|
|
860
|
-
if (implemented.node instanceof IntrospectedClass) continue;
|
|
861
|
-
|
|
862
|
-
if (implementedOnParent.find((p) => p.identifier.equals(implemented.identifier))?.node?.generics?.length === 0)
|
|
863
|
-
continue;
|
|
864
|
-
for (const member of implemented.node.members) {
|
|
865
|
-
if (!validateMethod(member)) continue;
|
|
866
|
-
methods.set(member.name, member);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
for (const implemented of resolution.implements()) {
|
|
871
|
-
[...implemented].forEach((e) => {
|
|
872
|
-
if (e.node instanceof IntrospectedClass) return;
|
|
873
|
-
|
|
874
|
-
if (implementedOnParent.find((p) => p.identifier.equals(e.identifier))?.node.generics.length === 0) return;
|
|
875
|
-
for (const member of e.node.members) {
|
|
876
|
-
if (!validateMethod(member)) continue;
|
|
877
|
-
|
|
878
|
-
methods.set(member.name, member);
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
// If an interface inherits from a class (such as Gtk.Widget)
|
|
884
|
-
// we need to pull in every method from that class...
|
|
885
|
-
for (const implemented of resolution.implements()) {
|
|
886
|
-
const extended = implemented.extends();
|
|
887
|
-
|
|
888
|
-
if (extended?.node instanceof IntrospectedClass) {
|
|
889
|
-
for (const member of extended.node.members) {
|
|
890
|
-
if (!validateMethod(member)) continue;
|
|
891
|
-
|
|
892
|
-
methods.set(member.name, member);
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
}
|
|
852
|
+
const methods = this.collectImplementedItems(
|
|
853
|
+
(node) => node.members,
|
|
854
|
+
(method) =>
|
|
855
|
+
!(method instanceof IntrospectedStaticClassFunction) &&
|
|
856
|
+
!this.hasInstanceSymbol(method) &&
|
|
857
|
+
potentialConflicts.every((m) => method.name !== m.name),
|
|
858
|
+
);
|
|
896
859
|
|
|
897
860
|
return [...methods.values()].map((f) => {
|
|
898
861
|
const mapping = new Map<string, TypeExpression>();
|
package/src/gir/record.ts
CHANGED
|
@@ -248,7 +248,7 @@ export class IntrospectedRecord extends IntrospectedBaseClass {
|
|
|
248
248
|
namespace: IntrospectedNamespace,
|
|
249
249
|
name: string,
|
|
250
250
|
): void {
|
|
251
|
-
const gtypeStructFor = element.$["glib:is-gtype-struct-for"];
|
|
251
|
+
const gtypeStructFor = "glib:is-gtype-struct-for" in element.$ ? element.$["glib:is-gtype-struct-for"] : undefined;
|
|
252
252
|
|
|
253
253
|
if (typeof gtypeStructFor === "string" && gtypeStructFor) {
|
|
254
254
|
const structFor = parseTypeIdentifier(namespace.namespace, gtypeStructFor);
|
package/src/gir/registry.ts
CHANGED
|
@@ -13,7 +13,6 @@ import { InterfaceVisitor } from "../validators/interface.ts";
|
|
|
13
13
|
import type { GirVisitor } from "../visitor.ts";
|
|
14
14
|
import type { IntrospectedNamespace } from "./namespace.ts";
|
|
15
15
|
|
|
16
|
-
// TODO: Singleton
|
|
17
16
|
export class NSRegistry {
|
|
18
17
|
mapping: TwoKeyMap<string, string, IntrospectedNamespace> = new TwoKeyMap();
|
|
19
18
|
private formatters: Map<string, Formatter> = new Map();
|
package/src/gir/signal.ts
CHANGED
|
@@ -34,12 +34,20 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
|
|
|
34
34
|
parameters: IntrospectedFunctionParameter[];
|
|
35
35
|
return_type: TypeExpression;
|
|
36
36
|
detailed: boolean;
|
|
37
|
+
action: boolean;
|
|
38
|
+
noRecurse: boolean;
|
|
39
|
+
noHooks: boolean;
|
|
40
|
+
when?: "first" | "last" | "cleanup";
|
|
37
41
|
|
|
38
42
|
constructor({
|
|
39
43
|
name,
|
|
40
44
|
parameters = [],
|
|
41
45
|
return_type = UnknownType,
|
|
42
46
|
detailed = false,
|
|
47
|
+
action = false,
|
|
48
|
+
noRecurse = false,
|
|
49
|
+
noHooks = false,
|
|
50
|
+
when,
|
|
43
51
|
parent,
|
|
44
52
|
...args
|
|
45
53
|
}: Options<{
|
|
@@ -47,6 +55,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
|
|
|
47
55
|
parameters?: IntrospectedFunctionParameter[];
|
|
48
56
|
return_type?: TypeExpression;
|
|
49
57
|
detailed?: boolean;
|
|
58
|
+
action?: boolean;
|
|
59
|
+
noRecurse?: boolean;
|
|
60
|
+
noHooks?: boolean;
|
|
61
|
+
when?: "first" | "last" | "cleanup";
|
|
50
62
|
parent: IntrospectedClass;
|
|
51
63
|
}>) {
|
|
52
64
|
super(name, parent, { ...args });
|
|
@@ -54,6 +66,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
|
|
|
54
66
|
this.parameters = parameters.map((p) => p.copy({ parent: this }));
|
|
55
67
|
this.return_type = return_type;
|
|
56
68
|
this.detailed = detailed;
|
|
69
|
+
this.action = action;
|
|
70
|
+
this.noRecurse = noRecurse;
|
|
71
|
+
this.noHooks = noHooks;
|
|
72
|
+
this.when = when;
|
|
57
73
|
}
|
|
58
74
|
|
|
59
75
|
accept(visitor: GirVisitor): IntrospectedSignal {
|
|
@@ -72,11 +88,19 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
|
|
|
72
88
|
parameters,
|
|
73
89
|
returnType,
|
|
74
90
|
detailed,
|
|
91
|
+
action,
|
|
92
|
+
noRecurse,
|
|
93
|
+
noHooks,
|
|
94
|
+
when,
|
|
75
95
|
}: {
|
|
76
96
|
parent?: IntrospectedClass;
|
|
77
97
|
parameters?: IntrospectedFunctionParameter[];
|
|
78
98
|
returnType?: TypeExpression;
|
|
79
99
|
detailed?: boolean;
|
|
100
|
+
action?: boolean;
|
|
101
|
+
noRecurse?: boolean;
|
|
102
|
+
noHooks?: boolean;
|
|
103
|
+
when?: "first" | "last" | "cleanup";
|
|
80
104
|
} = {}): IntrospectedSignal {
|
|
81
105
|
return new IntrospectedSignal({
|
|
82
106
|
name: this.name,
|
|
@@ -84,6 +108,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
|
|
|
84
108
|
parameters: parameters ?? this.parameters,
|
|
85
109
|
return_type: returnType ?? this.return_type,
|
|
86
110
|
detailed: detailed ?? this.detailed,
|
|
111
|
+
action: action ?? this.action,
|
|
112
|
+
noRecurse: noRecurse ?? this.noRecurse,
|
|
113
|
+
noHooks: noHooks ?? this.noHooks,
|
|
114
|
+
when: when ?? this.when,
|
|
87
115
|
})._copyBaseProperties(this);
|
|
88
116
|
}
|
|
89
117
|
|
|
@@ -93,6 +121,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
|
|
|
93
121
|
name: element.$.name,
|
|
94
122
|
parent,
|
|
95
123
|
detailed: element.$.detailed === "1",
|
|
124
|
+
action: element.$.action === "1",
|
|
125
|
+
noRecurse: element.$["no-recurse"] === "1",
|
|
126
|
+
noHooks: element.$["no-hooks"] === "1",
|
|
127
|
+
when: element.$.when as "first" | "last" | "cleanup" | undefined,
|
|
96
128
|
isIntrospectable: isIntrospectable(element),
|
|
97
129
|
});
|
|
98
130
|
|