@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
@@ -8,7 +8,15 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  export * from './client-ids.js';
11
- export * from './language-client-text-shadow.js';
11
+ export * from './client-session-errors.js';
12
+ export * from './client-session-registry.js';
13
+ export * from './language-client-shadow.js';
12
14
  export * from './hydranium-text-documents.js';
15
+ export * from './model-ledger.js';
16
+ export * from './text-ledger.js';
17
+ export * from './dirty-state-tracker.js';
18
+ export * from './document-release-handler.js';
19
+ export * from './document-release-scheduler.js';
20
+ export * from './version-sync-service.js';
13
21
  export * from './ast-document-manager.js';
14
- export * from './self-save-registry.js';
22
+ export * from './file-system-task-queue.js';
@@ -0,0 +1,451 @@
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
+ import { type CanonicalUri, type LanguageClientUri, textHash, type Tracer } from '@hydranium/protocol';
11
+ import { diffLines } from 'diff';
12
+ import { Range, type TextDocumentsConfiguration, type TextEdit, uinteger } from 'vscode-languageserver';
13
+ import { TextDocument, type TextDocumentContentChangeEvent } from 'vscode-languageserver-textdocument';
14
+
15
+ /**
16
+ * The language client's open of a document under one URI, from its didOpen to
17
+ * its didClose. Each URI is its own editor buffer with its own version counter,
18
+ * so a file reached through a symlink and its real path has one of these each.
19
+ */
20
+ export interface LanguageClientDocumentState {
21
+ /** The version the client last declared for this URI. */
22
+ declaredVersion: number;
23
+ /**
24
+ * The version an applied versioned push moved this URI to, ahead of its
25
+ * echo. Apart from `declaredVersion`, whose staleness guard would drop that
26
+ * echo and strand its pending push.
27
+ */
28
+ pushedVersion?: number;
29
+ }
30
+
31
+ /**
32
+ * One text pushed to the language client whose echo has not come back yet.
33
+ * Outbound pushes and inbound echoes are uncorrelated on the wire; a FIFO of
34
+ * these per URI is the explicit correlation.
35
+ */
36
+ export interface PendingLanguageClientPush {
37
+ /** {@link textHash} of the text this push moves the client to. */
38
+ readonly afterHash: string;
39
+ }
40
+
41
+ /** A push {@link LanguageClientShadow.preparePush} has queued, for the store to send and settle. */
42
+ export interface PreparedLanguageClientPush {
43
+ readonly clientUri: LanguageClientUri;
44
+ readonly edits: TextEdit[];
45
+ /**
46
+ * The client version the edits are addressed at, so the client refuses a
47
+ * push its buffer has outrun; `null` for a full replace, which lands on any
48
+ * buffer and is the caller's retry after a refusal.
49
+ */
50
+ readonly version: number | null;
51
+ /**
52
+ * Record what the client answered. Only the first call counts; a refusal of
53
+ * an addressed push is logged; an answer that arrives after the client
54
+ * reopened the URI changes nothing.
55
+ */
56
+ notifyOutcome(outcome: LanguageClientPushOutcome): void;
57
+ }
58
+
59
+ /** What the client answered a {@link PreparedLanguageClientPush}. */
60
+ export type LanguageClientPushOutcome = 'applied' | 'refused' | 'failed';
61
+
62
+ /** What an incoming language-client change is, as {@link LanguageClientShadow.acceptChange} finds it. */
63
+ export type LanguageClientChangeVerdict =
64
+ /** The client is reporting a text we pushed it. The synced document is already there. */
65
+ | { readonly kind: 'echo' }
66
+ /**
67
+ * The client's buffer holds a text we did not push it — a keystroke that
68
+ * raced a push, or an edit to a buffer the store has already been written
69
+ * past. Its ranges address that buffer, so applied to the synced text they
70
+ * splice the wrong lines; `text` is what it now holds, and is authoritative.
71
+ */
72
+ | { readonly kind: 'divergent'; readonly text: string }
73
+ /** The client's buffer is the synced text, so its ranges apply as sent. */
74
+ | { readonly kind: 'direct' };
75
+
76
+ /**
77
+ * The store's model of what the LSP language client holds for each URI it
78
+ * opened: the text, the version it declared and the version a push moved it
79
+ * to, and the pushes it has not echoed yet. The store speaks the protocol;
80
+ * this answers what an incoming change is and what an outgoing push sends.
81
+ *
82
+ * Keyed by the URI the client opened under, which differs from the store's
83
+ * canonical key when the path does not match its real path, so one document
84
+ * can have several.
85
+ *
86
+ * A push is a diff against the text the client holds rather than a full
87
+ * replace: a full-range replace on a large source makes Monaco re-tokenise the
88
+ * whole document, observed as multi-second hangs.
89
+ */
90
+ export interface LanguageClientShadow {
91
+ /**
92
+ * The client opened `key` under `clientUri` holding `text`. `firstOpen`,
93
+ * the store's first open of `key`: that text becomes the diff baseline;
94
+ * otherwise there is none, since a buffer opened from disk can lag the
95
+ * synced text, and a push of other text is a full replace. Either replaces
96
+ * what was tracked for `clientUri` before the open. A no-op when this URI
97
+ * is already open.
98
+ */
99
+ addOpen(key: CanonicalUri, clientUri: LanguageClientUri, version: number, text: string, firstOpen: boolean): void;
100
+ /** The version the client last declared for `key` under `clientUri`; `undefined` when it never opened it there. */
101
+ declaredVersion(key: CanonicalUri, clientUri: LanguageClientUri): number | undefined;
102
+ /**
103
+ * Take `version` as the client's newest for `clientUri`, and classify its
104
+ * change against `document`, the synced document. The caller has already
105
+ * dropped a stale change. After a `direct` or `divergent` verdict the caller
106
+ * commits the change and reports the synced text through
107
+ * {@link LanguageClientShadow.setClientText}: a `direct` change advances what
108
+ * the client was last heard to hold only through that call, and without it
109
+ * the next change is rebuilt against a stale text.
110
+ */
111
+ acceptChange(
112
+ key: CanonicalUri,
113
+ clientUri: LanguageClientUri,
114
+ version: number,
115
+ document: TextDocument,
116
+ changes: TextDocumentContentChangeEvent[]
117
+ ): LanguageClientChangeVerdict;
118
+ /** The client holds `text` with nothing in flight. */
119
+ setClientText(clientUri: LanguageClientUri, text: string): void;
120
+ /** The client closed `clientUri`; what it held there is forgotten. */
121
+ removeOpen(key: CanonicalUri, clientUri: LanguageClientUri): void;
122
+ /** Whether the client has `key` open: under `clientUri` when given, else under any URI. */
123
+ isOpen(key: CanonicalUri, clientUri?: LanguageClientUri): boolean;
124
+ /** Forget every URI the client holds `key` under. */
125
+ removeAllOpens(key: CanonicalUri): void;
126
+ /**
127
+ * The URIs a push of `key` goes to: each open of it, none when the client
128
+ * has not opened it. A client applies a push to a closed file by opening
129
+ * it, and an open racing its own push leaves no text to diff against.
130
+ */
131
+ pushTargets(key: CanonicalUri): LanguageClientUri[];
132
+ /**
133
+ * Diff `text` against what the client holds under `clientUri` and queue the
134
+ * push for echo correlation, which has to precede the RPC because an echo
135
+ * can arrive before its response. `undefined` when there is nothing to send,
136
+ * which includes a `clientUri` the client no longer has open: a close can
137
+ * land while the push to another of its URIs is in flight.
138
+ */
139
+ preparePush(key: CanonicalUri, clientUri: LanguageClientUri, text: string): PreparedLanguageClientPush | undefined;
140
+ /**
141
+ * Drop the diff baseline and the pushes in flight under `clientUri`; its
142
+ * next push is a full replace, or nothing when the client was last heard to
143
+ * hold that text. What the client was last heard to hold stays, and its
144
+ * changes are still rebuilt against it.
145
+ */
146
+ invalidateClientText(clientUri: LanguageClientUri): void;
147
+ }
148
+
149
+ /**
150
+ * Upper bound on the pending pushes per URI. Echoes normally return within
151
+ * milliseconds; a queue this deep means the client stopped echoing.
152
+ */
153
+ const PENDING_ECHO_CAP = 32;
154
+
155
+ /** The range every full-document replace emitted here carries. */
156
+ const FULL_RANGE = Range.create(0, 0, uinteger.MAX_VALUE, uinteger.MAX_VALUE);
157
+
158
+ /**
159
+ * Whether `edits` is the single full-document replace a push emits when it has
160
+ * no usable baseline. A full replace is position-independent and lands on any
161
+ * client buffer; a line-keyed diff lands only on the text it was diffed
162
+ * against, so only the latter needs a client-version gate.
163
+ */
164
+ export function isFullReplace(edits: readonly TextEdit[]): boolean {
165
+ if (edits.length !== 1) {
166
+ return false;
167
+ }
168
+ const { start, end } = edits[0].range;
169
+ return start.line === FULL_RANGE.start.line && start.character === FULL_RANGE.start.character && end.line === FULL_RANGE.end.line;
170
+ }
171
+
172
+ export class DefaultLanguageClientShadow<T extends TextDocument = TextDocument> implements LanguageClientShadow {
173
+ protected readonly opens = new Map<CanonicalUri, Map<LanguageClientUri, LanguageClientDocumentState>>();
174
+ /** The diff baseline: the text the client holds once every push in flight has landed. */
175
+ protected readonly baselines = new Map<LanguageClientUri, string>();
176
+ /**
177
+ * What the client was last heard to hold: the text of its open, advanced
178
+ * through every change since. Each change's ranges address the text the
179
+ * previous one left, so changes are rebuilt against this; the diff baseline
180
+ * moves ahead at a push and does not hold it. A push compares against it
181
+ * for equality only: a line-keyed diff keyed to it splices a buffer the
182
+ * client may have moved past.
183
+ */
184
+ protected readonly heardTexts = new Map<LanguageClientUri, string>();
185
+ protected readonly pending = new Map<LanguageClientUri, PendingLanguageClientPush[]>();
186
+
187
+ /**
188
+ * @param configuration the store's text-document factories, the store's own
189
+ * `create` and `update`. Probes go through them rather than `TextDocument`
190
+ * directly, so an adopter's custom text-document type applies ranges here
191
+ * as it does on the synced document; the bare `TextDocument.update` also
192
+ * refuses a document it did not create.
193
+ */
194
+ constructor(
195
+ protected readonly configuration: TextDocumentsConfiguration<T>,
196
+ protected readonly tracer: Tracer
197
+ ) {}
198
+
199
+ addOpen(key: CanonicalUri, clientUri: LanguageClientUri, version: number, text: string, firstOpen: boolean): void {
200
+ let uris = this.opens.get(key);
201
+ if (uris?.has(clientUri)) {
202
+ return;
203
+ }
204
+ if (!uris) {
205
+ uris = new Map();
206
+ this.opens.set(key, uris);
207
+ }
208
+ uris.set(clientUri, { declaredVersion: version });
209
+ // Dropped: a seed set before the open names no buffer, and a line diff
210
+ // against it splices text the client does not hold.
211
+ this.invalidateClientText(clientUri);
212
+ this.heardTexts.set(clientUri, text);
213
+ if (firstOpen) {
214
+ this.baselines.set(clientUri, text);
215
+ }
216
+ }
217
+
218
+ declaredVersion(key: CanonicalUri, clientUri: LanguageClientUri): number | undefined {
219
+ return this.opens.get(key)?.get(clientUri)?.declaredVersion;
220
+ }
221
+
222
+ acceptChange(
223
+ key: CanonicalUri,
224
+ clientUri: LanguageClientUri,
225
+ version: number,
226
+ document: TextDocument,
227
+ changes: TextDocumentContentChangeEvent[]
228
+ ): LanguageClientChangeVerdict {
229
+ const state = this.opens.get(key)?.get(clientUri);
230
+ if (state) {
231
+ state.declaredVersion = version;
232
+ }
233
+ return this.classify(clientUri, document, changes);
234
+ }
235
+
236
+ /**
237
+ * Reconstruct the client's resulting buffer against what it was last heard
238
+ * to hold, which its ranges address whatever was pushed meanwhile.
239
+ *
240
+ * The client applies pushes in order, so the first echo belongs to the
241
+ * oldest entry. Matching against every pending hash, not only the oldest,
242
+ * recognises an echo a newer push already superseded, and consumes
243
+ * everything older too. A reconstruction matching none means the client's
244
+ * buffer went somewhere we did not send it, and the queue drops.
245
+ *
246
+ * Content equality is a sound echo proof because entries live only between
247
+ * a push and its echo, and `didChange` arrives in mutation order: an undo
248
+ * back to a previously pushed text revisits a past state, while the queue
249
+ * holds only in-flight ones.
250
+ */
251
+ protected classify(
252
+ clientUri: LanguageClientUri,
253
+ document: TextDocument,
254
+ changes: TextDocumentContentChangeEvent[]
255
+ ): LanguageClientChangeVerdict {
256
+ // The synced text stands in only for a URI with nothing recorded, which
257
+ // has nothing in flight either.
258
+ const heard = this.heardTexts.get(clientUri) ?? document.getText();
259
+ const pending = this.pending.get(clientUri);
260
+ if (!pending?.length && heard === document.getText()) {
261
+ // The ranges apply to the synced text as sent, and the caller's
262
+ // setClientText records the result. Were it rebuilt here too, every
263
+ // keystroke would copy the whole text a second time and rescan its lines.
264
+ return { kind: 'direct' };
265
+ }
266
+ const probe = this.configuration.create(clientUri, document.languageId, 0, heard);
267
+ const reconstructed = this.configuration.update(probe, changes, 0).getText();
268
+ this.heardTexts.set(clientUri, reconstructed);
269
+ if (pending?.length) {
270
+ const matchIndex = pending.findIndex(push => push.afterHash === textHash(reconstructed));
271
+ if (matchIndex >= 0) {
272
+ pending.splice(0, matchIndex + 1);
273
+ return { kind: 'echo' };
274
+ }
275
+ this.pending.delete(clientUri);
276
+ }
277
+ return heard === document.getText() ? { kind: 'direct' } : { kind: 'divergent', text: reconstructed };
278
+ }
279
+
280
+ setClientText(clientUri: LanguageClientUri, text: string): void {
281
+ this.baselines.set(clientUri, text);
282
+ this.heardTexts.set(clientUri, text);
283
+ this.pending.delete(clientUri);
284
+ }
285
+
286
+ removeOpen(key: CanonicalUri, clientUri: LanguageClientUri): void {
287
+ const uris = this.opens.get(key);
288
+ if (uris?.delete(clientUri)) {
289
+ this.invalidateClientText(clientUri);
290
+ this.heardTexts.delete(clientUri);
291
+ if (uris.size === 0) {
292
+ this.opens.delete(key);
293
+ }
294
+ }
295
+ }
296
+
297
+ isOpen(key: CanonicalUri, clientUri?: LanguageClientUri): boolean {
298
+ const uris = this.opens.get(key);
299
+ return clientUri === undefined ? uris !== undefined : (uris?.has(clientUri) ?? false);
300
+ }
301
+
302
+ removeAllOpens(key: CanonicalUri): void {
303
+ for (const clientUri of this.opens.get(key)?.keys() ?? []) {
304
+ this.invalidateClientText(clientUri);
305
+ this.heardTexts.delete(clientUri);
306
+ }
307
+ this.opens.delete(key);
308
+ }
309
+
310
+ pushTargets(key: CanonicalUri): LanguageClientUri[] {
311
+ return [...(this.opens.get(key)?.keys() ?? [])];
312
+ }
313
+
314
+ preparePush(key: CanonicalUri, clientUri: LanguageClientUri, text: string): PreparedLanguageClientPush | undefined {
315
+ // Captured now: a reopen while the push is in flight replaces the state.
316
+ const state = this.opens.get(key)?.get(clientUri);
317
+ if (state === undefined) {
318
+ return undefined;
319
+ }
320
+ const edits = this.computeEdits(clientUri, text);
321
+ if (edits.length === 0) {
322
+ return undefined;
323
+ }
324
+ this.recordPendingPush(clientUri, text);
325
+ // Gating a full replace turns a stale-by-one version into a refused
326
+ // update for no safety gain, and refuses the retry after a rejection.
327
+ const version = isFullReplace(edits) ? null : Math.max(state.declaredVersion, state.pushedVersion ?? state.declaredVersion);
328
+ let settled = false;
329
+ return {
330
+ clientUri,
331
+ edits,
332
+ version,
333
+ notifyOutcome: outcome => {
334
+ if (!settled) {
335
+ settled = true;
336
+ if (outcome === 'refused' && version !== null) {
337
+ this.tracer
338
+ .with(key)
339
+ .warn(
340
+ `Language client refused applyEdit addressed at version ${version} (it last declared version ${state.declaredVersion})`
341
+ );
342
+ }
343
+ // A reopen while the push was in flight reset what is tracked for the new buffer.
344
+ if (this.opens.get(key)?.get(clientUri) === state) {
345
+ this.settle(clientUri, version, state, outcome);
346
+ }
347
+ }
348
+ }
349
+ };
350
+ }
351
+
352
+ /** What a prepared push's {@link PreparedLanguageClientPush.notifyOutcome} does. */
353
+ protected settle(
354
+ clientUri: LanguageClientUri,
355
+ version: number | null,
356
+ state: LanguageClientDocumentState | undefined,
357
+ outcome: LanguageClientPushOutcome
358
+ ): void {
359
+ if (outcome !== 'applied') {
360
+ this.invalidateClientText(clientUri);
361
+ } else if (version !== null && state) {
362
+ // A client steps once per applied edit that changes its buffer. Left
363
+ // to the echo, a push sent next is refused at the old version.
364
+ state.pushedVersion = version + 1;
365
+ }
366
+ }
367
+
368
+ invalidateClientText(clientUri: LanguageClientUri): void {
369
+ this.baselines.delete(clientUri);
370
+ this.pending.delete(clientUri);
371
+ }
372
+
373
+ /**
374
+ * The edits that bring the client from its baseline to `text`, moving the
375
+ * baseline to `text`. A full replace without a baseline, none when the
376
+ * client was last heard to hold exactly `text` (pushing it anyway dirties
377
+ * the buffer and adds an undo step), and otherwise a line diff, verified by
378
+ * applying it: a diff that does not reproduce `text` falls back to a full
379
+ * replace rather than corrupting the client.
380
+ */
381
+ protected computeEdits(clientUri: LanguageClientUri, text: string): TextEdit[] {
382
+ const old = this.baselines.get(clientUri);
383
+ if (old === text) {
384
+ return [];
385
+ }
386
+ this.baselines.set(clientUri, text);
387
+ const fullReplace: TextEdit = { range: FULL_RANGE, newText: text };
388
+ if (old === undefined) {
389
+ return this.heardTexts.get(clientUri) === text ? [] : [fullReplace];
390
+ }
391
+ const edits = diffToEdits(old, text);
392
+ const probe = this.configuration.create(clientUri, 'plaintext', 0, old);
393
+ if (TextDocument.applyEdits(probe, edits) !== text) {
394
+ this.tracer.with(clientUri).warn('Diff apply-verify fallback (apply-verify-mismatch) — using full-document replace');
395
+ return [fullReplace];
396
+ }
397
+ return edits;
398
+ }
399
+
400
+ /** Bounded, so an echo that never arrives cannot grow the queue without limit. */
401
+ protected recordPendingPush(clientUri: LanguageClientUri, text: string): void {
402
+ let queue = this.pending.get(clientUri);
403
+ if (!queue) {
404
+ queue = [];
405
+ this.pending.set(clientUri, queue);
406
+ }
407
+ queue.push({ afterHash: textHash(text) });
408
+ if (queue.length > PENDING_ECHO_CAP) {
409
+ queue.shift();
410
+ this.tracer.with(clientUri).debug(`Pending-echo queue exceeded ${PENDING_ECHO_CAP} entries; dropped the oldest`);
411
+ }
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Convert a {@link diffLines} result to a list of LSP {@link TextEdit}s keyed on line positions
417
+ * in the *old* text. Contiguous added/removed hunks are coalesced into a single replace so the
418
+ * client sees one edit per changed region.
419
+ */
420
+ export function diffToEdits(oldText: string, newText: string): TextEdit[] {
421
+ const hunks = diffLines(oldText, newText);
422
+ const edits: TextEdit[] = [];
423
+ let oldLine = 0;
424
+ let i = 0;
425
+ while (i < hunks.length) {
426
+ const hunk = hunks[i];
427
+ if (!hunk.added && !hunk.removed) {
428
+ oldLine += hunk.count ?? 0;
429
+ i++;
430
+ continue;
431
+ }
432
+ // Coalesce a run of add/remove hunks into a single replace for this region.
433
+ let removedLines = 0;
434
+ let addedText = '';
435
+ while (i < hunks.length && (hunks[i].added || hunks[i].removed)) {
436
+ if (hunks[i].removed) {
437
+ removedLines += hunks[i].count ?? 0;
438
+ }
439
+ if (hunks[i].added) {
440
+ addedText += hunks[i].value;
441
+ }
442
+ i++;
443
+ }
444
+ edits.push({
445
+ range: Range.create(oldLine, 0, oldLine + removedLines, 0),
446
+ newText: addedText
447
+ });
448
+ oldLine += removedLines;
449
+ }
450
+ return edits;
451
+ }
@@ -0,0 +1,66 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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
+ import { type AstNode } from '@hydranium/langium';
11
+ import { asModelVersion, type ModelVersion, UNRECORDED_VERSION } from '@hydranium/protocol';
12
+
13
+ /** What {@link ModelLedger} holds for one root. */
14
+ export interface ModelRecord {
15
+ readonly version: ModelVersion;
16
+ /** For a root whose CST no longer is the text it describes: changed in place, or shed. */
17
+ readonly text?: string;
18
+ }
19
+
20
+ /**
21
+ * The version of the text each root was parsed from, and that text where the
22
+ * root's CST does not hold it. Stores what it is told; the rest of the
23
+ * framework relies on these:
24
+ *
25
+ * - every workspace root is recorded through `VersionSyncService.modelProduced` when produced;
26
+ * - a version is recorded only for text the store held at that version, else `STALE_VERSION`;
27
+ * - the builder's placeholder for a file it has not parsed carries no version;
28
+ * - re-recording a root without text keeps the text recorded before.
29
+ */
30
+ export interface ModelLedger {
31
+ record(root: AstNode, version: number, text?: string): void;
32
+ /** `UNRECORDED_VERSION`, which every write conflicts with, for a root nothing recorded. */
33
+ versionOf(root: AstNode): ModelVersion;
34
+ /** The recorded text, else the root's CST text; `undefined` for a root with neither. */
35
+ textOf(root: AstNode): string | undefined;
36
+ /** Mark `root`, registered before any parse, as no parse of any text, dropping its record. */
37
+ markPlaceholder(root: AstNode): void;
38
+ /** Keyed on the root, not its state: a rebuilt document is reset below `Parsed` but keeps its root. */
39
+ isPlaceholder(root: AstNode): boolean;
40
+ }
41
+
42
+ export class DefaultModelLedger implements ModelLedger {
43
+ protected readonly records = new WeakMap<AstNode, ModelRecord>();
44
+ protected readonly placeholders = new WeakSet<AstNode>();
45
+
46
+ record(root: AstNode, version: number, text?: string): void {
47
+ this.records.set(root, { version: asModelVersion(version), text: text ?? this.records.get(root)?.text });
48
+ }
49
+
50
+ versionOf(root: AstNode): ModelVersion {
51
+ return this.records.get(root)?.version ?? UNRECORDED_VERSION;
52
+ }
53
+
54
+ textOf(root: AstNode): string | undefined {
55
+ return this.records.get(root)?.text ?? root.$cstNode?.root.fullText;
56
+ }
57
+
58
+ markPlaceholder(root: AstNode): void {
59
+ this.placeholders.add(root);
60
+ this.records.delete(root);
61
+ }
62
+
63
+ isPlaceholder(root: AstNode): boolean {
64
+ return this.placeholders.has(root);
65
+ }
66
+ }
@@ -0,0 +1,112 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 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
+ import { type CanonicalUri, type TextVersion, textHash } from '@hydranium/protocol';
11
+ import { type TextDocument } from 'vscode-languageserver-textdocument';
12
+
13
+ /** What {@link TextLedger} holds for a document: where its version sequence stands, kept across closes and reopens. */
14
+ export interface TextRecord {
15
+ readonly version: TextVersion;
16
+ /** {@link textHash} of the text at that version. */
17
+ readonly hash: string;
18
+ }
19
+
20
+ /**
21
+ * Where each document's {@link TextVersion} sequence stands, and who authored
22
+ * each version; the text-side counterpart of `ModelLedger`.
23
+ *
24
+ * A record survives the document's release and is never pruned, not even when
25
+ * the file is deleted: a sequence that restarts lets a write based on the old
26
+ * text pass the base-version gate. Authors last only until the release.
27
+ */
28
+ export interface TextLedger {
29
+ /**
30
+ * The version a first open of `key` with `text` starts at: the record's
31
+ * version when the text is unchanged, one step on when it changed;
32
+ * `undefined` without a record.
33
+ */
34
+ openingVersion(key: CanonicalUri, text: string): TextVersion | undefined;
35
+ /** Keep where the sequence of the released `document` stands. */
36
+ record(key: CanonicalUri, document: TextDocument): void;
37
+ recordOf(key: CanonicalUri): TextRecord | undefined;
38
+ /**
39
+ * Text reached the closed document `key` outside the store's write paths.
40
+ * Steps the record iff `text` differs from it, and starts one at `0` when
41
+ * there is none.
42
+ */
43
+ reconcile(key: CanonicalUri, text: string): TextVersion;
44
+ /** {@link textHash} of `document`'s text, taken once per version. */
45
+ hashOf(document: TextDocument): string;
46
+ setAuthor(key: CanonicalUri, version: TextVersion, author: string): void;
47
+ /** The author of `version`, or of the latest version when `version` is omitted. */
48
+ authorOf(key: CanonicalUri, version?: TextVersion): string | undefined;
49
+ clearAuthors(key: CanonicalUri): void;
50
+ }
51
+
52
+ export class DefaultTextLedger implements TextLedger {
53
+ protected readonly records = new Map<CanonicalUri, TextRecord>();
54
+ protected readonly authors = new Map<CanonicalUri, string[]>();
55
+ protected readonly hashes = new WeakMap<TextDocument, { readonly version: number; readonly hash: string }>();
56
+
57
+ openingVersion(key: CanonicalUri, text: string): TextVersion | undefined {
58
+ const recorded = this.records.get(key);
59
+ if (recorded === undefined) {
60
+ return undefined;
61
+ }
62
+ return recorded.hash === textHash(text) ? recorded.version : recorded.version + 1;
63
+ }
64
+
65
+ record(key: CanonicalUri, document: TextDocument): void {
66
+ this.records.set(key, { version: document.version, hash: this.hashOf(document) });
67
+ }
68
+
69
+ recordOf(key: CanonicalUri): TextRecord | undefined {
70
+ return this.records.get(key);
71
+ }
72
+
73
+ reconcile(key: CanonicalUri, text: string): TextVersion {
74
+ const hash = textHash(text);
75
+ const recorded = this.records.get(key);
76
+ if (recorded?.hash === hash) {
77
+ return recorded.version;
78
+ }
79
+ const version = recorded === undefined ? 0 : recorded.version + 1;
80
+ this.records.set(key, { version, hash });
81
+ return version;
82
+ }
83
+
84
+ hashOf(document: TextDocument): string {
85
+ const taken = this.hashes.get(document);
86
+ if (taken?.version === document.version) {
87
+ return taken.hash;
88
+ }
89
+ const hash = textHash(document.getText());
90
+ this.hashes.set(document, { version: document.version, hash });
91
+ return hash;
92
+ }
93
+
94
+ setAuthor(key: CanonicalUri, version: TextVersion, author: string): void {
95
+ let history = this.authors.get(key);
96
+ if (!history) {
97
+ history = [];
98
+ this.authors.set(key, history);
99
+ }
100
+ history[version] = author;
101
+ }
102
+
103
+ authorOf(key: CanonicalUri, version?: TextVersion): string | undefined {
104
+ const history = this.authors.get(key);
105
+ // `!== undefined` so version 0 is not read as "latest".
106
+ return version !== undefined ? history?.[version] : history?.at(-1);
107
+ }
108
+
109
+ clearAuthors(key: CanonicalUri): void {
110
+ this.authors.delete(key);
111
+ }
112
+ }