@gtkx/codegen 1.1.0 → 1.2.1
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/analysis/descriptor-render.d.ts.map +1 -1
- package/dist/analysis/descriptor-render.js +14 -10
- package/dist/analysis/descriptor-render.js.map +1 -1
- package/dist/analysis/descriptor.d.ts +11 -5
- package/dist/analysis/descriptor.d.ts.map +1 -1
- package/dist/analysis/descriptor.js +25 -9
- package/dist/analysis/descriptor.js.map +1 -1
- package/dist/analysis/interface-conflicts.d.ts +3 -1
- package/dist/analysis/interface-conflicts.d.ts.map +1 -1
- package/dist/analysis/interface-conflicts.js +3 -8
- package/dist/analysis/interface-conflicts.js.map +1 -1
- package/dist/analysis/ts-type.d.ts +3 -2
- package/dist/analysis/ts-type.d.ts.map +1 -1
- package/dist/analysis/ts-type.js +16 -9
- package/dist/analysis/ts-type.js.map +1 -1
- package/dist/analysis/type-shape.d.ts +3 -2
- package/dist/analysis/type-shape.d.ts.map +1 -1
- package/dist/analysis/type-shape.js +2 -1
- package/dist/analysis/type-shape.js.map +1 -1
- package/dist/compile.d.ts +4 -5
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +56 -4
- package/dist/compile.js.map +1 -1
- package/dist/docs/api-reference.d.ts +2 -0
- package/dist/docs/api-reference.d.ts.map +1 -1
- package/dist/docs/api-reference.js +1 -1
- package/dist/docs/api-reference.js.map +1 -1
- package/dist/docs/pipeline.d.ts +1 -0
- package/dist/docs/pipeline.d.ts.map +1 -1
- package/dist/docs/pipeline.js +10 -3
- package/dist/docs/pipeline.js.map +1 -1
- package/dist/docs/symbol-page.d.ts.map +1 -1
- package/dist/docs/symbol-page.js +2 -4
- package/dist/docs/symbol-page.js.map +1 -1
- package/dist/fingerprint.d.ts +11 -5
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +22 -19
- package/dist/fingerprint.js.map +1 -1
- package/dist/gi.d.ts +1 -0
- package/dist/gi.d.ts.map +1 -1
- package/dist/gi.js +7 -2
- package/dist/gi.js.map +1 -1
- package/dist/gir/class.d.ts +7 -2
- package/dist/gir/class.d.ts.map +1 -1
- package/dist/gir/class.js +4 -1
- package/dist/gir/class.js.map +1 -1
- package/dist/gir/gir-path.d.ts +1 -1
- package/dist/gir/gir-path.js +1 -1
- package/dist/gir/gir-path.js.map +1 -1
- package/dist/gir/library.d.ts +5 -1
- package/dist/gir/library.d.ts.map +1 -1
- package/dist/gir/library.js +8 -1
- package/dist/gir/library.js.map +1 -1
- package/dist/gir/parse.d.ts.map +1 -1
- package/dist/gir/parse.js +4 -1
- package/dist/gir/parse.js.map +1 -1
- package/dist/gir/primitives.js +1 -1
- package/dist/gir/primitives.js.map +1 -1
- package/dist/khronos/args.d.ts.map +1 -1
- package/dist/khronos/args.js +8 -6
- package/dist/khronos/args.js.map +1 -1
- package/dist/khronos/render.d.ts.map +1 -1
- package/dist/khronos/render.js +8 -4
- package/dist/khronos/render.js.map +1 -1
- package/dist/runner.d.ts +2 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +5 -3
- package/dist/runner.js.map +1 -1
- package/dist/staging.d.ts.map +1 -1
- package/dist/staging.js +1 -1
- package/dist/staging.js.map +1 -1
- package/dist/store/compile-store.d.ts +0 -1
- package/dist/store/compile-store.d.ts.map +1 -1
- package/dist/store/compile-store.js +7 -34
- package/dist/store/compile-store.js.map +1 -1
- package/dist/store/gi/callables.d.ts +2 -4
- package/dist/store/gi/callables.d.ts.map +1 -1
- package/dist/store/gi/callables.js +22 -7
- package/dist/store/gi/callables.js.map +1 -1
- package/dist/store/gi/class.d.ts.map +1 -1
- package/dist/store/gi/class.js +63 -17
- package/dist/store/gi/class.js.map +1 -1
- package/dist/store/gi/constant.js +1 -1
- package/dist/store/gi/constant.js.map +1 -1
- package/dist/store/gi/enum.d.ts.map +1 -1
- package/dist/store/gi/enum.js +2 -5
- package/dist/store/gi/enum.js.map +1 -1
- package/dist/store/gi/gtype-binding.d.ts +2 -1
- package/dist/store/gi/gtype-binding.d.ts.map +1 -1
- package/dist/store/gi/gtype-binding.js +13 -1
- package/dist/store/gi/gtype-binding.js.map +1 -1
- package/dist/store/gi/interface.js +4 -4
- package/dist/store/gi/interface.js.map +1 -1
- package/dist/store/gi/method.d.ts.map +1 -1
- package/dist/store/gi/method.js +4 -7
- package/dist/store/gi/method.js.map +1 -1
- package/dist/store/gi/property-accessor.d.ts +0 -3
- package/dist/store/gi/property-accessor.d.ts.map +1 -1
- package/dist/store/gi/property-accessor.js +15 -108
- package/dist/store/gi/property-accessor.js.map +1 -1
- package/dist/store/gi/record-constructor.d.ts.map +1 -1
- package/dist/store/gi/record-constructor.js +7 -5
- package/dist/store/gi/record-constructor.js.map +1 -1
- package/dist/store/gi/record-field-accessor.d.ts +3 -2
- package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
- package/dist/store/gi/record-field-accessor.js +42 -12
- package/dist/store/gi/record-field-accessor.js.map +1 -1
- package/dist/store/gi/record.d.ts.map +1 -1
- package/dist/store/gi/record.js +5 -9
- package/dist/store/gi/record.js.map +1 -1
- package/dist/store/gi/return-wrap.js +1 -1
- package/dist/store/gi/return-wrap.js.map +1 -1
- package/dist/store/gi/signal.d.ts.map +1 -1
- package/dist/store/gi/signal.js +27 -6
- package/dist/store/gi/signal.js.map +1 -1
- package/dist/store/jsx-store.d.ts.map +1 -1
- package/dist/store/jsx-store.js +0 -1
- package/dist/store/jsx-store.js.map +1 -1
- package/dist/store/resolve-store.d.ts.map +1 -1
- package/dist/store/resolve-store.js +1 -0
- package/dist/store/resolve-store.js.map +1 -1
- package/dist/store/store-fs.d.ts +0 -1
- package/dist/store/store-fs.d.ts.map +1 -1
- package/dist/store/store-fs.js +2 -7
- package/dist/store/store-fs.js.map +1 -1
- package/dist/xml.d.ts +1 -0
- package/dist/xml.d.ts.map +1 -1
- package/dist/xml.js +28 -1
- package/dist/xml.js.map +1 -1
- package/overrides/gobject/object.ts.ejs +2 -0
- package/package.json +3 -3
- package/src/analysis/descriptor-render.ts +19 -10
- package/src/analysis/descriptor.ts +43 -9
- package/src/analysis/interface-conflicts.ts +6 -8
- package/src/analysis/ts-type.ts +30 -11
- package/src/analysis/type-shape.ts +5 -2
- package/src/compile.ts +87 -6
- package/src/docs/api-reference.ts +3 -1
- package/src/docs/pipeline.ts +13 -7
- package/src/docs/symbol-page.ts +1 -5
- package/src/fingerprint.ts +31 -38
- package/src/gi.ts +9 -2
- package/src/gir/class.ts +12 -3
- package/src/gir/gir-path.ts +1 -1
- package/src/gir/library.ts +9 -1
- package/src/gir/parse.ts +6 -1
- package/src/gir/primitives.ts +1 -1
- package/src/khronos/args.ts +9 -6
- package/src/khronos/render.ts +8 -6
- package/src/runner.ts +7 -3
- package/src/staging.ts +1 -3
- package/src/store/compile-store.ts +7 -40
- package/src/store/gi/callables.ts +30 -11
- package/src/store/gi/class.ts +96 -21
- package/src/store/gi/constant.ts +1 -1
- package/src/store/gi/enum.ts +2 -6
- package/src/store/gi/gtype-binding.ts +16 -1
- package/src/store/gi/interface.ts +4 -4
- package/src/store/gi/method.ts +4 -9
- package/src/store/gi/property-accessor.ts +22 -193
- package/src/store/gi/record-constructor.ts +7 -5
- package/src/store/gi/record-field-accessor.ts +65 -13
- package/src/store/gi/record.ts +13 -17
- package/src/store/gi/return-wrap.ts +1 -1
- package/src/store/gi/signal.ts +36 -13
- package/src/store/jsx-store.ts +0 -1
- package/src/store/resolve-store.ts +1 -0
- package/src/store/store-fs.ts +3 -9
- package/src/xml.ts +43 -1
|
@@ -87,6 +87,11 @@ type FundamentalOptions = {
|
|
|
87
87
|
|
|
88
88
|
type ListDescriptorName = "list" | "slist" | "ptrArray" | "gArray";
|
|
89
89
|
|
|
90
|
+
type ArrayLayout = {
|
|
91
|
+
elementSize?: number | undefined;
|
|
92
|
+
isBytes: boolean;
|
|
93
|
+
};
|
|
94
|
+
|
|
90
95
|
type BindArgs = {
|
|
91
96
|
libExpr: string;
|
|
92
97
|
symbolExpr: string;
|
|
@@ -156,6 +161,7 @@ const tUint8: string = T.uint8;
|
|
|
156
161
|
const tUint32: string = T.uint32;
|
|
157
162
|
const tInt32: string = T.int32;
|
|
158
163
|
const tUint64: string = T.uint64;
|
|
164
|
+
const tBiguint64: string = T.biguint64;
|
|
159
165
|
const tGtype: string = T.gtype;
|
|
160
166
|
const tBuffer: string = T.buffer;
|
|
161
167
|
|
|
@@ -229,44 +235,69 @@ const tFlags = (lib: string, typeFnName: string, isSigned: boolean): string =>
|
|
|
229
235
|
|
|
230
236
|
const tByteArray = (ownership: Ownership): string => call("byteArray", [sourceStringLiteral(ownership)]);
|
|
231
237
|
|
|
238
|
+
const tNumericByteArray = (ownership: Ownership): string =>
|
|
239
|
+
call("array", [
|
|
240
|
+
tUint8,
|
|
241
|
+
sourceStringLiteral("gbytearray"),
|
|
242
|
+
sourceStringLiteral(ownership),
|
|
243
|
+
]);
|
|
244
|
+
|
|
232
245
|
const tList = (name: ListDescriptorName, element: string, ownership: Ownership): string =>
|
|
233
246
|
call(name, [element, sourceStringLiteral(ownership)]);
|
|
234
247
|
|
|
235
|
-
const
|
|
248
|
+
const arrayLayoutArg = (ownership: Ownership | undefined, layout: ArrayLayout): string | undefined => {
|
|
249
|
+
if (ownership === undefined) {
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const entries = [
|
|
254
|
+
layout.elementSize === undefined ? undefined : `elementSize: ${String(layout.elementSize)}`,
|
|
255
|
+
layout.isBytes ? "isBytes: true" : undefined,
|
|
256
|
+
].filter((entry): entry is string => entry !== undefined);
|
|
257
|
+
|
|
258
|
+
return entries.length === 0 ? undefined : `{ ${entries.join(", ")} }`;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const tArray = (element: string, ownership: Ownership | undefined, layout: ArrayLayout): string =>
|
|
236
262
|
call("array", [
|
|
237
263
|
element,
|
|
238
264
|
ownership === undefined ? undefined : sourceStringLiteral("array"),
|
|
239
265
|
ownership === undefined ? undefined : sourceStringLiteral(ownership),
|
|
240
|
-
|
|
266
|
+
arrayLayoutArg(ownership, layout),
|
|
241
267
|
]);
|
|
242
268
|
|
|
243
269
|
const tSizedArray = (
|
|
244
270
|
element: string,
|
|
245
271
|
lengthIndex: number,
|
|
246
|
-
ownership
|
|
247
|
-
|
|
272
|
+
ownership: Ownership | undefined,
|
|
273
|
+
layout: ArrayLayout,
|
|
248
274
|
): string =>
|
|
249
275
|
call("sizedArray", [
|
|
250
276
|
element,
|
|
251
277
|
String(lengthIndex),
|
|
252
278
|
ownership === undefined ? undefined : sourceStringLiteral(ownership),
|
|
253
|
-
|
|
279
|
+
arrayLayoutArg(ownership, layout),
|
|
254
280
|
]);
|
|
255
281
|
|
|
256
|
-
const tCursorArray = (
|
|
282
|
+
const tCursorArray = (
|
|
283
|
+
element: string,
|
|
284
|
+
bounds: GirCursorBounds,
|
|
285
|
+
ownership: Ownership | undefined,
|
|
286
|
+
layout: ArrayLayout,
|
|
287
|
+
): string =>
|
|
257
288
|
call("cursorArray", [
|
|
258
289
|
element,
|
|
259
290
|
`{ baseParamIndex: ${String(bounds.baseIndex)}, sizeParamIndex: ${String(bounds.lengthIndex)} }`,
|
|
260
291
|
ownership === undefined ? undefined : sourceStringLiteral(ownership),
|
|
261
|
-
|
|
292
|
+
arrayLayoutArg(ownership, layout),
|
|
262
293
|
]);
|
|
263
294
|
|
|
264
|
-
const tFixedArray = (element: string, length: number, ownership
|
|
295
|
+
const tFixedArray = (element: string, length: number, ownership: Ownership | undefined, layout: ArrayLayout): string =>
|
|
265
296
|
call("fixedArray", [
|
|
266
297
|
element,
|
|
267
298
|
String(length),
|
|
268
299
|
ownership === undefined ? undefined : sourceStringLiteral(ownership),
|
|
269
|
-
|
|
300
|
+
arrayLayoutArg(ownership, layout),
|
|
270
301
|
]);
|
|
271
302
|
|
|
272
303
|
const tCallback = (spec: CallbackSpecParts): string => {
|
|
@@ -296,6 +327,7 @@ export {
|
|
|
296
327
|
tUint32,
|
|
297
328
|
tInt32,
|
|
298
329
|
tUint64,
|
|
330
|
+
tBiguint64,
|
|
299
331
|
tGtype,
|
|
300
332
|
tBuffer,
|
|
301
333
|
tScalar,
|
|
@@ -310,6 +342,7 @@ export {
|
|
|
310
342
|
tEnum,
|
|
311
343
|
tFlags,
|
|
312
344
|
tByteArray,
|
|
345
|
+
tNumericByteArray,
|
|
313
346
|
tList,
|
|
314
347
|
tArray,
|
|
315
348
|
tSizedArray,
|
|
@@ -318,6 +351,7 @@ export {
|
|
|
318
351
|
tCallback,
|
|
319
352
|
tBind,
|
|
320
353
|
tFn,
|
|
354
|
+
type ArrayLayout,
|
|
321
355
|
type Ownership,
|
|
322
356
|
type ScalarDescriptorName,
|
|
323
357
|
type ListDescriptorName,
|
|
@@ -217,21 +217,19 @@ const prerequisiteConflicts = (library: Library, iface: GirClass, base: Resolved
|
|
|
217
217
|
return names;
|
|
218
218
|
};
|
|
219
219
|
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
return typeRef;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const keys = [...new Set(omissions)].map((name) => JSON.stringify(name)).join(" | ");
|
|
220
|
+
const omittedKeys = (omissions: string[]): string =>
|
|
221
|
+
[...new Set(omissions)].map((name) => JSON.stringify(name)).join(" | ");
|
|
226
222
|
|
|
227
|
-
|
|
228
|
-
}
|
|
223
|
+
const omittedTypeRef = (typeRef: string, omissions: string[]): string =>
|
|
224
|
+
omissions.length === 0 ? typeRef : `Omit<${typeRef}, ${omittedKeys(omissions)}>`;
|
|
229
225
|
|
|
230
226
|
export {
|
|
227
|
+
areCallablesAssignable,
|
|
231
228
|
type ClaimedMembers,
|
|
232
229
|
claimInterfaceMembers,
|
|
233
230
|
inheritedMembers,
|
|
234
231
|
interfaceConflicts,
|
|
232
|
+
omittedKeys,
|
|
235
233
|
omittedTypeRef,
|
|
236
234
|
prerequisiteConflicts,
|
|
237
235
|
};
|
package/src/analysis/ts-type.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type TypeId,
|
|
13
13
|
} from "../gir/type-id.js";
|
|
14
14
|
import { gtypeTsType } from "../store/gi/gtype-binding.js";
|
|
15
|
+
import { isByteSequence } from "./type-shape.js";
|
|
15
16
|
|
|
16
17
|
type ReferenceName = {
|
|
17
18
|
namespaceName: string;
|
|
@@ -21,11 +22,15 @@ type ReferenceName = {
|
|
|
21
22
|
type TsTypeTarget = {
|
|
22
23
|
containerStyle: "map" | "record";
|
|
23
24
|
callbackType: string;
|
|
24
|
-
|
|
25
|
+
byteArrayType: string;
|
|
25
26
|
renderNamed: (resolved: GirType | undefined, name: ReferenceName) => string;
|
|
26
27
|
renderGtype: () => string;
|
|
27
28
|
};
|
|
28
29
|
|
|
30
|
+
const BYTE_ARRAY_TYPE = "Uint8Array";
|
|
31
|
+
const BYTE_ARRAY_INPUT_TYPE = "Uint8Array | number[]";
|
|
32
|
+
const NUMBER_ARRAY_TYPE = "number[]";
|
|
33
|
+
|
|
29
34
|
const willEmitEntity = (type: EntityType): boolean => isEmittableEntity(type.value);
|
|
30
35
|
|
|
31
36
|
const referenceName = (library: Library, ref: TypeId): ReferenceName | undefined => {
|
|
@@ -97,14 +102,14 @@ const renderContainerType = (
|
|
|
97
102
|
};
|
|
98
103
|
|
|
99
104
|
const renderSequenceType = (library: Library, target: TsTypeTarget, type: CArrayType | ListType): string => {
|
|
100
|
-
if (type.kind === "list" && type.flavor === "gbytearray" && target.shouldRenderByteArrayAsNumber) {
|
|
101
|
-
return "number[]";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
105
|
if (type.kind === "carray" && hasUnknownArrayLength(type)) {
|
|
105
106
|
return "number";
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
if (isByteSequence(library, type)) {
|
|
110
|
+
return target.byteArrayType;
|
|
111
|
+
}
|
|
112
|
+
|
|
108
113
|
return `${renderBaseType(library, target, type.element)}[]`;
|
|
109
114
|
};
|
|
110
115
|
|
|
@@ -120,20 +125,34 @@ const renderNamedType = (
|
|
|
120
125
|
return target.renderNamed(resolved, name);
|
|
121
126
|
};
|
|
122
127
|
|
|
123
|
-
const
|
|
128
|
+
const getByteArrayType = (library: Library): string =>
|
|
129
|
+
library.isByteArrayTyped ? BYTE_ARRAY_TYPE : NUMBER_ARRAY_TYPE;
|
|
130
|
+
|
|
131
|
+
const moduleTarget = (context: ModuleContext, byteArrayType: string): TsTypeTarget => ({
|
|
124
132
|
containerStyle: "map",
|
|
125
133
|
callbackType: "((...args: any[]) => any)",
|
|
126
|
-
|
|
134
|
+
byteArrayType,
|
|
127
135
|
renderNamed: (_resolved, name) => context.qualify(name.namespaceName, name.typeName),
|
|
128
136
|
renderGtype: () => gtypeTsType(context),
|
|
129
137
|
});
|
|
130
138
|
|
|
131
|
-
const
|
|
132
|
-
|
|
139
|
+
const renderModuleType = (
|
|
140
|
+
context: ModuleContext,
|
|
141
|
+
ref: TypeId | undefined,
|
|
142
|
+
isNullable: boolean,
|
|
143
|
+
byteArrayType: string,
|
|
144
|
+
): string => {
|
|
145
|
+
const base = renderBaseType(context.library, moduleTarget(context, byteArrayType), ref);
|
|
133
146
|
|
|
134
147
|
return isNullable ? `${base} | null` : base;
|
|
135
148
|
};
|
|
136
149
|
|
|
150
|
+
const renderTsType = (context: ModuleContext, ref: TypeId | undefined, isNullable = false): string =>
|
|
151
|
+
renderModuleType(context, ref, isNullable, getByteArrayType(context.library));
|
|
152
|
+
|
|
153
|
+
const renderParameterTsType = (context: ModuleContext, ref: TypeId | undefined, isNullable = false): string =>
|
|
154
|
+
renderModuleType(context, ref, isNullable, BYTE_ARRAY_INPUT_TYPE);
|
|
155
|
+
|
|
137
156
|
const recordTypeTarget = (
|
|
138
157
|
library: Library,
|
|
139
158
|
renderNamedRef: (name: ReferenceName) => string,
|
|
@@ -142,7 +161,7 @@ const recordTypeTarget = (
|
|
|
142
161
|
const target: TsTypeTarget = {
|
|
143
162
|
containerStyle: "record",
|
|
144
163
|
callbackType: "((...args: unknown[]) => unknown)",
|
|
145
|
-
|
|
164
|
+
byteArrayType: getByteArrayType(library),
|
|
146
165
|
renderNamed: (resolved, name) => {
|
|
147
166
|
if (resolved?.kind === "alias") {
|
|
148
167
|
return resolved.value.target === undefined
|
|
@@ -158,4 +177,4 @@ const recordTypeTarget = (
|
|
|
158
177
|
return target;
|
|
159
178
|
};
|
|
160
179
|
|
|
161
|
-
export { renderBaseType, renderTsType, recordTypeTarget, type TsTypeTarget };
|
|
180
|
+
export { renderBaseType, renderParameterTsType, renderTsType, recordTypeTarget, type TsTypeTarget };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Library } from "../gir/library.js";
|
|
2
2
|
import type { PrimitiveCategory } from "../gir/primitives.js";
|
|
3
|
-
import type { CArrayType, TypeId } from "../gir/type-id.js";
|
|
3
|
+
import type { CArrayType, ListType, TypeId } from "../gir/type-id.js";
|
|
4
4
|
import type { GirType } from "../gir/type.js";
|
|
5
5
|
|
|
6
6
|
const resolvedTypeFor = (library: Library, ref: TypeId | undefined): GirType | undefined =>
|
|
@@ -21,4 +21,7 @@ const primitiveCategoryFor = (library: Library, ref: TypeId | undefined): Primit
|
|
|
21
21
|
const isUnboundedArray = (type: CArrayType): boolean =>
|
|
22
22
|
type.isZeroTerminated && type.lengthParameterIndex === undefined && type.fixedSize === undefined;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const isByteSequence = (library: Library, type: CArrayType | ListType): boolean =>
|
|
25
|
+
type.kind === "list" ? type.flavor === "gbytearray" : primitiveCategoryFor(library, type.element) === "uint8";
|
|
26
|
+
|
|
27
|
+
export { carrayFor, isByteSequence, isUnboundedArray, primitiveCategoryFor };
|
package/src/compile.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { errorMessage, normalizeError } from "@gtkx/utils";
|
|
1
|
+
import { errorCode, errorMessage, normalizeError } from "@gtkx/utils";
|
|
2
2
|
import { existsSync, mkdirSync, renameSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -14,10 +14,19 @@ type SourceModule = ProjectFile & {
|
|
|
14
14
|
source: string;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
type
|
|
17
|
+
type ProjectContext = {
|
|
18
18
|
projectDir: string;
|
|
19
19
|
files: ProjectFile[];
|
|
20
|
+
label: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type CompileProjectParams = ProjectContext & {
|
|
20
24
|
compilerOptions: Record<string, unknown>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type EmitModulesParams = {
|
|
28
|
+
projectDir: string;
|
|
29
|
+
files: SourceModule[];
|
|
21
30
|
label: string;
|
|
22
31
|
};
|
|
23
32
|
|
|
@@ -60,9 +69,33 @@ const CHECK_OPTIONS = {
|
|
|
60
69
|
noEmit: true,
|
|
61
70
|
};
|
|
62
71
|
|
|
72
|
+
const DECLARATION_EMIT = {
|
|
73
|
+
declaration: true,
|
|
74
|
+
isolatedDeclarations: true,
|
|
75
|
+
removeComments: false,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const MODULE_EMIT = {
|
|
79
|
+
removeComments: false,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const DECLARATION_OPTIONS = ts.convertCompilerOptionsFromJson(
|
|
83
|
+
{ ...BASE_COMPILER_OPTIONS, ...DECLARATION_EMIT },
|
|
84
|
+
".",
|
|
85
|
+
).options;
|
|
86
|
+
|
|
87
|
+
const MODULE_OPTIONS = ts.convertCompilerOptionsFromJson(
|
|
88
|
+
{ ...BASE_COMPILER_OPTIONS, ...MODULE_EMIT },
|
|
89
|
+
".",
|
|
90
|
+
).options;
|
|
91
|
+
|
|
92
|
+
const TS_EXTENSION_PATTERN = /\.tsx?$/;
|
|
93
|
+
const DECLARATION_EXTENSION = ".d.ts";
|
|
94
|
+
const JAVASCRIPT_EXTENSION = ".js";
|
|
63
95
|
const CHECK_DIR = ".gtkx-check";
|
|
64
96
|
const FAILED_CHECK_DIR = `${CHECK_DIR}.failed`;
|
|
65
97
|
const LEGACY_CHECK_PREFIX = `${CHECK_DIR}-`;
|
|
98
|
+
const ESM_SCOPE_MANIFEST = `${JSON.stringify({ type: "module" }, null, 4)}\n`;
|
|
66
99
|
|
|
67
100
|
const FORMAT_HOST: ts.FormatDiagnosticsHost = {
|
|
68
101
|
getCanonicalFileName: (fileName) => fileName,
|
|
@@ -90,6 +123,16 @@ const linkToolingModules = (projectDir: string): (() => void) => {
|
|
|
90
123
|
};
|
|
91
124
|
};
|
|
92
125
|
|
|
126
|
+
const ensureModuleScope = (projectDir: string): void => {
|
|
127
|
+
try {
|
|
128
|
+
writeFileSync(join(projectDir, "package.json"), ESM_SCOPE_MANIFEST, { flag: "wx" });
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (errorCode(error) !== "EEXIST") {
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
93
136
|
const isProjectFile = (rel: string): boolean =>
|
|
94
137
|
!rel.startsWith("..") && !isAbsolute(rel) && !rel.split(/[/\\]/).includes("node_modules");
|
|
95
138
|
|
|
@@ -160,17 +203,17 @@ const originLines = (diagnosed: DiagnosedFile[], files: ProjectFile[]): string[]
|
|
|
160
203
|
([origin, generated]) => `Generated from ${origin}: ${[...generated].join(", ")}`,
|
|
161
204
|
);
|
|
162
205
|
|
|
163
|
-
const diagnosticError = (params:
|
|
206
|
+
const diagnosticError = (params: ProjectContext, diagnostics: ts.Diagnostic[]): Error => {
|
|
164
207
|
const diagnosed = projectDiagnosticFiles(diagnostics, params.projectDir);
|
|
165
208
|
const { label } = params;
|
|
166
209
|
|
|
167
210
|
if (diagnosed.length === 0) {
|
|
168
|
-
return new Error(`
|
|
211
|
+
return new Error(`Compiling ${label} failed:\n${ts.formatDiagnostics(diagnostics, FORMAT_HOST).trim()}`);
|
|
169
212
|
}
|
|
170
213
|
|
|
171
214
|
const lines = [...diagnosed.map((entry) => entry.text), ...originLines(diagnosed, params.files)];
|
|
172
215
|
|
|
173
|
-
return new Error(`
|
|
216
|
+
return new Error(`Compiling ${label} found ${String(diagnosed.length)} error(s):\n${lines.join("\n")}`);
|
|
174
217
|
};
|
|
175
218
|
|
|
176
219
|
const keepFailedProject = (input: FailedProjectInput): Error => {
|
|
@@ -214,7 +257,45 @@ const runProgram = (params: CompileProjectParams): ts.Diagnostic[] => {
|
|
|
214
257
|
return [...program.emit().diagnostics];
|
|
215
258
|
};
|
|
216
259
|
|
|
260
|
+
const replaceExtension = (fileName: string, extension: string): string =>
|
|
261
|
+
`${fileName.replace(TS_EXTENSION_PATTERN, "")}${extension}`;
|
|
262
|
+
|
|
263
|
+
const transpileOptions = (compilerOptions: ts.CompilerOptions, fileName: string): ts.TranspileOptions => ({
|
|
264
|
+
compilerOptions,
|
|
265
|
+
fileName,
|
|
266
|
+
reportDiagnostics: true,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const emitModule = (module: SourceModule, projectDir: string): ts.Diagnostic[] => {
|
|
270
|
+
const fileName = join(projectDir, module.fileName);
|
|
271
|
+
const declaration = ts.transpileDeclaration(module.source, transpileOptions(DECLARATION_OPTIONS, fileName));
|
|
272
|
+
const javascript = ts.transpileModule(module.source, transpileOptions(MODULE_OPTIONS, fileName));
|
|
273
|
+
const diagnostics = [...declaration.diagnostics ?? [], ...javascript.diagnostics ?? []];
|
|
274
|
+
|
|
275
|
+
if (diagnostics.length > 0) {
|
|
276
|
+
return diagnostics;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
writeFileSync(replaceExtension(fileName, DECLARATION_EXTENSION), declaration.outputText);
|
|
280
|
+
writeFileSync(replaceExtension(fileName, JAVASCRIPT_EXTENSION), javascript.outputText);
|
|
281
|
+
|
|
282
|
+
return [];
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const emitModules = (params: EmitModulesParams): void => {
|
|
286
|
+
const diagnostics: ts.Diagnostic[] = [];
|
|
287
|
+
|
|
288
|
+
for (const module of params.files) {
|
|
289
|
+
diagnostics.push(...emitModule(module, params.projectDir));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (diagnostics.length > 0) {
|
|
293
|
+
throw diagnosticError(params, diagnostics);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
217
297
|
const compileProject = (params: CompileProjectParams): void => {
|
|
298
|
+
ensureModuleScope(params.projectDir);
|
|
218
299
|
const unlinkToolingModules = linkToolingModules(params.projectDir);
|
|
219
300
|
|
|
220
301
|
try {
|
|
@@ -261,4 +342,4 @@ const checkModules = (params: { modules: SourceModule[]; resolveFrom: string; la
|
|
|
261
342
|
rmSync(keepAt, { recursive: true, force: true });
|
|
262
343
|
};
|
|
263
344
|
|
|
264
|
-
export {
|
|
345
|
+
export { checkModules, emitModules, keepFailedProject, type SourceModule };
|
|
@@ -24,6 +24,8 @@ type ApiReferenceOptions = {
|
|
|
24
24
|
props?: ElementProps;
|
|
25
25
|
/** GObject properties the project omits from generated props; without it pages show props that do not exist. */
|
|
26
26
|
omittedProps?: OmittedProps;
|
|
27
|
+
/** Describes GIR byte sequences as `Uint8Array` rather than `number[]`; defaults to false. */
|
|
28
|
+
isByteArrayTyped?: boolean;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
/** Narrows an `ApiReference.symbols` enumeration. */
|
|
@@ -371,7 +373,7 @@ class ApiReference {
|
|
|
371
373
|
this.libraries = options.libraries;
|
|
372
374
|
this.props = options.props ?? {};
|
|
373
375
|
this.omittedProps = options.omittedProps ?? {};
|
|
374
|
-
this.library = Library.load(options.libraries, options.girPath);
|
|
376
|
+
this.library = Library.load(options.libraries, options.girPath, options.isByteArrayTyped === true);
|
|
375
377
|
this.elementContext = { library: this.library, linkFor: (): string | undefined => undefined };
|
|
376
378
|
this.buildIndex();
|
|
377
379
|
}
|
package/src/docs/pipeline.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
computeDocsFingerprint,
|
|
6
6
|
type DocsFingerprintInput,
|
|
7
7
|
FINGERPRINT_FILENAME,
|
|
8
|
+
type GiInputs,
|
|
8
9
|
isDocsOutputFresh,
|
|
9
10
|
} from "../fingerprint.js";
|
|
10
11
|
import { Library } from "../gir/library.js";
|
|
@@ -37,6 +38,7 @@ type DocsOptions = {
|
|
|
37
38
|
props?: ElementProps;
|
|
38
39
|
omittedProps?: OmittedProps;
|
|
39
40
|
isForced?: boolean;
|
|
41
|
+
isByteArrayTyped?: boolean;
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
type DocsManifest = {
|
|
@@ -253,6 +255,13 @@ const outDirRefusal = (outDir: string, reason: string): Error =>
|
|
|
253
255
|
"empty directory or at one gtkx generated, or remove it yourself first.",
|
|
254
256
|
);
|
|
255
257
|
|
|
258
|
+
const giInputs = (options: DocsOptions, girFiles: string[]): GiInputs => ({
|
|
259
|
+
girFiles,
|
|
260
|
+
libraries: options.libraries,
|
|
261
|
+
girPath: options.girPath,
|
|
262
|
+
isByteArrayTyped: options.isByteArrayTyped === true,
|
|
263
|
+
});
|
|
264
|
+
|
|
256
265
|
const assertOwnedOutDir = (options: DocsOptions, manifest: DocsManifest | undefined): void => {
|
|
257
266
|
const stats = statSync(options.outDir, { throwIfNoEntry: false });
|
|
258
267
|
|
|
@@ -301,7 +310,7 @@ const cachedDocsResult = (
|
|
|
301
310
|
return undefined;
|
|
302
311
|
}
|
|
303
312
|
|
|
304
|
-
if (!isDocsOutputFresh(options.outDir, options
|
|
313
|
+
if (!isDocsOutputFresh(options.outDir, giInputs(options, []), input)) {
|
|
305
314
|
return undefined;
|
|
306
315
|
}
|
|
307
316
|
|
|
@@ -335,18 +344,15 @@ const writeDocs = (options: DocsOptions): DocsResult => {
|
|
|
335
344
|
}
|
|
336
345
|
|
|
337
346
|
assertOwnedOutDir(options, previous);
|
|
338
|
-
const library = Library.load(options.libraries, options.girPath);
|
|
347
|
+
const library = Library.load(options.libraries, options.girPath, options.isByteArrayTyped === true);
|
|
339
348
|
const { pages, namespaces } = generatePages(options, input.basePath, library);
|
|
340
349
|
clearOutDir(options, previous);
|
|
341
350
|
mkdirSync(options.outDir, { recursive: true });
|
|
342
351
|
const manifest: DocsManifest = { generator: MANIFEST_GENERATOR, namespaces };
|
|
343
352
|
writeFileSync(manifestPath, JSON.stringify(manifest));
|
|
344
353
|
writePages(options.outDir, pages);
|
|
345
|
-
|
|
346
|
-
writeFileSync(
|
|
347
|
-
join(options.outDir, FINGERPRINT_FILENAME),
|
|
348
|
-
JSON.stringify(computeDocsFingerprint(library.girFiles, options.libraries, options.girPath, input)),
|
|
349
|
-
);
|
|
354
|
+
const fingerprint = computeDocsFingerprint(giInputs(options, library.girFiles), input);
|
|
355
|
+
writeFileSync(join(options.outDir, FINGERPRINT_FILENAME), JSON.stringify(fingerprint));
|
|
350
356
|
|
|
351
357
|
return { isRegenerated: true, namespaces };
|
|
352
358
|
};
|
package/src/docs/symbol-page.ts
CHANGED
|
@@ -16,7 +16,6 @@ import { PRIMITIVE_TS_TYPE, primitiveCategory } from "../gir/primitives.js";
|
|
|
16
16
|
import { callableSpec } from "../store/gi/callable-doc.js";
|
|
17
17
|
import {
|
|
18
18
|
dedupeCallables,
|
|
19
|
-
indexMethodsByName,
|
|
20
19
|
instanceScope,
|
|
21
20
|
matchStaticFinishFunction,
|
|
22
21
|
renderInstanceMethodSignature,
|
|
@@ -146,7 +145,6 @@ type MemberOwner = {
|
|
|
146
145
|
type PropertyAccessorSetup = {
|
|
147
146
|
context: ModuleContext;
|
|
148
147
|
claimedNames: Set<string>;
|
|
149
|
-
methodByName: Map<string, GirFunction>;
|
|
150
148
|
};
|
|
151
149
|
|
|
152
150
|
type ResolvedRecordField = NonNullable<ReturnType<typeof resolveRecordFieldEntry>>;
|
|
@@ -391,7 +389,6 @@ const propertyAccessorSetup = (
|
|
|
391
389
|
return {
|
|
392
390
|
context: docsSignatureContext(owner.namespace, library),
|
|
393
391
|
claimedNames,
|
|
394
|
-
methodByName: indexMethodsByName(dedupeCallables(owner.klass.methods)),
|
|
395
392
|
};
|
|
396
393
|
};
|
|
397
394
|
|
|
@@ -418,7 +415,6 @@ const ownerPropertyEntries = (owner: MemberOwner, setup: PropertyAccessorSetup,
|
|
|
418
415
|
context: setup.context,
|
|
419
416
|
property,
|
|
420
417
|
claimedNames: setup.claimedNames,
|
|
421
|
-
methodByName: setup.methodByName,
|
|
422
418
|
});
|
|
423
419
|
|
|
424
420
|
if (accessor === undefined || seen.has(accessor.jsName)) {
|
|
@@ -637,7 +633,7 @@ const fieldsSection = (record: GirRecord, context: ModuleContext, claimedNames:
|
|
|
637
633
|
const entries: MetaDocEntry[] = [];
|
|
638
634
|
|
|
639
635
|
for (const slot of slots) {
|
|
640
|
-
const field = resolveRecordFieldEntry(context, slot, claimedNames);
|
|
636
|
+
const field = resolveRecordFieldEntry(context, slot, claimedNames, record.fields);
|
|
641
637
|
|
|
642
638
|
if (field === undefined) {
|
|
643
639
|
continue;
|
package/src/fingerprint.ts
CHANGED
|
@@ -7,6 +7,13 @@ import packageManifest from "../package.json" with { type: "json" };
|
|
|
7
7
|
import { arrayGuard, hasFields, isNumber, isString, optionalGuard } from "./guards.js";
|
|
8
8
|
import { readJsonFile } from "./json.js";
|
|
9
9
|
|
|
10
|
+
type GiInputs = {
|
|
11
|
+
girFiles: string[];
|
|
12
|
+
libraries: string[];
|
|
13
|
+
girPath: string[];
|
|
14
|
+
isByteArrayTyped: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
10
17
|
type GiFingerprint = {
|
|
11
18
|
value: string;
|
|
12
19
|
girFiles: string[];
|
|
@@ -56,15 +63,17 @@ const overrideFiles = (): string[] => {
|
|
|
56
63
|
.map((entry: Dirent) => join(entry.parentPath, entry.name));
|
|
57
64
|
};
|
|
58
65
|
|
|
59
|
-
const hashGi = (
|
|
66
|
+
const hashGi = (inputs: GiInputs): string => {
|
|
60
67
|
const hash = createHash("sha256");
|
|
61
68
|
hash.update(CODEGEN_VERSION);
|
|
62
69
|
hash.update("\n");
|
|
63
|
-
hash.update(sortAlpha(libraries));
|
|
70
|
+
hash.update(sortAlpha(inputs.libraries));
|
|
71
|
+
hash.update("\n");
|
|
72
|
+
hash.update(sortAlpha(inputs.girPath));
|
|
64
73
|
hash.update("\n");
|
|
65
|
-
hash.update(
|
|
74
|
+
hash.update(String(inputs.isByteArrayTyped));
|
|
66
75
|
hash.update("\n");
|
|
67
|
-
const hashedFiles = sortStrings([...girFiles, ...overrideFiles()]);
|
|
76
|
+
const hashedFiles = sortStrings([...inputs.girFiles, ...overrideFiles()]);
|
|
68
77
|
|
|
69
78
|
for (const file of hashedFiles) {
|
|
70
79
|
hash.update("\n");
|
|
@@ -76,15 +85,11 @@ const hashGi = (girFiles: string[], libraries: string[], girPath: string[]): str
|
|
|
76
85
|
return hash.digest("hex");
|
|
77
86
|
};
|
|
78
87
|
|
|
79
|
-
const computeGiFingerprint = (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
value: hashGi(girFiles, libraries, girPath),
|
|
85
|
-
girFiles,
|
|
86
|
-
libraries,
|
|
87
|
-
girPath,
|
|
88
|
+
const computeGiFingerprint = (inputs: GiInputs): GiFingerprint => ({
|
|
89
|
+
value: hashGi(inputs),
|
|
90
|
+
girFiles: inputs.girFiles,
|
|
91
|
+
libraries: inputs.libraries,
|
|
92
|
+
girPath: inputs.girPath,
|
|
88
93
|
});
|
|
89
94
|
|
|
90
95
|
const readSentinel = (storeDir: string): unknown => readJsonFile(join(storeDir, FINGERPRINT_FILENAME));
|
|
@@ -103,30 +108,27 @@ const isDocsFingerprint = (value: unknown): value is DocsFingerprint =>
|
|
|
103
108
|
const isJsxFingerprint = (value: unknown): value is JsxFingerprint =>
|
|
104
109
|
hasFields<JsxFingerprint>(value, { value: isString, intrinsicElementCount: isNumber });
|
|
105
110
|
|
|
106
|
-
const recordedGiValue = (sentinel: GiFingerprint,
|
|
107
|
-
if (!hasMatchingRecordedInputs(sentinel,
|
|
111
|
+
const recordedGiValue = (sentinel: GiFingerprint, inputs: GiInputs): string | undefined => {
|
|
112
|
+
if (!hasMatchingRecordedInputs(sentinel, inputs)) {
|
|
108
113
|
return undefined;
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
try {
|
|
112
|
-
return hashGi(sentinel.girFiles, sentinel.libraries
|
|
117
|
+
return hashGi({ ...inputs, girFiles: sentinel.girFiles, libraries: sentinel.libraries });
|
|
113
118
|
} catch {
|
|
114
119
|
return undefined;
|
|
115
120
|
}
|
|
116
121
|
};
|
|
117
122
|
|
|
118
|
-
const isGiStoreFresh = (
|
|
119
|
-
giStoreDir: string,
|
|
120
|
-
libraries: string[],
|
|
121
|
-
girPath: string[],
|
|
122
|
-
): boolean => {
|
|
123
|
+
const isGiStoreFresh = (giStoreDir: string, inputs: GiInputs): boolean => {
|
|
123
124
|
const sentinel = readSentinel(giStoreDir);
|
|
124
125
|
|
|
125
|
-
return isGiFingerprint(sentinel) && recordedGiValue(sentinel,
|
|
126
|
+
return isGiFingerprint(sentinel) && recordedGiValue(sentinel, inputs) === sentinel.value;
|
|
126
127
|
};
|
|
127
128
|
|
|
128
|
-
const hasMatchingRecordedInputs = (sentinel: GiFingerprint,
|
|
129
|
-
sortAlpha(sentinel.libraries) === sortAlpha(libraries) &&
|
|
129
|
+
const hasMatchingRecordedInputs = (sentinel: GiFingerprint, inputs: GiInputs): boolean =>
|
|
130
|
+
sortAlpha(sentinel.libraries) === sortAlpha(inputs.libraries) &&
|
|
131
|
+
sortAlpha(sentinel.girPath ?? []) === sortAlpha(inputs.girPath);
|
|
130
132
|
|
|
131
133
|
const hashDocs = (giValue: string, input: DocsFingerprintInput): string =>
|
|
132
134
|
createHash("sha256")
|
|
@@ -140,30 +142,20 @@ const hashDocs = (giValue: string, input: DocsFingerprintInput): string =>
|
|
|
140
142
|
)
|
|
141
143
|
.digest("hex");
|
|
142
144
|
|
|
143
|
-
const computeDocsFingerprint = (
|
|
144
|
-
|
|
145
|
-
libraries: string[],
|
|
146
|
-
girPath: string[],
|
|
147
|
-
input: DocsFingerprintInput,
|
|
148
|
-
): DocsFingerprint => {
|
|
149
|
-
const gi = computeGiFingerprint(girFiles, libraries, girPath);
|
|
145
|
+
const computeDocsFingerprint = (inputs: GiInputs, input: DocsFingerprintInput): DocsFingerprint => {
|
|
146
|
+
const gi = computeGiFingerprint(inputs);
|
|
150
147
|
|
|
151
148
|
return { value: hashDocs(gi.value, input), gi };
|
|
152
149
|
};
|
|
153
150
|
|
|
154
|
-
const isDocsOutputFresh = (
|
|
155
|
-
outDir: string,
|
|
156
|
-
libraries: string[],
|
|
157
|
-
girPath: string[],
|
|
158
|
-
input: DocsFingerprintInput,
|
|
159
|
-
): boolean => {
|
|
151
|
+
const isDocsOutputFresh = (outDir: string, inputs: GiInputs, input: DocsFingerprintInput): boolean => {
|
|
160
152
|
const sentinel = readSentinel(outDir);
|
|
161
153
|
|
|
162
154
|
if (!isDocsFingerprint(sentinel)) {
|
|
163
155
|
return false;
|
|
164
156
|
}
|
|
165
157
|
|
|
166
|
-
const giValue = recordedGiValue(sentinel.gi,
|
|
158
|
+
const giValue = recordedGiValue(sentinel.gi, inputs);
|
|
167
159
|
|
|
168
160
|
return giValue !== undefined && hashDocs(giValue, input) === sentinel.value;
|
|
169
161
|
};
|
|
@@ -217,6 +209,7 @@ export {
|
|
|
217
209
|
computeJsxFingerprint,
|
|
218
210
|
jsxStoreFreshness,
|
|
219
211
|
type DocsFingerprintInput,
|
|
212
|
+
type GiInputs,
|
|
220
213
|
type GiFingerprint,
|
|
221
214
|
type JsxFingerprintInput,
|
|
222
215
|
};
|