@gtkx/codegen 1.1.0 → 1.2.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/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 +1 -3
- 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/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 +1 -3
- package/dist/store/gi/callables.d.ts.map +1 -1
- package/dist/store/gi/callables.js +19 -4
- 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 +48 -9
- 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/interface.js +2 -2
- 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.js +3 -3
- package/dist/store/gi/record-constructor.js.map +1 -1
- package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
- package/dist/store/gi/record-field-accessor.js +15 -3
- package/dist/store/gi/record-field-accessor.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 +25 -4
- 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/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 +0 -4
- package/src/fingerprint.ts +31 -38
- package/src/gi.ts +9 -2
- 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 +26 -7
- package/src/store/gi/class.ts +63 -7
- package/src/store/gi/constant.ts +1 -1
- package/src/store/gi/enum.ts +2 -6
- package/src/store/gi/interface.ts +2 -2
- package/src/store/gi/method.ts +4 -9
- package/src/store/gi/property-accessor.ts +22 -193
- package/src/store/gi/record-constructor.ts +3 -3
- package/src/store/gi/record-field-accessor.ts +18 -3
- package/src/store/gi/return-wrap.ts +1 -1
- package/src/store/gi/signal.ts +30 -4
- package/src/store/jsx-store.ts +0 -1
- package/src/store/store-fs.ts +3 -9
- package/src/xml.ts +43 -1
|
@@ -1,52 +1,19 @@
|
|
|
1
|
-
import { rmSync
|
|
1
|
+
import { rmSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { emitModules, type SourceModule } from "../compile.js";
|
|
4
4
|
|
|
5
5
|
type CompileStoreParams = {
|
|
6
6
|
storeDir: string;
|
|
7
7
|
files: SourceModule[];
|
|
8
8
|
packageName: string;
|
|
9
|
-
requiresEnvReference?: boolean;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const EMIT_OPTIONS = {
|
|
13
|
-
declaration: true,
|
|
14
|
-
removeComments: false,
|
|
15
|
-
sourceMap: false,
|
|
16
|
-
declarationMap: false,
|
|
17
|
-
rootDir: ".",
|
|
18
|
-
outDir: ".",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const ENV_REFERENCE_FILE = "__gtkx-env__.d.ts";
|
|
22
|
-
|
|
23
|
-
const writeEnvReference = (storeDir: string): (() => void) => {
|
|
24
|
-
writeFileSync(join(storeDir, ENV_REFERENCE_FILE), "/// <reference types=\"@gtkx/react/env\" />\n");
|
|
25
|
-
|
|
26
|
-
return () => {
|
|
27
|
-
rmSync(join(storeDir, ENV_REFERENCE_FILE), { force: true });
|
|
28
|
-
};
|
|
29
9
|
};
|
|
30
10
|
|
|
31
11
|
const compileStore = (params: CompileStoreParams): void => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
? [{ fileName: ENV_REFERENCE_FILE }, ...params.files]
|
|
38
|
-
: params.files;
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
compileProject({
|
|
42
|
-
projectDir: params.storeDir,
|
|
43
|
-
files,
|
|
44
|
-
compilerOptions: EMIT_OPTIONS,
|
|
45
|
-
label: `the generated ${params.packageName} store`,
|
|
46
|
-
});
|
|
47
|
-
} finally {
|
|
48
|
-
removeEnvReference();
|
|
49
|
-
}
|
|
12
|
+
emitModules({
|
|
13
|
+
projectDir: params.storeDir,
|
|
14
|
+
files: params.files,
|
|
15
|
+
label: `the generated ${params.packageName} store`,
|
|
16
|
+
});
|
|
50
17
|
|
|
51
18
|
for (const file of params.files) {
|
|
52
19
|
rmSync(join(params.storeDir, file.fileName), { force: true });
|
|
@@ -69,6 +69,15 @@ type PlainTypeMembersOptions = {
|
|
|
69
69
|
hasGtype: boolean;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
const RUNTIME_OWNED_LIFETIME_METHODS: Set<string> = new Set([
|
|
73
|
+
"force_floating",
|
|
74
|
+
"free",
|
|
75
|
+
"ref",
|
|
76
|
+
"ref_sink",
|
|
77
|
+
"take_ref",
|
|
78
|
+
"unref",
|
|
79
|
+
]);
|
|
80
|
+
|
|
72
81
|
const renderInstanceMethodSignature: InstanceMemberRenderer = instanceMemberRenderer(
|
|
73
82
|
(context, callable, { name, finishFn }) =>
|
|
74
83
|
`${memberDoc(context, callable, finishFn)}${memberSignatureText(context, callable, name, { finishFn })};`,
|
|
@@ -373,6 +382,7 @@ const isEmittableCallable = (context: ModuleContext, callable: GirFunction): boo
|
|
|
373
382
|
callable.introspectable &&
|
|
374
383
|
callable.shadowedBy === undefined &&
|
|
375
384
|
callable.cIdentifier !== undefined &&
|
|
385
|
+
!RUNTIME_OWNED_LIFETIME_METHODS.has(callable.name) &&
|
|
376
386
|
!hasUnmarshalableParam(context, callable);
|
|
377
387
|
|
|
378
388
|
const constructorMemberName = (girName: string): string | undefined => {
|
|
@@ -408,6 +418,20 @@ const renderStaticSignature = (
|
|
|
408
418
|
};
|
|
409
419
|
};
|
|
410
420
|
|
|
421
|
+
const staticMemberName = (
|
|
422
|
+
context: ModuleContext,
|
|
423
|
+
callable: GirFunction,
|
|
424
|
+
resolveName: (girName: string) => string | undefined,
|
|
425
|
+
): string | undefined => {
|
|
426
|
+
if (!isEmittableCallable(context, callable)) {
|
|
427
|
+
return undefined;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const name = resolveName(callable.name);
|
|
431
|
+
|
|
432
|
+
return name !== undefined && isEmittableMemberName(name) ? name : undefined;
|
|
433
|
+
};
|
|
434
|
+
|
|
411
435
|
const collectStaticMembers = (
|
|
412
436
|
context: ModuleContext,
|
|
413
437
|
group: GirFunction[],
|
|
@@ -416,7 +440,7 @@ const collectStaticMembers = (
|
|
|
416
440
|
const members: StaticMember[] = [];
|
|
417
441
|
|
|
418
442
|
for (const callable of group) {
|
|
419
|
-
const name =
|
|
443
|
+
const name = staticMemberName(context, callable, resolveName);
|
|
420
444
|
|
|
421
445
|
if (name !== undefined) {
|
|
422
446
|
members.push({ callable, name });
|
|
@@ -427,13 +451,10 @@ const collectStaticMembers = (
|
|
|
427
451
|
};
|
|
428
452
|
|
|
429
453
|
const staticMembers = (context: ModuleContext, callables: Callables): StaticMember[] => [
|
|
430
|
-
...collectStaticMembers(context, callables.constructors,
|
|
454
|
+
...collectStaticMembers(context, callables.constructors, memberName),
|
|
431
455
|
...collectStaticMembers(context, callables.functions, memberName),
|
|
432
456
|
];
|
|
433
457
|
|
|
434
|
-
const constructorMemberNames = (context: ModuleContext, constructors: GirFunction[]): string[] =>
|
|
435
|
-
collectStaticMembers(context, constructors, constructorMemberName).map((member) => member.name);
|
|
436
|
-
|
|
437
458
|
const collectStaticEntries = (
|
|
438
459
|
context: ModuleContext,
|
|
439
460
|
group: GirFunction[],
|
|
@@ -513,10 +534,8 @@ export {
|
|
|
513
534
|
dedupeCallables,
|
|
514
535
|
generateBindings,
|
|
515
536
|
matchStaticFinishFunction,
|
|
516
|
-
indexMethodsByName,
|
|
517
537
|
isEmittableCallable,
|
|
518
538
|
renderStaticSignature,
|
|
519
|
-
constructorMemberNames,
|
|
520
539
|
renderStaticHead,
|
|
521
540
|
renderPlainTypeMembers,
|
|
522
541
|
staticMembers,
|
package/src/store/gi/class.ts
CHANGED
|
@@ -11,10 +11,12 @@ import {
|
|
|
11
11
|
type InheritedMethods,
|
|
12
12
|
} from "../../analysis/inheritance.js";
|
|
13
13
|
import {
|
|
14
|
+
areCallablesAssignable,
|
|
14
15
|
type ClaimedMembers,
|
|
15
16
|
claimInterfaceMembers,
|
|
16
17
|
inheritedMembers,
|
|
17
18
|
interfaceConflicts,
|
|
19
|
+
omittedKeys,
|
|
18
20
|
omittedTypeRef,
|
|
19
21
|
} from "../../analysis/interface-conflicts.js";
|
|
20
22
|
import { ancestorChain, getParentRef, type ResolvedAncestor } from "../../gir/ancestry.js";
|
|
@@ -22,13 +24,13 @@ import { isEmittableEntity } from "../../gir/emittable.js";
|
|
|
22
24
|
import { indentMembers } from "../../writer/emit.js";
|
|
23
25
|
import {
|
|
24
26
|
type Callables,
|
|
25
|
-
constructorMemberNames,
|
|
26
27
|
dedupeCallables,
|
|
27
28
|
generateBindings,
|
|
28
29
|
type InstanceScope,
|
|
29
30
|
instanceScope,
|
|
30
31
|
renderClassInstanceMember,
|
|
31
32
|
renderStaticHead,
|
|
33
|
+
staticMembers,
|
|
32
34
|
} from "./callables.js";
|
|
33
35
|
import { renderClassConstructor, renderConstructorPropsInterface } from "./constructor-props.js";
|
|
34
36
|
import { getDoc } from "./doc-spec.js";
|
|
@@ -91,7 +93,7 @@ const generateClass = (context: ModuleContext, klass: GirClass): void => {
|
|
|
91
93
|
|
|
92
94
|
generateBindings(context, callables);
|
|
93
95
|
const parentExpression = resolveParent(context, klass);
|
|
94
|
-
const extendsClause = renderExtendsClause(context, parentExpression, callables);
|
|
96
|
+
const extendsClause = renderExtendsClause(context, parentExpression, klass, callables);
|
|
95
97
|
const implemented = resolveImplementedRefs(context, klass);
|
|
96
98
|
const typeRefs = implemented.map((ref) => omittedTypeRef(ref.typeRef, ref.conflicts));
|
|
97
99
|
const implementsClause = typeRefs.length === 0 ? "" : ` implements ${typeRefs.join(", ")}`;
|
|
@@ -189,7 +191,6 @@ const renderClassMembers = (
|
|
|
189
191
|
context,
|
|
190
192
|
property,
|
|
191
193
|
claimedNames,
|
|
192
|
-
methodByName: scope.methodByName,
|
|
193
194
|
inheritedTypes,
|
|
194
195
|
inheritedNames,
|
|
195
196
|
});
|
|
@@ -336,25 +337,80 @@ const resolveImplementedRefs = (context: ModuleContext, klass: GirClass): Implem
|
|
|
336
337
|
return refs;
|
|
337
338
|
};
|
|
338
339
|
|
|
340
|
+
const classCallables = (klass: GirClass): Callables => ({
|
|
341
|
+
constructors: klass.constructors,
|
|
342
|
+
functions: klass.functions,
|
|
343
|
+
methods: klass.methods,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const resolveParentClass = (context: ModuleContext, klass: GirClass): ResolvedAncestor | undefined => {
|
|
347
|
+
const parent = getParentRef(klass);
|
|
348
|
+
|
|
349
|
+
if (parent === undefined) {
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const resolved = context.library.resolveType(parent.namespaceName ?? context.namespace.name, parent.typeName);
|
|
354
|
+
|
|
355
|
+
return resolved?.kind === "class" ? { klass: resolved.value, namespaceName: resolved.namespace.name } : undefined;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const addAncestorStatics = (context: ModuleContext, klass: GirClass, table: Map<string, GirFunction>): void => {
|
|
359
|
+
const members = staticMembers(context, classCallables(klass));
|
|
360
|
+
|
|
361
|
+
for (const member of members) {
|
|
362
|
+
if (!table.has(member.name)) {
|
|
363
|
+
table.set(member.name, member.callable);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const inheritedStatics = (context: ModuleContext, klass: GirClass): Map<string, GirFunction> => {
|
|
369
|
+
const table: Map<string, GirFunction> = new Map();
|
|
370
|
+
const parent = resolveParentClass(context, klass);
|
|
371
|
+
|
|
372
|
+
if (parent === undefined) {
|
|
373
|
+
return table;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
for (const ancestor of ancestorChain(context.library, parent.klass, parent.namespaceName)) {
|
|
377
|
+
addAncestorStatics(context, ancestor.klass, table);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return table;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const shadowedStaticNames = (context: ModuleContext, klass: GirClass, callables: Callables): string[] => {
|
|
384
|
+
const inherited = inheritedStatics(context, klass);
|
|
385
|
+
|
|
386
|
+
return staticMembers(context, callables)
|
|
387
|
+
.filter((member) => {
|
|
388
|
+
const shadowed = inherited.get(member.name);
|
|
389
|
+
|
|
390
|
+
return shadowed !== undefined && !areCallablesAssignable(context.library, member.callable, shadowed);
|
|
391
|
+
})
|
|
392
|
+
.map((member) => member.name);
|
|
393
|
+
};
|
|
394
|
+
|
|
339
395
|
const renderExtendsClause = (
|
|
340
396
|
context: ModuleContext,
|
|
341
397
|
parentExpression: string | undefined,
|
|
398
|
+
klass: GirClass,
|
|
342
399
|
callables: Callables,
|
|
343
400
|
): string => {
|
|
344
401
|
if (parentExpression === undefined) {
|
|
345
402
|
return "";
|
|
346
403
|
}
|
|
347
404
|
|
|
348
|
-
const
|
|
405
|
+
const staticNames = shadowedStaticNames(context, klass, callables);
|
|
349
406
|
|
|
350
|
-
if (
|
|
407
|
+
if (staticNames.length === 0) {
|
|
351
408
|
return ` extends ${parentExpression}`;
|
|
352
409
|
}
|
|
353
410
|
|
|
354
411
|
context.addRuntimeTypeImport("StaticBase");
|
|
355
|
-
const omitted = constructorNames.map((name) => JSON.stringify(name)).join(" | ");
|
|
356
412
|
|
|
357
|
-
return ` extends (${parentExpression} as StaticBase<typeof ${parentExpression}, ${
|
|
413
|
+
return ` extends (${parentExpression} as StaticBase<typeof ${parentExpression}, ${omittedKeys(staticNames)}>)`;
|
|
358
414
|
};
|
|
359
415
|
|
|
360
416
|
const resolveParent = (context: ModuleContext, klass: GirClass): string | undefined => {
|
package/src/store/gi/constant.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { isEmittableEntity } from "../../gir/emittable.js";
|
|
|
7
7
|
import { getDoc } from "./doc-spec.js";
|
|
8
8
|
|
|
9
9
|
const TRUE_VALUES: Set<string> = new Set(["true", "1"]);
|
|
10
|
-
const BIGINT_CATEGORIES: Set<PrimitiveCategory> = new Set(["bigint64", "biguint64", "gtype"]);
|
|
10
|
+
const BIGINT_CATEGORIES: Set<PrimitiveCategory> = new Set(["bigint64", "biguint64", "gtype", "pointer"]);
|
|
11
11
|
|
|
12
12
|
const generateConstant = (context: ModuleContext, constant: GirConstant): void => {
|
|
13
13
|
if (!isEmittableEntity(constant)) {
|
package/src/store/gi/enum.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sanitizeTypeIdentifier, sourceStringLiteral, uniqBy } from "@gtkx/utils";
|
|
1
|
+
import { escapeIdentifierStart, sanitizeTypeIdentifier, sourceStringLiteral, uniqBy } from "@gtkx/utils";
|
|
2
2
|
import type { EnumMember, GirEnum } from "../../gir/enum.js";
|
|
3
3
|
import type { ModuleContext } from "../../writer/context.js";
|
|
4
4
|
import { hasAnnotations } from "../../gir/annotations.js";
|
|
@@ -94,11 +94,7 @@ const appendEnumDeclaration = (context: ModuleContext, enumeration: GirEnum, mem
|
|
|
94
94
|
});
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
-
const enumMemberKey = (name: string): string =>
|
|
98
|
-
const upper = name.toUpperCase().replaceAll("-", "_");
|
|
99
|
-
|
|
100
|
-
return /^\d/.test(upper) ? `_${upper}` : upper;
|
|
101
|
-
};
|
|
97
|
+
const enumMemberKey = (name: string): string => escapeIdentifierStart(name.toUpperCase().replaceAll("-", "_"));
|
|
102
98
|
|
|
103
99
|
const renderQuarkExpression = (context: ModuleContext, errorDomain: string): string => {
|
|
104
100
|
if (context.namespace.name === "GLib") {
|
|
@@ -336,11 +336,11 @@ const collectMethodMembers = (options: MethodMemberOptions): string[] => {
|
|
|
336
336
|
};
|
|
337
337
|
|
|
338
338
|
const collectPropertyMembers = (options: PropertyMemberOptions): string[] => {
|
|
339
|
-
const { context, iface,
|
|
339
|
+
const { context, iface, renderers, claimedNames } = options;
|
|
340
340
|
const members: string[] = [];
|
|
341
341
|
|
|
342
342
|
for (const property of iface.properties) {
|
|
343
|
-
const block = renderers.renderProperty({ context, property, claimedNames
|
|
343
|
+
const block = renderers.renderProperty({ context, property, claimedNames });
|
|
344
344
|
|
|
345
345
|
if (block !== undefined) {
|
|
346
346
|
members.push(block);
|
package/src/store/gi/method.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { camelCase, sourceStringLiteral } from "@gtkx/utils";
|
|
1
|
+
import { camelCase, escapeIdentifierStart, sourceStringLiteral } from "@gtkx/utils";
|
|
2
2
|
import type { GirFunction } from "../../gir/function.js";
|
|
3
3
|
import type { GirType } from "../../gir/type.js";
|
|
4
4
|
import type { ModuleContext } from "../../writer/context.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
inputParameters,
|
|
20
20
|
parameterIdentifier,
|
|
21
21
|
} from "../../analysis/param-structure.js";
|
|
22
|
-
import { renderTsType } from "../../analysis/ts-type.js";
|
|
22
|
+
import { renderParameterTsType, renderTsType } from "../../analysis/ts-type.js";
|
|
23
23
|
import { type GirParameter, isCallerAllocatedOut, isInoutParameter, isOutParameter } from "../../gir/parameter.js";
|
|
24
24
|
import { hasUnknownArrayLength, type TypeId } from "../../gir/type-id.js";
|
|
25
25
|
import { areClosuresInvoked } from "./closure-invocation.js";
|
|
@@ -86,12 +86,7 @@ type PlanArgsContext = {
|
|
|
86
86
|
folded: Set<number>;
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
const memberName = (girName: string): string =>
|
|
90
|
-
const camel = camelCase(girName);
|
|
91
|
-
|
|
92
|
-
return /^\d/.test(camel) ? `_${camel}` : camel;
|
|
93
|
-
};
|
|
94
|
-
|
|
89
|
+
const memberName = (girName: string): string => escapeIdentifierStart(camelCase(girName));
|
|
95
90
|
const methodExportName = (fn: GirFunction): string => memberName(fn.name);
|
|
96
91
|
|
|
97
92
|
const arrayLengthArgument = (source: GirParameter, sourceIndex: number): string => {
|
|
@@ -125,7 +120,7 @@ const parameterAnnotation = (context: ModuleContext, fn: GirFunction, parameter:
|
|
|
125
120
|
return comparator;
|
|
126
121
|
}
|
|
127
122
|
|
|
128
|
-
const base =
|
|
123
|
+
const base = renderParameterTsType(context, parameter.type, parameter.nullable);
|
|
129
124
|
|
|
130
125
|
return requiresClosureAnnotation(context, fn, parameter) ? closureAnnotation(context, base) : base;
|
|
131
126
|
};
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sourceStringLiteral, toCamelIdentifier } from "@gtkx/utils";
|
|
2
2
|
import type { GirFunction } from "../../gir/function.js";
|
|
3
3
|
import type { TypeId } from "../../gir/type-id.js";
|
|
4
4
|
import type { ModuleContext } from "../../writer/context.js";
|
|
5
5
|
import { renderDescriptor } from "../../analysis/descriptor-render.js";
|
|
6
|
-
import { inputParameters } from "../../analysis/param-structure.js";
|
|
7
6
|
import { renderTsType } from "../../analysis/ts-type.js";
|
|
8
7
|
import { type GirProperty, isConstructableProperty } from "../../gir/property.js";
|
|
9
|
-
import { comparisonContextFor } from "../../writer/comparison-context.js";
|
|
10
8
|
import { renderBlock } from "../../writer/emit.js";
|
|
11
9
|
import { isEmittableCallable } from "./callables.js";
|
|
12
10
|
import { getDoc } from "./doc-spec.js";
|
|
13
|
-
import { methodExportName
|
|
14
|
-
|
|
15
|
-
type AccessorTypes = {
|
|
16
|
-
readType: string;
|
|
17
|
-
writeType: string;
|
|
18
|
-
};
|
|
11
|
+
import { methodExportName } from "./method.js";
|
|
19
12
|
|
|
20
13
|
type InheritedAccessorTypes = {
|
|
21
14
|
readType: string | undefined;
|
|
@@ -29,24 +22,17 @@ type ResolvedAccessor = {
|
|
|
29
22
|
writeType: string;
|
|
30
23
|
hasGetter: boolean;
|
|
31
24
|
isWritable: boolean;
|
|
32
|
-
getterMember: string | undefined;
|
|
33
|
-
setterMember: string | undefined;
|
|
34
25
|
};
|
|
35
26
|
|
|
36
27
|
type PropertyAccessorArgs = {
|
|
37
28
|
context: ModuleContext;
|
|
38
29
|
property: GirProperty;
|
|
39
30
|
claimedNames: Set<string>;
|
|
40
|
-
methodByName: Map<string, GirFunction>;
|
|
41
31
|
inheritedTypes?: InheritedAccessorTypes | undefined;
|
|
42
32
|
inheritedNames?: Set<string> | undefined;
|
|
43
33
|
};
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
type AccessorDelegates = { getter: AccessorDelegate | undefined; setter: AccessorDelegate | undefined };
|
|
47
|
-
type TypedDelegates = { types: AccessorTypes; delegates: AccessorDelegates };
|
|
48
|
-
|
|
49
|
-
const NULLABLE_SUFFIX = " | null";
|
|
35
|
+
const NON_NULLABLE_KINDS: Set<string> = new Set(["primitive", "enum"]);
|
|
50
36
|
|
|
51
37
|
const isNullablePropertyType = (context: ModuleContext, type: TypeId | undefined): boolean => {
|
|
52
38
|
if (type === undefined) {
|
|
@@ -59,141 +45,19 @@ const isNullablePropertyType = (context: ModuleContext, type: TypeId | undefined
|
|
|
59
45
|
return true;
|
|
60
46
|
}
|
|
61
47
|
|
|
62
|
-
if (resolved.kind === "primitive") {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (resolved.kind === "enum") {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
48
|
if (resolved.kind === "alias") {
|
|
71
49
|
return isNullablePropertyType(context, resolved.value.target);
|
|
72
50
|
}
|
|
73
51
|
|
|
74
|
-
return
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const resolveDelegate = (
|
|
78
|
-
args: PropertyAccessorArgs,
|
|
79
|
-
attribute: string | undefined,
|
|
80
|
-
member: string | undefined,
|
|
81
|
-
isDelegatable: (method: GirFunction) => boolean,
|
|
82
|
-
): AccessorDelegate | undefined => {
|
|
83
|
-
const method = member !== undefined && attribute !== undefined ? args.methodByName.get(attribute) : undefined;
|
|
84
|
-
|
|
85
|
-
if (member === undefined || method === undefined || !isDelegatable(method)) {
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return { member, method };
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const resolveGetterDelegate = (args: PropertyAccessorArgs, jsName: string): AccessorDelegate | undefined => {
|
|
93
|
-
const { context, property, claimedNames } = args;
|
|
94
|
-
const member = delegateMember(property.getter, jsName, claimedNames);
|
|
95
|
-
|
|
96
|
-
return resolveDelegate(
|
|
97
|
-
args,
|
|
98
|
-
property.getter,
|
|
99
|
-
member,
|
|
100
|
-
(method) =>
|
|
101
|
-
inputParameters(context.library, method).length === 0 &&
|
|
102
|
-
!renderMethodReturnType(context, method).startsWith("["),
|
|
103
|
-
);
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const resolveSetterDelegate = (
|
|
107
|
-
args: PropertyAccessorArgs,
|
|
108
|
-
jsName: string,
|
|
109
|
-
isWritable: boolean,
|
|
110
|
-
): AccessorDelegate | undefined => {
|
|
111
|
-
const { context, property, claimedNames } = args;
|
|
112
|
-
const member = isWritable ? delegateMember(property.setter, jsName, claimedNames) : undefined;
|
|
113
|
-
|
|
114
|
-
return resolveDelegate(
|
|
115
|
-
args,
|
|
116
|
-
property.setter,
|
|
117
|
-
member,
|
|
118
|
-
(method) => inputParameters(context.library, method).length === 1,
|
|
119
|
-
);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const baseTypeName = (type: string): string =>
|
|
123
|
-
type.endsWith(NULLABLE_SUFFIX) ? type.slice(0, -NULLABLE_SUFFIX.length) : type;
|
|
124
|
-
|
|
125
|
-
const areDelegateBaseTypesAgreeing = (
|
|
126
|
-
context: ModuleContext,
|
|
127
|
-
getter: AccessorDelegate | undefined,
|
|
128
|
-
setter: AccessorDelegate | undefined,
|
|
129
|
-
): boolean => {
|
|
130
|
-
const setterParam = setter?.method.parameters[0];
|
|
131
|
-
|
|
132
|
-
if (setterParam === undefined || getter === undefined) {
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const scratch = comparisonContextFor(context);
|
|
137
|
-
const read = baseTypeName(renderMethodReturnType(scratch, getter.method));
|
|
138
|
-
const written = baseTypeName(renderTsType(scratch, setterParam.type, false));
|
|
139
|
-
|
|
140
|
-
return read === written;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const resolveDelegates = (args: PropertyAccessorArgs, jsName: string, isWritable: boolean): AccessorDelegates => {
|
|
144
|
-
const getter = resolveGetterDelegate(args, jsName);
|
|
145
|
-
const setter = resolveSetterDelegate(args, jsName, isWritable);
|
|
146
|
-
|
|
147
|
-
if (areDelegateBaseTypesAgreeing(args.context, getter, setter)) {
|
|
148
|
-
return { getter, setter };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return { getter, setter: undefined };
|
|
52
|
+
return !NON_NULLABLE_KINDS.has(resolved.kind);
|
|
152
53
|
};
|
|
153
54
|
|
|
154
55
|
const declaredPropertyType = (context: ModuleContext, property: GirProperty): string =>
|
|
155
|
-
renderTsType(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
delegates: AccessorDelegates,
|
|
161
|
-
): AccessorTypes => {
|
|
162
|
-
const getterMethod = delegates.getter?.method;
|
|
163
|
-
const setterParam = delegates.setter?.method.parameters[0];
|
|
164
|
-
|
|
165
|
-
return {
|
|
166
|
-
readType: getterMethod === undefined
|
|
167
|
-
? declaredPropertyType(context, property)
|
|
168
|
-
: renderMethodReturnType(context, getterMethod),
|
|
169
|
-
writeType: setterParam === undefined
|
|
170
|
-
? declaredPropertyType(context, property)
|
|
171
|
-
: renderTsType(context, setterParam.type, setterParam.nullable || setterParam.optional),
|
|
172
|
-
};
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const isAssignableType = (source: string, target: string): boolean =>
|
|
176
|
-
source === target || baseTypeName(target) === source;
|
|
177
|
-
|
|
178
|
-
const agreeingDelegates = (
|
|
179
|
-
delegates: AccessorDelegates,
|
|
180
|
-
ownTypes: AccessorTypes,
|
|
181
|
-
declaredTypes: AccessorTypes,
|
|
182
|
-
): AccessorDelegates => ({
|
|
183
|
-
getter: isAssignableType(ownTypes.readType, declaredTypes.readType) ? delegates.getter : undefined,
|
|
184
|
-
setter: isAssignableType(declaredTypes.writeType, ownTypes.writeType) ? delegates.setter : undefined,
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
const resolveTypedDelegates = (args: PropertyAccessorArgs, resolved: AccessorDelegates): TypedDelegates => {
|
|
188
|
-
const ownTypes = resolveOwnTypes(args.context, args.property, resolved);
|
|
189
|
-
|
|
190
|
-
const types = {
|
|
191
|
-
readType: args.inheritedTypes?.readType ?? ownTypes.readType,
|
|
192
|
-
writeType: args.inheritedTypes?.writeType ?? ownTypes.writeType,
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
return { types, delegates: agreeingDelegates(resolved, ownTypes, types) };
|
|
196
|
-
};
|
|
56
|
+
renderTsType(
|
|
57
|
+
context,
|
|
58
|
+
property.type,
|
|
59
|
+
property.defaultValue === "NULL" || isNullablePropertyType(context, property.type),
|
|
60
|
+
);
|
|
197
61
|
|
|
198
62
|
const isSkippedAccessor = (args: PropertyAccessorArgs, jsName: string): boolean =>
|
|
199
63
|
!args.property.introspectable ||
|
|
@@ -201,31 +65,28 @@ const isSkippedAccessor = (args: PropertyAccessorArgs, jsName: string): boolean
|
|
|
201
65
|
args.inheritedNames?.has(jsName) === true ||
|
|
202
66
|
jsName === "constructor";
|
|
203
67
|
|
|
68
|
+
const isAccessorEmittable = (args: PropertyAccessorArgs, jsName: string, isWritable: boolean): boolean =>
|
|
69
|
+
!isSkippedAccessor(args, jsName) && (args.property.readable || isWritable);
|
|
70
|
+
|
|
204
71
|
const resolveAccessor = (args: PropertyAccessorArgs): ResolvedAccessor | undefined => {
|
|
205
72
|
const { property } = args;
|
|
206
73
|
const jsName = toCamelIdentifier(property.name);
|
|
207
|
-
|
|
208
|
-
if (isSkippedAccessor(args, jsName)) {
|
|
209
|
-
return undefined;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
74
|
const isWritable = isConstructableProperty(property) && !property.constructOnly;
|
|
213
|
-
const { types, delegates } = resolveTypedDelegates(args, resolveDelegates(args, jsName, isWritable));
|
|
214
|
-
const hasGetter = property.readable || delegates.getter !== undefined;
|
|
215
75
|
|
|
216
|
-
if (!
|
|
76
|
+
if (!isAccessorEmittable(args, jsName, isWritable)) {
|
|
217
77
|
return undefined;
|
|
218
78
|
}
|
|
219
79
|
|
|
80
|
+
const declared = declaredPropertyType(args.context, property);
|
|
81
|
+
const hasGetter = property.readable;
|
|
82
|
+
|
|
220
83
|
return {
|
|
221
84
|
property,
|
|
222
85
|
jsName,
|
|
223
|
-
readType:
|
|
224
|
-
writeType:
|
|
86
|
+
readType: args.inheritedTypes?.readType ?? declared,
|
|
87
|
+
writeType: args.inheritedTypes?.writeType ?? declared,
|
|
225
88
|
hasGetter,
|
|
226
89
|
isWritable,
|
|
227
|
-
getterMember: delegates.getter?.member,
|
|
228
|
-
setterMember: delegates.setter?.member,
|
|
229
90
|
};
|
|
230
91
|
};
|
|
231
92
|
|
|
@@ -234,7 +95,6 @@ const resolveOwnerAccessor = (
|
|
|
234
95
|
property: GirProperty,
|
|
235
96
|
methods: GirFunction[],
|
|
236
97
|
): ResolvedAccessor | undefined => {
|
|
237
|
-
const methodByName: Map<string, GirFunction> = new Map();
|
|
238
98
|
const claimedNames: Set<string> = new Set();
|
|
239
99
|
|
|
240
100
|
for (const method of methods) {
|
|
@@ -242,11 +102,10 @@ const resolveOwnerAccessor = (
|
|
|
242
102
|
continue;
|
|
243
103
|
}
|
|
244
104
|
|
|
245
|
-
methodByName.set(method.name, method);
|
|
246
105
|
claimedNames.add(methodExportName(method));
|
|
247
106
|
}
|
|
248
107
|
|
|
249
|
-
return resolveAccessor({ context, property, claimedNames
|
|
108
|
+
return resolveAccessor({ context, property, claimedNames });
|
|
250
109
|
};
|
|
251
110
|
|
|
252
111
|
const resolveAccessorTypes = (
|
|
@@ -284,18 +143,15 @@ const renderResolvedPropertyAccessor = (
|
|
|
284
143
|
property: GirProperty,
|
|
285
144
|
accessor: ResolvedAccessor,
|
|
286
145
|
): string => {
|
|
287
|
-
const { jsName, readType, writeType, hasGetter, isWritable
|
|
146
|
+
const { jsName, readType, writeType, hasGetter, isWritable } = accessor;
|
|
288
147
|
const blocks: string[] = [];
|
|
289
148
|
|
|
290
149
|
if (hasGetter) {
|
|
291
|
-
blocks.push(renderBlock(`get ${jsName}(): ${readType}`,
|
|
150
|
+
blocks.push(renderBlock(`get ${jsName}(): ${readType}`, renderGenericGetBody(context, property, readType)));
|
|
292
151
|
}
|
|
293
152
|
|
|
294
153
|
if (isWritable) {
|
|
295
|
-
|
|
296
|
-
setterMember === undefined ? renderGenericSetBody(context, property) : `this.${setterMember}(value);`;
|
|
297
|
-
|
|
298
|
-
blocks.push(renderBlock(`set ${jsName}(value: ${writeType})`, setterBody));
|
|
154
|
+
blocks.push(renderBlock(`set ${jsName}(value: ${writeType})`, renderGenericSetBody(context, property)));
|
|
299
155
|
}
|
|
300
156
|
|
|
301
157
|
return `${propertyDoc(property)}${blocks.join("\n\n")}`;
|
|
@@ -347,33 +203,6 @@ const renderGenericSetBody = (context: ModuleContext, property: GirProperty): st
|
|
|
347
203
|
return `setObjectProperty(this, ${sourceStringLiteral(property.name)}, ${descriptor}, value);`;
|
|
348
204
|
};
|
|
349
205
|
|
|
350
|
-
const renderGetterBody = (context: ModuleContext, property: GirProperty, accessor: ResolvedAccessor): string =>
|
|
351
|
-
accessor.getterMember === undefined
|
|
352
|
-
? renderGenericGetBody(context, property, accessor.readType)
|
|
353
|
-
: `return this.${accessor.getterMember}();`;
|
|
354
|
-
|
|
355
|
-
const delegateMember = (
|
|
356
|
-
attribute: string | undefined,
|
|
357
|
-
accessorName: string,
|
|
358
|
-
claimedNames: Set<string>,
|
|
359
|
-
): string | undefined => {
|
|
360
|
-
if (attribute === undefined) {
|
|
361
|
-
return undefined;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const member = camelCase(attribute);
|
|
365
|
-
|
|
366
|
-
if (member === accessorName) {
|
|
367
|
-
return undefined;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
if (!claimedNames.has(member)) {
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return member;
|
|
375
|
-
};
|
|
376
|
-
|
|
377
206
|
export {
|
|
378
207
|
propertyDoc,
|
|
379
208
|
resolveAccessor,
|
|
@@ -121,9 +121,9 @@ const renderRecordConstructor = (context: ModuleContext, spec: RecordConstructor
|
|
|
121
121
|
|
|
122
122
|
const statements = [
|
|
123
123
|
...superCall,
|
|
124
|
-
`const
|
|
124
|
+
`const __handle = alloc(${allocArgs(context, record, size).join(", ")});`,
|
|
125
125
|
...renderFieldWrites(context, slots),
|
|
126
|
-
"setHandle(this,
|
|
126
|
+
"setHandle(this, __handle);",
|
|
127
127
|
];
|
|
128
128
|
|
|
129
129
|
return renderBlock(`constructor(props: ${className}ConstructorProps = {})`, statements.join("\n"));
|
|
@@ -151,7 +151,7 @@ const renderFieldWrite = (context: ModuleContext, entry: WritableFieldSlot): str
|
|
|
151
151
|
const write = emitFieldWrite(context, {
|
|
152
152
|
descriptor,
|
|
153
153
|
slot: entry.slot,
|
|
154
|
-
targetExpr: "
|
|
154
|
+
targetExpr: "__handle",
|
|
155
155
|
valueExpr: `props.${name}`,
|
|
156
156
|
});
|
|
157
157
|
|