@gtkx/gir 0.19.0 → 0.21.0
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/dist/index.d.ts +25 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -10
- package/dist/index.js.map +1 -1
- package/dist/internal/loader.d.ts +30 -0
- package/dist/internal/loader.d.ts.map +1 -0
- package/dist/internal/loader.js +109 -0
- package/dist/internal/loader.js.map +1 -0
- package/dist/internal/normalizer.d.ts +98 -15
- package/dist/internal/normalizer.d.ts.map +1 -1
- package/dist/internal/normalizer.js +381 -412
- package/dist/internal/normalizer.js.map +1 -1
- package/dist/internal/parser.d.ts +23 -31
- package/dist/internal/parser.d.ts.map +1 -1
- package/dist/internal/parser.js +228 -244
- package/dist/internal/parser.js.map +1 -1
- package/dist/internal/raw-types.d.ts +58 -109
- package/dist/internal/raw-types.d.ts.map +1 -1
- package/dist/internal/raw-types.js +0 -8
- package/dist/internal/raw-types.js.map +1 -1
- package/dist/intrinsics.d.ts.map +1 -1
- package/dist/intrinsics.js +7 -0
- package/dist/intrinsics.js.map +1 -1
- package/dist/model/alias.d.ts +21 -0
- package/dist/model/alias.d.ts.map +1 -0
- package/dist/model/alias.js +22 -0
- package/dist/model/alias.js.map +1 -0
- package/dist/model/callables.d.ts +102 -0
- package/dist/model/callables.d.ts.map +1 -0
- package/dist/model/callables.js +123 -0
- package/dist/model/callables.js.map +1 -0
- package/dist/model/callback.d.ts +22 -0
- package/dist/model/callback.d.ts.map +1 -0
- package/dist/model/callback.js +20 -0
- package/dist/model/callback.js.map +1 -0
- package/dist/model/class.d.ts +92 -0
- package/dist/model/class.d.ts.map +1 -0
- package/dist/model/class.js +171 -0
- package/dist/model/class.js.map +1 -0
- package/dist/model/constant.d.ts +21 -0
- package/dist/model/constant.d.ts.map +1 -0
- package/dist/model/constant.js +20 -0
- package/dist/model/constant.js.map +1 -0
- package/dist/model/enumeration.d.ts +41 -0
- package/dist/model/enumeration.d.ts.map +1 -0
- package/dist/model/enumeration.js +47 -0
- package/dist/model/enumeration.js.map +1 -0
- package/dist/model/field.d.ts +21 -0
- package/dist/model/field.d.ts.map +1 -0
- package/dist/model/field.js +20 -0
- package/dist/model/field.js.map +1 -0
- package/dist/model/interface.d.ts +44 -0
- package/dist/model/interface.d.ts.map +1 -0
- package/dist/model/interface.js +67 -0
- package/dist/model/interface.js.map +1 -0
- package/dist/model/namespace.d.ts +44 -0
- package/dist/model/namespace.d.ts.map +1 -0
- package/dist/model/namespace.js +36 -0
- package/dist/model/namespace.js.map +1 -0
- package/dist/model/parameter.d.ts +43 -0
- package/dist/model/parameter.d.ts.map +1 -0
- package/dist/model/parameter.js +54 -0
- package/dist/model/parameter.js.map +1 -0
- package/dist/model/property.d.ts +62 -0
- package/dist/model/property.d.ts.map +1 -0
- package/dist/model/property.js +69 -0
- package/dist/model/property.js.map +1 -0
- package/dist/model/record.d.ts +56 -0
- package/dist/model/record.d.ts.map +1 -0
- package/dist/model/record.js +70 -0
- package/dist/model/record.js.map +1 -0
- package/dist/model/repository-like.d.ts +19 -0
- package/dist/model/repository-like.d.ts.map +1 -0
- package/dist/model/repository-like.js +2 -0
- package/dist/model/repository-like.js.map +1 -0
- package/dist/model/signal.d.ts +22 -0
- package/dist/model/signal.d.ts.map +1 -0
- package/dist/model/signal.js +22 -0
- package/dist/model/signal.js.map +1 -0
- package/dist/model/type.d.ts +71 -0
- package/dist/model/type.d.ts.map +1 -0
- package/dist/model/type.js +112 -0
- package/dist/model/type.js.map +1 -0
- package/dist/repository.d.ts +92 -138
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +155 -219
- package/dist/repository.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +25 -39
- package/src/internal/loader.ts +127 -0
- package/src/internal/normalizer.ts +451 -475
- package/src/internal/parser.ts +242 -284
- package/src/internal/raw-types.ts +65 -116
- package/src/intrinsics.ts +7 -0
- package/src/model/alias.ts +31 -0
- package/src/model/callables.ts +172 -0
- package/src/model/callback.ts +30 -0
- package/src/model/class.ts +215 -0
- package/src/model/constant.ts +29 -0
- package/src/model/enumeration.ts +64 -0
- package/src/model/field.ts +29 -0
- package/src/model/interface.ts +89 -0
- package/src/model/namespace.ts +60 -0
- package/src/model/parameter.ts +74 -0
- package/src/model/property.ts +97 -0
- package/src/model/record.ts +97 -0
- package/src/model/repository-like.ts +20 -0
- package/src/model/signal.ts +32 -0
- package/src/model/type.ts +143 -0
- package/src/repository.ts +197 -283
- package/dist/types.d.ts +0 -655
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -879
- package/dist/types.js.map +0 -1
- package/src/types.ts +0 -1192
package/src/internal/parser.ts
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GObject Introspection XML (GIR) parser.
|
|
3
|
-
*
|
|
4
|
-
* Parses GIR files to extract type information for GTK/GLib libraries.
|
|
5
|
-
* Outputs raw GIR types that are then normalized by the normalizer.
|
|
6
|
-
*
|
|
7
|
-
* @internal
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
1
|
import { XMLParser } from "fast-xml-parser";
|
|
2
|
+
import type { ContainerType } from "../model/type.js";
|
|
11
3
|
import type {
|
|
12
|
-
ContainerType,
|
|
13
4
|
RawAlias,
|
|
14
5
|
RawCallback,
|
|
15
6
|
RawClass,
|
|
16
7
|
RawConstant,
|
|
17
8
|
RawConstructor,
|
|
9
|
+
RawDependency,
|
|
18
10
|
RawEnumeration,
|
|
19
11
|
RawEnumerationMember,
|
|
20
12
|
RawField,
|
|
@@ -25,6 +17,7 @@ import type {
|
|
|
25
17
|
RawParameter,
|
|
26
18
|
RawProperty,
|
|
27
19
|
RawRecord,
|
|
20
|
+
RawRepositoryHeader,
|
|
28
21
|
RawSignal,
|
|
29
22
|
RawType,
|
|
30
23
|
} from "./raw-types.js";
|
|
@@ -40,7 +33,7 @@ const ARRAY_ELEMENT_PATHS = new Set<string>([
|
|
|
40
33
|
"namespace.constant",
|
|
41
34
|
"namespace.alias",
|
|
42
35
|
"namespace.class.method",
|
|
43
|
-
"namespace.class.
|
|
36
|
+
"namespace.class._constructor",
|
|
44
37
|
"namespace.class.function",
|
|
45
38
|
"namespace.class.property",
|
|
46
39
|
"namespace.class.signal",
|
|
@@ -50,11 +43,11 @@ const ARRAY_ELEMENT_PATHS = new Set<string>([
|
|
|
50
43
|
"namespace.interface.signal",
|
|
51
44
|
"namespace.interface.glib:signal",
|
|
52
45
|
"namespace.record.method",
|
|
53
|
-
"namespace.record.
|
|
46
|
+
"namespace.record._constructor",
|
|
54
47
|
"namespace.record.function",
|
|
55
48
|
"namespace.record.field",
|
|
56
49
|
"namespace.class.method.parameters.parameter",
|
|
57
|
-
"namespace.class.
|
|
50
|
+
"namespace.class._constructor.parameters.parameter",
|
|
58
51
|
"namespace.class.function.parameters.parameter",
|
|
59
52
|
"namespace.function.parameters.parameter",
|
|
60
53
|
"namespace.enumeration.member",
|
|
@@ -63,64 +56,86 @@ const ARRAY_ELEMENT_PATHS = new Set<string>([
|
|
|
63
56
|
"namespace.class.glib:signal.parameters.parameter",
|
|
64
57
|
"namespace.interface.glib:signal.parameters.parameter",
|
|
65
58
|
"namespace.record.method.parameters.parameter",
|
|
66
|
-
"namespace.record.
|
|
59
|
+
"namespace.record._constructor.parameters.parameter",
|
|
67
60
|
"namespace.record.function.parameters.parameter",
|
|
68
61
|
"namespace.callback.parameters.parameter",
|
|
69
62
|
]);
|
|
70
63
|
|
|
71
|
-
const
|
|
64
|
+
const INCLUDE_RE = /<include\s+name="([^"]+)"\s+version="([^"]+)"/g;
|
|
65
|
+
const NS_NAME_RE = /<namespace\s[^>]*name="([^"]+)"/;
|
|
66
|
+
const NS_VERSION_RE = /<namespace\s[^>]*version="([^"]+)"/;
|
|
67
|
+
|
|
68
|
+
function extractDoc(node: Record<string, unknown>): string | undefined {
|
|
72
69
|
const doc = node.doc as Record<string, unknown> | undefined;
|
|
73
70
|
if (!doc) return undefined;
|
|
74
71
|
const text = doc["#text"];
|
|
75
72
|
if (typeof text !== "string") return undefined;
|
|
76
73
|
return text.trim();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const ensureArray = (value: unknown): Record<string, unknown>[] =>
|
|
80
|
-
Array.isArray(value) ? (value as Record<string, unknown>[]) : [];
|
|
74
|
+
}
|
|
81
75
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
76
|
+
function ensureArray(value: unknown): Record<string, unknown>[] {
|
|
77
|
+
return Array.isArray(value) ? (value as Record<string, unknown>[]) : [];
|
|
78
|
+
}
|
|
85
79
|
|
|
86
80
|
/**
|
|
87
81
|
* Parser for GObject Introspection XML (GIR) files.
|
|
88
82
|
*
|
|
89
|
-
*
|
|
83
|
+
* Provides both a lightweight header parse (for dependency graph discovery)
|
|
84
|
+
* and a full parse (for complete namespace extraction).
|
|
90
85
|
*/
|
|
91
|
-
export class
|
|
92
|
-
private parser: XMLParser;
|
|
93
|
-
private includeNonIntrospectableNamespaces: Set<string>;
|
|
94
|
-
private currentNamespace: string = "";
|
|
86
|
+
export class GirParser {
|
|
87
|
+
private readonly parser: XMLParser;
|
|
95
88
|
|
|
96
|
-
constructor(
|
|
97
|
-
this.includeNonIntrospectableNamespaces = options.includeNonIntrospectableNamespaces ?? new Set();
|
|
89
|
+
constructor() {
|
|
98
90
|
this.parser = new XMLParser({
|
|
99
91
|
ignoreAttributes: false,
|
|
100
92
|
attributeNamePrefix: "@_",
|
|
101
93
|
textNodeName: "#text",
|
|
94
|
+
transformTagName: (tagName) => (tagName === "constructor" ? "_constructor" : tagName),
|
|
102
95
|
isArray: (_name, jpath, _isLeafNode, _isAttribute) => {
|
|
96
|
+
if (typeof jpath !== "string") return false;
|
|
103
97
|
const path = jpath.split(".").slice(1).join(".");
|
|
104
98
|
return ARRAY_ELEMENT_PATHS.has(path);
|
|
105
99
|
},
|
|
100
|
+
processEntities: { maxTotalExpansions: 100000 },
|
|
106
101
|
});
|
|
107
102
|
}
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Lightweight header parse using regex — extracts namespace name, version,
|
|
106
|
+
* and `<include>` dependencies without paying the cost of full XML parsing.
|
|
107
|
+
*/
|
|
108
|
+
parseHeader(girXml: string): RawRepositoryHeader {
|
|
109
|
+
const nameMatch = NS_NAME_RE.exec(girXml);
|
|
110
|
+
const versionMatch = NS_VERSION_RE.exec(girXml);
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
if (!nameMatch || !versionMatch) {
|
|
113
|
+
throw new Error("Failed to parse GIR header: missing namespace name or version");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const dependencies: RawDependency[] = [];
|
|
117
|
+
INCLUDE_RE.lastIndex = 0;
|
|
118
|
+
for (let m = INCLUDE_RE.exec(girXml); m !== null; m = INCLUDE_RE.exec(girXml)) {
|
|
119
|
+
const name = m[1];
|
|
120
|
+
const version = m[2];
|
|
121
|
+
if (name && version) {
|
|
122
|
+
dependencies.push({ name, version });
|
|
123
|
+
}
|
|
116
124
|
}
|
|
117
|
-
|
|
125
|
+
|
|
126
|
+
const namespaceName = nameMatch[1];
|
|
127
|
+
const namespaceVersion = versionMatch[1];
|
|
128
|
+
if (!namespaceName || !namespaceVersion) {
|
|
129
|
+
throw new Error("Failed to parse GIR header: missing namespace name or version");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return { namespaceName, namespaceVersion, dependencies };
|
|
118
133
|
}
|
|
119
134
|
|
|
120
135
|
/**
|
|
121
|
-
*
|
|
136
|
+
* Full parse of a GIR XML string into a raw namespace.
|
|
122
137
|
*/
|
|
123
|
-
|
|
138
|
+
parseNamespace(girXml: string): RawNamespace {
|
|
124
139
|
const parsed = this.parser.parse(girXml);
|
|
125
140
|
const repository = parsed.repository;
|
|
126
141
|
|
|
@@ -129,7 +144,6 @@ export class RawGirParser {
|
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
const namespace = repository.namespace;
|
|
132
|
-
this.currentNamespace = namespace["@_name"];
|
|
133
147
|
|
|
134
148
|
return {
|
|
135
149
|
name: namespace["@_name"],
|
|
@@ -148,25 +162,6 @@ export class RawGirParser {
|
|
|
148
162
|
};
|
|
149
163
|
}
|
|
150
164
|
|
|
151
|
-
private parseCallbacks(callbacks: Record<string, unknown>[]): RawCallback[] {
|
|
152
|
-
if (!callbacks || !Array.isArray(callbacks)) {
|
|
153
|
-
return [];
|
|
154
|
-
}
|
|
155
|
-
return callbacks
|
|
156
|
-
.filter((cb) => this.isIntrospectable(cb))
|
|
157
|
-
.map((cb) => ({
|
|
158
|
-
name: String(cb["@_name"] ?? ""),
|
|
159
|
-
cType: String(cb["@_c:type"] ?? ""),
|
|
160
|
-
returnType: this.parseReturnType(cb["return-value"] as Record<string, unknown> | undefined),
|
|
161
|
-
parameters: this.parseParameters(
|
|
162
|
-
(cb.parameters && typeof cb.parameters === "object" && cb.parameters !== null
|
|
163
|
-
? cb.parameters
|
|
164
|
-
: {}) as Record<string, unknown>,
|
|
165
|
-
),
|
|
166
|
-
doc: extractDoc(cb),
|
|
167
|
-
}));
|
|
168
|
-
}
|
|
169
|
-
|
|
170
165
|
private parseClasses(classes: Record<string, unknown>[]): RawClass[] {
|
|
171
166
|
return classes.map((cls) => ({
|
|
172
167
|
name: String(cls["@_name"] ?? ""),
|
|
@@ -183,7 +178,7 @@ export class RawGirParser {
|
|
|
183
178
|
cls.implements as Record<string, unknown>[] | Record<string, unknown> | undefined,
|
|
184
179
|
),
|
|
185
180
|
methods: this.parseMethods(ensureArray(cls.method)),
|
|
186
|
-
constructors: this.parseConstructors(ensureArray(cls.
|
|
181
|
+
constructors: this.parseConstructors(ensureArray(cls._constructor)),
|
|
187
182
|
functions: this.parseFunctions(ensureArray(cls.function)),
|
|
188
183
|
properties: this.parseProperties(ensureArray(cls.property)),
|
|
189
184
|
signals: this.parseSignals(ensureArray(cls["glib:signal"])),
|
|
@@ -198,9 +193,7 @@ export class RawGirParser {
|
|
|
198
193
|
}
|
|
199
194
|
|
|
200
195
|
private parseInterfaces(interfaces: Record<string, unknown>[]): RawInterface[] {
|
|
201
|
-
if (!interfaces || !Array.isArray(interfaces))
|
|
202
|
-
return [];
|
|
203
|
-
}
|
|
196
|
+
if (!interfaces || !Array.isArray(interfaces)) return [];
|
|
204
197
|
return interfaces.map((iface) => ({
|
|
205
198
|
name: String(iface["@_name"] ?? ""),
|
|
206
199
|
cType: String(iface["@_c:type"] ?? iface["@_glib:type-name"] ?? ""),
|
|
@@ -224,20 +217,12 @@ export class RawGirParser {
|
|
|
224
217
|
}
|
|
225
218
|
|
|
226
219
|
private parseMethods(methods: Record<string, unknown>[]): RawMethod[] {
|
|
227
|
-
if (!methods || !Array.isArray(methods))
|
|
228
|
-
return [];
|
|
229
|
-
}
|
|
220
|
+
if (!methods || !Array.isArray(methods)) return [];
|
|
230
221
|
return methods
|
|
231
|
-
.filter((
|
|
222
|
+
.filter((m) => m["@_introspectable"] !== "0")
|
|
232
223
|
.map((method) => {
|
|
233
224
|
const returnValue = method["return-value"] as Record<string, unknown> | undefined;
|
|
234
|
-
const
|
|
235
|
-
const shadows = method["@_shadows"] as string | undefined;
|
|
236
|
-
const shadowedBy = method["@_shadowed-by"] as string | undefined;
|
|
237
|
-
const parametersNode =
|
|
238
|
-
method.parameters && typeof method.parameters === "object" && method.parameters !== null
|
|
239
|
-
? (method.parameters as Record<string, unknown>)
|
|
240
|
-
: {};
|
|
225
|
+
const parametersNode = this.extractParametersNode(method);
|
|
241
226
|
return {
|
|
242
227
|
name: String(method["@_name"] ?? ""),
|
|
243
228
|
cIdentifier: String(method["@_c:identifier"] ?? ""),
|
|
@@ -247,84 +232,212 @@ export class RawGirParser {
|
|
|
247
232
|
throws: method["@_throws"] === "1",
|
|
248
233
|
doc: extractDoc(method),
|
|
249
234
|
returnDoc: returnValue ? extractDoc(returnValue) : undefined,
|
|
250
|
-
finishFunc:
|
|
251
|
-
shadows:
|
|
252
|
-
shadowedBy:
|
|
235
|
+
finishFunc: (method["@_glib:finish-func"] as string) || undefined,
|
|
236
|
+
shadows: (method["@_shadows"] as string) || undefined,
|
|
237
|
+
shadowedBy: (method["@_shadowed-by"] as string) || undefined,
|
|
253
238
|
};
|
|
254
239
|
});
|
|
255
240
|
}
|
|
256
241
|
|
|
257
242
|
private parseConstructors(constructors: Record<string, unknown>[]): RawConstructor[] {
|
|
258
|
-
if (!constructors || !Array.isArray(constructors))
|
|
259
|
-
return [];
|
|
260
|
-
}
|
|
243
|
+
if (!constructors || !Array.isArray(constructors)) return [];
|
|
261
244
|
return constructors
|
|
262
|
-
.filter((
|
|
245
|
+
.filter((c) => c["@_introspectable"] !== "0")
|
|
263
246
|
.map((ctor) => {
|
|
264
247
|
const returnValue = ctor["return-value"] as Record<string, unknown> | undefined;
|
|
265
|
-
const shadows = ctor["@_shadows"] as string | undefined;
|
|
266
|
-
const shadowedBy = ctor["@_shadowed-by"] as string | undefined;
|
|
267
248
|
return {
|
|
268
249
|
name: String(ctor["@_name"] ?? ""),
|
|
269
250
|
cIdentifier: String(ctor["@_c:identifier"] ?? ""),
|
|
270
251
|
returnType: this.parseReturnType(returnValue),
|
|
271
|
-
parameters: this.parseParameters(
|
|
272
|
-
(ctor.parameters && typeof ctor.parameters === "object" && ctor.parameters !== null
|
|
273
|
-
? ctor.parameters
|
|
274
|
-
: {}) as Record<string, unknown>,
|
|
275
|
-
),
|
|
252
|
+
parameters: this.parseParameters(this.extractParametersNode(ctor)),
|
|
276
253
|
throws: ctor["@_throws"] === "1",
|
|
277
254
|
doc: extractDoc(ctor),
|
|
278
255
|
returnDoc: returnValue ? extractDoc(returnValue) : undefined,
|
|
279
|
-
shadows:
|
|
280
|
-
shadowedBy:
|
|
256
|
+
shadows: (ctor["@_shadows"] as string) || undefined,
|
|
257
|
+
shadowedBy: (ctor["@_shadowed-by"] as string) || undefined,
|
|
281
258
|
};
|
|
282
259
|
});
|
|
283
260
|
}
|
|
284
261
|
|
|
285
262
|
private parseFunctions(functions: Record<string, unknown>[]): RawFunction[] {
|
|
286
|
-
if (!functions || !Array.isArray(functions))
|
|
287
|
-
return [];
|
|
288
|
-
}
|
|
263
|
+
if (!functions || !Array.isArray(functions)) return [];
|
|
289
264
|
return functions
|
|
290
|
-
.filter((
|
|
265
|
+
.filter((f) => f["@_introspectable"] !== "0")
|
|
291
266
|
.map((func) => {
|
|
292
267
|
const returnValue = func["return-value"] as Record<string, unknown> | undefined;
|
|
293
|
-
const shadows = func["@_shadows"] as string | undefined;
|
|
294
|
-
const shadowedBy = func["@_shadowed-by"] as string | undefined;
|
|
295
268
|
return {
|
|
296
269
|
name: String(func["@_name"] ?? ""),
|
|
297
270
|
cIdentifier: String(func["@_c:identifier"] ?? ""),
|
|
298
271
|
returnType: this.parseReturnType(returnValue),
|
|
299
|
-
parameters: this.parseParameters(
|
|
300
|
-
(func.parameters && typeof func.parameters === "object" && func.parameters !== null
|
|
301
|
-
? func.parameters
|
|
302
|
-
: {}) as Record<string, unknown>,
|
|
303
|
-
),
|
|
272
|
+
parameters: this.parseParameters(this.extractParametersNode(func)),
|
|
304
273
|
throws: func["@_throws"] === "1",
|
|
305
274
|
doc: extractDoc(func),
|
|
306
275
|
returnDoc: returnValue ? extractDoc(returnValue) : undefined,
|
|
307
|
-
shadows:
|
|
308
|
-
shadowedBy:
|
|
276
|
+
shadows: (func["@_shadows"] as string) || undefined,
|
|
277
|
+
shadowedBy: (func["@_shadowed-by"] as string) || undefined,
|
|
309
278
|
};
|
|
310
279
|
});
|
|
311
280
|
}
|
|
312
281
|
|
|
313
|
-
private
|
|
314
|
-
if (!
|
|
315
|
-
|
|
316
|
-
|
|
282
|
+
private parseCallbacks(callbacks: Record<string, unknown>[]): RawCallback[] {
|
|
283
|
+
if (!callbacks || !Array.isArray(callbacks)) return [];
|
|
284
|
+
return callbacks
|
|
285
|
+
.filter((cb) => cb["@_introspectable"] !== "0")
|
|
286
|
+
.map((cb) => ({
|
|
287
|
+
name: String(cb["@_name"] ?? ""),
|
|
288
|
+
cType: String(cb["@_c:type"] ?? ""),
|
|
289
|
+
returnType: this.parseReturnType(cb["return-value"] as Record<string, unknown> | undefined),
|
|
290
|
+
parameters: this.parseParameters(this.extractParametersNode(cb)),
|
|
291
|
+
doc: extractDoc(cb),
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
317
294
|
|
|
318
|
-
|
|
295
|
+
private parseRecords(records: Record<string, unknown>[]): RawRecord[] {
|
|
296
|
+
if (!records || !Array.isArray(records)) return [];
|
|
297
|
+
return records.map((record) => ({
|
|
298
|
+
name: String(record["@_name"] ?? ""),
|
|
299
|
+
cType: String(record["@_c:type"] ?? record["@_glib:type-name"] ?? ""),
|
|
300
|
+
opaque: record["@_opaque"] === "1",
|
|
301
|
+
disguised: record["@_disguised"] === "1",
|
|
302
|
+
glibTypeName: record["@_glib:type-name"] ? String(record["@_glib:type-name"]) : undefined,
|
|
303
|
+
glibGetType: record["@_glib:get-type"] ? String(record["@_glib:get-type"]) : undefined,
|
|
304
|
+
isGtypeStructFor: record["@_glib:is-gtype-struct-for"]
|
|
305
|
+
? String(record["@_glib:is-gtype-struct-for"])
|
|
306
|
+
: undefined,
|
|
307
|
+
copyFunction: record["@_copy-function"] ? String(record["@_copy-function"]) : undefined,
|
|
308
|
+
freeFunction: record["@_free-function"] ? String(record["@_free-function"]) : undefined,
|
|
309
|
+
fields: this.parseFields(ensureArray(record.field)),
|
|
310
|
+
methods: this.parseMethods(ensureArray(record.method)),
|
|
311
|
+
constructors: this.parseConstructors(ensureArray(record._constructor)),
|
|
312
|
+
functions: this.parseFunctions(ensureArray(record.function)),
|
|
313
|
+
doc: extractDoc(record),
|
|
314
|
+
}));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private parseEnumerations(enumerations: Record<string, unknown>[]): RawEnumeration[] {
|
|
318
|
+
if (!enumerations || !Array.isArray(enumerations)) return [];
|
|
319
|
+
return enumerations.map((enumeration) => ({
|
|
320
|
+
name: String(enumeration["@_name"] ?? ""),
|
|
321
|
+
cType: String(enumeration["@_c:type"] ?? ""),
|
|
322
|
+
members: this.parseEnumerationMembers(ensureArray(enumeration.member)),
|
|
323
|
+
glibGetType:
|
|
324
|
+
typeof enumeration["@_glib:get-type"] === "string" ? enumeration["@_glib:get-type"] : undefined,
|
|
325
|
+
doc: extractDoc(enumeration),
|
|
326
|
+
}));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private parseEnumerationMembers(members: Record<string, unknown>[]): RawEnumerationMember[] {
|
|
330
|
+
if (!members || !Array.isArray(members)) return [];
|
|
331
|
+
return members.map((member) => ({
|
|
332
|
+
name: String(member["@_name"] ?? ""),
|
|
333
|
+
value: String(member["@_value"] ?? ""),
|
|
334
|
+
cIdentifier: String(member["@_c:identifier"] ?? ""),
|
|
335
|
+
doc: extractDoc(member),
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
319
338
|
|
|
339
|
+
private parseConstants(constants: Record<string, unknown>[]): RawConstant[] {
|
|
340
|
+
if (!constants || !Array.isArray(constants)) return [];
|
|
341
|
+
return constants.map((constant) => ({
|
|
342
|
+
name: String(constant["@_name"] ?? ""),
|
|
343
|
+
cType: String(constant["@_c:type"] ?? ""),
|
|
344
|
+
value: String(constant["@_value"] ?? ""),
|
|
345
|
+
type: this.parseType((constant.type ?? constant.array) as Record<string, unknown> | undefined),
|
|
346
|
+
doc: extractDoc(constant),
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private parseAliases(aliases: Record<string, unknown>[]): RawAlias[] {
|
|
351
|
+
if (!aliases || !Array.isArray(aliases)) return [];
|
|
352
|
+
return aliases.map((alias) => ({
|
|
353
|
+
name: String(alias["@_name"] ?? ""),
|
|
354
|
+
cType: String(alias["@_c:type"] ?? ""),
|
|
355
|
+
targetType: this.parseType(alias.type as Record<string, unknown> | undefined),
|
|
356
|
+
doc: extractDoc(alias),
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
private parseProperties(properties: Record<string, unknown>[]): RawProperty[] {
|
|
361
|
+
if (!properties || !Array.isArray(properties)) return [];
|
|
362
|
+
return properties.map((prop) => {
|
|
363
|
+
let getter = prop["@_getter"] ? String(prop["@_getter"]) : undefined;
|
|
364
|
+
let setter = prop["@_setter"] ? String(prop["@_setter"]) : undefined;
|
|
365
|
+
|
|
366
|
+
const attributes = prop.attribute as Record<string, unknown>[] | Record<string, unknown> | undefined;
|
|
367
|
+
if (attributes) {
|
|
368
|
+
const attrList = Array.isArray(attributes) ? attributes : [attributes];
|
|
369
|
+
for (const attr of attrList) {
|
|
370
|
+
if (attr["@_name"] === "org.gtk.Property.get" && attr["@_value"]) {
|
|
371
|
+
getter = String(attr["@_value"]);
|
|
372
|
+
} else if (attr["@_name"] === "org.gtk.Property.set" && attr["@_value"]) {
|
|
373
|
+
setter = String(attr["@_value"]);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
name: String(prop["@_name"] ?? ""),
|
|
380
|
+
type: this.parseType((prop.type ?? prop.array) as Record<string, unknown> | undefined),
|
|
381
|
+
readable: prop["@_readable"] !== "0",
|
|
382
|
+
writable: prop["@_writable"] === "1",
|
|
383
|
+
constructOnly: prop["@_construct-only"] === "1",
|
|
384
|
+
defaultValueRaw: prop["@_default-value"] !== undefined ? String(prop["@_default-value"]) : undefined,
|
|
385
|
+
getter,
|
|
386
|
+
setter,
|
|
387
|
+
doc: extractDoc(prop),
|
|
388
|
+
};
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private parseSignals(signals: Record<string, unknown>[]): RawSignal[] {
|
|
393
|
+
if (!signals || !Array.isArray(signals)) return [];
|
|
394
|
+
return signals.map((signal) => {
|
|
395
|
+
const whenValue = String(signal["@_when"] ?? "last");
|
|
396
|
+
const validWhen = whenValue === "first" || whenValue === "last" || whenValue === "cleanup";
|
|
397
|
+
return {
|
|
398
|
+
name: String(signal["@_name"] ?? ""),
|
|
399
|
+
when: validWhen ? (whenValue as "first" | "last" | "cleanup") : "last",
|
|
400
|
+
returnType: signal["return-value"]
|
|
401
|
+
? this.parseReturnType(signal["return-value"] as Record<string, unknown>)
|
|
402
|
+
: undefined,
|
|
403
|
+
parameters:
|
|
404
|
+
signal.parameters && typeof signal.parameters === "object" && signal.parameters !== null
|
|
405
|
+
? this.parseParameters(signal.parameters as Record<string, unknown>)
|
|
406
|
+
: [],
|
|
407
|
+
doc: extractDoc(signal),
|
|
408
|
+
};
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
private parseFields(fields: Record<string, unknown>[]): RawField[] {
|
|
413
|
+
if (!fields || !Array.isArray(fields)) return [];
|
|
414
|
+
return fields
|
|
415
|
+
.filter((field) => field.callback === undefined)
|
|
416
|
+
.map((field) => ({
|
|
417
|
+
name: String(field["@_name"] ?? ""),
|
|
418
|
+
type: this.parseType((field.type ?? field.array) as Record<string, unknown> | undefined),
|
|
419
|
+
writable: field["@_writable"] === "1",
|
|
420
|
+
readable: field["@_readable"] !== "0",
|
|
421
|
+
private: field["@_private"] === "1",
|
|
422
|
+
doc: extractDoc(field),
|
|
423
|
+
}));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private extractParametersNode(node: Record<string, unknown>): Record<string, unknown> {
|
|
427
|
+
return node.parameters && typeof node.parameters === "object" && node.parameters !== null
|
|
428
|
+
? (node.parameters as Record<string, unknown>)
|
|
429
|
+
: {};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private parseParameters(parametersNode: Record<string, unknown>): RawParameter[] {
|
|
433
|
+
if (!parametersNode?.parameter) return [];
|
|
434
|
+
const params = Array.isArray(parametersNode.parameter) ? parametersNode.parameter : [parametersNode.parameter];
|
|
320
435
|
return params.map((param: Record<string, unknown>) => this.parseSingleParameter(param));
|
|
321
436
|
}
|
|
322
437
|
|
|
323
438
|
private parseInstanceParameter(parametersNode: Record<string, unknown>): RawParameter | undefined {
|
|
324
439
|
const instanceParam = parametersNode?.["instance-parameter"] as Record<string, unknown> | undefined;
|
|
325
|
-
if (!instanceParam)
|
|
326
|
-
return undefined;
|
|
327
|
-
}
|
|
440
|
+
if (!instanceParam) return undefined;
|
|
328
441
|
return this.parseSingleParameter(instanceParam);
|
|
329
442
|
}
|
|
330
443
|
|
|
@@ -341,7 +454,7 @@ export class RawGirParser {
|
|
|
341
454
|
callerAllocates: callerAllocates === "1",
|
|
342
455
|
nullable: param["@_nullable"] === "1",
|
|
343
456
|
optional: param["@_allow-none"] === "1" || param["@_optional"] === "1",
|
|
344
|
-
scope: scope as "async" | "call" | "notified" | undefined,
|
|
457
|
+
scope: scope as "async" | "call" | "notified" | "forever" | undefined,
|
|
345
458
|
closure: closure !== undefined ? parseInt(closure, 10) : undefined,
|
|
346
459
|
destroy: destroy !== undefined ? parseInt(destroy, 10) : undefined,
|
|
347
460
|
transferOwnership:
|
|
@@ -353,9 +466,7 @@ export class RawGirParser {
|
|
|
353
466
|
}
|
|
354
467
|
|
|
355
468
|
private parseReturnType(returnValue: Record<string, unknown> | undefined): RawType {
|
|
356
|
-
if (!returnValue) {
|
|
357
|
-
return { name: "void" };
|
|
358
|
-
}
|
|
469
|
+
if (!returnValue) return { name: "void" };
|
|
359
470
|
const type = this.parseType((returnValue.type ?? returnValue.array) as Record<string, unknown> | undefined);
|
|
360
471
|
const transferOwnership = returnValue["@_transfer-ownership"] as string | undefined;
|
|
361
472
|
if (transferOwnership === "none" || transferOwnership === "full" || transferOwnership === "container") {
|
|
@@ -368,21 +479,15 @@ export class RawGirParser {
|
|
|
368
479
|
}
|
|
369
480
|
|
|
370
481
|
private parseType(typeNode: Record<string, unknown> | undefined): RawType {
|
|
371
|
-
if (!typeNode) {
|
|
372
|
-
return { name: "void" };
|
|
373
|
-
}
|
|
482
|
+
if (!typeNode) return { name: "void" };
|
|
374
483
|
|
|
375
484
|
const typeName = typeNode["@_name"] ? String(typeNode["@_name"]) : undefined;
|
|
376
485
|
const cType = typeNode["@_c:type"] ? String(typeNode["@_c:type"]) : undefined;
|
|
377
486
|
|
|
378
487
|
const containerResult = this.parseGLibContainerType(typeName, typeNode, cType);
|
|
379
|
-
if (containerResult)
|
|
380
|
-
return containerResult;
|
|
381
|
-
}
|
|
488
|
+
if (containerResult) return containerResult;
|
|
382
489
|
|
|
383
|
-
if (typeName) {
|
|
384
|
-
return { name: typeName, cType };
|
|
385
|
-
}
|
|
490
|
+
if (typeName) return { name: typeName, cType };
|
|
386
491
|
|
|
387
492
|
const isArrayNode =
|
|
388
493
|
typeNode.type ||
|
|
@@ -391,17 +496,14 @@ export class RawGirParser {
|
|
|
391
496
|
typeNode["@_length"] !== undefined;
|
|
392
497
|
|
|
393
498
|
if (isArrayNode) {
|
|
394
|
-
const lengthAttr = typeNode["@_length"];
|
|
395
|
-
const zeroTerminatedAttr = typeNode["@_zero-terminated"];
|
|
396
|
-
const fixedSizeAttr = typeNode["@_fixed-size"];
|
|
397
|
-
|
|
398
499
|
return {
|
|
399
500
|
name: "array",
|
|
400
501
|
isArray: true,
|
|
401
502
|
elementType: typeNode.type ? this.parseType(typeNode.type as Record<string, unknown>) : undefined,
|
|
402
|
-
sizeParamIndex:
|
|
403
|
-
zeroTerminated:
|
|
404
|
-
|
|
503
|
+
sizeParamIndex: typeNode["@_length"] !== undefined ? Number(typeNode["@_length"]) : undefined,
|
|
504
|
+
zeroTerminated:
|
|
505
|
+
typeNode["@_zero-terminated"] !== undefined ? typeNode["@_zero-terminated"] !== "0" : undefined,
|
|
506
|
+
fixedSize: typeNode["@_fixed-size"] !== undefined ? Number(typeNode["@_fixed-size"]) : undefined,
|
|
405
507
|
};
|
|
406
508
|
}
|
|
407
509
|
|
|
@@ -461,6 +563,16 @@ export class RawGirParser {
|
|
|
461
563
|
};
|
|
462
564
|
}
|
|
463
565
|
|
|
566
|
+
if (typeName === "GLib.ByteArray") {
|
|
567
|
+
return {
|
|
568
|
+
name: typeName,
|
|
569
|
+
cType,
|
|
570
|
+
isArray: true,
|
|
571
|
+
containerType: "gbytearray" as ContainerType,
|
|
572
|
+
elementType: { name: "guint8", cType: "guint8" },
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
464
576
|
if (typeName === "GLib.List" || typeName === "GLib.SList") {
|
|
465
577
|
const innerType = (typeNode.type ?? typeNode.array) as Record<string, unknown> | undefined;
|
|
466
578
|
const elementType = innerType ? this.parseType(innerType) : undefined;
|
|
@@ -476,158 +588,4 @@ export class RawGirParser {
|
|
|
476
588
|
|
|
477
589
|
return null;
|
|
478
590
|
}
|
|
479
|
-
|
|
480
|
-
private parseProperties(properties: Record<string, unknown>[]): RawProperty[] {
|
|
481
|
-
if (!properties || !Array.isArray(properties)) {
|
|
482
|
-
return [];
|
|
483
|
-
}
|
|
484
|
-
return properties.map((prop) => {
|
|
485
|
-
let getter = prop["@_getter"] ? String(prop["@_getter"]) : undefined;
|
|
486
|
-
let setter = prop["@_setter"] ? String(prop["@_setter"]) : undefined;
|
|
487
|
-
|
|
488
|
-
const attributes = prop.attribute as Record<string, unknown>[] | Record<string, unknown> | undefined;
|
|
489
|
-
if (attributes) {
|
|
490
|
-
const attrList = Array.isArray(attributes) ? attributes : [attributes];
|
|
491
|
-
for (const attr of attrList) {
|
|
492
|
-
const attrName = attr["@_name"];
|
|
493
|
-
const attrValue = attr["@_value"];
|
|
494
|
-
if (attrName === "org.gtk.Property.get" && attrValue) {
|
|
495
|
-
getter = String(attrValue);
|
|
496
|
-
} else if (attrName === "org.gtk.Property.set" && attrValue) {
|
|
497
|
-
setter = String(attrValue);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
return {
|
|
503
|
-
name: String(prop["@_name"] ?? ""),
|
|
504
|
-
type: this.parseType((prop.type ?? prop.array) as Record<string, unknown> | undefined),
|
|
505
|
-
readable: prop["@_readable"] !== "0",
|
|
506
|
-
writable: prop["@_writable"] === "1",
|
|
507
|
-
constructOnly: prop["@_construct-only"] === "1",
|
|
508
|
-
defaultValueRaw: prop["@_default-value"] !== undefined ? String(prop["@_default-value"]) : undefined,
|
|
509
|
-
getter,
|
|
510
|
-
setter,
|
|
511
|
-
doc: extractDoc(prop),
|
|
512
|
-
};
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
private parseSignals(signals: Record<string, unknown>[]): RawSignal[] {
|
|
517
|
-
if (!signals || !Array.isArray(signals)) {
|
|
518
|
-
return [];
|
|
519
|
-
}
|
|
520
|
-
return signals.map((signal) => {
|
|
521
|
-
const whenValue = String(signal["@_when"] ?? "last");
|
|
522
|
-
const validWhen = whenValue === "first" || whenValue === "last" || whenValue === "cleanup";
|
|
523
|
-
return {
|
|
524
|
-
name: String(signal["@_name"] ?? ""),
|
|
525
|
-
when: validWhen ? (whenValue as "first" | "last" | "cleanup") : "last",
|
|
526
|
-
returnType: signal["return-value"]
|
|
527
|
-
? this.parseReturnType(signal["return-value"] as Record<string, unknown>)
|
|
528
|
-
: undefined,
|
|
529
|
-
parameters:
|
|
530
|
-
signal.parameters && typeof signal.parameters === "object" && signal.parameters !== null
|
|
531
|
-
? this.parseParameters(signal.parameters as Record<string, unknown>)
|
|
532
|
-
: [],
|
|
533
|
-
doc: extractDoc(signal),
|
|
534
|
-
};
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
private parseRecords(records: Record<string, unknown>[]): RawRecord[] {
|
|
539
|
-
if (!records || !Array.isArray(records)) {
|
|
540
|
-
return [];
|
|
541
|
-
}
|
|
542
|
-
return records.map((record) => ({
|
|
543
|
-
name: String(record["@_name"] ?? ""),
|
|
544
|
-
cType: String(record["@_c:type"] ?? record["@_glib:type-name"] ?? ""),
|
|
545
|
-
opaque: record["@_opaque"] === "1",
|
|
546
|
-
disguised: record["@_disguised"] === "1",
|
|
547
|
-
glibTypeName: record["@_glib:type-name"] ? String(record["@_glib:type-name"]) : undefined,
|
|
548
|
-
glibGetType: record["@_glib:get-type"] ? String(record["@_glib:get-type"]) : undefined,
|
|
549
|
-
isGtypeStructFor: record["@_glib:is-gtype-struct-for"]
|
|
550
|
-
? String(record["@_glib:is-gtype-struct-for"])
|
|
551
|
-
: undefined,
|
|
552
|
-
copyFunction: record["@_copy-function"] ? String(record["@_copy-function"]) : undefined,
|
|
553
|
-
freeFunction: record["@_free-function"] ? String(record["@_free-function"]) : undefined,
|
|
554
|
-
fields: this.parseFields(ensureArray(record.field)),
|
|
555
|
-
methods: this.parseMethods(ensureArray(record.method)),
|
|
556
|
-
constructors: this.parseConstructors(ensureArray(record.constructor)),
|
|
557
|
-
functions: this.parseFunctions(ensureArray(record.function)),
|
|
558
|
-
doc: extractDoc(record),
|
|
559
|
-
}));
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
private parseFields(fields: Record<string, unknown>[]): RawField[] {
|
|
563
|
-
if (!fields || !Array.isArray(fields)) {
|
|
564
|
-
return [];
|
|
565
|
-
}
|
|
566
|
-
return fields
|
|
567
|
-
.filter((field) => {
|
|
568
|
-
const hasCallback = field.callback !== undefined;
|
|
569
|
-
return !hasCallback;
|
|
570
|
-
})
|
|
571
|
-
.map((field) => ({
|
|
572
|
-
name: String(field["@_name"] ?? ""),
|
|
573
|
-
type: this.parseType((field.type ?? field.array) as Record<string, unknown> | undefined),
|
|
574
|
-
writable: field["@_writable"] === "1",
|
|
575
|
-
readable: field["@_readable"] !== "0",
|
|
576
|
-
private: field["@_private"] === "1",
|
|
577
|
-
doc: extractDoc(field),
|
|
578
|
-
}));
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
private parseEnumerations(enumerations: Record<string, unknown>[]): RawEnumeration[] {
|
|
582
|
-
if (!enumerations || !Array.isArray(enumerations)) {
|
|
583
|
-
return [];
|
|
584
|
-
}
|
|
585
|
-
return enumerations.map((enumeration) => {
|
|
586
|
-
const glibGetType = enumeration["@_glib:get-type"];
|
|
587
|
-
return {
|
|
588
|
-
name: String(enumeration["@_name"] ?? ""),
|
|
589
|
-
cType: String(enumeration["@_c:type"] ?? ""),
|
|
590
|
-
members: this.parseEnumerationMembers(ensureArray(enumeration.member)),
|
|
591
|
-
glibGetType: typeof glibGetType === "string" ? glibGetType : undefined,
|
|
592
|
-
doc: extractDoc(enumeration),
|
|
593
|
-
};
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
private parseEnumerationMembers(members: Record<string, unknown>[]): RawEnumerationMember[] {
|
|
598
|
-
if (!members || !Array.isArray(members)) {
|
|
599
|
-
return [];
|
|
600
|
-
}
|
|
601
|
-
return members.map((member) => ({
|
|
602
|
-
name: String(member["@_name"] ?? ""),
|
|
603
|
-
value: String(member["@_value"] ?? ""),
|
|
604
|
-
cIdentifier: String(member["@_c:identifier"] ?? ""),
|
|
605
|
-
doc: extractDoc(member),
|
|
606
|
-
}));
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
private parseConstants(constants: Record<string, unknown>[]): RawConstant[] {
|
|
610
|
-
if (!constants || !Array.isArray(constants)) {
|
|
611
|
-
return [];
|
|
612
|
-
}
|
|
613
|
-
return constants.map((constant) => ({
|
|
614
|
-
name: String(constant["@_name"] ?? ""),
|
|
615
|
-
cType: String(constant["@_c:type"] ?? ""),
|
|
616
|
-
value: String(constant["@_value"] ?? ""),
|
|
617
|
-
type: this.parseType((constant.type ?? constant.array) as Record<string, unknown> | undefined),
|
|
618
|
-
doc: extractDoc(constant),
|
|
619
|
-
}));
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
private parseAliases(aliases: Record<string, unknown>[]): RawAlias[] {
|
|
623
|
-
if (!aliases || !Array.isArray(aliases)) {
|
|
624
|
-
return [];
|
|
625
|
-
}
|
|
626
|
-
return aliases.map((alias) => ({
|
|
627
|
-
name: String(alias["@_name"] ?? ""),
|
|
628
|
-
cType: String(alias["@_c:type"] ?? ""),
|
|
629
|
-
targetType: this.parseType(alias.type as Record<string, unknown> | undefined),
|
|
630
|
-
doc: extractDoc(alias),
|
|
631
|
-
}));
|
|
632
|
-
}
|
|
633
591
|
}
|