@hydranium/core 1.0.0-next.22 → 1.0.0-next.221

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 (652) hide show
  1. package/README.md +14 -8
  2. package/lib/documents/ast-document-manager.d.ts +219 -122
  3. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  4. package/lib/documents/ast-document-manager.js +241 -130
  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 +146 -0
  15. package/lib/documents/client-session-registry.d.ts.map +1 -0
  16. package/lib/documents/client-session-registry.js +207 -0
  17. package/lib/documents/client-session-registry.js.map +1 -0
  18. package/lib/documents/dirty-state-tracker.d.ts +79 -0
  19. package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
  20. package/lib/documents/dirty-state-tracker.js +69 -0
  21. package/lib/documents/dirty-state-tracker.js.map +1 -0
  22. package/lib/documents/document-release-handler.d.ts +179 -0
  23. package/lib/documents/document-release-handler.d.ts.map +1 -0
  24. package/lib/documents/document-release-handler.js +283 -0
  25. package/lib/documents/document-release-handler.js.map +1 -0
  26. package/lib/documents/document-release-scheduler.d.ts +67 -0
  27. package/lib/documents/document-release-scheduler.d.ts.map +1 -0
  28. package/lib/documents/document-release-scheduler.js +80 -0
  29. package/lib/documents/document-release-scheduler.js.map +1 -0
  30. package/lib/documents/file-system-task-queue.d.ts +49 -0
  31. package/lib/documents/file-system-task-queue.d.ts.map +1 -0
  32. package/lib/documents/file-system-task-queue.js +34 -0
  33. package/lib/documents/file-system-task-queue.js.map +1 -0
  34. package/lib/documents/hydranium-text-documents.d.ts +399 -282
  35. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  36. package/lib/documents/hydranium-text-documents.js +816 -483
  37. package/lib/documents/hydranium-text-documents.js.map +1 -1
  38. package/lib/documents/index.d.ts +10 -2
  39. package/lib/documents/index.d.ts.map +1 -1
  40. package/lib/documents/index.js +10 -2
  41. package/lib/documents/index.js.map +1 -1
  42. package/lib/documents/language-client-shadow.d.ts +218 -0
  43. package/lib/documents/language-client-shadow.d.ts.map +1 -0
  44. package/lib/documents/language-client-shadow.js +283 -0
  45. package/lib/documents/language-client-shadow.js.map +1 -0
  46. package/lib/documents/model-ledger.d.ts +47 -0
  47. package/lib/documents/model-ledger.d.ts.map +1 -0
  48. package/lib/documents/model-ledger.js +30 -0
  49. package/lib/documents/model-ledger.js.map +1 -0
  50. package/lib/documents/text-ledger.d.ts +64 -0
  51. package/lib/documents/text-ledger.d.ts.map +1 -0
  52. package/lib/documents/text-ledger.js +63 -0
  53. package/lib/documents/text-ledger.js.map +1 -0
  54. package/lib/documents/version-sync-service.d.ts +134 -0
  55. package/lib/documents/version-sync-service.d.ts.map +1 -0
  56. package/lib/documents/version-sync-service.js +171 -0
  57. package/lib/documents/version-sync-service.js.map +1 -0
  58. package/lib/index.d.ts +4 -0
  59. package/lib/index.d.ts.map +1 -1
  60. package/lib/index.js +7 -0
  61. package/lib/index.js.map +1 -1
  62. package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
  63. package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
  64. package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
  65. package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
  66. package/lib/langium/ast-extension/ast-node-builder.js +60 -22
  67. package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
  68. package/lib/langium/bootstrap.d.ts +5 -5
  69. package/lib/langium/bootstrap.d.ts.map +1 -1
  70. package/lib/langium/bootstrap.js +42 -17
  71. package/lib/langium/bootstrap.js.map +1 -1
  72. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
  73. package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
  74. package/lib/langium/composite-ast-reflection.d.ts +43 -0
  75. package/lib/langium/composite-ast-reflection.d.ts.map +1 -0
  76. package/lib/langium/composite-ast-reflection.js +92 -0
  77. package/lib/langium/composite-ast-reflection.js.map +1 -0
  78. package/lib/langium/config/configuration-provider.d.ts +81 -0
  79. package/lib/langium/config/configuration-provider.d.ts.map +1 -0
  80. package/lib/langium/config/configuration-provider.js +112 -0
  81. package/lib/langium/config/configuration-provider.js.map +1 -0
  82. package/lib/langium/config/index.d.ts +1 -0
  83. package/lib/langium/config/index.d.ts.map +1 -1
  84. package/lib/langium/config/index.js +1 -0
  85. package/lib/langium/config/index.js.map +1 -1
  86. package/lib/langium/config/settings.js.map +1 -1
  87. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
  88. package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
  89. package/lib/langium/diagnostics/logger.d.ts +10 -3
  90. package/lib/langium/diagnostics/logger.d.ts.map +1 -1
  91. package/lib/langium/diagnostics/logger.js +12 -5
  92. package/lib/langium/diagnostics/logger.js.map +1 -1
  93. package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
  94. package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
  95. package/lib/langium/diagnostics/lsp-logger.js +57 -16
  96. package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
  97. package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
  98. package/lib/langium/diagnostics/server-tracer.js.map +1 -1
  99. package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
  100. package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
  101. package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
  102. package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
  103. package/lib/langium/document-builder/build-session.d.ts +93 -0
  104. package/lib/langium/document-builder/build-session.d.ts.map +1 -0
  105. package/lib/langium/document-builder/build-session.js +72 -0
  106. package/lib/langium/document-builder/build-session.js.map +1 -0
  107. package/lib/langium/document-builder/document-builder.d.ts +401 -29
  108. package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
  109. package/lib/langium/document-builder/document-builder.js +698 -61
  110. package/lib/langium/document-builder/document-builder.js.map +1 -1
  111. package/lib/langium/document-builder/index.d.ts +1 -0
  112. package/lib/langium/document-builder/index.d.ts.map +1 -1
  113. package/lib/langium/document-builder/index.js +1 -0
  114. package/lib/langium/document-builder/index.js.map +1 -1
  115. package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
  116. package/lib/langium/documentation/comment-provider.js.map +1 -1
  117. package/lib/langium/integration-services.d.ts +61 -19
  118. package/lib/langium/integration-services.d.ts.map +1 -1
  119. package/lib/langium/integration-services.js +10 -5
  120. package/lib/langium/integration-services.js.map +1 -1
  121. package/lib/langium/integrity/integrity-rule.d.ts +16 -8
  122. package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
  123. package/lib/langium/integrity/integrity-rule.js.map +1 -1
  124. package/lib/langium/integrity/integrity-service.d.ts +81 -24
  125. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  126. package/lib/langium/integrity/integrity-service.js +264 -57
  127. package/lib/langium/integrity/integrity-service.js.map +1 -1
  128. package/lib/langium/keys/containment.d.ts +64 -0
  129. package/lib/langium/keys/containment.d.ts.map +1 -0
  130. package/lib/langium/keys/containment.js +53 -0
  131. package/lib/langium/keys/containment.js.map +1 -0
  132. package/lib/langium/keys/index.d.ts +1 -0
  133. package/lib/langium/keys/index.d.ts.map +1 -1
  134. package/lib/langium/keys/index.js +1 -0
  135. package/lib/langium/keys/index.js.map +1 -1
  136. package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
  137. package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
  138. package/lib/langium/keys/name-based-key-provider.js +4 -0
  139. package/lib/langium/keys/name-based-key-provider.js.map +1 -1
  140. package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
  141. package/lib/langium/keys/positional-key-provider.js.map +1 -1
  142. package/lib/langium/labeling/label-provider.d.ts.map +1 -1
  143. package/lib/langium/labeling/label-provider.js.map +1 -1
  144. package/lib/langium/language-module.d.ts +29 -4
  145. package/lib/langium/language-module.d.ts.map +1 -1
  146. package/lib/langium/language-module.js +18 -4
  147. package/lib/langium/language-module.js.map +1 -1
  148. package/lib/langium/model-service/client-session.d.ts +343 -0
  149. package/lib/langium/model-service/client-session.d.ts.map +1 -0
  150. package/lib/langium/model-service/client-session.js +411 -0
  151. package/lib/langium/model-service/client-session.js.map +1 -0
  152. package/lib/langium/model-service/index.d.ts +2 -0
  153. package/lib/langium/model-service/index.d.ts.map +1 -1
  154. package/lib/langium/model-service/index.js +2 -0
  155. package/lib/langium/model-service/index.js.map +1 -1
  156. package/lib/langium/model-service/model-events.d.ts +61 -0
  157. package/lib/langium/model-service/model-events.d.ts.map +1 -0
  158. package/lib/langium/model-service/model-events.js +10 -0
  159. package/lib/langium/model-service/model-events.js.map +1 -0
  160. package/lib/langium/model-service/model-service.d.ts +432 -282
  161. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  162. package/lib/langium/model-service/model-service.js +504 -438
  163. package/lib/langium/model-service/model-service.js.map +1 -1
  164. package/lib/langium/module.d.ts +157 -35
  165. package/lib/langium/module.d.ts.map +1 -1
  166. package/lib/langium/module.js +52 -35
  167. package/lib/langium/module.js.map +1 -1
  168. package/lib/langium/naming/name-provider.d.ts +25 -4
  169. package/lib/langium/naming/name-provider.d.ts.map +1 -1
  170. package/lib/langium/naming/name-provider.js +2 -1
  171. package/lib/langium/naming/name-provider.js.map +1 -1
  172. package/lib/langium/naming/name-separator-validation.d.ts +23 -0
  173. package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
  174. package/lib/langium/naming/name-separator-validation.js +30 -1
  175. package/lib/langium/naming/name-separator-validation.js.map +1 -1
  176. package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
  177. package/lib/langium/project/abstract-project-manager.js +9 -2
  178. package/lib/langium/project/abstract-project-manager.js.map +1 -1
  179. package/lib/langium/project/project-change-event.d.ts +2 -2
  180. package/lib/langium/project/single-project-manager.d.ts.map +1 -1
  181. package/lib/langium/project/single-project-manager.js.map +1 -1
  182. package/lib/langium/residency/cst-residency-service.d.ts +31 -11
  183. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  184. package/lib/langium/residency/cst-residency-service.js +23 -57
  185. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  186. package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
  187. package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
  188. package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
  189. package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
  190. package/lib/langium/scope/hydranium-scope-provider.d.ts +48 -13
  191. package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
  192. package/lib/langium/scope/hydranium-scope-provider.js +56 -20
  193. package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
  194. package/lib/langium/scope/reference-builder.d.ts.map +1 -1
  195. package/lib/langium/scope/reference-builder.js.map +1 -1
  196. package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
  197. package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
  198. package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
  199. package/lib/langium/scope/scope-extension-service.js.map +1 -1
  200. package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
  201. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  202. package/lib/langium/serialization/abstract-serializer.js +12 -21
  203. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  204. package/lib/langium/serialization/json-serializer.d.ts +1 -1
  205. package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
  206. package/lib/langium/serialization/json-serializer.js.map +1 -1
  207. package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
  208. package/lib/langium/serialization/yaml-serializer.js.map +1 -1
  209. package/lib/langium/service-registry.d.ts +29 -1
  210. package/lib/langium/service-registry.d.ts.map +1 -1
  211. package/lib/langium/service-registry.js +37 -0
  212. package/lib/langium/service-registry.js.map +1 -1
  213. package/lib/langium/shared-services.d.ts +23 -6
  214. package/lib/langium/shared-services.d.ts.map +1 -1
  215. package/lib/langium/shared-services.js.map +1 -1
  216. package/lib/langium/transfer/transfer-encoder.d.ts +77 -26
  217. package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
  218. package/lib/langium/transfer/transfer-encoder.js +46 -24
  219. package/lib/langium/transfer/transfer-encoder.js.map +1 -1
  220. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  221. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  222. package/lib/langium/trivia/comment-preserver.js +906 -0
  223. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  224. package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
  225. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  226. package/lib/langium/trivia/document-ending-preserver.js +48 -0
  227. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  228. package/lib/langium/trivia/index.d.ts +14 -0
  229. package/lib/langium/trivia/index.d.ts.map +1 -0
  230. package/lib/langium/trivia/index.js +14 -0
  231. package/lib/langium/trivia/index.js.map +1 -0
  232. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  233. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  234. package/lib/langium/trivia/trivia-contribution.js +10 -0
  235. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  236. package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
  237. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  238. package/lib/langium/trivia/trivia-preserver.js +10 -0
  239. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  240. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  241. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  242. package/lib/langium/trivia/trivia-service.js +56 -0
  243. package/lib/langium/trivia/trivia-service.js.map +1 -0
  244. package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
  245. package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
  246. package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
  247. package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
  248. package/lib/langium/validation/document-validator.d.ts +294 -10
  249. package/lib/langium/validation/document-validator.d.ts.map +1 -1
  250. package/lib/langium/validation/document-validator.js +448 -5
  251. package/lib/langium/validation/document-validator.js.map +1 -1
  252. package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
  253. package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
  254. package/lib/langium/validation/validation-contribution-collector.js +1 -1
  255. package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
  256. package/lib/langium/workspace/document-uri-policy.d.ts +18 -14
  257. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  258. package/lib/langium/workspace/document-uri-policy.js +10 -9
  259. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  260. package/lib/langium/workspace/file-not-found.d.ts +23 -0
  261. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  262. package/lib/langium/workspace/file-not-found.js +31 -0
  263. package/lib/langium/workspace/file-not-found.js.map +1 -0
  264. package/lib/langium/workspace/file-system-provider.d.ts +135 -9
  265. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  266. package/lib/langium/workspace/file-system-provider.js +93 -14
  267. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  268. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
  269. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
  270. package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
  271. package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
  272. package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
  273. package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
  274. package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
  275. package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
  276. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +82 -9
  277. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  278. package/lib/langium/workspace/hydranium-workspace-manager.js +128 -10
  279. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  280. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -3
  281. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  282. package/lib/langium/workspace/in-memory-file-system-provider.js +41 -15
  283. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  284. package/lib/langium/workspace/index-manager.d.ts.map +1 -1
  285. package/lib/langium/workspace/index-manager.js.map +1 -1
  286. package/lib/langium/workspace/index.d.ts +1 -0
  287. package/lib/langium/workspace/index.d.ts.map +1 -1
  288. package/lib/langium/workspace/index.js +1 -0
  289. package/lib/langium/workspace/index.js.map +1 -1
  290. package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
  291. package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
  292. package/lib/langium/workspace/initialize-workspace.js +13 -5
  293. package/lib/langium/workspace/initialize-workspace.js.map +1 -1
  294. package/lib/langium/workspace/langium-documents.d.ts +86 -17
  295. package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
  296. package/lib/langium/workspace/langium-documents.js +101 -29
  297. package/lib/langium/workspace/langium-documents.js.map +1 -1
  298. package/lib/langium/workspace/persistent-file-system-provider.d.ts +1 -8
  299. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  300. package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
  301. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  302. package/lib/{documents → langium/workspace}/self-save-registry.d.ts +38 -7
  303. package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
  304. package/lib/{documents → langium/workspace}/self-save-registry.js +29 -16
  305. package/lib/langium/workspace/self-save-registry.js.map +1 -0
  306. package/lib/langium/workspace/virtual-document.d.ts +48 -15
  307. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  308. package/lib/langium/workspace/virtual-document.js +78 -18
  309. package/lib/langium/workspace/virtual-document.js.map +1 -1
  310. package/lib/langium/workspace/write-lock-scope.d.ts +20 -10
  311. package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
  312. package/lib/langium/workspace/write-lock-scope.js +12 -4
  313. package/lib/langium/workspace/write-lock-scope.js.map +1 -1
  314. package/lib/locale/index.d.ts +10 -0
  315. package/lib/locale/index.d.ts.map +1 -0
  316. package/lib/locale/index.js +10 -0
  317. package/lib/locale/index.js.map +1 -0
  318. package/lib/locale/server-locale.d.ts +73 -0
  319. package/lib/locale/server-locale.d.ts.map +1 -0
  320. package/lib/locale/server-locale.js +61 -0
  321. package/lib/locale/server-locale.js.map +1 -0
  322. package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
  323. package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
  324. package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
  325. package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
  326. package/lib/lsp/connection-features.d.ts +23 -0
  327. package/lib/lsp/connection-features.d.ts.map +1 -0
  328. package/lib/lsp/connection-features.js +60 -0
  329. package/lib/lsp/connection-features.js.map +1 -0
  330. package/lib/lsp/diagnostics-connection.d.ts +27 -0
  331. package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
  332. package/lib/lsp/diagnostics-connection.js +53 -0
  333. package/lib/lsp/diagnostics-connection.js.map +1 -0
  334. package/lib/lsp/hydranium-document-update-handler.d.ts +92 -81
  335. package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
  336. package/lib/lsp/hydranium-document-update-handler.js +153 -99
  337. package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
  338. package/lib/lsp/index.d.ts +3 -1
  339. package/lib/lsp/index.d.ts.map +1 -1
  340. package/lib/lsp/index.js +3 -1
  341. package/lib/lsp/index.js.map +1 -1
  342. package/lib/lsp/lsp-latency.d.ts +39 -0
  343. package/lib/lsp/lsp-latency.d.ts.map +1 -0
  344. package/lib/lsp/lsp-latency.js +58 -0
  345. package/lib/lsp/lsp-latency.js.map +1 -0
  346. package/lib/lsp/semantic-token-provider.d.ts +34 -1
  347. package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
  348. package/lib/lsp/semantic-token-provider.js +55 -8
  349. package/lib/lsp/semantic-token-provider.js.map +1 -1
  350. package/lib/lsp/shared-module.d.ts +4 -8
  351. package/lib/lsp/shared-module.d.ts.map +1 -1
  352. package/lib/lsp/shared-module.js.map +1 -1
  353. package/lib/lsp/start-language-server.d.ts +8 -7
  354. package/lib/lsp/start-language-server.d.ts.map +1 -1
  355. package/lib/lsp/start-language-server.js +13 -7
  356. package/lib/lsp/start-language-server.js.map +1 -1
  357. package/lib/messages/carriers.d.ts +54 -0
  358. package/lib/messages/carriers.d.ts.map +1 -0
  359. package/lib/messages/carriers.js +62 -0
  360. package/lib/messages/carriers.js.map +1 -0
  361. package/lib/messages/index.d.ts +25 -0
  362. package/lib/messages/index.d.ts.map +1 -0
  363. package/lib/messages/index.js +25 -0
  364. package/lib/messages/index.js.map +1 -0
  365. package/lib/messages/renderer.d.ts +142 -0
  366. package/lib/messages/renderer.d.ts.map +1 -0
  367. package/lib/messages/renderer.js +165 -0
  368. package/lib/messages/renderer.js.map +1 -0
  369. package/lib/node/event-loop-monitor.js.map +1 -1
  370. package/lib/node/heap-ceiling.d.ts +61 -0
  371. package/lib/node/heap-ceiling.d.ts.map +1 -0
  372. package/lib/node/heap-ceiling.js +72 -0
  373. package/lib/node/heap-ceiling.js.map +1 -0
  374. package/lib/node/index.d.ts +1 -1
  375. package/lib/node/index.d.ts.map +1 -1
  376. package/lib/node/index.js +1 -1
  377. package/lib/node/index.js.map +1 -1
  378. package/lib/node/latency-from-env.d.ts +1 -1
  379. package/lib/node/latency-from-env.js +1 -1
  380. package/lib/node/lint-grammar.js.map +1 -1
  381. package/lib/node/measure-memory.d.ts.map +1 -1
  382. package/lib/node/measure-memory.js +1 -0
  383. package/lib/node/measure-memory.js.map +1 -1
  384. package/lib/node/memory-monitor.js.map +1 -1
  385. package/lib/node/node-file-system-provider.d.ts +41 -6
  386. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  387. package/lib/node/node-file-system-provider.js +109 -49
  388. package/lib/node/node-file-system-provider.js.map +1 -1
  389. package/lib/node/profile-capture.d.ts +8 -2
  390. package/lib/node/profile-capture.d.ts.map +1 -1
  391. package/lib/node/profile-capture.js +1 -1
  392. package/lib/node/profile-capture.js.map +1 -1
  393. package/lib/node/profile-digest.js.map +1 -1
  394. package/lib/node/profiling-run.d.ts +13 -3
  395. package/lib/node/profiling-run.d.ts.map +1 -1
  396. package/lib/node/profiling-run.js +17 -8
  397. package/lib/node/profiling-run.js.map +1 -1
  398. package/lib/node/rename-over-open-readers.d.ts +52 -0
  399. package/lib/node/rename-over-open-readers.d.ts.map +1 -0
  400. package/lib/node/rename-over-open-readers.js +66 -0
  401. package/lib/node/rename-over-open-readers.js.map +1 -0
  402. package/lib/node/socket-launcher.d.ts +20 -4
  403. package/lib/node/socket-launcher.d.ts.map +1 -1
  404. package/lib/node/socket-launcher.js +5 -4
  405. package/lib/node/socket-launcher.js.map +1 -1
  406. package/lib/node/stdio-launcher.d.ts +6 -5
  407. package/lib/node/stdio-launcher.d.ts.map +1 -1
  408. package/lib/node/stdio-launcher.js +2 -2
  409. package/lib/node/stdio-launcher.js.map +1 -1
  410. package/lib/testing/document-uri-policy-conformance.js.map +1 -1
  411. package/lib/testing/fake-description.js.map +1 -1
  412. package/lib/testing/fake-document.d.ts +16 -4
  413. package/lib/testing/fake-document.d.ts.map +1 -1
  414. package/lib/testing/fake-document.js +18 -3
  415. package/lib/testing/fake-document.js.map +1 -1
  416. package/lib/testing/index.d.ts +1 -1
  417. package/lib/testing/index.d.ts.map +1 -1
  418. package/lib/testing/index.js +2 -1
  419. package/lib/testing/index.js.map +1 -1
  420. package/lib/testing/langium-test-helpers.d.ts.map +1 -1
  421. package/lib/testing/langium-test-helpers.js +1 -0
  422. package/lib/testing/langium-test-helpers.js.map +1 -1
  423. package/lib/testing/make-noop-language-services.js.map +1 -1
  424. package/lib/testing/make-noop-shared-services.d.ts +14 -0
  425. package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
  426. package/lib/testing/make-noop-shared-services.js +28 -2
  427. package/lib/testing/make-noop-shared-services.js.map +1 -1
  428. package/lib/testing/make-test-services.d.ts +72 -14
  429. package/lib/testing/make-test-services.d.ts.map +1 -1
  430. package/lib/testing/make-test-services.js +42 -10
  431. package/lib/testing/make-test-services.js.map +1 -1
  432. package/lib/testing/make-test-tracer.d.ts +12 -0
  433. package/lib/testing/make-test-tracer.d.ts.map +1 -1
  434. package/lib/testing/make-test-tracer.js +13 -0
  435. package/lib/testing/make-test-tracer.js.map +1 -1
  436. package/lib/testing/node/golden-corpus.js.map +1 -1
  437. package/lib/testing/node/index.d.ts +1 -0
  438. package/lib/testing/node/index.d.ts.map +1 -1
  439. package/lib/testing/node/index.js +1 -0
  440. package/lib/testing/node/index.js.map +1 -1
  441. package/lib/testing/node/lsp-harness.d.ts.map +1 -1
  442. package/lib/testing/node/lsp-harness.js +2 -0
  443. package/lib/testing/node/lsp-harness.js.map +1 -1
  444. package/lib/testing/node/lsp-server-connection.d.ts +11 -3
  445. package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
  446. package/lib/testing/node/lsp-server-connection.js +43 -10
  447. package/lib/testing/node/lsp-server-connection.js.map +1 -1
  448. package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
  449. package/lib/testing/node/scratch-workspace.js +10 -5
  450. package/lib/testing/node/scratch-workspace.js.map +1 -1
  451. package/lib/testing/node/spawned-server.d.ts +14 -0
  452. package/lib/testing/node/spawned-server.d.ts.map +1 -1
  453. package/lib/testing/node/spawned-server.js +34 -2
  454. package/lib/testing/node/spawned-server.js.map +1 -1
  455. package/lib/testing/node/unhandled-rejections.d.ts +20 -0
  456. package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
  457. package/lib/testing/node/unhandled-rejections.js +32 -0
  458. package/lib/testing/node/unhandled-rejections.js.map +1 -0
  459. package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
  460. package/lib/testing/playwright/e2e-profiling.js.map +1 -1
  461. package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
  462. package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
  463. package/lib/testing/playwright/flaky-network-proxy.js +164 -0
  464. package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
  465. package/lib/testing/playwright/index.d.ts +1 -0
  466. package/lib/testing/playwright/index.d.ts.map +1 -1
  467. package/lib/testing/playwright/index.js +1 -0
  468. package/lib/testing/playwright/index.js.map +1 -1
  469. package/lib/testing/playwright/server-log-capture.d.ts +24 -8
  470. package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
  471. package/lib/testing/playwright/server-log-capture.js +27 -6
  472. package/lib/testing/playwright/server-log-capture.js.map +1 -1
  473. package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
  474. package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
  475. package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
  476. package/lib/testing/run-update-pipeline.d.ts +4 -4
  477. package/lib/testing/run-update-pipeline.d.ts.map +1 -1
  478. package/lib/testing/stub-ast-document-manager.d.ts +11 -52
  479. package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
  480. package/lib/testing/stub-ast-document-manager.js +24 -65
  481. package/lib/testing/stub-ast-document-manager.js.map +1 -1
  482. package/lib/testing/stub-document-builder.d.ts +26 -11
  483. package/lib/testing/stub-document-builder.d.ts.map +1 -1
  484. package/lib/testing/stub-document-builder.js +78 -5
  485. package/lib/testing/stub-document-builder.js.map +1 -1
  486. package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
  487. package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
  488. package/lib/testing/stub-hydranium-text-documents.js +115 -16
  489. package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
  490. package/lib/testing/stub-index-manager.js.map +1 -1
  491. package/lib/testing/stub-langium-documents.d.ts +3 -2
  492. package/lib/testing/stub-langium-documents.d.ts.map +1 -1
  493. package/lib/testing/stub-langium-documents.js.map +1 -1
  494. package/lib/testing/stub-model-service.d.ts +7 -6
  495. package/lib/testing/stub-model-service.d.ts.map +1 -1
  496. package/lib/testing/stub-model-service.js +4 -4
  497. package/lib/testing/stub-model-service.js.map +1 -1
  498. package/lib/testing/stub-project-manager.js.map +1 -1
  499. package/lib/testing/stub-self-save-registry.d.ts +1 -1
  500. package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
  501. package/lib/testing/stub-service-registry.d.ts +1 -1
  502. package/lib/testing/stub-service-registry.js.map +1 -1
  503. package/lib/testing/stub-writable-file-system.d.ts +1 -1
  504. package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
  505. package/lib/util/connection-liveness.d.ts +7 -6
  506. package/lib/util/connection-liveness.d.ts.map +1 -1
  507. package/lib/util/connection-liveness.js +35 -14
  508. package/lib/util/connection-liveness.js.map +1 -1
  509. package/lib/util/environment.d.ts.map +1 -1
  510. package/lib/util/environment.js.map +1 -1
  511. package/lib/util/registry.d.ts.map +1 -1
  512. package/package.json +32 -48
  513. package/src/documents/ast-document-manager.ts +379 -231
  514. package/src/documents/client-ids.ts +5 -22
  515. package/src/documents/client-session-errors.ts +24 -0
  516. package/src/documents/client-session-registry.ts +262 -0
  517. package/src/documents/dirty-state-tracker.ts +130 -0
  518. package/src/documents/document-release-handler.ts +365 -0
  519. package/src/documents/document-release-scheduler.ts +121 -0
  520. package/src/documents/file-system-task-queue.ts +68 -0
  521. package/src/documents/hydranium-text-documents.ts +931 -595
  522. package/src/documents/index.ts +10 -2
  523. package/src/documents/language-client-shadow.ts +451 -0
  524. package/src/documents/model-ledger.ts +66 -0
  525. package/src/documents/text-ledger.ts +112 -0
  526. package/src/documents/version-sync-service.ts +267 -0
  527. package/src/index.ts +7 -0
  528. package/src/langium/ast-extension/ast-node-builder.ts +66 -22
  529. package/src/langium/bootstrap.ts +42 -17
  530. package/src/langium/composite-ast-reflection.ts +107 -0
  531. package/src/langium/config/configuration-provider.ts +119 -0
  532. package/src/langium/config/index.ts +1 -0
  533. package/src/langium/diagnostics/logger.ts +12 -5
  534. package/src/langium/diagnostics/lsp-logger.ts +59 -15
  535. package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
  536. package/src/langium/document-builder/build-session.ts +87 -0
  537. package/src/langium/document-builder/document-builder.ts +825 -59
  538. package/src/langium/document-builder/index.ts +1 -0
  539. package/src/langium/integration-services.ts +83 -24
  540. package/src/langium/integrity/integrity-rule.ts +16 -8
  541. package/src/langium/integrity/integrity-service.ts +287 -62
  542. package/src/langium/keys/containment.ts +87 -0
  543. package/src/langium/keys/index.ts +1 -0
  544. package/src/langium/keys/name-based-key-provider.ts +4 -0
  545. package/src/langium/language-module.ts +48 -7
  546. package/src/langium/model-service/client-session.ts +644 -0
  547. package/src/langium/model-service/index.ts +2 -0
  548. package/src/langium/model-service/model-events.ts +75 -0
  549. package/src/langium/model-service/model-service.ts +790 -468
  550. package/src/langium/module.ts +210 -64
  551. package/src/langium/naming/name-provider.ts +27 -5
  552. package/src/langium/naming/name-separator-validation.ts +34 -5
  553. package/src/langium/project/abstract-project-manager.ts +9 -1
  554. package/src/langium/project/project-change-event.ts +2 -2
  555. package/src/langium/residency/cst-residency-service.ts +46 -15
  556. package/src/langium/scope/hydranium-scope-provider.ts +60 -22
  557. package/src/langium/serialization/abstract-serializer.ts +13 -32
  558. package/src/langium/service-registry.ts +41 -2
  559. package/src/langium/shared-services.ts +27 -6
  560. package/src/langium/transfer/transfer-encoder.ts +104 -37
  561. package/src/langium/trivia/comment-preserver.ts +1100 -0
  562. package/src/langium/trivia/document-ending-preserver.ts +55 -0
  563. package/src/langium/trivia/index.ts +14 -0
  564. package/src/langium/trivia/trivia-contribution.ts +39 -0
  565. package/src/langium/trivia/trivia-preserver.ts +54 -0
  566. package/src/langium/trivia/trivia-service.ts +99 -0
  567. package/src/langium/update-rewrite/update-rewrite.ts +1 -1
  568. package/src/langium/validation/document-validator.ts +537 -11
  569. package/src/langium/validation/validation-contribution-collector.ts +10 -1
  570. package/src/langium/workspace/document-uri-policy.ts +18 -14
  571. package/src/langium/workspace/file-not-found.ts +35 -0
  572. package/src/langium/workspace/file-system-provider.ts +205 -17
  573. package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
  574. package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
  575. package/src/langium/workspace/hydranium-workspace-manager.ts +154 -14
  576. package/src/langium/workspace/in-memory-file-system-provider.ts +48 -17
  577. package/src/langium/workspace/index.ts +1 -0
  578. package/src/langium/workspace/initialize-workspace.ts +43 -5
  579. package/src/langium/workspace/langium-documents.ts +124 -33
  580. package/src/langium/workspace/persistent-file-system-provider.ts +1 -8
  581. package/src/{documents → langium/workspace}/self-save-registry.ts +54 -15
  582. package/src/langium/workspace/virtual-document.ts +96 -19
  583. package/src/langium/workspace/write-lock-scope.ts +24 -11
  584. package/src/locale/index.ts +10 -0
  585. package/src/locale/server-locale.ts +86 -0
  586. package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
  587. package/src/lsp/connection-features.ts +67 -0
  588. package/src/lsp/diagnostics-connection.ts +56 -0
  589. package/src/lsp/hydranium-document-update-handler.ts +187 -108
  590. package/src/lsp/index.ts +3 -1
  591. package/src/lsp/lsp-latency.ts +62 -0
  592. package/src/lsp/semantic-token-provider.ts +74 -7
  593. package/src/lsp/shared-module.ts +4 -8
  594. package/src/lsp/start-language-server.ts +13 -7
  595. package/src/messages/carriers.ts +78 -0
  596. package/src/messages/index.ts +36 -0
  597. package/src/messages/renderer.ts +212 -0
  598. package/src/node/heap-ceiling.ts +108 -0
  599. package/src/node/index.ts +1 -1
  600. package/src/node/latency-from-env.ts +1 -1
  601. package/src/node/measure-memory.ts +1 -0
  602. package/src/node/node-file-system-provider.ts +124 -53
  603. package/src/node/profile-capture.ts +9 -3
  604. package/src/node/profiling-run.ts +30 -8
  605. package/src/node/rename-over-open-readers.ts +78 -0
  606. package/src/node/socket-launcher.ts +24 -8
  607. package/src/node/stdio-launcher.ts +8 -7
  608. package/src/testing/fake-document.ts +24 -5
  609. package/src/testing/index.ts +2 -1
  610. package/src/testing/langium-test-helpers.ts +1 -0
  611. package/src/testing/make-noop-shared-services.ts +50 -2
  612. package/src/testing/make-test-services.ts +125 -31
  613. package/src/testing/make-test-tracer.ts +26 -0
  614. package/src/testing/node/index.ts +1 -0
  615. package/src/testing/node/lsp-harness.ts +2 -0
  616. package/src/testing/node/lsp-server-connection.ts +66 -12
  617. package/src/testing/node/scratch-workspace.ts +10 -5
  618. package/src/testing/node/spawned-server.ts +36 -2
  619. package/src/testing/node/unhandled-rejections.ts +31 -0
  620. package/src/testing/parse-semantic-root.ts +1 -1
  621. package/src/testing/playwright/flaky-network-proxy.ts +240 -0
  622. package/src/testing/playwright/index.ts +1 -0
  623. package/src/testing/playwright/server-log-capture.ts +45 -11
  624. package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
  625. package/src/testing/run-update-pipeline.ts +4 -4
  626. package/src/testing/stub-ast-document-manager.ts +36 -138
  627. package/src/testing/stub-document-builder.ts +102 -18
  628. package/src/testing/stub-hydranium-text-documents.ts +165 -27
  629. package/src/testing/stub-langium-documents.ts +3 -2
  630. package/src/testing/stub-model-service.ts +9 -8
  631. package/src/testing/stub-self-save-registry.ts +1 -1
  632. package/src/testing/stub-service-registry.ts +1 -1
  633. package/src/testing/stub-writable-file-system.ts +1 -1
  634. package/src/util/connection-liveness.ts +37 -14
  635. package/src/util/environment.ts +9 -1
  636. package/lib/documents/language-client-text-shadow.d.ts +0 -101
  637. package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
  638. package/lib/documents/language-client-text-shadow.js +0 -156
  639. package/lib/documents/language-client-text-shadow.js.map +0 -1
  640. package/lib/documents/self-save-registry.d.ts.map +0 -1
  641. package/lib/documents/self-save-registry.js.map +0 -1
  642. package/lib/lsp/instrument-connection.d.ts +0 -36
  643. package/lib/lsp/instrument-connection.d.ts.map +0 -1
  644. package/lib/lsp/instrument-connection.js +0 -62
  645. package/lib/lsp/instrument-connection.js.map +0 -1
  646. package/lib/node/process-memory.d.ts +0 -66
  647. package/lib/node/process-memory.d.ts.map +0 -1
  648. package/lib/node/process-memory.js +0 -252
  649. package/lib/node/process-memory.js.map +0 -1
  650. package/src/documents/language-client-text-shadow.ts +0 -175
  651. package/src/lsp/instrument-connection.ts +0 -66
  652. package/src/node/process-memory.ts +0 -299
@@ -9,25 +9,14 @@
9
9
  import { Debouncer, type Logger, ObservableValue, type MaybeObservableValue } from '@hydranium/protocol';
10
10
  import { URI } from '@hydranium/langium';
11
11
  import { DefaultDocumentUpdateHandler } from '@hydranium/langium/lsp';
12
- import { type HydraniumDocumentBuilder } from '../langium/document-builder/document-builder.js';
12
+ import { HYDRANIUM_BUILD_REASONS, type HydraniumDocumentBuilder } from '../langium/document-builder/document-builder.js';
13
13
  import { type ServerSharedServices } from '../langium/module.js';
14
- import { type SelfSaveRegistry } from '../documents/self-save-registry.js';
15
- import { type WritableFileSystemProvider } from '../documents/ast-document-manager.js';
14
+ import { type SelfSaveRegistry } from '../langium/workspace/self-save-registry.js';
15
+ import { type WritableFileSystemProvider } from '../langium/workspace/file-system-provider.js';
16
16
  import { type HydraniumTextDocuments } from '../documents/hydranium-text-documents.js';
17
- import { type DidChangeWatchedFilesParams, type TextDocumentChangeEvent } from 'vscode-languageserver';
17
+ import { type DidChangeWatchedFilesParams, type TextDocumentChangeEvent, type TextDocumentWillSaveEvent, type TextEdit } from 'vscode-languageserver';
18
18
  import { type TextDocument } from 'vscode-languageserver-textdocument';
19
- /**
20
- * Default LSP-event reasons stamped by {@link HydraniumDocumentUpdateHandler}
21
- * onto the next `documentBuilder.update` call via `markNextReason`. Exposed
22
- * so adopters subclassing the handler can layer additional reasons or rename
23
- * existing ones without losing the canonical names the framework emits.
24
- */
25
- export declare const HYDRANIUM_BUILD_REASONS: Readonly<{
26
- readonly didOpen: "didOpen";
27
- readonly didChangeContent: "didChangeContent";
28
- readonly didChangeWatchedFiles: "didChangeWatchedFiles";
29
- readonly didClose: "didClose";
30
- }>;
19
+ export { HYDRANIUM_BUILD_REASONS };
31
20
  /**
32
21
  * Construction options for {@link HydraniumDocumentUpdateHandler}.
33
22
  */
@@ -52,6 +41,17 @@ export interface HydraniumDocumentUpdateHandlerOptions {
52
41
  * load tests).
53
42
  */
54
43
  readonly bypassNonLanguageClientChanges?: boolean;
44
+ /**
45
+ * Longest an editor's save waits on the server, in milliseconds, at each of
46
+ * its two steps: the `willSaveWaitUntil` answer waits for the server's disk
47
+ * writes of the document already queued, and server writes queued after the
48
+ * answer wait for the editor's `didSave`. Either wait that runs out is
49
+ * logged, and the editor's write and the server's can then land in either
50
+ * order. Default `1000`: VS Code gives up on an answer after about 1.5 s,
51
+ * and switches the listener off for the session once four answers, over
52
+ * all documents, timed out or failed.
53
+ */
54
+ readonly willSaveGateMs?: number;
55
55
  }
56
56
  /**
57
57
  * Framework `DocumentUpdateHandler` adding these behaviours over Langium's
@@ -66,30 +66,37 @@ export interface HydraniumDocumentUpdateHandlerOptions {
66
66
  * changes and watched-file changes bypass the debounce (their
67
67
  * producers are already coalesced).
68
68
  * 3. **Build-reason stamping** — the LSP event overrides
69
- * (`didOpenDocument`, `didChangeContent`, `didChangeWatchedFiles`,
70
- * `didCloseDocument`) populate {@link nextReason} with a canonical
71
- * reason string. {@link fireDocumentUpdate} captures the reason;
72
- * {@link dispatch} stages it on the builder via
73
- * {@link HydraniumDocumentBuilder.markNextReason}, so a subclass that
74
- * formats build logs can tag its line with the event that caused the
75
- * build without per-adopter wiring to capture it.
76
- * 4. **Last-client-close rebuild trigger** ({@link didCloseDocument}) —
77
- * when the final client closes a document, dispatch a build so the
78
- * LangiumDocument's `textDocument` is refreshed (from disk for `file:`
79
- * URIs, or removed from the index for ephemeral URIs). Langium's
80
- * default handler does not implement `didCloseDocument`, so the
81
- * in-memory text of the last writer would otherwise persist.
69
+ * (`didOpenDocument`, `didChangeContent`, `didChangeWatchedFiles`)
70
+ * populate {@link nextReason} with a canonical reason string.
71
+ * {@link fireDocumentUpdate} captures the reason; {@link dispatch} hands
72
+ * it to {@link HydraniumDocumentBuilder.scheduleUpdate}, which stages it
73
+ * through {@link HydraniumDocumentBuilder.markNextReason} when the build
74
+ * runs, so a subclass that formats build logs can tag its line with the
75
+ * event that caused the build without per-adopter wiring to capture it.
76
+ * 4. **Editor save gate** ({@link willSaveDocumentWaitUntil}) — the editor
77
+ * writes the file itself, so the server's disk writes of that document
78
+ * are ordered around it: the editor's save waits for the ones already
79
+ * queued, and the ones queued during its save wait for its `didSave`.
80
+ * Both waits are capped by
81
+ * {@link HydraniumDocumentUpdateHandlerOptions.willSaveGateMs}.
82
+ *
83
+ * What the build keeps after a document's last close is not dispatched here:
84
+ * the store hands the released document to the `DocumentReleaseHandler` for
85
+ * every head, the LSP head included, so a `didCloseDocument` added in a
86
+ * subclass would build the document twice. A change still debounced for the
87
+ * document is dropped when the store releases it: the release handler rebuilds
88
+ * the document from the file system provider or removes it.
82
89
  *
83
90
  * Adopters with their own handler subclass should extend this class
84
91
  * (not Langium's `DefaultDocumentUpdateHandler`) so all of them are
85
92
  * preserved. The {@link dispatch} hook is the canonical override
86
- * point for adopters that need to stamp additional per-build metadata
87
- * inside the workspace-lock callback.
93
+ * point for adopters that need to stamp additional per-build metadata.
88
94
  */
89
95
  export declare class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler {
96
+ protected readonly services: ServerSharedServices;
90
97
  /**
91
98
  * Narrow Langium's `DefaultDocumentUpdateHandler.documentBuilder` typing to
92
- * the framework subclass: `markNextReason` is the only method this handler
99
+ * the framework subclass: `scheduleUpdate` is the only method this handler
93
100
  * reaches for beyond the Langium interface.
94
101
  */
95
102
  protected readonly documentBuilder: HydraniumDocumentBuilder;
@@ -117,52 +124,53 @@ export declare class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdat
117
124
  protected nextReason?: string;
118
125
  /**
119
126
  * Build-reason captured at `fireDocumentUpdate` time, drained by
120
- * {@link dispatch} into `markNextReason`. Survives across debounced
121
- * batches (`?? pendingReason` in `fireDocumentUpdate` retains the
122
- * first reason in a coalesced burst).
127
+ * {@link dispatch} into the scheduled build. Survives across debounced
128
+ * batches: `fireDocumentUpdate` replaces it with each event's reason, so a
129
+ * coalesced burst carries its latest.
123
130
  */
124
131
  protected pendingReason?: string;
132
+ protected readonly willSaveGateMs: number;
133
+ /**
134
+ * Per document URI, the release of the hold an editor's save in progress
135
+ * keeps on the document's disk queue. A second save of the document
136
+ * releases the first: its hold would otherwise keep the second's answer
137
+ * waiting until the cap. The key is the document, not the save, so for a
138
+ * client that sends its next `willSaveWaitUntil` before the previous
139
+ * `didSave`, that late `didSave` releases the next save's hold.
140
+ */
141
+ protected readonly editorSaves: Map<string, () => void>;
125
142
  constructor(services: ServerSharedServices, options?: HydraniumDocumentUpdateHandlerOptions);
126
143
  didOpenDocument(_change: TextDocumentChangeEvent<TextDocument>): void;
127
144
  didChangeContent(change: TextDocumentChangeEvent<TextDocument>): void;
145
+ didChangeWatchedFiles(params: DidChangeWatchedFilesParams): void;
128
146
  /**
129
- * Last-client close is the missing rebuild trigger in Langium's
130
- * `DefaultDocumentUpdateHandler`: `documents.onDidClose` fires on every
131
- * per-client close, but the default handler ignores the event entirely.
132
- * For multi-client servers this leaves the LangiumDocument carrying the
133
- * unsaved in-memory `textDocument` of the last writer until something
134
- * else triggers a rebuild — integrity rules walking `langiumDocuments.all`
135
- * then see stale text long after the user discarded their edits.
136
- *
137
- * We funnel the last-client transition through the same dispatch path
138
- * the other LSP events use, so the rebuild gets debouncing, workspace
139
- * locking, build-reason stamping, and `markNextReason` for free. The
140
- * scheme split governs the `DocumentBuilder.update` shape:
147
+ * Answer an editor's `willSaveWaitUntil` with no edits once the server's
148
+ * disk writes of the document already queued have landed, or after
149
+ * {@link willSaveGateMs}, whichever is first. From the moment the queue
150
+ * reaches this save, disk tasks of the document queued behind it wait for
151
+ * the editor's `didSave`, reported through
152
+ * `HydraniumTextDocuments.onDidSaveInLanguageClient`, or for
153
+ * {@link willSaveGateMs} more.
141
154
  *
142
- * - **`file:` URI** → `update([uri], [])`. Routes through
143
- * `LangiumDocuments.invalidateDocument` (doc stays in the trie) and
144
- * `LangiumDocumentFactory.update`, which consults the LSP-tracked
145
- * open-documents map first. That map is cleared LATER in the same
146
- * synchronous `notifyDidCloseTextDocument` call that fires this event,
147
- * and {@link dispatch} defers the build behind `workspaceManager.ready`
148
- * — so by the time the factory looks, the URI is gone: it falls back to
149
- * `FileSystemProvider.readFile` and the doc rebuilds from disk,
150
- * Langium's canonical close-without-save semantic. A dispatch made
151
- * synchronously here would still see the open document and re-read the
152
- * in-memory text instead.
153
- * - **non-`file:` URI** (`builtin:`, `untitled:`) → no dispatch.
154
- * Adopter-loaded schemes — documents pulled in via
155
- * `loadAdditionalDocuments` — need to stay in the workspace index;
156
- * dropping them on close would break every cross-reference that
157
- * targets them. The framework cannot enumerate adopter schemes, so the
158
- * safe default is "leave alone unless it's a file." Adopters that need
159
- * ephemeral-URI cleanup handle it explicitly.
160
- *
161
- * Per-client closes (where other clients still hold the URI) are
162
- * suppressed via {@link HydraniumTextDocuments.isOpenInAnyClient}.
155
+ * The hold is a disk task that waits only for that signal or its timer:
156
+ * waiting on a build, a save or anything else queued for the document would
157
+ * wedge its queue. Resolves in every case, since a failed request counts
158
+ * against the listener in VS Code; Langium drops the request's cancellation,
159
+ * so an abandoned request still runs to the cap. A hold that runs out is
160
+ * logged at debug only: an editor skips `didSave` for a save it cancels or
161
+ * that changed nothing.
163
162
  */
164
- didCloseDocument(change: TextDocumentChangeEvent<TextDocument>): void;
165
- didChangeWatchedFiles(params: DidChangeWatchedFilesParams): void;
163
+ willSaveDocumentWaitUntil(event: TextDocumentWillSaveEvent<TextDocument>): Promise<TextEdit[]>;
164
+ /**
165
+ * Present so that Langium advertises `save` and editors send `didSave`;
166
+ * without it every hold of {@link willSaveDocumentWaitUntil} waits out its
167
+ * cap. The hold is released on
168
+ * `HydraniumTextDocuments.onDidSaveInLanguageClient` instead: it fires as
169
+ * soon as the editor reports the save, while `onDidSave`, and so this
170
+ * method, follows only once the file has been read back, and not at all
171
+ * when the file does not hold the store's text.
172
+ */
173
+ didSaveDocument(_event: TextDocumentChangeEvent<TextDocument>): void;
166
174
  /**
167
175
  * Drop watched-file changes whose path + mtime match a recent self-save
168
176
  * record. Deletions always pass (no mtime); stat failures pass (the
@@ -177,8 +185,7 @@ export declare class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdat
177
185
  * flush immediately (`immediateFlush` or `debounceMs <= 0`) or restart
178
186
  * the trailing-edge timer. Subclasses that need to stamp per-build
179
187
  * metadata can override and inspect the merged sets — but the canonical
180
- * override point for the workspace-lock callback is {@link dispatch},
181
- * not this method.
188
+ * override point for the build is {@link dispatch}, not this method.
182
189
  */
183
190
  protected fireDocumentUpdate(changed: URI[], deleted: URI[]): void;
184
191
  /**
@@ -189,15 +196,19 @@ export declare class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdat
189
196
  */
190
197
  flushPending(): void;
191
198
  /**
192
- * Workspace-lock + `documentBuilder.update` call for the merged sets.
193
- * Mirrors Langium's `super.fireDocumentUpdate` body plus
194
- * `markNextReason(pendingReason)` inside the write-lock callback, so the
195
- * build the lock is about to run carries the LSP event that triggered it.
196
- * Adopters override to stamp additional per-build metadata — the canonical
197
- * pattern is to read the reason via `this.pendingReason`, call
198
- * `super.dispatch(...)` or replicate the
199
- * `workspaceManager.ready -> workspaceLock.write` block, and add
200
- * adopter-specific behaviour inside the write callback.
199
+ * Build the merged sets once the workspace is ready, through
200
+ * {@link HydraniumDocumentBuilder.scheduleUpdate} with the pending reason,
201
+ * so the build carries the LSP event that triggered it. A session's write
202
+ * fires the store's change event before the session rebuilds the document
203
+ * itself, and the scheduled build is what the two share.
204
+ *
205
+ * Adopters override to stamp additional per-build metadata: read the reason
206
+ * via `this.pendingReason` and call `super.dispatch(...)`; the build may
207
+ * be shared with other requests, so metadata stamped for it describes
208
+ * theirs too. An override that needs code inside the write action takes
209
+ * `workspaceLock.write` itself, as Langium's `fireDocumentUpdate` does, and
210
+ * stages the reason through `markNextReason` there; its build then cancels
211
+ * a scheduled one it coincides with rather than sharing it.
201
212
  */
202
213
  protected dispatch(changed: URI[], deleted: URI[]): void;
203
214
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hydranium-document-update-handler.d.ts","sourceRoot":"","sources":["../../src/lsp/hydranium-document-update-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hydranium-document-update-handler.d.ts","sourceRoot":"","sources":["../../src/lsp/hydranium-document-update-handler.ts"],"names":[],"mappings":"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"}
@@ -6,23 +6,14 @@
6
6
  *
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
- import { Debouncer, ObservableValue } from '@hydranium/protocol';
9
+ import { Debouncer, Deferred, ObservableValue, TIMED_OUT } from '@hydranium/protocol';
10
10
  import { URI, UriUtils } from '@hydranium/langium';
11
11
  import { DefaultDocumentUpdateHandler } from '@hydranium/langium/lsp';
12
+ import { HYDRANIUM_BUILD_REASONS } from '../langium/document-builder/document-builder.js';
12
13
  import { LANGUAGE_CLIENT_ID } from '../documents/client-ids.js';
14
+ import { isConnectionGoneError } from '../util/connection-liveness.js';
13
15
  import { FileChangeType } from 'vscode-languageserver';
14
- /**
15
- * Default LSP-event reasons stamped by {@link HydraniumDocumentUpdateHandler}
16
- * onto the next `documentBuilder.update` call via `markNextReason`. Exposed
17
- * so adopters subclassing the handler can layer additional reasons or rename
18
- * existing ones without losing the canonical names the framework emits.
19
- */
20
- export const HYDRANIUM_BUILD_REASONS = Object.freeze({
21
- didOpen: 'didOpen',
22
- didChangeContent: 'didChangeContent',
23
- didChangeWatchedFiles: 'didChangeWatchedFiles',
24
- didClose: 'didClose'
25
- });
16
+ export { HYDRANIUM_BUILD_REASONS };
26
17
  /**
27
18
  * Framework `DocumentUpdateHandler` adding these behaviours over Langium's
28
19
  * default:
@@ -36,27 +27,34 @@ export const HYDRANIUM_BUILD_REASONS = Object.freeze({
36
27
  * changes and watched-file changes bypass the debounce (their
37
28
  * producers are already coalesced).
38
29
  * 3. **Build-reason stamping** — the LSP event overrides
39
- * (`didOpenDocument`, `didChangeContent`, `didChangeWatchedFiles`,
40
- * `didCloseDocument`) populate {@link nextReason} with a canonical
41
- * reason string. {@link fireDocumentUpdate} captures the reason;
42
- * {@link dispatch} stages it on the builder via
43
- * {@link HydraniumDocumentBuilder.markNextReason}, so a subclass that
44
- * formats build logs can tag its line with the event that caused the
45
- * build without per-adopter wiring to capture it.
46
- * 4. **Last-client-close rebuild trigger** ({@link didCloseDocument}) —
47
- * when the final client closes a document, dispatch a build so the
48
- * LangiumDocument's `textDocument` is refreshed (from disk for `file:`
49
- * URIs, or removed from the index for ephemeral URIs). Langium's
50
- * default handler does not implement `didCloseDocument`, so the
51
- * in-memory text of the last writer would otherwise persist.
30
+ * (`didOpenDocument`, `didChangeContent`, `didChangeWatchedFiles`)
31
+ * populate {@link nextReason} with a canonical reason string.
32
+ * {@link fireDocumentUpdate} captures the reason; {@link dispatch} hands
33
+ * it to {@link HydraniumDocumentBuilder.scheduleUpdate}, which stages it
34
+ * through {@link HydraniumDocumentBuilder.markNextReason} when the build
35
+ * runs, so a subclass that formats build logs can tag its line with the
36
+ * event that caused the build without per-adopter wiring to capture it.
37
+ * 4. **Editor save gate** ({@link willSaveDocumentWaitUntil}) — the editor
38
+ * writes the file itself, so the server's disk writes of that document
39
+ * are ordered around it: the editor's save waits for the ones already
40
+ * queued, and the ones queued during its save wait for its `didSave`.
41
+ * Both waits are capped by
42
+ * {@link HydraniumDocumentUpdateHandlerOptions.willSaveGateMs}.
43
+ *
44
+ * What the build keeps after a document's last close is not dispatched here:
45
+ * the store hands the released document to the `DocumentReleaseHandler` for
46
+ * every head, the LSP head included, so a `didCloseDocument` added in a
47
+ * subclass would build the document twice. A change still debounced for the
48
+ * document is dropped when the store releases it: the release handler rebuilds
49
+ * the document from the file system provider or removes it.
52
50
  *
53
51
  * Adopters with their own handler subclass should extend this class
54
52
  * (not Langium's `DefaultDocumentUpdateHandler`) so all of them are
55
53
  * preserved. The {@link dispatch} hook is the canonical override
56
- * point for adopters that need to stamp additional per-build metadata
57
- * inside the workspace-lock callback.
54
+ * point for adopters that need to stamp additional per-build metadata.
58
55
  */
59
56
  export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler {
57
+ services;
60
58
  logger;
61
59
  selfSaveRegistry;
62
60
  fileSystemProvider;
@@ -81,13 +79,24 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
81
79
  nextReason;
82
80
  /**
83
81
  * Build-reason captured at `fireDocumentUpdate` time, drained by
84
- * {@link dispatch} into `markNextReason`. Survives across debounced
85
- * batches (`?? pendingReason` in `fireDocumentUpdate` retains the
86
- * first reason in a coalesced burst).
82
+ * {@link dispatch} into the scheduled build. Survives across debounced
83
+ * batches: `fireDocumentUpdate` replaces it with each event's reason, so a
84
+ * coalesced burst carries its latest.
87
85
  */
88
86
  pendingReason;
87
+ willSaveGateMs;
88
+ /**
89
+ * Per document URI, the release of the hold an editor's save in progress
90
+ * keeps on the document's disk queue. A second save of the document
91
+ * releases the first: its hold would otherwise keep the second's answer
92
+ * waiting until the cap. The key is the document, not the save, so for a
93
+ * client that sends its next `willSaveWaitUntil` before the previous
94
+ * `didSave`, that late `didSave` releases the next save's hold.
95
+ */
96
+ editorSaves = new Map();
89
97
  constructor(services, options = {}) {
90
98
  super(services);
99
+ this.services = services;
91
100
  this.logger = services.Logger;
92
101
  this.selfSaveRegistry = services.workspace.SelfSaveRegistry;
93
102
  this.fileSystemProvider = services.workspace.FileSystemProvider;
@@ -95,6 +104,19 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
95
104
  this.debounce = ObservableValue.from(options.debounceMs ?? 0);
96
105
  this.flushDebouncer = new Debouncer(services.Clock, () => this.flushPending(), { delayMs: this.debounce });
97
106
  this.bypassNonLanguageClientChanges = options.bypassNonLanguageClientChanges ?? true;
107
+ this.willSaveGateMs = options.willSaveGateMs ?? 1000;
108
+ this.textDocuments.onDidSaveInLanguageClient(event => this.editorSaves.get(event.uri)?.());
109
+ services.workspace.VersionSyncService.registerDeferredBuilds(uri => this.pendingChanged.has(uri.toString()) || this.pendingDeleted.has(uri.toString()));
110
+ // A change still debounced for a document the store has released would
111
+ // build it once more after the release handler's build: from the
112
+ // provider again, or, for a document the release removed, by reading a
113
+ // file that is not there.
114
+ this.textDocuments.onDidReleaseDocument(event => {
115
+ this.pendingChanged.delete(URI.parse(event.uri).toString());
116
+ if (this.pendingChanged.size === 0 && this.pendingDeleted.size === 0) {
117
+ this.pendingReason = undefined;
118
+ }
119
+ });
98
120
  }
99
121
  didOpenDocument(_change) {
100
122
  // Langium also fires `didChangeContent` on open, which is what triggers
@@ -116,60 +138,21 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
116
138
  }
117
139
  super.didChangeContent(change);
118
140
  }
119
- /**
120
- * Last-client close is the missing rebuild trigger in Langium's
121
- * `DefaultDocumentUpdateHandler`: `documents.onDidClose` fires on every
122
- * per-client close, but the default handler ignores the event entirely.
123
- * For multi-client servers this leaves the LangiumDocument carrying the
124
- * unsaved in-memory `textDocument` of the last writer until something
125
- * else triggers a rebuild — integrity rules walking `langiumDocuments.all`
126
- * then see stale text long after the user discarded their edits.
127
- *
128
- * We funnel the last-client transition through the same dispatch path
129
- * the other LSP events use, so the rebuild gets debouncing, workspace
130
- * locking, build-reason stamping, and `markNextReason` for free. The
131
- * scheme split governs the `DocumentBuilder.update` shape:
132
- *
133
- * - **`file:` URI** → `update([uri], [])`. Routes through
134
- * `LangiumDocuments.invalidateDocument` (doc stays in the trie) and
135
- * `LangiumDocumentFactory.update`, which consults the LSP-tracked
136
- * open-documents map first. That map is cleared LATER in the same
137
- * synchronous `notifyDidCloseTextDocument` call that fires this event,
138
- * and {@link dispatch} defers the build behind `workspaceManager.ready`
139
- * — so by the time the factory looks, the URI is gone: it falls back to
140
- * `FileSystemProvider.readFile` and the doc rebuilds from disk,
141
- * Langium's canonical close-without-save semantic. A dispatch made
142
- * synchronously here would still see the open document and re-read the
143
- * in-memory text instead.
144
- * - **non-`file:` URI** (`builtin:`, `untitled:`) → no dispatch.
145
- * Adopter-loaded schemes — documents pulled in via
146
- * `loadAdditionalDocuments` — need to stay in the workspace index;
147
- * dropping them on close would break every cross-reference that
148
- * targets them. The framework cannot enumerate adopter schemes, so the
149
- * safe default is "leave alone unless it's a file." Adopters that need
150
- * ephemeral-URI cleanup handle it explicitly.
151
- *
152
- * Per-client closes (where other clients still hold the URI) are
153
- * suppressed via {@link HydraniumTextDocuments.isOpenInAnyClient}.
154
- */
155
- didCloseDocument(change) {
156
- if (this.textDocuments.isOpenInAnyClient(change.document.uri)) {
157
- return;
158
- }
159
- const uri = URI.parse(change.document.uri);
160
- if (uri.scheme !== 'file') {
161
- return;
162
- }
163
- this.nextReason = HYDRANIUM_BUILD_REASONS.didClose;
164
- this.immediateFlush = true;
165
- this.fireDocumentUpdate([uri], []);
166
- }
167
141
  didChangeWatchedFiles(params) {
168
142
  void this.filterSelfSaves(params)
169
143
  .then(filtered => {
170
144
  if (filtered.changes.length === 0) {
171
145
  return;
172
146
  }
147
+ // Only an open document keeps the file's text as its disk
148
+ // baseline; the store ignores the rest. The self-save filter has
149
+ // dropped the server's own writes, which set the baseline when
150
+ // they wrote.
151
+ for (const change of filtered.changes) {
152
+ this.textDocuments
153
+ .reloadDiskBaseline(change.uri)
154
+ .catch((err) => this.logger.error(`Disk baseline not reloaded for ${change.uri}. ${String(err)}`));
155
+ }
173
156
  // External file-system changes are authoritative — overwrite any
174
157
  // pending reason (typically empty here; could be `didChangeContent`
175
158
  // if a watcher event raced an in-flight Monaco edit, in which case
@@ -190,6 +173,70 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
190
173
  this.logger.error(`Watched-file update dropped for ${uris}. ${detail}`);
191
174
  });
192
175
  }
176
+ /**
177
+ * Answer an editor's `willSaveWaitUntil` with no edits once the server's
178
+ * disk writes of the document already queued have landed, or after
179
+ * {@link willSaveGateMs}, whichever is first. From the moment the queue
180
+ * reaches this save, disk tasks of the document queued behind it wait for
181
+ * the editor's `didSave`, reported through
182
+ * `HydraniumTextDocuments.onDidSaveInLanguageClient`, or for
183
+ * {@link willSaveGateMs} more.
184
+ *
185
+ * The hold is a disk task that waits only for that signal or its timer:
186
+ * waiting on a build, a save or anything else queued for the document would
187
+ * wedge its queue. Resolves in every case, since a failed request counts
188
+ * against the listener in VS Code; Langium drops the request's cancellation,
189
+ * so an abandoned request still runs to the cap. A hold that runs out is
190
+ * logged at debug only: an editor skips `didSave` for a save it cancels or
191
+ * that changed nothing.
192
+ */
193
+ willSaveDocumentWaitUntil(event) {
194
+ const uri = event.document.uri;
195
+ this.editorSaves.get(uri)?.();
196
+ const hold = new Deferred();
197
+ const release = () => {
198
+ if (this.editorSaves.get(uri) === release) {
199
+ this.editorSaves.delete(uri);
200
+ }
201
+ hold.resolve();
202
+ };
203
+ this.editorSaves.set(uri, release);
204
+ return new Promise(resolve => {
205
+ const clock = this.services.Clock;
206
+ const cap = clock.setTimer(() => {
207
+ this.logger.warn(`willSaveWaitUntil for ${uri} answered after ${this.willSaveGateMs} ms with server writes of it still queued; the editor's save may race them.`);
208
+ resolve([]);
209
+ }, this.willSaveGateMs);
210
+ try {
211
+ void this.services.workspace.FileSystemTaskQueue.enqueue(uri, async () => {
212
+ cap.dispose();
213
+ resolve([]);
214
+ if ((await clock.raceTimer(hold.promise, this.willSaveGateMs)) === TIMED_OUT) {
215
+ this.logger.debug(`No didSave for ${uri} within ${this.willSaveGateMs} ms; server writes of it no longer wait for the editor's save.`);
216
+ release();
217
+ }
218
+ });
219
+ }
220
+ catch (err) {
221
+ cap.dispose();
222
+ this.logger.error(`willSaveWaitUntil for ${uri} answered without waiting. ${err instanceof Error ? (err.stack ?? err.message) : String(err)}`);
223
+ release();
224
+ resolve([]);
225
+ }
226
+ });
227
+ }
228
+ /**
229
+ * Present so that Langium advertises `save` and editors send `didSave`;
230
+ * without it every hold of {@link willSaveDocumentWaitUntil} waits out its
231
+ * cap. The hold is released on
232
+ * `HydraniumTextDocuments.onDidSaveInLanguageClient` instead: it fires as
233
+ * soon as the editor reports the save, while `onDidSave`, and so this
234
+ * method, follows only once the file has been read back, and not at all
235
+ * when the file does not hold the store's text.
236
+ */
237
+ didSaveDocument(_event) {
238
+ // Nothing to do; see the doc comment.
239
+ }
193
240
  /**
194
241
  * Drop watched-file changes whose path + mtime match a recent self-save
195
242
  * record. Deletions always pass (no mtime); stat failures pass (the
@@ -205,7 +252,7 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
205
252
  }
206
253
  const uri = UriUtils.toUri(change.uri);
207
254
  const mtimeMs = await this.fileSystemProvider.mtimeMs?.(uri);
208
- if (mtimeMs !== undefined && this.selfSaveRegistry.matches(uri.fsPath, mtimeMs)) {
255
+ if (mtimeMs !== undefined && this.selfSaveRegistry.isRegistered(uri.fsPath, mtimeMs)) {
209
256
  return undefined;
210
257
  }
211
258
  return change;
@@ -217,15 +264,13 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
217
264
  * flush immediately (`immediateFlush` or `debounceMs <= 0`) or restart
218
265
  * the trailing-edge timer. Subclasses that need to stamp per-build
219
266
  * metadata can override and inspect the merged sets — but the canonical
220
- * override point for the workspace-lock callback is {@link dispatch},
221
- * not this method.
267
+ * override point for the build is {@link dispatch}, not this method.
222
268
  */
223
269
  fireDocumentUpdate(changed, deleted) {
224
270
  // Capture the reason set by the LSP event handler immediately before
225
- // we merge into the pending sets. `?? pendingReason` keeps the
226
- // first reason in a coalesced burst (LSP events arriving inside an
227
- // active debounce window all stamp the same `pendingReason` once,
228
- // because subsequent stamps see the field already non-undefined).
271
+ // we merge into the pending sets. Each event stamps its own reason, so
272
+ // a coalesced burst carries its latest; `?? pendingReason` keeps the
273
+ // earlier one only for a call no event stamped.
229
274
  this.pendingReason = this.nextReason ?? this.pendingReason;
230
275
  this.nextReason = undefined;
231
276
  for (const uri of changed) {
@@ -261,25 +306,34 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
261
306
  this.dispatch(changed, deleted);
262
307
  }
263
308
  /**
264
- * Workspace-lock + `documentBuilder.update` call for the merged sets.
265
- * Mirrors Langium's `super.fireDocumentUpdate` body plus
266
- * `markNextReason(pendingReason)` inside the write-lock callback, so the
267
- * build the lock is about to run carries the LSP event that triggered it.
268
- * Adopters override to stamp additional per-build metadata — the canonical
269
- * pattern is to read the reason via `this.pendingReason`, call
270
- * `super.dispatch(...)` or replicate the
271
- * `workspaceManager.ready -> workspaceLock.write` block, and add
272
- * adopter-specific behaviour inside the write callback.
309
+ * Build the merged sets once the workspace is ready, through
310
+ * {@link HydraniumDocumentBuilder.scheduleUpdate} with the pending reason,
311
+ * so the build carries the LSP event that triggered it. A session's write
312
+ * fires the store's change event before the session rebuilds the document
313
+ * itself, and the scheduled build is what the two share.
314
+ *
315
+ * Adopters override to stamp additional per-build metadata: read the reason
316
+ * via `this.pendingReason` and call `super.dispatch(...)`; the build may
317
+ * be shared with other requests, so metadata stamped for it describes
318
+ * theirs too. An override that needs code inside the write action takes
319
+ * `workspaceLock.write` itself, as Langium's `fireDocumentUpdate` does, and
320
+ * stages the reason through `markNextReason` there; its build then cancels
321
+ * a scheduled one it coincides with rather than sharing it.
273
322
  */
274
323
  dispatch(changed, deleted) {
275
324
  const reason = this.pendingReason;
276
325
  this.pendingReason = undefined;
277
326
  this.workspaceManager.ready
278
- .then(() => this.workspaceLock.write(token => {
279
- this.documentBuilder.markNextReason(reason);
280
- return this.documentBuilder.update(changed, deleted, token);
281
- }))
327
+ .then(() => this.documentBuilder.scheduleUpdate(changed, deleted, reason))
282
328
  .catch(err => {
329
+ // A deferred rebuild can finish after the LSP peer has gone away.
330
+ // Unless the head was started through `startLanguageServer`, whose
331
+ // guard absorbs it, the diagnostics publish then fails this build:
332
+ // a routine teardown race, not a failed workspace update. Keep
333
+ // genuine update failures visible.
334
+ if (isConnectionGoneError(err)) {
335
+ return;
336
+ }
283
337
  const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
284
338
  this.logger.error(`Workspace initialization failed. Could not perform document update. ${detail}`);
285
339
  });