@hydranium/core 1.0.0-next.19 → 1.0.0-next.193

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 (588) hide show
  1. package/README.md +6 -2
  2. package/lib/documents/ast-document-manager.d.ts +222 -63
  3. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  4. package/lib/documents/ast-document-manager.js +250 -83
  5. package/lib/documents/ast-document-manager.js.map +1 -1
  6. package/lib/documents/client-ids.d.ts +5 -19
  7. package/lib/documents/client-ids.d.ts.map +1 -1
  8. package/lib/documents/client-ids.js +5 -19
  9. package/lib/documents/client-ids.js.map +1 -1
  10. package/lib/documents/client-session-errors.d.ts +15 -0
  11. package/lib/documents/client-session-errors.d.ts.map +1 -0
  12. package/lib/documents/client-session-errors.js +15 -0
  13. package/lib/documents/client-session-errors.js.map +1 -0
  14. package/lib/documents/client-session-registry.d.ts +138 -0
  15. package/lib/documents/client-session-registry.d.ts.map +1 -0
  16. package/lib/documents/client-session-registry.js +187 -0
  17. package/lib/documents/client-session-registry.js.map +1 -0
  18. package/lib/documents/file-system-task-queue.d.ts +49 -0
  19. package/lib/documents/file-system-task-queue.d.ts.map +1 -0
  20. package/lib/documents/file-system-task-queue.js +34 -0
  21. package/lib/documents/file-system-task-queue.js.map +1 -0
  22. package/lib/documents/hydranium-text-documents.d.ts +523 -101
  23. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  24. package/lib/documents/hydranium-text-documents.js +961 -177
  25. package/lib/documents/hydranium-text-documents.js.map +1 -1
  26. package/lib/documents/index.d.ts +5 -0
  27. package/lib/documents/index.d.ts.map +1 -1
  28. package/lib/documents/index.js +5 -0
  29. package/lib/documents/index.js.map +1 -1
  30. package/lib/documents/language-client-text-shadow.d.ts +41 -9
  31. package/lib/documents/language-client-text-shadow.d.ts.map +1 -1
  32. package/lib/documents/language-client-text-shadow.js +56 -11
  33. package/lib/documents/language-client-text-shadow.js.map +1 -1
  34. package/lib/documents/model-ledger.d.ts +47 -0
  35. package/lib/documents/model-ledger.d.ts.map +1 -0
  36. package/lib/documents/model-ledger.js +30 -0
  37. package/lib/documents/model-ledger.js.map +1 -0
  38. package/lib/documents/self-save-registry.d.ts +37 -6
  39. package/lib/documents/self-save-registry.d.ts.map +1 -1
  40. package/lib/documents/self-save-registry.js +28 -15
  41. package/lib/documents/self-save-registry.js.map +1 -1
  42. package/lib/documents/version-sync-service.d.ts +134 -0
  43. package/lib/documents/version-sync-service.d.ts.map +1 -0
  44. package/lib/documents/version-sync-service.js +171 -0
  45. package/lib/documents/version-sync-service.js.map +1 -0
  46. package/lib/index.d.ts +3 -0
  47. package/lib/index.d.ts.map +1 -1
  48. package/lib/index.js +6 -0
  49. package/lib/index.js.map +1 -1
  50. package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
  51. package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
  52. package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
  53. package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
  54. package/lib/langium/ast-extension/ast-node-builder.js +60 -22
  55. package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
  56. package/lib/langium/bootstrap.d.ts.map +1 -1
  57. package/lib/langium/bootstrap.js +32 -9
  58. package/lib/langium/bootstrap.js.map +1 -1
  59. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
  60. package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
  61. package/lib/langium/config/configuration-provider.d.ts +81 -0
  62. package/lib/langium/config/configuration-provider.d.ts.map +1 -0
  63. package/lib/langium/config/configuration-provider.js +112 -0
  64. package/lib/langium/config/configuration-provider.js.map +1 -0
  65. package/lib/langium/config/index.d.ts +1 -0
  66. package/lib/langium/config/index.d.ts.map +1 -1
  67. package/lib/langium/config/index.js +1 -0
  68. package/lib/langium/config/index.js.map +1 -1
  69. package/lib/langium/config/settings.js.map +1 -1
  70. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
  71. package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
  72. package/lib/langium/diagnostics/logger.d.ts +10 -3
  73. package/lib/langium/diagnostics/logger.d.ts.map +1 -1
  74. package/lib/langium/diagnostics/logger.js +12 -5
  75. package/lib/langium/diagnostics/logger.js.map +1 -1
  76. package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
  77. package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
  78. package/lib/langium/diagnostics/lsp-logger.js +56 -13
  79. package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
  80. package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
  81. package/lib/langium/diagnostics/server-tracer.js.map +1 -1
  82. package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
  83. package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
  84. package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
  85. package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
  86. package/lib/langium/document-builder/build-session.d.ts +93 -0
  87. package/lib/langium/document-builder/build-session.d.ts.map +1 -0
  88. package/lib/langium/document-builder/build-session.js +72 -0
  89. package/lib/langium/document-builder/build-session.js.map +1 -0
  90. package/lib/langium/document-builder/document-builder.d.ts +382 -29
  91. package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
  92. package/lib/langium/document-builder/document-builder.js +659 -61
  93. package/lib/langium/document-builder/document-builder.js.map +1 -1
  94. package/lib/langium/document-builder/index.d.ts +1 -0
  95. package/lib/langium/document-builder/index.d.ts.map +1 -1
  96. package/lib/langium/document-builder/index.js +1 -0
  97. package/lib/langium/document-builder/index.js.map +1 -1
  98. package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
  99. package/lib/langium/documentation/comment-provider.js.map +1 -1
  100. package/lib/langium/integration-services.d.ts +45 -1
  101. package/lib/langium/integration-services.d.ts.map +1 -1
  102. package/lib/langium/integration-services.js +10 -5
  103. package/lib/langium/integration-services.js.map +1 -1
  104. package/lib/langium/integrity/integrity-rule.d.ts +13 -5
  105. package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
  106. package/lib/langium/integrity/integrity-rule.js.map +1 -1
  107. package/lib/langium/integrity/integrity-service.d.ts +58 -13
  108. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  109. package/lib/langium/integrity/integrity-service.js +204 -29
  110. package/lib/langium/integrity/integrity-service.js.map +1 -1
  111. package/lib/langium/keys/containment.d.ts +64 -0
  112. package/lib/langium/keys/containment.d.ts.map +1 -0
  113. package/lib/langium/keys/containment.js +53 -0
  114. package/lib/langium/keys/containment.js.map +1 -0
  115. package/lib/langium/keys/index.d.ts +1 -0
  116. package/lib/langium/keys/index.d.ts.map +1 -1
  117. package/lib/langium/keys/index.js +1 -0
  118. package/lib/langium/keys/index.js.map +1 -1
  119. package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
  120. package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
  121. package/lib/langium/keys/name-based-key-provider.js +4 -0
  122. package/lib/langium/keys/name-based-key-provider.js.map +1 -1
  123. package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
  124. package/lib/langium/keys/positional-key-provider.js.map +1 -1
  125. package/lib/langium/labeling/label-provider.d.ts.map +1 -1
  126. package/lib/langium/labeling/label-provider.js.map +1 -1
  127. package/lib/langium/language-module.d.ts +27 -2
  128. package/lib/langium/language-module.d.ts.map +1 -1
  129. package/lib/langium/language-module.js +16 -2
  130. package/lib/langium/language-module.js.map +1 -1
  131. package/lib/langium/model-service/client-session.d.ts +330 -0
  132. package/lib/langium/model-service/client-session.d.ts.map +1 -0
  133. package/lib/langium/model-service/client-session.js +418 -0
  134. package/lib/langium/model-service/client-session.js.map +1 -0
  135. package/lib/langium/model-service/index.d.ts +1 -0
  136. package/lib/langium/model-service/index.d.ts.map +1 -1
  137. package/lib/langium/model-service/index.js +1 -0
  138. package/lib/langium/model-service/index.js.map +1 -1
  139. package/lib/langium/model-service/model-service.d.ts +353 -253
  140. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  141. package/lib/langium/model-service/model-service.js +361 -408
  142. package/lib/langium/model-service/model-service.js.map +1 -1
  143. package/lib/langium/module.d.ts +150 -35
  144. package/lib/langium/module.d.ts.map +1 -1
  145. package/lib/langium/module.js +50 -35
  146. package/lib/langium/module.js.map +1 -1
  147. package/lib/langium/naming/name-provider.d.ts +25 -4
  148. package/lib/langium/naming/name-provider.d.ts.map +1 -1
  149. package/lib/langium/naming/name-provider.js +2 -1
  150. package/lib/langium/naming/name-provider.js.map +1 -1
  151. package/lib/langium/naming/name-separator-validation.d.ts +23 -0
  152. package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
  153. package/lib/langium/naming/name-separator-validation.js +30 -1
  154. package/lib/langium/naming/name-separator-validation.js.map +1 -1
  155. package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
  156. package/lib/langium/project/abstract-project-manager.js +9 -2
  157. package/lib/langium/project/abstract-project-manager.js.map +1 -1
  158. package/lib/langium/project/project-change-event.d.ts +2 -2
  159. package/lib/langium/project/single-project-manager.d.ts.map +1 -1
  160. package/lib/langium/project/single-project-manager.js.map +1 -1
  161. package/lib/langium/residency/cst-residency-service.d.ts +31 -11
  162. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  163. package/lib/langium/residency/cst-residency-service.js +23 -57
  164. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  165. package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
  166. package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
  167. package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
  168. package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
  169. package/lib/langium/scope/hydranium-scope-provider.d.ts +48 -13
  170. package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
  171. package/lib/langium/scope/hydranium-scope-provider.js +56 -20
  172. package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
  173. package/lib/langium/scope/reference-builder.d.ts.map +1 -1
  174. package/lib/langium/scope/reference-builder.js.map +1 -1
  175. package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
  176. package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
  177. package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
  178. package/lib/langium/scope/scope-extension-service.js.map +1 -1
  179. package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
  180. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  181. package/lib/langium/serialization/abstract-serializer.js +12 -21
  182. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  183. package/lib/langium/serialization/json-serializer.d.ts +1 -1
  184. package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
  185. package/lib/langium/serialization/json-serializer.js.map +1 -1
  186. package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
  187. package/lib/langium/serialization/yaml-serializer.js.map +1 -1
  188. package/lib/langium/service-registry.d.ts +15 -1
  189. package/lib/langium/service-registry.d.ts.map +1 -1
  190. package/lib/langium/service-registry.js +16 -0
  191. package/lib/langium/service-registry.js.map +1 -1
  192. package/lib/langium/shared-services.d.ts +21 -4
  193. package/lib/langium/shared-services.d.ts.map +1 -1
  194. package/lib/langium/shared-services.js.map +1 -1
  195. package/lib/langium/transfer/transfer-encoder.d.ts +75 -23
  196. package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
  197. package/lib/langium/transfer/transfer-encoder.js +44 -21
  198. package/lib/langium/transfer/transfer-encoder.js.map +1 -1
  199. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  200. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  201. package/lib/langium/trivia/comment-preserver.js +906 -0
  202. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  203. package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
  204. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  205. package/lib/langium/trivia/document-ending-preserver.js +48 -0
  206. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  207. package/lib/langium/trivia/index.d.ts +14 -0
  208. package/lib/langium/trivia/index.d.ts.map +1 -0
  209. package/lib/langium/trivia/index.js +14 -0
  210. package/lib/langium/trivia/index.js.map +1 -0
  211. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  212. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  213. package/lib/langium/trivia/trivia-contribution.js +10 -0
  214. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  215. package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
  216. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  217. package/lib/langium/trivia/trivia-preserver.js +10 -0
  218. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  219. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  220. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  221. package/lib/langium/trivia/trivia-service.js +56 -0
  222. package/lib/langium/trivia/trivia-service.js.map +1 -0
  223. package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
  224. package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
  225. package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
  226. package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
  227. package/lib/langium/validation/document-validator.d.ts +294 -10
  228. package/lib/langium/validation/document-validator.d.ts.map +1 -1
  229. package/lib/langium/validation/document-validator.js +448 -5
  230. package/lib/langium/validation/document-validator.js.map +1 -1
  231. package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
  232. package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
  233. package/lib/langium/workspace/document-uri-policy.d.ts +17 -12
  234. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  235. package/lib/langium/workspace/document-uri-policy.js +10 -9
  236. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  237. package/lib/langium/workspace/file-not-found.d.ts +17 -0
  238. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  239. package/lib/langium/workspace/file-not-found.js +20 -0
  240. package/lib/langium/workspace/file-not-found.js.map +1 -0
  241. package/lib/langium/workspace/file-system-provider.d.ts +84 -8
  242. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  243. package/lib/langium/workspace/file-system-provider.js +93 -14
  244. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  245. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
  246. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
  247. package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
  248. package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
  249. package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
  250. package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
  251. package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
  252. package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
  253. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +81 -8
  254. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  255. package/lib/langium/workspace/hydranium-workspace-manager.js +128 -10
  256. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  257. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +25 -2
  258. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  259. package/lib/langium/workspace/in-memory-file-system-provider.js +41 -15
  260. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  261. package/lib/langium/workspace/index-manager.d.ts.map +1 -1
  262. package/lib/langium/workspace/index-manager.js.map +1 -1
  263. package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
  264. package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
  265. package/lib/langium/workspace/initialize-workspace.js +13 -5
  266. package/lib/langium/workspace/initialize-workspace.js.map +1 -1
  267. package/lib/langium/workspace/langium-documents.d.ts +86 -17
  268. package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
  269. package/lib/langium/workspace/langium-documents.js +101 -29
  270. package/lib/langium/workspace/langium-documents.js.map +1 -1
  271. package/lib/langium/workspace/persistent-file-system-provider.d.ts +0 -7
  272. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  273. package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
  274. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  275. package/lib/langium/workspace/virtual-document.d.ts +48 -15
  276. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  277. package/lib/langium/workspace/virtual-document.js +78 -18
  278. package/lib/langium/workspace/virtual-document.js.map +1 -1
  279. package/lib/langium/workspace/write-lock-scope.d.ts +20 -10
  280. package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
  281. package/lib/langium/workspace/write-lock-scope.js +12 -4
  282. package/lib/langium/workspace/write-lock-scope.js.map +1 -1
  283. package/lib/locale/index.d.ts +10 -0
  284. package/lib/locale/index.d.ts.map +1 -0
  285. package/lib/locale/index.js +10 -0
  286. package/lib/locale/index.js.map +1 -0
  287. package/lib/locale/server-locale.d.ts +73 -0
  288. package/lib/locale/server-locale.d.ts.map +1 -0
  289. package/lib/locale/server-locale.js +61 -0
  290. package/lib/locale/server-locale.js.map +1 -0
  291. package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
  292. package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
  293. package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
  294. package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
  295. package/lib/lsp/connection-features.d.ts +23 -0
  296. package/lib/lsp/connection-features.d.ts.map +1 -0
  297. package/lib/lsp/connection-features.js +60 -0
  298. package/lib/lsp/connection-features.js.map +1 -0
  299. package/lib/lsp/diagnostics-connection.d.ts +27 -0
  300. package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
  301. package/lib/lsp/diagnostics-connection.js +53 -0
  302. package/lib/lsp/diagnostics-connection.js.map +1 -0
  303. package/lib/lsp/hydranium-document-update-handler.d.ts +90 -79
  304. package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
  305. package/lib/lsp/hydranium-document-update-handler.js +153 -99
  306. package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
  307. package/lib/lsp/index.d.ts +3 -1
  308. package/lib/lsp/index.d.ts.map +1 -1
  309. package/lib/lsp/index.js +3 -1
  310. package/lib/lsp/index.js.map +1 -1
  311. package/lib/lsp/lsp-latency.d.ts +39 -0
  312. package/lib/lsp/lsp-latency.d.ts.map +1 -0
  313. package/lib/lsp/lsp-latency.js +58 -0
  314. package/lib/lsp/lsp-latency.js.map +1 -0
  315. package/lib/lsp/semantic-token-provider.d.ts +34 -1
  316. package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
  317. package/lib/lsp/semantic-token-provider.js +55 -8
  318. package/lib/lsp/semantic-token-provider.js.map +1 -1
  319. package/lib/lsp/shared-module.d.ts +4 -8
  320. package/lib/lsp/shared-module.d.ts.map +1 -1
  321. package/lib/lsp/shared-module.js.map +1 -1
  322. package/lib/lsp/start-language-server.d.ts +8 -7
  323. package/lib/lsp/start-language-server.d.ts.map +1 -1
  324. package/lib/lsp/start-language-server.js +13 -7
  325. package/lib/lsp/start-language-server.js.map +1 -1
  326. package/lib/messages/carriers.d.ts +54 -0
  327. package/lib/messages/carriers.d.ts.map +1 -0
  328. package/lib/messages/carriers.js +62 -0
  329. package/lib/messages/carriers.js.map +1 -0
  330. package/lib/messages/index.d.ts +25 -0
  331. package/lib/messages/index.d.ts.map +1 -0
  332. package/lib/messages/index.js +25 -0
  333. package/lib/messages/index.js.map +1 -0
  334. package/lib/messages/renderer.d.ts +142 -0
  335. package/lib/messages/renderer.d.ts.map +1 -0
  336. package/lib/messages/renderer.js +165 -0
  337. package/lib/messages/renderer.js.map +1 -0
  338. package/lib/node/event-loop-monitor.js.map +1 -1
  339. package/lib/node/heap-ceiling.d.ts +61 -0
  340. package/lib/node/heap-ceiling.d.ts.map +1 -0
  341. package/lib/node/heap-ceiling.js +72 -0
  342. package/lib/node/heap-ceiling.js.map +1 -0
  343. package/lib/node/index.d.ts +1 -0
  344. package/lib/node/index.d.ts.map +1 -1
  345. package/lib/node/index.js +1 -0
  346. package/lib/node/index.js.map +1 -1
  347. package/lib/node/latency-from-env.d.ts +1 -1
  348. package/lib/node/latency-from-env.js +1 -1
  349. package/lib/node/lint-grammar.js.map +1 -1
  350. package/lib/node/measure-memory.d.ts.map +1 -1
  351. package/lib/node/measure-memory.js +1 -0
  352. package/lib/node/measure-memory.js.map +1 -1
  353. package/lib/node/memory-monitor.js.map +1 -1
  354. package/lib/node/node-file-system-provider.d.ts +39 -4
  355. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  356. package/lib/node/node-file-system-provider.js +109 -49
  357. package/lib/node/node-file-system-provider.js.map +1 -1
  358. package/lib/node/process-memory.js.map +1 -1
  359. package/lib/node/profile-capture.d.ts +8 -2
  360. package/lib/node/profile-capture.d.ts.map +1 -1
  361. package/lib/node/profile-capture.js.map +1 -1
  362. package/lib/node/profile-digest.js.map +1 -1
  363. package/lib/node/profiling-run.d.ts +13 -3
  364. package/lib/node/profiling-run.d.ts.map +1 -1
  365. package/lib/node/profiling-run.js +17 -8
  366. package/lib/node/profiling-run.js.map +1 -1
  367. package/lib/node/rename-over-open-readers.d.ts +52 -0
  368. package/lib/node/rename-over-open-readers.d.ts.map +1 -0
  369. package/lib/node/rename-over-open-readers.js +66 -0
  370. package/lib/node/rename-over-open-readers.js.map +1 -0
  371. package/lib/node/socket-launcher.d.ts +16 -1
  372. package/lib/node/socket-launcher.d.ts.map +1 -1
  373. package/lib/node/socket-launcher.js +4 -3
  374. package/lib/node/socket-launcher.js.map +1 -1
  375. package/lib/node/stdio-launcher.d.ts +1 -1
  376. package/lib/node/stdio-launcher.d.ts.map +1 -1
  377. package/lib/node/stdio-launcher.js +1 -1
  378. package/lib/node/stdio-launcher.js.map +1 -1
  379. package/lib/testing/document-uri-policy-conformance.js.map +1 -1
  380. package/lib/testing/fake-description.js.map +1 -1
  381. package/lib/testing/fake-document.d.ts +16 -4
  382. package/lib/testing/fake-document.d.ts.map +1 -1
  383. package/lib/testing/fake-document.js +18 -3
  384. package/lib/testing/fake-document.js.map +1 -1
  385. package/lib/testing/index.d.ts +1 -1
  386. package/lib/testing/index.d.ts.map +1 -1
  387. package/lib/testing/index.js +2 -1
  388. package/lib/testing/index.js.map +1 -1
  389. package/lib/testing/langium-test-helpers.d.ts.map +1 -1
  390. package/lib/testing/langium-test-helpers.js +1 -0
  391. package/lib/testing/langium-test-helpers.js.map +1 -1
  392. package/lib/testing/make-noop-language-services.js.map +1 -1
  393. package/lib/testing/make-noop-shared-services.d.ts +14 -0
  394. package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
  395. package/lib/testing/make-noop-shared-services.js +28 -2
  396. package/lib/testing/make-noop-shared-services.js.map +1 -1
  397. package/lib/testing/make-test-services.d.ts +69 -14
  398. package/lib/testing/make-test-services.d.ts.map +1 -1
  399. package/lib/testing/make-test-services.js +39 -10
  400. package/lib/testing/make-test-services.js.map +1 -1
  401. package/lib/testing/make-test-tracer.js.map +1 -1
  402. package/lib/testing/node/golden-corpus.js.map +1 -1
  403. package/lib/testing/node/index.d.ts +1 -0
  404. package/lib/testing/node/index.d.ts.map +1 -1
  405. package/lib/testing/node/index.js +1 -0
  406. package/lib/testing/node/index.js.map +1 -1
  407. package/lib/testing/node/lsp-harness.d.ts.map +1 -1
  408. package/lib/testing/node/lsp-harness.js +2 -0
  409. package/lib/testing/node/lsp-harness.js.map +1 -1
  410. package/lib/testing/node/lsp-server-connection.d.ts +11 -3
  411. package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
  412. package/lib/testing/node/lsp-server-connection.js +42 -9
  413. package/lib/testing/node/lsp-server-connection.js.map +1 -1
  414. package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
  415. package/lib/testing/node/scratch-workspace.js +10 -5
  416. package/lib/testing/node/scratch-workspace.js.map +1 -1
  417. package/lib/testing/node/spawned-server.d.ts +14 -0
  418. package/lib/testing/node/spawned-server.d.ts.map +1 -1
  419. package/lib/testing/node/spawned-server.js +33 -1
  420. package/lib/testing/node/spawned-server.js.map +1 -1
  421. package/lib/testing/node/unhandled-rejections.d.ts +20 -0
  422. package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
  423. package/lib/testing/node/unhandled-rejections.js +32 -0
  424. package/lib/testing/node/unhandled-rejections.js.map +1 -0
  425. package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
  426. package/lib/testing/playwright/e2e-profiling.js.map +1 -1
  427. package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
  428. package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
  429. package/lib/testing/playwright/flaky-network-proxy.js +164 -0
  430. package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
  431. package/lib/testing/playwright/index.d.ts +1 -0
  432. package/lib/testing/playwright/index.d.ts.map +1 -1
  433. package/lib/testing/playwright/index.js +1 -0
  434. package/lib/testing/playwright/index.js.map +1 -1
  435. package/lib/testing/playwright/server-log-capture.d.ts +24 -8
  436. package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
  437. package/lib/testing/playwright/server-log-capture.js +27 -6
  438. package/lib/testing/playwright/server-log-capture.js.map +1 -1
  439. package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
  440. package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
  441. package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
  442. package/lib/testing/run-update-pipeline.d.ts +4 -4
  443. package/lib/testing/run-update-pipeline.d.ts.map +1 -1
  444. package/lib/testing/stub-ast-document-manager.d.ts +11 -9
  445. package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
  446. package/lib/testing/stub-ast-document-manager.js +25 -9
  447. package/lib/testing/stub-ast-document-manager.js.map +1 -1
  448. package/lib/testing/stub-document-builder.d.ts +26 -11
  449. package/lib/testing/stub-document-builder.d.ts.map +1 -1
  450. package/lib/testing/stub-document-builder.js +57 -4
  451. package/lib/testing/stub-document-builder.js.map +1 -1
  452. package/lib/testing/stub-hydranium-text-documents.d.ts +22 -7
  453. package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
  454. package/lib/testing/stub-hydranium-text-documents.js +97 -15
  455. package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
  456. package/lib/testing/stub-index-manager.js.map +1 -1
  457. package/lib/testing/stub-langium-documents.d.ts +3 -2
  458. package/lib/testing/stub-langium-documents.d.ts.map +1 -1
  459. package/lib/testing/stub-langium-documents.js.map +1 -1
  460. package/lib/testing/stub-model-service.d.ts +7 -6
  461. package/lib/testing/stub-model-service.d.ts.map +1 -1
  462. package/lib/testing/stub-model-service.js +4 -4
  463. package/lib/testing/stub-model-service.js.map +1 -1
  464. package/lib/testing/stub-project-manager.js.map +1 -1
  465. package/lib/testing/stub-service-registry.js.map +1 -1
  466. package/lib/util/connection-liveness.d.ts +7 -6
  467. package/lib/util/connection-liveness.d.ts.map +1 -1
  468. package/lib/util/connection-liveness.js +35 -14
  469. package/lib/util/connection-liveness.js.map +1 -1
  470. package/lib/util/environment.d.ts.map +1 -1
  471. package/lib/util/environment.js.map +1 -1
  472. package/lib/util/registry.d.ts.map +1 -1
  473. package/package.json +35 -26
  474. package/src/documents/ast-document-manager.ts +395 -126
  475. package/src/documents/client-ids.ts +5 -22
  476. package/src/documents/client-session-errors.ts +24 -0
  477. package/src/documents/client-session-registry.ts +240 -0
  478. package/src/documents/file-system-task-queue.ts +68 -0
  479. package/src/documents/hydranium-text-documents.ts +1175 -225
  480. package/src/documents/index.ts +5 -0
  481. package/src/documents/language-client-text-shadow.ts +59 -11
  482. package/src/documents/model-ledger.ts +66 -0
  483. package/src/documents/self-save-registry.ts +52 -13
  484. package/src/documents/version-sync-service.ts +267 -0
  485. package/src/index.ts +6 -0
  486. package/src/langium/ast-extension/ast-node-builder.ts +66 -22
  487. package/src/langium/bootstrap.ts +32 -9
  488. package/src/langium/config/configuration-provider.ts +119 -0
  489. package/src/langium/config/index.ts +1 -0
  490. package/src/langium/diagnostics/logger.ts +12 -5
  491. package/src/langium/diagnostics/lsp-logger.ts +58 -12
  492. package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
  493. package/src/langium/document-builder/build-session.ts +87 -0
  494. package/src/langium/document-builder/document-builder.ts +776 -59
  495. package/src/langium/document-builder/index.ts +1 -0
  496. package/src/langium/integration-services.ts +67 -6
  497. package/src/langium/integrity/integrity-rule.ts +13 -5
  498. package/src/langium/integrity/integrity-service.ts +220 -30
  499. package/src/langium/keys/containment.ts +87 -0
  500. package/src/langium/keys/index.ts +1 -0
  501. package/src/langium/keys/name-based-key-provider.ts +4 -0
  502. package/src/langium/language-module.ts +42 -4
  503. package/src/langium/model-service/client-session.ts +649 -0
  504. package/src/langium/model-service/index.ts +1 -0
  505. package/src/langium/model-service/model-service.ts +570 -433
  506. package/src/langium/module.ts +201 -64
  507. package/src/langium/naming/name-provider.ts +27 -5
  508. package/src/langium/naming/name-separator-validation.ts +34 -5
  509. package/src/langium/project/abstract-project-manager.ts +9 -1
  510. package/src/langium/project/project-change-event.ts +2 -2
  511. package/src/langium/residency/cst-residency-service.ts +46 -15
  512. package/src/langium/scope/hydranium-scope-provider.ts +60 -22
  513. package/src/langium/serialization/abstract-serializer.ts +13 -32
  514. package/src/langium/service-registry.ts +19 -2
  515. package/src/langium/shared-services.ts +25 -4
  516. package/src/langium/transfer/transfer-encoder.ts +102 -34
  517. package/src/langium/trivia/comment-preserver.ts +1100 -0
  518. package/src/langium/trivia/document-ending-preserver.ts +55 -0
  519. package/src/langium/trivia/index.ts +14 -0
  520. package/src/langium/trivia/trivia-contribution.ts +39 -0
  521. package/src/langium/trivia/trivia-preserver.ts +54 -0
  522. package/src/langium/trivia/trivia-service.ts +99 -0
  523. package/src/langium/update-rewrite/update-rewrite.ts +1 -1
  524. package/src/langium/validation/document-validator.ts +537 -11
  525. package/src/langium/workspace/document-uri-policy.ts +17 -12
  526. package/src/langium/workspace/file-not-found.ts +23 -0
  527. package/src/langium/workspace/file-system-provider.ts +153 -16
  528. package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
  529. package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
  530. package/src/langium/workspace/hydranium-workspace-manager.ts +153 -13
  531. package/src/langium/workspace/in-memory-file-system-provider.ts +47 -16
  532. package/src/langium/workspace/initialize-workspace.ts +43 -5
  533. package/src/langium/workspace/langium-documents.ts +124 -33
  534. package/src/langium/workspace/persistent-file-system-provider.ts +0 -7
  535. package/src/langium/workspace/virtual-document.ts +96 -19
  536. package/src/langium/workspace/write-lock-scope.ts +24 -11
  537. package/src/locale/index.ts +10 -0
  538. package/src/locale/server-locale.ts +86 -0
  539. package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
  540. package/src/lsp/connection-features.ts +67 -0
  541. package/src/lsp/diagnostics-connection.ts +56 -0
  542. package/src/lsp/hydranium-document-update-handler.ts +185 -106
  543. package/src/lsp/index.ts +3 -1
  544. package/src/lsp/lsp-latency.ts +62 -0
  545. package/src/lsp/semantic-token-provider.ts +74 -7
  546. package/src/lsp/shared-module.ts +4 -8
  547. package/src/lsp/start-language-server.ts +13 -7
  548. package/src/messages/carriers.ts +78 -0
  549. package/src/messages/index.ts +36 -0
  550. package/src/messages/renderer.ts +212 -0
  551. package/src/node/heap-ceiling.ts +108 -0
  552. package/src/node/index.ts +1 -0
  553. package/src/node/latency-from-env.ts +1 -1
  554. package/src/node/measure-memory.ts +1 -0
  555. package/src/node/node-file-system-provider.ts +122 -51
  556. package/src/node/profile-capture.ts +8 -2
  557. package/src/node/profiling-run.ts +30 -8
  558. package/src/node/rename-over-open-readers.ts +78 -0
  559. package/src/node/socket-launcher.ts +19 -4
  560. package/src/node/stdio-launcher.ts +1 -2
  561. package/src/testing/fake-document.ts +24 -5
  562. package/src/testing/index.ts +2 -1
  563. package/src/testing/langium-test-helpers.ts +1 -0
  564. package/src/testing/make-noop-shared-services.ts +50 -2
  565. package/src/testing/make-test-services.ts +120 -31
  566. package/src/testing/node/index.ts +1 -0
  567. package/src/testing/node/lsp-harness.ts +2 -0
  568. package/src/testing/node/lsp-server-connection.ts +61 -11
  569. package/src/testing/node/scratch-workspace.ts +10 -5
  570. package/src/testing/node/spawned-server.ts +35 -1
  571. package/src/testing/node/unhandled-rejections.ts +31 -0
  572. package/src/testing/playwright/flaky-network-proxy.ts +240 -0
  573. package/src/testing/playwright/index.ts +1 -0
  574. package/src/testing/playwright/server-log-capture.ts +45 -11
  575. package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
  576. package/src/testing/run-update-pipeline.ts +4 -4
  577. package/src/testing/stub-ast-document-manager.ts +40 -23
  578. package/src/testing/stub-document-builder.ts +83 -17
  579. package/src/testing/stub-hydranium-text-documents.ts +133 -23
  580. package/src/testing/stub-langium-documents.ts +3 -2
  581. package/src/testing/stub-model-service.ts +9 -8
  582. package/src/util/connection-liveness.ts +37 -14
  583. package/src/util/environment.ts +9 -1
  584. package/lib/lsp/instrument-connection.d.ts +0 -36
  585. package/lib/lsp/instrument-connection.d.ts.map +0 -1
  586. package/lib/lsp/instrument-connection.js +0 -62
  587. package/lib/lsp/instrument-connection.js.map +0 -1
  588. package/src/lsp/instrument-connection.ts +0 -66
@@ -10,6 +10,7 @@
10
10
  import {
11
11
  type Clock,
12
12
  DefaultTracer,
13
+ type Locale,
13
14
  type Logger,
14
15
  NoopLogger,
15
16
  type Project,
@@ -18,13 +19,24 @@ import {
18
19
  type TransferDiagnostic,
19
20
  type TransferElement
20
21
  } from '@hydranium/protocol';
22
+ import { DefaultServerLocale, type ServerLocale } from '../locale/server-locale.js';
23
+ import { DefaultMessageRenderer, type MessageRenderer } from '../messages/renderer.js';
21
24
  import type { Harness } from '@hydranium/protocol/testing';
22
25
  import { type AstNode, type AstNodeDescription, type WorkspaceLock } from '@hydranium/langium';
26
+ import {
27
+ type ClientSessionFactory,
28
+ type ClientSessionFactoryOptions,
29
+ DefaultClientSessionFactory
30
+ } from '../langium/model-service/client-session.js';
23
31
  import type { ModelService, ModelServiceOptions } from '../langium/model-service/model-service.js';
24
32
  import type { ServerSharedServices } from '../langium/module.js';
25
- import { TransferEncoder } from '../langium/transfer/transfer-encoder.js';
33
+ import type { AstDiagnostic } from '../langium/validation/document-validator.js';
34
+ import { DefaultTransferEncoder, type TransferEncoder } from '../langium/transfer/transfer-encoder.js';
26
35
  import { DefaultDocumentUriPolicy, type DocumentUriPolicy } from '../langium/workspace/document-uri-policy.js';
27
36
  import { HydraniumWorkspaceLock } from '../langium/workspace/hydranium-workspace-lock.js';
37
+ import { DefaultFileSystemTaskQueue, type FileSystemTaskQueue } from '../documents/file-system-task-queue.js';
38
+ import { DefaultModelLedger, type ModelLedger } from '../documents/model-ledger.js';
39
+ import { DefaultVersionSyncService, type VersionSyncService } from '../documents/version-sync-service.js';
28
40
  import type { FakeDocumentOptions } from './fake-document.js';
29
41
  import { makeStubDocumentBuilder, type StubDocumentBuilder } from './stub-document-builder.js';
30
42
  import { makeStubIndexManager, type StubIndexManager } from './stub-index-manager.js';
@@ -46,12 +58,21 @@ import { makeStubWritableFileSystem, type StubWritableFileSystem } from './stub-
46
58
  * to `ServerSharedServices` in {@link makeTestServices} is therefore the
47
59
  * single named place where the "stub stands in for the full service tree"
48
60
  * assertion happens.
61
+ *
62
+ * **`TDiagnostic` and `TTransferDiagnostic` are the two ends of a conversion
63
+ * and must stay separate.** The first is what the build left on
64
+ * `LangiumDocument.diagnostics` and what `ModelService` hands back on an
65
+ * `AstDocument`; the second is what `TransferEncoder.toTransferDiagnostic`
66
+ * produces for the wire. One parameter serving both makes the tree
67
+ * unbindable for an adopter who extends either shape, since extending one
68
+ * says nothing about the other.
49
69
  */
50
70
  export interface TestSharedServices<
51
71
  TAst extends AstNode = AstNode,
52
- TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
72
+ TDiagnostic extends AstDiagnostic = AstDiagnostic,
53
73
  TTransfer extends TransferElement = TransferElement,
54
- TProject extends Project = Project
74
+ TProject extends Project = Project,
75
+ TTransferDiagnostic extends TransferDiagnostic = TransferDiagnostic
55
76
  > {
56
77
  readonly Clock: Clock;
57
78
  readonly Logger: Logger;
@@ -72,6 +93,8 @@ export interface TestSharedServices<
72
93
  SelfSaveRegistry: StubSelfSaveRegistry;
73
94
  ProjectManager: StubProjectManager<TProject>;
74
95
  DocumentUriPolicy: DocumentUriPolicy;
96
+ /** The REAL queue: a stub that runs each task at once hides the save interleaving the queue exists to prevent. */
97
+ FileSystemTaskQueue: FileSystemTaskQueue;
75
98
  /**
76
99
  * Present only when {@link MakeTestServicesOptions.seedIndex} was passed.
77
100
  * Omitted otherwise for the same reason as `ServiceRegistry` — see that
@@ -88,19 +111,34 @@ export interface TestSharedServices<
88
111
  * through this tree and let a reentrant write pass unnoticed.
89
112
  */
90
113
  WorkspaceLock: WorkspaceLock;
114
+ /** The REAL ledger: it is a weak map with no dependencies. */
115
+ ModelLedger: ModelLedger;
116
+ /** The REAL service, over this tree's stubs; it reconciles nothing against the stub store. */
117
+ VersionSyncService: VersionSyncService;
91
118
  };
92
119
  readonly model: {
93
- TransferEncoder: TransferEncoder<unknown, TDiagnostic>;
120
+ TransferEncoder: TransferEncoder<TTransferDiagnostic>;
94
121
  ModelService: ModelService<TAst, TDiagnostic, TTransfer>;
122
+ ClientSessionFactory: ClientSessionFactory;
95
123
  };
124
+ /**
125
+ * The REAL services, not stubs — the framework renderer's no-catalogue
126
+ * behaviour is a pass-through, so the stub tree agrees with a production one
127
+ * unless a test installs a catalogue. Bound rather than omitted because
128
+ * `HydraniumDocumentBuilder` renders through the renderer on every
129
+ * `Validated` phase, where an omitted slot is a `TypeError`.
130
+ */
131
+ readonly ServerLocale: ServerLocale;
132
+ readonly MessageRenderer: MessageRenderer;
96
133
  }
97
134
 
98
135
  /** Optional configuration for {@link makeTestServices}. */
99
136
  export interface MakeTestServicesOptions<
100
137
  TAst extends AstNode = AstNode,
101
- TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
138
+ TDiagnostic extends AstDiagnostic = AstDiagnostic,
102
139
  TTransfer extends TransferElement = TransferElement,
103
- TProject extends Project = Project
140
+ TProject extends Project = Project,
141
+ TTransferDiagnostic extends TransferDiagnostic = TransferDiagnostic
104
142
  > {
105
143
  /**
106
144
  * Serialiser used by the bundled `StubModelService`. The stub tree
@@ -112,6 +150,14 @@ export interface MakeTestServicesOptions<
112
150
  * for tests that don't assert on the produced text.
113
151
  */
114
152
  serialize?: (uri: string, root: TTransfer) => string;
153
+ /**
154
+ * Renderer bound on `MessageRenderer`. Default: the framework's own, which
155
+ * passes every sentence through unchanged. Supply one to install a catalogue
156
+ * or to drive the throwing path.
157
+ */
158
+ messageRenderer?: (services: ServerSharedServices<TProject>) => MessageRenderer;
159
+ /** Locale handed to the bundle's {@link ServerLocale}. Default: none, i.e. the framework's English. */
160
+ locale?: Locale;
115
161
  /**
116
162
  * Languages to register on a {@link StubServiceRegistry} bound on the
117
163
  * `ServiceRegistry` slot. This is how a test gets multi-language routing:
@@ -120,7 +166,7 @@ export interface MakeTestServicesOptions<
120
166
  *
121
167
  * **Default: no `ServiceRegistry` slot at all.** Binding an empty registry
122
168
  * by default would silently change behaviour for the tests that rely on the
123
- * slot being absent — `ModelService.updateRewriteService` optional-chains it
169
+ * slot being absent — `ModelService.rewriteModel` optional-chains it
124
170
  * precisely for those bundles — so a registry appears only when a test asks
125
171
  * for one.
126
172
  */
@@ -178,16 +224,23 @@ export interface MakeTestServicesOptions<
178
224
  modelService?: (services: ServerSharedServices<TProject>) => ModelService<TAst, TDiagnostic, TTransfer>;
179
225
  /**
180
226
  * Framework {@link ModelServiceOptions} for the DEFAULT stub service, so a
181
- * test can reach an option-gated path (`serializeBuilds`, the slow-warn
182
- * threshold) without supplying a whole {@link modelService} factory. Ignored
183
- * when `modelService` is given — that factory owns its own construction.
227
+ * test can reach an option-gated path (`allowReentrantBuilds`) without supplying
228
+ * a whole {@link modelService} factory. Ignored when `modelService` is
229
+ * given — that factory owns its own construction.
184
230
  */
185
231
  modelServiceOptions?: ModelServiceOptions;
232
+ /**
233
+ * Options of the {@link DefaultClientSessionFactory} bound on
234
+ * `model.ClientSessionFactory`, so a test can reach the slow-update warn.
235
+ * Its sessions serialise and rebuild through the `model.ModelService` slot,
236
+ * so a test of a model service subclass passes it as {@link modelService}.
237
+ */
238
+ clientSessionFactoryOptions?: ClientSessionFactoryOptions;
186
239
  /**
187
240
  * Override the {@link TransferEncoder} factory. Default: framework
188
241
  * {@link TransferEncoder} with no overrides.
189
242
  */
190
- transferEncoder?: (services: ServerSharedServices<TProject>) => TransferEncoder<unknown, TDiagnostic>;
243
+ transferEncoder?: (services: ServerSharedServices<TProject, TTransferDiagnostic>) => TransferEncoder<TTransferDiagnostic>;
191
244
  }
192
245
 
193
246
  /**
@@ -205,11 +258,12 @@ export interface MakeTestServicesOptions<
205
258
  */
206
259
  export interface TestServicesBundle<
207
260
  TAst extends AstNode = AstNode,
208
- TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
261
+ TDiagnostic extends AstDiagnostic = AstDiagnostic,
209
262
  TTransfer extends TransferElement = TransferElement,
210
- TProject extends Project = Project
263
+ TProject extends Project = Project,
264
+ TTransferDiagnostic extends TransferDiagnostic = TransferDiagnostic
211
265
  > extends Harness {
212
- readonly services: ServerSharedServices<TProject>;
266
+ readonly services: ServerSharedServices<TProject, TTransferDiagnostic>;
213
267
  readonly documents: StubLangiumDocuments<TAst, TDiagnostic>;
214
268
  readonly textDocuments: StubHydraniumTextDocuments;
215
269
  readonly astDocumentManager: StubAstDocumentManager<TAst, TDiagnostic>;
@@ -218,6 +272,7 @@ export interface TestServicesBundle<
218
272
  readonly selfSaveRegistry: StubSelfSaveRegistry;
219
273
  readonly projectManager: StubProjectManager<TProject>;
220
274
  readonly documentUriPolicy: DocumentUriPolicy;
275
+ readonly modelLedger: ModelLedger;
221
276
  /**
222
277
  * The registry bound on the `ServiceRegistry` slot, or `undefined` when no
223
278
  * {@link MakeTestServicesOptions.languages} were declared.
@@ -229,10 +284,18 @@ export interface TestServicesBundle<
229
284
  */
230
285
  readonly indexManager: StubIndexManager | undefined;
231
286
  readonly modelService: ModelService<TAst, TDiagnostic, TTransfer>;
232
- readonly transferEncoder: TransferEncoder<unknown, TDiagnostic>;
287
+ readonly transferEncoder: TransferEncoder<TTransferDiagnostic>;
233
288
  readonly logger: Logger;
234
289
  /** The clock bound on the `Clock` slot — a `makeFakeClock()` if one was passed. */
235
290
  readonly clock: Clock;
291
+ /**
292
+ * The service bound on `ServerLocale`, so a test can hand over a locale
293
+ * mid-run — which is also how it verifies the renderer reads the locale per
294
+ * render rather than caching it at construction.
295
+ */
296
+ readonly serverLocale: ServerLocale;
297
+ /** The renderer bound on `MessageRenderer` — the framework's own unless one was supplied. */
298
+ readonly messageRenderer: MessageRenderer;
236
299
  }
237
300
 
238
301
  /**
@@ -247,22 +310,25 @@ export interface TestServicesBundle<
247
310
  */
248
311
  export function makeTestServices<
249
312
  TAst extends AstNode = AstNode,
250
- TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
313
+ TDiagnostic extends AstDiagnostic = AstDiagnostic,
251
314
  TTransfer extends TransferElement = TransferElement,
252
- TProject extends Project = Project
315
+ TProject extends Project = Project,
316
+ TTransferDiagnostic extends TransferDiagnostic = TransferDiagnostic
253
317
  >(
254
- options: MakeTestServicesOptions<TAst, TDiagnostic, TTransfer, TProject> = {}
255
- ): TestServicesBundle<TAst, TDiagnostic, TTransfer, TProject> {
318
+ options: MakeTestServicesOptions<TAst, TDiagnostic, TTransfer, TProject, TTransferDiagnostic> = {}
319
+ ): TestServicesBundle<TAst, TDiagnostic, TTransfer, TProject, TTransferDiagnostic> {
256
320
  const documents = makeStubLangiumDocuments<TAst, TDiagnostic>(options.seedDocuments);
257
321
  const textDocuments = makeStubHydraniumTextDocuments();
258
- const documentBuilder = makeStubDocumentBuilder();
259
- const selfSaveRegistry = makeStubSelfSaveRegistry();
260
- const fileSystem = makeStubWritableFileSystem(selfSaveRegistry);
261
- const projectManager = makeStubProjectManager<TProject>(options.seedProjects);
262
- const astDocumentManager = makeStubAstDocumentManager<TAst, TDiagnostic>(textDocuments, fileSystem, documents);
263
322
  const logger = options.logger ?? new NoopLogger();
264
323
  const clock = options.clock ?? new SystemClock();
265
324
  const tracer = new DefaultTracer(logger, clock);
325
+ const workspaceLock = new HydraniumWorkspaceLock({ Clock: clock, Tracer: tracer });
326
+ const documentBuilder = makeStubDocumentBuilder(workspaceLock);
327
+ const selfSaveRegistry = makeStubSelfSaveRegistry();
328
+ const fileSystem = makeStubWritableFileSystem(selfSaveRegistry);
329
+ const projectManager = makeStubProjectManager<TProject>(options.seedProjects);
330
+ const modelLedger = new DefaultModelLedger();
331
+ const astDocumentManager = makeStubAstDocumentManager<TAst, TDiagnostic>(textDocuments, fileSystem, documents, modelLedger);
266
332
  const documentUriPolicy = options.documentUriPolicy ?? new DefaultDocumentUriPolicy();
267
333
  const serviceRegistry = options.languages
268
334
  ? makeStubServiceRegistry(options.languages, { openLanguageIds: options.openLanguageIds })
@@ -285,11 +351,11 @@ export function makeTestServices<
285
351
  // is dependency-free (as `HydraniumWorkspaceLock` is) — a no-op stub of a
286
352
  // synchronisation primitive hides the very interleaving it exists to prevent.
287
353
  //
288
- // `model.TransferEncoder` / `model.ModelService` are populated below
354
+ // The `model` slots are populated below
289
355
  // (after the factories run); the literal uses unsafe casts to
290
356
  // partially-built objects to satisfy TestSharedServices, then patches
291
357
  // them in.
292
- const services: TestSharedServices<TAst, TDiagnostic, TTransfer, TProject> = {
358
+ const services: TestSharedServices<TAst, TDiagnostic, TTransfer, TProject, TTransferDiagnostic> = {
293
359
  Clock: clock,
294
360
  Logger: logger,
295
361
  Tracer: tracer,
@@ -309,26 +375,46 @@ export function makeTestServices<
309
375
  // Spread for the same reason as `ServiceRegistry` above — the slot must
310
376
  // be genuinely ABSENT, not present-and-undefined, when no index was seeded.
311
377
  ...(indexManager ? { IndexManager: indexManager } : {}),
312
- WorkspaceLock: new HydraniumWorkspaceLock()
378
+ WorkspaceLock: workspaceLock,
379
+ FileSystemTaskQueue: new DefaultFileSystemTaskQueue({ workspace: { DocumentUriPolicy: documentUriPolicy } }),
380
+ ModelLedger: modelLedger,
381
+ // Patched in below: it reads the tree it belongs to.
382
+ VersionSyncService: {} as VersionSyncService
313
383
  },
314
- model: {} as TestSharedServices<TAst, TDiagnostic, TTransfer, TProject>['model']
384
+ model: {} as TestSharedServices<TAst, TDiagnostic, TTransfer, TProject, TTransferDiagnostic>['model'],
385
+ ServerLocale: {} as ServerLocale,
386
+ MessageRenderer: {} as DefaultMessageRenderer
315
387
  };
316
- const sharedServices = services as unknown as ServerSharedServices<TProject>;
388
+ const sharedServices = services as unknown as ServerSharedServices<TProject, TTransferDiagnostic>;
389
+
390
+ // Patched in after the literal, like `model` below: both read the tree they
391
+ // belong to, and the renderer reads the locale service.
392
+ services.workspace.VersionSyncService = new DefaultVersionSyncService(sharedServices);
393
+ const mutableMessages = services as { ServerLocale: ServerLocale; MessageRenderer: MessageRenderer };
394
+ const serverLocale = new DefaultServerLocale(sharedServices);
395
+ if (options.locale) {
396
+ serverLocale.accept(options.locale);
397
+ }
398
+ mutableMessages.ServerLocale = serverLocale;
399
+ const messageRenderer = options.messageRenderer?.(sharedServices) ?? new DefaultMessageRenderer(sharedServices);
400
+ mutableMessages.MessageRenderer = messageRenderer;
317
401
 
318
402
  const serialize = options.serialize ?? ((_uri: string, root: TTransfer) => JSON.stringify(root));
319
403
  const transferEncoder = options.transferEncoder
320
404
  ? options.transferEncoder(sharedServices)
321
- : new TransferEncoder<unknown, TDiagnostic>(sharedServices);
405
+ : new DefaultTransferEncoder<unknown, TTransferDiagnostic>(sharedServices);
322
406
  const modelService = options.modelService
323
407
  ? options.modelService(sharedServices)
324
408
  : makeStubModelService<TAst, TDiagnostic, TTransfer>(sharedServices, serialize, options.modelServiceOptions);
325
409
 
326
410
  const mutableModel = services.model as {
327
- TransferEncoder: TransferEncoder<unknown, TDiagnostic>;
411
+ TransferEncoder: TransferEncoder<TTransferDiagnostic>;
328
412
  ModelService: ModelService<TAst, TDiagnostic, TTransfer>;
413
+ ClientSessionFactory: ClientSessionFactory;
329
414
  };
330
415
  mutableModel.TransferEncoder = transferEncoder;
331
416
  mutableModel.ModelService = modelService;
417
+ mutableModel.ClientSessionFactory = new DefaultClientSessionFactory(sharedServices, options.clientSessionFactoryOptions);
332
418
 
333
419
  return {
334
420
  services: sharedServices,
@@ -340,12 +426,15 @@ export function makeTestServices<
340
426
  selfSaveRegistry,
341
427
  projectManager,
342
428
  documentUriPolicy,
429
+ modelLedger,
343
430
  serviceRegistry,
344
431
  indexManager,
345
432
  modelService,
346
433
  transferEncoder,
347
434
  logger,
348
435
  clock,
436
+ serverLocale,
437
+ messageRenderer,
349
438
  dispose: () => {
350
439
  // No-op: the bundled stubs hold only in-memory state (maps, arrays),
351
440
  // released with the bundle when it goes out of scope. The hook exists
@@ -27,3 +27,4 @@ export * from './lsp-harness.js';
27
27
  export * from './lsp-server-connection.js';
28
28
  export * from './scratch-workspace.js';
29
29
  export * from './spawned-server.js';
30
+ export * from './unhandled-rejections.js';
@@ -216,12 +216,14 @@ export function makeLspHarness(options: MakeLspHarnessOptions): LspHarness {
216
216
  },
217
217
  shutdown: transport.shutdown,
218
218
  openDocument: transport.openDocument,
219
+ closeDocument: transport.closeDocument,
219
220
  changeDocument: transport.changeDocument,
220
221
  completion: transport.completion,
221
222
  hover: transport.hover,
222
223
  semanticTokens: transport.semanticTokens,
223
224
  nextDiagnostics: transport.nextDiagnostics,
224
225
  appliedEdits: transport.appliedEdits,
226
+ wireBytes: transport.wireBytes,
225
227
  nextAppliedEdit: transport.nextAppliedEdit,
226
228
  setApplyEditHandler: transport.setApplyEditHandler,
227
229
  buildWorkspace: folders => buildWorkspaceProgrammatically(services, folders),
@@ -8,17 +8,16 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  import { type Harness } from '@hydranium/protocol/testing';
11
- import { makeDuplexStreamPair } from '@hydranium/protocol/testing/node';
11
+ import { PassThrough, type TransformCallback } from 'node:stream';
12
12
  import { StreamMessageReader, StreamMessageWriter } from 'vscode-jsonrpc/node';
13
13
  import { type Connection, ProposedFeatures } from 'vscode-languageserver/node';
14
+ import { withHydraniumLspFeatures } from '../../lsp/connection-features.js';
14
15
  // The node `createConnection` from `vscode-languageserver/node` is built for a
15
16
  // standalone server PROCESS: it wires `process.exit()` onto the input stream's
16
17
  // `end`/`close` events, onto the `exit` notification (via its watchDog), and onto
17
- // a parent-pid liveness timer, and it calls `endProtocolConnection()` (a write)
18
- // on stream close. In-process every one of those is fatal — destroying the
19
- // streams at teardown trips the `close` handler, which writes into the destroyed
20
- // stream (an uncatchable synchronous `ERR_STREAM_DESTROYED`) and/or exits the host
21
- // test runner. The lower-level common `createConnection(connectionFactory,
18
+ // a parent-pid liveness timer. In-process every one of those is fatal —
19
+ // destroying the streams at teardown trips the `close` handler, which exits the
20
+ // host test runner. The lower-level common `createConnection(connectionFactory,
22
21
  // watchDog, features)` form does none of that: it lets us inject a no-op-`exit`
23
22
  // WatchDog and build the connection over the in-memory streams, so teardown is the
24
23
  // primitive's responsibility alone.
@@ -30,6 +29,7 @@ import {
30
29
  ApplyWorkspaceEditRequest,
31
30
  CompletionRequest,
32
31
  DidChangeTextDocumentNotification,
32
+ DidCloseTextDocumentNotification,
33
33
  DidOpenTextDocumentNotification,
34
34
  HoverRequest,
35
35
  InitializeRequest,
@@ -170,8 +170,8 @@ function insertedText(edit: WorkspaceEdit): string {
170
170
  }
171
171
 
172
172
  /**
173
- * The in-process LSP transport seam — a real `Connection` over the in-memory
174
- * {@link makeDuplexStreamPair}, plus the client side, the diagnostics capture,
173
+ * The in-process LSP transport seam — a real `Connection` over a crossed pair
174
+ * of in-memory streams, plus the client side, the diagnostics capture,
175
175
  * and the typed request facades — with NO services attached. It is the lower
176
176
  * half of `makeLspHarness`, factored out so a caller can OWN the services
177
177
  * tree: build the tree around {@link serverConnection} (`createXxxServices({
@@ -226,6 +226,12 @@ export interface LspServerConnection extends Harness {
226
226
  * unhandled method.
227
227
  */
228
228
  readonly appliedEdits: ReadonlyArray<AppliedEdit>;
229
+ /** Bytes written in each direction of the in-process JSON-RPC wire. */
230
+ readonly wireBytes: () => {
231
+ readonly clientToServer: number;
232
+ readonly serverToClient: number;
233
+ readonly total: number;
234
+ };
229
235
 
230
236
  /**
231
237
  * Drive the real LSP `initialize` → `initialized` handshake and return the
@@ -247,6 +253,8 @@ export interface LspServerConnection extends Harness {
247
253
  * associates with a language (silent no-diagnostics). `version` defaults to 1.
248
254
  */
249
255
  openDocument(uri: string, text: string, languageId: string, version?: number): void;
256
+ /** Send `textDocument/didClose` for a document opened through this harness. */
257
+ closeDocument(uri: string): Promise<void>;
250
258
  /** Send `textDocument/didChange` for `uri` as a single full-text replacement at `version`. */
251
259
  changeDocument(uri: string, text: string, version: number): void;
252
260
 
@@ -293,7 +301,7 @@ export interface LspServerConnection extends Harness {
293
301
  *
294
302
  * **An egress push is asynchronous well past the call that triggers it** —
295
303
  * the framework coalesces per URI and drives the sync from a build-phase
296
- * settle, so a `ModelService.update` resolves long before the push is sent.
304
+ * settle, so a session's `update` resolves long before the push is sent.
297
305
  * Record `appliedEdits.length`, drive the edit, then await this; reading the
298
306
  * capture on the line after the write proves nothing.
299
307
  */
@@ -319,6 +327,39 @@ export interface LspServerConnection extends Harness {
319
327
  dispose(): void;
320
328
  }
321
329
 
330
+ /**
331
+ * A `PassThrough` that counts the bytes written through it. Counting here
332
+ * rather than in a `'data'` listener is what keeps the wire buffering: a
333
+ * listener switches the stream to flowing mode, and a message written before
334
+ * the server calls `listen()` is then delivered to the counter alone and lost.
335
+ */
336
+ class CountingPassThrough extends PassThrough {
337
+ bytes = 0;
338
+
339
+ override _transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback): void {
340
+ this.bytes += chunk.length;
341
+ callback(null, chunk);
342
+ }
343
+ }
344
+
345
+ /** A crossed pair of {@link CountingPassThrough}s, disposed as one. */
346
+ function makeCountingStreamPair(): {
347
+ readonly clientToServer: CountingPassThrough;
348
+ readonly serverToClient: CountingPassThrough;
349
+ dispose(): void;
350
+ } {
351
+ const clientToServer = new CountingPassThrough();
352
+ const serverToClient = new CountingPassThrough();
353
+ return {
354
+ clientToServer,
355
+ serverToClient,
356
+ dispose(): void {
357
+ clientToServer.destroy();
358
+ serverToClient.destroy();
359
+ }
360
+ };
361
+ }
362
+
322
363
  /**
323
364
  * Build the in-process LSP transport seam (server `Connection` + client + wire +
324
365
  * diagnostics capture + typed facades) WITHOUT attaching a server. The caller
@@ -331,7 +372,7 @@ export interface LspServerConnection extends Harness {
331
372
  * additional protocol heads (data-server, GLSP) onto the same `shared` services.
332
373
  */
333
374
  export function makeLspServerConnection(): LspServerConnection {
334
- const pair = makeDuplexStreamPair();
375
+ const pair = makeCountingStreamPair();
335
376
 
336
377
  // No-op watchDog: in-process, no LSP lifecycle event (parent-pid liveness, the
337
378
  // `exit` notification, …) may exit the host test runner — `dispose()` owns
@@ -347,7 +388,7 @@ export function makeLspServerConnection(): LspServerConnection {
347
388
  logger =>
348
389
  createProtocolConnection(new StreamMessageReader(pair.clientToServer), new StreamMessageWriter(pair.serverToClient), logger),
349
390
  watchDog,
350
- ProposedFeatures.all
391
+ withHydraniumLspFeatures(ProposedFeatures.all)
351
392
  );
352
393
 
353
394
  // Client side mirrors the directions: reads serverToClient, writes clientToServer.
@@ -415,6 +456,11 @@ export function makeLspServerConnection(): LspServerConnection {
415
456
  client,
416
457
  diagnostics,
417
458
  appliedEdits,
459
+ wireBytes: () => ({
460
+ clientToServer: pair.clientToServer.bytes,
461
+ serverToClient: pair.serverToClient.bytes,
462
+ total: pair.clientToServer.bytes + pair.serverToClient.bytes
463
+ }),
418
464
 
419
465
  async initialize(params?: Partial<InitializeParams>): Promise<InitializeResult> {
420
466
  const initializeParams: InitializeParams = {
@@ -455,6 +501,10 @@ export function makeLspServerConnection(): LspServerConnection {
455
501
  });
456
502
  },
457
503
 
504
+ async closeDocument(uri: string): Promise<void> {
505
+ await client.sendNotification(DidCloseTextDocumentNotification.type, { textDocument: { uri } });
506
+ },
507
+
458
508
  changeDocument(uri: string, text: string, version: number): void {
459
509
  client.sendNotification(DidChangeTextDocumentNotification.type, {
460
510
  textDocument: { uri, version },
@@ -14,15 +14,15 @@
14
14
  *
15
15
  * Any test that drives a **write path** needs one, and the reason is not
16
16
  * obvious enough to rediscover per suite. The writes themselves are usually
17
- * in-memory — `ModelService.update` goes to the multi-client text store, and
17
+ * in-memory — a session's `update` goes to the multi-client text store, and
18
18
  * only `save` reaches disk — but a rebuild also runs the integrity rules, and
19
19
  * their default `'silent'` sync mode persists repairs through
20
20
  * `WritableFileSystemProvider.writeFile`. So a write-path test pointed at a
21
21
  * committed sample workspace can **rewrite the sample files**, after which
22
22
  * every later run asserts against already-repaired input: a suite that passes
23
23
  * while testing nothing. The same applies to a fixture built in place, which
24
- * additionally loses its explanatory comments, because the write-back goes
25
- * through the serializer.
24
+ * additionally comes back in the serializer's layout, because the write-back
25
+ * goes through it.
26
26
  *
27
27
  * The second reason is cleanup. Hand-rolled `mkdtempSync` without a matching
28
28
  * `rmSync` leaks a directory per test run into the OS temp dir, which nobody
@@ -49,7 +49,7 @@
49
49
  */
50
50
 
51
51
  import { URI } from '@hydranium/langium';
52
- import { cpSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
52
+ import { cpSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
53
53
  import { tmpdir } from 'node:os';
54
54
  import * as path from 'node:path';
55
55
 
@@ -106,7 +106,12 @@ export interface ScratchWorkspace {
106
106
  * returned {@link ScratchWorkspace.dispose} with an `afterEach`.
107
107
  */
108
108
  export function makeScratchWorkspace(options: ScratchWorkspaceOptions = {}): ScratchWorkspace {
109
- const root = mkdtempSync(path.join(tmpdir(), options.prefix ?? 'hydranium-scratch-'));
109
+ // RESOLVED, because `tmpdir()` can itself be a symlink — on macOS it answers
110
+ // `/tmp`, which links to `/private/tmp`. A root the server canonicalises to a
111
+ // different path than the one it was handed registers documents under one
112
+ // spelling and reads them under the other, failing initialization with an
113
+ // ENOENT that names neither the link nor this call.
114
+ const root = realpathSync(mkdtempSync(path.join(tmpdir(), options.prefix ?? 'hydranium-scratch-')));
110
115
  if (options.seed) {
111
116
  cpSync(options.seed, root, { recursive: true });
112
117
  }
@@ -203,6 +203,37 @@ export interface SpawnedServer extends Harness {
203
203
  dispose(): Promise<number | null>;
204
204
  }
205
205
 
206
+ /**
207
+ * Every server started and not yet disposed, so {@link disposeSpawnedServers}
208
+ * can reach one a test forgot.
209
+ *
210
+ * Holds the server — and through it the `ChildProcess` — rather than a pid. A
211
+ * pid identifies a process only while that process is alive: once it exits the
212
+ * OS may reissue the number, and Windows does so within seconds. A teardown
213
+ * that signalled a recorded pid would therefore reach whatever holds it now,
214
+ * which on a concurrent build is another task's compiler or test runner.
215
+ */
216
+ const liveServers = new Set<SpawnedServer>();
217
+
218
+ /**
219
+ * Terminate every server this module started that has not been disposed, and
220
+ * forget them.
221
+ *
222
+ * Safe to call when none are outstanding, and safe to call twice. Nothing here
223
+ * can reach a process this module did not spawn, because every kill goes
224
+ * through the `ChildProcess` handle libuv holds and libuv will not signal a
225
+ * child it has already reaped.
226
+ *
227
+ * A suite that disposes each server as it finishes needs this only as a net; a
228
+ * suite that does not needs it, because an orphan holding a port or a pipe
229
+ * makes the NEXT run's verdict meaningless.
230
+ */
231
+ export async function disposeSpawnedServers(): Promise<void> {
232
+ const outstanding = [...liveServers];
233
+ liveServers.clear();
234
+ await Promise.all(outstanding.map(server => server.dispose()));
235
+ }
236
+
206
237
  /** The captured streams, quoted into a boot-failure message. */
207
238
  function bootDiagnosis(stdoutPrefix: string, stderr: string): string {
208
239
  return (
@@ -390,7 +421,7 @@ export async function startSpawnedServer(options: SpawnedServerOptions): Promise
390
421
  return exitCode;
391
422
  }
392
423
 
393
- return {
424
+ const server: SpawnedServer = {
394
425
  connection,
395
426
  pid: child.pid,
396
427
  initializeResult,
@@ -440,8 +471,11 @@ export async function startSpawnedServer(options: SpawnedServerOptions): Promise
440
471
  });
441
472
  },
442
473
  dispose(): Promise<number | null> {
474
+ liveServers.delete(server);
443
475
  disposal ??= terminate();
444
476
  return disposal;
445
477
  }
446
478
  };
479
+ liveServers.add(server);
480
+ return server;
447
481
  }
@@ -0,0 +1,31 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ /**
11
+ * Run a Node-only assertion while collecting process-level unhandled rejection
12
+ * events. The callback owns the event-loop drain and can therefore choose the
13
+ * right observation window for the operation under test.
14
+ *
15
+ * Inside the window a rejection reaches only the array: while any listener is
16
+ * registered, Node hands none to its default handler and Vitest reports none as
17
+ * an error. A callback that never asserts on the array therefore hides every
18
+ * rejection it provokes.
19
+ */
20
+ export async function captureUnhandledRejections<T>(callback: (rejections: unknown[]) => Promise<T>): Promise<T> {
21
+ const rejections: unknown[] = [];
22
+ const listener = (reason: unknown): void => {
23
+ rejections.push(reason);
24
+ };
25
+ process.on('unhandledRejection', listener);
26
+ try {
27
+ return await callback(rejections);
28
+ } finally {
29
+ process.off('unhandledRejection', listener);
30
+ }
31
+ }