@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
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") {
|
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import { sourceStringLiteral } from "@gtkx/utils";
|
|
2
2
|
import type { ModuleContext } from "../../writer/context.js";
|
|
3
3
|
import { PRIMITIVE_TS_TYPE } from "../../gir/primitives.js";
|
|
4
|
+
import { renderJsDoc } from "../../writer/doc.js";
|
|
5
|
+
import { renderBlock } from "../../writer/emit.js";
|
|
4
6
|
|
|
5
7
|
type TypeSource = {
|
|
6
8
|
glibGetType: string | undefined;
|
|
7
9
|
glibTypeName: string | undefined;
|
|
8
10
|
};
|
|
9
11
|
|
|
12
|
+
const GTYPE_NOTE = [
|
|
13
|
+
"The GType this class is registered under, read off the class it is accessed on rather than",
|
|
14
|
+
"inherited, so a subclass `registerClass` created reports its own type and one that never went",
|
|
15
|
+
"through `registerClass` reports the invalid type.",
|
|
16
|
+
].join("\n");
|
|
17
|
+
|
|
10
18
|
const gtypeTsType = (context: ModuleContext): string =>
|
|
11
19
|
context.namespace.name === "GObject" ? "Type" : PRIMITIVE_TS_TYPE.gtype;
|
|
12
20
|
|
|
13
21
|
const gtypeMemberDeclaration = (context: ModuleContext): string => `declare __type__: ${gtypeTsType(context)};`;
|
|
14
22
|
|
|
23
|
+
const gtypeStaticMember = (context: ModuleContext): string => {
|
|
24
|
+
context.addRuntimeImport("getClassType");
|
|
25
|
+
const block = renderBlock(`static get __gtype__(): ${gtypeTsType(context)}`, "return getClassType(this);");
|
|
26
|
+
|
|
27
|
+
return `${renderJsDoc(undefined, GTYPE_NOTE)}${block}`;
|
|
28
|
+
};
|
|
29
|
+
|
|
15
30
|
const renderInternGtype = (context: ModuleContext, typeName: string | undefined): string | undefined => {
|
|
16
31
|
if (typeName === undefined) {
|
|
17
32
|
return undefined;
|
|
@@ -48,4 +63,4 @@ const renderSourceGtype = (context: ModuleContext, source: TypeSource): string |
|
|
|
48
63
|
? undefined
|
|
49
64
|
: renderGtypeExpression(context, source.glibGetType, source.glibTypeName);
|
|
50
65
|
|
|
51
|
-
export { gtypeTsType, gtypeMemberDeclaration, renderSourceGtype };
|
|
66
|
+
export { gtypeTsType, gtypeMemberDeclaration, gtypeStaticMember, renderSourceGtype };
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
renderStaticHead,
|
|
22
22
|
} from "./callables.js";
|
|
23
23
|
import { annotationSpec, getDoc } from "./doc-spec.js";
|
|
24
|
-
import { renderSourceGtype } from "./gtype-binding.js";
|
|
24
|
+
import { gtypeStaticMember, renderSourceGtype } from "./gtype-binding.js";
|
|
25
25
|
import { methodExportName } from "./method.js";
|
|
26
26
|
import {
|
|
27
27
|
type PropertyAccessorArgs,
|
|
@@ -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);
|
|
@@ -378,7 +378,7 @@ const renderInterfaceClass = (context: ModuleContext, options: InterfaceClassOpt
|
|
|
378
378
|
const members: string[] = [];
|
|
379
379
|
|
|
380
380
|
if (gtypeExpr !== undefined) {
|
|
381
|
-
members.push(renderInterfaceHasInstance(context, className, gtypeExpr));
|
|
381
|
+
members.push(renderInterfaceHasInstance(context, className, gtypeExpr), gtypeStaticMember(context));
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
members.push(...renderStaticHead(context, callables, className), renderInterfaceBrand(context, implRef));
|
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,
|
|
@@ -11,7 +11,7 @@ import { renderBlock, renderBracedOrEmpty } from "../../writer/emit.js";
|
|
|
11
11
|
import { type Callables, staticMembers } from "./callables.js";
|
|
12
12
|
import { getDoc } from "./doc-spec.js";
|
|
13
13
|
import { renderSourceGtype } from "./gtype-binding.js";
|
|
14
|
-
import { emitFieldWrite, isEmittableField, isInlineField } from "./record-field-accessor.js";
|
|
14
|
+
import { emitFieldWrite, isEmittableField, isInlineField, isStorableFieldType } from "./record-field-accessor.js";
|
|
15
15
|
import { computeRecordFieldSlots, type RecordFieldSlot } from "./record-layout.js";
|
|
16
16
|
import { isConstructibleRecord } from "./value-marshalable.js";
|
|
17
17
|
|
|
@@ -25,7 +25,9 @@ type RecordConstructorSpec = {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const isWritableFieldSlot = (context: ModuleContext, entry: RecordFieldSlot): entry is WritableFieldSlot =>
|
|
28
|
-
entry.field.writable &&
|
|
28
|
+
entry.field.writable &&
|
|
29
|
+
isEmittableField(context, entry.field) &&
|
|
30
|
+
isStorableFieldType(context, entry.field.type);
|
|
29
31
|
|
|
30
32
|
const renderRecordConstructorPropsInterface = (
|
|
31
33
|
context: ModuleContext,
|
|
@@ -121,9 +123,9 @@ const renderRecordConstructor = (context: ModuleContext, spec: RecordConstructor
|
|
|
121
123
|
|
|
122
124
|
const statements = [
|
|
123
125
|
...superCall,
|
|
124
|
-
`const
|
|
126
|
+
`const __handle = alloc(${allocArgs(context, record, size).join(", ")});`,
|
|
125
127
|
...renderFieldWrites(context, slots),
|
|
126
|
-
"setHandle(this,
|
|
128
|
+
"setHandle(this, __handle);",
|
|
127
129
|
];
|
|
128
130
|
|
|
129
131
|
return renderBlock(`constructor(props: ${className}ConstructorProps = {})`, statements.join("\n"));
|
|
@@ -151,7 +153,7 @@ const renderFieldWrite = (context: ModuleContext, entry: WritableFieldSlot): str
|
|
|
151
153
|
const write = emitFieldWrite(context, {
|
|
152
154
|
descriptor,
|
|
153
155
|
slot: entry.slot,
|
|
154
|
-
targetExpr: "
|
|
156
|
+
targetExpr: "__handle",
|
|
155
157
|
valueExpr: `props.${name}`,
|
|
156
158
|
});
|
|
157
159
|
|
|
@@ -9,6 +9,7 @@ import type { ModuleContext } from "../../writer/context.js";
|
|
|
9
9
|
import { isInlineCallbackRef, renderDescriptor } from "../../analysis/descriptor-render.js";
|
|
10
10
|
import { tStruct } from "../../analysis/descriptor.js";
|
|
11
11
|
import { renderTsType } from "../../analysis/ts-type.js";
|
|
12
|
+
import { isUnboundedArray } from "../../analysis/type-shape.js";
|
|
12
13
|
import { indent, renderBlock } from "../../writer/emit.js";
|
|
13
14
|
import { getDoc } from "./doc-spec.js";
|
|
14
15
|
import { bitMask, computeRecordFieldSlots, mergeBitfield, type RecordFieldSlot } from "./record-layout.js";
|
|
@@ -27,6 +28,10 @@ type AdmittedField = {
|
|
|
27
28
|
jsName: string;
|
|
28
29
|
};
|
|
29
30
|
|
|
31
|
+
type AccessibleField = AdmittedField & {
|
|
32
|
+
isSettable: boolean;
|
|
33
|
+
};
|
|
34
|
+
|
|
30
35
|
type RecordFieldEntry = {
|
|
31
36
|
jsName: string;
|
|
32
37
|
tsType: string;
|
|
@@ -167,12 +172,49 @@ const admitField = (
|
|
|
167
172
|
return { field, jsName };
|
|
168
173
|
};
|
|
169
174
|
|
|
175
|
+
const isNullTerminatedArrayField = (context: ModuleContext, ref: TypeId): boolean => {
|
|
176
|
+
const type = context.library.typeFor(ref);
|
|
177
|
+
|
|
178
|
+
return type?.kind === "carray" && isUnboundedArray(type) && type.elementCType?.endsWith("*") === true;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const isAccessibleFieldType = (context: ModuleContext, ref: TypeId): boolean =>
|
|
182
|
+
isAccessorEligibleType(context, ref) || isNullTerminatedArrayField(context, ref);
|
|
183
|
+
|
|
184
|
+
const isStorableFieldType = (context: ModuleContext, ref: TypeId): boolean => {
|
|
185
|
+
const kind = context.library.typeFor(ref)?.kind;
|
|
186
|
+
|
|
187
|
+
return kind !== "carray" && kind !== "list" && kind !== "hashtable";
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const admitAccessibleField = (
|
|
191
|
+
context: ModuleContext,
|
|
192
|
+
slot: RecordFieldSlot,
|
|
193
|
+
claimedNames: Set<string>,
|
|
194
|
+
siblingFields: GirField[],
|
|
195
|
+
): AccessibleField | undefined => {
|
|
196
|
+
const admitted = admitField(context, slot, claimedNames);
|
|
197
|
+
|
|
198
|
+
if (admitted === undefined) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const { field, jsName } = admitted;
|
|
203
|
+
const target: StructArrayTarget = { field, jsName, slot: slot.slot, siblingFields };
|
|
204
|
+
const hasStructArray = resolveStructArray(context, target) !== undefined;
|
|
205
|
+
const hasAccessor = hasStructArray || isAccessibleFieldType(context, field.type);
|
|
206
|
+
const isSettable = field.writable && (hasStructArray || isStorableFieldType(context, field.type));
|
|
207
|
+
|
|
208
|
+
return hasAccessor ? { ...admitted, isSettable } : undefined;
|
|
209
|
+
};
|
|
210
|
+
|
|
170
211
|
const resolveRecordFieldEntry = (
|
|
171
212
|
context: ModuleContext,
|
|
172
213
|
slot: RecordFieldSlot,
|
|
173
214
|
claimedNames: Set<string>,
|
|
215
|
+
siblingFields: GirField[],
|
|
174
216
|
): RecordFieldEntry | undefined => {
|
|
175
|
-
const admitted =
|
|
217
|
+
const admitted = admitAccessibleField(context, slot, claimedNames, siblingFields);
|
|
176
218
|
|
|
177
219
|
if (admitted === undefined) {
|
|
178
220
|
return undefined;
|
|
@@ -181,7 +223,7 @@ const resolveRecordFieldEntry = (
|
|
|
181
223
|
return {
|
|
182
224
|
jsName: admitted.jsName,
|
|
183
225
|
tsType: renderTsType(context, admitted.field.type, false),
|
|
184
|
-
isWritable: admitted.
|
|
226
|
+
isWritable: admitted.isSettable,
|
|
185
227
|
doc: admitted.field.doc,
|
|
186
228
|
annotations: admitted.field.annotations,
|
|
187
229
|
};
|
|
@@ -193,7 +235,7 @@ const renderRecordFieldAccessor = (
|
|
|
193
235
|
claimedNames: Set<string>,
|
|
194
236
|
siblingFields: GirField[],
|
|
195
237
|
): string | undefined => {
|
|
196
|
-
const admitted =
|
|
238
|
+
const admitted = admitAccessibleField(context, slot, claimedNames, siblingFields);
|
|
197
239
|
|
|
198
240
|
if (admitted === undefined) {
|
|
199
241
|
return undefined;
|
|
@@ -207,12 +249,6 @@ const renderRecordFieldAccessor = (
|
|
|
207
249
|
return `${doc}${structArray}`;
|
|
208
250
|
}
|
|
209
251
|
|
|
210
|
-
if (!isAccessorEligibleType(context, field.type)) {
|
|
211
|
-
const tsType = renderTsType(context, field.type, false);
|
|
212
|
-
|
|
213
|
-
return `${doc}declare ${jsName}: ${tsType};`;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
252
|
const descriptor = context.hoistDescriptor(
|
|
217
253
|
renderDescriptor(context, field.type, "none", { isInline: isInlineField(context, field) }),
|
|
218
254
|
);
|
|
@@ -230,7 +266,7 @@ const renderRecordFieldAccessor = (
|
|
|
230
266
|
|
|
231
267
|
const blocks: string[] = [getterBlock(accessorOptions)];
|
|
232
268
|
|
|
233
|
-
if (
|
|
269
|
+
if (admitted.isSettable) {
|
|
234
270
|
blocks.push(setterBlock(accessorOptions));
|
|
235
271
|
}
|
|
236
272
|
|
|
@@ -366,6 +402,21 @@ const visitInlineStructFields = (
|
|
|
366
402
|
}
|
|
367
403
|
};
|
|
368
404
|
|
|
405
|
+
const inlineLeafCount = (context: ModuleContext, fields: GirField[]): number => {
|
|
406
|
+
let count = 0;
|
|
407
|
+
|
|
408
|
+
visitInlineStructFields(context, fields, 0, {
|
|
409
|
+
leaf: () => {
|
|
410
|
+
count += 1;
|
|
411
|
+
},
|
|
412
|
+
nested: (_jsName, nested) => {
|
|
413
|
+
count += inlineLeafCount(context, nested);
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
return count;
|
|
418
|
+
};
|
|
419
|
+
|
|
369
420
|
const elementAccessExpr = (descriptor: string, offset: number): string =>
|
|
370
421
|
`read(__array, ${descriptor}, __base + ${String(offset)})`;
|
|
371
422
|
|
|
@@ -452,7 +503,7 @@ const structArrayGetterBlock = (options: StructArrayAccessorOptions): string =>
|
|
|
452
503
|
};
|
|
453
504
|
|
|
454
505
|
const structArraySetterStatements = (context: ModuleContext, options: StructArrayAccessorOptions): string => {
|
|
455
|
-
const { elementDescriptor, offset, elementSize, elementFields } = options;
|
|
506
|
+
const { elementDescriptor, offset, elementSize, elementFields, lengthExpr } = options;
|
|
456
507
|
const writes: string[] = [];
|
|
457
508
|
|
|
458
509
|
appendElementWriteStatements(context, {
|
|
@@ -468,7 +519,7 @@ const structArraySetterStatements = (context: ModuleContext, options: StructArra
|
|
|
468
519
|
`const __descriptor = ${elementDescriptor};`,
|
|
469
520
|
`const __array = read(getHandle(this), __descriptor, ${String(offset)}) as ReturnType<typeof getHandle>;`,
|
|
470
521
|
"for (const [__index, __element] of __value.entries()) {",
|
|
471
|
-
indent(loop
|
|
522
|
+
indent(`if (__index >= ${lengthExpr}) {\n break;\n}\n\n${loop}`, 1),
|
|
472
523
|
"}",
|
|
473
524
|
`write(getHandle(this), __descriptor, ${String(offset)}, __array);`,
|
|
474
525
|
].join("\n");
|
|
@@ -543,7 +594,7 @@ const resolveStructArray = (context: ModuleContext, target: StructArrayTarget):
|
|
|
543
594
|
|
|
544
595
|
const shape = resolveStructArrayShape(context, elements, siblingFields);
|
|
545
596
|
|
|
546
|
-
if (shape === undefined) {
|
|
597
|
+
if (shape === undefined || inlineLeafCount(context, elements.elementFields) === 0) {
|
|
547
598
|
return undefined;
|
|
548
599
|
}
|
|
549
600
|
|
|
@@ -639,6 +690,7 @@ const setterBlock = (options: AccessorOptions): string =>
|
|
|
639
690
|
export {
|
|
640
691
|
isEmittableField,
|
|
641
692
|
isInlineField,
|
|
693
|
+
isStorableFieldType,
|
|
642
694
|
emitFieldWrite,
|
|
643
695
|
resolveRecordFieldEntry,
|
|
644
696
|
renderRecordFieldAccessor,
|