@gtkx/codegen 1.0.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/README.md +1 -1
- package/dist/analysis/descriptor-render.d.ts +12 -15
- package/dist/analysis/descriptor-render.d.ts.map +1 -1
- package/dist/analysis/descriptor-render.js +59 -38
- package/dist/analysis/descriptor-render.js.map +1 -1
- package/dist/analysis/descriptor.d.ts +25 -10
- package/dist/analysis/descriptor.d.ts.map +1 -1
- package/dist/analysis/descriptor.js +37 -9
- package/dist/analysis/descriptor.js.map +1 -1
- package/dist/analysis/inheritance.d.ts +4 -2
- package/dist/analysis/inheritance.d.ts.map +1 -1
- package/dist/analysis/inheritance.js +80 -38
- package/dist/analysis/inheritance.js.map +1 -1
- package/dist/analysis/interface-conflicts.d.ts +25 -0
- package/dist/analysis/interface-conflicts.d.ts.map +1 -0
- package/dist/analysis/interface-conflicts.js +139 -0
- package/dist/analysis/interface-conflicts.js.map +1 -0
- package/dist/analysis/param-capability.d.ts.map +1 -1
- package/dist/analysis/param-capability.js +3 -4
- package/dist/analysis/param-capability.js.map +1 -1
- package/dist/analysis/param-structure.js +2 -2
- package/dist/analysis/param-structure.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 +26 -26
- package/dist/analysis/ts-type.js.map +1 -1
- package/dist/analysis/type-key.d.ts +5 -0
- package/dist/analysis/type-key.d.ts.map +1 -0
- package/dist/analysis/type-key.js +9 -0
- package/dist/analysis/type-key.js.map +1 -0
- 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 +14 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +125 -24
- 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 +11 -10
- package/dist/docs/api-reference.js.map +1 -1
- package/dist/docs/element-page.d.ts.map +1 -1
- package/dist/docs/element-page.js +5 -3
- package/dist/docs/element-page.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 +93 -19
- package/dist/docs/pipeline.js.map +1 -1
- package/dist/docs/render.d.ts +2 -1
- package/dist/docs/render.d.ts.map +1 -1
- package/dist/docs/render.js +5 -4
- package/dist/docs/render.js.map +1 -1
- package/dist/docs/symbol-page.d.ts.map +1 -1
- package/dist/docs/symbol-page.js +10 -9
- package/dist/docs/symbol-page.js.map +1 -1
- package/dist/fingerprint.d.ts +20 -3
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +56 -37
- 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 +8 -2
- package/dist/gi.js.map +1 -1
- package/dist/gir/ancestry.d.ts +7 -1
- package/dist/gir/ancestry.d.ts.map +1 -1
- package/dist/gir/ancestry.js +9 -1
- package/dist/gir/ancestry.js.map +1 -1
- package/dist/gir/annotations.d.ts +1 -2
- package/dist/gir/annotations.d.ts.map +1 -1
- package/dist/gir/annotations.js +1 -1
- package/dist/gir/annotations.js.map +1 -1
- package/dist/gir/cursor-overrides.d.ts +8 -0
- package/dist/gir/cursor-overrides.d.ts.map +1 -0
- package/dist/gir/cursor-overrides.js +6 -0
- package/dist/gir/cursor-overrides.js.map +1 -0
- package/dist/gir/emittable.d.ts +7 -0
- package/dist/gir/emittable.d.ts.map +1 -0
- package/dist/gir/emittable.js +3 -0
- package/dist/gir/emittable.js.map +1 -0
- package/dist/gir/function.d.ts.map +1 -1
- package/dist/gir/function.js +28 -2
- package/dist/gir/function.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 +9 -2
- package/dist/gir/library.js.map +1 -1
- package/dist/gir/namespace.d.ts +5 -1
- package/dist/gir/namespace.d.ts.map +1 -1
- package/dist/gir/namespace.js +4 -2
- package/dist/gir/namespace.js.map +1 -1
- package/dist/gir/parameter.d.ts +13 -1
- package/dist/gir/parameter.d.ts.map +1 -1
- package/dist/gir/parameter.js +1 -0
- package/dist/gir/parameter.js.map +1 -1
- package/dist/gir/parse.d.ts.map +1 -1
- package/dist/gir/parse.js +6 -6
- 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/guards.d.ts +16 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +11 -0
- package/dist/guards.js.map +1 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -1
- package/dist/json.d.ts +3 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +11 -0
- package/dist/json.js.map +1 -0
- 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/modules.d.ts.map +1 -1
- package/dist/khronos/modules.js +22 -7
- package/dist/khronos/modules.js.map +1 -1
- package/dist/khronos/parse.d.ts.map +1 -1
- package/dist/khronos/parse.js +3 -4
- package/dist/khronos/parse.js.map +1 -1
- package/dist/khronos/pipeline.d.ts +1 -1
- package/dist/khronos/pipeline.d.ts.map +1 -1
- package/dist/khronos/pipeline.js.map +1 -1
- package/dist/khronos/plan.d.ts +1 -7
- package/dist/khronos/plan.d.ts.map +1 -1
- package/dist/khronos/plan.js +1 -1
- package/dist/khronos/plan.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 +7 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +21 -3
- package/dist/runner.js.map +1 -1
- package/dist/staging.d.ts +5 -0
- package/dist/staging.d.ts.map +1 -0
- package/dist/staging.js +57 -0
- package/dist/staging.js.map +1 -0
- 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 -32
- package/dist/store/compile-store.js.map +1 -1
- package/dist/store/gi/callables.d.ts +6 -3
- package/dist/store/gi/callables.d.ts.map +1 -1
- package/dist/store/gi/callables.js +40 -30
- package/dist/store/gi/callables.js.map +1 -1
- package/dist/store/gi/callback.d.ts.map +1 -1
- package/dist/store/gi/callback.js +9 -5
- package/dist/store/gi/callback.js.map +1 -1
- package/dist/store/gi/class.d.ts.map +1 -1
- package/dist/store/gi/class.js +104 -44
- package/dist/store/gi/class.js.map +1 -1
- package/dist/store/gi/companion.d.ts.map +1 -1
- package/dist/store/gi/companion.js +6 -6
- package/dist/store/gi/companion.js.map +1 -1
- package/dist/store/gi/constant.d.ts.map +1 -1
- package/dist/store/gi/constant.js +11 -3
- package/dist/store/gi/constant.js.map +1 -1
- package/dist/store/gi/constructor-props.js +1 -1
- package/dist/store/gi/constructor-props.js.map +1 -1
- package/dist/store/gi/enum.d.ts.map +1 -1
- package/dist/store/gi/enum.js +29 -12
- package/dist/store/gi/enum.js.map +1 -1
- package/dist/store/gi/function.d.ts +1 -3
- package/dist/store/gi/function.d.ts.map +1 -1
- package/dist/store/gi/function.js +24 -18
- package/dist/store/gi/function.js.map +1 -1
- package/dist/store/gi/gtype-binding.d.ts.map +1 -1
- package/dist/store/gi/gtype-binding.js +4 -1
- package/dist/store/gi/gtype-binding.js.map +1 -1
- package/dist/store/gi/interface.d.ts.map +1 -1
- package/dist/store/gi/interface.js +34 -19
- package/dist/store/gi/interface.js.map +1 -1
- package/dist/store/gi/method.d.ts +7 -6
- package/dist/store/gi/method.d.ts.map +1 -1
- package/dist/store/gi/method.js +13 -24
- package/dist/store/gi/method.js.map +1 -1
- package/dist/store/gi/param-marshal.d.ts +3 -2
- package/dist/store/gi/param-marshal.d.ts.map +1 -1
- package/dist/store/gi/param-marshal.js +50 -5
- package/dist/store/gi/param-marshal.js.map +1 -1
- package/dist/store/gi/pipeline.d.ts.map +1 -1
- package/dist/store/gi/pipeline.js +21 -10
- package/dist/store/gi/pipeline.js.map +1 -1
- package/dist/store/gi/properties.d.ts +2 -1
- package/dist/store/gi/properties.d.ts.map +1 -1
- package/dist/store/gi/properties.js +6 -3
- package/dist/store/gi/properties.js.map +1 -1
- package/dist/store/gi/property-accessor.d.ts +10 -8
- package/dist/store/gi/property-accessor.d.ts.map +1 -1
- package/dist/store/gi/property-accessor.js +49 -91
- package/dist/store/gi/property-accessor.js.map +1 -1
- package/dist/store/gi/record-constructor.d.ts +8 -1
- package/dist/store/gi/record-constructor.d.ts.map +1 -1
- package/dist/store/gi/record-constructor.js +34 -13
- 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 +20 -4
- package/dist/store/gi/record-field-accessor.js.map +1 -1
- package/dist/store/gi/record-layout.d.ts +6 -1
- package/dist/store/gi/record-layout.d.ts.map +1 -1
- package/dist/store/gi/record-layout.js +8 -1
- package/dist/store/gi/record-layout.js.map +1 -1
- package/dist/store/gi/record.d.ts.map +1 -1
- package/dist/store/gi/record.js +19 -8
- package/dist/store/gi/record.js.map +1 -1
- package/dist/store/gi/registration.js +2 -2
- package/dist/store/gi/registration.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 +2 -1
- package/dist/store/gi/signal.d.ts.map +1 -1
- package/dist/store/gi/signal.js +55 -28
- package/dist/store/gi/signal.js.map +1 -1
- package/dist/store/gi/value-marshalable.d.ts.map +1 -1
- package/dist/store/gi/value-marshalable.js +2 -1
- package/dist/store/gi/value-marshalable.js.map +1 -1
- package/dist/store/gi/vtable.d.ts +4 -1
- package/dist/store/gi/vtable.d.ts.map +1 -1
- package/dist/store/gi/vtable.js +60 -17
- package/dist/store/gi/vtable.js.map +1 -1
- package/dist/store/gi-store.d.ts +1 -0
- package/dist/store/gi-store.d.ts.map +1 -1
- package/dist/store/gi-store.js +15 -20
- package/dist/store/gi-store.js.map +1 -1
- package/dist/store/jsx/generated-elements.d.ts +2 -1
- package/dist/store/jsx/generated-elements.d.ts.map +1 -1
- package/dist/store/jsx/generated-elements.js +13 -7
- package/dist/store/jsx/generated-elements.js.map +1 -1
- package/dist/store/jsx/jsx.js +3 -3
- package/dist/store/jsx/jsx.js.map +1 -1
- package/dist/store/jsx/metadata.d.ts.map +1 -1
- package/dist/store/jsx/metadata.js +3 -1
- package/dist/store/jsx/metadata.js.map +1 -1
- package/dist/store/jsx-store.d.ts.map +1 -1
- package/dist/store/jsx-store.js +3 -4
- package/dist/store/jsx-store.js.map +1 -1
- package/dist/store/resolve-store.d.ts +14 -3
- package/dist/store/resolve-store.d.ts.map +1 -1
- package/dist/store/resolve-store.js +98 -15
- package/dist/store/resolve-store.js.map +1 -1
- package/dist/store/store-fs.d.ts +9 -7
- package/dist/store/store-fs.d.ts.map +1 -1
- package/dist/store/store-fs.js +54 -25
- package/dist/store/store-fs.js.map +1 -1
- package/dist/store/store-links.d.ts +3 -0
- package/dist/store/store-links.d.ts.map +1 -0
- package/dist/store/store-links.js +39 -0
- package/dist/store/store-links.js.map +1 -0
- package/dist/writer/comparison-context.d.ts +4 -0
- package/dist/writer/comparison-context.d.ts.map +1 -0
- package/dist/writer/comparison-context.js +13 -0
- package/dist/writer/comparison-context.js.map +1 -0
- package/dist/writer/context.d.ts +3 -3
- package/dist/writer/context.d.ts.map +1 -1
- package/dist/writer/context.js +11 -6
- package/dist/writer/context.js.map +1 -1
- package/dist/writer/module.d.ts +13 -5
- package/dist/writer/module.d.ts.map +1 -1
- package/dist/writer/module.js +68 -11
- package/dist/writer/module.js.map +1 -1
- package/dist/xml.d.ts +8 -1
- package/dist/xml.d.ts.map +1 -1
- package/dist/xml.js +70 -1
- package/dist/xml.js.map +1 -1
- package/overrides/gobject/object.ts.ejs +2 -0
- package/package.json +14 -3
- package/src/analysis/descriptor-render.ts +106 -52
- package/src/analysis/descriptor.ts +76 -15
- package/src/analysis/inheritance.ts +134 -44
- package/src/analysis/interface-conflicts.ts +235 -0
- package/src/analysis/param-capability.ts +3 -6
- package/src/analysis/param-structure.ts +2 -2
- package/src/analysis/ts-type.ts +43 -28
- package/src/analysis/type-key.ts +14 -0
- package/src/analysis/type-shape.ts +5 -2
- package/src/compile.ts +192 -27
- package/src/docs/api-reference.ts +13 -10
- package/src/docs/element-page.ts +5 -2
- package/src/docs/pipeline.ts +140 -24
- package/src/docs/render.ts +7 -3
- package/src/docs/symbol-page.ts +12 -11
- package/src/fingerprint.ts +95 -47
- package/src/gi.ts +10 -2
- package/src/gir/ancestry.ts +17 -1
- package/src/gir/annotations.ts +1 -1
- package/src/gir/cursor-overrides.ts +12 -0
- package/src/gir/emittable.ts +8 -0
- package/src/gir/function.ts +45 -9
- package/src/gir/gir-path.ts +1 -1
- package/src/gir/library.ts +10 -2
- package/src/gir/namespace.ts +8 -2
- package/src/gir/parameter.ts +15 -0
- package/src/gir/parse.ts +10 -7
- package/src/gir/primitives.ts +1 -1
- package/src/guards.ts +23 -0
- package/src/internal.ts +2 -0
- package/src/json.ts +11 -0
- package/src/khronos/args.ts +9 -6
- package/src/khronos/modules.ts +25 -9
- package/src/khronos/parse.ts +3 -4
- package/src/khronos/pipeline.ts +1 -1
- package/src/khronos/plan.ts +0 -1
- package/src/khronos/render.ts +8 -6
- package/src/runner.ts +26 -4
- package/src/staging.ts +67 -0
- package/src/store/compile-store.ts +7 -38
- package/src/store/gi/callables.ts +60 -33
- package/src/store/gi/callback.ts +9 -9
- package/src/store/gi/class.ts +140 -53
- package/src/store/gi/companion.ts +7 -6
- package/src/store/gi/constant.ts +13 -3
- package/src/store/gi/constructor-props.ts +1 -1
- package/src/store/gi/enum.ts +36 -26
- package/src/store/gi/function.ts +30 -24
- package/src/store/gi/gtype-binding.ts +7 -2
- package/src/store/gi/interface.ts +39 -20
- package/src/store/gi/method.ts +26 -32
- package/src/store/gi/param-marshal.ts +77 -6
- package/src/store/gi/pipeline.ts +25 -15
- package/src/store/gi/properties.ts +8 -4
- package/src/store/gi/property-accessor.ts +73 -161
- package/src/store/gi/record-constructor.ts +53 -21
- package/src/store/gi/record-field-accessor.ts +26 -4
- package/src/store/gi/record-layout.ts +11 -1
- package/src/store/gi/record.ts +20 -12
- package/src/store/gi/registration.ts +2 -2
- package/src/store/gi/return-wrap.ts +1 -1
- package/src/store/gi/signal.ts +66 -42
- package/src/store/gi/value-marshalable.ts +3 -1
- package/src/store/gi/vtable.ts +97 -20
- package/src/store/gi-store.ts +26 -31
- package/src/store/jsx/generated-elements.ts +17 -8
- package/src/store/jsx/jsx.ts +3 -3
- package/src/store/jsx/metadata.ts +4 -1
- package/src/store/jsx-store.ts +3 -4
- package/src/store/resolve-store.ts +133 -18
- package/src/store/store-fs.ts +82 -35
- package/src/store/store-links.ts +49 -0
- package/src/writer/comparison-context.ts +18 -0
- package/src/writer/context.ts +12 -6
- package/src/writer/module.ts +101 -14
- package/src/xml.ts +103 -1
package/src/store/gi/pipeline.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { sanitizeTypeIdentifier } from "@gtkx/utils";
|
|
1
2
|
import type { GirClass } from "../../gir/class.js";
|
|
2
3
|
import type { Library } from "../../gir/library.js";
|
|
3
4
|
import type { GirAlias, GirNamespace } from "../../gir/namespace.js";
|
|
4
5
|
import { renderTsType } from "../../analysis/ts-type.js";
|
|
6
|
+
import { getParentRef } from "../../gir/ancestry.js";
|
|
7
|
+
import { isEmittableEntity } from "../../gir/emittable.js";
|
|
5
8
|
import { PRIMITIVE_TS_TYPE, primitiveCategory } from "../../gir/primitives.js";
|
|
6
|
-
import { splitOptionalNamespace } from "../../gir/type-ref.js";
|
|
7
9
|
import { ModuleContext } from "../../writer/context.js";
|
|
8
10
|
import { generateCallback } from "./callback.js";
|
|
9
11
|
import { generateClass } from "./class.js";
|
|
10
12
|
import { generateConstant } from "./constant.js";
|
|
11
13
|
import { getDoc } from "./doc-spec.js";
|
|
12
14
|
import { generateEnum } from "./enum.js";
|
|
13
|
-
import {
|
|
15
|
+
import { generateNamespaceFunction } from "./function.js";
|
|
14
16
|
import { generateInterface } from "./interface.js";
|
|
15
17
|
import { generateRecord } from "./record.js";
|
|
16
18
|
|
|
@@ -28,6 +30,14 @@ const generateNamespaceModule = (namespace: GirNamespace, library: Library): str
|
|
|
28
30
|
generateNamespaceTypes(context, namespace);
|
|
29
31
|
generateNamespaceMembers(context, namespace);
|
|
30
32
|
|
|
33
|
+
if (!context.module.hasExports()) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`GIR file at ${namespace.girFile} has nothing to generate: its ${namespace.name} namespace produces a ` +
|
|
36
|
+
"module with no exports, so the file is empty, truncated, or declares only entries GIR marks as not " +
|
|
37
|
+
"introspectable",
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
31
41
|
return context.module.toSource();
|
|
32
42
|
};
|
|
33
43
|
|
|
@@ -58,8 +68,6 @@ const generateNamespaceMembers = (context: ModuleContext, namespace: GirNamespac
|
|
|
58
68
|
generateNamespaceFunction(context, fn);
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
generateNamespaceBootstrap(context, namespace);
|
|
62
|
-
|
|
63
71
|
for (const constant of namespace.constants) {
|
|
64
72
|
generateConstant(context, constant);
|
|
65
73
|
}
|
|
@@ -70,14 +78,20 @@ const generateNamespaceMembers = (context: ModuleContext, namespace: GirNamespac
|
|
|
70
78
|
};
|
|
71
79
|
|
|
72
80
|
const generateAlias = (context: ModuleContext, alias: GirAlias): void => {
|
|
81
|
+
if (!isEmittableEntity(alias)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
73
85
|
const category = alias.cType === undefined ? undefined : primitiveCategory(alias.cType);
|
|
74
86
|
const targetType = category === "gtype" ? PRIMITIVE_TS_TYPE.gtype : renderTsType(context, alias.target);
|
|
75
87
|
const doc = getDoc(alias);
|
|
88
|
+
const name = sanitizeTypeIdentifier(alias.name);
|
|
76
89
|
|
|
77
|
-
context.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
context.declare({
|
|
91
|
+
name,
|
|
92
|
+
code: `${doc}export type ${name} = ${targetType};`,
|
|
93
|
+
owner: alias.name,
|
|
94
|
+
});
|
|
81
95
|
};
|
|
82
96
|
|
|
83
97
|
const visitClass = (state: TopologicalState, klass: GirClass): void => {
|
|
@@ -124,17 +138,13 @@ const sameNamespaceParent = (
|
|
|
124
138
|
namespaceName: string,
|
|
125
139
|
byLocalName: Map<string, GirClass>,
|
|
126
140
|
): GirClass | undefined => {
|
|
127
|
-
|
|
128
|
-
return undefined;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const [parentNamespace, typeName] = splitOptionalNamespace(klass.parent);
|
|
141
|
+
const parent = getParentRef(klass);
|
|
132
142
|
|
|
133
|
-
if (
|
|
143
|
+
if (parent === undefined || (parent.namespaceName !== undefined && parent.namespaceName !== namespaceName)) {
|
|
134
144
|
return undefined;
|
|
135
145
|
}
|
|
136
146
|
|
|
137
|
-
return byLocalName.get(typeName);
|
|
147
|
+
return byLocalName.get(parent.typeName);
|
|
138
148
|
};
|
|
139
149
|
|
|
140
150
|
export { generateNamespaceModule };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GirClass } from "../../gir/class.js";
|
|
2
2
|
import type { ModuleContext } from "../../writer/context.js";
|
|
3
|
+
import type { Declaration } from "../../writer/module.js";
|
|
3
4
|
import { collectInterfaceProperties } from "../../analysis/inheritance.js";
|
|
4
5
|
import { renderBracedOrEmpty } from "../../writer/emit.js";
|
|
5
6
|
import { parentCompanionRef } from "./companion.js";
|
|
@@ -8,7 +9,7 @@ import { propertyDoc, type ResolvedAccessor, resolveOwnerAccessor } from "./prop
|
|
|
8
9
|
const PROPERTIES_SUFFIX = "Properties";
|
|
9
10
|
|
|
10
11
|
const propertyEntry = (accessor: ResolvedAccessor): string =>
|
|
11
|
-
`${propertyDoc(accessor.property)}${accessor.jsName}: ${accessor.
|
|
12
|
+
`${propertyDoc(accessor.property)}${accessor.jsName}: ${accessor.readType};`;
|
|
12
13
|
|
|
13
14
|
const interfaceEntries = (context: ModuleContext, klass: GirClass): string[] => {
|
|
14
15
|
const entries: string[] = [];
|
|
@@ -31,7 +32,7 @@ const renderPropertyDeclarations = (
|
|
|
31
32
|
klass: GirClass,
|
|
32
33
|
className: string,
|
|
33
34
|
accessors: ResolvedAccessor[],
|
|
34
|
-
):
|
|
35
|
+
): Declaration[] => {
|
|
35
36
|
const parentRef = parentCompanionRef(context, klass, PROPERTIES_SUFFIX);
|
|
36
37
|
const extendsClause = parentRef === undefined ? "" : ` extends ${parentRef}`;
|
|
37
38
|
|
|
@@ -43,8 +44,11 @@ const renderPropertyDeclarations = (
|
|
|
43
44
|
const map = `${className}${PROPERTIES_SUFFIX}`;
|
|
44
45
|
|
|
45
46
|
return [
|
|
46
|
-
renderBracedOrEmpty(`export interface ${map}${extendsClause}`, entries.join("\n")),
|
|
47
|
-
|
|
47
|
+
{ name: map, code: renderBracedOrEmpty(`export interface ${map}${extendsClause}`, entries.join("\n")) },
|
|
48
|
+
{
|
|
49
|
+
name: className,
|
|
50
|
+
code: renderBracedOrEmpty(`export interface ${className}`, `__properties__: ${map};`),
|
|
51
|
+
},
|
|
48
52
|
];
|
|
49
53
|
};
|
|
50
54
|
|
|
@@ -1,44 +1,38 @@
|
|
|
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
8
|
import { renderBlock } from "../../writer/emit.js";
|
|
10
9
|
import { isEmittableCallable } from "./callables.js";
|
|
11
10
|
import { getDoc } from "./doc-spec.js";
|
|
12
|
-
import { methodExportName
|
|
11
|
+
import { methodExportName } from "./method.js";
|
|
12
|
+
|
|
13
|
+
type InheritedAccessorTypes = {
|
|
14
|
+
readType: string | undefined;
|
|
15
|
+
writeType: string | undefined;
|
|
16
|
+
};
|
|
13
17
|
|
|
14
18
|
type ResolvedAccessor = {
|
|
15
19
|
property: GirProperty;
|
|
16
20
|
jsName: string;
|
|
17
|
-
|
|
21
|
+
readType: string;
|
|
22
|
+
writeType: string;
|
|
18
23
|
hasGetter: boolean;
|
|
19
24
|
isWritable: boolean;
|
|
20
|
-
getterMember: string | undefined;
|
|
21
|
-
getterMethod: GirFunction | undefined;
|
|
22
|
-
setterMember: string | undefined;
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
type PropertyAccessorArgs = {
|
|
26
28
|
context: ModuleContext;
|
|
27
29
|
property: GirProperty;
|
|
28
30
|
claimedNames: Set<string>;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
inheritedTypes?: InheritedAccessorTypes | undefined;
|
|
32
|
+
inheritedNames?: Set<string> | undefined;
|
|
31
33
|
};
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
type GetterBodyOptions = {
|
|
36
|
-
context: ModuleContext;
|
|
37
|
-
property: GirProperty;
|
|
38
|
-
getterMember: string | undefined;
|
|
39
|
-
getterMethod: GirFunction | undefined;
|
|
40
|
-
tsType: string;
|
|
41
|
-
};
|
|
35
|
+
const NON_NULLABLE_KINDS: Set<string> = new Set(["primitive", "enum"]);
|
|
42
36
|
|
|
43
37
|
const isNullablePropertyType = (context: ModuleContext, type: TypeId | undefined): boolean => {
|
|
44
38
|
if (type === undefined) {
|
|
@@ -51,105 +45,49 @@ const isNullablePropertyType = (context: ModuleContext, type: TypeId | undefined
|
|
|
51
45
|
return true;
|
|
52
46
|
}
|
|
53
47
|
|
|
54
|
-
if (resolved.kind === "primitive") {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (resolved.kind === "enum") {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
48
|
if (resolved.kind === "alias") {
|
|
63
49
|
return isNullablePropertyType(context, resolved.value.target);
|
|
64
50
|
}
|
|
65
51
|
|
|
66
|
-
return
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const resolveDelegate = (
|
|
70
|
-
args: PropertyAccessorArgs,
|
|
71
|
-
attribute: string | undefined,
|
|
72
|
-
member: string | undefined,
|
|
73
|
-
isDelegatable: (method: GirFunction) => boolean,
|
|
74
|
-
): AccessorDelegate => {
|
|
75
|
-
const method = member !== undefined && attribute !== undefined ? args.methodByName.get(attribute) : undefined;
|
|
76
|
-
const canDelegate = method === undefined || isDelegatable(method);
|
|
77
|
-
|
|
78
|
-
return canDelegate ? { member, method } : { member: undefined, method: undefined };
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const resolveGetterDelegate = (args: PropertyAccessorArgs, jsName: string): AccessorDelegate => {
|
|
82
|
-
const { context, property, claimedNames } = args;
|
|
83
|
-
const member = delegateMember(property.getter, jsName, claimedNames);
|
|
84
|
-
|
|
85
|
-
return resolveDelegate(
|
|
86
|
-
args,
|
|
87
|
-
property.getter,
|
|
88
|
-
member,
|
|
89
|
-
(method) =>
|
|
90
|
-
inputParameters(context.library, method).length === 0 &&
|
|
91
|
-
!renderMethodReturnType(context, method).startsWith("["),
|
|
92
|
-
);
|
|
52
|
+
return !NON_NULLABLE_KINDS.has(resolved.kind);
|
|
93
53
|
};
|
|
94
54
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
args,
|
|
101
|
-
property.setter,
|
|
102
|
-
member,
|
|
103
|
-
(method) => inputParameters(context.library, method).length === 1,
|
|
55
|
+
const declaredPropertyType = (context: ModuleContext, property: GirProperty): string =>
|
|
56
|
+
renderTsType(
|
|
57
|
+
context,
|
|
58
|
+
property.type,
|
|
59
|
+
property.defaultValue === "NULL" || isNullablePropertyType(context, property.type),
|
|
104
60
|
);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const resolveOwnType = (
|
|
108
|
-
context: ModuleContext,
|
|
109
|
-
property: GirProperty,
|
|
110
|
-
getterMethod: GirFunction | undefined,
|
|
111
|
-
setterMethod: GirFunction | undefined,
|
|
112
|
-
): string => {
|
|
113
|
-
const setterParam = setterMethod?.parameters[0];
|
|
114
|
-
|
|
115
|
-
if (setterParam !== undefined) {
|
|
116
|
-
return renderTsType(context, setterParam.type, setterParam.nullable || setterParam.optional);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (getterMethod !== undefined) {
|
|
120
|
-
return renderMethodReturnType(context, getterMethod);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return renderTsType(context, property.type, isNullablePropertyType(context, property.type));
|
|
124
|
-
};
|
|
125
61
|
|
|
126
|
-
const isSkippedAccessor = (
|
|
127
|
-
!property.introspectable ||
|
|
62
|
+
const isSkippedAccessor = (args: PropertyAccessorArgs, jsName: string): boolean =>
|
|
63
|
+
!args.property.introspectable ||
|
|
64
|
+
args.claimedNames.has(jsName) ||
|
|
65
|
+
args.inheritedNames?.has(jsName) === true ||
|
|
66
|
+
jsName === "constructor";
|
|
128
67
|
|
|
129
|
-
const
|
|
130
|
-
|
|
68
|
+
const isAccessorEmittable = (args: PropertyAccessorArgs, jsName: string, isWritable: boolean): boolean =>
|
|
69
|
+
!isSkippedAccessor(args, jsName) && (args.property.readable || isWritable);
|
|
131
70
|
|
|
132
71
|
const resolveAccessor = (args: PropertyAccessorArgs): ResolvedAccessor | undefined => {
|
|
133
|
-
const {
|
|
72
|
+
const { property } = args;
|
|
134
73
|
const jsName = toCamelIdentifier(property.name);
|
|
135
|
-
|
|
136
|
-
if (isSkippedAccessor(property, jsName, claimedNames)) {
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
74
|
const isWritable = isConstructableProperty(property) && !property.constructOnly;
|
|
141
|
-
const { member: getterMember, method: getterMethod } = resolveGetterDelegate(args, jsName);
|
|
142
|
-
const { member: setterMember, method: setterMethod } = resolveSetterDelegate(args, jsName, isWritable);
|
|
143
|
-
const hasGetter = property.readable || getterMember !== undefined;
|
|
144
75
|
|
|
145
|
-
if (!
|
|
76
|
+
if (!isAccessorEmittable(args, jsName, isWritable)) {
|
|
146
77
|
return undefined;
|
|
147
78
|
}
|
|
148
79
|
|
|
149
|
-
const
|
|
150
|
-
const
|
|
80
|
+
const declared = declaredPropertyType(args.context, property);
|
|
81
|
+
const hasGetter = property.readable;
|
|
151
82
|
|
|
152
|
-
return {
|
|
83
|
+
return {
|
|
84
|
+
property,
|
|
85
|
+
jsName,
|
|
86
|
+
readType: args.inheritedTypes?.readType ?? declared,
|
|
87
|
+
writeType: args.inheritedTypes?.writeType ?? declared,
|
|
88
|
+
hasGetter,
|
|
89
|
+
isWritable,
|
|
90
|
+
};
|
|
153
91
|
};
|
|
154
92
|
|
|
155
93
|
const resolveOwnerAccessor = (
|
|
@@ -157,7 +95,6 @@ const resolveOwnerAccessor = (
|
|
|
157
95
|
property: GirProperty,
|
|
158
96
|
methods: GirFunction[],
|
|
159
97
|
): ResolvedAccessor | undefined => {
|
|
160
|
-
const methodByName: Map<string, GirFunction> = new Map();
|
|
161
98
|
const claimedNames: Set<string> = new Set();
|
|
162
99
|
|
|
163
100
|
for (const method of methods) {
|
|
@@ -165,18 +102,28 @@ const resolveOwnerAccessor = (
|
|
|
165
102
|
continue;
|
|
166
103
|
}
|
|
167
104
|
|
|
168
|
-
methodByName.set(method.name, method);
|
|
169
105
|
claimedNames.add(methodExportName(method));
|
|
170
106
|
}
|
|
171
107
|
|
|
172
|
-
return resolveAccessor({ context, property, claimedNames
|
|
108
|
+
return resolveAccessor({ context, property, claimedNames });
|
|
173
109
|
};
|
|
174
110
|
|
|
175
|
-
const
|
|
111
|
+
const resolveAccessorTypes = (
|
|
176
112
|
context: ModuleContext,
|
|
177
113
|
property: GirProperty,
|
|
178
114
|
methods: GirFunction[],
|
|
179
|
-
):
|
|
115
|
+
): InheritedAccessorTypes | undefined => {
|
|
116
|
+
const accessor = resolveOwnerAccessor(context, property, methods);
|
|
117
|
+
|
|
118
|
+
if (accessor === undefined) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
readType: accessor.hasGetter ? accessor.readType : undefined,
|
|
124
|
+
writeType: accessor.isWritable ? accessor.writeType : undefined,
|
|
125
|
+
};
|
|
126
|
+
};
|
|
180
127
|
|
|
181
128
|
const withAccessor = (
|
|
182
129
|
args: PropertyAccessorArgs,
|
|
@@ -196,19 +143,15 @@ const renderResolvedPropertyAccessor = (
|
|
|
196
143
|
property: GirProperty,
|
|
197
144
|
accessor: ResolvedAccessor,
|
|
198
145
|
): string => {
|
|
199
|
-
const { jsName,
|
|
146
|
+
const { jsName, readType, writeType, hasGetter, isWritable } = accessor;
|
|
200
147
|
const blocks: string[] = [];
|
|
201
148
|
|
|
202
149
|
if (hasGetter) {
|
|
203
|
-
|
|
204
|
-
blocks.push(renderBlock(`get ${jsName}(): ${tsType}`, getterBody));
|
|
150
|
+
blocks.push(renderBlock(`get ${jsName}(): ${readType}`, renderGenericGetBody(context, property, readType)));
|
|
205
151
|
}
|
|
206
152
|
|
|
207
153
|
if (isWritable) {
|
|
208
|
-
|
|
209
|
-
setterMember === undefined ? renderGenericSetBody(context, property) : `this.${setterMember}(value);`;
|
|
210
|
-
|
|
211
|
-
blocks.push(renderBlock(`set ${jsName}(value: ${tsType})`, setterBody));
|
|
154
|
+
blocks.push(renderBlock(`set ${jsName}(value: ${writeType})`, renderGenericSetBody(context, property)));
|
|
212
155
|
}
|
|
213
156
|
|
|
214
157
|
return `${propertyDoc(property)}${blocks.join("\n\n")}`;
|
|
@@ -220,20 +163,26 @@ const propertyDoc = (property: GirProperty): string =>
|
|
|
220
163
|
const renderPropertyAccessor = (args: PropertyAccessorArgs): string | undefined =>
|
|
221
164
|
withAccessor(args, (accessor) => renderResolvedPropertyAccessor(args.context, args.property, accessor));
|
|
222
165
|
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
const doc = propertyDoc(args.property);
|
|
166
|
+
const renderAccessorPairSignature = (accessor: ResolvedAccessor): string => {
|
|
167
|
+
const { jsName, readType, writeType, hasGetter, isWritable } = accessor;
|
|
226
168
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
169
|
+
if (!hasGetter) {
|
|
170
|
+
return `set ${jsName}(value: ${writeType});`;
|
|
171
|
+
}
|
|
230
172
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
173
|
+
if (!isWritable) {
|
|
174
|
+
return `get ${jsName}(): ${readType};`;
|
|
175
|
+
}
|
|
234
176
|
|
|
235
|
-
|
|
236
|
-
|
|
177
|
+
if (readType === writeType) {
|
|
178
|
+
return `${jsName}: ${readType};`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return `get ${jsName}(): ${readType};\nset ${jsName}(value: ${writeType});`;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const renderPropertyAccessorSignature = (args: PropertyAccessorArgs): string | undefined =>
|
|
185
|
+
withAccessor(args, (accessor) => `${propertyDoc(args.property)}${renderAccessorPairSignature(accessor)}`);
|
|
237
186
|
|
|
238
187
|
const renderPropertyDescriptor = (context: ModuleContext, property: GirProperty): string =>
|
|
239
188
|
renderDescriptor(context, property.type, property.transferOwnership);
|
|
@@ -254,52 +203,15 @@ const renderGenericSetBody = (context: ModuleContext, property: GirProperty): st
|
|
|
254
203
|
return `setObjectProperty(this, ${sourceStringLiteral(property.name)}, ${descriptor}, value);`;
|
|
255
204
|
};
|
|
256
205
|
|
|
257
|
-
const renderGetterBody = (options: GetterBodyOptions): string => {
|
|
258
|
-
const { context, property, getterMember, getterMethod, tsType } = options;
|
|
259
|
-
|
|
260
|
-
if (getterMember === undefined) {
|
|
261
|
-
return renderGenericGetBody(context, property, tsType);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (getterMethod === undefined) {
|
|
265
|
-
return `return this.${getterMember}() as ${tsType};`;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const getterType = renderMethodReturnType(context, getterMethod);
|
|
269
|
-
|
|
270
|
-
return getterType === tsType ? `return this.${getterMember}();` : `return this.${getterMember}() as ${tsType};`;
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
const delegateMember = (
|
|
274
|
-
attribute: string | undefined,
|
|
275
|
-
accessorName: string,
|
|
276
|
-
claimedNames: Set<string>,
|
|
277
|
-
): string | undefined => {
|
|
278
|
-
if (attribute === undefined) {
|
|
279
|
-
return undefined;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const member = camelCase(attribute);
|
|
283
|
-
|
|
284
|
-
if (member === accessorName) {
|
|
285
|
-
return undefined;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (!claimedNames.has(member)) {
|
|
289
|
-
return undefined;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
return member;
|
|
293
|
-
};
|
|
294
|
-
|
|
295
206
|
export {
|
|
296
207
|
propertyDoc,
|
|
297
208
|
resolveAccessor,
|
|
298
209
|
resolveOwnerAccessor,
|
|
299
|
-
|
|
210
|
+
resolveAccessorTypes,
|
|
300
211
|
renderResolvedPropertyAccessor,
|
|
301
212
|
renderPropertyAccessor,
|
|
302
213
|
renderPropertyAccessorSignature,
|
|
214
|
+
type InheritedAccessorTypes,
|
|
303
215
|
type ResolvedAccessor,
|
|
304
216
|
type PropertyAccessorArgs,
|
|
305
217
|
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { sourceStringLiteral, toCamelIdentifier } from "@gtkx/utils";
|
|
2
2
|
import type { GirField } from "../../gir/field.js";
|
|
3
|
+
import type { GirFunction } from "../../gir/function.js";
|
|
3
4
|
import type { GirRecord } from "../../gir/record.js";
|
|
4
5
|
import type { TypeId } from "../../gir/type-id.js";
|
|
5
6
|
import type { ModuleContext } from "../../writer/context.js";
|
|
6
7
|
import { renderDescriptor } from "../../analysis/descriptor-render.js";
|
|
8
|
+
import { inputParameters, parameterIdentifier } from "../../analysis/param-structure.js";
|
|
7
9
|
import { renderTsType } from "../../analysis/ts-type.js";
|
|
8
10
|
import { renderBlock, renderBracedOrEmpty } from "../../writer/emit.js";
|
|
11
|
+
import { type Callables, staticMembers } from "./callables.js";
|
|
9
12
|
import { getDoc } from "./doc-spec.js";
|
|
10
13
|
import { renderSourceGtype } from "./gtype-binding.js";
|
|
11
14
|
import { emitFieldWrite, isEmittableField, isInlineField } from "./record-field-accessor.js";
|
|
@@ -14,22 +17,22 @@ import { isConstructibleRecord } from "./value-marshalable.js";
|
|
|
14
17
|
|
|
15
18
|
type WritableFieldSlot = RecordFieldSlot & { field: GirField & { type: TypeId } };
|
|
16
19
|
|
|
20
|
+
type RecordConstructorSpec = {
|
|
21
|
+
record: GirRecord;
|
|
22
|
+
className: string;
|
|
23
|
+
callables: Callables;
|
|
24
|
+
isErrorSubclass: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
17
27
|
const isWritableFieldSlot = (context: ModuleContext, entry: RecordFieldSlot): entry is WritableFieldSlot =>
|
|
18
28
|
entry.field.writable && isEmittableField(context, entry.field);
|
|
19
29
|
|
|
20
|
-
const isOpaque = (record: GirRecord): boolean => record.opaque || record.disguised;
|
|
21
|
-
|
|
22
30
|
const renderRecordConstructorPropsInterface = (
|
|
23
31
|
context: ModuleContext,
|
|
24
32
|
record: GirRecord,
|
|
25
33
|
className: string,
|
|
26
34
|
): string => {
|
|
27
35
|
const head = `export interface ${className}ConstructorProps`;
|
|
28
|
-
|
|
29
|
-
if (isOpaque(record) || !isConstructibleRecord(context, context.namespace.name, record)) {
|
|
30
|
-
return renderBracedOrEmpty(head, "");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
36
|
const { slots } = computeRecordFieldSlots(context, record.fields, record.isUnion);
|
|
34
37
|
|
|
35
38
|
const lines = slots
|
|
@@ -43,8 +46,41 @@ const renderRecordConstructorPropsInterface = (
|
|
|
43
46
|
return renderBracedOrEmpty(head, lines.join("\n"));
|
|
44
47
|
};
|
|
45
48
|
|
|
46
|
-
const
|
|
47
|
-
const
|
|
49
|
+
const isSelfReturning = (context: ModuleContext, record: GirRecord, callable: GirFunction): boolean => {
|
|
50
|
+
const ref = callable.returnValue.type;
|
|
51
|
+
const name = ref === undefined ? undefined : context.library.nameFor(ref);
|
|
52
|
+
|
|
53
|
+
return name?.namespaceName === context.namespace.name && name.typeName === record.name;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const renderStaticCall = (context: ModuleContext, callable: GirFunction, name: string): string => {
|
|
57
|
+
const args = inputParameters(context.library, callable).map(({ parameter, index }) =>
|
|
58
|
+
parameterIdentifier(parameter, index));
|
|
59
|
+
|
|
60
|
+
return `${name}(${args.join(", ")})`;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const constructionHint = (context: ModuleContext, spec: RecordConstructorSpec): string | undefined => {
|
|
64
|
+
const candidates = staticMembers(context, spec.callables).filter(({ callable }) =>
|
|
65
|
+
isSelfReturning(context, spec.record, callable));
|
|
66
|
+
|
|
67
|
+
const candidate = candidates.find(({ name }) => name === "new") ?? candidates[0];
|
|
68
|
+
|
|
69
|
+
return candidate === undefined ? undefined : renderStaticCall(context, candidate.callable, candidate.name);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const unconstructibleMessage = (context: ModuleContext, spec: RecordConstructorSpec): string => {
|
|
73
|
+
const qualified = `${context.namespace.name}.${spec.className}`;
|
|
74
|
+
const hint = constructionHint(context, spec);
|
|
75
|
+
|
|
76
|
+
return hint === undefined
|
|
77
|
+
? `Cannot construct ${qualified} with new: its instances come from the functions that return them.`
|
|
78
|
+
: `Cannot construct ${qualified} with new: use ${qualified}.${hint} instead.`;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const renderUnconstructibleGuard = (context: ModuleContext, spec: RecordConstructorSpec): string => {
|
|
82
|
+
const superCall = spec.isErrorSubclass ? ["super();"] : [];
|
|
83
|
+
const message = sourceStringLiteral(unconstructibleMessage(context, spec));
|
|
48
84
|
|
|
49
85
|
return renderBlock("constructor()", [...superCall, `throw new globalThis.Error(${message});`].join("\n"));
|
|
50
86
|
};
|
|
@@ -66,18 +102,14 @@ const renderFieldWrites = (context: ModuleContext, slots: RecordFieldSlot[]): st
|
|
|
66
102
|
return statements;
|
|
67
103
|
};
|
|
68
104
|
|
|
69
|
-
const renderRecordConstructor = (
|
|
70
|
-
|
|
71
|
-
record: GirRecord,
|
|
72
|
-
className: string,
|
|
73
|
-
isErrorSubclass = false,
|
|
74
|
-
): string => {
|
|
75
|
-
const superCall = isErrorSubclass ? ["super();"] : [];
|
|
105
|
+
const renderRecordConstructor = (context: ModuleContext, spec: RecordConstructorSpec): string => {
|
|
106
|
+
const { record, className, isErrorSubclass } = spec;
|
|
76
107
|
|
|
77
|
-
if (
|
|
78
|
-
return
|
|
108
|
+
if (!isConstructibleRecord(context, context.namespace.name, record)) {
|
|
109
|
+
return renderUnconstructibleGuard(context, spec);
|
|
79
110
|
}
|
|
80
111
|
|
|
112
|
+
const superCall = isErrorSubclass ? ["super();"] : [];
|
|
81
113
|
const { slots, size } = computeRecordFieldSlots(context, record.fields, record.isUnion);
|
|
82
114
|
|
|
83
115
|
if (size === 0) {
|
|
@@ -89,9 +121,9 @@ const renderRecordConstructor = (
|
|
|
89
121
|
|
|
90
122
|
const statements = [
|
|
91
123
|
...superCall,
|
|
92
|
-
`const
|
|
124
|
+
`const __handle = alloc(${allocArgs(context, record, size).join(", ")});`,
|
|
93
125
|
...renderFieldWrites(context, slots),
|
|
94
|
-
"setHandle(this,
|
|
126
|
+
"setHandle(this, __handle);",
|
|
95
127
|
];
|
|
96
128
|
|
|
97
129
|
return renderBlock(`constructor(props: ${className}ConstructorProps = {})`, statements.join("\n"));
|
|
@@ -119,7 +151,7 @@ const renderFieldWrite = (context: ModuleContext, entry: WritableFieldSlot): str
|
|
|
119
151
|
const write = emitFieldWrite(context, {
|
|
120
152
|
descriptor,
|
|
121
153
|
slot: entry.slot,
|
|
122
|
-
targetExpr: "
|
|
154
|
+
targetExpr: "__handle",
|
|
123
155
|
valueExpr: `props.${name}`,
|
|
124
156
|
});
|
|
125
157
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { toCamelIdentifier } from "@gtkx/utils";
|
|
2
2
|
import type { GirAnnotations } from "../../gir/annotations.js";
|
|
3
3
|
import type { GirField } from "../../gir/field.js";
|
|
4
|
+
import type { GirRecord } from "../../gir/record.js";
|
|
4
5
|
import type { FieldSlot } from "../../gir/size.js";
|
|
5
6
|
import type { TypeId } from "../../gir/type-id.js";
|
|
6
7
|
import type { GirType } from "../../gir/type.js";
|
|
@@ -365,6 +366,21 @@ const visitInlineStructFields = (
|
|
|
365
366
|
}
|
|
366
367
|
};
|
|
367
368
|
|
|
369
|
+
const inlineLeafCount = (context: ModuleContext, fields: GirField[]): number => {
|
|
370
|
+
let count = 0;
|
|
371
|
+
|
|
372
|
+
visitInlineStructFields(context, fields, 0, {
|
|
373
|
+
leaf: () => {
|
|
374
|
+
count += 1;
|
|
375
|
+
},
|
|
376
|
+
nested: (_jsName, nested) => {
|
|
377
|
+
count += inlineLeafCount(context, nested);
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
return count;
|
|
382
|
+
};
|
|
383
|
+
|
|
368
384
|
const elementAccessExpr = (descriptor: string, offset: number): string =>
|
|
369
385
|
`read(__array, ${descriptor}, __base + ${String(offset)})`;
|
|
370
386
|
|
|
@@ -451,7 +467,7 @@ const structArrayGetterBlock = (options: StructArrayAccessorOptions): string =>
|
|
|
451
467
|
};
|
|
452
468
|
|
|
453
469
|
const structArraySetterStatements = (context: ModuleContext, options: StructArrayAccessorOptions): string => {
|
|
454
|
-
const { elementDescriptor, offset, elementSize, elementFields } = options;
|
|
470
|
+
const { elementDescriptor, offset, elementSize, elementFields, lengthExpr } = options;
|
|
455
471
|
const writes: string[] = [];
|
|
456
472
|
|
|
457
473
|
appendElementWriteStatements(context, {
|
|
@@ -467,7 +483,7 @@ const structArraySetterStatements = (context: ModuleContext, options: StructArra
|
|
|
467
483
|
`const __descriptor = ${elementDescriptor};`,
|
|
468
484
|
`const __array = read(getHandle(this), __descriptor, ${String(offset)}) as ReturnType<typeof getHandle>;`,
|
|
469
485
|
"for (const [__index, __element] of __value.entries()) {",
|
|
470
|
-
indent(loop
|
|
486
|
+
indent(`if (__index >= ${lengthExpr}) {\n break;\n}\n\n${loop}`, 1),
|
|
471
487
|
"}",
|
|
472
488
|
`write(getHandle(this), __descriptor, ${String(offset)}, __array);`,
|
|
473
489
|
].join("\n");
|
|
@@ -479,6 +495,12 @@ const structArraySetterBlock = (options: StructArrayAccessorOptions): string =>
|
|
|
479
495
|
structArraySetterStatements(options.context, options),
|
|
480
496
|
);
|
|
481
497
|
|
|
498
|
+
const isPlainDataRecord = (record: GirRecord): boolean =>
|
|
499
|
+
record.glibGetType === undefined &&
|
|
500
|
+
record.constructors.length === 0 &&
|
|
501
|
+
record.functions.length === 0 &&
|
|
502
|
+
record.methods.length === 0;
|
|
503
|
+
|
|
482
504
|
const resolveStructArrayElements = (context: ModuleContext, fieldType: TypeId): StructArrayElements | undefined => {
|
|
483
505
|
const arrayType = context.library.typeFor(fieldType);
|
|
484
506
|
|
|
@@ -488,7 +510,7 @@ const resolveStructArrayElements = (context: ModuleContext, fieldType: TypeId):
|
|
|
488
510
|
|
|
489
511
|
const elementType = context.library.typeFor(arrayType.element);
|
|
490
512
|
|
|
491
|
-
if (elementType?.kind === "record" && elementType.value
|
|
513
|
+
if (elementType?.kind === "record" && !isPlainDataRecord(elementType.value)) {
|
|
492
514
|
return undefined;
|
|
493
515
|
}
|
|
494
516
|
|
|
@@ -536,7 +558,7 @@ const resolveStructArray = (context: ModuleContext, target: StructArrayTarget):
|
|
|
536
558
|
|
|
537
559
|
const shape = resolveStructArrayShape(context, elements, siblingFields);
|
|
538
560
|
|
|
539
|
-
if (shape === undefined) {
|
|
561
|
+
if (shape === undefined || inlineLeafCount(context, elements.elementFields) === 0) {
|
|
540
562
|
return undefined;
|
|
541
563
|
}
|
|
542
564
|
|