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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (588) hide show
  1. package/README.md +6 -2
  2. package/lib/documents/ast-document-manager.d.ts +222 -63
  3. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  4. package/lib/documents/ast-document-manager.js +250 -83
  5. package/lib/documents/ast-document-manager.js.map +1 -1
  6. package/lib/documents/client-ids.d.ts +5 -19
  7. package/lib/documents/client-ids.d.ts.map +1 -1
  8. package/lib/documents/client-ids.js +5 -19
  9. package/lib/documents/client-ids.js.map +1 -1
  10. package/lib/documents/client-session-errors.d.ts +15 -0
  11. package/lib/documents/client-session-errors.d.ts.map +1 -0
  12. package/lib/documents/client-session-errors.js +15 -0
  13. package/lib/documents/client-session-errors.js.map +1 -0
  14. package/lib/documents/client-session-registry.d.ts +138 -0
  15. package/lib/documents/client-session-registry.d.ts.map +1 -0
  16. package/lib/documents/client-session-registry.js +187 -0
  17. package/lib/documents/client-session-registry.js.map +1 -0
  18. package/lib/documents/file-system-task-queue.d.ts +49 -0
  19. package/lib/documents/file-system-task-queue.d.ts.map +1 -0
  20. package/lib/documents/file-system-task-queue.js +34 -0
  21. package/lib/documents/file-system-task-queue.js.map +1 -0
  22. package/lib/documents/hydranium-text-documents.d.ts +523 -101
  23. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  24. package/lib/documents/hydranium-text-documents.js +961 -177
  25. package/lib/documents/hydranium-text-documents.js.map +1 -1
  26. package/lib/documents/index.d.ts +5 -0
  27. package/lib/documents/index.d.ts.map +1 -1
  28. package/lib/documents/index.js +5 -0
  29. package/lib/documents/index.js.map +1 -1
  30. package/lib/documents/language-client-text-shadow.d.ts +41 -9
  31. package/lib/documents/language-client-text-shadow.d.ts.map +1 -1
  32. package/lib/documents/language-client-text-shadow.js +56 -11
  33. package/lib/documents/language-client-text-shadow.js.map +1 -1
  34. package/lib/documents/model-ledger.d.ts +47 -0
  35. package/lib/documents/model-ledger.d.ts.map +1 -0
  36. package/lib/documents/model-ledger.js +30 -0
  37. package/lib/documents/model-ledger.js.map +1 -0
  38. package/lib/documents/self-save-registry.d.ts +37 -6
  39. package/lib/documents/self-save-registry.d.ts.map +1 -1
  40. package/lib/documents/self-save-registry.js +28 -15
  41. package/lib/documents/self-save-registry.js.map +1 -1
  42. package/lib/documents/version-sync-service.d.ts +134 -0
  43. package/lib/documents/version-sync-service.d.ts.map +1 -0
  44. package/lib/documents/version-sync-service.js +171 -0
  45. package/lib/documents/version-sync-service.js.map +1 -0
  46. package/lib/index.d.ts +3 -0
  47. package/lib/index.d.ts.map +1 -1
  48. package/lib/index.js +6 -0
  49. package/lib/index.js.map +1 -1
  50. package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
  51. package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
  52. package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
  53. package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
  54. package/lib/langium/ast-extension/ast-node-builder.js +60 -22
  55. package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
  56. package/lib/langium/bootstrap.d.ts.map +1 -1
  57. package/lib/langium/bootstrap.js +32 -9
  58. package/lib/langium/bootstrap.js.map +1 -1
  59. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
  60. package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
  61. package/lib/langium/config/configuration-provider.d.ts +81 -0
  62. package/lib/langium/config/configuration-provider.d.ts.map +1 -0
  63. package/lib/langium/config/configuration-provider.js +112 -0
  64. package/lib/langium/config/configuration-provider.js.map +1 -0
  65. package/lib/langium/config/index.d.ts +1 -0
  66. package/lib/langium/config/index.d.ts.map +1 -1
  67. package/lib/langium/config/index.js +1 -0
  68. package/lib/langium/config/index.js.map +1 -1
  69. package/lib/langium/config/settings.js.map +1 -1
  70. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
  71. package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
  72. package/lib/langium/diagnostics/logger.d.ts +10 -3
  73. package/lib/langium/diagnostics/logger.d.ts.map +1 -1
  74. package/lib/langium/diagnostics/logger.js +12 -5
  75. package/lib/langium/diagnostics/logger.js.map +1 -1
  76. package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
  77. package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
  78. package/lib/langium/diagnostics/lsp-logger.js +56 -13
  79. package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
  80. package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
  81. package/lib/langium/diagnostics/server-tracer.js.map +1 -1
  82. package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
  83. package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
  84. package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
  85. package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
  86. package/lib/langium/document-builder/build-session.d.ts +93 -0
  87. package/lib/langium/document-builder/build-session.d.ts.map +1 -0
  88. package/lib/langium/document-builder/build-session.js +72 -0
  89. package/lib/langium/document-builder/build-session.js.map +1 -0
  90. package/lib/langium/document-builder/document-builder.d.ts +382 -29
  91. package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
  92. package/lib/langium/document-builder/document-builder.js +659 -61
  93. package/lib/langium/document-builder/document-builder.js.map +1 -1
  94. package/lib/langium/document-builder/index.d.ts +1 -0
  95. package/lib/langium/document-builder/index.d.ts.map +1 -1
  96. package/lib/langium/document-builder/index.js +1 -0
  97. package/lib/langium/document-builder/index.js.map +1 -1
  98. package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
  99. package/lib/langium/documentation/comment-provider.js.map +1 -1
  100. package/lib/langium/integration-services.d.ts +45 -1
  101. package/lib/langium/integration-services.d.ts.map +1 -1
  102. package/lib/langium/integration-services.js +10 -5
  103. package/lib/langium/integration-services.js.map +1 -1
  104. package/lib/langium/integrity/integrity-rule.d.ts +13 -5
  105. package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
  106. package/lib/langium/integrity/integrity-rule.js.map +1 -1
  107. package/lib/langium/integrity/integrity-service.d.ts +58 -13
  108. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  109. package/lib/langium/integrity/integrity-service.js +204 -29
  110. package/lib/langium/integrity/integrity-service.js.map +1 -1
  111. package/lib/langium/keys/containment.d.ts +64 -0
  112. package/lib/langium/keys/containment.d.ts.map +1 -0
  113. package/lib/langium/keys/containment.js +53 -0
  114. package/lib/langium/keys/containment.js.map +1 -0
  115. package/lib/langium/keys/index.d.ts +1 -0
  116. package/lib/langium/keys/index.d.ts.map +1 -1
  117. package/lib/langium/keys/index.js +1 -0
  118. package/lib/langium/keys/index.js.map +1 -1
  119. package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
  120. package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
  121. package/lib/langium/keys/name-based-key-provider.js +4 -0
  122. package/lib/langium/keys/name-based-key-provider.js.map +1 -1
  123. package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
  124. package/lib/langium/keys/positional-key-provider.js.map +1 -1
  125. package/lib/langium/labeling/label-provider.d.ts.map +1 -1
  126. package/lib/langium/labeling/label-provider.js.map +1 -1
  127. package/lib/langium/language-module.d.ts +27 -2
  128. package/lib/langium/language-module.d.ts.map +1 -1
  129. package/lib/langium/language-module.js +16 -2
  130. package/lib/langium/language-module.js.map +1 -1
  131. package/lib/langium/model-service/client-session.d.ts +330 -0
  132. package/lib/langium/model-service/client-session.d.ts.map +1 -0
  133. package/lib/langium/model-service/client-session.js +418 -0
  134. package/lib/langium/model-service/client-session.js.map +1 -0
  135. package/lib/langium/model-service/index.d.ts +1 -0
  136. package/lib/langium/model-service/index.d.ts.map +1 -1
  137. package/lib/langium/model-service/index.js +1 -0
  138. package/lib/langium/model-service/index.js.map +1 -1
  139. package/lib/langium/model-service/model-service.d.ts +353 -253
  140. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  141. package/lib/langium/model-service/model-service.js +361 -408
  142. package/lib/langium/model-service/model-service.js.map +1 -1
  143. package/lib/langium/module.d.ts +150 -35
  144. package/lib/langium/module.d.ts.map +1 -1
  145. package/lib/langium/module.js +50 -35
  146. package/lib/langium/module.js.map +1 -1
  147. package/lib/langium/naming/name-provider.d.ts +25 -4
  148. package/lib/langium/naming/name-provider.d.ts.map +1 -1
  149. package/lib/langium/naming/name-provider.js +2 -1
  150. package/lib/langium/naming/name-provider.js.map +1 -1
  151. package/lib/langium/naming/name-separator-validation.d.ts +23 -0
  152. package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
  153. package/lib/langium/naming/name-separator-validation.js +30 -1
  154. package/lib/langium/naming/name-separator-validation.js.map +1 -1
  155. package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
  156. package/lib/langium/project/abstract-project-manager.js +9 -2
  157. package/lib/langium/project/abstract-project-manager.js.map +1 -1
  158. package/lib/langium/project/project-change-event.d.ts +2 -2
  159. package/lib/langium/project/single-project-manager.d.ts.map +1 -1
  160. package/lib/langium/project/single-project-manager.js.map +1 -1
  161. package/lib/langium/residency/cst-residency-service.d.ts +31 -11
  162. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  163. package/lib/langium/residency/cst-residency-service.js +23 -57
  164. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  165. package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
  166. package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
  167. package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
  168. package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
  169. package/lib/langium/scope/hydranium-scope-provider.d.ts +48 -13
  170. package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
  171. package/lib/langium/scope/hydranium-scope-provider.js +56 -20
  172. package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
  173. package/lib/langium/scope/reference-builder.d.ts.map +1 -1
  174. package/lib/langium/scope/reference-builder.js.map +1 -1
  175. package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
  176. package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
  177. package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
  178. package/lib/langium/scope/scope-extension-service.js.map +1 -1
  179. package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
  180. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  181. package/lib/langium/serialization/abstract-serializer.js +12 -21
  182. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  183. package/lib/langium/serialization/json-serializer.d.ts +1 -1
  184. package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
  185. package/lib/langium/serialization/json-serializer.js.map +1 -1
  186. package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
  187. package/lib/langium/serialization/yaml-serializer.js.map +1 -1
  188. package/lib/langium/service-registry.d.ts +15 -1
  189. package/lib/langium/service-registry.d.ts.map +1 -1
  190. package/lib/langium/service-registry.js +16 -0
  191. package/lib/langium/service-registry.js.map +1 -1
  192. package/lib/langium/shared-services.d.ts +21 -4
  193. package/lib/langium/shared-services.d.ts.map +1 -1
  194. package/lib/langium/shared-services.js.map +1 -1
  195. package/lib/langium/transfer/transfer-encoder.d.ts +75 -23
  196. package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
  197. package/lib/langium/transfer/transfer-encoder.js +44 -21
  198. package/lib/langium/transfer/transfer-encoder.js.map +1 -1
  199. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  200. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  201. package/lib/langium/trivia/comment-preserver.js +906 -0
  202. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  203. package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
  204. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  205. package/lib/langium/trivia/document-ending-preserver.js +48 -0
  206. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  207. package/lib/langium/trivia/index.d.ts +14 -0
  208. package/lib/langium/trivia/index.d.ts.map +1 -0
  209. package/lib/langium/trivia/index.js +14 -0
  210. package/lib/langium/trivia/index.js.map +1 -0
  211. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  212. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  213. package/lib/langium/trivia/trivia-contribution.js +10 -0
  214. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  215. package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
  216. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  217. package/lib/langium/trivia/trivia-preserver.js +10 -0
  218. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  219. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  220. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  221. package/lib/langium/trivia/trivia-service.js +56 -0
  222. package/lib/langium/trivia/trivia-service.js.map +1 -0
  223. package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
  224. package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
  225. package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
  226. package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
  227. package/lib/langium/validation/document-validator.d.ts +294 -10
  228. package/lib/langium/validation/document-validator.d.ts.map +1 -1
  229. package/lib/langium/validation/document-validator.js +448 -5
  230. package/lib/langium/validation/document-validator.js.map +1 -1
  231. package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
  232. package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
  233. package/lib/langium/workspace/document-uri-policy.d.ts +17 -12
  234. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  235. package/lib/langium/workspace/document-uri-policy.js +10 -9
  236. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  237. package/lib/langium/workspace/file-not-found.d.ts +17 -0
  238. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  239. package/lib/langium/workspace/file-not-found.js +20 -0
  240. package/lib/langium/workspace/file-not-found.js.map +1 -0
  241. package/lib/langium/workspace/file-system-provider.d.ts +84 -8
  242. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  243. package/lib/langium/workspace/file-system-provider.js +93 -14
  244. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  245. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
  246. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
  247. package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
  248. package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
  249. package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
  250. package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
  251. package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
  252. package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
  253. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +81 -8
  254. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  255. package/lib/langium/workspace/hydranium-workspace-manager.js +128 -10
  256. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  257. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +25 -2
  258. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  259. package/lib/langium/workspace/in-memory-file-system-provider.js +41 -15
  260. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  261. package/lib/langium/workspace/index-manager.d.ts.map +1 -1
  262. package/lib/langium/workspace/index-manager.js.map +1 -1
  263. package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
  264. package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
  265. package/lib/langium/workspace/initialize-workspace.js +13 -5
  266. package/lib/langium/workspace/initialize-workspace.js.map +1 -1
  267. package/lib/langium/workspace/langium-documents.d.ts +86 -17
  268. package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
  269. package/lib/langium/workspace/langium-documents.js +101 -29
  270. package/lib/langium/workspace/langium-documents.js.map +1 -1
  271. package/lib/langium/workspace/persistent-file-system-provider.d.ts +0 -7
  272. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  273. package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
  274. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  275. package/lib/langium/workspace/virtual-document.d.ts +48 -15
  276. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  277. package/lib/langium/workspace/virtual-document.js +78 -18
  278. package/lib/langium/workspace/virtual-document.js.map +1 -1
  279. package/lib/langium/workspace/write-lock-scope.d.ts +20 -10
  280. package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
  281. package/lib/langium/workspace/write-lock-scope.js +12 -4
  282. package/lib/langium/workspace/write-lock-scope.js.map +1 -1
  283. package/lib/locale/index.d.ts +10 -0
  284. package/lib/locale/index.d.ts.map +1 -0
  285. package/lib/locale/index.js +10 -0
  286. package/lib/locale/index.js.map +1 -0
  287. package/lib/locale/server-locale.d.ts +73 -0
  288. package/lib/locale/server-locale.d.ts.map +1 -0
  289. package/lib/locale/server-locale.js +61 -0
  290. package/lib/locale/server-locale.js.map +1 -0
  291. package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
  292. package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
  293. package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
  294. package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
  295. package/lib/lsp/connection-features.d.ts +23 -0
  296. package/lib/lsp/connection-features.d.ts.map +1 -0
  297. package/lib/lsp/connection-features.js +60 -0
  298. package/lib/lsp/connection-features.js.map +1 -0
  299. package/lib/lsp/diagnostics-connection.d.ts +27 -0
  300. package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
  301. package/lib/lsp/diagnostics-connection.js +53 -0
  302. package/lib/lsp/diagnostics-connection.js.map +1 -0
  303. package/lib/lsp/hydranium-document-update-handler.d.ts +90 -79
  304. package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
  305. package/lib/lsp/hydranium-document-update-handler.js +153 -99
  306. package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
  307. package/lib/lsp/index.d.ts +3 -1
  308. package/lib/lsp/index.d.ts.map +1 -1
  309. package/lib/lsp/index.js +3 -1
  310. package/lib/lsp/index.js.map +1 -1
  311. package/lib/lsp/lsp-latency.d.ts +39 -0
  312. package/lib/lsp/lsp-latency.d.ts.map +1 -0
  313. package/lib/lsp/lsp-latency.js +58 -0
  314. package/lib/lsp/lsp-latency.js.map +1 -0
  315. package/lib/lsp/semantic-token-provider.d.ts +34 -1
  316. package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
  317. package/lib/lsp/semantic-token-provider.js +55 -8
  318. package/lib/lsp/semantic-token-provider.js.map +1 -1
  319. package/lib/lsp/shared-module.d.ts +4 -8
  320. package/lib/lsp/shared-module.d.ts.map +1 -1
  321. package/lib/lsp/shared-module.js.map +1 -1
  322. package/lib/lsp/start-language-server.d.ts +8 -7
  323. package/lib/lsp/start-language-server.d.ts.map +1 -1
  324. package/lib/lsp/start-language-server.js +13 -7
  325. package/lib/lsp/start-language-server.js.map +1 -1
  326. package/lib/messages/carriers.d.ts +54 -0
  327. package/lib/messages/carriers.d.ts.map +1 -0
  328. package/lib/messages/carriers.js +62 -0
  329. package/lib/messages/carriers.js.map +1 -0
  330. package/lib/messages/index.d.ts +25 -0
  331. package/lib/messages/index.d.ts.map +1 -0
  332. package/lib/messages/index.js +25 -0
  333. package/lib/messages/index.js.map +1 -0
  334. package/lib/messages/renderer.d.ts +142 -0
  335. package/lib/messages/renderer.d.ts.map +1 -0
  336. package/lib/messages/renderer.js +165 -0
  337. package/lib/messages/renderer.js.map +1 -0
  338. package/lib/node/event-loop-monitor.js.map +1 -1
  339. package/lib/node/heap-ceiling.d.ts +61 -0
  340. package/lib/node/heap-ceiling.d.ts.map +1 -0
  341. package/lib/node/heap-ceiling.js +72 -0
  342. package/lib/node/heap-ceiling.js.map +1 -0
  343. package/lib/node/index.d.ts +1 -0
  344. package/lib/node/index.d.ts.map +1 -1
  345. package/lib/node/index.js +1 -0
  346. package/lib/node/index.js.map +1 -1
  347. package/lib/node/latency-from-env.d.ts +1 -1
  348. package/lib/node/latency-from-env.js +1 -1
  349. package/lib/node/lint-grammar.js.map +1 -1
  350. package/lib/node/measure-memory.d.ts.map +1 -1
  351. package/lib/node/measure-memory.js +1 -0
  352. package/lib/node/measure-memory.js.map +1 -1
  353. package/lib/node/memory-monitor.js.map +1 -1
  354. package/lib/node/node-file-system-provider.d.ts +39 -4
  355. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  356. package/lib/node/node-file-system-provider.js +109 -49
  357. package/lib/node/node-file-system-provider.js.map +1 -1
  358. package/lib/node/process-memory.js.map +1 -1
  359. package/lib/node/profile-capture.d.ts +8 -2
  360. package/lib/node/profile-capture.d.ts.map +1 -1
  361. package/lib/node/profile-capture.js.map +1 -1
  362. package/lib/node/profile-digest.js.map +1 -1
  363. package/lib/node/profiling-run.d.ts +13 -3
  364. package/lib/node/profiling-run.d.ts.map +1 -1
  365. package/lib/node/profiling-run.js +17 -8
  366. package/lib/node/profiling-run.js.map +1 -1
  367. package/lib/node/rename-over-open-readers.d.ts +52 -0
  368. package/lib/node/rename-over-open-readers.d.ts.map +1 -0
  369. package/lib/node/rename-over-open-readers.js +66 -0
  370. package/lib/node/rename-over-open-readers.js.map +1 -0
  371. package/lib/node/socket-launcher.d.ts +16 -1
  372. package/lib/node/socket-launcher.d.ts.map +1 -1
  373. package/lib/node/socket-launcher.js +4 -3
  374. package/lib/node/socket-launcher.js.map +1 -1
  375. package/lib/node/stdio-launcher.d.ts +1 -1
  376. package/lib/node/stdio-launcher.d.ts.map +1 -1
  377. package/lib/node/stdio-launcher.js +1 -1
  378. package/lib/node/stdio-launcher.js.map +1 -1
  379. package/lib/testing/document-uri-policy-conformance.js.map +1 -1
  380. package/lib/testing/fake-description.js.map +1 -1
  381. package/lib/testing/fake-document.d.ts +16 -4
  382. package/lib/testing/fake-document.d.ts.map +1 -1
  383. package/lib/testing/fake-document.js +18 -3
  384. package/lib/testing/fake-document.js.map +1 -1
  385. package/lib/testing/index.d.ts +1 -1
  386. package/lib/testing/index.d.ts.map +1 -1
  387. package/lib/testing/index.js +2 -1
  388. package/lib/testing/index.js.map +1 -1
  389. package/lib/testing/langium-test-helpers.d.ts.map +1 -1
  390. package/lib/testing/langium-test-helpers.js +1 -0
  391. package/lib/testing/langium-test-helpers.js.map +1 -1
  392. package/lib/testing/make-noop-language-services.js.map +1 -1
  393. package/lib/testing/make-noop-shared-services.d.ts +14 -0
  394. package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
  395. package/lib/testing/make-noop-shared-services.js +28 -2
  396. package/lib/testing/make-noop-shared-services.js.map +1 -1
  397. package/lib/testing/make-test-services.d.ts +69 -14
  398. package/lib/testing/make-test-services.d.ts.map +1 -1
  399. package/lib/testing/make-test-services.js +39 -10
  400. package/lib/testing/make-test-services.js.map +1 -1
  401. package/lib/testing/make-test-tracer.js.map +1 -1
  402. package/lib/testing/node/golden-corpus.js.map +1 -1
  403. package/lib/testing/node/index.d.ts +1 -0
  404. package/lib/testing/node/index.d.ts.map +1 -1
  405. package/lib/testing/node/index.js +1 -0
  406. package/lib/testing/node/index.js.map +1 -1
  407. package/lib/testing/node/lsp-harness.d.ts.map +1 -1
  408. package/lib/testing/node/lsp-harness.js +2 -0
  409. package/lib/testing/node/lsp-harness.js.map +1 -1
  410. package/lib/testing/node/lsp-server-connection.d.ts +11 -3
  411. package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
  412. package/lib/testing/node/lsp-server-connection.js +42 -9
  413. package/lib/testing/node/lsp-server-connection.js.map +1 -1
  414. package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
  415. package/lib/testing/node/scratch-workspace.js +10 -5
  416. package/lib/testing/node/scratch-workspace.js.map +1 -1
  417. package/lib/testing/node/spawned-server.d.ts +14 -0
  418. package/lib/testing/node/spawned-server.d.ts.map +1 -1
  419. package/lib/testing/node/spawned-server.js +33 -1
  420. package/lib/testing/node/spawned-server.js.map +1 -1
  421. package/lib/testing/node/unhandled-rejections.d.ts +20 -0
  422. package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
  423. package/lib/testing/node/unhandled-rejections.js +32 -0
  424. package/lib/testing/node/unhandled-rejections.js.map +1 -0
  425. package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
  426. package/lib/testing/playwright/e2e-profiling.js.map +1 -1
  427. package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
  428. package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
  429. package/lib/testing/playwright/flaky-network-proxy.js +164 -0
  430. package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
  431. package/lib/testing/playwright/index.d.ts +1 -0
  432. package/lib/testing/playwright/index.d.ts.map +1 -1
  433. package/lib/testing/playwright/index.js +1 -0
  434. package/lib/testing/playwright/index.js.map +1 -1
  435. package/lib/testing/playwright/server-log-capture.d.ts +24 -8
  436. package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
  437. package/lib/testing/playwright/server-log-capture.js +27 -6
  438. package/lib/testing/playwright/server-log-capture.js.map +1 -1
  439. package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
  440. package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
  441. package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
  442. package/lib/testing/run-update-pipeline.d.ts +4 -4
  443. package/lib/testing/run-update-pipeline.d.ts.map +1 -1
  444. package/lib/testing/stub-ast-document-manager.d.ts +11 -9
  445. package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
  446. package/lib/testing/stub-ast-document-manager.js +25 -9
  447. package/lib/testing/stub-ast-document-manager.js.map +1 -1
  448. package/lib/testing/stub-document-builder.d.ts +26 -11
  449. package/lib/testing/stub-document-builder.d.ts.map +1 -1
  450. package/lib/testing/stub-document-builder.js +57 -4
  451. package/lib/testing/stub-document-builder.js.map +1 -1
  452. package/lib/testing/stub-hydranium-text-documents.d.ts +22 -7
  453. package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
  454. package/lib/testing/stub-hydranium-text-documents.js +97 -15
  455. package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
  456. package/lib/testing/stub-index-manager.js.map +1 -1
  457. package/lib/testing/stub-langium-documents.d.ts +3 -2
  458. package/lib/testing/stub-langium-documents.d.ts.map +1 -1
  459. package/lib/testing/stub-langium-documents.js.map +1 -1
  460. package/lib/testing/stub-model-service.d.ts +7 -6
  461. package/lib/testing/stub-model-service.d.ts.map +1 -1
  462. package/lib/testing/stub-model-service.js +4 -4
  463. package/lib/testing/stub-model-service.js.map +1 -1
  464. package/lib/testing/stub-project-manager.js.map +1 -1
  465. package/lib/testing/stub-service-registry.js.map +1 -1
  466. package/lib/util/connection-liveness.d.ts +7 -6
  467. package/lib/util/connection-liveness.d.ts.map +1 -1
  468. package/lib/util/connection-liveness.js +35 -14
  469. package/lib/util/connection-liveness.js.map +1 -1
  470. package/lib/util/environment.d.ts.map +1 -1
  471. package/lib/util/environment.js.map +1 -1
  472. package/lib/util/registry.d.ts.map +1 -1
  473. package/package.json +35 -26
  474. package/src/documents/ast-document-manager.ts +395 -126
  475. package/src/documents/client-ids.ts +5 -22
  476. package/src/documents/client-session-errors.ts +24 -0
  477. package/src/documents/client-session-registry.ts +240 -0
  478. package/src/documents/file-system-task-queue.ts +68 -0
  479. package/src/documents/hydranium-text-documents.ts +1175 -225
  480. package/src/documents/index.ts +5 -0
  481. package/src/documents/language-client-text-shadow.ts +59 -11
  482. package/src/documents/model-ledger.ts +66 -0
  483. package/src/documents/self-save-registry.ts +52 -13
  484. package/src/documents/version-sync-service.ts +267 -0
  485. package/src/index.ts +6 -0
  486. package/src/langium/ast-extension/ast-node-builder.ts +66 -22
  487. package/src/langium/bootstrap.ts +32 -9
  488. package/src/langium/config/configuration-provider.ts +119 -0
  489. package/src/langium/config/index.ts +1 -0
  490. package/src/langium/diagnostics/logger.ts +12 -5
  491. package/src/langium/diagnostics/lsp-logger.ts +58 -12
  492. package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
  493. package/src/langium/document-builder/build-session.ts +87 -0
  494. package/src/langium/document-builder/document-builder.ts +776 -59
  495. package/src/langium/document-builder/index.ts +1 -0
  496. package/src/langium/integration-services.ts +67 -6
  497. package/src/langium/integrity/integrity-rule.ts +13 -5
  498. package/src/langium/integrity/integrity-service.ts +220 -30
  499. package/src/langium/keys/containment.ts +87 -0
  500. package/src/langium/keys/index.ts +1 -0
  501. package/src/langium/keys/name-based-key-provider.ts +4 -0
  502. package/src/langium/language-module.ts +42 -4
  503. package/src/langium/model-service/client-session.ts +649 -0
  504. package/src/langium/model-service/index.ts +1 -0
  505. package/src/langium/model-service/model-service.ts +570 -433
  506. package/src/langium/module.ts +201 -64
  507. package/src/langium/naming/name-provider.ts +27 -5
  508. package/src/langium/naming/name-separator-validation.ts +34 -5
  509. package/src/langium/project/abstract-project-manager.ts +9 -1
  510. package/src/langium/project/project-change-event.ts +2 -2
  511. package/src/langium/residency/cst-residency-service.ts +46 -15
  512. package/src/langium/scope/hydranium-scope-provider.ts +60 -22
  513. package/src/langium/serialization/abstract-serializer.ts +13 -32
  514. package/src/langium/service-registry.ts +19 -2
  515. package/src/langium/shared-services.ts +25 -4
  516. package/src/langium/transfer/transfer-encoder.ts +102 -34
  517. package/src/langium/trivia/comment-preserver.ts +1100 -0
  518. package/src/langium/trivia/document-ending-preserver.ts +55 -0
  519. package/src/langium/trivia/index.ts +14 -0
  520. package/src/langium/trivia/trivia-contribution.ts +39 -0
  521. package/src/langium/trivia/trivia-preserver.ts +54 -0
  522. package/src/langium/trivia/trivia-service.ts +99 -0
  523. package/src/langium/update-rewrite/update-rewrite.ts +1 -1
  524. package/src/langium/validation/document-validator.ts +537 -11
  525. package/src/langium/workspace/document-uri-policy.ts +17 -12
  526. package/src/langium/workspace/file-not-found.ts +23 -0
  527. package/src/langium/workspace/file-system-provider.ts +153 -16
  528. package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
  529. package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
  530. package/src/langium/workspace/hydranium-workspace-manager.ts +153 -13
  531. package/src/langium/workspace/in-memory-file-system-provider.ts +47 -16
  532. package/src/langium/workspace/initialize-workspace.ts +43 -5
  533. package/src/langium/workspace/langium-documents.ts +124 -33
  534. package/src/langium/workspace/persistent-file-system-provider.ts +0 -7
  535. package/src/langium/workspace/virtual-document.ts +96 -19
  536. package/src/langium/workspace/write-lock-scope.ts +24 -11
  537. package/src/locale/index.ts +10 -0
  538. package/src/locale/server-locale.ts +86 -0
  539. package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
  540. package/src/lsp/connection-features.ts +67 -0
  541. package/src/lsp/diagnostics-connection.ts +56 -0
  542. package/src/lsp/hydranium-document-update-handler.ts +185 -106
  543. package/src/lsp/index.ts +3 -1
  544. package/src/lsp/lsp-latency.ts +62 -0
  545. package/src/lsp/semantic-token-provider.ts +74 -7
  546. package/src/lsp/shared-module.ts +4 -8
  547. package/src/lsp/start-language-server.ts +13 -7
  548. package/src/messages/carriers.ts +78 -0
  549. package/src/messages/index.ts +36 -0
  550. package/src/messages/renderer.ts +212 -0
  551. package/src/node/heap-ceiling.ts +108 -0
  552. package/src/node/index.ts +1 -0
  553. package/src/node/latency-from-env.ts +1 -1
  554. package/src/node/measure-memory.ts +1 -0
  555. package/src/node/node-file-system-provider.ts +122 -51
  556. package/src/node/profile-capture.ts +8 -2
  557. package/src/node/profiling-run.ts +30 -8
  558. package/src/node/rename-over-open-readers.ts +78 -0
  559. package/src/node/socket-launcher.ts +19 -4
  560. package/src/node/stdio-launcher.ts +1 -2
  561. package/src/testing/fake-document.ts +24 -5
  562. package/src/testing/index.ts +2 -1
  563. package/src/testing/langium-test-helpers.ts +1 -0
  564. package/src/testing/make-noop-shared-services.ts +50 -2
  565. package/src/testing/make-test-services.ts +120 -31
  566. package/src/testing/node/index.ts +1 -0
  567. package/src/testing/node/lsp-harness.ts +2 -0
  568. package/src/testing/node/lsp-server-connection.ts +61 -11
  569. package/src/testing/node/scratch-workspace.ts +10 -5
  570. package/src/testing/node/spawned-server.ts +35 -1
  571. package/src/testing/node/unhandled-rejections.ts +31 -0
  572. package/src/testing/playwright/flaky-network-proxy.ts +240 -0
  573. package/src/testing/playwright/index.ts +1 -0
  574. package/src/testing/playwright/server-log-capture.ts +45 -11
  575. package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
  576. package/src/testing/run-update-pipeline.ts +4 -4
  577. package/src/testing/stub-ast-document-manager.ts +40 -23
  578. package/src/testing/stub-document-builder.ts +83 -17
  579. package/src/testing/stub-hydranium-text-documents.ts +133 -23
  580. package/src/testing/stub-langium-documents.ts +3 -2
  581. package/src/testing/stub-model-service.ts +9 -8
  582. package/src/util/connection-liveness.ts +37 -14
  583. package/src/util/environment.ts +9 -1
  584. package/lib/lsp/instrument-connection.d.ts +0 -36
  585. package/lib/lsp/instrument-connection.d.ts.map +0 -1
  586. package/lib/lsp/instrument-connection.js +0 -62
  587. package/lib/lsp/instrument-connection.js.map +0 -1
  588. package/src/lsp/instrument-connection.ts +0 -66
@@ -0,0 +1,649 @@
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 {
11
+ type BaseVersion,
12
+ ConflictError,
13
+ isModelVersion,
14
+ Logger,
15
+ type MaybeObservableValue,
16
+ type MaybePromise,
17
+ ObservableValue,
18
+ type TextVersion,
19
+ type Tracer,
20
+ type TransferElement
21
+ } from '@hydranium/protocol';
22
+ import { type AstNode, type DocumentBuilder, DocumentState, UriUtils } from '@hydranium/langium';
23
+ import { type CancellationToken, type Disposable } from 'vscode-languageserver';
24
+ import { type AstDocument, type SavedAstDocument } from '../../documents/ast-document-manager.js';
25
+ import { DocumentNotOpenError, SessionClosedError } from '../../documents/client-session-errors.js';
26
+ import { type OpenOptions, type SessionEndCause } from '../../documents/client-session-registry.js';
27
+ import { type LogNameOptions } from '../diagnostics/logger.js';
28
+ import { IntegrityService } from '../integrity/integrity-service.js';
29
+ import { type ServerSharedServices } from '../module.js';
30
+ import { type AstDiagnostic } from '../validation/document-validator.js';
31
+ import { type ModelService } from './model-service.js';
32
+
33
+ /** What a session's `update` and `save` write into one document; the session supplies its own client id. */
34
+ export interface ClientSessionWriteArgs<TTransfer> {
35
+ uri: string;
36
+ /** The whole structured model root, or its serialised textual form. */
37
+ model: TTransfer | string;
38
+ /**
39
+ * The version the write was authored against, or `'any'` to write
40
+ * unconditionally. Required, so an ungated write is a decision the caller
41
+ * makes rather than a field it forgot.
42
+ */
43
+ baseVersion: BaseVersion;
44
+ }
45
+
46
+ /** What a session's `persist` writes: the text the store holds for `uri`. */
47
+ export type ClientSessionPersistArgs = Omit<ClientSessionWriteArgs<never>, 'model'>;
48
+
49
+ /** What a session's `updateAll` writes, all or none. */
50
+ export interface ClientSessionUpdateAllArgs<TTransfer> {
51
+ updates: ClientSessionWriteArgs<TTransfer>[];
52
+ }
53
+
54
+ /**
55
+ * One participant's handle on the documents it works on, started by
56
+ * `ModelService.createSession`.
57
+ *
58
+ * The session writes only what it has open: `update`, `save` and `persist`
59
+ * fail with `DocumentNotOpenError` unless this session has the URI open in the
60
+ * synchronous step that applies or takes the text, so a write either lands
61
+ * while the document is open or fails. A document stays open until this
62
+ * session closes it, the session ends, or the file is deleted.
63
+ *
64
+ * One open per URI, without reference counting: opening a URI the session
65
+ * already has open changes nothing, and one `close` ends it.
66
+ *
67
+ * After `dispose`, every other member throws `SessionClosedError`
68
+ * synchronously, before returning a promise.
69
+ *
70
+ * Reads need no session and live on `ModelService`.
71
+ */
72
+ export interface ClientSession<
73
+ TAst extends AstNode,
74
+ TDiagnostic extends AstDiagnostic = AstDiagnostic,
75
+ TTransfer extends TransferElement = TransferElement,
76
+ TOpenOptions extends OpenOptions = OpenOptions
77
+ > {
78
+ /** Unique in the process while the session is live: the author label on its writes and the key of its opens. */
79
+ readonly clientId: string;
80
+ readonly label: string;
81
+
82
+ /**
83
+ * Open `uri` for this session, reading it from disk unless some client has
84
+ * it open already or it holds this client's unsaved text within its revert
85
+ * grace. `options` are kept for this open until it closes; a repeat open,
86
+ * concurrent or not, keeps the options of the first.
87
+ */
88
+ open(uri: string, options?: TOpenOptions): Promise<void>;
89
+ /** The options this session opened `uri` with, or `undefined` when it gave none or does not have `uri` open. */
90
+ openOptions(uri: string): TOpenOptions | undefined;
91
+ /**
92
+ * Create a document with `text` and open it for this session. It reaches
93
+ * disk on the first `save`. Fails when the file exists, any client has the
94
+ * URI open, or the URI waits out the revert grace, and of two creates of one
95
+ * URI at most one succeeds.
96
+ *
97
+ * Resolves with the version the created document took, which a write based
98
+ * on it names: once this resolves, the store's version may already be
99
+ * another client's write.
100
+ */
101
+ create(uri: string, text: string): Promise<TextVersion>;
102
+ /**
103
+ * Write `args.model` into a document this session has open. Resolves to the
104
+ * rebuilt document once it is validated, in whichever build carried the
105
+ * write, so the answer holds every diagnostic its update event does: that
106
+ * event names this session, and a client dropping its own echo would
107
+ * otherwise never see them.
108
+ */
109
+ update(args: ClientSessionWriteArgs<TTransfer>, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
110
+ /**
111
+ * Write several documents this session has open, all or none: a
112
+ * `ConflictError` or `DocumentNotOpenError` for any of them is thrown before
113
+ * any text applies. Resolves to the rebuilt documents, in the order given,
114
+ * each validated as {@link update}'s is.
115
+ */
116
+ updateAll(args: ClientSessionUpdateAllArgs<TTransfer>, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>[]>;
117
+ /** Write `args.model` as {@link update} does, then persist the document. */
118
+ save(args: ClientSessionWriteArgs<TTransfer>, cancelToken?: CancellationToken): Promise<SavedAstDocument<TAst, TDiagnostic>>;
119
+ /**
120
+ * Persist the text the store holds for `args.uri` as it is, with no update
121
+ * and no serialisation, and resolve to the document as {@link save} does.
122
+ * The saved event names this session, also when another client wrote the
123
+ * text.
124
+ */
125
+ persist(args: ClientSessionPersistArgs, cancelToken?: CancellationToken): Promise<SavedAstDocument<TAst, TDiagnostic>>;
126
+ /** Close this session's open of `uri`, at once. A no-op when it does not have `uri` open. */
127
+ close(uri: string): Promise<void>;
128
+ /**
129
+ * Open `uri`, run `fn`, and close `uri` when `fn` settles, whether it
130
+ * returned or threw. A URI the session already had open, or is still
131
+ * opening through another call, stays open: the close undoes only the open
132
+ * this call made.
133
+ */
134
+ withOpen<T>(uri: string, fn: () => MaybePromise<T>): Promise<T>;
135
+ /** Whether an event's `sourceClientId` names this session, i.e. the event echoes its own write. */
136
+ isOwnEcho(sourceClientId: string): boolean;
137
+ /**
138
+ * End the session: close everything it has open and free its id.
139
+ * Idempotent. `cause` is `'lost'` when the session ends because its
140
+ * client's connection went away, which lets each document it was the last
141
+ * to have open wait out the store's revert grace; ending it for any other
142
+ * reason reverts such a document at once.
143
+ */
144
+ dispose(cause?: SessionEndCause): void;
145
+ }
146
+
147
+ /**
148
+ * The phase a session write waits for before it answers: `Validated`, or
149
+ * {@link IntegrityService.SettledState} when rebuilds do not validate, since
150
+ * no build then reaches `Validated` and the wait would never end. Read from
151
+ * `updateBuildOptions`, which every rebuild takes; a document a
152
+ * `shouldValidate` override skips is the builder's to resolve.
153
+ *
154
+ * Waiting for the write's own build is not enough: a later write cancels it,
155
+ * and the build that takes over validates the document after the answer was
156
+ * taken.
157
+ */
158
+ function answerState(builder: DocumentBuilder): DocumentState {
159
+ return builder.updateBuildOptions.validation ? DocumentState.Validated : IntegrityService.SettledState;
160
+ }
161
+
162
+ /**
163
+ * The framework's {@link ClientSession}, built by
164
+ * {@link DefaultClientSessionFactory}.
165
+ *
166
+ * Override the protected method behind a member to change how every session
167
+ * writes, and return the subclass from a {@link ClientSessionFactory} bound on
168
+ * `model.ClientSessionFactory`. Serialising a model and rebuilding a document
169
+ * are the {@link ModelService}'s.
170
+ *
171
+ * An override of {@link dispose} calls `super.dispose(cause)`: that is what
172
+ * closes the session's opens and frees its id, and dropping `cause` reverts
173
+ * a lost client's documents without their grace.
174
+ */
175
+ export class DefaultClientSession<
176
+ TAst extends AstNode,
177
+ TDiagnostic extends AstDiagnostic = AstDiagnostic,
178
+ TTransfer extends TransferElement = TransferElement,
179
+ TOpenOptions extends OpenOptions = OpenOptions
180
+ > implements ClientSession<TAst, TDiagnostic, TTransfer, TOpenOptions> {
181
+ protected disposed = false;
182
+ /**
183
+ * This session's opens still under way, by canonical URI. Recorded before
184
+ * the first await, so a second open of the same URI joins the first rather
185
+ * than racing it, and `withOpen` can tell an open another call is making.
186
+ */
187
+ protected readonly pendingOpens = new Map<string, Promise<void>>();
188
+ /**
189
+ * The options of this session's opens, by canonical URI. A first open
190
+ * records its entry before the store has the URI open, and the entry goes
191
+ * when that open closes, whoever ends it: this session, or the store for a
192
+ * deleted file. A first open that fails never opens, so nothing closes it
193
+ * and its entry stays until the next first open of the URI overwrites it;
194
+ * {@link openOptions} therefore reads an entry only while the store has the
195
+ * URI open for this session.
196
+ */
197
+ protected readonly openOptionsByUri = new Map<string, TOpenOptions | undefined>();
198
+ /** Drops an open's options from {@link openOptionsByUri} when the store closes the open. */
199
+ protected readonly closeListener: Disposable;
200
+ /** Logs under `logName`, `ClientSession` when none is given, with this session's id in a bracket of its own, so a line names the session that wrote. */
201
+ protected readonly tracer: Tracer;
202
+ /** The service bound on `model.ModelService`, which serialises and rebuilds for this session. */
203
+ protected readonly modelService: ModelService<TAst, TDiagnostic, TTransfer>;
204
+ /** See {@link ClientSessionFactoryOptions.slowUpdateWarnMs}; `undefined` when not set. */
205
+ protected readonly slowUpdateWarn?: ObservableValue<number>;
206
+ readonly clientId: string;
207
+ readonly label: string;
208
+
209
+ constructor(
210
+ protected readonly services: ServerSharedServices,
211
+ options: ClientSessionOptions
212
+ ) {
213
+ this.clientId = options.clientId;
214
+ this.label = options.label ?? options.clientId;
215
+ // The slot is shared across grammars; this session's types hold for the
216
+ // grammar that started it, as `createSession`'s narrowing does.
217
+ this.modelService = services.model.ModelService as ModelService<TAst, TDiagnostic, TTransfer>;
218
+ this.slowUpdateWarn = options.slowUpdateWarnMs !== undefined ? ObservableValue.from(options.slowUpdateWarnMs) : undefined;
219
+ this.tracer = services.Tracer.for(options.logName ?? 'ClientSession').with(this.clientId);
220
+ this.closeListener = services.workspace.TextDocuments.onDidClose(event => {
221
+ if (event.clientId === this.clientId) {
222
+ this.openOptionsByUri.delete(event.document.uri);
223
+ }
224
+ });
225
+ }
226
+
227
+ open(uri: string, options?: TOpenOptions): Promise<void> {
228
+ this.assertLive();
229
+ return this.openDocument(uri, options);
230
+ }
231
+
232
+ openOptions(uri: string): TOpenOptions | undefined {
233
+ this.assertLive();
234
+ return this.services.workspace.TextDocuments.isOpenInClient(uri, this.clientId)
235
+ ? this.openOptionsByUri.get(this.canonicalKey(uri))
236
+ : undefined;
237
+ }
238
+
239
+ create(uri: string, text: string): Promise<TextVersion> {
240
+ this.assertLive();
241
+ return this.createDocument(uri, text);
242
+ }
243
+
244
+ update(args: ClientSessionWriteArgs<TTransfer>, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>> {
245
+ this.assertLive();
246
+ return this.updateDocument(args, cancelToken);
247
+ }
248
+
249
+ updateAll(args: ClientSessionUpdateAllArgs<TTransfer>, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>[]> {
250
+ this.assertLive();
251
+ return this.updateDocuments(args, cancelToken);
252
+ }
253
+
254
+ save(args: ClientSessionWriteArgs<TTransfer>, cancelToken?: CancellationToken): Promise<SavedAstDocument<TAst, TDiagnostic>> {
255
+ this.assertLive();
256
+ return this.saveDocument(args, cancelToken);
257
+ }
258
+
259
+ persist(args: ClientSessionPersistArgs, cancelToken?: CancellationToken): Promise<SavedAstDocument<TAst, TDiagnostic>> {
260
+ this.assertLive();
261
+ return this.persistDocument(args, cancelToken);
262
+ }
263
+
264
+ close(uri: string): Promise<void> {
265
+ this.assertLive();
266
+ return this.closeDocument(uri);
267
+ }
268
+
269
+ withOpen<T>(uri: string, fn: () => MaybePromise<T>): Promise<T> {
270
+ this.assertLive();
271
+ return this.runWithOpen(uri, fn);
272
+ }
273
+
274
+ isOwnEcho(sourceClientId: string): boolean {
275
+ this.assertLive();
276
+ return sourceClientId === this.clientId;
277
+ }
278
+
279
+ dispose(cause?: SessionEndCause): void {
280
+ if (this.disposed) {
281
+ return;
282
+ }
283
+ this.disposed = true;
284
+ this.services.workspace.TextDocuments.closeSession(this.clientId, cause);
285
+ this.closeListener.dispose();
286
+ }
287
+
288
+ protected assertLive(): void {
289
+ if (this.disposed) {
290
+ throw new SessionClosedError(this.clientId);
291
+ }
292
+ }
293
+
294
+ /** Throw `DocumentNotOpenError` unless this session has `uri` open. */
295
+ protected assertOpen(uri: string): void {
296
+ if (!this.services.workspace.TextDocuments.isOpenInClient(uri, this.clientId)) {
297
+ throw new DocumentNotOpenError(uri, this.clientId);
298
+ }
299
+ }
300
+
301
+ /**
302
+ * Throw `ConflictError` when `baseVersion` names a version other than
303
+ * `currentVersion`. A write calls it at the door and again in the
304
+ * synchronous step that applies the text, and has to call it synchronously
305
+ * there: a check separated from the apply by an await lets two writes based
306
+ * on one version both apply.
307
+ */
308
+ protected assertBaseVersion(uri: string, baseVersion: BaseVersion, currentVersion: number): void {
309
+ if (isModelVersion(baseVersion) && currentVersion !== baseVersion) {
310
+ // Distinct from the post-build "superseded" debug line of an update: this
311
+ // is a stale-base-version rejection (the write never applies), not two
312
+ // writes racing.
313
+ this.tracer.debug(`Conflict on ${uri}: stale base, model v${baseVersion} / text v${currentVersion}`);
314
+ throw new ConflictError(uri, baseVersion, currentVersion);
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Serialise `args.model`, apply it to the store under this session's id,
320
+ * rebuild, and resolve to the rebuilt document.
321
+ *
322
+ * The open check and the `baseVersion` gate run at the door, so a write that
323
+ * cannot land is refused before any adopter serialiser runs, and again in
324
+ * the synchronous step that applies the text: made only before the
325
+ * serialiser's await, a close during it lets the write land on a document
326
+ * this session no longer has open, and two writes based on one version
327
+ * both apply.
328
+ *
329
+ * Resolves with the latest build of the document, which may already carry
330
+ * a newer write; that is logged at debug, and a slow update at warn when
331
+ * `ClientSessionFactoryOptions.slowUpdateWarnMs` is set.
332
+ */
333
+ protected async updateDocument(
334
+ args: ClientSessionWriteArgs<TTransfer>,
335
+ cancelToken?: CancellationToken
336
+ ): Promise<AstDocument<TAst, TDiagnostic>> {
337
+ const service = this.modelService;
338
+ const slowWarn = this.slowUpdateWarn && { threshold: this.slowUpdateWarn, stopwatch: this.services.Clock.stopwatch() };
339
+ const uri = this.canonicalKey(args.uri);
340
+ const profile = Logger.isLevelEnabled('debug') ? this.tracer.profile(`model-update ${uri}`) : undefined;
341
+ const run = async <T>(stage: string, fn: () => MaybePromise<T>): Promise<T> => (profile ? profile.scope(stage, fn) : fn());
342
+ const textDocuments = this.services.workspace.TextDocuments;
343
+ this.assertOpen(uri);
344
+ this.assertBaseVersion(uri, args.baseVersion, textDocuments.version(uri));
345
+ service.assertCanBuild(uri);
346
+ const text = await run('serialize', () => service.modelToText(uri, args.model, cancelToken));
347
+ const appliedVersion = await run('apply', () => {
348
+ this.assertOpen(uri);
349
+ this.assertBaseVersion(uri, args.baseVersion, textDocuments.version(uri));
350
+ return this.services.workspace.AstDocumentManager.update(uri, text, this.clientId);
351
+ });
352
+ // Through the public `rebuild`, so an override of it stays in the path.
353
+ // An override that awaits before calling the base can outlast the build
354
+ // this write already has, and then builds it twice; see
355
+ // `ModelService.rebuild`.
356
+ const doc = await run('rebuild', () => service.rebuild(uri, answerState(this.services.workspace.DocumentBuilder), cancelToken));
357
+ const finalVersion = textDocuments.version(uri);
358
+ if (finalVersion > appliedVersion) {
359
+ this.tracer.debug(`Update to v${appliedVersion} ready at v${finalVersion} (changed again before it settled)`);
360
+ } else {
361
+ this.tracer.debug(`Update to v${appliedVersion} ready`);
362
+ }
363
+ if (slowWarn) {
364
+ const elapsed = Math.round(slowWarn.stopwatch.elapsedMs);
365
+ const threshold = slowWarn.threshold.value;
366
+ if (elapsed >= threshold) {
367
+ this.tracer.withUri(uri).warn(`Slow update: ${elapsed}ms ≥ ${threshold}ms (v${appliedVersion}, client=${this.clientId})`);
368
+ }
369
+ }
370
+ profile?.report('debug');
371
+ return doc;
372
+ }
373
+
374
+ /**
375
+ * Write every document of `args.updates`, all or none: every model is
376
+ * serialised first, then every open check and `baseVersion` gate runs and every
377
+ * text is applied in one synchronous step. Checked at the door as well, so
378
+ * a stale set is refused before any adopter serialiser runs.
379
+ *
380
+ * The apply step relies on `AstDocumentManager.update` applying its text
381
+ * before its first await, as the default does: an override that awaits first
382
+ * lets another write land between two documents of the set.
383
+ */
384
+ protected async updateDocuments(
385
+ args: ClientSessionUpdateAllArgs<TTransfer>,
386
+ cancelToken?: CancellationToken
387
+ ): Promise<AstDocument<TAst, TDiagnostic>[]> {
388
+ const service = this.modelService;
389
+ const { updates } = args;
390
+ const textDocuments = this.services.workspace.TextDocuments;
391
+ const uris = updates.map(update => this.canonicalKey(update.uri));
392
+ if (new Set(uris).size !== uris.length) {
393
+ throw new Error(`updateAll names a document more than once: ${uris.join(', ')}`);
394
+ }
395
+ const check = (): void =>
396
+ updates.forEach((update, i) => {
397
+ this.assertOpen(uris[i]);
398
+ this.assertBaseVersion(uris[i], update.baseVersion, textDocuments.version(uris[i]));
399
+ service.assertCanBuild(uris[i]);
400
+ });
401
+ check();
402
+ const texts: string[] = [];
403
+ for (const [i, update] of updates.entries()) {
404
+ texts.push(await service.modelToText(uris[i], update.model, cancelToken));
405
+ }
406
+ // One synchronous step from the first check to the last apply: an await
407
+ // anywhere in it lets a close or another write land after its document
408
+ // was checked, and the set then half-applies before a later check fails.
409
+ check();
410
+ const applied = uris.map((uri, i) => this.services.workspace.AstDocumentManager.update(uri, texts[i], this.clientId));
411
+ await Promise.all(applied);
412
+ const state = answerState(this.services.workspace.DocumentBuilder);
413
+ return Promise.all(uris.map(uri => service.rebuild(uri, state, cancelToken)));
414
+ }
415
+
416
+ /**
417
+ * Write `args.model` through {@link updateDocument}, so an override of it
418
+ * applies to saves too, then persist the document.
419
+ *
420
+ * Fails with `DocumentNotOpenError` and writes nothing when this session
421
+ * closes the URI while the text is being built: the check sits in the same
422
+ * synchronous step as the manager taking the text. Checked any earlier, a
423
+ * session that closes the URI during the rebuild still has the shared
424
+ * text, other clients' edits included, written in its name. Once taken,
425
+ * the write completes whatever the session does next.
426
+ */
427
+ protected async saveDocument(
428
+ args: ClientSessionWriteArgs<TTransfer>,
429
+ cancelToken?: CancellationToken
430
+ ): Promise<SavedAstDocument<TAst, TDiagnostic>> {
431
+ const doc = await this.updateDocument(args, cancelToken);
432
+ const uri = this.canonicalKey(args.uri);
433
+ this.assertOpen(uri);
434
+ const version = await this.services.workspace.AstDocumentManager.save(uri, this.clientId);
435
+ return { ...doc, persisted: { version } };
436
+ }
437
+
438
+ /**
439
+ * Persist the store's text for `args.uri` under this session's id.
440
+ *
441
+ * The open check and the `baseVersion` gate sit in the same synchronous step
442
+ * as the manager taking the text: an await between them lets another
443
+ * client's write land after the gate, and its text is then persisted under
444
+ * this session's id without this session ever having seen it.
445
+ */
446
+ protected async persistDocument(
447
+ args: ClientSessionPersistArgs,
448
+ cancelToken?: CancellationToken
449
+ ): Promise<SavedAstDocument<TAst, TDiagnostic>> {
450
+ const uri = this.canonicalKey(args.uri);
451
+ this.assertOpen(uri);
452
+ this.assertBaseVersion(uri, args.baseVersion, this.services.workspace.TextDocuments.version(uri));
453
+ const version = await this.services.workspace.AstDocumentManager.save(uri, this.clientId);
454
+ const doc = await this.modelService.ensureDocumentState(uri, answerState(this.services.workspace.DocumentBuilder), cancelToken);
455
+ return { ...doc, persisted: { version } };
456
+ }
457
+
458
+ protected async closeDocument(uri: string): Promise<void> {
459
+ await this.services.workspace.AstDocumentManager.close({ uri, clientId: this.clientId });
460
+ }
461
+
462
+ /** Open `uri`, or join the open of it this session already has under way, whose options then stand. */
463
+ protected openDocument(uri: string, options: TOpenOptions | undefined): Promise<void> {
464
+ const key = this.canonicalKey(uri);
465
+ const pending = this.pendingOpens.get(key);
466
+ if (pending) {
467
+ return pending;
468
+ }
469
+ const opening = this.registerOpen(uri, options).finally(() => {
470
+ if (this.pendingOpens.get(key) === opening) {
471
+ this.pendingOpens.delete(key);
472
+ }
473
+ });
474
+ this.pendingOpens.set(key, opening);
475
+ return opening;
476
+ }
477
+
478
+ /**
479
+ * Open `uri` in the store for this session. The open path does not thread
480
+ * cancellation: the file read behind it takes no token, so a cancelled
481
+ * caller still completes the open.
482
+ *
483
+ * A first open records its options before the store opens the URI, so a
484
+ * listener of the store's open reads this open's options rather than an
485
+ * earlier one's.
486
+ */
487
+ protected async registerOpen(uri: string, options: TOpenOptions | undefined): Promise<void> {
488
+ const wasOpen = this.services.workspace.TextDocuments.isOpenInClient(uri, this.clientId);
489
+ if (!wasOpen) {
490
+ this.openOptionsByUri.set(this.canonicalKey(uri), options);
491
+ }
492
+ await this.services.workspace.AstDocumentManager.open({ uri, clientId: this.clientId });
493
+ await this.rejectIfEnded(uri, wasOpen);
494
+ }
495
+
496
+ protected canonicalKey(uri: string): string {
497
+ return this.services.workspace.DocumentUriPolicy.canonicalUri(uri);
498
+ }
499
+
500
+ protected async createDocument(uri: string, text: string): Promise<TextVersion> {
501
+ if (await this.services.workspace.FileSystemProvider.exists(UriUtils.toUri(uri))) {
502
+ throw new Error(`Cannot create ${uri}: the file exists`);
503
+ }
504
+ this.assertLive();
505
+ if (this.services.workspace.TextDocuments.isRevertPending(uri)) {
506
+ throw new Error(`Cannot create ${uri}: it holds the unsaved text of a lost client, waiting out the revert grace`);
507
+ }
508
+ if (this.modelService.isOpen(uri)) {
509
+ throw new Error(`Cannot create ${uri}: it is open in a client`);
510
+ }
511
+ // The check above cannot see an open that registers while this one is
512
+ // under way, and opening an already-open URI only attaches, dropping
513
+ // `text`. Only an open that creates the document fires `onDidOpen`, so
514
+ // hearing it for this session, during this open, is what proves the
515
+ // document holds `text`; the client list afterwards cannot, since a
516
+ // client that registered first may have closed again by then.
517
+ const key = this.canonicalKey(uri);
518
+ let created: TextVersion | undefined;
519
+ const listener = this.services.workspace.TextDocuments.onDidOpen(event => {
520
+ if (event.clientId === this.clientId && event.document.uri === key) {
521
+ created = event.document.version;
522
+ }
523
+ });
524
+ try {
525
+ await this.services.workspace.AstDocumentManager.open({ uri, clientId: this.clientId, text });
526
+ } finally {
527
+ listener.dispose();
528
+ }
529
+ await this.rejectIfEnded(uri, false);
530
+ if (created === undefined) {
531
+ await this.closeDocument(uri);
532
+ throw new Error(`Cannot create ${uri}: it is open in a client`);
533
+ }
534
+ return created;
535
+ }
536
+
537
+ protected async runWithOpen<T>(uri: string, fn: () => MaybePromise<T>): Promise<T> {
538
+ // An open another call of this session is still making counts as made:
539
+ // closing it afterwards would take away an open that call asked for.
540
+ const alreadyOpen =
541
+ this.services.workspace.TextDocuments.isOpenInClient(uri, this.clientId) || this.pendingOpens.has(this.canonicalKey(uri));
542
+ await this.openDocument(uri, undefined);
543
+ try {
544
+ return await fn();
545
+ } finally {
546
+ if (!alreadyOpen && !this.disposed) {
547
+ await this.closeDocument(uri);
548
+ }
549
+ }
550
+ }
551
+
552
+ /**
553
+ * Undo an open that completed after the session ended, then fail it.
554
+ *
555
+ * Ending the session closed only what it had open at that moment. An open
556
+ * still reading from disk registers afterwards, under an id that is no
557
+ * longer a session, and nothing would ever close it.
558
+ *
559
+ * Opens are keyed by id, so once a new session holds the same id this open
560
+ * is indistinguishable from one of its own, and closing it would close the
561
+ * new session's. It is left to that session, which releases it at its end.
562
+ */
563
+ protected async rejectIfEnded(uri: string, wasOpen: boolean): Promise<void> {
564
+ if (!this.disposed) {
565
+ return;
566
+ }
567
+ if (!wasOpen && this.modelService.getSession(this.clientId) === undefined) {
568
+ await this.closeDocument(uri);
569
+ }
570
+ throw new SessionClosedError(this.clientId);
571
+ }
572
+ }
573
+
574
+ /** Constructor options for {@link DefaultClientSessionFactory}. */
575
+ export interface ClientSessionFactoryOptions extends LogNameOptions {
576
+ /**
577
+ * The name the factory and every session it builds log under, so one
578
+ * option renames both. Default: `ClientSessionFactory` for the factory,
579
+ * and `ClientSession` for a session, which adds its client id in a bracket
580
+ * of its own.
581
+ */
582
+ readonly logName?: string;
583
+ /**
584
+ * When set, a session's `update` logs a `warn` line if its end-to-end wait
585
+ * (serialise, apply, rebuild) takes at least this many milliseconds. Default
586
+ * `undefined`: no warn line, and no per-update stopwatch.
587
+ *
588
+ * Observability only: the update is neither aborted nor resolved
589
+ * differently. A hard timeout that throws is an override of
590
+ * `DefaultClientSession.updateDocument` racing the parent call against a
591
+ * deadline.
592
+ *
593
+ * A recommended starting threshold is 2-5 seconds; workspaces with very
594
+ * large documents or slow validation can exceed 5 s on a cold build. A
595
+ * `Settings.number` binding retunes it live.
596
+ */
597
+ readonly slowUpdateWarnMs?: MaybeObservableValue<number>;
598
+ }
599
+
600
+ /**
601
+ * Constructor options for {@link DefaultClientSession}: the factory's options,
602
+ * which it forwards, plus the session's identity.
603
+ */
604
+ export interface ClientSessionOptions extends ClientSessionFactoryOptions {
605
+ readonly clientId: string;
606
+ /** What the session is. Pass one: the client id stands in for it otherwise. */
607
+ readonly label?: string;
608
+ }
609
+
610
+ /**
611
+ * Builds the handle for a session `ModelService.createSession` has already
612
+ * registered, so registration and the uniqueness check cannot be skipped by
613
+ * binding a factory of one's own. Bind one on `model.ClientSessionFactory` to
614
+ * use a session class of your own. A factory that does not pass
615
+ * {@link ClientSessionFactoryOptions.slowUpdateWarnMs} on to its sessions
616
+ * loses their slow-update warn; subclassing {@link DefaultClientSessionFactory}
617
+ * keeps it.
618
+ *
619
+ * Typed for every grammar, since the slot is shared: `createSession` narrows
620
+ * the result to its caller's types.
621
+ */
622
+ export interface ClientSessionFactory {
623
+ create(clientId: string, label: string): ClientSession<AstNode>;
624
+ }
625
+
626
+ /**
627
+ * The framework's {@link ClientSessionFactory}: a {@link DefaultClientSession}
628
+ * over the {@link ModelService} bound on `model.ModelService`, which the session
629
+ * serialises and rebuilds through. A model service constructed outside that
630
+ * slot therefore starts sessions that write through the bound one.
631
+ *
632
+ * A subclass that overrides {@link create} to build a session class of its
633
+ * own passes {@link options} on to that session's constructor; a session built
634
+ * without them has no slow-update warn and logs under the default name.
635
+ */
636
+ export class DefaultClientSessionFactory implements ClientSessionFactory {
637
+ protected readonly tracer: Tracer;
638
+
639
+ constructor(
640
+ protected readonly services: ServerSharedServices,
641
+ protected readonly options: ClientSessionFactoryOptions = {}
642
+ ) {
643
+ this.tracer = services.Tracer.for(options.logName ?? 'ClientSessionFactory').trace('instantiated');
644
+ }
645
+
646
+ create(clientId: string, label: string): ClientSession<AstNode> {
647
+ return new DefaultClientSession(this.services, { ...this.options, clientId, label });
648
+ }
649
+ }
@@ -8,3 +8,4 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  export * from './model-service.js';
11
+ export * from './client-session.js';