@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,4 @@
1
- import { pascalCase, sortStringsBy, upperFirst } from "@gtkx/utils";
1
+ import { sanitizeTypeIdentifier, sortStringsBy, upperFirst } from "@gtkx/utils";
2
2
  import type { GirAnnotations } from "../gir/annotations.js";
3
3
  import type { GirClass } from "../gir/class.js";
4
4
  import type { EnumMember, GirEnum } from "../gir/enum.js";
@@ -51,6 +51,7 @@ import {
51
51
  type OriginSignatureEntry,
52
52
  plainText,
53
53
  propertyMetaLine,
54
+ qualifiedClassName,
54
55
  renderDocsSignalHandlerType,
55
56
  renderDocsType,
56
57
  signalTags,
@@ -202,9 +203,6 @@ const pageHeader = (entry: GiSymbolEntry, kindLabel: string): string[] => [
202
203
  importBlock(entry),
203
204
  ];
204
205
 
205
- const qualifiedClassName = (namespaceName: string, className: string): string =>
206
- `${namespaceName}.${pascalCase(className)}`;
207
-
208
206
  const elementNote = (entry: ClassSymbol, options: SymbolPageOptions): string[] => {
209
207
  const glibName = options.elementNameFor(entry.namespace.name, entry.klass.name);
210
208
 
@@ -354,7 +352,7 @@ const memberOwners = (entry: ClassSymbol, library: Library): MemberOwner[] => [
354
352
 
355
353
  const interfaceMethodNames = (library: Library, owner: MemberOwner): string[] => {
356
354
  const context = docsSignatureContext(owner.namespace, library);
357
- const className = pascalCase(owner.klass.name);
355
+ const className = sanitizeTypeIdentifier(owner.klass.name);
358
356
  const methods = dedupeCallables(owner.klass.methods);
359
357
 
360
358
  const scope = instanceScope(className, {
@@ -402,9 +400,16 @@ const getAccessNotes = (accessor: ResolvedAccessor): string[] => {
402
400
  return ["read-only"];
403
401
  }
404
402
 
405
- return accessor.hasGetter ? [] : ["write-only"];
403
+ if (!accessor.hasGetter) {
404
+ return ["write-only"];
405
+ }
406
+
407
+ return accessor.readType === accessor.writeType ? [] : [`writes \`${accessor.writeType}\``];
406
408
  };
407
409
 
410
+ const documentedAccessorType = (accessor: ResolvedAccessor): string =>
411
+ accessor.hasGetter ? accessor.readType : accessor.writeType;
412
+
408
413
  const ownerPropertyEntries = (owner: MemberOwner, setup: PropertyAccessorSetup, seen: Set<string>): MetaDocEntry[] => {
409
414
  const entries: MetaDocEntry[] = [];
410
415
 
@@ -425,7 +430,7 @@ const ownerPropertyEntries = (owner: MemberOwner, setup: PropertyAccessorSetup,
425
430
  entries.push({
426
431
  name: accessor.jsName,
427
432
  meta: propertyMetaLine({
428
- type: accessor.tsType,
433
+ type: documentedAccessorType(accessor),
429
434
  property,
430
435
  accessNotes: getAccessNotes(accessor),
431
436
  origin: owner.origin,
@@ -1,9 +1,11 @@
1
1
  import { sortStrings } from "@gtkx/utils";
2
2
  import { createHash } from "node:crypto";
3
3
  import { type Dirent, existsSync, readdirSync, readFileSync } from "node:fs";
4
- import { createRequire } from "node:module";
5
4
  import { dirname, join, resolve } from "node:path";
6
5
  import { fileURLToPath } from "node:url";
6
+ import packageManifest from "../package.json" with { type: "json" };
7
+ import { arrayGuard, hasFields, isNumber, isString, optionalGuard } from "./guards.js";
8
+ import { readJsonFile } from "./json.js";
7
9
 
8
10
  type GiFingerprint = {
9
11
  value: string;
@@ -14,6 +16,17 @@ type GiFingerprint = {
14
16
 
15
17
  type ModuleExport = { module: string; export: string };
16
18
 
19
+ type DocsFingerprintInput = {
20
+ basePath: string;
21
+ props: Record<string, ModuleExport>;
22
+ omittedProps: Record<string, string[]>;
23
+ };
24
+
25
+ type DocsFingerprint = {
26
+ value: string;
27
+ gi: GiFingerprint;
28
+ };
29
+
17
30
  type JsxFingerprintInput = {
18
31
  reactVersion: string;
19
32
  components: Record<string, ModuleExport>;
@@ -27,9 +40,8 @@ type JsxFingerprint = {
27
40
  intrinsicElementCount: number;
28
41
  };
29
42
 
30
- const require = createRequire(import.meta.url);
31
43
  const FINGERPRINT_FILENAME = ".codegen-fingerprint.json";
32
- const CODEGEN_VERSION: string = (require("../package.json") as { version: string }).version;
44
+ const CODEGEN_VERSION: string = packageManifest.version;
33
45
  const OVERRIDES_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "overrides");
34
46
 
35
47
  const sortAlpha = (values: string[]): string => sortStrings(values).join(",");
@@ -75,39 +87,87 @@ const computeGiFingerprint = (
75
87
  girPath,
76
88
  });
77
89
 
78
- const isGiStoreFresh = (
79
- giStoreDir: string,
80
- libraries: string[],
81
- girPath: string[],
82
- ): boolean => {
83
- const sentinelPath = join(giStoreDir, FINGERPRINT_FILENAME);
90
+ const readSentinel = (storeDir: string): unknown => readJsonFile(join(storeDir, FINGERPRINT_FILENAME));
84
91
 
85
- if (!existsSync(sentinelPath)) {
86
- return false;
87
- }
92
+ const isGiFingerprint = (value: unknown): value is GiFingerprint =>
93
+ hasFields<GiFingerprint>(value, {
94
+ value: isString,
95
+ girFiles: arrayGuard(isString),
96
+ libraries: arrayGuard(isString),
97
+ girPath: optionalGuard(arrayGuard(isString)),
98
+ });
88
99
 
89
- let sentinel: GiFingerprint;
100
+ const isDocsFingerprint = (value: unknown): value is DocsFingerprint =>
101
+ hasFields<DocsFingerprint>(value, { value: isString, gi: isGiFingerprint });
90
102
 
91
- try {
92
- sentinel = JSON.parse(readFileSync(sentinelPath, "utf8")) as GiFingerprint;
93
- } catch {
94
- return false;
95
- }
103
+ const isJsxFingerprint = (value: unknown): value is JsxFingerprint =>
104
+ hasFields<JsxFingerprint>(value, { value: isString, intrinsicElementCount: isNumber });
96
105
 
106
+ const recordedGiValue = (sentinel: GiFingerprint, libraries: string[], girPath: string[]): string | undefined => {
97
107
  if (!hasMatchingRecordedInputs(sentinel, libraries, girPath)) {
98
- return false;
108
+ return undefined;
99
109
  }
100
110
 
101
111
  try {
102
- return hashGi(sentinel.girFiles, sentinel.libraries, girPath) === sentinel.value;
112
+ return hashGi(sentinel.girFiles, sentinel.libraries, girPath);
103
113
  } catch {
104
- return false;
114
+ return undefined;
105
115
  }
106
116
  };
107
117
 
118
+ const isGiStoreFresh = (
119
+ giStoreDir: string,
120
+ libraries: string[],
121
+ girPath: string[],
122
+ ): boolean => {
123
+ const sentinel = readSentinel(giStoreDir);
124
+
125
+ return isGiFingerprint(sentinel) && recordedGiValue(sentinel, libraries, girPath) === sentinel.value;
126
+ };
127
+
108
128
  const hasMatchingRecordedInputs = (sentinel: GiFingerprint, libraries: string[], girPath: string[]): boolean =>
109
129
  sortAlpha(sentinel.libraries) === sortAlpha(libraries) && sortAlpha(sentinel.girPath ?? []) === sortAlpha(girPath);
110
130
 
131
+ const hashDocs = (giValue: string, input: DocsFingerprintInput): string =>
132
+ createHash("sha256")
133
+ .update(
134
+ JSON.stringify([
135
+ giValue,
136
+ input.basePath,
137
+ serializeModuleExports(input.props),
138
+ serializeOmittedProps(input.omittedProps),
139
+ ]),
140
+ )
141
+ .digest("hex");
142
+
143
+ const computeDocsFingerprint = (
144
+ girFiles: string[],
145
+ libraries: string[],
146
+ girPath: string[],
147
+ input: DocsFingerprintInput,
148
+ ): DocsFingerprint => {
149
+ const gi = computeGiFingerprint(girFiles, libraries, girPath);
150
+
151
+ return { value: hashDocs(gi.value, input), gi };
152
+ };
153
+
154
+ const isDocsOutputFresh = (
155
+ outDir: string,
156
+ libraries: string[],
157
+ girPath: string[],
158
+ input: DocsFingerprintInput,
159
+ ): boolean => {
160
+ const sentinel = readSentinel(outDir);
161
+
162
+ if (!isDocsFingerprint(sentinel)) {
163
+ return false;
164
+ }
165
+
166
+ const giValue = recordedGiValue(sentinel.gi, libraries, girPath);
167
+
168
+ return giValue !== undefined && hashDocs(giValue, input) === sentinel.value;
169
+ };
170
+
111
171
  const serializeModuleExports = (map: Record<string, ModuleExport>): [string, string, string][] =>
112
172
  sortStrings(Object.keys(map)).map((type) => [type, map[type]?.module ?? "", map[type]?.export ?? ""]);
113
173
 
@@ -137,17 +197,9 @@ const jsxStoreFreshness = (
137
197
  jsxStoreDir: string,
138
198
  input: JsxFingerprintInput,
139
199
  ): { isFresh: boolean; intrinsicElementCount: number } => {
140
- const sentinelPath = join(jsxStoreDir, FINGERPRINT_FILENAME);
141
-
142
- if (!existsSync(sentinelPath)) {
143
- return { isFresh: false, intrinsicElementCount: 0 };
144
- }
200
+ const sentinel = readSentinel(jsxStoreDir);
145
201
 
146
- let sentinel: JsxFingerprint;
147
-
148
- try {
149
- sentinel = JSON.parse(readFileSync(sentinelPath, "utf8")) as JsxFingerprint;
150
- } catch {
202
+ if (!isJsxFingerprint(sentinel)) {
151
203
  return { isFresh: false, intrinsicElementCount: 0 };
152
204
  }
153
205
 
@@ -159,9 +211,12 @@ const jsxStoreFreshness = (
159
211
  export {
160
212
  FINGERPRINT_FILENAME,
161
213
  computeGiFingerprint,
214
+ computeDocsFingerprint,
162
215
  isGiStoreFresh,
216
+ isDocsOutputFresh,
163
217
  computeJsxFingerprint,
164
218
  jsxStoreFreshness,
219
+ type DocsFingerprintInput,
165
220
  type GiFingerprint,
166
221
  type JsxFingerprintInput,
167
222
  };
package/src/gi.ts CHANGED
@@ -17,6 +17,7 @@ const runGiCodegen = (library: Library, options: GiCodegenOptions): number => {
17
17
  const namespaces: GiNamespaceInput[] = Array.from(library.namespaces.values(), (namespace) => ({
18
18
  directory: namespaceDirectory(namespace),
19
19
  rawSource: generateNamespaceModule(namespace, library),
20
+ girFile: namespace.girFile,
20
21
  }));
21
22
 
22
23
  const fingerprint = computeGiFingerprint(library.girFiles, [...libraries], [...girPath]);
@@ -1,12 +1,28 @@
1
1
  import type { GirClass } from "./class.js";
2
2
  import type { Library } from "./library.js";
3
3
  import type { GirType } from "./type.js";
4
+ import { splitOptionalNamespace } from "./type-ref.js";
4
5
 
5
6
  type ResolvedAncestor = {
6
7
  klass: GirClass;
7
8
  namespaceName: string;
8
9
  };
9
10
 
11
+ type ParentRef = {
12
+ namespaceName: string | undefined;
13
+ typeName: string;
14
+ };
15
+
16
+ const getParentRef = (klass: GirClass): ParentRef | undefined => {
17
+ if (klass.parent === undefined) {
18
+ return undefined;
19
+ }
20
+
21
+ const [namespaceName, typeName] = splitOptionalNamespace(klass.parent);
22
+
23
+ return { namespaceName, typeName };
24
+ };
25
+
10
26
  const getAncestor = (resolved: GirType | undefined): ResolvedAncestor | undefined =>
11
27
  resolved !== undefined && (resolved.kind === "class" || resolved.kind === "interface")
12
28
  ? { klass: resolved.value, namespaceName: resolved.namespace.name }
@@ -64,4 +80,4 @@ function* ancestorChain(library: Library, klass: GirClass, namespaceName: string
64
80
  }
65
81
  }
66
82
 
67
- export { resolveInterfaces, ancestorChain, type ResolvedAncestor };
83
+ export { resolveClassOrInterface, resolveInterfaces, ancestorChain, getParentRef, type ResolvedAncestor };
@@ -34,4 +34,4 @@ const documentedFromNode = (node: RawNode): DocumentedNode => ({
34
34
  const hasAnnotations = (annotations: GirAnnotations): boolean =>
35
35
  annotations.since !== undefined || annotations.isDeprecated || annotations.deprecatedSince !== undefined;
36
36
 
37
- export { annotationsFromNode, documentedFromNode, hasAnnotations, type GirAnnotations };
37
+ export { documentedFromNode, hasAnnotations, type GirAnnotations };
@@ -0,0 +1,12 @@
1
+ type CursorParameterNames = {
2
+ cursor: string;
3
+ base: string;
4
+ length: string;
5
+ };
6
+
7
+ const PARAMETERS_MISSING_ARRAY_EXTENT: Map<string, CursorParameterNames[]> = new Map([
8
+ ["g_utf8_validate", [{ cursor: "end", base: "str", length: "max_len" }]],
9
+ ["g_utf8_validate_len", [{ cursor: "end", base: "str", length: "max_len" }]],
10
+ ]);
11
+
12
+ export { PARAMETERS_MISSING_ARRAY_EXTENT, type CursorParameterNames };
@@ -0,0 +1,8 @@
1
+ type NamedEntity = {
2
+ name: string;
3
+ introspectable?: boolean | undefined;
4
+ };
5
+
6
+ const isEmittableEntity = (entity: NamedEntity): boolean => entity.name.length > 0 && entity.introspectable !== false;
7
+
8
+ export { isEmittableEntity };
@@ -1,5 +1,6 @@
1
1
  import type { GirAnnotations } from "./annotations.js";
2
2
  import type { ParseContext } from "./type-id.js";
3
+ import { type CursorParameterNames, PARAMETERS_MISSING_ARRAY_EXTENT } from "./cursor-overrides.js";
3
4
  import { PARAMETERS_MISSING_NULLABLE_ANNOTATION } from "./nullable-overrides.js";
4
5
  import { type GirParameter, type GirReturnValue, parameterFromNode, parseCallable } from "./parameter.js";
5
6
  import { attr, getChild, type RawNode } from "./parse.js";
@@ -50,18 +51,53 @@ const relaxMissingNullable = (fn: GirFunction): GirFunction => {
50
51
  return fn;
51
52
  };
52
53
 
54
+ const parameterIndexFor = (parameters: GirParameter[], name: string): number => {
55
+ const index = parameters.findIndex((parameter) => parameter.name === name);
56
+
57
+ if (index === -1) {
58
+ throw new Error(`A cursor correction names a parameter the GIR does not declare: ${name}`);
59
+ }
60
+
61
+ return index;
62
+ };
63
+
64
+ const bindCursorParameters = (parameters: GirParameter[], corrections: CursorParameterNames[]): void => {
65
+ for (const names of corrections) {
66
+ const parameter = parameters[parameterIndexFor(parameters, names.cursor)];
67
+
68
+ if (parameter !== undefined) {
69
+ parameter.cursor = {
70
+ baseIndex: parameterIndexFor(parameters, names.base),
71
+ lengthIndex: parameterIndexFor(parameters, names.length),
72
+ };
73
+ }
74
+ }
75
+ };
76
+
77
+ const bindMissingArrayExtent = (fn: GirFunction): GirFunction => {
78
+ const corrections = fn.cIdentifier === undefined ? undefined : PARAMETERS_MISSING_ARRAY_EXTENT.get(fn.cIdentifier);
79
+
80
+ if (corrections !== undefined) {
81
+ bindCursorParameters(fn.parameters, corrections);
82
+ }
83
+
84
+ return fn;
85
+ };
86
+
53
87
  const functionFromNode = (node: RawNode, context: ParseContext): GirFunction => {
54
88
  const instanceNode = getChild(getChild(node, "parameters"), "instance-parameter");
55
89
 
56
- return relaxMissingNullable({
57
- ...parseCallable(node, context),
58
- name: attr(node, "shadows") ?? attr(node, "name") ?? "",
59
- cIdentifier: attr(node, "c:identifier"),
60
- movedTo: attr(node, "moved-to"),
61
- shadowedBy: attr(node, "shadowed-by"),
62
- finishFunc: attr(node, "glib:finish-func"),
63
- instance: instanceNode === undefined ? undefined : parameterFromNode(instanceNode, context),
64
- });
90
+ return bindMissingArrayExtent(
91
+ relaxMissingNullable({
92
+ ...parseCallable(node, context),
93
+ name: attr(node, "shadows") ?? attr(node, "name") ?? "",
94
+ cIdentifier: attr(node, "c:identifier"),
95
+ movedTo: attr(node, "moved-to"),
96
+ shadowedBy: attr(node, "shadowed-by"),
97
+ finishFunc: attr(node, "glib:finish-func"),
98
+ instance: instanceNode === undefined ? undefined : parameterFromNode(instanceNode, context),
99
+ }),
100
+ );
65
101
  };
66
102
 
67
103
  export { functionFromNode, type GirFunction };
@@ -294,7 +294,7 @@ class Library {
294
294
  seen.add(namespaceName);
295
295
  const path = locateGirFile(identifier, girPath);
296
296
  girFiles.push(path);
297
- const header = parseNamespaceHeader(readRepositoryNode(path));
297
+ const header = parseNamespaceHeader(readRepositoryNode(path), path);
298
298
  const shell = this.registerNamespace(header);
299
299
  discovered.push({ header, shell });
300
300
 
@@ -44,6 +44,8 @@ type GirNamespace = {
44
44
  id: number;
45
45
  /** Namespace name as it appears in the GIR, such as `Gtk`. */
46
46
  name: string;
47
+ /** Path of the `.gir` file the namespace was parsed from, named by every diagnostic the namespace causes. */
48
+ girFile: string;
47
49
  /** The `shared-library` attribute verbatim: the objects to load symbols from, separated by commas. */
48
50
  sharedLibrary: string | undefined;
49
51
  /** Prefixes stripped off C identifiers to derive export names, such as `gtk`. */
@@ -78,6 +80,8 @@ type NamespaceInclude = {
78
80
  type NamespaceHeader = {
79
81
  /** Namespace name as it appears in the GIR, such as `Gtk`. */
80
82
  name: string;
83
+ /** Path of the `.gir` file the header was read from. */
84
+ girFile: string;
81
85
  /** The `shared-library` attribute verbatim: the objects to load symbols from, separated by commas. */
82
86
  sharedLibrary: string | undefined;
83
87
  /** Prefixes stripped off C identifiers to derive export names, such as `gtk`. */
@@ -90,7 +94,7 @@ type NamespaceHeader = {
90
94
 
91
95
  const namespaceDirectory = (namespace: Pick<GirNamespace, "name">): string => namespace.name.toLowerCase();
92
96
 
93
- const parseNamespaceHeader = (repositoryNode: RawNode): NamespaceHeader => {
97
+ const parseNamespaceHeader = (repositoryNode: RawNode, path: string): NamespaceHeader => {
94
98
  const includes = getChildren(repositoryNode, "include").map<NamespaceInclude>((include) => ({
95
99
  name: nameAttr(include),
96
100
  version: attr(include, "version") ?? "",
@@ -99,11 +103,12 @@ const parseNamespaceHeader = (repositoryNode: RawNode): NamespaceHeader => {
99
103
  const namespaceNode = getChildren(repositoryNode, "namespace")[0];
100
104
 
101
105
  if (namespaceNode === undefined) {
102
- throw new Error("GIR repository has no <namespace> child");
106
+ throw new Error(`GIR file at ${path} has no <namespace> child in its <repository>`);
103
107
  }
104
108
 
105
109
  return {
106
110
  name: nameAttr(namespaceNode),
111
+ girFile: path,
107
112
  sharedLibrary: attr(namespaceNode, "shared-library"),
108
113
  cSymbolPrefixes: splitPrefixes(attr(namespaceNode, "c:symbol-prefixes")),
109
114
  includes,
@@ -114,6 +119,7 @@ const parseNamespaceHeader = (repositoryNode: RawNode): NamespaceHeader => {
114
119
  const createNamespaceShell = (header: NamespaceHeader, id: number): GirNamespace => ({
115
120
  id,
116
121
  name: header.name,
122
+ girFile: header.girFile,
117
123
  sharedLibrary: header.sharedLibrary,
118
124
  cSymbolPrefixes: header.cSymbolPrefixes,
119
125
  classes: [],
@@ -23,6 +23,17 @@ type ParameterTransfer = "none" | "full" | "container";
23
23
  */
24
24
  type CallbackScope = "call" | "notified" | "async" | "forever";
25
25
 
26
+ /**
27
+ * Bounds of an out parameter that points into the buffer of a sibling parameter instead of to an
28
+ * array of its own, which GIR describes as an array with no extent of any kind.
29
+ */
30
+ type GirCursorBounds = {
31
+ /** Position of the parameter holding the buffer the pointer points into. */
32
+ baseIndex: number;
33
+ /** Position of the parameter carrying that buffer's element count. */
34
+ lengthIndex: number;
35
+ };
36
+
26
37
  /** A parameter of a {@link GirCallable}, with the annotations that decide how it is marshalled. */
27
38
  type GirParameter = {
28
39
  /** The name GIR gives the parameter. */
@@ -51,6 +62,8 @@ type GirParameter = {
51
62
  destroyIndex: number | undefined;
52
63
  /** Whether the parameter is the `...` varargs marker. */
53
64
  isVarargs: boolean;
65
+ /** Where the buffer is that the parameter points into, when it carries a cursor rather than an array. */
66
+ cursor: GirCursorBounds | undefined;
54
67
  };
55
68
 
56
69
  /** What a {@link GirCallable} hands back, with the annotations that decide how it is marshalled. */
@@ -118,6 +131,7 @@ const parameterFromNode = (node: RawNode, context: ParseContext): GirParameter =
118
131
  closureIndex: intAttr(node, "closure"),
119
132
  destroyIndex: intAttr(node, "destroy"),
120
133
  isVarargs: getChild(node, "varargs") !== undefined,
134
+ cursor: undefined,
121
135
  });
122
136
 
123
137
  const isOutParameter = (parameter: GirParameter): boolean =>
@@ -163,6 +177,7 @@ export {
163
177
  isInoutParameter,
164
178
  parseCallable,
165
179
  type ParameterTransfer,
180
+ type GirCursorBounds,
166
181
  type GirParameter,
167
182
  type GirReturnValue,
168
183
  type GirCallable,
package/src/gir/parse.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { readFileSync } from "node:fs";
2
- import { createXmlParser } from "../xml.js";
1
+ import { createXmlParser, parseXmlFile } from "../xml.js";
3
2
 
4
3
  /** An element of the parsed GIR XML: attributes under `@_`-prefixed keys, children under their tag names. */
5
4
  type RawNode = Record<string, unknown>;
6
5
 
6
+ const GIR_LABEL = "GIR file";
7
+
7
8
  const MULTI_TAGS: Set<string> = new Set([
8
9
  "include",
9
10
  "class",
@@ -42,11 +43,8 @@ function renameReservedTag(tag: string): string {
42
43
  return RESERVED_TAG_RENAMES.get(tag) ?? tag;
43
44
  }
44
45
 
45
- const parseGirFile = (path: string): RawNode => {
46
- const xml = readFileSync(path, "utf8");
47
-
48
- return PARSER.parse(xml) as RawNode;
49
- };
46
+ const parseGirFile = (path: string): RawNode =>
47
+ parseXmlFile({ parser: PARSER, label: GIR_LABEL, path }) as RawNode;
50
48
 
51
49
  const attr = (node: RawNode | undefined, name: string): string | undefined => {
52
50
  if (node === undefined) {
package/src/guards.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { isRecord } from "@gtkx/utils";
2
+
3
+ type Guard<T> = (value: unknown) => value is T;
4
+ type OptionalGuard<T> = Guard<T | undefined> & { __optional__: true };
5
+ type FieldGuard<T> = [undefined] extends [T] ? OptionalGuard<NonNullable<T>> : Guard<T>;
6
+ type FieldGuards<T> = { [K in keyof Required<T>]: FieldGuard<T[K]> };
7
+
8
+ const isBoolean = (value: unknown): value is boolean => typeof value === "boolean";
9
+ const isNumber = (value: unknown): value is number => typeof value === "number";
10
+ const isString = (value: unknown): value is string => typeof value === "string";
11
+
12
+ const arrayGuard = <T>(isEntry: Guard<T>): Guard<T[]> =>
13
+ (value: unknown): value is T[] => Array.isArray(value) && value.every((entry: unknown) => isEntry(entry));
14
+
15
+ const optionalGuard = <T>(isPresent: Guard<T>): OptionalGuard<T> =>
16
+ Object.assign((value: unknown): value is T | undefined => value === undefined || isPresent(value), {
17
+ __optional__: true as const,
18
+ });
19
+
20
+ const hasFields = <T extends object>(value: unknown, guards: FieldGuards<T>): value is T =>
21
+ isRecord(value) && Object.entries(guards).every(([name, guard]) => (guard as Guard<unknown>)(value[name]));
22
+
23
+ export { arrayGuard, hasFields, isBoolean, isNumber, isString, optionalGuard };
package/src/internal.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export { writeDocs } from "./docs/pipeline.js";
2
2
  export { runGlCodegen } from "./runner.js";
3
+ export { getShadowingStorePaths, sweepProjectStaging } from "./store/resolve-store.js";
4
+ export { ensureStoreLinks } from "./store/store-links.js";
package/src/json.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { readFileSync } from "node:fs";
2
+
3
+ const readJsonFile = (path: string): unknown => {
4
+ try {
5
+ return JSON.parse(readFileSync(path, "utf8")) as unknown;
6
+ } catch {
7
+ return undefined;
8
+ }
9
+ };
10
+
11
+ export { readJsonFile };
@@ -76,7 +76,10 @@ const renderEnumsModule = (tokens: EnumRow[], docs: GlDocContext): string => {
76
76
  const builder = new ModuleBuilder();
77
77
 
78
78
  for (const row of tokens) {
79
- builder.appendDeclaration(`${enumJsDoc(row, docs)}\nexport const ${row.exportName} = ${row.literal};`);
79
+ builder.appendDeclaration({
80
+ name: row.exportName,
81
+ code: `${enumJsDoc(row, docs)}\nexport const ${row.exportName} = ${row.literal};`,
82
+ });
80
83
  }
81
84
 
82
85
  return `${generatedHeader(docs)}\n\n${builder.toSource()}`;
@@ -135,7 +138,11 @@ const appendScalarAliases = (builder: ModuleBuilder, docs: GlDocContext): void =
135
138
  }
136
139
 
137
140
  seen.add(scalar.tsAlias);
138
- builder.appendDeclaration(`${scalarJsDoc(scalar.tsAlias, docs)}\nexport type ${scalar.tsAlias} = number;`);
141
+
142
+ builder.appendDeclaration({
143
+ name: scalar.tsAlias,
144
+ code: `${scalarJsDoc(scalar.tsAlias, docs)}\nexport type ${scalar.tsAlias} = number;`,
145
+ });
139
146
  }
140
147
  };
141
148
 
@@ -143,7 +150,10 @@ const appendGroupAliases = (builder: ModuleBuilder, groupAliases: Map<string, st
143
150
  const sorted = sortStringsBy(groupAliases.entries(), ([key]) => key);
144
151
 
145
152
  for (const [group, base] of sorted) {
146
- builder.appendDeclaration(`${groupAliasJsDoc(group, base, docs)}\nexport type ${group} = ${base};`);
153
+ builder.appendDeclaration({
154
+ name: group,
155
+ code: `${groupAliasJsDoc(group, base, docs)}\nexport type ${group} = ${base};`,
156
+ });
147
157
  }
148
158
  };
149
159
 
@@ -151,12 +161,18 @@ const renderTypesModule = (groupAliases: Map<string, string>, docs: GlDocContext
151
161
  const builder = new ModuleBuilder();
152
162
  builder.imports.addNamed("@gtkx/native", "ExternalObject", true);
153
163
  builder.imports.addNamed("@gtkx/native", "Handle", true);
154
- builder.appendDeclaration(`${syncJsDoc(docs)}\nexport type GLsync = ExternalObject<Handle>;`);
155
164
 
156
- builder.appendDeclaration(
157
- "/** An opaque native pointer handle (e.g. a `glMapBufferRange` mapping). */\n" +
158
- "export type GLpointer = ExternalObject<Handle>;",
159
- );
165
+ builder.appendDeclaration({
166
+ name: "GLsync",
167
+ code: `${syncJsDoc(docs)}\nexport type GLsync = ExternalObject<Handle>;`,
168
+ });
169
+
170
+ builder.appendDeclaration({
171
+ name: "GLpointer",
172
+ code:
173
+ "/** An opaque native pointer handle (e.g. a `glMapBufferRange` mapping). */\n" +
174
+ "export type GLpointer = ExternalObject<Handle>;",
175
+ });
160
176
 
161
177
  appendScalarAliases(builder, docs);
162
178
  appendGroupAliases(builder, groupAliases, docs);
@@ -184,7 +200,7 @@ const appendCommandBindings = (builder: ModuleBuilder, commands: RenderedCommand
184
200
 
185
201
  const appendCommandDeclarations = (builder: ModuleBuilder, commands: RenderedCommand[]): void => {
186
202
  for (const command of commands) {
187
- builder.appendDeclaration(command.declaration);
203
+ builder.appendDeclaration({ name: command.exportName, code: command.declaration });
188
204
  }
189
205
  };
190
206
 
@@ -1,10 +1,10 @@
1
- import { readFileSync } from "node:fs";
2
- import { createXmlParser } from "../xml.js";
1
+ import { createXmlParser, parseXmlFile } from "../xml.js";
3
2
 
4
3
  type OrderedNode = Record<string, unknown>;
5
4
 
6
5
  const ATTRIBUTES_KEY = ":@";
7
6
  const TEXT_KEY = "#text";
7
+ const REGISTRY_LABEL = "OpenGL registry";
8
8
 
9
9
  const PARSER = createXmlParser({
10
10
  trimValues: false,
@@ -12,8 +12,7 @@ const PARSER = createXmlParser({
12
12
  });
13
13
 
14
14
  const parseRegistryFile = (path: string): OrderedNode[] => {
15
- const xml = readFileSync(path, "utf8");
16
- const documentNodes = PARSER.parse(xml) as OrderedNode[];
15
+ const documentNodes = parseXmlFile({ parser: PARSER, label: REGISTRY_LABEL, path }) as OrderedNode[];
17
16
 
18
17
  for (const node of documentNodes) {
19
18
  if (nodeTag(node) === "registry") {
@@ -387,4 +387,4 @@ const generateGlModules = (options: GlGenerationOptions): GlGenerationResult =>
387
387
  };
388
388
  };
389
389
 
390
- export { generateGlModules, type GlGenerationReport, type GlGenerationResult };
390
+ export { generateGlModules, type GlGenerationReport };
@@ -328,7 +328,6 @@ const planCommand = (command: GlCommand, policy: GlPlanPolicy): CommandPlan => {
328
328
 
329
329
  export {
330
330
  GL_SCALARS,
331
- parseCType,
332
331
  planCommand,
333
332
  type GlScalar,
334
333
  type ParamPlan,