@gtkx/codegen 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/dist/dsl/context.d.ts +104 -0
- package/dist/dsl/context.d.ts.map +1 -0
- package/dist/dsl/context.js +140 -0
- package/dist/dsl/context.js.map +1 -0
- package/dist/dsl/emit.d.ts +28 -0
- package/dist/dsl/emit.d.ts.map +1 -0
- package/dist/dsl/emit.js +41 -0
- package/dist/dsl/emit.js.map +1 -0
- package/dist/dsl/identifier.d.ts +28 -0
- package/dist/dsl/identifier.d.ts.map +1 -0
- package/dist/dsl/identifier.js +45 -0
- package/dist/dsl/identifier.js.map +1 -0
- package/dist/dsl/imports.d.ts +58 -0
- package/dist/dsl/imports.d.ts.map +1 -0
- package/dist/dsl/imports.js +107 -0
- package/dist/dsl/imports.js.map +1 -0
- package/dist/dsl/module.d.ts +53 -0
- package/dist/dsl/module.d.ts.map +1 -0
- package/dist/dsl/module.js +76 -0
- package/dist/dsl/module.js.map +1 -0
- package/dist/ffi/pipeline.d.ts +19 -0
- package/dist/ffi/pipeline.d.ts.map +1 -0
- package/dist/ffi/pipeline.js +107 -0
- package/dist/ffi/pipeline.js.map +1 -0
- package/dist/fingerprint.d.ts +30 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +33 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/gi-store.d.ts +34 -0
- package/dist/gi-store.d.ts.map +1 -0
- package/dist/gi-store.js +154 -0
- package/dist/gi-store.js.map +1 -0
- package/dist/gir/boxed.d.ts +66 -0
- package/dist/gir/boxed.d.ts.map +1 -0
- package/dist/gir/boxed.js +49 -0
- package/dist/gir/boxed.js.map +1 -0
- package/dist/gir/callback.d.ts +15 -0
- package/dist/gir/callback.d.ts.map +1 -0
- package/dist/gir/callback.js +17 -0
- package/dist/gir/callback.js.map +1 -0
- package/dist/gir/class.d.ts +49 -0
- package/dist/gir/class.d.ts.map +1 -0
- package/dist/gir/class.js +42 -0
- package/dist/gir/class.js.map +1 -0
- package/dist/gir/enum.d.ts +39 -0
- package/dist/gir/enum.d.ts.map +1 -0
- package/dist/gir/enum.js +24 -0
- package/dist/gir/enum.js.map +1 -0
- package/dist/gir/field.d.ts +27 -0
- package/dist/gir/field.d.ts.map +1 -0
- package/dist/gir/field.js +19 -0
- package/dist/gir/field.js.map +1 -0
- package/dist/gir/function.d.ts +47 -0
- package/dist/gir/function.d.ts.map +1 -0
- package/dist/gir/function.js +28 -0
- package/dist/gir/function.js.map +1 -0
- package/dist/gir/namespace.d.ts +65 -0
- package/dist/gir/namespace.d.ts.map +1 -0
- package/dist/gir/namespace.js +60 -0
- package/dist/gir/namespace.js.map +1 -0
- package/dist/gir/parameter.d.ts +82 -0
- package/dist/gir/parameter.d.ts.map +1 -0
- package/dist/gir/parameter.js +66 -0
- package/dist/gir/parameter.js.map +1 -0
- package/dist/gir/parse.d.ts +78 -0
- package/dist/gir/parse.d.ts.map +1 -0
- package/dist/gir/parse.js +155 -0
- package/dist/gir/parse.js.map +1 -0
- package/dist/gir/primitives.d.ts +36 -0
- package/dist/gir/primitives.d.ts.map +1 -0
- package/dist/gir/primitives.js +109 -0
- package/dist/gir/primitives.js.map +1 -0
- package/dist/gir/property.d.ts +29 -0
- package/dist/gir/property.d.ts.map +1 -0
- package/dist/gir/property.js +16 -0
- package/dist/gir/property.js.map +1 -0
- package/dist/gir/qualified-name.d.ts +37 -0
- package/dist/gir/qualified-name.d.ts.map +1 -0
- package/dist/gir/qualified-name.js +39 -0
- package/dist/gir/qualified-name.js.map +1 -0
- package/dist/gir/qualify.d.ts +32 -0
- package/dist/gir/qualify.d.ts.map +1 -0
- package/dist/gir/qualify.js +60 -0
- package/dist/gir/qualify.js.map +1 -0
- package/dist/gir/repository.d.ts +82 -0
- package/dist/gir/repository.d.ts.map +1 -0
- package/dist/gir/repository.js +122 -0
- package/dist/gir/repository.js.map +1 -0
- package/dist/gir/signal.d.ts +22 -0
- package/dist/gir/signal.d.ts.map +1 -0
- package/dist/gir/signal.js +20 -0
- package/dist/gir/signal.js.map +1 -0
- package/dist/gir/size.d.ts +67 -0
- package/dist/gir/size.d.ts.map +1 -0
- package/dist/gir/size.js +87 -0
- package/dist/gir/size.js.map +1 -0
- package/dist/gir/type-ref.d.ts +79 -0
- package/dist/gir/type-ref.d.ts.map +1 -0
- package/dist/gir/type-ref.js +101 -0
- package/dist/gir/type-ref.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-store.d.ts +22 -0
- package/dist/jsx-store.d.ts.map +1 -0
- package/dist/jsx-store.js +40 -0
- package/dist/jsx-store.js.map +1 -0
- package/dist/react/compounds-meta.d.ts +18 -0
- package/dist/react/compounds-meta.d.ts.map +1 -0
- package/dist/react/compounds-meta.js +93 -0
- package/dist/react/compounds-meta.js.map +1 -0
- package/dist/react/compounds.d.ts +27 -0
- package/dist/react/compounds.d.ts.map +1 -0
- package/dist/react/compounds.js +164 -0
- package/dist/react/compounds.js.map +1 -0
- package/dist/react/internal.d.ts +14 -0
- package/dist/react/internal.d.ts.map +1 -0
- package/dist/react/internal.js +79 -0
- package/dist/react/internal.js.map +1 -0
- package/dist/react/jsx.d.ts +22 -0
- package/dist/react/jsx.d.ts.map +1 -0
- package/dist/react/jsx.js +134 -0
- package/dist/react/jsx.js.map +1 -0
- package/dist/react/pipeline.d.ts +13 -0
- package/dist/react/pipeline.d.ts.map +1 -0
- package/dist/react/pipeline.js +25 -0
- package/dist/react/pipeline.js.map +1 -0
- package/dist/react/props.d.ts +38 -0
- package/dist/react/props.d.ts.map +1 -0
- package/dist/react/props.js +231 -0
- package/dist/react/props.js.map +1 -0
- package/dist/react/slot-props.d.ts +10 -0
- package/dist/react/slot-props.d.ts.map +1 -0
- package/dist/react/slot-props.js +56 -0
- package/dist/react/slot-props.js.map +1 -0
- package/dist/react/widgets.d.ts +83 -0
- package/dist/react/widgets.d.ts.map +1 -0
- package/dist/react/widgets.js +152 -0
- package/dist/react/widgets.js.map +1 -0
- package/dist/runner.d.ts +55 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +60 -0
- package/dist/runner.js.map +1 -0
- package/dist/store-fs.d.ts +109 -0
- package/dist/store-fs.d.ts.map +1 -0
- package/dist/store-fs.js +98 -0
- package/dist/store-fs.js.map +1 -0
- package/dist/transpile.d.ts +32 -0
- package/dist/transpile.d.ts.map +1 -0
- package/dist/transpile.js +63 -0
- package/dist/transpile.js.map +1 -0
- package/dist/typecheck-store.d.ts +41 -0
- package/dist/typecheck-store.d.ts.map +1 -0
- package/dist/typecheck-store.js +102 -0
- package/dist/typecheck-store.js.map +1 -0
- package/dist/writers/alias.d.ts +13 -0
- package/dist/writers/alias.d.ts.map +1 -0
- package/dist/writers/alias.js +17 -0
- package/dist/writers/alias.js.map +1 -0
- package/dist/writers/async.d.ts +22 -0
- package/dist/writers/async.d.ts.map +1 -0
- package/dist/writers/async.js +48 -0
- package/dist/writers/async.js.map +1 -0
- package/dist/writers/boxed-constructor.d.ts +26 -0
- package/dist/writers/boxed-constructor.d.ts.map +1 -0
- package/dist/writers/boxed-constructor.js +85 -0
- package/dist/writers/boxed-constructor.js.map +1 -0
- package/dist/writers/boxed-field-accessor.d.ts +18 -0
- package/dist/writers/boxed-field-accessor.d.ts.map +1 -0
- package/dist/writers/boxed-field-accessor.js +260 -0
- package/dist/writers/boxed-field-accessor.js.map +1 -0
- package/dist/writers/boxed-layout.d.ts +27 -0
- package/dist/writers/boxed-layout.d.ts.map +1 -0
- package/dist/writers/boxed-layout.js +128 -0
- package/dist/writers/boxed-layout.js.map +1 -0
- package/dist/writers/boxed.d.ts +20 -0
- package/dist/writers/boxed.d.ts.map +1 -0
- package/dist/writers/boxed.js +71 -0
- package/dist/writers/boxed.js.map +1 -0
- package/dist/writers/callables.d.ts +124 -0
- package/dist/writers/callables.d.ts.map +1 -0
- package/dist/writers/callables.js +283 -0
- package/dist/writers/callables.js.map +1 -0
- package/dist/writers/callback.d.ts +16 -0
- package/dist/writers/callback.d.ts.map +1 -0
- package/dist/writers/callback.js +38 -0
- package/dist/writers/callback.js.map +1 -0
- package/dist/writers/class-struct-record.d.ts +31 -0
- package/dist/writers/class-struct-record.d.ts.map +1 -0
- package/dist/writers/class-struct-record.js +67 -0
- package/dist/writers/class-struct-record.js.map +1 -0
- package/dist/writers/class-struct.d.ts +22 -0
- package/dist/writers/class-struct.d.ts.map +1 -0
- package/dist/writers/class-struct.js +85 -0
- package/dist/writers/class-struct.js.map +1 -0
- package/dist/writers/class.d.ts +16 -0
- package/dist/writers/class.d.ts.map +1 -0
- package/dist/writers/class.js +307 -0
- package/dist/writers/class.js.map +1 -0
- package/dist/writers/constant.d.ts +15 -0
- package/dist/writers/constant.d.ts.map +1 -0
- package/dist/writers/constant.js +23 -0
- package/dist/writers/constant.js.map +1 -0
- package/dist/writers/constants.d.ts +15 -0
- package/dist/writers/constants.d.ts.map +1 -0
- package/dist/writers/constants.js +23 -0
- package/dist/writers/constants.js.map +1 -0
- package/dist/writers/constructor-props.d.ts +32 -0
- package/dist/writers/constructor-props.d.ts.map +1 -0
- package/dist/writers/constructor-props.js +110 -0
- package/dist/writers/constructor-props.js.map +1 -0
- package/dist/writers/enum.d.ts +21 -0
- package/dist/writers/enum.d.ts.map +1 -0
- package/dist/writers/enum.js +48 -0
- package/dist/writers/enum.js.map +1 -0
- package/dist/writers/function.d.ts +40 -0
- package/dist/writers/function.d.ts.map +1 -0
- package/dist/writers/function.js +127 -0
- package/dist/writers/function.js.map +1 -0
- package/dist/writers/gtype-binding.d.ts +19 -0
- package/dist/writers/gtype-binding.d.ts.map +1 -0
- package/dist/writers/gtype-binding.js +40 -0
- package/dist/writers/gtype-binding.js.map +1 -0
- package/dist/writers/inheritance.d.ts +48 -0
- package/dist/writers/inheritance.d.ts.map +1 -0
- package/dist/writers/inheritance.js +90 -0
- package/dist/writers/inheritance.js.map +1 -0
- package/dist/writers/interface.d.ts +16 -0
- package/dist/writers/interface.d.ts.map +1 -0
- package/dist/writers/interface.js +155 -0
- package/dist/writers/interface.js.map +1 -0
- package/dist/writers/method.d.ts +150 -0
- package/dist/writers/method.d.ts.map +1 -0
- package/dist/writers/method.js +510 -0
- package/dist/writers/method.js.map +1 -0
- package/dist/writers/param-classify.d.ts +93 -0
- package/dist/writers/param-classify.d.ts.map +1 -0
- package/dist/writers/param-classify.js +163 -0
- package/dist/writers/param-classify.js.map +1 -0
- package/dist/writers/property-accessor.d.ts +19 -0
- package/dist/writers/property-accessor.d.ts.map +1 -0
- package/dist/writers/property-accessor.js +117 -0
- package/dist/writers/property-accessor.js.map +1 -0
- package/dist/writers/registration.d.ts +27 -0
- package/dist/writers/registration.d.ts.map +1 -0
- package/dist/writers/registration.js +30 -0
- package/dist/writers/registration.js.map +1 -0
- package/dist/writers/return-wrap.d.ts +39 -0
- package/dist/writers/return-wrap.d.ts.map +1 -0
- package/dist/writers/return-wrap.js +152 -0
- package/dist/writers/return-wrap.js.map +1 -0
- package/dist/writers/runtime-override.d.ts +18 -0
- package/dist/writers/runtime-override.d.ts.map +1 -0
- package/dist/writers/runtime-override.js +44 -0
- package/dist/writers/runtime-override.js.map +1 -0
- package/dist/writers/signal.d.ts +21 -0
- package/dist/writers/signal.d.ts.map +1 -0
- package/dist/writers/signal.js +260 -0
- package/dist/writers/signal.js.map +1 -0
- package/dist/writers/ts-type.d.ts +50 -0
- package/dist/writers/ts-type.d.ts.map +1 -0
- package/dist/writers/ts-type.js +75 -0
- package/dist/writers/ts-type.js.map +1 -0
- package/dist/writers/types-ts.d.ts +27 -0
- package/dist/writers/types-ts.d.ts.map +1 -0
- package/dist/writers/types-ts.js +97 -0
- package/dist/writers/types-ts.js.map +1 -0
- package/dist/writers/value.d.ts +89 -0
- package/dist/writers/value.d.ts.map +1 -0
- package/dist/writers/value.js +402 -0
- package/dist/writers/value.js.map +1 -0
- package/package.json +55 -0
- package/src/dsl/context.ts +146 -0
- package/src/dsl/emit.ts +42 -0
- package/src/dsl/identifier.ts +52 -0
- package/src/dsl/imports.ts +109 -0
- package/src/dsl/module.ts +75 -0
- package/src/ffi/pipeline.ts +113 -0
- package/src/fingerprint.ts +50 -0
- package/src/gi-store.ts +199 -0
- package/src/gir/boxed.ts +94 -0
- package/src/gir/callback.ts +26 -0
- package/src/gir/class.ts +79 -0
- package/src/gir/enum.ts +55 -0
- package/src/gir/field.ts +40 -0
- package/src/gir/function.ts +67 -0
- package/src/gir/namespace.ts +118 -0
- package/src/gir/parameter.ts +120 -0
- package/src/gir/parse.ts +171 -0
- package/src/gir/primitives.ts +137 -0
- package/src/gir/property.ts +39 -0
- package/src/gir/qualified-name.ts +55 -0
- package/src/gir/qualify.ts +64 -0
- package/src/gir/repository.ts +149 -0
- package/src/gir/signal.ts +36 -0
- package/src/gir/size.ts +129 -0
- package/src/gir/type-ref.ts +180 -0
- package/src/index.ts +16 -0
- package/src/jsx-store.ts +53 -0
- package/src/react/compounds-meta.ts +99 -0
- package/src/react/compounds.ts +204 -0
- package/src/react/internal.ts +91 -0
- package/src/react/jsx.ts +155 -0
- package/src/react/pipeline.ts +29 -0
- package/src/react/props.ts +307 -0
- package/src/react/slot-props.ts +57 -0
- package/src/react/widgets.ts +185 -0
- package/src/runner.ts +89 -0
- package/src/store-fs.ts +157 -0
- package/src/transpile.ts +80 -0
- package/src/typecheck-store.ts +136 -0
- package/src/writers/alias.ts +19 -0
- package/src/writers/async.ts +44 -0
- package/src/writers/boxed-constructor.ts +105 -0
- package/src/writers/boxed-field-accessor.ts +306 -0
- package/src/writers/boxed-layout.ts +166 -0
- package/src/writers/boxed.ts +77 -0
- package/src/writers/callables.ts +339 -0
- package/src/writers/callback.ts +40 -0
- package/src/writers/class-struct-record.ts +75 -0
- package/src/writers/class-struct.ts +96 -0
- package/src/writers/class.ts +384 -0
- package/src/writers/constant.ts +29 -0
- package/src/writers/constructor-props.ts +130 -0
- package/src/writers/enum.ts +53 -0
- package/src/writers/function.ts +136 -0
- package/src/writers/gtype-binding.ts +48 -0
- package/src/writers/inheritance.ts +104 -0
- package/src/writers/interface.ts +168 -0
- package/src/writers/method.ts +678 -0
- package/src/writers/param-classify.ts +178 -0
- package/src/writers/property-accessor.ts +139 -0
- package/src/writers/registration.ts +42 -0
- package/src/writers/return-wrap.ts +180 -0
- package/src/writers/runtime-override.ts +59 -0
- package/src/writers/signal.ts +318 -0
- package/src/writers/ts-type.ts +115 -0
- package/src/writers/value.ts +485 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { boxedFromNode, boxedKind, type GirBoxed } from "./boxed.js";
|
|
2
|
+
import { callbackFromNode, type GirCallback } from "./callback.js";
|
|
3
|
+
import { classFromNode, type GirClass } from "./class.js";
|
|
4
|
+
import { enumFromNode, type GirEnum } from "./enum.js";
|
|
5
|
+
import { functionFromNode, type GirFunction } from "./function.js";
|
|
6
|
+
import { attr, childrenOf, type RawNode } from "./parse.js";
|
|
7
|
+
import { type GirTypeRef, typeRefFromSlot } from "./type-ref.js";
|
|
8
|
+
|
|
9
|
+
/** A `<constant>` declaration at namespace level. */
|
|
10
|
+
export type GirConstant = {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly cType: string | undefined;
|
|
13
|
+
readonly cIdentifier: string | undefined;
|
|
14
|
+
/** Constant value as the raw string from GIR. */
|
|
15
|
+
readonly value: string;
|
|
16
|
+
readonly type: GirTypeRef | undefined;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** A `<alias>` declaration at namespace level. */
|
|
20
|
+
export type GirAlias = {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly target: GirTypeRef | undefined;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A single namespace loaded from one `.gir` file.
|
|
27
|
+
*
|
|
28
|
+
* The class lives in `namespace.ts` (mutable holder) because populating it
|
|
29
|
+
* involves walking the raw XML tree once, materialising each construct.
|
|
30
|
+
* After construction the public surface is read-only by convention.
|
|
31
|
+
*/
|
|
32
|
+
export type GirNamespace = {
|
|
33
|
+
/** Namespace name (e.g. `"Gtk"`). */
|
|
34
|
+
readonly name: string;
|
|
35
|
+
/** Namespace version (e.g. `"4.0"`). */
|
|
36
|
+
readonly version: string;
|
|
37
|
+
/** `Name-Version` identifier (e.g. `"Gtk-4.0"`). */
|
|
38
|
+
readonly identifier: string;
|
|
39
|
+
/** Comma-separated `shared-library` value (passed verbatim to `t.fn(...)`). */
|
|
40
|
+
readonly sharedLibrary: string | undefined;
|
|
41
|
+
/** GIR `c:identifier-prefixes` (used to strip type prefixes). */
|
|
42
|
+
readonly cIdentifierPrefixes: readonly string[];
|
|
43
|
+
/** GIR `c:symbol-prefixes` (used to strip function prefixes). */
|
|
44
|
+
readonly cSymbolPrefixes: readonly string[];
|
|
45
|
+
/** Other namespaces referenced via `<include>`. */
|
|
46
|
+
readonly includes: readonly NamespaceInclude[];
|
|
47
|
+
readonly classes: readonly GirClass[];
|
|
48
|
+
readonly interfaces: readonly GirClass[];
|
|
49
|
+
readonly boxeds: readonly GirBoxed[];
|
|
50
|
+
readonly enums: readonly GirEnum[];
|
|
51
|
+
readonly callbacks: readonly GirCallback[];
|
|
52
|
+
readonly functions: readonly GirFunction[];
|
|
53
|
+
readonly constants: readonly GirConstant[];
|
|
54
|
+
readonly aliases: readonly GirAlias[];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** A `<include>` entry pointing at another namespace identifier. */
|
|
58
|
+
type NamespaceInclude = {
|
|
59
|
+
readonly name: string;
|
|
60
|
+
readonly version: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Builds a {@link GirNamespace} from a parsed `<repository>` root.
|
|
65
|
+
*
|
|
66
|
+
* @param repositoryNode - The raw `<repository>` element returned by `parseGirFile`
|
|
67
|
+
*/
|
|
68
|
+
export const namespaceFromRepository = (repositoryNode: RawNode): GirNamespace => {
|
|
69
|
+
const includes = childrenOf(repositoryNode, "include").map<NamespaceInclude>((include) => ({
|
|
70
|
+
name: attr(include, "name") ?? "",
|
|
71
|
+
version: attr(include, "version") ?? "",
|
|
72
|
+
}));
|
|
73
|
+
const namespaceNode = childrenOf(repositoryNode, "namespace")[0];
|
|
74
|
+
if (namespaceNode === undefined) {
|
|
75
|
+
throw new Error("GIR repository has no <namespace> child");
|
|
76
|
+
}
|
|
77
|
+
const name = attr(namespaceNode, "name") ?? "";
|
|
78
|
+
const version = attr(namespaceNode, "version") ?? "";
|
|
79
|
+
return {
|
|
80
|
+
name,
|
|
81
|
+
version,
|
|
82
|
+
identifier: `${name}-${version}`,
|
|
83
|
+
sharedLibrary: attr(namespaceNode, "shared-library"),
|
|
84
|
+
cIdentifierPrefixes: splitPrefixes(attr(namespaceNode, "c:identifier-prefixes")),
|
|
85
|
+
cSymbolPrefixes: splitPrefixes(attr(namespaceNode, "c:symbol-prefixes")),
|
|
86
|
+
includes,
|
|
87
|
+
classes: childrenOf(namespaceNode, "class").map((klass) => classFromNode(klass, false)),
|
|
88
|
+
interfaces: childrenOf(namespaceNode, "interface").map((iface) => classFromNode(iface, true)),
|
|
89
|
+
boxeds: collectBoxeds(namespaceNode),
|
|
90
|
+
enums: collectEnums(namespaceNode),
|
|
91
|
+
callbacks: childrenOf(namespaceNode, "callback").map(callbackFromNode),
|
|
92
|
+
functions: childrenOf(namespaceNode, "function").map((fn) => functionFromNode(fn, "function")),
|
|
93
|
+
constants: childrenOf(namespaceNode, "constant").map((constant) => ({
|
|
94
|
+
name: attr(constant, "name") ?? "",
|
|
95
|
+
cType: attr(constant, "c:type"),
|
|
96
|
+
cIdentifier: attr(constant, "c:identifier"),
|
|
97
|
+
value: attr(constant, "value") ?? "",
|
|
98
|
+
type: typeRefFromSlot(constant),
|
|
99
|
+
})),
|
|
100
|
+
aliases: childrenOf(namespaceNode, "alias").map((alias) => ({
|
|
101
|
+
name: attr(alias, "name") ?? "",
|
|
102
|
+
target: typeRefFromSlot(alias),
|
|
103
|
+
})),
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const splitPrefixes = (raw: string | undefined): readonly string[] =>
|
|
108
|
+
(raw ?? "").split(",").filter((prefix) => prefix.length > 0);
|
|
109
|
+
|
|
110
|
+
const collectBoxeds = (namespaceNode: RawNode): readonly GirBoxed[] => [
|
|
111
|
+
...childrenOf(namespaceNode, "record").map((record) => boxedFromNode(record, boxedKind(record), false)),
|
|
112
|
+
...childrenOf(namespaceNode, "union").map((union) => boxedFromNode(union, boxedKind(union), true)),
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
const collectEnums = (namespaceNode: RawNode) => [
|
|
116
|
+
...childrenOf(namespaceNode, "enumeration").map((enumeration) => enumFromNode(enumeration, "enumeration")),
|
|
117
|
+
...childrenOf(namespaceNode, "bitfield").map((bitfield) => enumFromNode(bitfield, "bitfield")),
|
|
118
|
+
];
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { attr, attrBool, childOf, type RawNode } from "./parse.js";
|
|
2
|
+
import { type GirTypeRef, typeRefFromSlot } from "./type-ref.js";
|
|
3
|
+
|
|
4
|
+
/** Direction of a `<parameter>` (`in`, `out`, `inout`). */
|
|
5
|
+
type ParameterDirection = "in" | "out" | "inout";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Lifetime conveyed by `transfer-ownership`. Mirrors the GIR vocabulary one
|
|
9
|
+
* for one; the marshal layer translates to the runtime's `Ownership` set.
|
|
10
|
+
*/
|
|
11
|
+
export type ParameterTransfer = "none" | "full" | "container";
|
|
12
|
+
|
|
13
|
+
/** Lifetime of a callback parameter (`scope=…`). */
|
|
14
|
+
type CallbackScope = "call" | "notified" | "async" | "forever";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A `<parameter>` or `<instance-parameter>` of a callable.
|
|
18
|
+
*
|
|
19
|
+
* Only the bits the FFI writers actually look at are retained; the original
|
|
20
|
+
* raw node is dropped so the domain model is self-describing.
|
|
21
|
+
*/
|
|
22
|
+
export type GirParameter = {
|
|
23
|
+
/** Parameter name as authored in GIR (often snake_case). */
|
|
24
|
+
readonly name: string;
|
|
25
|
+
/** Typed slot of the parameter, or `undefined` for `<varargs/>`. */
|
|
26
|
+
readonly type: GirTypeRef | undefined;
|
|
27
|
+
readonly direction: ParameterDirection;
|
|
28
|
+
readonly transferOwnership: ParameterTransfer;
|
|
29
|
+
readonly nullable: boolean;
|
|
30
|
+
readonly optional: boolean;
|
|
31
|
+
/** `caller-allocates="1"` — used in out parameters that fill a caller buffer. */
|
|
32
|
+
readonly callerAllocates: boolean;
|
|
33
|
+
/** Lifetime of a callback parameter (defined only when the parameter is a callback). */
|
|
34
|
+
readonly scope: CallbackScope | undefined;
|
|
35
|
+
/** Index of the paired `gpointer user_data` parameter in the C signature. */
|
|
36
|
+
readonly closureIndex: number | undefined;
|
|
37
|
+
/** Index of the paired `GDestroyNotify` parameter in the C signature. */
|
|
38
|
+
readonly destroyIndex: number | undefined;
|
|
39
|
+
/** `true` for `<instance-parameter>` (the implicit `self` of a method). */
|
|
40
|
+
readonly isInstance: boolean;
|
|
41
|
+
/** `<varargs/>` parameter; not marshalable. */
|
|
42
|
+
readonly isVarargs: boolean;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Builds a {@link GirParameter} from a `<parameter>` or `<instance-parameter>`.
|
|
47
|
+
*
|
|
48
|
+
* @param node - The XML element
|
|
49
|
+
* @param isInstance - Whether the source element was `<instance-parameter>`
|
|
50
|
+
*/
|
|
51
|
+
export const parameterFromNode = (node: RawNode, isInstance: boolean): GirParameter => {
|
|
52
|
+
const direction = (attr(node, "direction") ?? "in") as ParameterDirection;
|
|
53
|
+
const transferOwnership = (attr(node, "transfer-ownership") ?? "none") as ParameterTransfer;
|
|
54
|
+
const closure = attr(node, "closure");
|
|
55
|
+
const destroy = attr(node, "destroy");
|
|
56
|
+
return {
|
|
57
|
+
name: attr(node, "name") ?? "",
|
|
58
|
+
type: typeRefFromSlot(node),
|
|
59
|
+
direction,
|
|
60
|
+
transferOwnership,
|
|
61
|
+
nullable: attrBool(node, "nullable") || attrBool(node, "allow-none"),
|
|
62
|
+
optional: attrBool(node, "optional"),
|
|
63
|
+
callerAllocates: attrBool(node, "caller-allocates"),
|
|
64
|
+
scope: attr(node, "scope") as CallbackScope | undefined,
|
|
65
|
+
closureIndex: closure === undefined ? undefined : Number.parseInt(closure, 10),
|
|
66
|
+
destroyIndex: destroy === undefined ? undefined : Number.parseInt(destroy, 10),
|
|
67
|
+
isInstance,
|
|
68
|
+
isVarargs: childOf(node, "varargs") !== undefined,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Whether a parameter is a pure out-parameter: `direction="out"` and not
|
|
74
|
+
* caller-allocated, so it marshals through a `{ value }` cell the callee writes into.
|
|
75
|
+
*
|
|
76
|
+
* @param parameter - The parameter to test
|
|
77
|
+
*/
|
|
78
|
+
export const isOutParameter = (parameter: GirParameter): boolean =>
|
|
79
|
+
parameter.direction === "out" && !parameter.callerAllocates;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Whether a parameter is a caller-allocated out-parameter: `direction="out"`
|
|
83
|
+
* with `caller-allocates="1"`, passed as a pre-built handle the callee fills
|
|
84
|
+
* in place rather than through a `{ value }` cell.
|
|
85
|
+
*
|
|
86
|
+
* @param parameter - The parameter to test
|
|
87
|
+
*/
|
|
88
|
+
export const isCallerAllocatedOut = (parameter: GirParameter): boolean =>
|
|
89
|
+
parameter.direction === "out" && parameter.callerAllocates;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Whether a parameter is an inout parameter (`direction="inout"`).
|
|
93
|
+
*
|
|
94
|
+
* @param parameter - The parameter to test
|
|
95
|
+
*/
|
|
96
|
+
export const isInoutParameter = (parameter: GirParameter): boolean => parameter.direction === "inout";
|
|
97
|
+
|
|
98
|
+
/** A `<return-value>` plus its inferred type and transfer settings. */
|
|
99
|
+
export type GirReturnValue = {
|
|
100
|
+
readonly type: GirTypeRef | undefined;
|
|
101
|
+
readonly transferOwnership: ParameterTransfer;
|
|
102
|
+
readonly nullable: boolean;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Builds a {@link GirReturnValue} from a `<return-value>` element, or returns a
|
|
107
|
+
* void return when the element is missing.
|
|
108
|
+
*
|
|
109
|
+
* @param node - The `<return-value>` element, or `undefined`
|
|
110
|
+
*/
|
|
111
|
+
export const returnValueFromNode = (node: RawNode | undefined): GirReturnValue => {
|
|
112
|
+
if (node === undefined) {
|
|
113
|
+
return { type: undefined, transferOwnership: "none", nullable: false };
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
type: typeRefFromSlot(node),
|
|
117
|
+
transferOwnership: (attr(node, "transfer-ownership") ?? "none") as ParameterTransfer,
|
|
118
|
+
nullable: attrBool(node, "nullable") || attrBool(node, "allow-none"),
|
|
119
|
+
};
|
|
120
|
+
};
|
package/src/gir/parse.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { XMLParser } from "fast-xml-parser";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Raw GIR XML element after parsing.
|
|
6
|
+
*
|
|
7
|
+
* Attributes are exposed under `@_<name>` keys (the default
|
|
8
|
+
* `fast-xml-parser` convention). Child elements appear under their tag name.
|
|
9
|
+
* Multi-occurrence tags (every container in {@link MULTI_TAGS}) are always
|
|
10
|
+
* arrays so callers do not need to disambiguate "single child" from "many
|
|
11
|
+
* children" at every access. Single-occurrence tags appear as bare objects.
|
|
12
|
+
*/
|
|
13
|
+
export type RawNode = {
|
|
14
|
+
readonly [attributeOrChild: string]: unknown;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Tag names that the GIR schema permits at multi-occurrence positions.
|
|
19
|
+
*
|
|
20
|
+
* `fast-xml-parser` is configured to always materialize these as arrays so
|
|
21
|
+
* downstream traversal never needs to branch on "is this an object or an
|
|
22
|
+
* array of objects". Tags missing from this set may appear as a single
|
|
23
|
+
* object (e.g. `<return-value>`, `<parameters>`, `<type>`, `<doc>`).
|
|
24
|
+
*/
|
|
25
|
+
const MULTI_TAGS: ReadonlySet<string> = new Set([
|
|
26
|
+
"include",
|
|
27
|
+
"c:include",
|
|
28
|
+
"package",
|
|
29
|
+
"class",
|
|
30
|
+
"interface",
|
|
31
|
+
"record",
|
|
32
|
+
"enumeration",
|
|
33
|
+
"bitfield",
|
|
34
|
+
"callback",
|
|
35
|
+
"function",
|
|
36
|
+
"function-macro",
|
|
37
|
+
"constant",
|
|
38
|
+
"alias",
|
|
39
|
+
"union",
|
|
40
|
+
"glib:boxed",
|
|
41
|
+
"method",
|
|
42
|
+
"constructor",
|
|
43
|
+
"virtual-method",
|
|
44
|
+
"property",
|
|
45
|
+
"field",
|
|
46
|
+
"glib:signal",
|
|
47
|
+
"implements",
|
|
48
|
+
"prerequisite",
|
|
49
|
+
"member",
|
|
50
|
+
"parameter",
|
|
51
|
+
"attribute",
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The tag name codegen reads GIR constructors under.
|
|
56
|
+
*
|
|
57
|
+
* GIR spells constructors `<constructor>`, but `fast-xml-parser` rejects the
|
|
58
|
+
* literal names `constructor`, `prototype`, and `__proto__` to guard against
|
|
59
|
+
* prototype pollution, with no opt-out. {@link parseGirFile} rewrites the tag
|
|
60
|
+
* to this token via `transformTagName` before that guard runs, so every
|
|
61
|
+
* downstream lookup of a constructor child must use this constant rather than
|
|
62
|
+
* the raw GIR name.
|
|
63
|
+
*/
|
|
64
|
+
export const GIR_CONSTRUCTOR_TAG = "gir-constructor";
|
|
65
|
+
|
|
66
|
+
const RESERVED_TAG_RENAMES: ReadonlyMap<string, string> = new Map([["constructor", GIR_CONSTRUCTOR_TAG]]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Maps a GIR tag name to the token the parser exposes it under, rewriting the
|
|
70
|
+
* names {@link RESERVED_TAG_RENAMES} covers and passing every other tag
|
|
71
|
+
* through unchanged.
|
|
72
|
+
*
|
|
73
|
+
* @param tag - The raw GIR tag name
|
|
74
|
+
*/
|
|
75
|
+
const renameReservedTag = (tag: string): string => RESERVED_TAG_RENAMES.get(tag) ?? tag;
|
|
76
|
+
|
|
77
|
+
const RENAMED_MULTI_TAGS: ReadonlySet<string> = new Set([...MULTI_TAGS].map(renameReservedTag));
|
|
78
|
+
|
|
79
|
+
const PARSER = new XMLParser({
|
|
80
|
+
ignoreAttributes: false,
|
|
81
|
+
attributeNamePrefix: "@_",
|
|
82
|
+
parseAttributeValue: false,
|
|
83
|
+
parseTagValue: false,
|
|
84
|
+
trimValues: true,
|
|
85
|
+
transformTagName: renameReservedTag,
|
|
86
|
+
isArray: (name) => RENAMED_MULTI_TAGS.has(name),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Parses a GIR XML file from disk and returns its raw tree.
|
|
91
|
+
*
|
|
92
|
+
* The returned object always has a single `repository` property containing
|
|
93
|
+
* the root `<repository>` element. Callers should not interpret the tree
|
|
94
|
+
* directly — pass it to {@link GirRepository.load} (in `./repository.ts`),
|
|
95
|
+
* which builds the typed domain model on top of it.
|
|
96
|
+
*
|
|
97
|
+
* @param path - Absolute path to a `.gir` file
|
|
98
|
+
* @returns The raw repository node
|
|
99
|
+
*/
|
|
100
|
+
export const parseGirFile = (path: string): RawNode => {
|
|
101
|
+
const xml = readFileSync(path, "utf-8");
|
|
102
|
+
return PARSER.parse(xml) as RawNode;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Reads an attribute from a raw GIR node as a string, returning `undefined`
|
|
107
|
+
* when the attribute is absent.
|
|
108
|
+
*
|
|
109
|
+
* The `@_` prefix is added by `fast-xml-parser`; this helper hides that
|
|
110
|
+
* convention from the call sites.
|
|
111
|
+
*
|
|
112
|
+
* @param node - The raw element
|
|
113
|
+
* @param name - The attribute name (without the `@_` prefix)
|
|
114
|
+
*/
|
|
115
|
+
export const attr = (node: RawNode | undefined, name: string): string | undefined => {
|
|
116
|
+
if (node === undefined) return undefined;
|
|
117
|
+
const value = node[`@_${name}`];
|
|
118
|
+
return typeof value === "string" ? value : undefined;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Reads an attribute as a boolean using GIR's `"1"` / `"0"` convention.
|
|
123
|
+
*
|
|
124
|
+
* Attributes that are missing return the supplied default (defaulting to
|
|
125
|
+
* `false`). Any non-`"1"` value is treated as `false`.
|
|
126
|
+
*
|
|
127
|
+
* @param node - The raw element
|
|
128
|
+
* @param name - The attribute name (without the `@_` prefix)
|
|
129
|
+
* @param fallback - Value returned when the attribute is missing
|
|
130
|
+
*/
|
|
131
|
+
export const attrBool = (node: RawNode | undefined, name: string, fallback = false): boolean => {
|
|
132
|
+
const value = attr(node, name);
|
|
133
|
+
if (value === undefined) return fallback;
|
|
134
|
+
return value === "1";
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns the children of a raw node under a given tag name as an array.
|
|
139
|
+
*
|
|
140
|
+
* The parser configuration forces multi-occurrence tags to arrays already;
|
|
141
|
+
* this helper covers the residual case where a tag was registered as
|
|
142
|
+
* single-occurrence at the schema level but a particular file emits zero
|
|
143
|
+
* elements (returning `[]`) or where the caller wants a uniform array view.
|
|
144
|
+
*
|
|
145
|
+
* @param node - The parent element
|
|
146
|
+
* @param tag - The child tag name (with namespace prefix if any)
|
|
147
|
+
*/
|
|
148
|
+
export const childrenOf = (node: RawNode | undefined, tag: string): readonly RawNode[] => {
|
|
149
|
+
if (node === undefined) return [];
|
|
150
|
+
const value = node[tag];
|
|
151
|
+
if (value === undefined) return [];
|
|
152
|
+
if (Array.isArray(value)) return value as readonly RawNode[];
|
|
153
|
+
return [value as RawNode];
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Returns the single child of a raw node under a given tag, or `undefined`
|
|
158
|
+
* if absent. If multiple are present the first is returned.
|
|
159
|
+
*
|
|
160
|
+
* @param node - The parent element
|
|
161
|
+
* @param tag - The child tag name (with namespace prefix if any)
|
|
162
|
+
*/
|
|
163
|
+
export const childOf = (node: RawNode | undefined, tag: string): RawNode | undefined => {
|
|
164
|
+
if (node === undefined) return undefined;
|
|
165
|
+
const value = node[tag];
|
|
166
|
+
if (value === undefined) return undefined;
|
|
167
|
+
if (Array.isArray(value)) {
|
|
168
|
+
return value.length === 0 ? undefined : (value[0] as RawNode);
|
|
169
|
+
}
|
|
170
|
+
return value as RawNode;
|
|
171
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping from GIR primitive type names to the FFI marshaling categories
|
|
3
|
+
* the writers emit.
|
|
4
|
+
*
|
|
5
|
+
* The categories mirror the `t.*` helpers exposed by `@gtkx/ffi`'s runtime
|
|
6
|
+
* (see `packages/ffi/src/helpers.ts`). Categories that are not directly
|
|
7
|
+
* marshaled (e.g. `void`, `string`, `unichar`) are still listed so callers
|
|
8
|
+
* can branch on them without falling through to a default.
|
|
9
|
+
*/
|
|
10
|
+
export type PrimitiveCategory =
|
|
11
|
+
| "void"
|
|
12
|
+
| "boolean"
|
|
13
|
+
| "int8"
|
|
14
|
+
| "uint8"
|
|
15
|
+
| "int16"
|
|
16
|
+
| "uint16"
|
|
17
|
+
| "int32"
|
|
18
|
+
| "uint32"
|
|
19
|
+
| "int64"
|
|
20
|
+
| "uint64"
|
|
21
|
+
| "float32"
|
|
22
|
+
| "float64"
|
|
23
|
+
| "string"
|
|
24
|
+
| "unichar"
|
|
25
|
+
| "pointer";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Width in bytes of each primitive category on the x86-64 ABI (Linux LP64).
|
|
29
|
+
*
|
|
30
|
+
* The widths are also used as the natural alignment requirement of each
|
|
31
|
+
* category — every native integer/float aligns to its own size.
|
|
32
|
+
*/
|
|
33
|
+
export const PRIMITIVE_SIZE: Readonly<Record<PrimitiveCategory, number>> = Object.freeze({
|
|
34
|
+
void: 0,
|
|
35
|
+
boolean: 4,
|
|
36
|
+
int8: 1,
|
|
37
|
+
uint8: 1,
|
|
38
|
+
int16: 2,
|
|
39
|
+
uint16: 2,
|
|
40
|
+
int32: 4,
|
|
41
|
+
uint32: 4,
|
|
42
|
+
int64: 8,
|
|
43
|
+
uint64: 8,
|
|
44
|
+
float32: 4,
|
|
45
|
+
float64: 8,
|
|
46
|
+
string: 8,
|
|
47
|
+
unichar: 4,
|
|
48
|
+
pointer: 8,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const PRIMITIVE_BY_NAME: ReadonlyMap<string, PrimitiveCategory> = new Map([
|
|
52
|
+
["none", "void"],
|
|
53
|
+
["void", "void"],
|
|
54
|
+
["gboolean", "boolean"],
|
|
55
|
+
["gchar", "int8"],
|
|
56
|
+
["gint8", "int8"],
|
|
57
|
+
["guchar", "uint8"],
|
|
58
|
+
["guint8", "uint8"],
|
|
59
|
+
["gshort", "int16"],
|
|
60
|
+
["gint16", "int16"],
|
|
61
|
+
["gushort", "uint16"],
|
|
62
|
+
["guint16", "uint16"],
|
|
63
|
+
["gint", "int32"],
|
|
64
|
+
["gint32", "int32"],
|
|
65
|
+
["int", "int32"],
|
|
66
|
+
["int8", "int8"],
|
|
67
|
+
["uint8", "uint8"],
|
|
68
|
+
["int16", "int16"],
|
|
69
|
+
["uint16", "uint16"],
|
|
70
|
+
["int32", "int32"],
|
|
71
|
+
["uint32", "uint32"],
|
|
72
|
+
["int64", "int64"],
|
|
73
|
+
["uint64", "uint64"],
|
|
74
|
+
["guint", "uint32"],
|
|
75
|
+
["guint32", "uint32"],
|
|
76
|
+
["glong", "int64"],
|
|
77
|
+
["gint64", "int64"],
|
|
78
|
+
["long", "int64"],
|
|
79
|
+
["gssize", "int64"],
|
|
80
|
+
["gintptr", "int64"],
|
|
81
|
+
["gulong", "uint64"],
|
|
82
|
+
["guint64", "uint64"],
|
|
83
|
+
["gsize", "uint64"],
|
|
84
|
+
["guintptr", "uint64"],
|
|
85
|
+
["GType", "uint64"],
|
|
86
|
+
["time_t", "int64"],
|
|
87
|
+
["pid_t", "int32"],
|
|
88
|
+
["uid_t", "uint32"],
|
|
89
|
+
["gid_t", "uint32"],
|
|
90
|
+
["gfloat", "float32"],
|
|
91
|
+
["float", "float32"],
|
|
92
|
+
["gdouble", "float64"],
|
|
93
|
+
["double", "float64"],
|
|
94
|
+
["long double", "float64"],
|
|
95
|
+
["utf8", "string"],
|
|
96
|
+
["filename", "string"],
|
|
97
|
+
["gchararray", "string"],
|
|
98
|
+
["gunichar", "unichar"],
|
|
99
|
+
["gpointer", "pointer"],
|
|
100
|
+
["gconstpointer", "pointer"],
|
|
101
|
+
] as const);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Returns the FFI category for a GIR primitive name (`"gint"`, `"utf8"`,
|
|
105
|
+
* `"gsize"`, …) or `undefined` when the name is not a primitive.
|
|
106
|
+
*
|
|
107
|
+
* Aliases that GIR uses inconsistently (`gint` / `int` / `gint32`, …) all
|
|
108
|
+
* map to the same canonical category.
|
|
109
|
+
*
|
|
110
|
+
* @param name - The GIR type name as it appears in `<type name="…">`
|
|
111
|
+
*/
|
|
112
|
+
export const primitiveCategory = (name: string): PrimitiveCategory | undefined => PRIMITIVE_BY_NAME.get(name);
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* TypeScript surface type for each primitive category.
|
|
116
|
+
*
|
|
117
|
+
* Codegen surfaces both raw C primitives and string-marshalled categories
|
|
118
|
+
* (`string`, `unichar`) through this map so writers in the FFI and React
|
|
119
|
+
* pipelines agree on the same annotation per category.
|
|
120
|
+
*/
|
|
121
|
+
export const PRIMITIVE_TS_TYPE: Readonly<Record<PrimitiveCategory, string>> = Object.freeze({
|
|
122
|
+
void: "void",
|
|
123
|
+
boolean: "boolean",
|
|
124
|
+
int8: "number",
|
|
125
|
+
uint8: "number",
|
|
126
|
+
int16: "number",
|
|
127
|
+
uint16: "number",
|
|
128
|
+
int32: "number",
|
|
129
|
+
uint32: "number",
|
|
130
|
+
int64: "number",
|
|
131
|
+
uint64: "number",
|
|
132
|
+
float32: "number",
|
|
133
|
+
float64: "number",
|
|
134
|
+
string: "string",
|
|
135
|
+
unichar: "string",
|
|
136
|
+
pointer: "number",
|
|
137
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ParameterTransfer } from "./parameter.js";
|
|
2
|
+
import { attr, attrBool, type RawNode } from "./parse.js";
|
|
3
|
+
import { type GirTypeRef, typeRefFromSlot } from "./type-ref.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A `<property>` of a class or interface.
|
|
7
|
+
*
|
|
8
|
+
* GIR property names are kebab-case; the writers convert them to camelCase
|
|
9
|
+
* for the JS surface and pass the original GIR name through to
|
|
10
|
+
* `registerConstructionMeta` for `g_object_newv` parameter building.
|
|
11
|
+
*/
|
|
12
|
+
export type GirProperty = {
|
|
13
|
+
/** GIR property name, kebab-case (e.g. `"css-name"`). */
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** Property value type. */
|
|
16
|
+
readonly type: GirTypeRef | undefined;
|
|
17
|
+
readonly writable: boolean;
|
|
18
|
+
readonly construct: boolean;
|
|
19
|
+
readonly constructOnly: boolean;
|
|
20
|
+
readonly transferOwnership: ParameterTransfer;
|
|
21
|
+
/** Optional method name that backs the property's getter (`getter="get_foo"`). */
|
|
22
|
+
readonly getter: string | undefined;
|
|
23
|
+
/** Optional method name that backs the property's setter (`setter="set_foo"`). */
|
|
24
|
+
readonly setter: string | undefined;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Builds a {@link GirProperty} from a `<property>` element.
|
|
29
|
+
*/
|
|
30
|
+
export const propertyFromNode = (node: RawNode): GirProperty => ({
|
|
31
|
+
name: attr(node, "name") ?? "",
|
|
32
|
+
type: typeRefFromSlot(node),
|
|
33
|
+
writable: attrBool(node, "writable"),
|
|
34
|
+
construct: attrBool(node, "construct"),
|
|
35
|
+
constructOnly: attrBool(node, "construct-only"),
|
|
36
|
+
transferOwnership: (attr(node, "transfer-ownership") ?? "none") as ParameterTransfer,
|
|
37
|
+
getter: attr(node, "getter"),
|
|
38
|
+
setter: attr(node, "setter"),
|
|
39
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { GirClass } from "./class.js";
|
|
2
|
+
import type { GirRepository } from "./repository.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Splits a possibly cross-namespace GIR identifier (e.g. `"Gtk.Widget"`) into
|
|
6
|
+
* its namespace and local name.
|
|
7
|
+
*
|
|
8
|
+
* Identifiers without a dot are resolved against `defaultNamespace`. This
|
|
9
|
+
* mirrors the GIR convention where same-namespace references omit the
|
|
10
|
+
* namespace prefix.
|
|
11
|
+
*
|
|
12
|
+
* @param qualified - The GIR identifier as it appears in `<type>` / `parent`
|
|
13
|
+
* @param defaultNamespace - The namespace to assume when no prefix is present
|
|
14
|
+
*/
|
|
15
|
+
export const splitQualifiedName = (
|
|
16
|
+
qualified: string,
|
|
17
|
+
defaultNamespace: string,
|
|
18
|
+
): { readonly namespaceName: string; readonly typeName: string } => {
|
|
19
|
+
const dot = qualified.indexOf(".");
|
|
20
|
+
if (dot === -1) {
|
|
21
|
+
return { namespaceName: defaultNamespace, typeName: qualified };
|
|
22
|
+
}
|
|
23
|
+
return { namespaceName: qualified.slice(0, dot), typeName: qualified.slice(dot + 1) };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A class or interface together with the namespace it was resolved through.
|
|
28
|
+
*/
|
|
29
|
+
export type ResolvedQualifiedClass = {
|
|
30
|
+
readonly klass: GirClass;
|
|
31
|
+
readonly namespaceName: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolves a possibly cross-namespace identifier to its `class` or `interface`
|
|
36
|
+
* entry plus the namespace that declares it.
|
|
37
|
+
*
|
|
38
|
+
* Returns `undefined` when the identifier resolves to a different kind of GIR
|
|
39
|
+
* entity (boxed, enum, …) or cannot be resolved at all.
|
|
40
|
+
*
|
|
41
|
+
* @param repository - The repository to query
|
|
42
|
+
* @param qualified - The GIR identifier (e.g. `"Gtk.Widget"`)
|
|
43
|
+
* @param defaultNamespace - Namespace to assume for unqualified identifiers
|
|
44
|
+
*/
|
|
45
|
+
export const resolveQualifiedClass = (
|
|
46
|
+
repository: GirRepository,
|
|
47
|
+
qualified: string,
|
|
48
|
+
defaultNamespace: string,
|
|
49
|
+
): ResolvedQualifiedClass | undefined => {
|
|
50
|
+
const { namespaceName, typeName } = splitQualifiedName(qualified, defaultNamespace);
|
|
51
|
+
const resolved = repository.resolveNamed(namespaceName, typeName);
|
|
52
|
+
if (resolved === undefined) return undefined;
|
|
53
|
+
if (resolved.kind !== "class" && resolved.kind !== "interface") return undefined;
|
|
54
|
+
return { klass: resolved.value, namespaceName: resolved.namespace.name };
|
|
55
|
+
};
|