@gtkx/codegen 1.0.0 → 1.1.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 (316) hide show
  1. package/README.md +1 -1
  2. package/dist/analysis/descriptor-render.d.ts +12 -15
  3. package/dist/analysis/descriptor-render.d.ts.map +1 -1
  4. package/dist/analysis/descriptor-render.js +48 -31
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +16 -7
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +15 -3
  9. package/dist/analysis/descriptor.js.map +1 -1
  10. package/dist/analysis/inheritance.d.ts +4 -2
  11. package/dist/analysis/inheritance.d.ts.map +1 -1
  12. package/dist/analysis/inheritance.js +80 -38
  13. package/dist/analysis/inheritance.js.map +1 -1
  14. package/dist/analysis/interface-conflicts.d.ts +23 -0
  15. package/dist/analysis/interface-conflicts.d.ts.map +1 -0
  16. package/dist/analysis/interface-conflicts.js +144 -0
  17. package/dist/analysis/interface-conflicts.js.map +1 -0
  18. package/dist/analysis/param-capability.d.ts.map +1 -1
  19. package/dist/analysis/param-capability.js +3 -4
  20. package/dist/analysis/param-capability.js.map +1 -1
  21. package/dist/analysis/param-structure.js +2 -2
  22. package/dist/analysis/param-structure.js.map +1 -1
  23. package/dist/analysis/ts-type.d.ts.map +1 -1
  24. package/dist/analysis/ts-type.js +10 -17
  25. package/dist/analysis/ts-type.js.map +1 -1
  26. package/dist/analysis/type-key.d.ts +5 -0
  27. package/dist/analysis/type-key.d.ts.map +1 -0
  28. package/dist/analysis/type-key.js +9 -0
  29. package/dist/analysis/type-key.js.map +1 -0
  30. package/dist/compile.d.ts +12 -3
  31. package/dist/compile.d.ts.map +1 -1
  32. package/dist/compile.js +73 -24
  33. package/dist/compile.js.map +1 -1
  34. package/dist/docs/api-reference.d.ts.map +1 -1
  35. package/dist/docs/api-reference.js +10 -9
  36. package/dist/docs/api-reference.js.map +1 -1
  37. package/dist/docs/element-page.d.ts.map +1 -1
  38. package/dist/docs/element-page.js +5 -3
  39. package/dist/docs/element-page.js.map +1 -1
  40. package/dist/docs/pipeline.d.ts.map +1 -1
  41. package/dist/docs/pipeline.js +85 -18
  42. package/dist/docs/pipeline.js.map +1 -1
  43. package/dist/docs/render.d.ts +2 -1
  44. package/dist/docs/render.d.ts.map +1 -1
  45. package/dist/docs/render.js +5 -4
  46. package/dist/docs/render.js.map +1 -1
  47. package/dist/docs/symbol-page.d.ts.map +1 -1
  48. package/dist/docs/symbol-page.js +9 -6
  49. package/dist/docs/symbol-page.js.map +1 -1
  50. package/dist/fingerprint.d.ts +12 -1
  51. package/dist/fingerprint.d.ts.map +1 -1
  52. package/dist/fingerprint.js +44 -28
  53. package/dist/fingerprint.js.map +1 -1
  54. package/dist/gi.d.ts.map +1 -1
  55. package/dist/gi.js +1 -0
  56. package/dist/gi.js.map +1 -1
  57. package/dist/gir/ancestry.d.ts +7 -1
  58. package/dist/gir/ancestry.d.ts.map +1 -1
  59. package/dist/gir/ancestry.js +9 -1
  60. package/dist/gir/ancestry.js.map +1 -1
  61. package/dist/gir/annotations.d.ts +1 -2
  62. package/dist/gir/annotations.d.ts.map +1 -1
  63. package/dist/gir/annotations.js +1 -1
  64. package/dist/gir/annotations.js.map +1 -1
  65. package/dist/gir/cursor-overrides.d.ts +8 -0
  66. package/dist/gir/cursor-overrides.d.ts.map +1 -0
  67. package/dist/gir/cursor-overrides.js +6 -0
  68. package/dist/gir/cursor-overrides.js.map +1 -0
  69. package/dist/gir/emittable.d.ts +7 -0
  70. package/dist/gir/emittable.d.ts.map +1 -0
  71. package/dist/gir/emittable.js +3 -0
  72. package/dist/gir/emittable.js.map +1 -0
  73. package/dist/gir/function.d.ts.map +1 -1
  74. package/dist/gir/function.js +28 -2
  75. package/dist/gir/function.js.map +1 -1
  76. package/dist/gir/library.js +1 -1
  77. package/dist/gir/library.js.map +1 -1
  78. package/dist/gir/namespace.d.ts +5 -1
  79. package/dist/gir/namespace.d.ts.map +1 -1
  80. package/dist/gir/namespace.js +4 -2
  81. package/dist/gir/namespace.js.map +1 -1
  82. package/dist/gir/parameter.d.ts +13 -1
  83. package/dist/gir/parameter.d.ts.map +1 -1
  84. package/dist/gir/parameter.js +1 -0
  85. package/dist/gir/parameter.js.map +1 -1
  86. package/dist/gir/parse.d.ts.map +1 -1
  87. package/dist/gir/parse.js +3 -6
  88. package/dist/gir/parse.js.map +1 -1
  89. package/dist/guards.d.ts +16 -0
  90. package/dist/guards.d.ts.map +1 -0
  91. package/dist/guards.js +11 -0
  92. package/dist/guards.js.map +1 -0
  93. package/dist/internal.d.ts +2 -0
  94. package/dist/internal.d.ts.map +1 -1
  95. package/dist/internal.js +2 -0
  96. package/dist/internal.js.map +1 -1
  97. package/dist/json.d.ts +3 -0
  98. package/dist/json.d.ts.map +1 -0
  99. package/dist/json.js +11 -0
  100. package/dist/json.js.map +1 -0
  101. package/dist/khronos/modules.d.ts.map +1 -1
  102. package/dist/khronos/modules.js +22 -7
  103. package/dist/khronos/modules.js.map +1 -1
  104. package/dist/khronos/parse.d.ts.map +1 -1
  105. package/dist/khronos/parse.js +3 -4
  106. package/dist/khronos/parse.js.map +1 -1
  107. package/dist/khronos/pipeline.d.ts +1 -1
  108. package/dist/khronos/pipeline.d.ts.map +1 -1
  109. package/dist/khronos/pipeline.js.map +1 -1
  110. package/dist/khronos/plan.d.ts +1 -7
  111. package/dist/khronos/plan.d.ts.map +1 -1
  112. package/dist/khronos/plan.js +1 -1
  113. package/dist/khronos/plan.js.map +1 -1
  114. package/dist/runner.d.ts +5 -1
  115. package/dist/runner.d.ts.map +1 -1
  116. package/dist/runner.js +16 -0
  117. package/dist/runner.js.map +1 -1
  118. package/dist/staging.d.ts +5 -0
  119. package/dist/staging.d.ts.map +1 -0
  120. package/dist/staging.js +57 -0
  121. package/dist/staging.js.map +1 -0
  122. package/dist/store/compile-store.d.ts.map +1 -1
  123. package/dist/store/compile-store.js +4 -2
  124. package/dist/store/compile-store.js.map +1 -1
  125. package/dist/store/gi/callables.d.ts +7 -2
  126. package/dist/store/gi/callables.d.ts.map +1 -1
  127. package/dist/store/gi/callables.js +25 -30
  128. package/dist/store/gi/callables.js.map +1 -1
  129. package/dist/store/gi/callback.d.ts.map +1 -1
  130. package/dist/store/gi/callback.js +9 -5
  131. package/dist/store/gi/callback.js.map +1 -1
  132. package/dist/store/gi/class.d.ts.map +1 -1
  133. package/dist/store/gi/class.js +59 -38
  134. package/dist/store/gi/class.js.map +1 -1
  135. package/dist/store/gi/companion.d.ts.map +1 -1
  136. package/dist/store/gi/companion.js +6 -6
  137. package/dist/store/gi/companion.js.map +1 -1
  138. package/dist/store/gi/constant.d.ts.map +1 -1
  139. package/dist/store/gi/constant.js +10 -2
  140. package/dist/store/gi/constant.js.map +1 -1
  141. package/dist/store/gi/constructor-props.js +1 -1
  142. package/dist/store/gi/constructor-props.js.map +1 -1
  143. package/dist/store/gi/enum.d.ts.map +1 -1
  144. package/dist/store/gi/enum.js +28 -8
  145. package/dist/store/gi/enum.js.map +1 -1
  146. package/dist/store/gi/function.d.ts +1 -3
  147. package/dist/store/gi/function.d.ts.map +1 -1
  148. package/dist/store/gi/function.js +24 -18
  149. package/dist/store/gi/function.js.map +1 -1
  150. package/dist/store/gi/gtype-binding.d.ts.map +1 -1
  151. package/dist/store/gi/gtype-binding.js +4 -1
  152. package/dist/store/gi/gtype-binding.js.map +1 -1
  153. package/dist/store/gi/interface.d.ts.map +1 -1
  154. package/dist/store/gi/interface.js +32 -17
  155. package/dist/store/gi/interface.js.map +1 -1
  156. package/dist/store/gi/method.d.ts +7 -6
  157. package/dist/store/gi/method.d.ts.map +1 -1
  158. package/dist/store/gi/method.js +13 -21
  159. package/dist/store/gi/method.js.map +1 -1
  160. package/dist/store/gi/param-marshal.d.ts +3 -2
  161. package/dist/store/gi/param-marshal.d.ts.map +1 -1
  162. package/dist/store/gi/param-marshal.js +50 -5
  163. package/dist/store/gi/param-marshal.js.map +1 -1
  164. package/dist/store/gi/pipeline.d.ts.map +1 -1
  165. package/dist/store/gi/pipeline.js +21 -10
  166. package/dist/store/gi/pipeline.js.map +1 -1
  167. package/dist/store/gi/properties.d.ts +2 -1
  168. package/dist/store/gi/properties.d.ts.map +1 -1
  169. package/dist/store/gi/properties.js +6 -3
  170. package/dist/store/gi/properties.js.map +1 -1
  171. package/dist/store/gi/property-accessor.d.ts +10 -5
  172. package/dist/store/gi/property-accessor.d.ts.map +1 -1
  173. package/dist/store/gi/property-accessor.js +95 -44
  174. package/dist/store/gi/property-accessor.js.map +1 -1
  175. package/dist/store/gi/record-constructor.d.ts +8 -1
  176. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  177. package/dist/store/gi/record-constructor.js +31 -10
  178. package/dist/store/gi/record-constructor.js.map +1 -1
  179. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  180. package/dist/store/gi/record-field-accessor.js +5 -1
  181. package/dist/store/gi/record-field-accessor.js.map +1 -1
  182. package/dist/store/gi/record-layout.d.ts +6 -1
  183. package/dist/store/gi/record-layout.d.ts.map +1 -1
  184. package/dist/store/gi/record-layout.js +8 -1
  185. package/dist/store/gi/record-layout.js.map +1 -1
  186. package/dist/store/gi/record.d.ts.map +1 -1
  187. package/dist/store/gi/record.js +19 -8
  188. package/dist/store/gi/record.js.map +1 -1
  189. package/dist/store/gi/registration.js +2 -2
  190. package/dist/store/gi/registration.js.map +1 -1
  191. package/dist/store/gi/signal.d.ts +2 -1
  192. package/dist/store/gi/signal.d.ts.map +1 -1
  193. package/dist/store/gi/signal.js +30 -24
  194. package/dist/store/gi/signal.js.map +1 -1
  195. package/dist/store/gi/value-marshalable.d.ts.map +1 -1
  196. package/dist/store/gi/value-marshalable.js +2 -1
  197. package/dist/store/gi/value-marshalable.js.map +1 -1
  198. package/dist/store/gi/vtable.d.ts +4 -1
  199. package/dist/store/gi/vtable.d.ts.map +1 -1
  200. package/dist/store/gi/vtable.js +60 -17
  201. package/dist/store/gi/vtable.js.map +1 -1
  202. package/dist/store/gi-store.d.ts +1 -0
  203. package/dist/store/gi-store.d.ts.map +1 -1
  204. package/dist/store/gi-store.js +15 -20
  205. package/dist/store/gi-store.js.map +1 -1
  206. package/dist/store/jsx/generated-elements.d.ts +2 -1
  207. package/dist/store/jsx/generated-elements.d.ts.map +1 -1
  208. package/dist/store/jsx/generated-elements.js +13 -7
  209. package/dist/store/jsx/generated-elements.js.map +1 -1
  210. package/dist/store/jsx/jsx.js +3 -3
  211. package/dist/store/jsx/jsx.js.map +1 -1
  212. package/dist/store/jsx/metadata.d.ts.map +1 -1
  213. package/dist/store/jsx/metadata.js +3 -1
  214. package/dist/store/jsx/metadata.js.map +1 -1
  215. package/dist/store/jsx-store.d.ts.map +1 -1
  216. package/dist/store/jsx-store.js +3 -3
  217. package/dist/store/jsx-store.js.map +1 -1
  218. package/dist/store/resolve-store.d.ts +14 -3
  219. package/dist/store/resolve-store.d.ts.map +1 -1
  220. package/dist/store/resolve-store.js +98 -15
  221. package/dist/store/resolve-store.js.map +1 -1
  222. package/dist/store/store-fs.d.ts +9 -6
  223. package/dist/store/store-fs.d.ts.map +1 -1
  224. package/dist/store/store-fs.js +59 -25
  225. package/dist/store/store-fs.js.map +1 -1
  226. package/dist/store/store-links.d.ts +3 -0
  227. package/dist/store/store-links.d.ts.map +1 -0
  228. package/dist/store/store-links.js +39 -0
  229. package/dist/store/store-links.js.map +1 -0
  230. package/dist/writer/comparison-context.d.ts +4 -0
  231. package/dist/writer/comparison-context.d.ts.map +1 -0
  232. package/dist/writer/comparison-context.js +13 -0
  233. package/dist/writer/comparison-context.js.map +1 -0
  234. package/dist/writer/context.d.ts +3 -3
  235. package/dist/writer/context.d.ts.map +1 -1
  236. package/dist/writer/context.js +11 -6
  237. package/dist/writer/context.js.map +1 -1
  238. package/dist/writer/module.d.ts +13 -5
  239. package/dist/writer/module.d.ts.map +1 -1
  240. package/dist/writer/module.js +68 -11
  241. package/dist/writer/module.js.map +1 -1
  242. package/dist/xml.d.ts +7 -1
  243. package/dist/xml.d.ts.map +1 -1
  244. package/dist/xml.js +43 -1
  245. package/dist/xml.js.map +1 -1
  246. package/package.json +14 -3
  247. package/src/analysis/descriptor-render.ts +90 -45
  248. package/src/analysis/descriptor.ts +35 -8
  249. package/src/analysis/inheritance.ts +134 -44
  250. package/src/analysis/interface-conflicts.ts +237 -0
  251. package/src/analysis/param-capability.ts +3 -6
  252. package/src/analysis/param-structure.ts +2 -2
  253. package/src/analysis/ts-type.ts +13 -17
  254. package/src/analysis/type-key.ts +14 -0
  255. package/src/compile.ts +110 -26
  256. package/src/docs/api-reference.ts +10 -9
  257. package/src/docs/element-page.ts +5 -2
  258. package/src/docs/pipeline.ts +129 -19
  259. package/src/docs/render.ts +7 -3
  260. package/src/docs/symbol-page.ts +12 -7
  261. package/src/fingerprint.ts +86 -31
  262. package/src/gi.ts +1 -0
  263. package/src/gir/ancestry.ts +17 -1
  264. package/src/gir/annotations.ts +1 -1
  265. package/src/gir/cursor-overrides.ts +12 -0
  266. package/src/gir/emittable.ts +8 -0
  267. package/src/gir/function.ts +45 -9
  268. package/src/gir/library.ts +1 -1
  269. package/src/gir/namespace.ts +8 -2
  270. package/src/gir/parameter.ts +15 -0
  271. package/src/gir/parse.ts +5 -7
  272. package/src/guards.ts +23 -0
  273. package/src/internal.ts +2 -0
  274. package/src/json.ts +11 -0
  275. package/src/khronos/modules.ts +25 -9
  276. package/src/khronos/parse.ts +3 -4
  277. package/src/khronos/pipeline.ts +1 -1
  278. package/src/khronos/plan.ts +0 -1
  279. package/src/runner.ts +19 -1
  280. package/src/staging.ts +69 -0
  281. package/src/store/compile-store.ts +6 -4
  282. package/src/store/gi/callables.ts +41 -33
  283. package/src/store/gi/callback.ts +9 -9
  284. package/src/store/gi/class.ts +79 -48
  285. package/src/store/gi/companion.ts +7 -6
  286. package/src/store/gi/constant.ts +12 -2
  287. package/src/store/gi/constructor-props.ts +1 -1
  288. package/src/store/gi/enum.ts +35 -21
  289. package/src/store/gi/function.ts +30 -24
  290. package/src/store/gi/gtype-binding.ts +7 -2
  291. package/src/store/gi/interface.ts +37 -18
  292. package/src/store/gi/method.ts +28 -29
  293. package/src/store/gi/param-marshal.ts +77 -6
  294. package/src/store/gi/pipeline.ts +25 -15
  295. package/src/store/gi/properties.ts +8 -4
  296. package/src/store/gi/property-accessor.ts +156 -73
  297. package/src/store/gi/record-constructor.ts +50 -18
  298. package/src/store/gi/record-field-accessor.ts +8 -1
  299. package/src/store/gi/record-layout.ts +11 -1
  300. package/src/store/gi/record.ts +20 -12
  301. package/src/store/gi/registration.ts +2 -2
  302. package/src/store/gi/signal.ts +36 -38
  303. package/src/store/gi/value-marshalable.ts +3 -1
  304. package/src/store/gi/vtable.ts +97 -20
  305. package/src/store/gi-store.ts +26 -31
  306. package/src/store/jsx/generated-elements.ts +17 -8
  307. package/src/store/jsx/jsx.ts +3 -3
  308. package/src/store/jsx/metadata.ts +4 -1
  309. package/src/store/jsx-store.ts +3 -3
  310. package/src/store/resolve-store.ts +133 -18
  311. package/src/store/store-fs.ts +87 -34
  312. package/src/store/store-links.ts +49 -0
  313. package/src/writer/comparison-context.ts +18 -0
  314. package/src/writer/context.ts +12 -6
  315. package/src/writer/module.ts +101 -14
  316. package/src/xml.ts +61 -1
@@ -1,4 +1,5 @@
1
1
  import { sourceStringLiteral } from "@gtkx/utils";
2
+ import type { GirCursorBounds } from "../gir/parameter.js";
2
3
  import { joinArgs } from "../writer/emit.js";
3
4
 
4
5
  type Ownership = "borrowed" | "full";
@@ -39,6 +40,7 @@ type DescriptorName =
39
40
  "byteArray" |
40
41
  "sizedArray" |
41
42
  "fixedArray" |
43
+ "cursorArray" |
42
44
  "callback" |
43
45
  "fn";
44
46
 
@@ -92,6 +94,21 @@ type BindArgs = {
92
94
  returnType: string;
93
95
  };
94
96
 
97
+ type FnSpecParts = {
98
+ args: string;
99
+ returns: string;
100
+ isReturnSkipped: boolean;
101
+ canThrow: boolean;
102
+ };
103
+
104
+ type CallbackSpecParts = {
105
+ argTypes: string[];
106
+ returns: string;
107
+ options: string[];
108
+ };
109
+
110
+ const SKIPPED_RETURN_ENTRY = "isReturnSkipped: true";
111
+
95
112
  const T: DescriptorNames = {
96
113
  bind: "t.bind",
97
114
  int8: "t.int8",
@@ -128,6 +145,7 @@ const T: DescriptorNames = {
128
145
  byteArray: "t.byteArray",
129
146
  sizedArray: "t.sizedArray",
130
147
  fixedArray: "t.fixedArray",
148
+ cursorArray: "t.cursorArray",
131
149
  callback: "t.callback",
132
150
  fn: "t.fn",
133
151
  };
@@ -235,6 +253,14 @@ const tSizedArray = (
235
253
  elementSize === undefined ? undefined : String(elementSize),
236
254
  ]);
237
255
 
256
+ const tCursorArray = (element: string, bounds: GirCursorBounds, ownership?: Ownership, elementSize?: number): string =>
257
+ call("cursorArray", [
258
+ element,
259
+ `{ baseParamIndex: ${String(bounds.baseIndex)}, sizeParamIndex: ${String(bounds.lengthIndex)} }`,
260
+ ownership === undefined ? undefined : sourceStringLiteral(ownership),
261
+ elementSize === undefined ? undefined : String(elementSize),
262
+ ]);
263
+
238
264
  const tFixedArray = (element: string, length: number, ownership?: Ownership, elementSize?: number): string =>
239
265
  call("fixedArray", [
240
266
  element,
@@ -243,23 +269,23 @@ const tFixedArray = (element: string, length: number, ownership?: Ownership, ele
243
269
  elementSize === undefined ? undefined : String(elementSize),
244
270
  ]);
245
271
 
246
- const tCallback = (argTypes: string[], returnType: string, options?: string): string =>
247
- call("callback", [`[${argTypes.join(", ")}]`, returnType, options]);
272
+ const tCallback = (spec: CallbackSpecParts): string => {
273
+ const optionsArg = spec.options.length > 0 ? `{ ${spec.options.join(", ")} }` : undefined;
274
+
275
+ return call("callback", [`[${spec.argTypes.join(", ")}]`, spec.returns, optionsArg]);
276
+ };
248
277
 
249
278
  const tBind = (args: BindArgs): string =>
250
279
  call("bind", [args.libExpr, args.symbolExpr, args.argList, args.returnType]);
251
280
 
252
- const tFn = (
253
- lib: string,
254
- cIdentifier: string,
255
- spec: { args: string; returns: string; canThrow: boolean },
256
- ): string => {
281
+ const tFn = (lib: string, cIdentifier: string, spec: FnSpecParts): string => {
282
+ const skipEntry = spec.isReturnSkipped ? `, ${SKIPPED_RETURN_ENTRY}` : "";
257
283
  const throwsEntry = spec.canThrow ? ", canThrow: true" : "";
258
284
 
259
285
  return call("fn", [
260
286
  sourceStringLiteral(lib),
261
287
  sourceStringLiteral(cIdentifier),
262
- `{ args: ${spec.args}, returns: ${spec.returns}${throwsEntry} }`,
288
+ `{ args: ${spec.args}, returns: ${spec.returns}${skipEntry}${throwsEntry} }`,
263
289
  ]);
264
290
  };
265
291
 
@@ -288,6 +314,7 @@ export {
288
314
  tArray,
289
315
  tSizedArray,
290
316
  tFixedArray,
317
+ tCursorArray,
291
318
  tCallback,
292
319
  tBind,
293
320
  tFn,
@@ -1,14 +1,17 @@
1
- import { camelCase, lowerFirst, pascalCase, toCamelIdentifier } from "@gtkx/utils";
1
+ import { lowerFirst, pascalCase, sanitizeTypeIdentifier, toCamelIdentifier } from "@gtkx/utils";
2
2
  import type { GirClass } from "../gir/class.js";
3
3
  import type { GirFunction } from "../gir/function.js";
4
4
  import type { Library } from "../gir/library.js";
5
+ import type { GirParameter } from "../gir/parameter.js";
5
6
  import type { GirProperty } from "../gir/property.js";
6
7
  import type { TypeId } from "../gir/type-id.js";
7
8
  import type { ModuleContext } from "../writer/context.js";
8
9
  import { ancestorChain, type ResolvedAncestor, resolveInterfaces } from "../gir/ancestry.js";
9
- import { methodExportName } from "../store/gi/method.js";
10
- import { resolveAccessorType } from "../store/gi/property-accessor.js";
10
+ import { isEmittableEntity } from "../gir/emittable.js";
11
+ import { memberName, methodExportName } from "../store/gi/method.js";
12
+ import { type InheritedAccessorTypes, resolveAccessorTypes } from "../store/gi/property-accessor.js";
11
13
  import { vfuncMemberNames } from "../store/gi/vtable.js";
14
+ import { comparisonContextFor } from "../writer/comparison-context.js";
12
15
  import { inputParameters } from "./param-structure.js";
13
16
  import { renderTsType } from "./ts-type.js";
14
17
 
@@ -18,6 +21,8 @@ type AncestryContext = {
18
21
  };
19
22
 
20
23
  type OwnedProperty = { owner: GirClass; property: GirProperty };
24
+ type DeclaredAccessorType = { type: string; owner: string };
25
+ type DeclaredAccessorTypes = { read: DeclaredAccessorType | undefined; write: DeclaredAccessorType | undefined };
21
26
  type MethodSignature = { returnType: string; arity: number };
22
27
 
23
28
  type InheritedMethod = {
@@ -30,6 +35,11 @@ type InheritedMethods = {
30
35
  definitions: Map<string, InheritedMethod>;
31
36
  };
32
37
 
38
+ type ParameterPair = {
39
+ own: GirParameter;
40
+ inherited: GirParameter;
41
+ };
42
+
33
43
  type InheritedMatch = {
34
44
  inheritedReturn: string;
35
45
  inheritedMethod: InheritedMethod;
@@ -63,7 +73,11 @@ const resolvePrerequisiteReference = (context: ModuleContext, name: string): str
63
73
  return undefined;
64
74
  }
65
75
 
66
- return context.qualify(resolved.namespace.name, pascalCase(resolved.value.name));
76
+ if (!isEmittableEntity(resolved.value)) {
77
+ return undefined;
78
+ }
79
+
80
+ return context.qualify(resolved.namespace.name, sanitizeTypeIdentifier(resolved.value.name));
67
81
  };
68
82
 
69
83
  const forEachAncestor = (
@@ -99,7 +113,7 @@ const visitInterfaceProperties = (
99
113
  }
100
114
  };
101
115
 
102
- const forEachInheritedProperty = (
116
+ const forEachAncestorProperty = (
103
117
  context: ModuleContext,
104
118
  klass: GirClass,
105
119
  visit: (owner: GirClass, property: GirProperty) => void,
@@ -113,6 +127,15 @@ const forEachInheritedProperty = (
113
127
  });
114
128
  };
115
129
 
130
+ const forEachInheritedProperty = (
131
+ context: ModuleContext,
132
+ klass: GirClass,
133
+ visit: (owner: GirClass, property: GirProperty) => void,
134
+ ): void => {
135
+ visitInterfaceProperties(resolveDirectInterfaces(context, klass, context.namespace.name), visit);
136
+ forEachAncestorProperty(context, klass, visit);
137
+ };
138
+
116
139
  const collectSeenPropertyNames = (context: ModuleContext, klass: GirClass): Set<string> => {
117
140
  const seen: Set<string> = new Set();
118
141
 
@@ -120,7 +143,7 @@ const collectSeenPropertyNames = (context: ModuleContext, klass: GirClass): Set<
120
143
  seen.add(toCamelIdentifier(property.name));
121
144
  }
122
145
 
123
- forEachInheritedProperty(context, klass, (_owner, property) => seen.add(toCamelIdentifier(property.name)));
146
+ forEachAncestorProperty(context, klass, (_owner, property) => seen.add(toCamelIdentifier(property.name)));
124
147
 
125
148
  return seen;
126
149
  };
@@ -159,7 +182,7 @@ const recordAncestorSignatures = (
159
182
  signatures: Map<string, MethodSignature>,
160
183
  ): void => {
161
184
  for (const method of klass.methods) {
162
- const name = camelCase(method.name);
185
+ const name = memberName(method.name);
163
186
 
164
187
  if (!method.introspectable || signatures.has(name)) {
165
188
  continue;
@@ -182,6 +205,9 @@ const ancestorClassMethodSignatures = (context: ModuleContext, klass: GirClass):
182
205
  return signatures;
183
206
  };
184
207
 
208
+ const ancestorClassMethodNames = (context: ModuleContext, klass: GirClass): Set<string> =>
209
+ new Set(ancestorClassMethodSignatures(context, klass).keys());
210
+
185
211
  const mergeOmissionName = (
186
212
  context: ModuleContext,
187
213
  method: GirFunction,
@@ -191,7 +217,7 @@ const mergeOmissionName = (
191
217
  return undefined;
192
218
  }
193
219
 
194
- const name = camelCase(method.name);
220
+ const name = memberName(method.name);
195
221
  const ancestor = ancestors.get(name);
196
222
 
197
223
  if (ancestor === undefined) {
@@ -243,24 +269,66 @@ const collectInterfaceMergeOmissions = (
243
269
  ...vfuncMergeOmissions(context, klass, iface),
244
270
  ];
245
271
 
246
- const collectInheritedPropertyTypes = (context: ModuleContext, klass: GirClass): Map<string, string> => {
247
- const types: Map<string, string> = new Map();
272
+ const declaredBy = (type: string | undefined, owner: string): DeclaredAccessorType | undefined =>
273
+ type === undefined ? undefined : { type, owner };
274
+
275
+ const reconcileAccessorType = (
276
+ jsName: string,
277
+ direction: string,
278
+ declared: DeclaredAccessorType | undefined,
279
+ candidate: DeclaredAccessorType | undefined,
280
+ ): DeclaredAccessorType | undefined => {
281
+ if (candidate === undefined) {
282
+ return declared;
283
+ }
284
+
285
+ if (declared === undefined || declared.type === candidate.type) {
286
+ return declared ?? candidate;
287
+ }
248
288
 
249
- const record = (owner: GirClass, property: GirProperty): void => {
250
- const jsName = toCamelIdentifier(property.name);
289
+ throw new Error(
290
+ `Cannot type the ${direction} accessor of ${jsName}: ${declared.owner} declares it as ${declared.type} ` +
291
+ `and ${candidate.owner} declares it as ${candidate.type}. Both are bases of the same class, so no single ` +
292
+ "member satisfies them; correct the GIR the disagreeing base comes from.",
293
+ );
294
+ };
251
295
 
252
- if (types.has(jsName)) {
253
- return;
254
- }
296
+ const recordInheritedPropertyType = (
297
+ context: ModuleContext,
298
+ types: Map<string, DeclaredAccessorTypes>,
299
+ owner: GirClass,
300
+ property: GirProperty,
301
+ ): void => {
302
+ const accessorTypes = resolveAccessorTypes(context, property, owner.methods);
255
303
 
256
- const tsType = resolveAccessorType(context, property, owner.methods);
304
+ if (accessorTypes === undefined) {
305
+ return;
306
+ }
257
307
 
258
- if (tsType !== undefined) {
259
- types.set(jsName, tsType);
260
- }
261
- };
308
+ const jsName = toCamelIdentifier(property.name);
309
+ const declared = types.get(jsName);
262
310
 
263
- forEachInheritedProperty(context, klass, record);
311
+ types.set(jsName, {
312
+ read: reconcileAccessorType(jsName, "read", declared?.read, declaredBy(accessorTypes.readType, owner.name)),
313
+ write: reconcileAccessorType(jsName, "write", declared?.write, declaredBy(accessorTypes.writeType, owner.name)),
314
+ });
315
+ };
316
+
317
+ const collectInheritedPropertyTypes = (
318
+ context: ModuleContext,
319
+ klass: GirClass,
320
+ ): Map<string, InheritedAccessorTypes> => {
321
+ const declared: Map<string, DeclaredAccessorTypes> = new Map();
322
+
323
+ forEachInheritedProperty(context, klass, (owner, property) => {
324
+ recordInheritedPropertyType(context, declared, owner, property);
325
+ });
326
+
327
+ const types: Map<string, InheritedAccessorTypes> = new Map();
328
+
329
+ for (const [jsName, entry] of declared) {
330
+ types.set(jsName, { readType: entry.read?.type, writeType: entry.write?.type });
331
+ }
264
332
 
265
333
  return types;
266
334
  };
@@ -298,7 +366,7 @@ const absorbInheritedMethods = (
298
366
  continue;
299
367
  }
300
368
 
301
- const name = camelCase(method.name);
369
+ const name = memberName(method.name);
302
370
 
303
371
  if (returnTypes.has(name)) {
304
372
  continue;
@@ -332,11 +400,49 @@ const hasMethodConflict = (options: {
332
400
  return (
333
401
  inheritedReturn !== ownReturn ||
334
402
  hasParameterEnumConflict(context, callable, inheritedMethod) ||
335
- inputParameters(context.library, callable).length !==
336
- inputParameters(context.library, inheritedMethod.method).length
403
+ hasParameterTypeConflict(context, callable, inheritedMethod.method)
337
404
  );
338
405
  };
339
406
 
407
+ const isCallbackType = (context: ModuleContext, ref: TypeId | undefined): boolean =>
408
+ ref !== undefined && context.library.typeFor(ref)?.kind === "callback";
409
+
410
+ const areParametersComparable = (context: ModuleContext, pair: ParameterPair): boolean => {
411
+ if (isCallbackType(context, pair.own.type) && isCallbackType(context, pair.inherited.type)) {
412
+ return true;
413
+ }
414
+
415
+ const scratch = comparisonContextFor(context);
416
+
417
+ return renderTsType(scratch, pair.own.type, false) === renderTsType(scratch, pair.inherited.type, false);
418
+ };
419
+
420
+ const inputParameterPairs = (context: ModuleContext, own: GirFunction, inherited: GirFunction): ParameterPair[] => {
421
+ const ownParams = inputParameters(context.library, own);
422
+ const inheritedParams = inputParameters(context.library, inherited);
423
+ const pairs: ParameterPair[] = [];
424
+
425
+ for (const [index, entry] of ownParams.entries()) {
426
+ const other = inheritedParams[index];
427
+
428
+ if (other !== undefined) {
429
+ pairs.push({ own: entry.parameter, inherited: other.parameter });
430
+ }
431
+ }
432
+
433
+ return pairs;
434
+ };
435
+
436
+ const hasParameterTypeConflict = (context: ModuleContext, own: GirFunction, inherited: GirFunction): boolean => {
437
+ const ownCount = inputParameters(context.library, own).length;
438
+
439
+ if (ownCount !== inputParameters(context.library, inherited).length) {
440
+ return true;
441
+ }
442
+
443
+ return inputParameterPairs(context, own, inherited).some((pair) => !areParametersComparable(context, pair));
444
+ };
445
+
340
446
  const conflictRename = (
341
447
  context: ModuleContext,
342
448
  callable: GirFunction,
@@ -383,26 +489,9 @@ const hasEnumConflict = (
383
489
  return ownEnum !== undefined && inheritedEnum !== undefined && ownEnum !== inheritedEnum;
384
490
  };
385
491
 
386
- const hasParameterEnumConflict = (context: ModuleContext, own: GirFunction, inherited: InheritedMethod): boolean => {
387
- const ownParams = inputParameters(context.library, own);
388
- const inheritedParams = inputParameters(context.library, inherited.method);
389
- const count = Math.min(ownParams.length, inheritedParams.length);
390
-
391
- for (let index = 0; index < count; index += 1) {
392
- const ownParam = ownParams[index];
393
- const inheritedParam = inheritedParams[index];
394
-
395
- if (
396
- ownParam !== undefined &&
397
- inheritedParam !== undefined &&
398
- hasEnumConflict(context, ownParam.parameter.type, inheritedParam.parameter.type)
399
- ) {
400
- return true;
401
- }
402
- }
403
-
404
- return false;
405
- };
492
+ const hasParameterEnumConflict = (context: ModuleContext, own: GirFunction, inherited: InheritedMethod): boolean =>
493
+ inputParameterPairs(context, own, inherited.method).some(
494
+ (pair) => hasEnumConflict(context, pair.own.type, pair.inherited.type));
406
495
 
407
496
  const enumIdentity = (context: ModuleContext, ref: TypeId | undefined): string | undefined => {
408
497
  if (ref === undefined) {
@@ -419,6 +508,7 @@ const enumIdentity = (context: ModuleContext, ref: TypeId | undefined): string |
419
508
  };
420
509
 
421
510
  export {
511
+ ancestorClassMethodNames,
422
512
  resolvePrerequisiteReference,
423
513
  forEachAncestor,
424
514
  collectInterfaceProperties,
@@ -0,0 +1,237 @@
1
+ import type { GirClass } from "../gir/class.js";
2
+ import type { GirFunction } from "../gir/function.js";
3
+ import type { Library } from "../gir/library.js";
4
+ import type { ModuleContext } from "../writer/context.js";
5
+ import { resolveClassOrInterface, type ResolvedAncestor, resolveInterfaces } from "../gir/ancestry.js";
6
+ import { isOutParameter } from "../gir/parameter.js";
7
+ import { memberName } from "../store/gi/method.js";
8
+ import { protectedChainSlotKeys, vfuncCallables, vfuncMemberNames } from "../store/gi/vtable.js";
9
+ import { forEachAncestor } from "./inheritance.js";
10
+ import { inputParameters } from "./param-structure.js";
11
+ import { typeKey } from "./type-key.js";
12
+
13
+ type MemberTable = Map<string, GirFunction>;
14
+
15
+ type ClaimedMembers = {
16
+ inherited: MemberTable;
17
+ interfaces: MemberTable;
18
+ };
19
+
20
+ type InterfaceConflictOptions = {
21
+ context: ModuleContext;
22
+ klass: GirClass;
23
+ iface: GirClass;
24
+ ifaceNamespace: string;
25
+ };
26
+
27
+ type CallableKeys = {
28
+ inputs: string[];
29
+ outputs: string[];
30
+ };
31
+
32
+ type CallableKeyPair = {
33
+ own: CallableKeys;
34
+ other: CallableKeys;
35
+ };
36
+
37
+ const CHAINABLE_SIGNAL_MEMBERS = ["addEventListener", "off", "on", "once", "removeEventListener"];
38
+
39
+ const callableKeys = (library: Library, fn: GirFunction): CallableKeys => ({
40
+ inputs: inputParameters(library, fn).map((entry) => typeKey(library, entry.parameter.type)),
41
+ outputs: [
42
+ typeKey(library, fn.returnValue.type),
43
+ ...fn.parameters
44
+ .filter((parameter) => isOutParameter(parameter))
45
+ .map((parameter) => typeKey(library, parameter.type)),
46
+ ],
47
+ });
48
+
49
+ const areKeysEqual = (left: string[], right: string[]): boolean =>
50
+ left.length === right.length && left.every((key, index) => key === right[index]);
51
+
52
+ const callableKeyPair = (library: Library, own: GirFunction, other: GirFunction): CallableKeyPair => ({
53
+ own: callableKeys(library, own),
54
+ other: callableKeys(library, other),
55
+ });
56
+
57
+ const areCallablesIdentical = (library: Library, own: GirFunction, other: GirFunction): boolean => {
58
+ const keys = callableKeyPair(library, own, other);
59
+
60
+ return areKeysEqual(keys.own.inputs, keys.other.inputs) && areKeysEqual(keys.own.outputs, keys.other.outputs);
61
+ };
62
+
63
+ const areCallablesAssignable = (library: Library, own: GirFunction, other: GirFunction): boolean => {
64
+ const keys = callableKeyPair(library, own, other);
65
+
66
+ if (keys.own.inputs.length > keys.other.inputs.length) {
67
+ return false;
68
+ }
69
+
70
+ if (keys.own.inputs.some((key, index) => key !== keys.other.inputs[index])) {
71
+ return false;
72
+ }
73
+
74
+ return areKeysEqual(keys.other.outputs, ["void"]) || areKeysEqual(keys.own.outputs, keys.other.outputs);
75
+ };
76
+
77
+ const collectMethods = (klass: GirClass, members: MemberTable): void => {
78
+ for (const method of klass.methods) {
79
+ const name = memberName(method.name);
80
+
81
+ if (method.introspectable && !members.has(name)) {
82
+ members.set(name, method);
83
+ }
84
+ }
85
+ };
86
+
87
+ const inheritedMembers = (context: ModuleContext, klass: GirClass): ClaimedMembers => {
88
+ const inherited: MemberTable = new Map();
89
+
90
+ forEachAncestor(context, klass, (ancestor) => {
91
+ collectMethods(ancestor.klass, inherited);
92
+ });
93
+
94
+ return { inherited, interfaces: new Map() };
95
+ };
96
+
97
+ const interfaceMembers = (options: InterfaceConflictOptions): MemberTable => {
98
+ const members: MemberTable = new Map();
99
+ collectMethods(options.iface, members);
100
+
101
+ for (const [key, callable] of vfuncCallables(options.context, options.ifaceNamespace, options.iface)) {
102
+ members.set(key, callable);
103
+ }
104
+
105
+ return members;
106
+ };
107
+
108
+ const claimInterfaceMembers = (options: InterfaceConflictOptions, claimed: ClaimedMembers): void => {
109
+ for (const [key, callable] of interfaceMembers(options)) {
110
+ if (!claimed.interfaces.has(key)) {
111
+ claimed.interfaces.set(key, callable);
112
+ }
113
+ }
114
+ };
115
+
116
+ const isConflictingMember = (library: Library, claimed: ClaimedMembers, entry: [string, GirFunction]): boolean => {
117
+ const [name, method] = entry;
118
+ const owned = claimed.inherited.get(name);
119
+
120
+ if (owned !== undefined) {
121
+ return !areCallablesAssignable(library, owned, method);
122
+ }
123
+
124
+ const sibling = claimed.interfaces.get(name);
125
+
126
+ return sibling !== undefined && !areCallablesIdentical(library, sibling, method);
127
+ };
128
+
129
+ const conflictingMemberNames = (options: InterfaceConflictOptions, claimed: ClaimedMembers): string[] =>
130
+ [...interfaceMembers(options)]
131
+ .filter((entry) => isConflictingMember(options.context.library, claimed, entry))
132
+ .map(([name]) => name);
133
+
134
+ const protectedVfuncNames = (options: InterfaceConflictOptions): string[] => {
135
+ const { context, klass, iface, ifaceNamespace } = options;
136
+ const protectedKeys = protectedChainSlotKeys(context, klass);
137
+
138
+ return vfuncMemberNames(context, ifaceNamespace, iface).filter((key) => protectedKeys.has(key));
139
+ };
140
+
141
+ const interfaceConflicts = (options: InterfaceConflictOptions, claimed: ClaimedMembers): string[] => {
142
+ const names = [...conflictingMemberNames(options, claimed), ...protectedVfuncNames(options)];
143
+
144
+ return names.length === 0 ? names : [...new Set([...names, ...CHAINABLE_SIGNAL_MEMBERS])];
145
+ };
146
+
147
+ const rootPrerequisite = (library: Library): ResolvedAncestor[] => {
148
+ const root = resolveClassOrInterface(library, "GObject", "Object");
149
+
150
+ return root === undefined ? [] : [root];
151
+ };
152
+
153
+ const interfaceSupertypes = (library: Library, entry: ResolvedAncestor): ResolvedAncestor[] => {
154
+ const prerequisites = entry.klass.prerequisites
155
+ .map((name) => resolveClassOrInterface(library, entry.namespaceName, name))
156
+ .filter((prerequisite) => prerequisite !== undefined);
157
+
158
+ return prerequisites.length === 0 ? rootPrerequisite(library) : prerequisites;
159
+ };
160
+
161
+ const classSupertypes = (library: Library, entry: ResolvedAncestor): ResolvedAncestor[] => {
162
+ const interfaces = resolveInterfaces(library, entry.namespaceName, entry.klass.implements);
163
+
164
+ if (entry.klass.parent === undefined) {
165
+ return interfaces;
166
+ }
167
+
168
+ const parent = resolveClassOrInterface(library, entry.namespaceName, entry.klass.parent);
169
+
170
+ return parent === undefined ? interfaces : [parent, ...interfaces];
171
+ };
172
+
173
+ const directSupertypes = (library: Library, entry: ResolvedAncestor): ResolvedAncestor[] =>
174
+ entry.klass.isInterface ? interfaceSupertypes(library, entry) : classSupertypes(library, entry);
175
+
176
+ const collectSupertypeMembers = (
177
+ library: Library,
178
+ entry: ResolvedAncestor,
179
+ visited: Set<string>,
180
+ members: MemberTable,
181
+ ): void => {
182
+ const key = `${entry.namespaceName}.${entry.klass.name}`;
183
+
184
+ if (visited.has(key)) {
185
+ return;
186
+ }
187
+
188
+ visited.add(key);
189
+ collectMethods(entry.klass, members);
190
+
191
+ for (const supertype of directSupertypes(library, entry)) {
192
+ collectSupertypeMembers(library, supertype, visited, members);
193
+ }
194
+ };
195
+
196
+ const supertypeMembers = (library: Library, base: ResolvedAncestor): MemberTable => {
197
+ const members: MemberTable = new Map();
198
+ collectSupertypeMembers(library, base, new Set(), members);
199
+
200
+ return members;
201
+ };
202
+
203
+ const prerequisiteConflicts = (library: Library, iface: GirClass, base: ResolvedAncestor): string[] => {
204
+ const members: MemberTable = new Map();
205
+ collectMethods(iface, members);
206
+ const inherited = supertypeMembers(library, base);
207
+ const names: string[] = [];
208
+
209
+ for (const [name, method] of members) {
210
+ const owned = inherited.get(name);
211
+
212
+ if (owned !== undefined && !areCallablesAssignable(library, method, owned)) {
213
+ names.push(name);
214
+ }
215
+ }
216
+
217
+ return names;
218
+ };
219
+
220
+ const omittedTypeRef = (typeRef: string, omissions: string[]): string => {
221
+ if (omissions.length === 0) {
222
+ return typeRef;
223
+ }
224
+
225
+ const keys = [...new Set(omissions)].map((name) => JSON.stringify(name)).join(" | ");
226
+
227
+ return `Omit<${typeRef}, ${keys}>`;
228
+ };
229
+
230
+ export {
231
+ type ClaimedMembers,
232
+ claimInterfaceMembers,
233
+ inheritedMembers,
234
+ interfaceConflicts,
235
+ omittedTypeRef,
236
+ prerequisiteConflicts,
237
+ };
@@ -3,9 +3,9 @@ import type { CArrayType, TypeId } from "../gir/type-id.js";
3
3
  import type { GirType } from "../gir/type.js";
4
4
  import type { ModuleContext } from "../writer/context.js";
5
5
  import { isCallerAllocatedOut, isInoutParameter } from "../gir/parameter.js";
6
- import { constructibleName } from "../store/gi/method.js";
7
6
  import { isCollectibleCallerOut, isHandlePassedInPlace, underlyingType } from "../store/gi/param-marshal.js";
8
- import { isScalarRef, recordInlineSize } from "./descriptor-render.js";
7
+ import { recordInlineSize } from "../store/gi/record-layout.js";
8
+ import { isScalarRef } from "./descriptor-render.js";
9
9
 
10
10
  const POINTER_DEPTH = 1;
11
11
 
@@ -114,15 +114,12 @@ const hasCallerSuppliedLength = (context: ModuleContext, parameter: GirParameter
114
114
  return type?.kind === "carray" && type.lengthParameterIndex !== undefined;
115
115
  };
116
116
 
117
- const isUnbuildableCallerOut = (context: ModuleContext, parameter: GirParameter): boolean =>
118
- constructibleName(context, parameter.type) === undefined || !isCollectibleCallerOut(context, parameter);
119
-
120
117
  const isUnmarshalableCallerOut = (context: ModuleContext, parameter: GirParameter): boolean => {
121
118
  if (hasCallerSuppliedLength(context, parameter)) {
122
119
  return true;
123
120
  }
124
121
 
125
- return isUnbuildableCallerOut(context, parameter) && !parameter.optional;
122
+ return !isCollectibleCallerOut(context, parameter) && !parameter.optional;
126
123
  };
127
124
 
128
125
  const hasIndirectionMismatch = (context: ModuleContext, parameter: GirParameter): boolean => {
@@ -4,7 +4,7 @@ import type { Library } from "../gir/library.js";
4
4
  import type { TypeId } from "../gir/type-id.js";
5
5
  import type { JsDocParam } from "../writer/doc-tags.js";
6
6
  import { type GirCallable, type GirParameter, isCallerAllocatedOut, isOutParameter } from "../gir/parameter.js";
7
- import { isCellInout, shouldOmitPrimaryReturn } from "./descriptor-render.js";
7
+ import { isCellInout, isVoidPrimaryReturn } from "./descriptor-render.js";
8
8
 
9
9
  type InputParameter = {
10
10
  parameter: GirParameter;
@@ -277,7 +277,7 @@ const renderHandlerResultType = (options: HandlerResultOptions): string => {
277
277
  const { library, signal, renderType, shouldIncludeCallerAllocated, isOptOut } = options;
278
278
  const shouldExcludeOut = options.shouldExcludeOut ?? (() => false);
279
279
 
280
- const primary = shouldOmitPrimaryReturn(library, signal.returnValue)
280
+ const primary = isVoidPrimaryReturn(library, signal.returnValue)
281
281
  ? undefined
282
282
  : renderType(signal.returnValue.type, signal.returnValue.nullable);
283
283