@gtkx/codegen 1.0.0 → 1.2.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 (347) 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 +59 -38
  5. package/dist/analysis/descriptor-render.js.map +1 -1
  6. package/dist/analysis/descriptor.d.ts +25 -10
  7. package/dist/analysis/descriptor.d.ts.map +1 -1
  8. package/dist/analysis/descriptor.js +37 -9
  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 +25 -0
  15. package/dist/analysis/interface-conflicts.d.ts.map +1 -0
  16. package/dist/analysis/interface-conflicts.js +139 -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 +3 -2
  24. package/dist/analysis/ts-type.d.ts.map +1 -1
  25. package/dist/analysis/ts-type.js +26 -26
  26. package/dist/analysis/ts-type.js.map +1 -1
  27. package/dist/analysis/type-key.d.ts +5 -0
  28. package/dist/analysis/type-key.d.ts.map +1 -0
  29. package/dist/analysis/type-key.js +9 -0
  30. package/dist/analysis/type-key.js.map +1 -0
  31. package/dist/analysis/type-shape.d.ts +3 -2
  32. package/dist/analysis/type-shape.d.ts.map +1 -1
  33. package/dist/analysis/type-shape.js +2 -1
  34. package/dist/analysis/type-shape.js.map +1 -1
  35. package/dist/compile.d.ts +14 -6
  36. package/dist/compile.d.ts.map +1 -1
  37. package/dist/compile.js +125 -24
  38. package/dist/compile.js.map +1 -1
  39. package/dist/docs/api-reference.d.ts +2 -0
  40. package/dist/docs/api-reference.d.ts.map +1 -1
  41. package/dist/docs/api-reference.js +11 -10
  42. package/dist/docs/api-reference.js.map +1 -1
  43. package/dist/docs/element-page.d.ts.map +1 -1
  44. package/dist/docs/element-page.js +5 -3
  45. package/dist/docs/element-page.js.map +1 -1
  46. package/dist/docs/pipeline.d.ts +1 -0
  47. package/dist/docs/pipeline.d.ts.map +1 -1
  48. package/dist/docs/pipeline.js +93 -19
  49. package/dist/docs/pipeline.js.map +1 -1
  50. package/dist/docs/render.d.ts +2 -1
  51. package/dist/docs/render.d.ts.map +1 -1
  52. package/dist/docs/render.js +5 -4
  53. package/dist/docs/render.js.map +1 -1
  54. package/dist/docs/symbol-page.d.ts.map +1 -1
  55. package/dist/docs/symbol-page.js +10 -9
  56. package/dist/docs/symbol-page.js.map +1 -1
  57. package/dist/fingerprint.d.ts +20 -3
  58. package/dist/fingerprint.d.ts.map +1 -1
  59. package/dist/fingerprint.js +56 -37
  60. package/dist/fingerprint.js.map +1 -1
  61. package/dist/gi.d.ts +1 -0
  62. package/dist/gi.d.ts.map +1 -1
  63. package/dist/gi.js +8 -2
  64. package/dist/gi.js.map +1 -1
  65. package/dist/gir/ancestry.d.ts +7 -1
  66. package/dist/gir/ancestry.d.ts.map +1 -1
  67. package/dist/gir/ancestry.js +9 -1
  68. package/dist/gir/ancestry.js.map +1 -1
  69. package/dist/gir/annotations.d.ts +1 -2
  70. package/dist/gir/annotations.d.ts.map +1 -1
  71. package/dist/gir/annotations.js +1 -1
  72. package/dist/gir/annotations.js.map +1 -1
  73. package/dist/gir/cursor-overrides.d.ts +8 -0
  74. package/dist/gir/cursor-overrides.d.ts.map +1 -0
  75. package/dist/gir/cursor-overrides.js +6 -0
  76. package/dist/gir/cursor-overrides.js.map +1 -0
  77. package/dist/gir/emittable.d.ts +7 -0
  78. package/dist/gir/emittable.d.ts.map +1 -0
  79. package/dist/gir/emittable.js +3 -0
  80. package/dist/gir/emittable.js.map +1 -0
  81. package/dist/gir/function.d.ts.map +1 -1
  82. package/dist/gir/function.js +28 -2
  83. package/dist/gir/function.js.map +1 -1
  84. package/dist/gir/gir-path.d.ts +1 -1
  85. package/dist/gir/gir-path.js +1 -1
  86. package/dist/gir/gir-path.js.map +1 -1
  87. package/dist/gir/library.d.ts +5 -1
  88. package/dist/gir/library.d.ts.map +1 -1
  89. package/dist/gir/library.js +9 -2
  90. package/dist/gir/library.js.map +1 -1
  91. package/dist/gir/namespace.d.ts +5 -1
  92. package/dist/gir/namespace.d.ts.map +1 -1
  93. package/dist/gir/namespace.js +4 -2
  94. package/dist/gir/namespace.js.map +1 -1
  95. package/dist/gir/parameter.d.ts +13 -1
  96. package/dist/gir/parameter.d.ts.map +1 -1
  97. package/dist/gir/parameter.js +1 -0
  98. package/dist/gir/parameter.js.map +1 -1
  99. package/dist/gir/parse.d.ts.map +1 -1
  100. package/dist/gir/parse.js +6 -6
  101. package/dist/gir/parse.js.map +1 -1
  102. package/dist/gir/primitives.js +1 -1
  103. package/dist/gir/primitives.js.map +1 -1
  104. package/dist/guards.d.ts +16 -0
  105. package/dist/guards.d.ts.map +1 -0
  106. package/dist/guards.js +11 -0
  107. package/dist/guards.js.map +1 -0
  108. package/dist/internal.d.ts +2 -0
  109. package/dist/internal.d.ts.map +1 -1
  110. package/dist/internal.js +2 -0
  111. package/dist/internal.js.map +1 -1
  112. package/dist/json.d.ts +3 -0
  113. package/dist/json.d.ts.map +1 -0
  114. package/dist/json.js +11 -0
  115. package/dist/json.js.map +1 -0
  116. package/dist/khronos/args.d.ts.map +1 -1
  117. package/dist/khronos/args.js +8 -6
  118. package/dist/khronos/args.js.map +1 -1
  119. package/dist/khronos/modules.d.ts.map +1 -1
  120. package/dist/khronos/modules.js +22 -7
  121. package/dist/khronos/modules.js.map +1 -1
  122. package/dist/khronos/parse.d.ts.map +1 -1
  123. package/dist/khronos/parse.js +3 -4
  124. package/dist/khronos/parse.js.map +1 -1
  125. package/dist/khronos/pipeline.d.ts +1 -1
  126. package/dist/khronos/pipeline.d.ts.map +1 -1
  127. package/dist/khronos/pipeline.js.map +1 -1
  128. package/dist/khronos/plan.d.ts +1 -7
  129. package/dist/khronos/plan.d.ts.map +1 -1
  130. package/dist/khronos/plan.js +1 -1
  131. package/dist/khronos/plan.js.map +1 -1
  132. package/dist/khronos/render.d.ts.map +1 -1
  133. package/dist/khronos/render.js +8 -4
  134. package/dist/khronos/render.js.map +1 -1
  135. package/dist/runner.d.ts +7 -1
  136. package/dist/runner.d.ts.map +1 -1
  137. package/dist/runner.js +21 -3
  138. package/dist/runner.js.map +1 -1
  139. package/dist/staging.d.ts +5 -0
  140. package/dist/staging.d.ts.map +1 -0
  141. package/dist/staging.js +57 -0
  142. package/dist/staging.js.map +1 -0
  143. package/dist/store/compile-store.d.ts +0 -1
  144. package/dist/store/compile-store.d.ts.map +1 -1
  145. package/dist/store/compile-store.js +7 -32
  146. package/dist/store/compile-store.js.map +1 -1
  147. package/dist/store/gi/callables.d.ts +6 -3
  148. package/dist/store/gi/callables.d.ts.map +1 -1
  149. package/dist/store/gi/callables.js +40 -30
  150. package/dist/store/gi/callables.js.map +1 -1
  151. package/dist/store/gi/callback.d.ts.map +1 -1
  152. package/dist/store/gi/callback.js +9 -5
  153. package/dist/store/gi/callback.js.map +1 -1
  154. package/dist/store/gi/class.d.ts.map +1 -1
  155. package/dist/store/gi/class.js +104 -44
  156. package/dist/store/gi/class.js.map +1 -1
  157. package/dist/store/gi/companion.d.ts.map +1 -1
  158. package/dist/store/gi/companion.js +6 -6
  159. package/dist/store/gi/companion.js.map +1 -1
  160. package/dist/store/gi/constant.d.ts.map +1 -1
  161. package/dist/store/gi/constant.js +11 -3
  162. package/dist/store/gi/constant.js.map +1 -1
  163. package/dist/store/gi/constructor-props.js +1 -1
  164. package/dist/store/gi/constructor-props.js.map +1 -1
  165. package/dist/store/gi/enum.d.ts.map +1 -1
  166. package/dist/store/gi/enum.js +29 -12
  167. package/dist/store/gi/enum.js.map +1 -1
  168. package/dist/store/gi/function.d.ts +1 -3
  169. package/dist/store/gi/function.d.ts.map +1 -1
  170. package/dist/store/gi/function.js +24 -18
  171. package/dist/store/gi/function.js.map +1 -1
  172. package/dist/store/gi/gtype-binding.d.ts.map +1 -1
  173. package/dist/store/gi/gtype-binding.js +4 -1
  174. package/dist/store/gi/gtype-binding.js.map +1 -1
  175. package/dist/store/gi/interface.d.ts.map +1 -1
  176. package/dist/store/gi/interface.js +34 -19
  177. package/dist/store/gi/interface.js.map +1 -1
  178. package/dist/store/gi/method.d.ts +7 -6
  179. package/dist/store/gi/method.d.ts.map +1 -1
  180. package/dist/store/gi/method.js +13 -24
  181. package/dist/store/gi/method.js.map +1 -1
  182. package/dist/store/gi/param-marshal.d.ts +3 -2
  183. package/dist/store/gi/param-marshal.d.ts.map +1 -1
  184. package/dist/store/gi/param-marshal.js +50 -5
  185. package/dist/store/gi/param-marshal.js.map +1 -1
  186. package/dist/store/gi/pipeline.d.ts.map +1 -1
  187. package/dist/store/gi/pipeline.js +21 -10
  188. package/dist/store/gi/pipeline.js.map +1 -1
  189. package/dist/store/gi/properties.d.ts +2 -1
  190. package/dist/store/gi/properties.d.ts.map +1 -1
  191. package/dist/store/gi/properties.js +6 -3
  192. package/dist/store/gi/properties.js.map +1 -1
  193. package/dist/store/gi/property-accessor.d.ts +10 -8
  194. package/dist/store/gi/property-accessor.d.ts.map +1 -1
  195. package/dist/store/gi/property-accessor.js +49 -91
  196. package/dist/store/gi/property-accessor.js.map +1 -1
  197. package/dist/store/gi/record-constructor.d.ts +8 -1
  198. package/dist/store/gi/record-constructor.d.ts.map +1 -1
  199. package/dist/store/gi/record-constructor.js +34 -13
  200. package/dist/store/gi/record-constructor.js.map +1 -1
  201. package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
  202. package/dist/store/gi/record-field-accessor.js +20 -4
  203. package/dist/store/gi/record-field-accessor.js.map +1 -1
  204. package/dist/store/gi/record-layout.d.ts +6 -1
  205. package/dist/store/gi/record-layout.d.ts.map +1 -1
  206. package/dist/store/gi/record-layout.js +8 -1
  207. package/dist/store/gi/record-layout.js.map +1 -1
  208. package/dist/store/gi/record.d.ts.map +1 -1
  209. package/dist/store/gi/record.js +19 -8
  210. package/dist/store/gi/record.js.map +1 -1
  211. package/dist/store/gi/registration.js +2 -2
  212. package/dist/store/gi/registration.js.map +1 -1
  213. package/dist/store/gi/return-wrap.js +1 -1
  214. package/dist/store/gi/return-wrap.js.map +1 -1
  215. package/dist/store/gi/signal.d.ts +2 -1
  216. package/dist/store/gi/signal.d.ts.map +1 -1
  217. package/dist/store/gi/signal.js +55 -28
  218. package/dist/store/gi/signal.js.map +1 -1
  219. package/dist/store/gi/value-marshalable.d.ts.map +1 -1
  220. package/dist/store/gi/value-marshalable.js +2 -1
  221. package/dist/store/gi/value-marshalable.js.map +1 -1
  222. package/dist/store/gi/vtable.d.ts +4 -1
  223. package/dist/store/gi/vtable.d.ts.map +1 -1
  224. package/dist/store/gi/vtable.js +60 -17
  225. package/dist/store/gi/vtable.js.map +1 -1
  226. package/dist/store/gi-store.d.ts +1 -0
  227. package/dist/store/gi-store.d.ts.map +1 -1
  228. package/dist/store/gi-store.js +15 -20
  229. package/dist/store/gi-store.js.map +1 -1
  230. package/dist/store/jsx/generated-elements.d.ts +2 -1
  231. package/dist/store/jsx/generated-elements.d.ts.map +1 -1
  232. package/dist/store/jsx/generated-elements.js +13 -7
  233. package/dist/store/jsx/generated-elements.js.map +1 -1
  234. package/dist/store/jsx/jsx.js +3 -3
  235. package/dist/store/jsx/jsx.js.map +1 -1
  236. package/dist/store/jsx/metadata.d.ts.map +1 -1
  237. package/dist/store/jsx/metadata.js +3 -1
  238. package/dist/store/jsx/metadata.js.map +1 -1
  239. package/dist/store/jsx-store.d.ts.map +1 -1
  240. package/dist/store/jsx-store.js +3 -4
  241. package/dist/store/jsx-store.js.map +1 -1
  242. package/dist/store/resolve-store.d.ts +14 -3
  243. package/dist/store/resolve-store.d.ts.map +1 -1
  244. package/dist/store/resolve-store.js +98 -15
  245. package/dist/store/resolve-store.js.map +1 -1
  246. package/dist/store/store-fs.d.ts +9 -7
  247. package/dist/store/store-fs.d.ts.map +1 -1
  248. package/dist/store/store-fs.js +54 -25
  249. package/dist/store/store-fs.js.map +1 -1
  250. package/dist/store/store-links.d.ts +3 -0
  251. package/dist/store/store-links.d.ts.map +1 -0
  252. package/dist/store/store-links.js +39 -0
  253. package/dist/store/store-links.js.map +1 -0
  254. package/dist/writer/comparison-context.d.ts +4 -0
  255. package/dist/writer/comparison-context.d.ts.map +1 -0
  256. package/dist/writer/comparison-context.js +13 -0
  257. package/dist/writer/comparison-context.js.map +1 -0
  258. package/dist/writer/context.d.ts +3 -3
  259. package/dist/writer/context.d.ts.map +1 -1
  260. package/dist/writer/context.js +11 -6
  261. package/dist/writer/context.js.map +1 -1
  262. package/dist/writer/module.d.ts +13 -5
  263. package/dist/writer/module.d.ts.map +1 -1
  264. package/dist/writer/module.js +68 -11
  265. package/dist/writer/module.js.map +1 -1
  266. package/dist/xml.d.ts +8 -1
  267. package/dist/xml.d.ts.map +1 -1
  268. package/dist/xml.js +70 -1
  269. package/dist/xml.js.map +1 -1
  270. package/overrides/gobject/object.ts.ejs +2 -0
  271. package/package.json +14 -3
  272. package/src/analysis/descriptor-render.ts +106 -52
  273. package/src/analysis/descriptor.ts +76 -15
  274. package/src/analysis/inheritance.ts +134 -44
  275. package/src/analysis/interface-conflicts.ts +235 -0
  276. package/src/analysis/param-capability.ts +3 -6
  277. package/src/analysis/param-structure.ts +2 -2
  278. package/src/analysis/ts-type.ts +43 -28
  279. package/src/analysis/type-key.ts +14 -0
  280. package/src/analysis/type-shape.ts +5 -2
  281. package/src/compile.ts +192 -27
  282. package/src/docs/api-reference.ts +13 -10
  283. package/src/docs/element-page.ts +5 -2
  284. package/src/docs/pipeline.ts +140 -24
  285. package/src/docs/render.ts +7 -3
  286. package/src/docs/symbol-page.ts +12 -11
  287. package/src/fingerprint.ts +95 -47
  288. package/src/gi.ts +10 -2
  289. package/src/gir/ancestry.ts +17 -1
  290. package/src/gir/annotations.ts +1 -1
  291. package/src/gir/cursor-overrides.ts +12 -0
  292. package/src/gir/emittable.ts +8 -0
  293. package/src/gir/function.ts +45 -9
  294. package/src/gir/gir-path.ts +1 -1
  295. package/src/gir/library.ts +10 -2
  296. package/src/gir/namespace.ts +8 -2
  297. package/src/gir/parameter.ts +15 -0
  298. package/src/gir/parse.ts +10 -7
  299. package/src/gir/primitives.ts +1 -1
  300. package/src/guards.ts +23 -0
  301. package/src/internal.ts +2 -0
  302. package/src/json.ts +11 -0
  303. package/src/khronos/args.ts +9 -6
  304. package/src/khronos/modules.ts +25 -9
  305. package/src/khronos/parse.ts +3 -4
  306. package/src/khronos/pipeline.ts +1 -1
  307. package/src/khronos/plan.ts +0 -1
  308. package/src/khronos/render.ts +8 -6
  309. package/src/runner.ts +26 -4
  310. package/src/staging.ts +67 -0
  311. package/src/store/compile-store.ts +7 -38
  312. package/src/store/gi/callables.ts +60 -33
  313. package/src/store/gi/callback.ts +9 -9
  314. package/src/store/gi/class.ts +140 -53
  315. package/src/store/gi/companion.ts +7 -6
  316. package/src/store/gi/constant.ts +13 -3
  317. package/src/store/gi/constructor-props.ts +1 -1
  318. package/src/store/gi/enum.ts +36 -26
  319. package/src/store/gi/function.ts +30 -24
  320. package/src/store/gi/gtype-binding.ts +7 -2
  321. package/src/store/gi/interface.ts +39 -20
  322. package/src/store/gi/method.ts +26 -32
  323. package/src/store/gi/param-marshal.ts +77 -6
  324. package/src/store/gi/pipeline.ts +25 -15
  325. package/src/store/gi/properties.ts +8 -4
  326. package/src/store/gi/property-accessor.ts +73 -161
  327. package/src/store/gi/record-constructor.ts +53 -21
  328. package/src/store/gi/record-field-accessor.ts +26 -4
  329. package/src/store/gi/record-layout.ts +11 -1
  330. package/src/store/gi/record.ts +20 -12
  331. package/src/store/gi/registration.ts +2 -2
  332. package/src/store/gi/return-wrap.ts +1 -1
  333. package/src/store/gi/signal.ts +66 -42
  334. package/src/store/gi/value-marshalable.ts +3 -1
  335. package/src/store/gi/vtable.ts +97 -20
  336. package/src/store/gi-store.ts +26 -31
  337. package/src/store/jsx/generated-elements.ts +17 -8
  338. package/src/store/jsx/jsx.ts +3 -3
  339. package/src/store/jsx/metadata.ts +4 -1
  340. package/src/store/jsx-store.ts +3 -4
  341. package/src/store/resolve-store.ts +133 -18
  342. package/src/store/store-fs.ts +82 -35
  343. package/src/store/store-links.ts +49 -0
  344. package/src/writer/comparison-context.ts +18 -0
  345. package/src/writer/context.ts +12 -6
  346. package/src/writer/module.ts +101 -14
  347. package/src/xml.ts +103 -1
@@ -1,9 +1,17 @@
1
1
  import { sortStringsBy } from "@gtkx/utils";
2
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { mkdirSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
- import { computeGiFingerprint, FINGERPRINT_FILENAME, isGiStoreFresh } from "../fingerprint.js";
4
+ import {
5
+ computeDocsFingerprint,
6
+ type DocsFingerprintInput,
7
+ FINGERPRINT_FILENAME,
8
+ type GiInputs,
9
+ isDocsOutputFresh,
10
+ } from "../fingerprint.js";
5
11
  import { Library } from "../gir/library.js";
6
12
  import { namespaceDirectory } from "../gir/namespace.js";
13
+ import { arrayGuard, hasFields, isString } from "../guards.js";
14
+ import { readJsonFile } from "../json.js";
7
15
  import { type ElementProps, setElementProps } from "../store/jsx/element-prop-imports.js";
8
16
  import { collectIntrinsicElementClasses, type GlibNamedClass } from "../store/jsx/intrinsic-elements.js";
9
17
  import { type OmittedProps, setOmittedProps } from "../store/jsx/omitted-props.js";
@@ -30,9 +38,11 @@ type DocsOptions = {
30
38
  props?: ElementProps;
31
39
  omittedProps?: OmittedProps;
32
40
  isForced?: boolean;
41
+ isByteArrayTyped?: boolean;
33
42
  };
34
43
 
35
44
  type DocsManifest = {
45
+ generator: string;
36
46
  namespaces: DocsNamespace[];
37
47
  };
38
48
 
@@ -50,6 +60,9 @@ type DocsResult = {
50
60
  };
51
61
 
52
62
  const MANIFEST_FILENAME = "manifest.json";
63
+ const MANIFEST_GENERATOR = "gtkx-docs";
64
+ const ROOT_INDEX_FILENAME = "index.md";
65
+ const DEFAULT_BASE_PATH = "/reference";
53
66
 
54
67
  const namespaceIndexPage = (namespace: DocsNamespace, elements: GlibNamedClass[]): string => {
55
68
  const rows = elements.map((entry, index) => {
@@ -144,6 +157,28 @@ const buildElementLinks = (elements: GlibNamedClass[], basePath: string): Map<st
144
157
  return linkByGlibName;
145
158
  };
146
159
 
160
+ const isEntryInsideOutDir = (value: string): boolean =>
161
+ value.length > 0 && value !== "." && value !== ".." && !value.includes("/") && !value.includes("\\");
162
+
163
+ const isChildEntry = (value: unknown): value is string => isString(value) && isEntryInsideOutDir(value);
164
+
165
+ const ownedEntry = (entry: string, source: string): string => {
166
+ if (isEntryInsideOutDir(entry)) {
167
+ return entry;
168
+ }
169
+
170
+ throw new Error(
171
+ `Refusing to generate documentation outside the output directory: ${source} maps to \`${entry}\`, ` +
172
+ "which is not an entry inside it. The GIR that declares it is malformed.",
173
+ );
174
+ };
175
+
176
+ const elementPagePath = (directory: string, entry: GlibNamedClass): string => {
177
+ const slug = ownedEntry(elementSlug(entry.klass.name), `the element ${entry.glibName}`);
178
+
179
+ return `${directory}/${slug}.md`;
180
+ };
181
+
147
182
  const namespacePages = (input: {
148
183
  name: string;
149
184
  elements: GlibNamedClass[];
@@ -152,7 +187,7 @@ const namespacePages = (input: {
152
187
  pageContext: ElementPageContext;
153
188
  }): NamespacePages => {
154
189
  const { name, elements, basePath, linkByGlibName, pageContext } = input;
155
- const directory = name.toLowerCase();
190
+ const directory = ownedEntry(namespaceDirectory({ name }), `the GIR namespace ${name}`);
156
191
 
157
192
  const docs: DocsNamespace = {
158
193
  name,
@@ -162,7 +197,7 @@ const namespacePages = (input: {
162
197
  };
163
198
 
164
199
  const pages: Page[] = elements.map((entry) => ({
165
- path: `${directory}/${elementSlug(entry.klass.name)}.md`,
200
+ path: elementPagePath(directory, entry),
166
201
  content: renderElementPage(entry, pageContext),
167
202
  }));
168
203
 
@@ -187,21 +222,97 @@ const generatePages = (options: DocsOptions, basePath: string, library: Library)
187
222
  namespaces.push(result.docs);
188
223
  }
189
224
 
190
- pages.push({ path: "index.md", content: rootIndexPage(namespaces, options.libraries) });
225
+ pages.push({ path: ROOT_INDEX_FILENAME, content: rootIndexPage(namespaces, options.libraries) });
191
226
 
192
227
  return { pages, namespaces };
193
228
  };
194
229
 
195
- const cachedDocsResult = (options: DocsOptions, manifestPath: string): DocsResult | undefined => {
196
- if (options.isForced === true || !isGiStoreFresh(options.outDir, options.libraries, options.girPath)) {
197
- return undefined;
230
+ const isGeneratorTag = (value: unknown): value is string => value === MANIFEST_GENERATOR;
231
+
232
+ const isDocsElementLink = (value: unknown): value is DocsElementLink =>
233
+ hasFields<DocsElementLink>(value, { text: isString, link: isString });
234
+
235
+ const isDocsNamespace = (value: unknown): value is DocsNamespace =>
236
+ hasFields<DocsNamespace>(value, {
237
+ name: isString,
238
+ directory: isChildEntry,
239
+ link: isString,
240
+ elements: arrayGuard(isDocsElementLink),
241
+ });
242
+
243
+ const isDocsManifest = (value: unknown): value is DocsManifest =>
244
+ hasFields<DocsManifest>(value, { generator: isGeneratorTag, namespaces: arrayGuard(isDocsNamespace) });
245
+
246
+ const readDocsManifest = (manifestPath: string): DocsManifest | undefined => {
247
+ const parsed = readJsonFile(manifestPath);
248
+
249
+ return isDocsManifest(parsed) ? parsed : undefined;
250
+ };
251
+
252
+ const outDirRefusal = (outDir: string, reason: string): Error =>
253
+ new Error(
254
+ `Refusing to generate documentation into ${outDir}: ${reason}. Point the output directory at an ` +
255
+ "empty directory or at one gtkx generated, or remove it yourself first.",
256
+ );
257
+
258
+ const giInputs = (options: DocsOptions, girFiles: string[]): GiInputs => ({
259
+ girFiles,
260
+ libraries: options.libraries,
261
+ girPath: options.girPath,
262
+ isByteArrayTyped: options.isByteArrayTyped === true,
263
+ });
264
+
265
+ const assertOwnedOutDir = (options: DocsOptions, manifest: DocsManifest | undefined): void => {
266
+ const stats = statSync(options.outDir, { throwIfNoEntry: false });
267
+
268
+ if (stats === undefined) {
269
+ return;
270
+ }
271
+
272
+ if (!stats.isDirectory()) {
273
+ throw outDirRefusal(options.outDir, "it already exists and is not a directory");
198
274
  }
199
275
 
200
- if (!existsSync(manifestPath)) {
276
+ if (manifest !== undefined || readdirSync(options.outDir).length === 0) {
277
+ return;
278
+ }
279
+
280
+ throw outDirRefusal(
281
+ options.outDir,
282
+ `it is not empty and holds no ${MANIFEST_FILENAME} written by \`gtkx docs\`, ` +
283
+ "so its contents are not gtkx's to replace",
284
+ );
285
+ };
286
+
287
+ const clearOutDir = (options: DocsOptions, manifest: DocsManifest | undefined): void => {
288
+ if (manifest === undefined) {
289
+ return;
290
+ }
291
+
292
+ const entries = [
293
+ ...manifest.namespaces.map((namespace) => namespace.directory),
294
+ ROOT_INDEX_FILENAME,
295
+ MANIFEST_FILENAME,
296
+ FINGERPRINT_FILENAME,
297
+ ];
298
+
299
+ for (const entry of entries) {
300
+ rmSync(join(options.outDir, entry), { recursive: true, force: true });
301
+ }
302
+ };
303
+
304
+ const cachedDocsResult = (
305
+ options: DocsOptions,
306
+ manifest: DocsManifest | undefined,
307
+ input: DocsFingerprintInput,
308
+ ): DocsResult | undefined => {
309
+ if (manifest === undefined || options.isForced === true) {
201
310
  return undefined;
202
311
  }
203
312
 
204
- const manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as DocsManifest;
313
+ if (!isDocsOutputFresh(options.outDir, giInputs(options, []), input)) {
314
+ return undefined;
315
+ }
205
316
 
206
317
  return { isRegenerated: false, namespaces: manifest.namespaces };
207
318
  };
@@ -214,29 +325,34 @@ const writePages = (outDir: string, pages: Page[]): void => {
214
325
  }
215
326
  };
216
327
 
328
+ const docsFingerprintInput = (options: DocsOptions): DocsFingerprintInput => ({
329
+ basePath: options.basePath ?? DEFAULT_BASE_PATH,
330
+ props: options.props ?? {},
331
+ omittedProps: options.omittedProps ?? {},
332
+ });
333
+
217
334
  const writeDocs = (options: DocsOptions): DocsResult => {
218
- setElementProps(options.props ?? {});
219
- setOmittedProps(options.omittedProps ?? {});
220
- const basePath = options.basePath ?? "/reference";
335
+ const input = docsFingerprintInput(options);
336
+ setElementProps(input.props);
337
+ setOmittedProps(input.omittedProps);
221
338
  const manifestPath = join(options.outDir, MANIFEST_FILENAME);
222
- const cached = cachedDocsResult(options, manifestPath);
339
+ const previous = readDocsManifest(manifestPath);
340
+ const cached = cachedDocsResult(options, previous, input);
223
341
 
224
342
  if (cached !== undefined) {
225
343
  return cached;
226
344
  }
227
345
 
228
- const library = Library.load(options.libraries, options.girPath);
229
- const { pages, namespaces } = generatePages(options, basePath, library);
230
- rmSync(options.outDir, { recursive: true, force: true });
346
+ assertOwnedOutDir(options, previous);
347
+ const library = Library.load(options.libraries, options.girPath, options.isByteArrayTyped === true);
348
+ const { pages, namespaces } = generatePages(options, input.basePath, library);
349
+ clearOutDir(options, previous);
231
350
  mkdirSync(options.outDir, { recursive: true });
232
- writePages(options.outDir, pages);
233
- const manifest: DocsManifest = { namespaces };
351
+ const manifest: DocsManifest = { generator: MANIFEST_GENERATOR, namespaces };
234
352
  writeFileSync(manifestPath, JSON.stringify(manifest));
235
-
236
- writeFileSync(
237
- join(options.outDir, FINGERPRINT_FILENAME),
238
- JSON.stringify(computeGiFingerprint(library.girFiles, options.libraries, options.girPath)),
239
- );
353
+ writePages(options.outDir, pages);
354
+ const fingerprint = computeDocsFingerprint(giInputs(options, library.girFiles), input);
355
+ writeFileSync(join(options.outDir, FINGERPRINT_FILENAME), JSON.stringify(fingerprint));
240
356
 
241
357
  return { isRegenerated: true, namespaces };
242
358
  };
@@ -1,4 +1,4 @@
1
- import { pascalCase, sortStringsBy } from "@gtkx/utils";
1
+ import { sanitizeTypeIdentifier, sortStringsBy } 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 { GirFunction } from "../gir/function.js";
@@ -286,10 +286,13 @@ const originSignatureBlocks = (entries: OriginSignatureEntry[]): string[] =>
286
286
  signatureEntryBlock(item, item.origin === undefined ? [] : [`From \`${item.origin}\`.`]),
287
287
  );
288
288
 
289
+ const qualifiedClassName = (namespaceName: string, className: string): string =>
290
+ `${namespaceName}.${sanitizeTypeIdentifier(className)}`;
291
+
289
292
  const classMethodEntries = (library: Library, namespace: GirNamespace, klass: GirClass): SignatureEntry[] => {
290
293
  const realContext = new ModuleContext(namespace, library);
291
294
  const signatureContext = docsSignatureContext(namespace, library);
292
- const className = pascalCase(klass.name);
295
+ const className = sanitizeTypeIdentifier(klass.name);
293
296
  const inherited = collectInheritedMethods(realContext, klass);
294
297
 
295
298
  return instanceMethodEntries(signatureContext, klass, (method) =>
@@ -307,7 +310,7 @@ const instanceMethodEntries = (
307
310
  ): SignatureEntry[] => {
308
311
  const deduped = dedupeCallables(klass.methods);
309
312
 
310
- const scope = instanceScope(pascalCase(klass.name), {
313
+ const scope = instanceScope(sanitizeTypeIdentifier(klass.name), {
311
314
  constructors: dedupeCallables(klass.constructors),
312
315
  functions: dedupeCallables(klass.functions),
313
316
  methods: deduped,
@@ -362,6 +365,7 @@ export {
362
365
  originSignatureBlocks,
363
366
  classMethodEntries,
364
367
  methodsSectionBlocks,
368
+ qualifiedClassName,
365
369
  tagNotes,
366
370
  type MetaDocEntry,
367
371
  type SignatureEntry,
@@ -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";
@@ -16,7 +16,6 @@ import { PRIMITIVE_TS_TYPE, primitiveCategory } from "../gir/primitives.js";
16
16
  import { callableSpec } from "../store/gi/callable-doc.js";
17
17
  import {
18
18
  dedupeCallables,
19
- indexMethodsByName,
20
19
  instanceScope,
21
20
  matchStaticFinishFunction,
22
21
  renderInstanceMethodSignature,
@@ -51,6 +50,7 @@ import {
51
50
  type OriginSignatureEntry,
52
51
  plainText,
53
52
  propertyMetaLine,
53
+ qualifiedClassName,
54
54
  renderDocsSignalHandlerType,
55
55
  renderDocsType,
56
56
  signalTags,
@@ -145,7 +145,6 @@ type MemberOwner = {
145
145
  type PropertyAccessorSetup = {
146
146
  context: ModuleContext;
147
147
  claimedNames: Set<string>;
148
- methodByName: Map<string, GirFunction>;
149
148
  };
150
149
 
151
150
  type ResolvedRecordField = NonNullable<ReturnType<typeof resolveRecordFieldEntry>>;
@@ -202,9 +201,6 @@ const pageHeader = (entry: GiSymbolEntry, kindLabel: string): string[] => [
202
201
  importBlock(entry),
203
202
  ];
204
203
 
205
- const qualifiedClassName = (namespaceName: string, className: string): string =>
206
- `${namespaceName}.${pascalCase(className)}`;
207
-
208
204
  const elementNote = (entry: ClassSymbol, options: SymbolPageOptions): string[] => {
209
205
  const glibName = options.elementNameFor(entry.namespace.name, entry.klass.name);
210
206
 
@@ -354,7 +350,7 @@ const memberOwners = (entry: ClassSymbol, library: Library): MemberOwner[] => [
354
350
 
355
351
  const interfaceMethodNames = (library: Library, owner: MemberOwner): string[] => {
356
352
  const context = docsSignatureContext(owner.namespace, library);
357
- const className = pascalCase(owner.klass.name);
353
+ const className = sanitizeTypeIdentifier(owner.klass.name);
358
354
  const methods = dedupeCallables(owner.klass.methods);
359
355
 
360
356
  const scope = instanceScope(className, {
@@ -393,7 +389,6 @@ const propertyAccessorSetup = (
393
389
  return {
394
390
  context: docsSignatureContext(owner.namespace, library),
395
391
  claimedNames,
396
- methodByName: indexMethodsByName(dedupeCallables(owner.klass.methods)),
397
392
  };
398
393
  };
399
394
 
@@ -402,9 +397,16 @@ const getAccessNotes = (accessor: ResolvedAccessor): string[] => {
402
397
  return ["read-only"];
403
398
  }
404
399
 
405
- return accessor.hasGetter ? [] : ["write-only"];
400
+ if (!accessor.hasGetter) {
401
+ return ["write-only"];
402
+ }
403
+
404
+ return accessor.readType === accessor.writeType ? [] : [`writes \`${accessor.writeType}\``];
406
405
  };
407
406
 
407
+ const documentedAccessorType = (accessor: ResolvedAccessor): string =>
408
+ accessor.hasGetter ? accessor.readType : accessor.writeType;
409
+
408
410
  const ownerPropertyEntries = (owner: MemberOwner, setup: PropertyAccessorSetup, seen: Set<string>): MetaDocEntry[] => {
409
411
  const entries: MetaDocEntry[] = [];
410
412
 
@@ -413,7 +415,6 @@ const ownerPropertyEntries = (owner: MemberOwner, setup: PropertyAccessorSetup,
413
415
  context: setup.context,
414
416
  property,
415
417
  claimedNames: setup.claimedNames,
416
- methodByName: setup.methodByName,
417
418
  });
418
419
 
419
420
  if (accessor === undefined || seen.has(accessor.jsName)) {
@@ -425,7 +426,7 @@ const ownerPropertyEntries = (owner: MemberOwner, setup: PropertyAccessorSetup,
425
426
  entries.push({
426
427
  name: accessor.jsName,
427
428
  meta: propertyMetaLine({
428
- type: accessor.tsType,
429
+ type: documentedAccessorType(accessor),
429
430
  property,
430
431
  accessNotes: getAccessNotes(accessor),
431
432
  origin: owner.origin,
@@ -1,9 +1,18 @@
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";
9
+
10
+ type GiInputs = {
11
+ girFiles: string[];
12
+ libraries: string[];
13
+ girPath: string[];
14
+ isByteArrayTyped: boolean;
15
+ };
7
16
 
8
17
  type GiFingerprint = {
9
18
  value: string;
@@ -14,6 +23,17 @@ type GiFingerprint = {
14
23
 
15
24
  type ModuleExport = { module: string; export: string };
16
25
 
26
+ type DocsFingerprintInput = {
27
+ basePath: string;
28
+ props: Record<string, ModuleExport>;
29
+ omittedProps: Record<string, string[]>;
30
+ };
31
+
32
+ type DocsFingerprint = {
33
+ value: string;
34
+ gi: GiFingerprint;
35
+ };
36
+
17
37
  type JsxFingerprintInput = {
18
38
  reactVersion: string;
19
39
  components: Record<string, ModuleExport>;
@@ -27,9 +47,8 @@ type JsxFingerprint = {
27
47
  intrinsicElementCount: number;
28
48
  };
29
49
 
30
- const require = createRequire(import.meta.url);
31
50
  const FINGERPRINT_FILENAME = ".codegen-fingerprint.json";
32
- const CODEGEN_VERSION: string = (require("../package.json") as { version: string }).version;
51
+ const CODEGEN_VERSION: string = packageManifest.version;
33
52
  const OVERRIDES_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "overrides");
34
53
 
35
54
  const sortAlpha = (values: string[]): string => sortStrings(values).join(",");
@@ -44,15 +63,17 @@ const overrideFiles = (): string[] => {
44
63
  .map((entry: Dirent) => join(entry.parentPath, entry.name));
45
64
  };
46
65
 
47
- const hashGi = (girFiles: string[], libraries: string[], girPath: string[]): string => {
66
+ const hashGi = (inputs: GiInputs): string => {
48
67
  const hash = createHash("sha256");
49
68
  hash.update(CODEGEN_VERSION);
50
69
  hash.update("\n");
51
- hash.update(sortAlpha(libraries));
70
+ hash.update(sortAlpha(inputs.libraries));
71
+ hash.update("\n");
72
+ hash.update(sortAlpha(inputs.girPath));
52
73
  hash.update("\n");
53
- hash.update(sortAlpha(girPath));
74
+ hash.update(String(inputs.isByteArrayTyped));
54
75
  hash.update("\n");
55
- const hashedFiles = sortStrings([...girFiles, ...overrideFiles()]);
76
+ const hashedFiles = sortStrings([...inputs.girFiles, ...overrideFiles()]);
56
77
 
57
78
  for (const file of hashedFiles) {
58
79
  hash.update("\n");
@@ -64,49 +85,80 @@ const hashGi = (girFiles: string[], libraries: string[], girPath: string[]): str
64
85
  return hash.digest("hex");
65
86
  };
66
87
 
67
- const computeGiFingerprint = (
68
- girFiles: string[],
69
- libraries: string[],
70
- girPath: string[],
71
- ): GiFingerprint => ({
72
- value: hashGi(girFiles, libraries, girPath),
73
- girFiles,
74
- libraries,
75
- girPath,
88
+ const computeGiFingerprint = (inputs: GiInputs): GiFingerprint => ({
89
+ value: hashGi(inputs),
90
+ girFiles: inputs.girFiles,
91
+ libraries: inputs.libraries,
92
+ girPath: inputs.girPath,
76
93
  });
77
94
 
78
- const isGiStoreFresh = (
79
- giStoreDir: string,
80
- libraries: string[],
81
- girPath: string[],
82
- ): boolean => {
83
- const sentinelPath = join(giStoreDir, FINGERPRINT_FILENAME);
95
+ const readSentinel = (storeDir: string): unknown => readJsonFile(join(storeDir, FINGERPRINT_FILENAME));
84
96
 
85
- if (!existsSync(sentinelPath)) {
86
- return false;
87
- }
97
+ const isGiFingerprint = (value: unknown): value is GiFingerprint =>
98
+ hasFields<GiFingerprint>(value, {
99
+ value: isString,
100
+ girFiles: arrayGuard(isString),
101
+ libraries: arrayGuard(isString),
102
+ girPath: optionalGuard(arrayGuard(isString)),
103
+ });
88
104
 
89
- let sentinel: GiFingerprint;
105
+ const isDocsFingerprint = (value: unknown): value is DocsFingerprint =>
106
+ hasFields<DocsFingerprint>(value, { value: isString, gi: isGiFingerprint });
90
107
 
91
- try {
92
- sentinel = JSON.parse(readFileSync(sentinelPath, "utf8")) as GiFingerprint;
93
- } catch {
94
- return false;
95
- }
108
+ const isJsxFingerprint = (value: unknown): value is JsxFingerprint =>
109
+ hasFields<JsxFingerprint>(value, { value: isString, intrinsicElementCount: isNumber });
96
110
 
97
- if (!hasMatchingRecordedInputs(sentinel, libraries, girPath)) {
98
- return false;
111
+ const recordedGiValue = (sentinel: GiFingerprint, inputs: GiInputs): string | undefined => {
112
+ if (!hasMatchingRecordedInputs(sentinel, inputs)) {
113
+ return undefined;
99
114
  }
100
115
 
101
116
  try {
102
- return hashGi(sentinel.girFiles, sentinel.libraries, girPath) === sentinel.value;
117
+ return hashGi({ ...inputs, girFiles: sentinel.girFiles, libraries: sentinel.libraries });
103
118
  } catch {
104
- return false;
119
+ return undefined;
105
120
  }
106
121
  };
107
122
 
108
- const hasMatchingRecordedInputs = (sentinel: GiFingerprint, libraries: string[], girPath: string[]): boolean =>
109
- sortAlpha(sentinel.libraries) === sortAlpha(libraries) && sortAlpha(sentinel.girPath ?? []) === sortAlpha(girPath);
123
+ const isGiStoreFresh = (giStoreDir: string, inputs: GiInputs): boolean => {
124
+ const sentinel = readSentinel(giStoreDir);
125
+
126
+ return isGiFingerprint(sentinel) && recordedGiValue(sentinel, inputs) === sentinel.value;
127
+ };
128
+
129
+ const hasMatchingRecordedInputs = (sentinel: GiFingerprint, inputs: GiInputs): boolean =>
130
+ sortAlpha(sentinel.libraries) === sortAlpha(inputs.libraries) &&
131
+ sortAlpha(sentinel.girPath ?? []) === sortAlpha(inputs.girPath);
132
+
133
+ const hashDocs = (giValue: string, input: DocsFingerprintInput): string =>
134
+ createHash("sha256")
135
+ .update(
136
+ JSON.stringify([
137
+ giValue,
138
+ input.basePath,
139
+ serializeModuleExports(input.props),
140
+ serializeOmittedProps(input.omittedProps),
141
+ ]),
142
+ )
143
+ .digest("hex");
144
+
145
+ const computeDocsFingerprint = (inputs: GiInputs, input: DocsFingerprintInput): DocsFingerprint => {
146
+ const gi = computeGiFingerprint(inputs);
147
+
148
+ return { value: hashDocs(gi.value, input), gi };
149
+ };
150
+
151
+ const isDocsOutputFresh = (outDir: string, inputs: GiInputs, input: DocsFingerprintInput): boolean => {
152
+ const sentinel = readSentinel(outDir);
153
+
154
+ if (!isDocsFingerprint(sentinel)) {
155
+ return false;
156
+ }
157
+
158
+ const giValue = recordedGiValue(sentinel.gi, inputs);
159
+
160
+ return giValue !== undefined && hashDocs(giValue, input) === sentinel.value;
161
+ };
110
162
 
111
163
  const serializeModuleExports = (map: Record<string, ModuleExport>): [string, string, string][] =>
112
164
  sortStrings(Object.keys(map)).map((type) => [type, map[type]?.module ?? "", map[type]?.export ?? ""]);
@@ -137,17 +189,9 @@ const jsxStoreFreshness = (
137
189
  jsxStoreDir: string,
138
190
  input: JsxFingerprintInput,
139
191
  ): { isFresh: boolean; intrinsicElementCount: number } => {
140
- const sentinelPath = join(jsxStoreDir, FINGERPRINT_FILENAME);
192
+ const sentinel = readSentinel(jsxStoreDir);
141
193
 
142
- if (!existsSync(sentinelPath)) {
143
- return { isFresh: false, intrinsicElementCount: 0 };
144
- }
145
-
146
- let sentinel: JsxFingerprint;
147
-
148
- try {
149
- sentinel = JSON.parse(readFileSync(sentinelPath, "utf8")) as JsxFingerprint;
150
- } catch {
194
+ if (!isJsxFingerprint(sentinel)) {
151
195
  return { isFresh: false, intrinsicElementCount: 0 };
152
196
  }
153
197
 
@@ -159,9 +203,13 @@ const jsxStoreFreshness = (
159
203
  export {
160
204
  FINGERPRINT_FILENAME,
161
205
  computeGiFingerprint,
206
+ computeDocsFingerprint,
162
207
  isGiStoreFresh,
208
+ isDocsOutputFresh,
163
209
  computeJsxFingerprint,
164
210
  jsxStoreFreshness,
211
+ type DocsFingerprintInput,
212
+ type GiInputs,
165
213
  type GiFingerprint,
166
214
  type JsxFingerprintInput,
167
215
  };
package/src/gi.ts CHANGED
@@ -9,17 +9,25 @@ type GiCodegenOptions = {
9
9
  gi: StoreOptions;
10
10
  libraries: string[];
11
11
  girPath: string[];
12
+ isByteArrayTyped: boolean;
12
13
  };
13
14
 
14
15
  const runGiCodegen = (library: Library, options: GiCodegenOptions): number => {
15
- const { gi, libraries, girPath } = options;
16
+ const { gi, libraries, girPath, isByteArrayTyped } = options;
16
17
 
17
18
  const namespaces: GiNamespaceInput[] = Array.from(library.namespaces.values(), (namespace) => ({
18
19
  directory: namespaceDirectory(namespace),
19
20
  rawSource: generateNamespaceModule(namespace, library),
21
+ girFile: namespace.girFile,
20
22
  }));
21
23
 
22
- const fingerprint = computeGiFingerprint(library.girFiles, [...libraries], [...girPath]);
24
+ const fingerprint = computeGiFingerprint({
25
+ girFiles: library.girFiles,
26
+ libraries: [...libraries],
27
+ girPath: [...girPath],
28
+ isByteArrayTyped,
29
+ });
30
+
23
31
  writeGiStore(gi, namespaces, fingerprint);
24
32
 
25
33
  return library.namespaces.size;
@@ -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 };