@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 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/writer/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,KAAK,YAAY,GAAG;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,cAAM,aAAa;IACf,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,kBAAkB,CAAkC;IAC5D,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,aAAa,CAAgB;IAC9B,OAAO,EAAE,cAAc,CAAwB;IAEtD,OAAO,CAAC,aAAa;IAarB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAYhD,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAc3C,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI;IAQ9D,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAItC,QAAQ,IAAI,MAAM;CAsBrB;AAED,OAAO,EAAE,KAAK,YAAY,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/writer/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,KAAK,WAAW,GAAG;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B,CAAC;AA6BF,cAAM,aAAa;IACf,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,kBAAkB,CAAkC;IAC5D,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAA0B;IACxC,OAAO,EAAE,cAAc,CAAwB;IAEtD,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,mBAAmB;IAa3B,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAYhD,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAc3C,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAOjD,UAAU,IAAI,OAAO;IAIrB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,EAAO,GAAG,IAAI;IAQ/D,QAAQ,IAAI,MAAM;CAuBrB;AAED,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,CAAC"}
@@ -1,19 +1,69 @@
1
1
  import { ImportsBuilder } from "./imports.js";
2
+ const EXPORTED_DECLARATION = /^export (?:abstract )?(class|const|enum|function|interface|type) ([A-Za-z_$][\w$]*)/mu;
3
+ const SPACES_BY_KEYWORD = new Map([
4
+ ["class", ["value", "type"]],
5
+ ["const", ["value"]],
6
+ ["enum", ["value", "type"]],
7
+ ["function", ["value"]],
8
+ ["interface", []],
9
+ ["type", ["type"]],
10
+ ]);
11
+ const getExportedDeclaration = (code) => {
12
+ const match = EXPORTED_DECLARATION.exec(code);
13
+ const spaces = SPACES_BY_KEYWORD.get(match?.[1] ?? "");
14
+ const name = match?.[2];
15
+ return spaces === undefined || name === undefined ? undefined : { name, spaces };
16
+ };
17
+ const exportedNameText = (exported) => exported === undefined ? "no name at all" : `'${exported.name}'`;
2
18
  class ModuleBuilder {
3
19
  bindings = [];
4
20
  bindingNames = new Set();
5
21
  hoistedDescriptors = new Map();
22
+ claimedSpaces = new Set();
6
23
  declarations = [];
24
+ declaredNames = new Set();
7
25
  declaredTypes = new Map();
8
26
  registrations = [];
27
+ requiredNames = new Set();
9
28
  imports = new ImportsBuilder();
10
- claimTypeName(declared) {
11
- const owner = this.declaredTypes.get(declared.name);
12
- if (owner !== undefined && owner !== declared.owner) {
13
- throw new Error(`The generated type '${declared.name}' is declared for both ${owner} and ${declared.owner}. ` +
29
+ claimSpace(name, space) {
30
+ const key = `${space} ${name}`;
31
+ if (this.claimedSpaces.has(key)) {
32
+ throw new Error(`The generated module declares '${name}' twice in its ${space} space. ` +
33
+ "A module may declare each exported name once per declaration space.");
34
+ }
35
+ this.claimedSpaces.add(key);
36
+ }
37
+ claimExportedName(declaration) {
38
+ const exported = getExportedDeclaration(declaration.code);
39
+ const spaces = exported?.name === declaration.name ? exported.spaces : undefined;
40
+ if (spaces === undefined) {
41
+ throw new Error(`The declaration recorded as '${declaration.name}' exports ${exportedNameText(exported)}. ` +
42
+ "A declaration may only be recorded under the name its own code exports.");
43
+ }
44
+ for (const space of spaces) {
45
+ this.claimSpace(declaration.name, space);
46
+ }
47
+ }
48
+ claimTypeName(declaration) {
49
+ const { name, owner } = declaration;
50
+ if (owner === undefined) {
51
+ return;
52
+ }
53
+ const previous = this.declaredTypes.get(name);
54
+ if (previous !== undefined && previous !== owner) {
55
+ throw new Error(`The generated type '${name}' is declared for both ${previous} and ${owner}. ` +
14
56
  "Rename one of them, or drop the namespace from the configuration.");
15
57
  }
16
- this.declaredTypes.set(declared.name, declared.owner);
58
+ this.declaredTypes.set(name, owner);
59
+ }
60
+ verifyRegistrations() {
61
+ const missing = [...this.requiredNames].filter((name) => !this.declaredNames.has(name));
62
+ if (missing.length === 0) {
63
+ return;
64
+ }
65
+ throw new Error(`The generated module registers ${missing.join(", ")}, which it never declares. ` +
66
+ "A registration may only name a symbol whose declaration the same module emits.");
17
67
  }
18
68
  appendBinding(code, name) {
19
69
  if (name !== undefined) {
@@ -34,16 +84,23 @@ class ModuleBuilder {
34
84
  this.appendBinding(`const ${name} = ${expression};`, name);
35
85
  return name;
36
86
  }
37
- appendDeclaration(code, declared) {
38
- if (declared !== undefined) {
39
- this.claimTypeName(declared);
40
- }
41
- this.declarations.push(code);
87
+ appendDeclaration(declaration) {
88
+ this.claimExportedName(declaration);
89
+ this.claimTypeName(declaration);
90
+ this.declaredNames.add(declaration.name);
91
+ this.declarations.push(declaration.code);
42
92
  }
43
- appendRegistration(code) {
93
+ hasExports() {
94
+ return this.declaredNames.size > 0;
95
+ }
96
+ appendRegistration(code, requires = []) {
97
+ for (const name of requires) {
98
+ this.requiredNames.add(name);
99
+ }
44
100
  this.registrations.push(code);
45
101
  }
46
102
  toSource() {
103
+ this.verifyRegistrations();
47
104
  const sections = [];
48
105
  const importsBlock = this.imports.toSource();
49
106
  if (importsBlock.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/writer/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAO9C,MAAM,aAAa;IACP,QAAQ,GAAa,EAAE,CAAC;IACxB,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC;IACtC,kBAAkB,GAAwB,IAAI,GAAG,EAAE,CAAC;IACpD,YAAY,GAAa,EAAE,CAAC;IAC5B,aAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC/C,aAAa,GAAa,EAAE,CAAC;IAC9B,OAAO,GAAmB,IAAI,cAAc,EAAE,CAAC;IAE9C,aAAa,CAAC,QAAsB;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEpD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACX,uBAAuB,QAAQ,CAAC,IAAI,0BAA0B,KAAK,QAAQ,QAAQ,CAAC,KAAK,IAAI;gBAC7F,mEAAmE,CACtE,CAAC;QACN,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IAED,aAAa,CAAC,IAAY,EAAE,IAAa;QACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,OAAO;YACX,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,eAAe,CAAC,UAAkB;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAEzD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QACpB,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,aAAa,CAAC,SAAS,IAAI,MAAM,UAAU,GAAG,EAAE,IAAI,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,iBAAiB,CAAC,IAAY,EAAE,QAAuB;QACnD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB,CAAC,IAAY;QAC3B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,QAAQ;QACJ,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QAE7C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACxC,CAAC;CACJ;AAED,OAAO,EAAqB,aAAa,EAAE,CAAC","sourcesContent":["import { ImportsBuilder } from \"./imports.js\";\n\ntype DeclaredType = {\n name: string;\n owner: string;\n};\n\nclass ModuleBuilder {\n private bindings: string[] = [];\n private bindingNames: Set<string> = new Set();\n private hoistedDescriptors: Map<string, string> = new Map();\n private declarations: string[] = [];\n private declaredTypes: Map<string, string> = new Map();\n private registrations: string[] = [];\n public imports: ImportsBuilder = new ImportsBuilder();\n\n private claimTypeName(declared: DeclaredType): void {\n const owner = this.declaredTypes.get(declared.name);\n\n if (owner !== undefined && owner !== declared.owner) {\n throw new Error(\n `The generated type '${declared.name}' is declared for both ${owner} and ${declared.owner}. ` +\n \"Rename one of them, or drop the namespace from the configuration.\",\n );\n }\n\n this.declaredTypes.set(declared.name, declared.owner);\n }\n\n appendBinding(code: string, name?: string): void {\n if (name !== undefined) {\n if (this.bindingNames.has(name)) {\n return;\n }\n\n this.bindingNames.add(name);\n }\n\n this.bindings.push(code);\n }\n\n hoistDescriptor(expression: string): string {\n const existing = this.hoistedDescriptors.get(expression);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const name = `_desc${String(this.hoistedDescriptors.size)}`;\n this.hoistedDescriptors.set(expression, name);\n this.appendBinding(`const ${name} = ${expression};`, name);\n\n return name;\n }\n\n appendDeclaration(code: string, declared?: DeclaredType): void {\n if (declared !== undefined) {\n this.claimTypeName(declared);\n }\n\n this.declarations.push(code);\n }\n\n appendRegistration(code: string): void {\n this.registrations.push(code);\n }\n\n toSource(): string {\n const sections: string[] = [];\n const importsBlock = this.imports.toSource();\n\n if (importsBlock.length > 0) {\n sections.push(importsBlock.trimEnd());\n }\n\n if (this.declarations.length > 0) {\n sections.push(this.declarations.join(\"\\n\\n\"));\n }\n\n if (this.bindings.length > 0) {\n sections.push(this.bindings.join(\"\\n\\n\"));\n }\n\n if (this.registrations.length > 0) {\n sections.push(this.registrations.join(\"\\n\\n\"));\n }\n\n return `${sections.join(\"\\n\\n\")}\\n`;\n }\n}\n\nexport { type DeclaredType, ModuleBuilder };\n"]}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/writer/module.ts"],"names":[],"mappings":"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","sourcesContent":["import { ImportsBuilder } from \"./imports.js\";\n\ntype Declaration = {\n name: string;\n code: string;\n owner?: string | undefined;\n};\n\ntype ExportedDeclaration = {\n name: string;\n spaces: string[];\n};\n\nconst EXPORTED_DECLARATION = /^export (?:abstract )?(class|const|enum|function|interface|type) ([A-Za-z_$][\\w$]*)/mu;\n\nconst SPACES_BY_KEYWORD: Map<string, string[]> = new Map([\n [\"class\", [\"value\", \"type\"]],\n [\"const\", [\"value\"]],\n [\"enum\", [\"value\", \"type\"]],\n [\"function\", [\"value\"]],\n [\"interface\", []],\n [\"type\", [\"type\"]],\n]);\n\nconst getExportedDeclaration = (code: string): ExportedDeclaration | undefined => {\n const match = EXPORTED_DECLARATION.exec(code);\n const spaces = SPACES_BY_KEYWORD.get(match?.[1] ?? \"\");\n const name = match?.[2];\n\n return spaces === undefined || name === undefined ? undefined : { name, spaces };\n};\n\nconst exportedNameText = (exported: ExportedDeclaration | undefined): string =>\n exported === undefined ? \"no name at all\" : `'${exported.name}'`;\n\nclass ModuleBuilder {\n private bindings: string[] = [];\n private bindingNames: Set<string> = new Set();\n private hoistedDescriptors: Map<string, string> = new Map();\n private claimedSpaces: Set<string> = new Set();\n private declarations: string[] = [];\n private declaredNames: Set<string> = new Set();\n private declaredTypes: Map<string, string> = new Map();\n private registrations: string[] = [];\n private requiredNames: Set<string> = new Set();\n public imports: ImportsBuilder = new ImportsBuilder();\n\n private claimSpace(name: string, space: string): void {\n const key = `${space} ${name}`;\n\n if (this.claimedSpaces.has(key)) {\n throw new Error(\n `The generated module declares '${name}' twice in its ${space} space. ` +\n \"A module may declare each exported name once per declaration space.\",\n );\n }\n\n this.claimedSpaces.add(key);\n }\n\n private claimExportedName(declaration: Declaration): void {\n const exported = getExportedDeclaration(declaration.code);\n const spaces = exported?.name === declaration.name ? exported.spaces : undefined;\n\n if (spaces === undefined) {\n throw new Error(\n `The declaration recorded as '${declaration.name}' exports ${exportedNameText(exported)}. ` +\n \"A declaration may only be recorded under the name its own code exports.\",\n );\n }\n\n for (const space of spaces) {\n this.claimSpace(declaration.name, space);\n }\n }\n\n private claimTypeName(declaration: Declaration): void {\n const { name, owner } = declaration;\n\n if (owner === undefined) {\n return;\n }\n\n const previous = this.declaredTypes.get(name);\n\n if (previous !== undefined && previous !== owner) {\n throw new Error(\n `The generated type '${name}' is declared for both ${previous} and ${owner}. ` +\n \"Rename one of them, or drop the namespace from the configuration.\",\n );\n }\n\n this.declaredTypes.set(name, owner);\n }\n\n private verifyRegistrations(): void {\n const missing = [...this.requiredNames].filter((name) => !this.declaredNames.has(name));\n\n if (missing.length === 0) {\n return;\n }\n\n throw new Error(\n `The generated module registers ${missing.join(\", \")}, which it never declares. ` +\n \"A registration may only name a symbol whose declaration the same module emits.\",\n );\n }\n\n appendBinding(code: string, name?: string): void {\n if (name !== undefined) {\n if (this.bindingNames.has(name)) {\n return;\n }\n\n this.bindingNames.add(name);\n }\n\n this.bindings.push(code);\n }\n\n hoistDescriptor(expression: string): string {\n const existing = this.hoistedDescriptors.get(expression);\n\n if (existing !== undefined) {\n return existing;\n }\n\n const name = `_desc${String(this.hoistedDescriptors.size)}`;\n this.hoistedDescriptors.set(expression, name);\n this.appendBinding(`const ${name} = ${expression};`, name);\n\n return name;\n }\n\n appendDeclaration(declaration: Declaration): void {\n this.claimExportedName(declaration);\n this.claimTypeName(declaration);\n this.declaredNames.add(declaration.name);\n this.declarations.push(declaration.code);\n }\n\n hasExports(): boolean {\n return this.declaredNames.size > 0;\n }\n\n appendRegistration(code: string, requires: string[] = []): void {\n for (const name of requires) {\n this.requiredNames.add(name);\n }\n\n this.registrations.push(code);\n }\n\n toSource(): string {\n this.verifyRegistrations();\n const sections: string[] = [];\n const importsBlock = this.imports.toSource();\n\n if (importsBlock.length > 0) {\n sections.push(importsBlock.trimEnd());\n }\n\n if (this.declarations.length > 0) {\n sections.push(this.declarations.join(\"\\n\\n\"));\n }\n\n if (this.bindings.length > 0) {\n sections.push(this.bindings.join(\"\\n\\n\"));\n }\n\n if (this.registrations.length > 0) {\n sections.push(this.registrations.join(\"\\n\\n\"));\n }\n\n return `${sections.join(\"\\n\\n\")}\\n`;\n }\n}\n\nexport { type Declaration, ModuleBuilder };\n"]}
package/dist/xml.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  import { type X2jOptions, XMLParser } from "fast-xml-parser";
2
+ type XmlFileInput = {
3
+ parser: XMLParser;
4
+ label: string;
5
+ path: string;
6
+ };
2
7
  declare const createXmlParser: (options: Partial<X2jOptions>) => XMLParser;
3
- export { createXmlParser };
8
+ declare const parseXmlFile: (input: XmlFileInput) => unknown;
9
+ export { createXmlParser, parseXmlFile };
4
10
  //# sourceMappingURL=xml.d.ts.map
package/dist/xml.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7D,QAAA,MAAM,eAAe,GAAI,SAAS,OAAO,CAAC,UAAU,CAAC,KAAG,SAOlD,CAAC;AAEP,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI7D,KAAK,YAAY,GAAG;IAChB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,SAAS,OAAO,CAAC,UAAU,CAAC,KAAG,SAOlD,CAAC;AA0CP,QAAA,MAAM,YAAY,GAAI,OAAO,YAAY,KAAG,OAS3C,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC"}
package/dist/xml.js CHANGED
@@ -1,4 +1,7 @@
1
+ import { errorMessage, isRecord } from "@gtkx/utils";
1
2
  import { XMLParser } from "fast-xml-parser";
3
+ import { SyntaxValidator } from "fast-xml-validator";
4
+ import { readFileSync } from "node:fs";
2
5
  const createXmlParser = (options) => new XMLParser({
3
6
  ignoreAttributes: false,
4
7
  attributeNamePrefix: "@_",
@@ -6,5 +9,44 @@ const createXmlParser = (options) => new XMLParser({
6
9
  parseTagValue: false,
7
10
  ...options,
8
11
  });
9
- export { createXmlParser };
12
+ const xmlFileError = (input, action, error) => new Error(`Cannot ${action} the ${input.label} at ${input.path}: ${errorMessage(error)}`, { cause: error });
13
+ const readXmlFile = (input) => {
14
+ try {
15
+ return readFileSync(input.path, "utf8");
16
+ }
17
+ catch (error) {
18
+ throw xmlFileError(input, "read", error);
19
+ }
20
+ };
21
+ const isLocated = (line, col) => typeof line === "number" && typeof col === "number" && (line > 1 || col > 1);
22
+ const positionSuffix = (error) => {
23
+ if (!isRecord(error)) {
24
+ return "";
25
+ }
26
+ const { line, col } = error;
27
+ if (!isLocated(line, col)) {
28
+ return "";
29
+ }
30
+ return ` (line ${String(line)}, column ${String(col)})`;
31
+ };
32
+ const assertWellFormed = (input, xml) => {
33
+ try {
34
+ SyntaxValidator.validate(xml);
35
+ }
36
+ catch (error) {
37
+ throw new Error(`The ${input.label} at ${input.path} is not well-formed XML: ` +
38
+ `${errorMessage(error)}${positionSuffix(error)}`, { cause: error });
39
+ }
40
+ };
41
+ const parseXmlFile = (input) => {
42
+ const xml = readXmlFile(input);
43
+ assertWellFormed(input, xml);
44
+ try {
45
+ return input.parser.parse(xml);
46
+ }
47
+ catch (error) {
48
+ throw xmlFileError(input, "parse", error);
49
+ }
50
+ };
51
+ export { createXmlParser, parseXmlFile };
10
52
  //# sourceMappingURL=xml.js.map
package/dist/xml.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"xml.js","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,eAAe,GAAG,CAAC,OAA4B,EAAa,EAAE,CAChE,IAAI,SAAS,CAAC;IACV,gBAAgB,EAAE,KAAK;IACvB,mBAAmB,EAAE,IAAI;IACzB,mBAAmB,EAAE,KAAK;IAC1B,aAAa,EAAE,KAAK;IACpB,GAAG,OAAO;CACb,CAAC,CAAC;AAEP,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import { type X2jOptions, XMLParser } from \"fast-xml-parser\";\n\nconst createXmlParser = (options: Partial<X2jOptions>): XMLParser =>\n new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n parseAttributeValue: false,\n parseTagValue: false,\n ...options,\n });\n\nexport { createXmlParser };\n"]}
1
+ {"version":3,"file":"xml.js","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAmB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQvC,MAAM,eAAe,GAAG,CAAC,OAA4B,EAAa,EAAE,CAChE,IAAI,SAAS,CAAC;IACV,gBAAgB,EAAE,KAAK;IACvB,mBAAmB,EAAE,IAAI;IACzB,mBAAmB,EAAE,KAAK;IAC1B,aAAa,EAAE,KAAK;IACpB,GAAG,OAAO;CACb,CAAC,CAAC;AAEP,MAAM,YAAY,GAAG,CAAC,KAAmB,EAAE,MAAc,EAAE,KAAc,EAAS,EAAE,CAChF,IAAI,KAAK,CAAC,UAAU,MAAM,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAEhH,MAAM,WAAW,GAAG,CAAC,KAAmB,EAAU,EAAE;IAChD,IAAI,CAAC;QACD,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,IAAa,EAAE,GAAY,EAAW,EAAE,CACvD,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;AAEjF,MAAM,cAAc,GAAG,CAAC,KAAc,EAAU,EAAE;IAC9C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAE5B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,OAAO,UAAU,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,KAAmB,EAAE,GAAW,EAAQ,EAAE;IAChE,IAAI,CAAC;QACD,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACX,OAAO,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,2BAA2B;YAC9D,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,EAChD,EAAE,KAAK,EAAE,KAAK,EAAE,CACnB,CAAC;IACN,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAmB,EAAW,EAAE;IAClD,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/B,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE7B,IAAI,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { errorMessage, isRecord } from \"@gtkx/utils\";\nimport { type X2jOptions, XMLParser } from \"fast-xml-parser\";\nimport { SyntaxValidator } from \"fast-xml-validator\";\nimport { readFileSync } from \"node:fs\";\n\ntype XmlFileInput = {\n parser: XMLParser;\n label: string;\n path: string;\n};\n\nconst createXmlParser = (options: Partial<X2jOptions>): XMLParser =>\n new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n parseAttributeValue: false,\n parseTagValue: false,\n ...options,\n });\n\nconst xmlFileError = (input: XmlFileInput, action: string, error: unknown): Error =>\n new Error(`Cannot ${action} the ${input.label} at ${input.path}: ${errorMessage(error)}`, { cause: error });\n\nconst readXmlFile = (input: XmlFileInput): string => {\n try {\n return readFileSync(input.path, \"utf8\");\n } catch (error) {\n throw xmlFileError(input, \"read\", error);\n }\n};\n\nconst isLocated = (line: unknown, col: unknown): boolean =>\n typeof line === \"number\" && typeof col === \"number\" && (line > 1 || col > 1);\n\nconst positionSuffix = (error: unknown): string => {\n if (!isRecord(error)) {\n return \"\";\n }\n\n const { line, col } = error;\n\n if (!isLocated(line, col)) {\n return \"\";\n }\n\n return ` (line ${String(line)}, column ${String(col)})`;\n};\n\nconst assertWellFormed = (input: XmlFileInput, xml: string): void => {\n try {\n SyntaxValidator.validate(xml);\n } catch (error) {\n throw new Error(\n `The ${input.label} at ${input.path} is not well-formed XML: ` +\n `${errorMessage(error)}${positionSuffix(error)}`,\n { cause: error },\n );\n }\n};\n\nconst parseXmlFile = (input: XmlFileInput): unknown => {\n const xml = readXmlFile(input);\n assertWellFormed(input, xml);\n\n try {\n return input.parser.parse(xml);\n } catch (error) {\n throw xmlFileError(input, \"parse\", error);\n }\n};\n\nexport { createXmlParser, parseXmlFile };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/codegen",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Generates the typed GTKX bindings and API reference from GIR and OpenGL registry data",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -40,15 +40,26 @@
40
40
  "overrides",
41
41
  "src"
42
42
  ],
43
+ "nx": {
44
+ "targets": {
45
+ "lint": {
46
+ "options": {
47
+ "cwd": ".",
48
+ "command": "eslint {projectRoot}"
49
+ }
50
+ }
51
+ }
52
+ },
43
53
  "engines": {
44
54
  "node": ">=24"
45
55
  },
46
56
  "dependencies": {
47
57
  "@types/node": "^26.2.0",
48
58
  "fast-xml-parser": "^5.10.1",
59
+ "fast-xml-validator": "^1.4.1",
49
60
  "typescript": "^6.0.3",
50
- "@gtkx/utils": "1.0.0",
51
- "@gtkx/react": "1.0.0"
61
+ "@gtkx/react": "1.1.0",
62
+ "@gtkx/utils": "1.1.0"
52
63
  },
53
64
  "scripts": {
54
65
  "release": "tsx ../../scripts/release-package.ts"
@@ -1,10 +1,11 @@
1
- import { sourceStringLiteral } from "@gtkx/utils";
1
+ import { sanitizeTypeIdentifier, sourceStringLiteral } from "@gtkx/utils";
2
2
  import type { GirCallback } from "../gir/callback.js";
3
3
  import type { Library } from "../gir/library.js";
4
4
  import type { PrimitiveCategory } from "../gir/primitives.js";
5
5
  import type { EntityType, GirType } from "../gir/type.js";
6
6
  import type { ModuleContext } from "../writer/context.js";
7
7
  import {
8
+ type GirCursorBounds,
8
9
  type GirParameter,
9
10
  type GirReturnValue,
10
11
  isCallerAllocatedOut,
@@ -20,7 +21,7 @@ import {
20
21
  type TypeId,
21
22
  } from "../gir/type-id.js";
22
23
  import { isRecordInout } from "../store/gi/param-marshal.js";
23
- import { computeRecordFieldSlots } from "../store/gi/record-layout.js";
24
+ import { computeRecordFieldSlots, recordInlineSize } from "../store/gi/record-layout.js";
24
25
  import { isValueMarshalable } from "../store/gi/value-marshalable.js";
25
26
  import {
26
27
  type ListDescriptorName,
@@ -30,6 +31,7 @@ import {
30
31
  tBoxed,
31
32
  tByteArray,
32
33
  tCallback,
34
+ tCursorArray,
33
35
  tEnum,
34
36
  tFixedArray,
35
37
  tFlags,
@@ -50,21 +52,23 @@ import {
50
52
  } from "./descriptor.js";
51
53
  import { carrayFor, isUnboundedArray, primitiveCategoryFor } from "./type-shape.js";
52
54
 
53
- type RenderDescriptorOptions = {
54
- argIndexOffset?: number;
55
- argIndexMap?: Map<number, number> | undefined;
56
- hasOutIndirection?: boolean;
57
- isCallerAllocated?: boolean;
58
- isInline?: boolean;
59
- isNewlyCreated?: boolean;
60
- };
55
+ type PrimaryReturnKind = "surfaced" | "void" | "skipped";
61
56
 
62
57
  type ArgIndexOptions = {
63
58
  argIndexOffset: number;
64
59
  argIndexMap: Map<number, number> | undefined;
60
+ cursor: GirCursorBounds | undefined;
65
61
  hasOutIndirection: boolean;
66
62
  };
67
63
 
64
+ type CursorArgIndexOptions = ArgIndexOptions & { cursor: GirCursorBounds };
65
+
66
+ type RenderDescriptorOptions = Partial<ArgIndexOptions> & {
67
+ isCallerAllocated?: boolean;
68
+ isInline?: boolean;
69
+ isNewlyCreated?: boolean;
70
+ };
71
+
68
72
  type RecordPlacement = {
69
73
  isCallerAllocated?: boolean;
70
74
  isInline?: boolean;
@@ -91,6 +95,7 @@ type ResolvedRecord = Extract<EntityType, { kind: "record" }>["value"];
91
95
 
92
96
  type FundamentalRecordOptions = {
93
97
  resolved: Extract<EntityType, { kind: "record" }>;
98
+ lib: string;
94
99
  refFunc: string;
95
100
  unrefFunc: string;
96
101
  ownership: Ownership;
@@ -131,12 +136,27 @@ const isVoidRef = (library: Library, ref: TypeId | undefined): boolean =>
131
136
  const isInlineCallbackRef = (library: Library, ref: TypeId | undefined): boolean =>
132
137
  ref !== undefined && library.typeFor(ref)?.kind === "callback" && library.nameFor(ref) === undefined;
133
138
 
139
+ const primaryReturnKind = (library: Library, returnValue: GirReturnValue): PrimaryReturnKind => {
140
+ if (isVoidRef(library, returnValue.type)) {
141
+ return "void";
142
+ }
143
+
144
+ return returnValue.skip ? "skipped" : "surfaced";
145
+ };
146
+
134
147
  const shouldOmitPrimaryReturn = (library: Library, returnValue: GirReturnValue): boolean =>
135
- isVoidRef(library, returnValue.type) || returnValue.skip;
148
+ primaryReturnKind(library, returnValue) !== "surfaced";
149
+
150
+ const isSkippedPrimaryReturn = (library: Library, returnValue: GirReturnValue): boolean =>
151
+ primaryReturnKind(library, returnValue) === "skipped";
152
+
153
+ const isVoidPrimaryReturn = (library: Library, returnValue: GirReturnValue): boolean =>
154
+ primaryReturnKind(library, returnValue) === "void";
136
155
 
137
156
  const argIndexOptions = (options: RenderDescriptorOptions): ArgIndexOptions => ({
138
157
  argIndexOffset: options.argIndexOffset ?? 0,
139
158
  argIndexMap: options.argIndexMap,
159
+ cursor: options.cursor,
140
160
  hasOutIndirection: options.hasOutIndirection === true,
141
161
  });
142
162
 
@@ -276,7 +296,7 @@ const renderParamDescriptor = (
276
296
  ref: TypeId | undefined,
277
297
  argIndex: Partial<ArgIndexOptions> = {},
278
298
  ): string => {
279
- const behindRef: RenderDescriptorOptions = { ...argIndex, hasOutIndirection: true };
299
+ const behindRef: RenderDescriptorOptions = { ...argIndex, cursor: parameter.cursor, hasOutIndirection: true };
280
300
 
281
301
  if (isCellInout(context.library, parameter)) {
282
302
  return tRef(renderDescriptor(context, ref, parameter.transferOwnership, behindRef), true);
@@ -310,7 +330,7 @@ const findUserDataIndex = (parameters: GirParameter[]): number | undefined => {
310
330
  return declared?.closureIndex ?? userDataIndexByName(parameters);
311
331
  };
312
332
 
313
- const callbackOptionsArg = (owningParameter: GirParameter, userDataIndex: number | undefined): string | undefined => {
333
+ const callbackOptionsArg = (owningParameter: GirParameter, userDataIndex: number | undefined): string[] => {
314
334
  const options: string[] = [];
315
335
 
316
336
  if (owningParameter.destroyIndex !== undefined) {
@@ -329,7 +349,7 @@ const callbackOptionsArg = (owningParameter: GirParameter, userDataIndex: number
329
349
  options.push(`scope: ${sourceStringLiteral(owningParameter.scope)}`);
330
350
  }
331
351
 
332
- return options.length > 0 ? `{ ${options.join(", ")} }` : undefined;
352
+ return options;
333
353
  };
334
354
 
335
355
  const renderCallbackType = (
@@ -348,15 +368,13 @@ const renderCallbackType = (
348
368
  (parameter, index) => argOverrides?.get(index) ?? renderParamDescriptor(context, parameter, parameter.type),
349
369
  );
350
370
 
351
- const returnRef = callback.returnValue.type;
371
+ const { returnValue } = callback;
352
372
 
353
- const returnType = isVoidRef(context.library, returnRef)
354
- ? tVoid
355
- : renderDescriptor(context, returnRef, callback.returnValue.transferOwnership);
356
-
357
- const optionsArg = callbackOptionsArg(owningParameter, findUserDataIndex(callback.parameters));
358
-
359
- return tCallback(argTypes, returnType, optionsArg);
373
+ return tCallback({
374
+ argTypes,
375
+ returns: renderDescriptor(context, returnValue.type, returnValue.transferOwnership),
376
+ options: callbackOptionsArg(owningParameter, findUserDataIndex(callback.parameters)),
377
+ });
360
378
  };
361
379
 
362
380
  const primitiveExpression = (category: PrimitiveCategory, ownership: Ownership): string => {
@@ -424,13 +442,14 @@ const getFundamental = (
424
442
  node: Extract<EntityType, { kind: "class" | "interface" }>,
425
443
  ): AncestorFundamental | undefined => {
426
444
  const cls = node.value;
445
+ const lib = node.namespace.sharedLibrary;
427
446
 
428
- if (!cls.fundamental || cls.glibRefFunc === undefined || cls.glibUnrefFunc === undefined) {
447
+ if (lib === undefined || !cls.fundamental || cls.glibRefFunc === undefined || cls.glibUnrefFunc === undefined) {
429
448
  return undefined;
430
449
  }
431
450
 
432
451
  return {
433
- lib: node.namespace.sharedLibrary ?? "",
452
+ lib,
434
453
  refFunc: cls.glibRefFunc,
435
454
  unrefFunc: cls.glibUnrefFunc,
436
455
  typeName: cls.glibTypeName,
@@ -529,7 +548,7 @@ const structExpression = (
529
548
  options: { isCallerAllocated: boolean; isInline: boolean },
530
549
  ): string => {
531
550
  const { size } = computeRecordFieldSlots(context, resolved.value.fields, resolved.value.isUnion);
532
- const wrapperClass = context.qualify(resolved.namespace.name, resolved.value.name);
551
+ const wrapperClass = context.qualify(resolved.namespace.name, sanitizeTypeIdentifier(resolved.value.name));
533
552
  const isCopyable = isValueMarshalable(context, resolved.namespace.name, resolved.value);
534
553
 
535
554
  return tStruct(ownership, {
@@ -541,10 +560,10 @@ const structExpression = (
541
560
  };
542
561
 
543
562
  const fundamentalRecordExpression = (options: FundamentalRecordOptions): string => {
544
- const { resolved, refFunc, unrefFunc, ownership, wrapperClass, isInline } = options;
563
+ const { resolved, lib, refFunc, unrefFunc, ownership, wrapperClass, isInline } = options;
545
564
 
546
565
  return renderFundamental({
547
- lib: resolved.namespace.sharedLibrary ?? "",
566
+ lib,
548
567
  refFunc,
549
568
  unrefFunc,
550
569
  typeName: resolved.value.glibTypeName,
@@ -605,14 +624,16 @@ const recordExpression = (
605
624
  ): string => {
606
625
  const record = resolved.value;
607
626
  const { refFunc, unrefFunc } = recordRefPair(record);
627
+ const lib = resolved.namespace.sharedLibrary;
608
628
 
609
- if (refFunc !== undefined && unrefFunc !== undefined) {
629
+ if (refFunc !== undefined && unrefFunc !== undefined && lib !== undefined) {
610
630
  const wrapperClass = requiresFallbackClass(record)
611
- ? context.qualify(resolved.namespace.name, record.name)
631
+ ? context.qualify(resolved.namespace.name, sanitizeTypeIdentifier(record.name))
612
632
  : undefined;
613
633
 
614
634
  return fundamentalRecordExpression({
615
635
  resolved,
636
+ lib,
616
637
  refFunc,
617
638
  unrefFunc,
618
639
  ownership,
@@ -629,13 +650,12 @@ const rawEnumDescriptor = (isSigned: boolean): string => (isSigned ? tInt32 : tU
629
650
  const enumExpression = (resolved: Extract<EntityType, { kind: "enum" }>): string => {
630
651
  const getter = resolved.value.glibGetType;
631
652
  const isSigned = resolved.value.members.some((member) => member.value.startsWith("-"));
653
+ const lib = resolved.namespace.sharedLibrary;
632
654
 
633
- if (getter === undefined || getter === "") {
655
+ if (getter === undefined || getter === "" || lib === undefined) {
634
656
  return rawEnumDescriptor(isSigned);
635
657
  }
636
658
 
637
- const lib = resolved.namespace.sharedLibrary ?? "";
638
-
639
659
  return resolved.value.kind === "bitfield" ? tFlags(lib, getter, isSigned) : tEnum(lib, getter, isSigned);
640
660
  };
641
661
 
@@ -667,19 +687,52 @@ const expressionForResolved = (
667
687
  }
668
688
  };
669
689
 
690
+ const elementExpression = (
691
+ context: ModuleContext,
692
+ ref: CArrayType,
693
+ transfer: ParameterTransfer,
694
+ options: ArgIndexOptions,
695
+ ): string =>
696
+ renderDescriptor(context, ref.element, deriveElementTransfer(transfer), {
697
+ ...options,
698
+ cursor: undefined,
699
+ hasOutIndirection: false,
700
+ });
701
+
702
+ const cursorArrayExpression = (
703
+ context: ModuleContext,
704
+ ref: CArrayType,
705
+ transfer: ParameterTransfer,
706
+ options: CursorArgIndexOptions,
707
+ ): string =>
708
+ tCursorArray(
709
+ elementExpression(context, ref, transfer, options),
710
+ {
711
+ baseIndex: mapArgIndex(options, options.cursor.baseIndex),
712
+ lengthIndex: mapArgIndex(options, options.cursor.lengthIndex),
713
+ },
714
+ transferOwnership(transfer),
715
+ inlineElementSize(context, ref, options.hasOutIndirection),
716
+ );
717
+
670
718
  const arrayExpression = (
671
719
  context: ModuleContext,
672
720
  ref: CArrayType,
673
721
  transfer: ParameterTransfer,
674
722
  options: ArgIndexOptions,
675
723
  ): string => {
724
+ const { cursor } = options;
725
+
726
+ if (cursor !== undefined) {
727
+ return cursorArrayExpression(context, ref, transfer, { ...options, cursor });
728
+ }
729
+
676
730
  if (hasUnknownArrayLength(ref)) {
677
731
  return tUint64;
678
732
  }
679
733
 
680
734
  const ownership = transferOwnership(transfer);
681
- const elementOptions: ArgIndexOptions = { ...options, hasOutIndirection: false };
682
- const element = renderDescriptor(context, ref.element, deriveElementTransfer(transfer), elementOptions);
735
+ const element = elementExpression(context, ref, transfer, options);
683
736
  const size = inlineElementSize(context, ref, options.hasOutIndirection);
684
737
 
685
738
  if (ref.lengthParameterIndex !== undefined) {
@@ -693,16 +746,6 @@ const arrayExpression = (
693
746
  return tArray(element, ownership, size);
694
747
  };
695
748
 
696
- const recordInlineSize = (context: ModuleContext, record: ResolvedRecord): number | undefined => {
697
- if (record.opaque || record.disguised || record.fields.length === 0) {
698
- return undefined;
699
- }
700
-
701
- const { size } = computeRecordFieldSlots(context, record.fields, record.isUnion);
702
-
703
- return size > 0 ? size : undefined;
704
- };
705
-
706
749
  const elementPointerDepth = (elementCType: string | undefined, hasOutIndirection: boolean): number => {
707
750
  const declared = elementCType === undefined ? 0 : elementCType.split("*").length - 1;
708
751
 
@@ -738,11 +781,13 @@ const aliasExpression = (
738
781
 
739
782
  export {
740
783
  isInlineCallbackRef,
784
+ isSkippedPrimaryReturn,
785
+ isVoidPrimaryReturn,
786
+ primaryReturnKind,
741
787
  shouldOmitPrimaryReturn,
742
788
  renderDescriptor,
743
789
  isScalarRef,
744
790
  isCellInout,
745
- recordInlineSize,
746
791
  renderParamDescriptor,
747
792
  renderCallbackType,
748
793
  renderSelfDescriptor,