@gtkx/codegen 1.0.0-rc.3 → 1.0.0-rc.4

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 (229) hide show
  1. package/README.md +4 -5
  2. package/dist/analysis/descriptor-render.d.ts +1 -3
  3. package/dist/analysis/descriptor-render.d.ts.map +1 -1
  4. package/dist/analysis/descriptor-render.js +14 -37
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +6 -6
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +7 -7
  9. package/dist/analysis/descriptor.js.map +1 -1
  10. package/dist/analysis/param-structure.d.ts +2 -2
  11. package/dist/analysis/param-structure.d.ts.map +1 -1
  12. package/dist/analysis/param-structure.js +5 -7
  13. package/dist/analysis/param-structure.js.map +1 -1
  14. package/dist/analysis/ts-type.d.ts +1 -1
  15. package/dist/analysis/ts-type.d.ts.map +1 -1
  16. package/dist/analysis/ts-type.js +3 -5
  17. package/dist/analysis/ts-type.js.map +1 -1
  18. package/dist/compile.d.ts.map +1 -1
  19. package/dist/compile.js +2 -1
  20. package/dist/compile.js.map +1 -1
  21. package/dist/docs/api-reference.d.ts +77 -1
  22. package/dist/docs/api-reference.d.ts.map +1 -1
  23. package/dist/docs/api-reference.js +62 -0
  24. package/dist/docs/api-reference.js.map +1 -1
  25. package/dist/docs/pipeline.d.ts +4 -4
  26. package/dist/docs/pipeline.d.ts.map +1 -1
  27. package/dist/docs/pipeline.js +4 -4
  28. package/dist/docs/pipeline.js.map +1 -1
  29. package/dist/docs/render.js +6 -6
  30. package/dist/docs/render.js.map +1 -1
  31. package/dist/docs/symbol-page.d.ts +5 -0
  32. package/dist/docs/symbol-page.d.ts.map +1 -1
  33. package/dist/docs/symbol-page.js +2 -2
  34. package/dist/docs/symbol-page.js.map +1 -1
  35. package/dist/fingerprint.d.ts +2 -5
  36. package/dist/fingerprint.d.ts.map +1 -1
  37. package/dist/fingerprint.js +6 -8
  38. package/dist/fingerprint.js.map +1 -1
  39. package/dist/gi.d.ts +3 -11
  40. package/dist/gi.d.ts.map +1 -1
  41. package/dist/gi.js +0 -7
  42. package/dist/gi.js.map +1 -1
  43. package/dist/gir/field.d.ts +0 -1
  44. package/dist/gir/field.d.ts.map +1 -1
  45. package/dist/gir/field.js +0 -3
  46. package/dist/gir/field.js.map +1 -1
  47. package/dist/gir/gir-path.d.ts +7 -0
  48. package/dist/gir/gir-path.d.ts.map +1 -1
  49. package/dist/gir/gir-path.js +7 -0
  50. package/dist/gir/gir-path.js.map +1 -1
  51. package/dist/gir/libraries.d.ts +13 -0
  52. package/dist/gir/libraries.d.ts.map +1 -1
  53. package/dist/gir/libraries.js +12 -0
  54. package/dist/gir/libraries.js.map +1 -1
  55. package/dist/gir/parameter.d.ts.map +1 -1
  56. package/dist/gir/parameter.js +0 -4
  57. package/dist/gir/parameter.js.map +1 -1
  58. package/dist/gir/size.d.ts.map +1 -1
  59. package/dist/gir/size.js +0 -3
  60. package/dist/gir/size.js.map +1 -1
  61. package/dist/gir/type-id.d.ts +1 -1
  62. package/dist/gir/type-id.d.ts.map +1 -1
  63. package/dist/gir/type-id.js +1 -3
  64. package/dist/gir/type-id.js.map +1 -1
  65. package/dist/gir/type-ref.js +1 -1
  66. package/dist/gir/type-ref.js.map +1 -1
  67. package/dist/index.d.ts +18 -6
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +12 -3
  70. package/dist/index.js.map +1 -1
  71. package/dist/internal.d.ts +3 -0
  72. package/dist/internal.d.ts.map +1 -0
  73. package/dist/internal.js +3 -0
  74. package/dist/internal.js.map +1 -0
  75. package/dist/jsx.d.ts +7 -12
  76. package/dist/jsx.d.ts.map +1 -1
  77. package/dist/jsx.js +18 -19
  78. package/dist/jsx.js.map +1 -1
  79. package/dist/khronos/args.d.ts.map +1 -1
  80. package/dist/khronos/args.js +1 -1
  81. package/dist/khronos/args.js.map +1 -1
  82. package/dist/khronos/pipeline.js +1 -1
  83. package/dist/khronos/pipeline.js.map +1 -1
  84. package/dist/khronos/plan.d.ts +2 -2
  85. package/dist/khronos/plan.d.ts.map +1 -1
  86. package/dist/khronos/plan.js +6 -6
  87. package/dist/khronos/plan.js.map +1 -1
  88. package/dist/react/element-config.d.ts +17 -11
  89. package/dist/react/element-config.d.ts.map +1 -1
  90. package/dist/react/element-config.js +22 -15
  91. package/dist/react/element-config.js.map +1 -1
  92. package/dist/runner.d.ts +35 -17
  93. package/dist/runner.d.ts.map +1 -1
  94. package/dist/runner.js +19 -20
  95. package/dist/runner.js.map +1 -1
  96. package/dist/store/compile-store.d.ts +1 -2
  97. package/dist/store/compile-store.d.ts.map +1 -1
  98. package/dist/store/compile-store.js +2 -2
  99. package/dist/store/compile-store.js.map +1 -1
  100. package/dist/store/gi/callables.js +4 -4
  101. package/dist/store/gi/callables.js.map +1 -1
  102. package/dist/store/gi/constant.d.ts.map +1 -1
  103. package/dist/store/gi/constant.js +0 -2
  104. package/dist/store/gi/constant.js.map +1 -1
  105. package/dist/store/gi/function.d.ts.map +1 -1
  106. package/dist/store/gi/function.js +1 -5
  107. package/dist/store/gi/function.js.map +1 -1
  108. package/dist/store/gi/method.d.ts.map +1 -1
  109. package/dist/store/gi/method.js +25 -23
  110. package/dist/store/gi/method.js.map +1 -1
  111. package/dist/store/gi/property-accessor.d.ts +1 -1
  112. package/dist/store/gi/property-accessor.d.ts.map +1 -1
  113. package/dist/store/gi/property-accessor.js +5 -7
  114. package/dist/store/gi/property-accessor.js.map +1 -1
  115. package/dist/store/gi/record-field-accessor.d.ts +1 -1
  116. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  117. package/dist/store/gi/record-field-accessor.js +3 -9
  118. package/dist/store/gi/record-field-accessor.js.map +1 -1
  119. package/dist/store/gi/record-layout.d.ts.map +1 -1
  120. package/dist/store/gi/record-layout.js +0 -4
  121. package/dist/store/gi/record-layout.js.map +1 -1
  122. package/dist/store/gi/return-wrap.d.ts +1 -1
  123. package/dist/store/gi/return-wrap.d.ts.map +1 -1
  124. package/dist/store/gi/return-wrap.js +4 -4
  125. package/dist/store/gi/return-wrap.js.map +1 -1
  126. package/dist/store/gi/signal.d.ts.map +1 -1
  127. package/dist/store/gi/signal.js +13 -16
  128. package/dist/store/gi/signal.js.map +1 -1
  129. package/dist/store/gi/value-marshalable.d.ts +0 -8
  130. package/dist/store/gi/value-marshalable.d.ts.map +1 -1
  131. package/dist/store/gi/value-marshalable.js +0 -9
  132. package/dist/store/gi/value-marshalable.js.map +1 -1
  133. package/dist/store/gi-store.d.ts +2 -3
  134. package/dist/store/gi-store.d.ts.map +1 -1
  135. package/dist/store/gi-store.js.map +1 -1
  136. package/dist/store/jsx/element-components.d.ts +0 -2
  137. package/dist/store/jsx/element-components.d.ts.map +1 -1
  138. package/dist/store/jsx/element-components.js +0 -4
  139. package/dist/store/jsx/element-components.js.map +1 -1
  140. package/dist/store/jsx/element-prop-imports.d.ts +2 -3
  141. package/dist/store/jsx/element-prop-imports.d.ts.map +1 -1
  142. package/dist/store/jsx/element-prop-imports.js +0 -2
  143. package/dist/store/jsx/element-prop-imports.js.map +1 -1
  144. package/dist/store/jsx/element-prop-types.d.ts +0 -1
  145. package/dist/store/jsx/element-prop-types.d.ts.map +1 -1
  146. package/dist/store/jsx/element-prop-types.js +0 -1
  147. package/dist/store/jsx/element-prop-types.js.map +1 -1
  148. package/dist/store/jsx/generated-elements.d.ts +29 -0
  149. package/dist/store/jsx/generated-elements.d.ts.map +1 -0
  150. package/dist/store/jsx/generated-elements.js +30 -0
  151. package/dist/store/jsx/generated-elements.js.map +1 -0
  152. package/dist/store/jsx/jsx.js +6 -6
  153. package/dist/store/jsx/jsx.js.map +1 -1
  154. package/dist/store/jsx/metadata.js +7 -7
  155. package/dist/store/jsx/metadata.js.map +1 -1
  156. package/dist/store/jsx/omitted-props.d.ts +2 -4
  157. package/dist/store/jsx/omitted-props.d.ts.map +1 -1
  158. package/dist/store/jsx/omitted-props.js +2 -4
  159. package/dist/store/jsx/omitted-props.js.map +1 -1
  160. package/dist/store/jsx/pipeline.d.ts +3 -1
  161. package/dist/store/jsx/pipeline.d.ts.map +1 -1
  162. package/dist/store/jsx/pipeline.js +3 -2
  163. package/dist/store/jsx/pipeline.js.map +1 -1
  164. package/dist/store/jsx/props.js +2 -2
  165. package/dist/store/jsx/props.js.map +1 -1
  166. package/dist/store/jsx-store.d.ts +2 -3
  167. package/dist/store/jsx-store.d.ts.map +1 -1
  168. package/dist/store/jsx-store.js +3 -3
  169. package/dist/store/jsx-store.js.map +1 -1
  170. package/dist/store/resolve-store.d.ts +28 -0
  171. package/dist/store/resolve-store.d.ts.map +1 -0
  172. package/dist/store/resolve-store.js +65 -0
  173. package/dist/store/resolve-store.js.map +1 -0
  174. package/dist/store/store-fs.d.ts +5 -1
  175. package/dist/store/store-fs.d.ts.map +1 -1
  176. package/dist/store/store-fs.js +6 -4
  177. package/dist/store/store-fs.js.map +1 -1
  178. package/overrides/gobject/object.ts.ejs +8 -8
  179. package/package.json +6 -10
  180. package/src/analysis/descriptor-render.ts +20 -45
  181. package/src/analysis/descriptor.ts +13 -13
  182. package/src/analysis/param-structure.ts +8 -10
  183. package/src/analysis/ts-type.ts +4 -6
  184. package/src/compile.ts +2 -1
  185. package/src/docs/api-reference.ts +127 -4
  186. package/src/docs/pipeline.ts +8 -8
  187. package/src/docs/render.ts +7 -7
  188. package/src/docs/symbol-page.ts +7 -2
  189. package/src/fingerprint.ts +8 -13
  190. package/src/gi.ts +4 -11
  191. package/src/gir/field.ts +0 -4
  192. package/src/gir/gir-path.ts +7 -0
  193. package/src/gir/libraries.ts +13 -0
  194. package/src/gir/parameter.ts +0 -4
  195. package/src/gir/size.ts +0 -3
  196. package/src/gir/type-id.ts +2 -4
  197. package/src/gir/type-ref.ts +1 -1
  198. package/src/index.ts +18 -16
  199. package/src/internal.ts +2 -0
  200. package/src/jsx.ts +26 -26
  201. package/src/khronos/args.ts +1 -1
  202. package/src/khronos/pipeline.ts +1 -1
  203. package/src/khronos/plan.ts +8 -8
  204. package/src/react/element-config.ts +22 -19
  205. package/src/runner.ts +57 -39
  206. package/src/store/compile-store.ts +3 -4
  207. package/src/store/gi/callables.ts +5 -5
  208. package/src/store/gi/constant.ts +0 -2
  209. package/src/store/gi/function.ts +1 -5
  210. package/src/store/gi/method.ts +30 -28
  211. package/src/store/gi/property-accessor.ts +6 -8
  212. package/src/store/gi/record-field-accessor.ts +4 -10
  213. package/src/store/gi/record-layout.ts +0 -4
  214. package/src/store/gi/return-wrap.ts +5 -5
  215. package/src/store/gi/signal.ts +17 -17
  216. package/src/store/gi/value-marshalable.ts +0 -9
  217. package/src/store/gi-store.ts +2 -4
  218. package/src/store/jsx/element-components.ts +0 -6
  219. package/src/store/jsx/element-prop-imports.ts +7 -4
  220. package/src/store/jsx/element-prop-types.ts +0 -1
  221. package/src/store/jsx/generated-elements.ts +60 -0
  222. package/src/store/jsx/jsx.ts +7 -7
  223. package/src/store/jsx/metadata.ts +8 -8
  224. package/src/store/jsx/omitted-props.ts +2 -4
  225. package/src/store/jsx/pipeline.ts +5 -3
  226. package/src/store/jsx/props.ts +2 -2
  227. package/src/store/jsx-store.ts +5 -7
  228. package/src/store/resolve-store.ts +100 -0
  229. package/src/store/store-fs.ts +12 -5
@@ -51,11 +51,9 @@ import {
51
51
 
52
52
  type RenderDescriptorOptions = {
53
53
  argIndexOffset?: number;
54
- /** GIR parameter index to emitted argument index, for callables that drop parameters. */
55
54
  argIndexMap?: Map<number, number> | undefined;
56
- callerAllocated?: boolean;
55
+ isCallerAllocated?: boolean;
57
56
  isInline?: boolean;
58
- /** Set on the return value of a callable with no instance parameter, which creates what it returns. */
59
57
  isNewlyCreated?: boolean;
60
58
  };
61
59
 
@@ -76,7 +74,7 @@ type FundamentalDescriptor = {
76
74
  typeName: string | undefined;
77
75
  ownership: Ownership;
78
76
  wrapperClass?: string | undefined;
79
- inline?: boolean | undefined;
77
+ isInline?: boolean | undefined;
80
78
  };
81
79
 
82
80
  type AncestorFundamental = {
@@ -94,7 +92,7 @@ type FundamentalRecordOptions = {
94
92
  unrefFunc: string;
95
93
  ownership: Ownership;
96
94
  wrapperClass: string | undefined;
97
- inline: boolean;
95
+ isInline: boolean;
98
96
  };
99
97
 
100
98
  const LIST_HELPERS: Record<Exclude<ListFlavor, "gbytearray">, ListDescriptorName> = {
@@ -104,17 +102,8 @@ const LIST_HELPERS: Record<Exclude<ListFlavor, "gbytearray">, ListDescriptorName
104
102
  garray: "gArray",
105
103
  };
106
104
 
107
- /**
108
- * `glib:type-name` of every fundamental whose instances are born with a floating reference, so a
109
- * callable that creates one hands back a claim nobody has taken rather than an owned reference.
110
- * GIR annotates those returns `transfer-ownership="full"` all the same, so the annotation alone
111
- * cannot tell them apart from a genuinely owned return such as `g_param_spec_ref`.
112
- */
113
105
  const FLOATING_FUNDAMENTALS: Set<string> = new Set(["GParam"]);
114
106
 
115
- // A callable that drops parameters (varargs, and the closure/destroy slots folded into a callback)
116
- // shifts every later parameter left, so a GIR length index has to be looked up in the emitted list
117
- // rather than shifted by the instance offset alone.
118
107
  const mapArgIndex = (options: ArgIndexOptions, girIndex: number): number =>
119
108
  options.argIndexMap?.get(girIndex) ?? girIndex + options.argIndexOffset;
120
109
 
@@ -175,9 +164,6 @@ const renderDescriptor = (
175
164
  case "varargs": {
176
165
  return tVoid;
177
166
  }
178
- // A callback in a slot no `renderCallbackType` covers (a vtable entry, a signal argument, a
179
- // record field) is still a function pointer occupying a pointer-sized slot. `t.void` would
180
- // hand the implementation `undefined` where the pointer belongs.
181
167
  case "callback": {
182
168
  return tUint64;
183
169
  }
@@ -288,13 +274,10 @@ const renderParamDescriptor = (
288
274
 
289
275
  return renderDescriptor(context, ref, parameter.transferOwnership, {
290
276
  ...argIndex,
291
- callerAllocated: isCallerAllocatedOut(parameter) || isRecordInout(context, parameter),
277
+ isCallerAllocated: isCallerAllocatedOut(parameter) || isRecordInout(context, parameter),
292
278
  });
293
279
  };
294
280
 
295
- // `closure=` on a callback's own parameter states which slot carries the user data, and it is what
296
- // the TypeScript signature already goes by. The name scan stays as a fallback: 88 callbacks across
297
- // the installed GIRs carry no `closure=` at all.
298
281
  const userDataIndexByName = (parameters: GirParameter[]): number | undefined => {
299
282
  let userDataIndex: number | undefined;
300
283
 
@@ -379,19 +362,16 @@ const primitiveExpression = (category: PrimitiveCategory, ownership: Ownership):
379
362
  };
380
363
 
381
364
  const renderFundamental = (descriptor: FundamentalDescriptor): string => {
382
- const { lib, refFunc, unrefFunc, typeName, ownership, wrapperClass, inline } = descriptor;
365
+ const { lib, refFunc, unrefFunc, typeName, ownership, wrapperClass, isInline } = descriptor;
383
366
 
384
367
  return tFundamental(lib, refFunc, unrefFunc, {
385
368
  ownership,
386
369
  typeName,
387
370
  wrapperClass,
388
- inline,
371
+ isInline,
389
372
  });
390
373
  };
391
374
 
392
- // A freshly created floating instance is claimed by sinking it, which is what the fundamental's
393
- // declared ref function does, so it is marshalled as transfer-none: adopting the floating reference
394
- // instead would leave the handle releasing a claim it never took.
395
375
  const sunkOwnership = (
396
376
  ancestor: AncestorFundamental,
397
377
  ownership: Ownership,
@@ -404,8 +384,6 @@ const sunkOwnership = (
404
384
  return FLOATING_FUNDAMENTALS.has(ancestor.typeName) ? "borrowed" : ownership;
405
385
  };
406
386
 
407
- // GIR marks only the root of a fundamental hierarchy with `glib:fundamental` and its ref/unref pair,
408
- // so a derived type such as GtkPropertyExpression carries neither and has to inherit both.
409
387
  const classOrInterfaceExpression = (
410
388
  context: ModuleContext,
411
389
  resolved: Extract<EntityType, { kind: "class" | "interface" }>,
@@ -510,9 +488,6 @@ const renderSelfDescriptor = (context: ModuleContext, instance: GirParameter): s
510
488
  return tObject("borrowed");
511
489
  };
512
490
 
513
- // A record expresses its acquire/release pair as `copy-function`/`free-function`: no `<record>` in
514
- // any installed GIR carries `glib:ref-func`, and GVariant's copy function really is
515
- // `g_variant_ref_sink`.
516
491
  const recordRefPair = (record: ResolvedRecord): { refFunc: string | undefined; unrefFunc: string | undefined } => ({
517
492
  refFunc: record.glibRefFunc ?? record.copyFunc,
518
493
  unrefFunc: record.glibUnrefFunc ?? record.freeFunc,
@@ -532,7 +507,7 @@ const structExpression = (
532
507
  context: ModuleContext,
533
508
  resolved: Extract<EntityType, { kind: "record" }>,
534
509
  ownership: Ownership,
535
- options: { callerAllocated: boolean; inline: boolean },
510
+ options: { isCallerAllocated: boolean; isInline: boolean },
536
511
  ): string => {
537
512
  const { size } = computeRecordFieldSlots(context, resolved.value.fields, resolved.value.isUnion);
538
513
  const wrapperClass = context.qualify(resolved.namespace.name, resolved.value.name);
@@ -541,13 +516,13 @@ const structExpression = (
541
516
  return tStruct(ownership, {
542
517
  size: isCopyable && size > 0 ? size : undefined,
543
518
  wrapperClass,
544
- callerAllocated: options.callerAllocated,
545
- inline: options.inline,
519
+ isCallerAllocated: options.isCallerAllocated,
520
+ isInline: options.isInline,
546
521
  });
547
522
  };
548
523
 
549
524
  const fundamentalRecordExpression = (options: FundamentalRecordOptions): string => {
550
- const { resolved, refFunc, unrefFunc, ownership, wrapperClass, inline } = options;
525
+ const { resolved, refFunc, unrefFunc, ownership, wrapperClass, isInline } = options;
551
526
 
552
527
  return renderFundamental({
553
528
  lib: resolved.namespace.sharedLibrary ?? "",
@@ -556,7 +531,7 @@ const fundamentalRecordExpression = (options: FundamentalRecordOptions): string
556
531
  typeName: resolved.value.glibTypeName,
557
532
  ownership,
558
533
  wrapperClass,
559
- inline,
534
+ isInline,
560
535
  });
561
536
  };
562
537
 
@@ -564,11 +539,11 @@ const boxedRecordExpression = (options: {
564
539
  context: ModuleContext;
565
540
  resolved: Extract<EntityType, { kind: "record" }>;
566
541
  ownership: Ownership;
567
- callerAllocated: boolean;
568
- inline: boolean;
542
+ isCallerAllocated: boolean;
543
+ isInline: boolean;
569
544
  typeFnName: string;
570
545
  }): string => {
571
- const { context, resolved, ownership, callerAllocated, inline, typeFnName } = options;
546
+ const { context, resolved, ownership, isCallerAllocated, isInline, typeFnName } = options;
572
547
  const record = resolved.value;
573
548
  const glibName = record.glibTypeName ?? record.cType ?? record.name;
574
549
  const { size } = computeRecordFieldSlots(context, record.fields, record.isUnion);
@@ -577,8 +552,8 @@ const boxedRecordExpression = (options: {
577
552
  ownership,
578
553
  sharedLibrary: resolved.namespace.sharedLibrary,
579
554
  getTypeFnName: typeFnName,
580
- callerAllocated,
581
- inline,
555
+ isCallerAllocated,
556
+ isInline,
582
557
  size: size > 0 ? size : undefined,
583
558
  });
584
559
  };
@@ -592,8 +567,8 @@ const plainRecordExpression = (
592
567
  const record = resolved.value;
593
568
 
594
569
  const layout = {
595
- callerAllocated: placement.isCallerAllocated ?? false,
596
- inline: placement.isInline ?? false,
570
+ isCallerAllocated: placement.isCallerAllocated ?? false,
571
+ isInline: placement.isInline ?? false,
597
572
  };
598
573
 
599
574
  if (record.glibGetType === undefined) {
@@ -623,7 +598,7 @@ const recordExpression = (
623
598
  unrefFunc,
624
599
  ownership,
625
600
  wrapperClass,
626
- inline: placement.isInline ?? false,
601
+ isInline: placement.isInline ?? false,
627
602
  });
628
603
  }
629
604
 
@@ -660,7 +635,7 @@ const expressionForResolved = (
660
635
  }
661
636
  case "record": {
662
637
  return recordExpression(context, resolved, ownership, {
663
- isCallerAllocated: options.callerAllocated ?? false,
638
+ isCallerAllocated: options.isCallerAllocated ?? false,
664
639
  isInline: options.isInline ?? false,
665
640
  });
666
641
  }
@@ -64,23 +64,23 @@ type BoxedOptions = {
64
64
  ownership: Ownership;
65
65
  sharedLibrary: string | undefined;
66
66
  getTypeFnName: string;
67
- callerAllocated: boolean;
68
- inline?: boolean;
67
+ isCallerAllocated: boolean;
68
+ isInline?: boolean;
69
69
  size: number | undefined;
70
70
  };
71
71
 
72
72
  type StructOptions = {
73
73
  size: number | string | undefined;
74
74
  wrapperClass: string | undefined;
75
- callerAllocated: boolean;
76
- inline?: boolean;
75
+ isCallerAllocated: boolean;
76
+ isInline?: boolean;
77
77
  };
78
78
 
79
79
  type FundamentalOptions = {
80
80
  ownership: Ownership;
81
81
  typeName: string | undefined;
82
82
  wrapperClass: string | undefined;
83
- inline?: boolean | undefined;
83
+ isInline?: boolean | undefined;
84
84
  };
85
85
 
86
86
  type ListDescriptorName = "list" | "slist" | "ptrArray" | "gArray";
@@ -165,8 +165,8 @@ const tBoxed = (glibName: string, options: BoxedOptions): string =>
165
165
  ? undefined
166
166
  : `sharedLibrary: ${sourceStringLiteral(options.sharedLibrary)}`,
167
167
  `getTypeFnName: ${sourceStringLiteral(options.getTypeFnName)}`,
168
- options.callerAllocated ? "callerAllocated: true" : undefined,
169
- options.inline === true ? "inline: true" : undefined,
168
+ options.isCallerAllocated ? "isCallerAllocated: true" : undefined,
169
+ options.isInline === true ? "isInline: true" : undefined,
170
170
  options.size === undefined ? undefined : `size: ${String(options.size)}`,
171
171
  ]),
172
172
  ]);
@@ -177,13 +177,13 @@ const tStruct = (ownership: Ownership, options: StructOptions): string =>
177
177
  optionsObject([
178
178
  options.size === undefined ? undefined : `size: ${String(options.size)}`,
179
179
  options.wrapperClass === undefined ? undefined : `wrapperClass: ${options.wrapperClass}`,
180
- options.callerAllocated ? "callerAllocated: true" : undefined,
181
- options.inline === true ? "inline: true" : undefined,
180
+ options.isCallerAllocated ? "isCallerAllocated: true" : undefined,
181
+ options.isInline === true ? "isInline: true" : undefined,
182
182
  ]),
183
183
  ]);
184
184
 
185
185
  const tInlineStruct = (): string =>
186
- tStruct("borrowed", { size: undefined, wrapperClass: undefined, callerAllocated: false });
186
+ tStruct("borrowed", { size: undefined, wrapperClass: undefined, isCallerAllocated: false });
187
187
 
188
188
  const tFundamental = (lib: string, refFunc: string, unrefFunc: string, options: FundamentalOptions): string =>
189
189
  call("fundamental", [
@@ -194,7 +194,7 @@ const tFundamental = (lib: string, refFunc: string, unrefFunc: string, options:
194
194
  `ownership: ${sourceStringLiteral(options.ownership)}`,
195
195
  options.typeName === undefined ? undefined : `typeName: ${sourceStringLiteral(options.typeName)}`,
196
196
  options.wrapperClass === undefined ? undefined : `wrapperClass: ${options.wrapperClass}`,
197
- options.inline === true ? "inline: true" : undefined,
197
+ options.isInline === true ? "isInline: true" : undefined,
198
198
  ]),
199
199
  ]);
200
200
 
@@ -252,9 +252,9 @@ const tBind = (args: BindArgs): string =>
252
252
  const tFn = (
253
253
  lib: string,
254
254
  cIdentifier: string,
255
- spec: { args: string; returns: string; throws: boolean },
255
+ spec: { args: string; returns: string; canThrow: boolean },
256
256
  ): string => {
257
- const throwsEntry = spec.throws ? ", throws: true" : "";
257
+ const throwsEntry = spec.canThrow ? ", canThrow: true" : "";
258
258
 
259
259
  return call("fn", [
260
260
  sourceStringLiteral(lib),
@@ -14,8 +14,8 @@ type HandlerResultOptions = {
14
14
  library: Library;
15
15
  signal: GirCallable;
16
16
  renderType: (ref: TypeId | undefined, isNullable: boolean) => string;
17
- includeCallerAllocated: boolean;
18
- optOut: boolean;
17
+ shouldIncludeCallerAllocated: boolean;
18
+ isOptOut: boolean;
19
19
  };
20
20
 
21
21
  const isInputParameter = (options: {
@@ -75,8 +75,6 @@ const closureAndDestroyIndices = (fn: GirFunction): Set<number> => {
75
75
  return indices;
76
76
  };
77
77
 
78
- // The emitted argument list is the instance parameter followed by every parameter `planParameter`
79
- // keeps, so a GIR index only lines up with an emitted index when nothing before it was dropped.
80
78
  const emittedArgIndices = (fn: GirFunction, instanceOffset: number): Map<number, number> => {
81
79
  const closureIndices = closureAndDestroyIndices(fn);
82
80
  const map: Map<number, number> = new Map();
@@ -199,9 +197,9 @@ const foldOutParamShape = (primary: string | undefined, outTypes: string[]): str
199
197
  const isHandlerOutParameter = (options: {
200
198
  library: Library;
201
199
  parameter: GirParameter;
202
- includeCallerAllocated: boolean;
200
+ shouldIncludeCallerAllocated: boolean;
203
201
  }): boolean => {
204
- const { library, parameter, includeCallerAllocated } = options;
202
+ const { library, parameter, shouldIncludeCallerAllocated } = options;
205
203
 
206
204
  if (parameter.isVarargs) {
207
205
  return false;
@@ -215,7 +213,7 @@ const isHandlerOutParameter = (options: {
215
213
  return true;
216
214
  }
217
215
 
218
- return includeCallerAllocated && isCallerAllocatedOut(parameter);
216
+ return shouldIncludeCallerAllocated && isCallerAllocatedOut(parameter);
219
217
  };
220
218
 
221
219
  const scalarResultType = (primary: string | undefined, isOptOut: boolean): string => {
@@ -227,18 +225,18 @@ const scalarResultType = (primary: string | undefined, isOptOut: boolean): strin
227
225
  };
228
226
 
229
227
  const renderHandlerResultType = (options: HandlerResultOptions): string => {
230
- const { library, signal, renderType, includeCallerAllocated, optOut } = options;
228
+ const { library, signal, renderType, shouldIncludeCallerAllocated, isOptOut } = options;
231
229
 
232
230
  const primary = shouldOmitPrimaryReturn(library, signal.returnValue)
233
231
  ? undefined
234
232
  : renderType(signal.returnValue.type, signal.returnValue.nullable);
235
233
 
236
234
  const outTypes = signal.parameters
237
- .filter((parameter) => isHandlerOutParameter({ library, parameter, includeCallerAllocated }))
235
+ .filter((parameter) => isHandlerOutParameter({ library, parameter, shouldIncludeCallerAllocated }))
238
236
  .map((parameter) => renderType(parameter.type, parameter.nullable));
239
237
 
240
238
  if (outTypes.length === 0) {
241
- return scalarResultType(primary, optOut);
239
+ return scalarResultType(primary, isOptOut);
242
240
  }
243
241
 
244
242
  return foldOutParamShape(primary, outTypes);
@@ -19,7 +19,7 @@ type ReferenceName = {
19
19
  type TsTypeTarget = {
20
20
  containerStyle: "map" | "record";
21
21
  callbackType: string;
22
- byteArrayAsNumber: boolean;
22
+ shouldRenderByteArrayAsNumber: boolean;
23
23
  renderNamed: (resolved: GirType | undefined, name: ReferenceName) => string;
24
24
  renderGtype: () => string;
25
25
  };
@@ -100,10 +100,8 @@ const renderContainerType = (
100
100
  return renderSequenceType(library, target, type);
101
101
  };
102
102
 
103
- // An array whose length nothing states decodes as the bare pointer it is, so its TypeScript type has
104
- // to say so too rather than promising elements nothing can count.
105
103
  const renderSequenceType = (library: Library, target: TsTypeTarget, type: CArrayType | ListType): string => {
106
- if (type.kind === "list" && type.flavor === "gbytearray" && target.byteArrayAsNumber) {
104
+ if (type.kind === "list" && type.flavor === "gbytearray" && target.shouldRenderByteArrayAsNumber) {
107
105
  return "number[]";
108
106
  }
109
107
 
@@ -129,7 +127,7 @@ const renderNamedType = (
129
127
  const moduleTarget = (context: ModuleContext): TsTypeTarget => ({
130
128
  containerStyle: "map",
131
129
  callbackType: "((...args: any[]) => any)",
132
- byteArrayAsNumber: true,
130
+ shouldRenderByteArrayAsNumber: true,
133
131
  renderNamed: (_resolved, name) => context.qualify(name.namespaceName, name.typeName),
134
132
  renderGtype: () => gtypeTsType(context),
135
133
  });
@@ -148,7 +146,7 @@ const recordTypeTarget = (
148
146
  const target: TsTypeTarget = {
149
147
  containerStyle: "record",
150
148
  callbackType: "((...args: unknown[]) => unknown)",
151
- byteArrayAsNumber: false,
149
+ shouldRenderByteArrayAsNumber: false,
152
150
  renderNamed: (resolved, name) => {
153
151
  if (resolved?.kind === "alias") {
154
152
  return resolved.value.target === undefined
package/src/compile.ts CHANGED
@@ -29,8 +29,10 @@ const BASE_COMPILER_OPTIONS = {
29
29
  noImplicitReturns: true,
30
30
  noFallthroughCasesInSwitch: true,
31
31
  allowUnreachableCode: false,
32
+ allowImportingTsExtensions: true,
32
33
  forceConsistentCasingInFileNames: true,
33
34
  resolveJsonModule: true,
35
+ rewriteRelativeImportExtensions: true,
34
36
  skipLibCheck: true,
35
37
  types: ["node"],
36
38
  };
@@ -47,7 +49,6 @@ const FORMAT_HOST: ts.FormatDiagnosticsHost = {
47
49
  getNewLine: () => "\n",
48
50
  };
49
51
 
50
- /** `@gtkx/codegen`'s own `node_modules`, which has `@types/node` plus the `@gtkx/*` deps the store typecheck needs. */
51
52
  const codegenModules = (): string => {
52
53
  const sourceDir = dirname(fileURLToPath(import.meta.url));
53
54
 
@@ -6,41 +6,90 @@ import { Library } from "../gir/library.js";
6
6
  import { type GirNamespace, namespaceDirectory } from "../gir/namespace.js";
7
7
  import { dedupeCallables, isEmittableCallable } from "../store/gi/callables.js";
8
8
  import { namespaceFunctionExportName } from "../store/gi/function.js";
9
+ import { type ElementProps, setElementProps } from "../store/jsx/element-prop-imports.js";
9
10
  import { collectIntrinsicElementClasses, type GlibNamedClass } from "../store/jsx/intrinsic-elements.js";
11
+ import { type OmittedProps, setOmittedProps } from "../store/jsx/omitted-props.js";
10
12
  import { createElementPageContext, type ElementPageContext, renderElementPage } from "./element-page.js";
11
13
  import { docsSignatureContext, firstSentence, namespaceOrder } from "./render.js";
12
14
  import { type GiSymbolEntry, renderSymbolPage, type SymbolPageOptions } from "./symbol-page.js";
13
15
 
16
+ /** What to index and the element config the rendered pages reflect. */
14
17
  type ApiReferenceOptions = {
18
+ /** GIR library identifiers to load, such as `"Gtk-4.0"`; their dependencies are pulled in too. */
15
19
  libraries: string[];
20
+ /** Directories to search for `.gir` files. */
16
21
  girPath: string[];
22
+ /** Base props interfaces per element, as read by `readBuiltinElements`; without it pages miss them. */
23
+ props?: ElementProps;
24
+ /** GObject properties the project omits from generated props; without it pages show props that do not exist. */
25
+ omittedProps?: OmittedProps;
17
26
  };
18
27
 
28
+ /** Narrows an `ApiReference.symbols` enumeration. */
29
+ type ApiSymbolQuery = {
30
+ /** GIR namespace to keep, matched case-insensitively; every namespace when omitted. */
31
+ namespace?: string;
32
+ /** Symbol kinds to keep; every kind when omitted. */
33
+ kinds?: ApiSymbolKind[];
34
+ };
35
+
36
+ /** What an indexed symbol is: one of the GIR symbol kinds, or a JSX element. */
19
37
  type ApiSymbolKind = GiSymbolEntry["kind"] | "element";
20
38
 
39
+ /** An indexed symbol, without its reference page. */
21
40
  type ApiSymbol = {
41
+ /** GIR namespace declaring the symbol, such as `"Gtk"`. */
22
42
  namespace: string;
43
+ /** Name within the namespace, which for an element is its GLib type name. */
23
44
  name: string;
45
+ /** Kind the reference groups and filters the symbol by, `"element"` for a JSX tag. */
24
46
  kind: ApiSymbolKind;
47
+ /** First sentence of the symbol's GIR documentation, elided past 220 characters and empty when it has none. */
25
48
  summary: string;
26
49
  };
27
50
 
51
+ /** How much of one namespace the reference indexes. */
28
52
  type ApiNamespaceSummary = {
53
+ /** GIR namespace name, such as `"Gtk"`. */
29
54
  name: string;
55
+ /** The `@gtkx/gi` subpath the namespace's symbols are imported from. */
30
56
  importPath: string;
57
+ /** How many symbols other than JSX elements the namespace contributes. */
31
58
  symbols: number;
59
+ /** How many JSX elements the namespace contributes. */
32
60
  elements: number;
33
61
  };
34
62
 
63
+ /** What an `ApiReference.lookup` found: a rendered page, several candidates for the name, or nothing. */
35
64
  type ApiLookupResult =
36
- | { outcome: "page"; symbol: ApiSymbol; markdown: string } |
37
- { outcome: "ambiguous"; candidates: ApiSymbol[] } |
38
- { outcome: "notFound" };
39
-
65
+ | {
66
+ /** Discriminant selecting the variant. */
67
+ outcome: "page";
68
+ /** Index entry for the symbol the query resolved to. */
69
+ symbol: ApiSymbol;
70
+ /** The symbol's complete reference page, rendered as Markdown. */
71
+ markdown: string;
72
+ } |
73
+ {
74
+ /** Discriminant selecting the variant. */
75
+ outcome: "ambiguous";
76
+ /** Every symbol the name answers to, to be narrowed by namespace or kind. */
77
+ candidates: ApiSymbol[];
78
+ } |
79
+ {
80
+ /** Discriminant selecting the variant. */
81
+ outcome: "notFound";
82
+ };
83
+
84
+ /** A fuzzy search over indexed symbol names. */
40
85
  type ApiSearchOptions = {
86
+ /** Text matched case-insensitively against each symbol's name and its qualified `Namespace.Name` form. */
41
87
  query: string;
88
+ /** GIR namespace to keep, matched case-insensitively; every namespace when omitted. */
42
89
  namespace?: string;
90
+ /** Symbol kinds to keep; every kind when omitted. */
43
91
  kinds?: ApiSymbolKind[];
92
+ /** Maximum number of results, 20 by default. */
44
93
  limit?: number;
45
94
  };
46
95
 
@@ -55,6 +104,7 @@ type ElementEntry = {
55
104
  type SymbolEntry = GiSymbolEntry | ElementEntry;
56
105
  type ScoredEntry = { score: number; entry: SymbolEntry };
57
106
 
107
+ /** Every kind the reference indexes, in the order a namespace overview groups its symbols. */
58
108
  const API_SYMBOL_KINDS: ApiSymbolKind[] = [
59
109
  "element",
60
110
  "class",
@@ -89,6 +139,32 @@ const compareNames = (a: string, b: string): number => {
89
139
  return a > b ? 1 : 0;
90
140
  };
91
141
 
142
+ const isQueriedEntry = (
143
+ entry: SymbolEntry,
144
+ namespaceFilter: string | undefined,
145
+ kinds: Set<ApiSymbolKind> | undefined,
146
+ ): boolean => {
147
+ if (namespaceFilter !== undefined && entry.namespace.name.toLowerCase() !== namespaceFilter) {
148
+ return false;
149
+ }
150
+
151
+ return kinds === undefined || kinds.has(entry.kind);
152
+ };
153
+
154
+ const compareApiSymbols = (a: ApiSymbol, b: ApiSymbol): number => {
155
+ const byNamespace = namespaceOrder(a.namespace).localeCompare(namespaceOrder(b.namespace));
156
+
157
+ return byNamespace === 0 ? a.name.localeCompare(b.name) : byNamespace;
158
+ };
159
+
160
+ /**
161
+ * Loads the GIR data for the given libraries and indexes every symbol and JSX element in it. The result is
162
+ * a read-only view: it generates no store and needs none, so a tool can explore the bindings a project would
163
+ * get without running codegen.
164
+ *
165
+ * @param options Which libraries to index, where to find them, and the project's element config.
166
+ * @returns The indexed reference.
167
+ */
92
168
  const loadApiReference = (options: ApiReferenceOptions): ApiReference => new ApiReference(options);
93
169
 
94
170
  const functionEntry = (
@@ -265,6 +341,7 @@ const searchScore = (entry: SymbolEntry, query: string): number => {
265
341
  return 0;
266
342
  };
267
343
 
344
+ /** An index over the GIR data a project's bindings are generated from, queryable and renderable as Markdown. */
268
345
  class ApiReference {
269
346
  private library: Library;
270
347
  private libraries: string[];
@@ -275,13 +352,23 @@ class ApiReference {
275
352
  private byNamespace: Map<string, SymbolEntry[]> = new Map();
276
353
  private elementsByClass: Map<string, string> = new Map();
277
354
 
355
+ private props: ElementProps;
356
+ private omittedProps: OmittedProps;
357
+
278
358
  constructor(options: ApiReferenceOptions) {
279
359
  this.libraries = options.libraries;
360
+ this.props = options.props ?? {};
361
+ this.omittedProps = options.omittedProps ?? {};
280
362
  this.library = Library.load(options.libraries, options.girPath);
281
363
  this.elementContext = createElementPageContext(this.library, (): string | undefined => undefined);
282
364
  this.buildIndex();
283
365
  }
284
366
 
367
+ private applyElementConfig(): void {
368
+ setElementProps(this.props);
369
+ setOmittedProps(this.omittedProps);
370
+ }
371
+
285
372
  private add(entry: SymbolEntry): void {
286
373
  this.entries.push(entry);
287
374
 
@@ -362,6 +449,8 @@ class ApiReference {
362
449
 
363
450
  private renderPage(entry: SymbolEntry): string {
364
451
  if (entry.kind === "element") {
452
+ this.applyElementConfig();
453
+
365
454
  return renderElementPage(entry.element, this.elementContext);
366
455
  }
367
456
 
@@ -410,10 +499,18 @@ class ApiReference {
410
499
  return scored;
411
500
  }
412
501
 
502
+ /** Paths of the `.gir` files the index was built from, including the ones pulled in as dependencies. */
413
503
  get girFiles(): string[] {
414
504
  return this.library.girFiles;
415
505
  }
416
506
 
507
+ /**
508
+ * Resolves a name to a single symbol and renders its reference page. The name may be bare (`Button`) or
509
+ * qualified (`Gtk.Button`), and is matched case-insensitively; a name several symbols answer to is
510
+ * reported as ambiguous rather than picked between.
511
+ *
512
+ * @param kind Restricts the match to one kind, which is how a class and its JSX element are told apart.
513
+ */
417
514
  lookup(query: string, kind?: ApiSymbolKind): ApiLookupResult {
418
515
  const trimmed = query.trim();
419
516
 
@@ -435,6 +532,21 @@ class ApiReference {
435
532
  return { outcome: "page", symbol: this.toApiSymbol(entry), markdown: this.renderPage(entry) };
436
533
  }
437
534
 
535
+ /** Every indexed symbol the query keeps, ordered by namespace (Gtk, then Adw, then alphabetically) and name. */
536
+ symbols(query: ApiSymbolQuery = {}): ApiSymbol[] {
537
+ const namespaceFilter = query.namespace?.toLowerCase();
538
+ const kinds = query.kinds === undefined ? undefined : new Set(query.kinds);
539
+
540
+ return this.entries
541
+ .filter((entry) => isQueriedEntry(entry, namespaceFilter, kinds))
542
+ .map((entry) => this.toApiSymbol(entry))
543
+ .toSorted(compareApiSymbols);
544
+ }
545
+
546
+ /**
547
+ * Symbols whose name matches the query, best first: an exact name beats a prefix, which beats a
548
+ * substring, and shorter names win ties. An empty query matches nothing.
549
+ */
438
550
  search(options: ApiSearchOptions): ApiSymbol[] {
439
551
  const query = options.query.trim().toLowerCase();
440
552
 
@@ -450,6 +562,7 @@ class ApiReference {
450
562
  return scored.slice(0, limit).map((item) => this.toApiSymbol(item.entry));
451
563
  }
452
564
 
565
+ /** A summary of every indexed namespace, ordered Gtk, Adw, then alphabetically. */
453
566
  namespaces(): ApiNamespaceSummary[] {
454
567
  const summaries = [...this.byNamespace].map(([name, entries]) => ({
455
568
  name,
@@ -461,6 +574,10 @@ class ApiReference {
461
574
  return sortStringsBy(summaries, (summary) => namespaceOrder(summary.name));
462
575
  }
463
576
 
577
+ /**
578
+ * Sorted names of everything a namespace contributes, JSX elements included. The namespace is matched
579
+ * case-insensitively, and an unindexed one yields an empty array.
580
+ */
464
581
  symbolNames(namespaceName: string): string[] {
465
582
  const namespace = this.findNamespace(namespaceName);
466
583
 
@@ -473,6 +590,7 @@ class ApiReference {
473
590
  return sortStrings(entries.map((entry) => entry.name));
474
591
  }
475
592
 
593
+ /** Renders the reference's Markdown landing page: every namespace, its import path, and its totals. */
476
594
  overview(): string {
477
595
  const rows = this.namespaces().map(
478
596
  (summary) =>
@@ -500,6 +618,10 @@ class ApiReference {
500
618
  ].join("\n");
501
619
  }
502
620
 
621
+ /**
622
+ * Renders one namespace's Markdown page: its import line and its symbol names grouped by kind. The
623
+ * namespace is matched case-insensitively, and an unindexed one yields undefined.
624
+ */
503
625
  namespaceOverview(name: string): string | undefined {
504
626
  const namespace = this.findNamespace(name);
505
627
 
@@ -549,4 +671,5 @@ export {
549
671
  type ApiNamespaceSummary,
550
672
  type ApiLookupResult,
551
673
  type ApiSearchOptions,
674
+ type ApiSymbolQuery,
552
675
  };