@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.
Files changed (340) hide show
  1. package/LICENSE +373 -0
  2. package/dist/dsl/context.d.ts +104 -0
  3. package/dist/dsl/context.d.ts.map +1 -0
  4. package/dist/dsl/context.js +140 -0
  5. package/dist/dsl/context.js.map +1 -0
  6. package/dist/dsl/emit.d.ts +28 -0
  7. package/dist/dsl/emit.d.ts.map +1 -0
  8. package/dist/dsl/emit.js +41 -0
  9. package/dist/dsl/emit.js.map +1 -0
  10. package/dist/dsl/identifier.d.ts +28 -0
  11. package/dist/dsl/identifier.d.ts.map +1 -0
  12. package/dist/dsl/identifier.js +45 -0
  13. package/dist/dsl/identifier.js.map +1 -0
  14. package/dist/dsl/imports.d.ts +58 -0
  15. package/dist/dsl/imports.d.ts.map +1 -0
  16. package/dist/dsl/imports.js +107 -0
  17. package/dist/dsl/imports.js.map +1 -0
  18. package/dist/dsl/module.d.ts +53 -0
  19. package/dist/dsl/module.d.ts.map +1 -0
  20. package/dist/dsl/module.js +76 -0
  21. package/dist/dsl/module.js.map +1 -0
  22. package/dist/ffi/pipeline.d.ts +19 -0
  23. package/dist/ffi/pipeline.d.ts.map +1 -0
  24. package/dist/ffi/pipeline.js +107 -0
  25. package/dist/ffi/pipeline.js.map +1 -0
  26. package/dist/fingerprint.d.ts +30 -0
  27. package/dist/fingerprint.d.ts.map +1 -0
  28. package/dist/fingerprint.js +33 -0
  29. package/dist/fingerprint.js.map +1 -0
  30. package/dist/gi-store.d.ts +34 -0
  31. package/dist/gi-store.d.ts.map +1 -0
  32. package/dist/gi-store.js +154 -0
  33. package/dist/gi-store.js.map +1 -0
  34. package/dist/gir/boxed.d.ts +66 -0
  35. package/dist/gir/boxed.d.ts.map +1 -0
  36. package/dist/gir/boxed.js +49 -0
  37. package/dist/gir/boxed.js.map +1 -0
  38. package/dist/gir/callback.d.ts +15 -0
  39. package/dist/gir/callback.d.ts.map +1 -0
  40. package/dist/gir/callback.js +17 -0
  41. package/dist/gir/callback.js.map +1 -0
  42. package/dist/gir/class.d.ts +49 -0
  43. package/dist/gir/class.d.ts.map +1 -0
  44. package/dist/gir/class.js +42 -0
  45. package/dist/gir/class.js.map +1 -0
  46. package/dist/gir/enum.d.ts +39 -0
  47. package/dist/gir/enum.d.ts.map +1 -0
  48. package/dist/gir/enum.js +24 -0
  49. package/dist/gir/enum.js.map +1 -0
  50. package/dist/gir/field.d.ts +27 -0
  51. package/dist/gir/field.d.ts.map +1 -0
  52. package/dist/gir/field.js +19 -0
  53. package/dist/gir/field.js.map +1 -0
  54. package/dist/gir/function.d.ts +47 -0
  55. package/dist/gir/function.d.ts.map +1 -0
  56. package/dist/gir/function.js +28 -0
  57. package/dist/gir/function.js.map +1 -0
  58. package/dist/gir/namespace.d.ts +65 -0
  59. package/dist/gir/namespace.d.ts.map +1 -0
  60. package/dist/gir/namespace.js +60 -0
  61. package/dist/gir/namespace.js.map +1 -0
  62. package/dist/gir/parameter.d.ts +82 -0
  63. package/dist/gir/parameter.d.ts.map +1 -0
  64. package/dist/gir/parameter.js +66 -0
  65. package/dist/gir/parameter.js.map +1 -0
  66. package/dist/gir/parse.d.ts +78 -0
  67. package/dist/gir/parse.d.ts.map +1 -0
  68. package/dist/gir/parse.js +155 -0
  69. package/dist/gir/parse.js.map +1 -0
  70. package/dist/gir/primitives.d.ts +36 -0
  71. package/dist/gir/primitives.d.ts.map +1 -0
  72. package/dist/gir/primitives.js +109 -0
  73. package/dist/gir/primitives.js.map +1 -0
  74. package/dist/gir/property.d.ts +29 -0
  75. package/dist/gir/property.d.ts.map +1 -0
  76. package/dist/gir/property.js +16 -0
  77. package/dist/gir/property.js.map +1 -0
  78. package/dist/gir/qualified-name.d.ts +37 -0
  79. package/dist/gir/qualified-name.d.ts.map +1 -0
  80. package/dist/gir/qualified-name.js +39 -0
  81. package/dist/gir/qualified-name.js.map +1 -0
  82. package/dist/gir/qualify.d.ts +32 -0
  83. package/dist/gir/qualify.d.ts.map +1 -0
  84. package/dist/gir/qualify.js +60 -0
  85. package/dist/gir/qualify.js.map +1 -0
  86. package/dist/gir/repository.d.ts +82 -0
  87. package/dist/gir/repository.d.ts.map +1 -0
  88. package/dist/gir/repository.js +122 -0
  89. package/dist/gir/repository.js.map +1 -0
  90. package/dist/gir/signal.d.ts +22 -0
  91. package/dist/gir/signal.d.ts.map +1 -0
  92. package/dist/gir/signal.js +20 -0
  93. package/dist/gir/signal.js.map +1 -0
  94. package/dist/gir/size.d.ts +67 -0
  95. package/dist/gir/size.d.ts.map +1 -0
  96. package/dist/gir/size.js +87 -0
  97. package/dist/gir/size.js.map +1 -0
  98. package/dist/gir/type-ref.d.ts +79 -0
  99. package/dist/gir/type-ref.d.ts.map +1 -0
  100. package/dist/gir/type-ref.js +101 -0
  101. package/dist/gir/type-ref.js.map +1 -0
  102. package/dist/index.d.ts +12 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +12 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/jsx-store.d.ts +22 -0
  107. package/dist/jsx-store.d.ts.map +1 -0
  108. package/dist/jsx-store.js +40 -0
  109. package/dist/jsx-store.js.map +1 -0
  110. package/dist/react/compounds-meta.d.ts +18 -0
  111. package/dist/react/compounds-meta.d.ts.map +1 -0
  112. package/dist/react/compounds-meta.js +93 -0
  113. package/dist/react/compounds-meta.js.map +1 -0
  114. package/dist/react/compounds.d.ts +27 -0
  115. package/dist/react/compounds.d.ts.map +1 -0
  116. package/dist/react/compounds.js +164 -0
  117. package/dist/react/compounds.js.map +1 -0
  118. package/dist/react/internal.d.ts +14 -0
  119. package/dist/react/internal.d.ts.map +1 -0
  120. package/dist/react/internal.js +79 -0
  121. package/dist/react/internal.js.map +1 -0
  122. package/dist/react/jsx.d.ts +22 -0
  123. package/dist/react/jsx.d.ts.map +1 -0
  124. package/dist/react/jsx.js +134 -0
  125. package/dist/react/jsx.js.map +1 -0
  126. package/dist/react/pipeline.d.ts +13 -0
  127. package/dist/react/pipeline.d.ts.map +1 -0
  128. package/dist/react/pipeline.js +25 -0
  129. package/dist/react/pipeline.js.map +1 -0
  130. package/dist/react/props.d.ts +38 -0
  131. package/dist/react/props.d.ts.map +1 -0
  132. package/dist/react/props.js +231 -0
  133. package/dist/react/props.js.map +1 -0
  134. package/dist/react/slot-props.d.ts +10 -0
  135. package/dist/react/slot-props.d.ts.map +1 -0
  136. package/dist/react/slot-props.js +56 -0
  137. package/dist/react/slot-props.js.map +1 -0
  138. package/dist/react/widgets.d.ts +83 -0
  139. package/dist/react/widgets.d.ts.map +1 -0
  140. package/dist/react/widgets.js +152 -0
  141. package/dist/react/widgets.js.map +1 -0
  142. package/dist/runner.d.ts +55 -0
  143. package/dist/runner.d.ts.map +1 -0
  144. package/dist/runner.js +60 -0
  145. package/dist/runner.js.map +1 -0
  146. package/dist/store-fs.d.ts +109 -0
  147. package/dist/store-fs.d.ts.map +1 -0
  148. package/dist/store-fs.js +98 -0
  149. package/dist/store-fs.js.map +1 -0
  150. package/dist/transpile.d.ts +32 -0
  151. package/dist/transpile.d.ts.map +1 -0
  152. package/dist/transpile.js +63 -0
  153. package/dist/transpile.js.map +1 -0
  154. package/dist/typecheck-store.d.ts +41 -0
  155. package/dist/typecheck-store.d.ts.map +1 -0
  156. package/dist/typecheck-store.js +102 -0
  157. package/dist/typecheck-store.js.map +1 -0
  158. package/dist/writers/alias.d.ts +13 -0
  159. package/dist/writers/alias.d.ts.map +1 -0
  160. package/dist/writers/alias.js +17 -0
  161. package/dist/writers/alias.js.map +1 -0
  162. package/dist/writers/async.d.ts +22 -0
  163. package/dist/writers/async.d.ts.map +1 -0
  164. package/dist/writers/async.js +48 -0
  165. package/dist/writers/async.js.map +1 -0
  166. package/dist/writers/boxed-constructor.d.ts +26 -0
  167. package/dist/writers/boxed-constructor.d.ts.map +1 -0
  168. package/dist/writers/boxed-constructor.js +85 -0
  169. package/dist/writers/boxed-constructor.js.map +1 -0
  170. package/dist/writers/boxed-field-accessor.d.ts +18 -0
  171. package/dist/writers/boxed-field-accessor.d.ts.map +1 -0
  172. package/dist/writers/boxed-field-accessor.js +260 -0
  173. package/dist/writers/boxed-field-accessor.js.map +1 -0
  174. package/dist/writers/boxed-layout.d.ts +27 -0
  175. package/dist/writers/boxed-layout.d.ts.map +1 -0
  176. package/dist/writers/boxed-layout.js +128 -0
  177. package/dist/writers/boxed-layout.js.map +1 -0
  178. package/dist/writers/boxed.d.ts +20 -0
  179. package/dist/writers/boxed.d.ts.map +1 -0
  180. package/dist/writers/boxed.js +71 -0
  181. package/dist/writers/boxed.js.map +1 -0
  182. package/dist/writers/callables.d.ts +124 -0
  183. package/dist/writers/callables.d.ts.map +1 -0
  184. package/dist/writers/callables.js +283 -0
  185. package/dist/writers/callables.js.map +1 -0
  186. package/dist/writers/callback.d.ts +16 -0
  187. package/dist/writers/callback.d.ts.map +1 -0
  188. package/dist/writers/callback.js +38 -0
  189. package/dist/writers/callback.js.map +1 -0
  190. package/dist/writers/class-struct-record.d.ts +31 -0
  191. package/dist/writers/class-struct-record.d.ts.map +1 -0
  192. package/dist/writers/class-struct-record.js +67 -0
  193. package/dist/writers/class-struct-record.js.map +1 -0
  194. package/dist/writers/class-struct.d.ts +22 -0
  195. package/dist/writers/class-struct.d.ts.map +1 -0
  196. package/dist/writers/class-struct.js +85 -0
  197. package/dist/writers/class-struct.js.map +1 -0
  198. package/dist/writers/class.d.ts +16 -0
  199. package/dist/writers/class.d.ts.map +1 -0
  200. package/dist/writers/class.js +307 -0
  201. package/dist/writers/class.js.map +1 -0
  202. package/dist/writers/constant.d.ts +15 -0
  203. package/dist/writers/constant.d.ts.map +1 -0
  204. package/dist/writers/constant.js +23 -0
  205. package/dist/writers/constant.js.map +1 -0
  206. package/dist/writers/constants.d.ts +15 -0
  207. package/dist/writers/constants.d.ts.map +1 -0
  208. package/dist/writers/constants.js +23 -0
  209. package/dist/writers/constants.js.map +1 -0
  210. package/dist/writers/constructor-props.d.ts +32 -0
  211. package/dist/writers/constructor-props.d.ts.map +1 -0
  212. package/dist/writers/constructor-props.js +110 -0
  213. package/dist/writers/constructor-props.js.map +1 -0
  214. package/dist/writers/enum.d.ts +21 -0
  215. package/dist/writers/enum.d.ts.map +1 -0
  216. package/dist/writers/enum.js +48 -0
  217. package/dist/writers/enum.js.map +1 -0
  218. package/dist/writers/function.d.ts +40 -0
  219. package/dist/writers/function.d.ts.map +1 -0
  220. package/dist/writers/function.js +127 -0
  221. package/dist/writers/function.js.map +1 -0
  222. package/dist/writers/gtype-binding.d.ts +19 -0
  223. package/dist/writers/gtype-binding.d.ts.map +1 -0
  224. package/dist/writers/gtype-binding.js +40 -0
  225. package/dist/writers/gtype-binding.js.map +1 -0
  226. package/dist/writers/inheritance.d.ts +48 -0
  227. package/dist/writers/inheritance.d.ts.map +1 -0
  228. package/dist/writers/inheritance.js +90 -0
  229. package/dist/writers/inheritance.js.map +1 -0
  230. package/dist/writers/interface.d.ts +16 -0
  231. package/dist/writers/interface.d.ts.map +1 -0
  232. package/dist/writers/interface.js +155 -0
  233. package/dist/writers/interface.js.map +1 -0
  234. package/dist/writers/method.d.ts +150 -0
  235. package/dist/writers/method.d.ts.map +1 -0
  236. package/dist/writers/method.js +510 -0
  237. package/dist/writers/method.js.map +1 -0
  238. package/dist/writers/param-classify.d.ts +93 -0
  239. package/dist/writers/param-classify.d.ts.map +1 -0
  240. package/dist/writers/param-classify.js +163 -0
  241. package/dist/writers/param-classify.js.map +1 -0
  242. package/dist/writers/property-accessor.d.ts +19 -0
  243. package/dist/writers/property-accessor.d.ts.map +1 -0
  244. package/dist/writers/property-accessor.js +117 -0
  245. package/dist/writers/property-accessor.js.map +1 -0
  246. package/dist/writers/registration.d.ts +27 -0
  247. package/dist/writers/registration.d.ts.map +1 -0
  248. package/dist/writers/registration.js +30 -0
  249. package/dist/writers/registration.js.map +1 -0
  250. package/dist/writers/return-wrap.d.ts +39 -0
  251. package/dist/writers/return-wrap.d.ts.map +1 -0
  252. package/dist/writers/return-wrap.js +152 -0
  253. package/dist/writers/return-wrap.js.map +1 -0
  254. package/dist/writers/runtime-override.d.ts +18 -0
  255. package/dist/writers/runtime-override.d.ts.map +1 -0
  256. package/dist/writers/runtime-override.js +44 -0
  257. package/dist/writers/runtime-override.js.map +1 -0
  258. package/dist/writers/signal.d.ts +21 -0
  259. package/dist/writers/signal.d.ts.map +1 -0
  260. package/dist/writers/signal.js +260 -0
  261. package/dist/writers/signal.js.map +1 -0
  262. package/dist/writers/ts-type.d.ts +50 -0
  263. package/dist/writers/ts-type.d.ts.map +1 -0
  264. package/dist/writers/ts-type.js +75 -0
  265. package/dist/writers/ts-type.js.map +1 -0
  266. package/dist/writers/types-ts.d.ts +27 -0
  267. package/dist/writers/types-ts.d.ts.map +1 -0
  268. package/dist/writers/types-ts.js +97 -0
  269. package/dist/writers/types-ts.js.map +1 -0
  270. package/dist/writers/value.d.ts +89 -0
  271. package/dist/writers/value.d.ts.map +1 -0
  272. package/dist/writers/value.js +402 -0
  273. package/dist/writers/value.js.map +1 -0
  274. package/package.json +55 -0
  275. package/src/dsl/context.ts +146 -0
  276. package/src/dsl/emit.ts +42 -0
  277. package/src/dsl/identifier.ts +52 -0
  278. package/src/dsl/imports.ts +109 -0
  279. package/src/dsl/module.ts +75 -0
  280. package/src/ffi/pipeline.ts +113 -0
  281. package/src/fingerprint.ts +50 -0
  282. package/src/gi-store.ts +199 -0
  283. package/src/gir/boxed.ts +94 -0
  284. package/src/gir/callback.ts +26 -0
  285. package/src/gir/class.ts +79 -0
  286. package/src/gir/enum.ts +55 -0
  287. package/src/gir/field.ts +40 -0
  288. package/src/gir/function.ts +67 -0
  289. package/src/gir/namespace.ts +118 -0
  290. package/src/gir/parameter.ts +120 -0
  291. package/src/gir/parse.ts +171 -0
  292. package/src/gir/primitives.ts +137 -0
  293. package/src/gir/property.ts +39 -0
  294. package/src/gir/qualified-name.ts +55 -0
  295. package/src/gir/qualify.ts +64 -0
  296. package/src/gir/repository.ts +149 -0
  297. package/src/gir/signal.ts +36 -0
  298. package/src/gir/size.ts +129 -0
  299. package/src/gir/type-ref.ts +180 -0
  300. package/src/index.ts +16 -0
  301. package/src/jsx-store.ts +53 -0
  302. package/src/react/compounds-meta.ts +99 -0
  303. package/src/react/compounds.ts +204 -0
  304. package/src/react/internal.ts +91 -0
  305. package/src/react/jsx.ts +155 -0
  306. package/src/react/pipeline.ts +29 -0
  307. package/src/react/props.ts +307 -0
  308. package/src/react/slot-props.ts +57 -0
  309. package/src/react/widgets.ts +185 -0
  310. package/src/runner.ts +89 -0
  311. package/src/store-fs.ts +157 -0
  312. package/src/transpile.ts +80 -0
  313. package/src/typecheck-store.ts +136 -0
  314. package/src/writers/alias.ts +19 -0
  315. package/src/writers/async.ts +44 -0
  316. package/src/writers/boxed-constructor.ts +105 -0
  317. package/src/writers/boxed-field-accessor.ts +306 -0
  318. package/src/writers/boxed-layout.ts +166 -0
  319. package/src/writers/boxed.ts +77 -0
  320. package/src/writers/callables.ts +339 -0
  321. package/src/writers/callback.ts +40 -0
  322. package/src/writers/class-struct-record.ts +75 -0
  323. package/src/writers/class-struct.ts +96 -0
  324. package/src/writers/class.ts +384 -0
  325. package/src/writers/constant.ts +29 -0
  326. package/src/writers/constructor-props.ts +130 -0
  327. package/src/writers/enum.ts +53 -0
  328. package/src/writers/function.ts +136 -0
  329. package/src/writers/gtype-binding.ts +48 -0
  330. package/src/writers/inheritance.ts +104 -0
  331. package/src/writers/interface.ts +168 -0
  332. package/src/writers/method.ts +678 -0
  333. package/src/writers/param-classify.ts +178 -0
  334. package/src/writers/property-accessor.ts +139 -0
  335. package/src/writers/registration.ts +42 -0
  336. package/src/writers/return-wrap.ts +180 -0
  337. package/src/writers/runtime-override.ts +59 -0
  338. package/src/writers/signal.ts +318 -0
  339. package/src/writers/ts-type.ts +115 -0
  340. package/src/writers/value.ts +485 -0
@@ -0,0 +1,678 @@
1
+ import { toCamelCase } from "@gtkx/utils";
2
+ import type { ModuleContext } from "../dsl/context.js";
3
+ import type { GirFunction } from "../gir/function.js";
4
+ import { type GirParameter, isCallerAllocatedOut, isInoutParameter, isOutParameter } from "../gir/parameter.js";
5
+ import { qualifyTypeRef } from "../gir/qualify.js";
6
+ import type { GirTypeRef, NamedTypeRef, PrimitiveTypeRef } from "../gir/type-ref.js";
7
+ import {
8
+ arrayLengthSources,
9
+ closureAndDestroyIndices,
10
+ inputParameters,
11
+ isCollectibleCallerOut,
12
+ isHandlePassing,
13
+ parameterIdentifier,
14
+ returnArrayLengthIndices,
15
+ } from "./param-classify.js";
16
+ import { handleCast, wrapReturnValue } from "./return-wrap.js";
17
+ import { renderTsType } from "./ts-type.js";
18
+ import { isCellInout, type ResolvedCallback, resolveCallbackType } from "./value.js";
19
+
20
+ /**
21
+ * Returns the camelCased JS export name for a callable's method or static.
22
+ *
23
+ * @param fn - The callable
24
+ */
25
+ export const methodExportName = (fn: GirFunction): string => toCamelCase(fn.name);
26
+
27
+ /**
28
+ * Renders the TypeScript parameter list for a callable.
29
+ *
30
+ * Drops out-only parameters, `<varargs>` slots, and array-length
31
+ * parameters whose value is computed from a sibling array's `.length`.
32
+ * Names follow `toCamelCase` of the GIR name, falling back to
33
+ * `arg<index>` for unnamed positions.
34
+ *
35
+ * @param context - The module context
36
+ * @param fn - The callable
37
+ */
38
+ export const renderMethodSignature = (context: ModuleContext, fn: GirFunction): string =>
39
+ renderInputParameters(
40
+ context,
41
+ fn,
42
+ () => false,
43
+ () => false,
44
+ );
45
+
46
+ const renderInputParameters = (
47
+ context: ModuleContext,
48
+ fn: GirFunction,
49
+ skip: (parameter: GirParameter) => boolean,
50
+ isOptionalExtra: (parameter: GirParameter) => boolean,
51
+ ): string => {
52
+ const parts: string[] = [];
53
+ let sawOptional = false;
54
+ for (const { parameter, index } of inputParameters(fn)) {
55
+ if (skip(parameter)) continue;
56
+ const name = parameterIdentifier(parameter, index);
57
+ if (parameter.optional || isOptionalExtra(parameter)) {
58
+ sawOptional = true;
59
+ }
60
+ const annotation = renderTsType(context, parameter.type, parameter.nullable);
61
+ parts.push(sawOptional ? `${name}?: ${annotation}` : `${name}: ${annotation}`);
62
+ }
63
+ return parts.join(", ");
64
+ };
65
+
66
+ /**
67
+ * Renders the TypeScript return-type annotation for a callable.
68
+ *
69
+ * Multi-out callables tuple the primary return with each out-parameter
70
+ * (`[primary, ...outs]`); when the primary return is void the tuple
71
+ * starts at the first out-parameter.
72
+ *
73
+ * @param context - The module context
74
+ * @param fn - The callable
75
+ */
76
+ export const renderMethodReturnType = (context: ModuleContext, fn: GirFunction): string => {
77
+ const consumedByReturn = returnArrayLengthIndices(fn);
78
+ const outs = fn.parameters.filter(
79
+ (p, index) =>
80
+ (isOutParameter(p) ||
81
+ (isCallerAllocatedOut(p) && isCollectibleCallerOut(context, p)) ||
82
+ isInoutParameter(p)) &&
83
+ !consumedByReturn.has(index),
84
+ );
85
+ const primaryReturnsValue = !isVoidReturn(fn);
86
+ if (outs.length === 0) {
87
+ return primaryReturnsValue ? renderTsType(context, fn.returnValue.type, fn.returnValue.nullable) : "void";
88
+ }
89
+ const outTypes = outs.map((parameter) => renderTsType(context, parameter.type, false));
90
+ if (!primaryReturnsValue) {
91
+ return outTypes.length === 1 ? `${outTypes[0]}` : `[${outTypes.join(", ")}]`;
92
+ }
93
+ const primary = renderTsType(context, fn.returnValue.type, fn.returnValue.nullable);
94
+ return `[${primary}, ${outTypes.join(", ")}]`;
95
+ };
96
+
97
+ const isVoidReturn = (fn: GirFunction): boolean => {
98
+ const ref = fn.returnValue.type;
99
+ if (ref === undefined) return true;
100
+ return ref.kind === "primitive" && ref.category === "void";
101
+ };
102
+
103
+ /**
104
+ * Optional override for the wrapper produced for the primary return value.
105
+ *
106
+ * Constructors use this to force the result to be wrapped as the owning
107
+ * class even when the GIR `<return-value>` is typed as a parent class.
108
+ */
109
+ type ReturnOverride =
110
+ | {
111
+ /**
112
+ * Resolve the wrapper from the value's runtime GLib type, so a
113
+ * constructor that hands back a subclass instance (e.g.
114
+ * `ShortcutTrigger.parseString` returning a `KeyvalTrigger`) keeps
115
+ * its concrete class and identity registration.
116
+ */
117
+ readonly via: "gobject";
118
+ }
119
+ | {
120
+ /** Local interface identifier to fall back to when no registered class conforms. */
121
+ readonly className: string;
122
+ /**
123
+ * Resolve the wrapper from the runtime type, walking to the closest
124
+ * registered ancestor that still implements the interface and falling
125
+ * back to the interface class itself — the path interface-typed values
126
+ * take so a private implementation type still exposes the interface.
127
+ */
128
+ readonly via: "interface";
129
+ }
130
+ | {
131
+ /** Local class identifier to pass as the second argument of `getNativeObject`. */
132
+ readonly className: string;
133
+ /**
134
+ * Wrap as the exact value-type class. Boxed records carry no runtime
135
+ * GObject type instance, so the class must be supplied explicitly.
136
+ */
137
+ readonly via: "boxed";
138
+ };
139
+
140
+ /**
141
+ * Renders the JS body of a promisified `*_async` method that delegates to
142
+ * the runtime's `promisify` helper.
143
+ *
144
+ * The method's leading FFI args (everything before the `GCancellable*`
145
+ * slot) and the cancellable parameter are extracted from the GIR `*_async`
146
+ * signature; the trailing `GAsyncReadyCallback` slot is filled by
147
+ * `promisify`. The `*_finish` companion is bound from the same class via
148
+ * `this[finishName].bind(this)`.
149
+ *
150
+ * @param context - The module context
151
+ * @param asyncFn - The `*_async` callable
152
+ * @param finishMember - The camelCase JS name of the companion `*_finish` method
153
+ * @param bindingExpression - Expression that evaluates to the bound async `t.fn` callable
154
+ */
155
+ export const renderPromisifiedBody = (
156
+ context: ModuleContext,
157
+ asyncFn: GirFunction,
158
+ finishMember: string,
159
+ bindingExpression: string,
160
+ ): string => {
161
+ context.addRuntimeImport("promisify");
162
+ const cancellableIndex = findCancellableIndex(asyncFn.parameters);
163
+ const closureIndices = closureAndDestroyIndices(asyncFn);
164
+ const lengthFor = arrayLengthSources(asyncFn);
165
+ const leadingExpressions: string[] = [];
166
+ if (asyncFn.instance !== undefined) {
167
+ context.addRuntimeImport("getHandle");
168
+ leadingExpressions.push("getHandle(this)");
169
+ }
170
+ let cancellableExpression = "null";
171
+ asyncFn.parameters.forEach((parameter, index) => {
172
+ if (parameter.isVarargs) return;
173
+ if (index === cancellableIndex) {
174
+ cancellableExpression = parameterIdentifier(parameter, index);
175
+ return;
176
+ }
177
+ if (isCallbackParameter(context, parameter)) return;
178
+ if (closureIndices.has(index)) return;
179
+ const sourceIndex = lengthFor.get(index);
180
+ if (sourceIndex !== undefined) {
181
+ const source = asyncFn.parameters[sourceIndex];
182
+ if (source !== undefined) {
183
+ leadingExpressions.push(`${parameterIdentifier(source, sourceIndex)}.length`);
184
+ return;
185
+ }
186
+ }
187
+ leadingExpressions.push(parameterCallExpression(context, parameter, index));
188
+ });
189
+ const leadingLiteral = `[${leadingExpressions.join(", ")}]`;
190
+ return `return promisify(${bindingExpression}, this.${finishMember}.bind(this), ${cancellableExpression}, { leading: ${leadingLiteral} });`;
191
+ };
192
+
193
+ const findCancellableIndex = (parameters: readonly GirParameter[]): number => {
194
+ for (let index = 0; index < parameters.length; index += 1) {
195
+ const parameter = parameters[index];
196
+ if (parameter === undefined) continue;
197
+ if (parameter.type?.kind !== "named") continue;
198
+ if (parameter.type.typeName === "Cancellable") return index;
199
+ }
200
+ return -1;
201
+ };
202
+
203
+ /**
204
+ * Renders the TypeScript signature for a promisified `*_async` method.
205
+ *
206
+ * The signature drops the trailing `GAsyncReadyCallback` and `gpointer
207
+ * user_data` slots, marks the cancellable optional, and returns a
208
+ * `Promise` wrapping the finish method's return type.
209
+ *
210
+ * @param context - The module context
211
+ * @param asyncFn - The `*_async` callable
212
+ * @param finishFn - The companion `*_finish` callable
213
+ */
214
+ export const renderPromisifiedSignature = (
215
+ context: ModuleContext,
216
+ asyncFn: GirFunction,
217
+ finishFn: GirFunction,
218
+ ): { readonly signature: string; readonly returnType: string } => {
219
+ const signature = renderInputParameters(
220
+ context,
221
+ asyncFn,
222
+ (parameter) => isCallbackParameter(context, parameter),
223
+ isCancellable,
224
+ );
225
+ const finishReturn = renderMethodReturnType(context, finishFn);
226
+ return { signature, returnType: `Promise<${finishReturn}>` };
227
+ };
228
+
229
+ const isCancellable = (parameter: GirParameter): boolean =>
230
+ parameter.type?.kind === "named" && parameter.type.typeName === "Cancellable";
231
+
232
+ const isCallbackParameter = (context: ModuleContext, parameter: GirParameter): boolean => {
233
+ const ref = parameter.type;
234
+ if (ref === undefined) return false;
235
+ if (ref.kind === "callback") return true;
236
+ if (ref.kind !== "named") return false;
237
+ const namespaceName = ref.namespaceName ?? context.namespace.name;
238
+ const resolved = context.repository.resolveNamed(namespaceName, ref.typeName);
239
+ return resolved !== undefined && resolved.kind === "callback";
240
+ };
241
+
242
+ /**
243
+ * Renders the JS body of a method or static that dispatches `binding(...)`
244
+ * and returns the appropriately wrapped result.
245
+ *
246
+ * Handles instance vs. static dispatch, optional handle coercion on
247
+ * inbound named-type parameters, out-parameter ref construction with
248
+ * tuple return, `GError` ref + `checkError`, and return-value wrapping
249
+ * via `getNativeObject` / `getNativeObjectAsInterface` for object and
250
+ * boxed results.
251
+ *
252
+ * @param context - The module context
253
+ * @param fn - The callable
254
+ * @param bindingExpression - Expression that evaluates to the bound `t.fn` callable
255
+ * @param isStatic - `true` for static methods, constructors, or namespace functions
256
+ * @param returnAs - Optional override for the primary return wrapping class
257
+ */
258
+ type OutRef = {
259
+ readonly name: string;
260
+ readonly type: GirTypeRef | undefined;
261
+ readonly nullable: boolean;
262
+ readonly raw?: boolean;
263
+ };
264
+
265
+ type BodyBuilder = {
266
+ readonly callArgs: string[];
267
+ readonly setup: string[];
268
+ readonly outRefs: OutRef[];
269
+ };
270
+
271
+ export type WriteMethodBodyOptions = {
272
+ /** Bound `t.fn` callable expression to invoke. */
273
+ readonly bindingExpression: string;
274
+ /** True for static methods, constructors, or namespace functions. */
275
+ readonly isStatic: boolean;
276
+ /** Optional override for the primary return wrapping class. */
277
+ readonly returnAs?: ReturnOverride;
278
+ };
279
+
280
+ export const renderMethodBody = (context: ModuleContext, fn: GirFunction, options: WriteMethodBodyOptions): string => {
281
+ const { bindingExpression, isStatic, returnAs } = options;
282
+ const builder: BodyBuilder = { callArgs: [], setup: [], outRefs: [] };
283
+ if (!isStatic && fn.instance !== undefined) {
284
+ context.addRuntimeImport("getHandle");
285
+ builder.callArgs.push("getHandle(this)");
286
+ }
287
+ collectParameterArgs(context, fn, builder);
288
+ const errorRef = appendErrorRef(fn, builder);
289
+ const callExpression = `${bindingExpression}(${builder.callArgs.join(", ")})`;
290
+ const lines: string[] = [...builder.setup];
291
+ const returnsValue = !isVoidReturn(fn);
292
+ lines.push(returnsValue ? `const __result = ${callExpression};` : `${callExpression};`);
293
+ if (errorRef !== undefined) {
294
+ context.addRuntimeImport("checkError");
295
+ lines.push(`checkError(${errorRef}, ${context.qualify("GLib", "Error")});`);
296
+ }
297
+ const primary = returnsValue ? wrapPrimary(context, fn, "__result", returnAs) : undefined;
298
+ appendReturn(context, lines, primary, builder.outRefs);
299
+ return lines.join("\n");
300
+ };
301
+
302
+ const collectParameterArgs = (context: ModuleContext, fn: GirFunction, builder: BodyBuilder): void => {
303
+ const lengthFor = arrayLengthSources(fn);
304
+ const closureIndices = closureAndDestroyIndices(fn);
305
+ const returnLengthIndices = returnArrayLengthIndices(fn);
306
+ fn.parameters.forEach((parameter, index) => {
307
+ if (parameter.isVarargs) return;
308
+ if (isOutParameter(parameter)) {
309
+ appendOutRef({ context, parameter, index, returnLengthIndices, builder });
310
+ return;
311
+ }
312
+ if (isCallerAllocatedOut(parameter)) {
313
+ appendCallerAllocatedOut(context, parameter, builder);
314
+ return;
315
+ }
316
+ if (isInoutParameter(parameter)) {
317
+ appendInoutParameter({ context, parameter, index, returnLengthIndices, builder });
318
+ return;
319
+ }
320
+ const sourceIndex = lengthFor.get(index);
321
+ if (sourceIndex !== undefined) {
322
+ const source = fn.parameters[sourceIndex];
323
+ if (source !== undefined) {
324
+ builder.callArgs.push(`${parameterIdentifier(source, sourceIndex)}.length`);
325
+ return;
326
+ }
327
+ }
328
+ if (closureIndices.has(index)) {
329
+ return;
330
+ }
331
+ builder.callArgs.push(parameterCallExpression(context, parameter, index));
332
+ });
333
+ };
334
+
335
+ type AppendOutRefOptions = {
336
+ readonly context: ModuleContext;
337
+ readonly parameter: GirParameter;
338
+ readonly index: number;
339
+ readonly returnLengthIndices: ReadonlySet<number>;
340
+ readonly builder: BodyBuilder;
341
+ };
342
+
343
+ const appendOutRef = (options: AppendOutRefOptions): void => {
344
+ const { context, parameter, builder } = options;
345
+ const refName = `out${builder.outRefs.length}`;
346
+ builder.setup.push(`const ${refName}: { value: unknown } = { value: ${outRefInitial(context, parameter.type)} };`);
347
+ registerRefArg(options, refName);
348
+ };
349
+
350
+ /**
351
+ * The initial value seeded into a pure-out `{ value }` ref cell.
352
+ *
353
+ * The native marshaller encodes the cell's current value against the ref's
354
+ * inner FFI type before the call, so the seed must be assignable to that
355
+ * type: numeric and pointer cells seed `0`, booleans `false`, strings `""`,
356
+ * and object/boxed cells `null`.
357
+ */
358
+ const outRefInitial = (context: ModuleContext, ref: GirTypeRef | undefined): string => {
359
+ if (ref === undefined) return "null";
360
+ switch (ref.kind) {
361
+ case "primitive":
362
+ return primitiveInitial(ref.category);
363
+ case "named":
364
+ return namedInitial(context, ref);
365
+ case "array":
366
+ case "list":
367
+ case "hashtable":
368
+ case "callback":
369
+ case "varargs":
370
+ return "null";
371
+ }
372
+ };
373
+
374
+ const primitiveInitial = (category: PrimitiveTypeRef["category"]): string => {
375
+ switch (category) {
376
+ case "boolean":
377
+ return "false";
378
+ case "string":
379
+ return '""';
380
+ case "void":
381
+ return "null";
382
+ default:
383
+ return "0";
384
+ }
385
+ };
386
+
387
+ const namedInitial = (context: ModuleContext, ref: NamedTypeRef): string => {
388
+ const owner = ref.namespaceName ?? context.namespace.name;
389
+ const resolved = context.repository.resolveNamed(owner, ref.typeName);
390
+ if (resolved === undefined) return "null";
391
+ if (resolved.kind === "enum") return "0";
392
+ if (resolved.kind === "alias") {
393
+ const qualified = qualifyTypeRef(resolved.targetRef, resolved.namespace.name);
394
+ return qualified === undefined ? "null" : outRefInitial(context, qualified);
395
+ }
396
+ return "null";
397
+ };
398
+
399
+ const appendInoutRef = (options: AppendOutRefOptions): void => {
400
+ const { context, parameter, index, builder } = options;
401
+ const refName = `inout${builder.outRefs.length}`;
402
+ builder.setup.push(
403
+ `const ${refName}: { value: unknown } = { value: ${parameterCallExpression(context, parameter, index)} };`,
404
+ );
405
+ registerRefArg(options, refName);
406
+ };
407
+
408
+ const appendInoutParameter = (options: AppendOutRefOptions): void => {
409
+ const { context, parameter } = options;
410
+ if (parameter.type !== undefined && isHandlePassing(context, parameter.type)) {
411
+ appendInoutHandle(options);
412
+ } else {
413
+ appendInoutRef(options);
414
+ }
415
+ };
416
+
417
+ const appendInoutHandle = (options: AppendOutRefOptions): void => {
418
+ const { context, parameter, index, returnLengthIndices, builder } = options;
419
+ builder.callArgs.push(parameterCallExpression(context, parameter, index));
420
+ if (!returnLengthIndices.has(index)) {
421
+ builder.outRefs.push({
422
+ name: parameterIdentifier(parameter, index),
423
+ type: parameter.type,
424
+ nullable: parameter.nullable,
425
+ raw: true,
426
+ });
427
+ }
428
+ };
429
+
430
+ const registerRefArg = (options: AppendOutRefOptions, refName: string): void => {
431
+ const { parameter, index, returnLengthIndices, builder } = options;
432
+ builder.callArgs.push(refName);
433
+ if (!returnLengthIndices.has(index)) {
434
+ builder.outRefs.push({ name: refName, type: parameter.type, nullable: parameter.nullable });
435
+ }
436
+ };
437
+
438
+ const appendCallerAllocatedOut = (context: ModuleContext, parameter: GirParameter, builder: BodyBuilder): void => {
439
+ const allocated = allocateCallerOut(context, parameter, builder.outRefs.length);
440
+ if (allocated === undefined) {
441
+ builder.callArgs.push("undefined");
442
+ return;
443
+ }
444
+ builder.setup.push(allocated.setup);
445
+ builder.callArgs.push(allocated.callArg);
446
+ builder.outRefs.push({
447
+ name: allocated.returnExpression,
448
+ type: parameter.type,
449
+ nullable: parameter.nullable,
450
+ raw: true,
451
+ });
452
+ };
453
+
454
+ const appendErrorRef = (fn: GirFunction, builder: BodyBuilder): string | undefined => {
455
+ if (!fn.throws) return undefined;
456
+ const errorRef = "__error";
457
+ builder.setup.push(`const ${errorRef} = { value: null };`);
458
+ builder.callArgs.push(errorRef);
459
+ return errorRef;
460
+ };
461
+
462
+ const appendReturn = (
463
+ context: ModuleContext,
464
+ lines: string[],
465
+ primary: string | undefined,
466
+ outRefs: readonly OutRef[],
467
+ ): void => {
468
+ if (outRefs.length === 0) {
469
+ if (primary !== undefined) lines.push(`return ${primary};`);
470
+ return;
471
+ }
472
+ const outExpressions = outRefs.map((ref) =>
473
+ ref.raw === true
474
+ ? ref.name
475
+ : wrapReturnValue(context, {
476
+ ref: ref.type,
477
+ transfer: "full",
478
+ nullable: false,
479
+ valueExpression: `${ref.name}.value`,
480
+ }),
481
+ );
482
+ if (primary !== undefined) {
483
+ lines.push(`return [${primary}, ${outExpressions.join(", ")}];`);
484
+ return;
485
+ }
486
+ if (outExpressions.length === 1) {
487
+ lines.push(`return ${outExpressions[0]};`);
488
+ return;
489
+ }
490
+ lines.push(`return [${outExpressions.join(", ")}];`);
491
+ };
492
+
493
+ const allocateCallerOut = (
494
+ context: ModuleContext,
495
+ parameter: GirParameter,
496
+ index: number,
497
+ ): { readonly setup: string; readonly callArg: string; readonly returnExpression: string } | undefined => {
498
+ if (parameter.type === undefined || parameter.type.kind !== "named") return undefined;
499
+ if (!isCollectibleCallerOut(context, parameter)) return undefined;
500
+ const owner = parameter.type.namespaceName ?? context.namespace.name;
501
+ const local = `__out${index}`;
502
+ const classExpression = context.qualify(owner, parameter.type.typeName);
503
+ context.addRuntimeImport("getHandle");
504
+ return {
505
+ setup: `const ${local} = new ${classExpression}();`,
506
+ callArg: `getHandle(${local})`,
507
+ returnExpression: local,
508
+ };
509
+ };
510
+
511
+ const parameterCallExpression = (context: ModuleContext, parameter: GirParameter, index: number): string => {
512
+ const name = parameterIdentifier(parameter, index);
513
+ const ref = parameter.type;
514
+ if (ref === undefined) return name;
515
+ const callback = resolveCallbackType(context, ref);
516
+ if (callback !== undefined) return renderCallbackArgument(context, callback, name);
517
+ const nullable = parameter.nullable || parameter.optional;
518
+ if (isHandlePassing(context, ref)) {
519
+ if (nullable) {
520
+ context.addRuntimeImport("tryGetHandle");
521
+ return `tryGetHandle(${name})`;
522
+ }
523
+ context.addRuntimeImport("getHandle");
524
+ return `getHandle(${name})`;
525
+ }
526
+ if ((ref.kind === "array" || ref.kind === "list") && isHandlePassing(context, ref.element)) {
527
+ context.addRuntimeImport("getHandle");
528
+ return nullable ? `${name}?.map((item) => getHandle(item))` : `${name}.map((item) => getHandle(item))`;
529
+ }
530
+ if (ref.kind === "hashtable") {
531
+ if (isHandlePassing(context, ref.value)) {
532
+ context.addRuntimeImport("tryGetHandle");
533
+ return `${name} ? globalThis.Array.from(${name}).map(([k, v]) => [k, tryGetHandle(v)]) : null`;
534
+ }
535
+ return `${name} ? globalThis.Array.from(${name}) : null`;
536
+ }
537
+ return name;
538
+ };
539
+
540
+ /**
541
+ * The marshalling plan for a callback or signal trampoline's incoming
542
+ * arguments: the rendered comma-separated handler call arguments and the
543
+ * trampoline-arg indices of any out-parameter cells.
544
+ */
545
+ export type TrampolineArgPlan = {
546
+ readonly callArgs: string;
547
+ readonly outArgIndices: number[];
548
+ };
549
+
550
+ /**
551
+ * Plans how a callback or signal trampoline forwards its raw arguments to the
552
+ * user handler.
553
+ *
554
+ * In-parameters are wrapped via {@link wrapReturnValue} and joined into the
555
+ * handler call; out-parameters are dropped from the call and their trampoline
556
+ * cell indices collected for write-back. `argOffset` shifts every `args[...]`
557
+ * access: callbacks read from index `0`, while signal trampolines reserve
558
+ * index `0` for the emitting instance and so pass `1`.
559
+ *
560
+ * @param context - The module context
561
+ * @param parameters - The callback or signal parameters, varargs excluded
562
+ * @param namespaceName - The namespace the parameter type references resolve against
563
+ * @param argOffset - Added to each parameter's positional index
564
+ */
565
+ export const planTrampolineArgs = (
566
+ context: ModuleContext,
567
+ parameters: readonly GirParameter[],
568
+ namespaceName: string,
569
+ argOffset: number,
570
+ ): TrampolineArgPlan => {
571
+ const callArgs = parameters
572
+ .map((parameter, index) =>
573
+ isOutParameter(parameter)
574
+ ? undefined
575
+ : wrapReturnValue(context, {
576
+ ref: qualifyTypeRef(parameter.type, namespaceName),
577
+ transfer: parameter.transferOwnership,
578
+ nullable: parameter.nullable,
579
+ valueExpression: isCellInout(context, parameter)
580
+ ? `args[${index + argOffset}].value`
581
+ : `args[${index + argOffset}]`,
582
+ }),
583
+ )
584
+ .filter((expression): expression is string => expression !== undefined)
585
+ .join(", ");
586
+ const outArgIndices = parameters
587
+ .map((parameter, index) =>
588
+ isOutParameter(parameter) || isCellInout(context, parameter) ? index + argOffset : -1,
589
+ )
590
+ .filter((index) => index >= 0);
591
+ return { callArgs, outArgIndices };
592
+ };
593
+
594
+ const renderCallbackArgument = (context: ModuleContext, resolved: ResolvedCallback, name: string): string => {
595
+ const { callback, namespaceName } = resolved;
596
+ const { callArgs, outArgIndices } = planTrampolineArgs(context, callback.parameters, namespaceName, 0);
597
+ const returnRef = qualifyTypeRef(callback.returnValue.type, namespaceName);
598
+ if (outArgIndices.length > 0) {
599
+ const body = renderTupleWriteback(context, `${name}(${callArgs})`, outArgIndices, returnRef);
600
+ return `${name} ? (...args: unknown[]) => {\n ${body}\n} : null`;
601
+ }
602
+ if (returnRef !== undefined && isHandlePassing(context, returnRef)) {
603
+ context.addRuntimeImport("getHandle");
604
+ return `${name} ? (...args: unknown[]) => {\n const _result = ${name}(${callArgs});\n return _result != null ? getHandle(_result) : null;\n} : null`;
605
+ }
606
+ return `${name} ? (...args: unknown[]) => ${name}(${callArgs}) : null`;
607
+ };
608
+
609
+ /**
610
+ * Renders the body of a native→JS callback wrapper that returns out-parameters
611
+ * as a tuple.
612
+ *
613
+ * The wrapped user function returns `[primary, ...outs]` (or the scalar out
614
+ * alone for a void return with a single out, or an out-only tuple otherwise).
615
+ * This emits `const _result = …;`, writes each out value into its `{ value }`
616
+ * cell's `value` slot (`args[i].value = …`), and returns the primary — keeping the
617
+ * tuple convention entirely in generated code so the native layer only flushes
618
+ * cells through their out-pointers. Shared by signal and callback writers.
619
+ *
620
+ * @param context - The module context
621
+ * @param callExpression - The expression that invokes the user function
622
+ * @param outArgIndices - Argument indices of the out-parameter cells
623
+ * @param returnRef - The primary return type, or `undefined` for void
624
+ */
625
+ export const renderTupleWriteback = (
626
+ context: ModuleContext,
627
+ callExpression: string,
628
+ outArgIndices: readonly number[],
629
+ returnRef: GirTypeRef | undefined,
630
+ ): string => {
631
+ const lines = [`const _result = ${callExpression};`];
632
+ const isVoid = returnRef === undefined || (returnRef.kind === "primitive" && returnRef.category === "void");
633
+ if (!isVoid) {
634
+ outArgIndices.forEach((argIndex, position) => {
635
+ lines.push(`args[${argIndex}].value = _result[${position + 1}];`);
636
+ });
637
+ if (returnRef !== undefined && isHandlePassing(context, returnRef)) {
638
+ context.addRuntimeImport("tryGetHandle");
639
+ lines.push("return tryGetHandle(_result[0]);");
640
+ } else {
641
+ lines.push("return _result[0];");
642
+ }
643
+ } else if (outArgIndices.length === 1) {
644
+ lines.push(`args[${outArgIndices[0]}].value = _result;`);
645
+ } else {
646
+ outArgIndices.forEach((argIndex, position) => {
647
+ lines.push(`args[${argIndex}].value = _result[${position}];`);
648
+ });
649
+ }
650
+ return lines.join("\n ");
651
+ };
652
+
653
+ const wrapPrimary = (
654
+ context: ModuleContext,
655
+ fn: GirFunction,
656
+ valueExpression: string,
657
+ returnAs: ReturnOverride | undefined,
658
+ ): string => {
659
+ if (returnAs !== undefined) {
660
+ const handle = handleCast(context, valueExpression, false);
661
+ if (returnAs.via === "gobject") {
662
+ context.addRuntimeImport("getNativeObject");
663
+ return `getNativeObject(${handle})`;
664
+ }
665
+ if (returnAs.via === "boxed") {
666
+ context.addRuntimeImport("getNativeObject");
667
+ return `getNativeObject(${handle}, ${returnAs.className})`;
668
+ }
669
+ context.addRuntimeImport("getNativeObjectAsInterface");
670
+ return `getNativeObjectAsInterface(${handle}, ${returnAs.className})`;
671
+ }
672
+ return wrapReturnValue(context, {
673
+ ref: fn.returnValue.type,
674
+ transfer: fn.returnValue.transferOwnership,
675
+ nullable: fn.returnValue.nullable,
676
+ valueExpression,
677
+ });
678
+ };