@hydranium/core 1.0.0-next.28 → 1.0.0-next.281

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 (740) hide show
  1. package/README.md +64 -82
  2. package/lib/documents/ast-document-manager.d.ts +252 -122
  3. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  4. package/lib/documents/ast-document-manager.js +290 -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 +101 -0
  19. package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
  20. package/lib/documents/dirty-state-tracker.js +85 -0
  21. package/lib/documents/dirty-state-tracker.js.map +1 -0
  22. package/lib/documents/document-release-handler.d.ts +204 -0
  23. package/lib/documents/document-release-handler.d.ts.map +1 -0
  24. package/lib/documents/document-release-handler.js +317 -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 +415 -282
  35. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  36. package/lib/documents/hydranium-text-documents.js +849 -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 +284 -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 +138 -0
  55. package/lib/documents/version-sync-service.d.ts.map +1 -0
  56. package/lib/documents/version-sync-service.js +173 -0
  57. package/lib/documents/version-sync-service.js.map +1 -0
  58. package/lib/index.d.ts +5 -0
  59. package/lib/index.d.ts.map +1 -1
  60. package/lib/index.js +8 -0
  61. package/lib/index.js.map +1 -1
  62. package/lib/langium/ast-extension/ast-extension-service.d.ts +3 -0
  63. package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
  64. package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
  65. package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
  66. package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
  67. package/lib/langium/ast-extension/ast-node-builder.js +60 -22
  68. package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
  69. package/lib/langium/bootstrap.d.ts +49 -36
  70. package/lib/langium/bootstrap.d.ts.map +1 -1
  71. package/lib/langium/bootstrap.js +91 -45
  72. package/lib/langium/bootstrap.js.map +1 -1
  73. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts +1 -1
  74. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
  75. package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
  76. package/lib/langium/build-phase-pass/build-phase-pass.d.ts +1 -1
  77. package/lib/langium/composite-ast-reflection.d.ts +46 -0
  78. package/lib/langium/composite-ast-reflection.d.ts.map +1 -0
  79. package/lib/langium/composite-ast-reflection.js +97 -0
  80. package/lib/langium/composite-ast-reflection.js.map +1 -0
  81. package/lib/langium/config/configuration-provider.d.ts +81 -0
  82. package/lib/langium/config/configuration-provider.d.ts.map +1 -0
  83. package/lib/langium/config/configuration-provider.js +112 -0
  84. package/lib/langium/config/configuration-provider.js.map +1 -0
  85. package/lib/langium/config/index.d.ts +1 -0
  86. package/lib/langium/config/index.d.ts.map +1 -1
  87. package/lib/langium/config/index.js +1 -0
  88. package/lib/langium/config/index.js.map +1 -1
  89. package/lib/langium/config/settings.js.map +1 -1
  90. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts +9 -20
  91. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
  92. package/lib/langium/diagnostics/hydranium-langium-profiler.js +15 -24
  93. package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
  94. package/lib/langium/diagnostics/log-preamble.js +1 -1
  95. package/lib/langium/diagnostics/log-preamble.js.map +1 -1
  96. package/lib/langium/diagnostics/logger.d.ts +10 -3
  97. package/lib/langium/diagnostics/logger.d.ts.map +1 -1
  98. package/lib/langium/diagnostics/logger.js +12 -5
  99. package/lib/langium/diagnostics/logger.js.map +1 -1
  100. package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
  101. package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
  102. package/lib/langium/diagnostics/lsp-logger.js +58 -17
  103. package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
  104. package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
  105. package/lib/langium/diagnostics/server-tracer.js.map +1 -1
  106. package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
  107. package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
  108. package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
  109. package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
  110. package/lib/langium/document-builder/build-session.d.ts +6 -5
  111. package/lib/langium/document-builder/build-session.d.ts.map +1 -1
  112. package/lib/langium/document-builder/build-session.js +5 -5
  113. package/lib/langium/document-builder/build-session.js.map +1 -1
  114. package/lib/langium/document-builder/document-builder.d.ts +309 -35
  115. package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
  116. package/lib/langium/document-builder/document-builder.js +511 -75
  117. package/lib/langium/document-builder/document-builder.js.map +1 -1
  118. package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
  119. package/lib/langium/documentation/comment-provider.js.map +1 -1
  120. package/lib/langium/integration-services.d.ts +40 -24
  121. package/lib/langium/integration-services.d.ts.map +1 -1
  122. package/lib/langium/integration-services.js +7 -4
  123. package/lib/langium/integration-services.js.map +1 -1
  124. package/lib/langium/integrity/integrity-rule.d.ts +16 -8
  125. package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
  126. package/lib/langium/integrity/integrity-rule.js.map +1 -1
  127. package/lib/langium/integrity/integrity-service.d.ts +83 -27
  128. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  129. package/lib/langium/integrity/integrity-service.js +273 -63
  130. package/lib/langium/integrity/integrity-service.js.map +1 -1
  131. package/lib/langium/keys/containment.d.ts +64 -0
  132. package/lib/langium/keys/containment.d.ts.map +1 -0
  133. package/lib/langium/keys/containment.js +53 -0
  134. package/lib/langium/keys/containment.js.map +1 -0
  135. package/lib/langium/keys/index.d.ts +1 -0
  136. package/lib/langium/keys/index.d.ts.map +1 -1
  137. package/lib/langium/keys/index.js +1 -0
  138. package/lib/langium/keys/index.js.map +1 -1
  139. package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
  140. package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
  141. package/lib/langium/keys/name-based-key-provider.js +4 -0
  142. package/lib/langium/keys/name-based-key-provider.js.map +1 -1
  143. package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
  144. package/lib/langium/keys/positional-key-provider.js.map +1 -1
  145. package/lib/langium/labeling/label-provider.d.ts.map +1 -1
  146. package/lib/langium/labeling/label-provider.js.map +1 -1
  147. package/lib/langium/language-module.d.ts +30 -5
  148. package/lib/langium/language-module.d.ts.map +1 -1
  149. package/lib/langium/language-module.js +18 -4
  150. package/lib/langium/language-module.js.map +1 -1
  151. package/lib/langium/model-service/client-session.d.ts +372 -0
  152. package/lib/langium/model-service/client-session.d.ts.map +1 -0
  153. package/lib/langium/model-service/client-session.js +446 -0
  154. package/lib/langium/model-service/client-session.js.map +1 -0
  155. package/lib/langium/model-service/index.d.ts +2 -0
  156. package/lib/langium/model-service/index.d.ts.map +1 -1
  157. package/lib/langium/model-service/index.js +2 -0
  158. package/lib/langium/model-service/index.js.map +1 -1
  159. package/lib/langium/model-service/model-events.d.ts +66 -0
  160. package/lib/langium/model-service/model-events.d.ts.map +1 -0
  161. package/lib/langium/model-service/model-events.js +10 -0
  162. package/lib/langium/model-service/model-events.js.map +1 -0
  163. package/lib/langium/model-service/model-service.d.ts +440 -282
  164. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  165. package/lib/langium/model-service/model-service.js +542 -446
  166. package/lib/langium/model-service/model-service.js.map +1 -1
  167. package/lib/langium/module.d.ts +158 -37
  168. package/lib/langium/module.d.ts.map +1 -1
  169. package/lib/langium/module.js +52 -36
  170. package/lib/langium/module.js.map +1 -1
  171. package/lib/langium/naming/name-provider.d.ts +27 -6
  172. package/lib/langium/naming/name-provider.d.ts.map +1 -1
  173. package/lib/langium/naming/name-provider.js +4 -3
  174. package/lib/langium/naming/name-provider.js.map +1 -1
  175. package/lib/langium/naming/name-separator-validation.d.ts +23 -1
  176. package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
  177. package/lib/langium/naming/name-separator-validation.js +22 -0
  178. package/lib/langium/naming/name-separator-validation.js.map +1 -1
  179. package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
  180. package/lib/langium/project/abstract-project-manager.js +13 -6
  181. package/lib/langium/project/abstract-project-manager.js.map +1 -1
  182. package/lib/langium/project/project-change-event.d.ts +2 -2
  183. package/lib/langium/project/single-project-manager.d.ts.map +1 -1
  184. package/lib/langium/project/single-project-manager.js.map +1 -1
  185. package/lib/langium/residency/cst-residency-service.d.ts +35 -12
  186. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  187. package/lib/langium/residency/cst-residency-service.js +23 -57
  188. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  189. package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
  190. package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
  191. package/lib/langium/scope/fallback-scope.d.ts +27 -0
  192. package/lib/langium/scope/fallback-scope.d.ts.map +1 -0
  193. package/lib/langium/scope/fallback-scope.js +35 -0
  194. package/lib/langium/scope/fallback-scope.js.map +1 -0
  195. package/lib/langium/scope/hydranium-scope-computation.d.ts +21 -18
  196. package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
  197. package/lib/langium/scope/hydranium-scope-computation.js +38 -39
  198. package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
  199. package/lib/langium/scope/hydranium-scope-provider.d.ts +61 -24
  200. package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
  201. package/lib/langium/scope/hydranium-scope-provider.js +74 -35
  202. package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
  203. package/lib/langium/scope/index.d.ts +1 -0
  204. package/lib/langium/scope/index.d.ts.map +1 -1
  205. package/lib/langium/scope/index.js +1 -0
  206. package/lib/langium/scope/index.js.map +1 -1
  207. package/lib/langium/scope/reference-builder.d.ts.map +1 -1
  208. package/lib/langium/scope/reference-builder.js.map +1 -1
  209. package/lib/langium/scope/reference-candidate-provider.d.ts +6 -5
  210. package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
  211. package/lib/langium/scope/reference-candidate-provider.js +3 -2
  212. package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
  213. package/lib/langium/scope/scope-extension-service.d.ts +41 -37
  214. package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
  215. package/lib/langium/scope/scope-extension-service.js +57 -29
  216. package/lib/langium/scope/scope-extension-service.js.map +1 -1
  217. package/lib/langium/scope/scoped-ast-node-description.d.ts +1 -3
  218. package/lib/langium/scope/scoped-ast-node-description.d.ts.map +1 -1
  219. package/lib/langium/scope/scoped-ast-node-description.js +1 -3
  220. package/lib/langium/scope/scoped-ast-node-description.js.map +1 -1
  221. package/lib/langium/serialization/abstract-serializer.d.ts +38 -27
  222. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  223. package/lib/langium/serialization/abstract-serializer.js +54 -30
  224. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  225. package/lib/langium/serialization/json-serializer.d.ts +8 -1
  226. package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
  227. package/lib/langium/serialization/json-serializer.js +13 -3
  228. package/lib/langium/serialization/json-serializer.js.map +1 -1
  229. package/lib/langium/serialization/serializer.d.ts +1 -1
  230. package/lib/langium/serialization/yaml-serializer.d.ts +4 -0
  231. package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
  232. package/lib/langium/serialization/yaml-serializer.js +4 -0
  233. package/lib/langium/serialization/yaml-serializer.js.map +1 -1
  234. package/lib/langium/service-registry.d.ts +29 -1
  235. package/lib/langium/service-registry.d.ts.map +1 -1
  236. package/lib/langium/service-registry.js +37 -0
  237. package/lib/langium/service-registry.js.map +1 -1
  238. package/lib/langium/shared-services.d.ts +23 -6
  239. package/lib/langium/shared-services.d.ts.map +1 -1
  240. package/lib/langium/shared-services.js.map +1 -1
  241. package/lib/langium/single-langium-copy.d.ts +22 -0
  242. package/lib/langium/single-langium-copy.d.ts.map +1 -0
  243. package/lib/langium/single-langium-copy.js +36 -0
  244. package/lib/langium/single-langium-copy.js.map +1 -0
  245. package/lib/langium/transfer/transfer-encoder.d.ts +84 -35
  246. package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
  247. package/lib/langium/transfer/transfer-encoder.js +34 -23
  248. package/lib/langium/transfer/transfer-encoder.js.map +1 -1
  249. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  250. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  251. package/lib/langium/trivia/comment-preserver.js +906 -0
  252. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  253. package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
  254. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  255. package/lib/langium/trivia/document-ending-preserver.js +48 -0
  256. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  257. package/lib/langium/trivia/index.d.ts +14 -0
  258. package/lib/langium/trivia/index.d.ts.map +1 -0
  259. package/lib/langium/trivia/index.js +14 -0
  260. package/lib/langium/trivia/index.js.map +1 -0
  261. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  262. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  263. package/lib/langium/trivia/trivia-contribution.js +10 -0
  264. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  265. package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
  266. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  267. package/lib/langium/trivia/trivia-preserver.js +10 -0
  268. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  269. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  270. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  271. package/lib/langium/trivia/trivia-service.js +56 -0
  272. package/lib/langium/trivia/trivia-service.js.map +1 -0
  273. package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
  274. package/lib/langium/update-rewrite/update-rewrite-service.d.ts +1 -1
  275. package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
  276. package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
  277. package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
  278. package/lib/langium/validation/document-validator.d.ts +280 -9
  279. package/lib/langium/validation/document-validator.d.ts.map +1 -1
  280. package/lib/langium/validation/document-validator.js +453 -8
  281. package/lib/langium/validation/document-validator.js.map +1 -1
  282. package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
  283. package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
  284. package/lib/langium/validation/validation-contribution-collector.js +1 -1
  285. package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
  286. package/lib/langium/workspace/document-uri-policy.d.ts +15 -10
  287. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  288. package/lib/langium/workspace/document-uri-policy.js +7 -5
  289. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  290. package/lib/langium/workspace/file-not-found.d.ts +23 -0
  291. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  292. package/lib/langium/workspace/file-not-found.js +31 -0
  293. package/lib/langium/workspace/file-not-found.js.map +1 -0
  294. package/lib/langium/workspace/file-system-provider.d.ts +154 -8
  295. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  296. package/lib/langium/workspace/file-system-provider.js +102 -13
  297. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  298. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
  299. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
  300. package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
  301. package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
  302. package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
  303. package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
  304. package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
  305. package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
  306. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +109 -9
  307. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  308. package/lib/langium/workspace/hydranium-workspace-manager.js +192 -12
  309. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  310. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -9
  311. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  312. package/lib/langium/workspace/in-memory-file-system-provider.js +45 -22
  313. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  314. package/lib/langium/workspace/index-manager.d.ts.map +1 -1
  315. package/lib/langium/workspace/index-manager.js.map +1 -1
  316. package/lib/langium/workspace/index.d.ts +1 -0
  317. package/lib/langium/workspace/index.d.ts.map +1 -1
  318. package/lib/langium/workspace/index.js +1 -0
  319. package/lib/langium/workspace/index.js.map +1 -1
  320. package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
  321. package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
  322. package/lib/langium/workspace/initialize-workspace.js +13 -5
  323. package/lib/langium/workspace/initialize-workspace.js.map +1 -1
  324. package/lib/langium/workspace/langium-documents.d.ts +37 -4
  325. package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
  326. package/lib/langium/workspace/langium-documents.js +49 -4
  327. package/lib/langium/workspace/langium-documents.js.map +1 -1
  328. package/lib/langium/workspace/persistent-file-system-provider.d.ts +7 -9
  329. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  330. package/lib/langium/workspace/persistent-file-system-provider.js +14 -13
  331. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  332. package/lib/langium/workspace/self-save-registry.d.ts +84 -0
  333. package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
  334. package/lib/{documents → langium/workspace}/self-save-registry.js +33 -22
  335. package/lib/langium/workspace/self-save-registry.js.map +1 -0
  336. package/lib/langium/workspace/virtual-document.d.ts +49 -15
  337. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  338. package/lib/langium/workspace/virtual-document.js +81 -18
  339. package/lib/langium/workspace/virtual-document.js.map +1 -1
  340. package/lib/langium/workspace/write-lock-scope.d.ts +22 -10
  341. package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
  342. package/lib/langium/workspace/write-lock-scope.js +15 -5
  343. package/lib/langium/workspace/write-lock-scope.js.map +1 -1
  344. package/lib/launcher/integrated-server.d.ts +3 -1
  345. package/lib/launcher/integrated-server.d.ts.map +1 -1
  346. package/lib/locale/index.d.ts +10 -0
  347. package/lib/locale/index.d.ts.map +1 -0
  348. package/lib/locale/index.js +10 -0
  349. package/lib/locale/index.js.map +1 -0
  350. package/lib/locale/server-locale.d.ts +73 -0
  351. package/lib/locale/server-locale.d.ts.map +1 -0
  352. package/lib/locale/server-locale.js +61 -0
  353. package/lib/locale/server-locale.js.map +1 -0
  354. package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
  355. package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
  356. package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
  357. package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
  358. package/lib/lsp/connection-features.d.ts +23 -0
  359. package/lib/lsp/connection-features.d.ts.map +1 -0
  360. package/lib/lsp/connection-features.js +60 -0
  361. package/lib/lsp/connection-features.js.map +1 -0
  362. package/lib/lsp/diagnostics-connection.d.ts +27 -0
  363. package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
  364. package/lib/lsp/diagnostics-connection.js +53 -0
  365. package/lib/lsp/diagnostics-connection.js.map +1 -0
  366. package/lib/lsp/hydranium-document-update-handler.d.ts +106 -82
  367. package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
  368. package/lib/lsp/hydranium-document-update-handler.js +182 -102
  369. package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
  370. package/lib/lsp/index.d.ts +3 -1
  371. package/lib/lsp/index.d.ts.map +1 -1
  372. package/lib/lsp/index.js +3 -1
  373. package/lib/lsp/index.js.map +1 -1
  374. package/lib/lsp/lsp-latency.d.ts +39 -0
  375. package/lib/lsp/lsp-latency.d.ts.map +1 -0
  376. package/lib/lsp/lsp-latency.js +58 -0
  377. package/lib/lsp/lsp-latency.js.map +1 -0
  378. package/lib/lsp/semantic-token-provider.d.ts +34 -1
  379. package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
  380. package/lib/lsp/semantic-token-provider.js +55 -8
  381. package/lib/lsp/semantic-token-provider.js.map +1 -1
  382. package/lib/lsp/shared-module.d.ts +4 -8
  383. package/lib/lsp/shared-module.d.ts.map +1 -1
  384. package/lib/lsp/shared-module.js.map +1 -1
  385. package/lib/lsp/start-language-server.d.ts +8 -7
  386. package/lib/lsp/start-language-server.d.ts.map +1 -1
  387. package/lib/lsp/start-language-server.js +13 -7
  388. package/lib/lsp/start-language-server.js.map +1 -1
  389. package/lib/messages/carriers.d.ts +18 -12
  390. package/lib/messages/carriers.d.ts.map +1 -1
  391. package/lib/messages/carriers.js +22 -13
  392. package/lib/messages/carriers.js.map +1 -1
  393. package/lib/messages/index.d.ts +4 -1
  394. package/lib/messages/index.d.ts.map +1 -1
  395. package/lib/messages/index.js +4 -1
  396. package/lib/messages/index.js.map +1 -1
  397. package/lib/messages/renderer.d.ts +142 -0
  398. package/lib/messages/renderer.d.ts.map +1 -0
  399. package/lib/messages/renderer.js +165 -0
  400. package/lib/messages/renderer.js.map +1 -0
  401. package/lib/node/event-loop-monitor.d.ts.map +1 -1
  402. package/lib/node/event-loop-monitor.js +2 -1
  403. package/lib/node/event-loop-monitor.js.map +1 -1
  404. package/lib/node/heap-ceiling.d.ts +61 -0
  405. package/lib/node/heap-ceiling.d.ts.map +1 -0
  406. package/lib/node/heap-ceiling.js +72 -0
  407. package/lib/node/heap-ceiling.js.map +1 -0
  408. package/lib/node/index.d.ts +1 -1
  409. package/lib/node/index.d.ts.map +1 -1
  410. package/lib/node/index.js +1 -1
  411. package/lib/node/index.js.map +1 -1
  412. package/lib/node/latency-from-env.d.ts +1 -1
  413. package/lib/node/latency-from-env.js +1 -1
  414. package/lib/node/lint-grammar.js.map +1 -1
  415. package/lib/node/log-preamble-node.d.ts +5 -3
  416. package/lib/node/log-preamble-node.d.ts.map +1 -1
  417. package/lib/node/log-preamble-node.js +13 -10
  418. package/lib/node/log-preamble-node.js.map +1 -1
  419. package/lib/node/measure-memory.d.ts.map +1 -1
  420. package/lib/node/measure-memory.js +5 -4
  421. package/lib/node/measure-memory.js.map +1 -1
  422. package/lib/node/memory-monitor.d.ts +2 -2
  423. package/lib/node/memory-monitor.d.ts.map +1 -1
  424. package/lib/node/memory-monitor.js +9 -10
  425. package/lib/node/memory-monitor.js.map +1 -1
  426. package/lib/node/node-file-system-provider.d.ts +60 -9
  427. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  428. package/lib/node/node-file-system-provider.js +162 -52
  429. package/lib/node/node-file-system-provider.js.map +1 -1
  430. package/lib/node/profile-capture.d.ts +12 -4
  431. package/lib/node/profile-capture.d.ts.map +1 -1
  432. package/lib/node/profile-capture.js +8 -6
  433. package/lib/node/profile-capture.js.map +1 -1
  434. package/lib/node/profile-digest.js.map +1 -1
  435. package/lib/node/profiling-run.d.ts +13 -3
  436. package/lib/node/profiling-run.d.ts.map +1 -1
  437. package/lib/node/profiling-run.js +17 -8
  438. package/lib/node/profiling-run.js.map +1 -1
  439. package/lib/node/rename-over-open-readers.d.ts +61 -0
  440. package/lib/node/rename-over-open-readers.d.ts.map +1 -0
  441. package/lib/node/rename-over-open-readers.js +80 -0
  442. package/lib/node/rename-over-open-readers.js.map +1 -0
  443. package/lib/node/server-diagnostics.js +1 -1
  444. package/lib/node/server-diagnostics.js.map +1 -1
  445. package/lib/node/server-state-snapshot.js +4 -4
  446. package/lib/node/server-state-snapshot.js.map +1 -1
  447. package/lib/node/socket-launcher.d.ts +20 -4
  448. package/lib/node/socket-launcher.d.ts.map +1 -1
  449. package/lib/node/socket-launcher.js +8 -7
  450. package/lib/node/socket-launcher.js.map +1 -1
  451. package/lib/node/stdio-launcher.d.ts +10 -10
  452. package/lib/node/stdio-launcher.d.ts.map +1 -1
  453. package/lib/node/stdio-launcher.js +17 -9
  454. package/lib/node/stdio-launcher.js.map +1 -1
  455. package/lib/testing/document-uri-policy-conformance.js +1 -1
  456. package/lib/testing/document-uri-policy-conformance.js.map +1 -1
  457. package/lib/testing/fake-description.js.map +1 -1
  458. package/lib/testing/fake-document.d.ts +16 -4
  459. package/lib/testing/fake-document.d.ts.map +1 -1
  460. package/lib/testing/fake-document.js +18 -3
  461. package/lib/testing/fake-document.js.map +1 -1
  462. package/lib/testing/index.d.ts +1 -1
  463. package/lib/testing/index.d.ts.map +1 -1
  464. package/lib/testing/index.js +2 -1
  465. package/lib/testing/index.js.map +1 -1
  466. package/lib/testing/langium-test-helpers.d.ts.map +1 -1
  467. package/lib/testing/langium-test-helpers.js +1 -0
  468. package/lib/testing/langium-test-helpers.js.map +1 -1
  469. package/lib/testing/make-noop-language-services.js.map +1 -1
  470. package/lib/testing/make-noop-shared-services.d.ts +14 -0
  471. package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
  472. package/lib/testing/make-noop-shared-services.js +28 -2
  473. package/lib/testing/make-noop-shared-services.js.map +1 -1
  474. package/lib/testing/make-test-services.d.ts +72 -14
  475. package/lib/testing/make-test-services.d.ts.map +1 -1
  476. package/lib/testing/make-test-services.js +42 -10
  477. package/lib/testing/make-test-services.js.map +1 -1
  478. package/lib/testing/make-test-tracer.d.ts +12 -0
  479. package/lib/testing/make-test-tracer.d.ts.map +1 -1
  480. package/lib/testing/make-test-tracer.js +13 -0
  481. package/lib/testing/make-test-tracer.js.map +1 -1
  482. package/lib/testing/node/applied-edit-capture.d.ts +29 -0
  483. package/lib/testing/node/applied-edit-capture.d.ts.map +1 -0
  484. package/lib/testing/node/applied-edit-capture.js +115 -0
  485. package/lib/testing/node/applied-edit-capture.js.map +1 -0
  486. package/lib/testing/node/golden-corpus.js.map +1 -1
  487. package/lib/testing/node/index.d.ts +1 -0
  488. package/lib/testing/node/index.d.ts.map +1 -1
  489. package/lib/testing/node/index.js +1 -0
  490. package/lib/testing/node/index.js.map +1 -1
  491. package/lib/testing/node/lsp-harness.d.ts.map +1 -1
  492. package/lib/testing/node/lsp-harness.js +2 -0
  493. package/lib/testing/node/lsp-harness.js.map +1 -1
  494. package/lib/testing/node/lsp-server-connection.d.ts +12 -4
  495. package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
  496. package/lib/testing/node/lsp-server-connection.js +45 -106
  497. package/lib/testing/node/lsp-server-connection.js.map +1 -1
  498. package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
  499. package/lib/testing/node/scratch-workspace.js +10 -5
  500. package/lib/testing/node/scratch-workspace.js.map +1 -1
  501. package/lib/testing/node/spawned-server.d.ts +30 -1
  502. package/lib/testing/node/spawned-server.d.ts.map +1 -1
  503. package/lib/testing/node/spawned-server.js +39 -2
  504. package/lib/testing/node/spawned-server.js.map +1 -1
  505. package/lib/testing/node/unhandled-rejections.d.ts +20 -0
  506. package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
  507. package/lib/testing/node/unhandled-rejections.js +32 -0
  508. package/lib/testing/node/unhandled-rejections.js.map +1 -0
  509. package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
  510. package/lib/testing/playwright/e2e-profiling.js.map +1 -1
  511. package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
  512. package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
  513. package/lib/testing/playwright/flaky-network-proxy.js +164 -0
  514. package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
  515. package/lib/testing/playwright/index.d.ts +1 -0
  516. package/lib/testing/playwright/index.d.ts.map +1 -1
  517. package/lib/testing/playwright/index.js +1 -0
  518. package/lib/testing/playwright/index.js.map +1 -1
  519. package/lib/testing/playwright/server-log-capture.d.ts +35 -8
  520. package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
  521. package/lib/testing/playwright/server-log-capture.js +39 -6
  522. package/lib/testing/playwright/server-log-capture.js.map +1 -1
  523. package/lib/testing/playwright/server-log-fixture.d.ts +16 -0
  524. package/lib/testing/playwright/server-log-fixture.d.ts.map +1 -1
  525. package/lib/testing/playwright/server-log-fixture.js +25 -6
  526. package/lib/testing/playwright/server-log-fixture.js.map +1 -1
  527. package/lib/testing/playwright/server-log-region.d.ts +15 -0
  528. package/lib/testing/playwright/server-log-region.d.ts.map +1 -0
  529. package/lib/testing/playwright/server-log-region.js +30 -0
  530. package/lib/testing/playwright/server-log-region.js.map +1 -0
  531. package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
  532. package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
  533. package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
  534. package/lib/testing/run-update-pipeline.d.ts +6 -5
  535. package/lib/testing/run-update-pipeline.d.ts.map +1 -1
  536. package/lib/testing/run-update-pipeline.js.map +1 -1
  537. package/lib/testing/stub-ast-document-manager.d.ts +11 -52
  538. package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
  539. package/lib/testing/stub-ast-document-manager.js +31 -62
  540. package/lib/testing/stub-ast-document-manager.js.map +1 -1
  541. package/lib/testing/stub-document-builder.d.ts +33 -11
  542. package/lib/testing/stub-document-builder.d.ts.map +1 -1
  543. package/lib/testing/stub-document-builder.js +103 -5
  544. package/lib/testing/stub-document-builder.js.map +1 -1
  545. package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
  546. package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
  547. package/lib/testing/stub-hydranium-text-documents.js +132 -16
  548. package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
  549. package/lib/testing/stub-index-manager.js.map +1 -1
  550. package/lib/testing/stub-langium-documents.d.ts +3 -2
  551. package/lib/testing/stub-langium-documents.d.ts.map +1 -1
  552. package/lib/testing/stub-langium-documents.js.map +1 -1
  553. package/lib/testing/stub-model-service.d.ts +9 -8
  554. package/lib/testing/stub-model-service.d.ts.map +1 -1
  555. package/lib/testing/stub-model-service.js +6 -6
  556. package/lib/testing/stub-model-service.js.map +1 -1
  557. package/lib/testing/stub-project-manager.js.map +1 -1
  558. package/lib/testing/stub-self-save-registry.d.ts +1 -1
  559. package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
  560. package/lib/testing/stub-service-registry.d.ts +1 -1
  561. package/lib/testing/stub-service-registry.js.map +1 -1
  562. package/lib/testing/stub-writable-file-system.d.ts +1 -1
  563. package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
  564. package/lib/testing/stub-writable-file-system.js +2 -1
  565. package/lib/testing/stub-writable-file-system.js.map +1 -1
  566. package/lib/util/connection-liveness.d.ts +19 -6
  567. package/lib/util/connection-liveness.d.ts.map +1 -1
  568. package/lib/util/connection-liveness.js +61 -15
  569. package/lib/util/connection-liveness.js.map +1 -1
  570. package/lib/util/environment.d.ts.map +1 -1
  571. package/lib/util/environment.js.map +1 -1
  572. package/lib/util/registry.d.ts.map +1 -1
  573. package/package.json +29 -53
  574. package/src/documents/ast-document-manager.ts +463 -231
  575. package/src/documents/client-ids.ts +5 -22
  576. package/src/documents/client-session-errors.ts +24 -0
  577. package/src/documents/client-session-registry.ts +262 -0
  578. package/src/documents/dirty-state-tracker.ts +167 -0
  579. package/src/documents/document-release-handler.ts +404 -0
  580. package/src/documents/document-release-scheduler.ts +121 -0
  581. package/src/documents/file-system-task-queue.ts +68 -0
  582. package/src/documents/hydranium-text-documents.ts +968 -595
  583. package/src/documents/index.ts +10 -2
  584. package/src/documents/language-client-shadow.ts +452 -0
  585. package/src/documents/model-ledger.ts +66 -0
  586. package/src/documents/text-ledger.ts +112 -0
  587. package/src/documents/version-sync-service.ts +275 -0
  588. package/src/index.ts +8 -0
  589. package/src/langium/ast-extension/ast-extension-service.ts +3 -0
  590. package/src/langium/ast-extension/ast-node-builder.ts +66 -22
  591. package/src/langium/bootstrap.ts +95 -52
  592. package/src/langium/build-phase-pass/build-phase-pass-service.ts +1 -1
  593. package/src/langium/build-phase-pass/build-phase-pass.ts +1 -1
  594. package/src/langium/composite-ast-reflection.ts +112 -0
  595. package/src/langium/config/configuration-provider.ts +119 -0
  596. package/src/langium/config/index.ts +1 -0
  597. package/src/langium/diagnostics/hydranium-langium-profiler.ts +15 -39
  598. package/src/langium/diagnostics/log-preamble.ts +1 -1
  599. package/src/langium/diagnostics/logger.ts +12 -5
  600. package/src/langium/diagnostics/lsp-logger.ts +61 -16
  601. package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
  602. package/src/langium/document-builder/build-session.ts +4 -3
  603. package/src/langium/document-builder/document-builder.ts +616 -73
  604. package/src/langium/integration-services.ts +59 -28
  605. package/src/langium/integrity/integrity-rule.ts +16 -8
  606. package/src/langium/integrity/integrity-service.ts +296 -69
  607. package/src/langium/keys/containment.ts +87 -0
  608. package/src/langium/keys/index.ts +1 -0
  609. package/src/langium/keys/name-based-key-provider.ts +4 -0
  610. package/src/langium/language-module.ts +49 -8
  611. package/src/langium/model-service/client-session.ts +702 -0
  612. package/src/langium/model-service/index.ts +2 -0
  613. package/src/langium/model-service/model-events.ts +80 -0
  614. package/src/langium/model-service/model-service.ts +835 -475
  615. package/src/langium/module.ts +212 -67
  616. package/src/langium/naming/name-provider.ts +29 -7
  617. package/src/langium/naming/name-separator-validation.ts +25 -3
  618. package/src/langium/project/abstract-project-manager.ts +13 -5
  619. package/src/langium/project/project-change-event.ts +2 -2
  620. package/src/langium/residency/cst-residency-service.ts +50 -16
  621. package/src/langium/scope/fallback-scope.ts +38 -0
  622. package/src/langium/scope/hydranium-scope-computation.ts +45 -44
  623. package/src/langium/scope/hydranium-scope-provider.ts +89 -38
  624. package/src/langium/scope/index.ts +1 -0
  625. package/src/langium/scope/reference-candidate-provider.ts +6 -5
  626. package/src/langium/scope/scope-extension-service.ts +74 -59
  627. package/src/langium/scope/scoped-ast-node-description.ts +1 -3
  628. package/src/langium/serialization/abstract-serializer.ts +57 -41
  629. package/src/langium/serialization/json-serializer.ts +14 -3
  630. package/src/langium/serialization/serializer.ts +1 -1
  631. package/src/langium/serialization/yaml-serializer.ts +4 -0
  632. package/src/langium/service-registry.ts +41 -2
  633. package/src/langium/shared-services.ts +26 -6
  634. package/src/langium/single-langium-copy.ts +42 -0
  635. package/src/langium/transfer/transfer-encoder.ts +102 -45
  636. package/src/langium/trivia/comment-preserver.ts +1100 -0
  637. package/src/langium/trivia/document-ending-preserver.ts +55 -0
  638. package/src/langium/trivia/index.ts +14 -0
  639. package/src/langium/trivia/trivia-contribution.ts +39 -0
  640. package/src/langium/trivia/trivia-preserver.ts +54 -0
  641. package/src/langium/trivia/trivia-service.ts +99 -0
  642. package/src/langium/update-rewrite/update-rewrite-service.ts +1 -1
  643. package/src/langium/update-rewrite/update-rewrite.ts +1 -1
  644. package/src/langium/validation/document-validator.ts +528 -13
  645. package/src/langium/validation/validation-contribution-collector.ts +10 -1
  646. package/src/langium/workspace/document-uri-policy.ts +15 -10
  647. package/src/langium/workspace/file-not-found.ts +35 -0
  648. package/src/langium/workspace/file-system-provider.ts +234 -16
  649. package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
  650. package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
  651. package/src/langium/workspace/hydranium-workspace-manager.ts +221 -16
  652. package/src/langium/workspace/in-memory-file-system-provider.ts +54 -23
  653. package/src/langium/workspace/index.ts +1 -0
  654. package/src/langium/workspace/initialize-workspace.ts +43 -5
  655. package/src/langium/workspace/langium-documents.ts +63 -5
  656. package/src/langium/workspace/persistent-file-system-provider.ts +15 -14
  657. package/src/langium/workspace/self-save-registry.ts +118 -0
  658. package/src/langium/workspace/virtual-document.ts +100 -19
  659. package/src/langium/workspace/write-lock-scope.ts +27 -12
  660. package/src/launcher/integrated-server.ts +3 -1
  661. package/src/locale/index.ts +10 -0
  662. package/src/locale/server-locale.ts +86 -0
  663. package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
  664. package/src/lsp/connection-features.ts +67 -0
  665. package/src/lsp/diagnostics-connection.ts +56 -0
  666. package/src/lsp/hydranium-document-update-handler.ts +227 -111
  667. package/src/lsp/index.ts +3 -1
  668. package/src/lsp/lsp-latency.ts +62 -0
  669. package/src/lsp/semantic-token-provider.ts +74 -7
  670. package/src/lsp/shared-module.ts +4 -8
  671. package/src/lsp/start-language-server.ts +13 -7
  672. package/src/messages/carriers.ts +23 -15
  673. package/src/messages/index.ts +13 -1
  674. package/src/messages/renderer.ts +212 -0
  675. package/src/node/event-loop-monitor.ts +2 -1
  676. package/src/node/heap-ceiling.ts +108 -0
  677. package/src/node/index.ts +1 -1
  678. package/src/node/latency-from-env.ts +1 -1
  679. package/src/node/log-preamble-node.ts +20 -10
  680. package/src/node/measure-memory.ts +5 -4
  681. package/src/node/memory-monitor.ts +10 -10
  682. package/src/node/node-file-system-provider.ts +178 -56
  683. package/src/node/profile-capture.ts +16 -15
  684. package/src/node/profiling-run.ts +30 -8
  685. package/src/node/rename-over-open-readers.ts +94 -0
  686. package/src/node/server-diagnostics.ts +1 -1
  687. package/src/node/server-state-snapshot.ts +5 -5
  688. package/src/node/socket-launcher.ts +27 -11
  689. package/src/node/stdio-launcher.ts +22 -14
  690. package/src/testing/document-uri-policy-conformance.ts +1 -1
  691. package/src/testing/fake-document.ts +24 -5
  692. package/src/testing/index.ts +2 -1
  693. package/src/testing/langium-test-helpers.ts +1 -0
  694. package/src/testing/make-noop-shared-services.ts +50 -2
  695. package/src/testing/make-test-services.ts +125 -31
  696. package/src/testing/make-test-tracer.ts +26 -0
  697. package/src/testing/node/applied-edit-capture.ts +139 -0
  698. package/src/testing/node/index.ts +1 -0
  699. package/src/testing/node/lsp-harness.ts +2 -0
  700. package/src/testing/node/lsp-server-connection.ts +74 -117
  701. package/src/testing/node/scratch-workspace.ts +10 -5
  702. package/src/testing/node/spawned-server.ts +57 -3
  703. package/src/testing/node/unhandled-rejections.ts +31 -0
  704. package/src/testing/parse-semantic-root.ts +1 -1
  705. package/src/testing/playwright/flaky-network-proxy.ts +240 -0
  706. package/src/testing/playwright/index.ts +1 -0
  707. package/src/testing/playwright/server-log-capture.ts +63 -11
  708. package/src/testing/playwright/server-log-fixture.ts +46 -6
  709. package/src/testing/playwright/server-log-region.ts +32 -0
  710. package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
  711. package/src/testing/run-update-pipeline.ts +6 -5
  712. package/src/testing/stub-ast-document-manager.ts +47 -128
  713. package/src/testing/stub-document-builder.ts +133 -18
  714. package/src/testing/stub-hydranium-text-documents.ts +184 -27
  715. package/src/testing/stub-langium-documents.ts +3 -2
  716. package/src/testing/stub-model-service.ts +11 -10
  717. package/src/testing/stub-self-save-registry.ts +1 -1
  718. package/src/testing/stub-service-registry.ts +1 -1
  719. package/src/testing/stub-writable-file-system.ts +3 -2
  720. package/src/util/connection-liveness.ts +67 -15
  721. package/src/util/environment.ts +9 -1
  722. package/lib/documents/language-client-text-shadow.d.ts +0 -101
  723. package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
  724. package/lib/documents/language-client-text-shadow.js +0 -156
  725. package/lib/documents/language-client-text-shadow.js.map +0 -1
  726. package/lib/documents/self-save-registry.d.ts +0 -55
  727. package/lib/documents/self-save-registry.d.ts.map +0 -1
  728. package/lib/documents/self-save-registry.js.map +0 -1
  729. package/lib/lsp/instrument-connection.d.ts +0 -36
  730. package/lib/lsp/instrument-connection.d.ts.map +0 -1
  731. package/lib/lsp/instrument-connection.js +0 -62
  732. package/lib/lsp/instrument-connection.js.map +0 -1
  733. package/lib/node/process-memory.d.ts +0 -66
  734. package/lib/node/process-memory.d.ts.map +0 -1
  735. package/lib/node/process-memory.js +0 -252
  736. package/lib/node/process-memory.js.map +0 -1
  737. package/src/documents/language-client-text-shadow.ts +0 -175
  738. package/src/documents/self-save-registry.ts +0 -81
  739. package/src/lsp/instrument-connection.ts +0 -66
  740. package/src/node/process-memory.ts +0 -299
@@ -7,30 +7,35 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
- import { Debouncer, type Logger, ObservableValue, type MaybeObservableValue } from '@hydranium/protocol';
10
+ import {
11
+ Debouncer,
12
+ Deferred,
13
+ type Logger,
14
+ ObservableValue,
15
+ type MaybeObservableValue,
16
+ TIMED_OUT,
17
+ describeErrorWithStack
18
+ } from '@hydranium/protocol';
11
19
  import { URI, UriUtils } from '@hydranium/langium';
12
20
  import { DefaultDocumentUpdateHandler } from '@hydranium/langium/lsp';
13
- import { type HydraniumDocumentBuilder } from '../langium/document-builder/document-builder.js';
21
+ import { HYDRANIUM_BUILD_REASONS, type HydraniumDocumentBuilder } from '../langium/document-builder/document-builder.js';
14
22
  import { type ServerSharedServices } from '../langium/module.js';
15
23
  import { LANGUAGE_CLIENT_ID } from '../documents/client-ids.js';
16
- import { type SelfSaveRegistry } from '../documents/self-save-registry.js';
17
- import { type WritableFileSystemProvider } from '../documents/ast-document-manager.js';
24
+ import { type SelfSaveRegistry } from '../langium/workspace/self-save-registry.js';
25
+ import { type WritableFileSystemProvider } from '../langium/workspace/file-system-provider.js';
18
26
  import { type HydraniumTextDocuments } from '../documents/hydranium-text-documents.js';
19
- import { type DidChangeWatchedFilesParams, type FileEvent, FileChangeType, type TextDocumentChangeEvent } from 'vscode-languageserver';
27
+ import { isConnectionGoneError } from '../util/connection-liveness.js';
28
+ import {
29
+ type DidChangeWatchedFilesParams,
30
+ type FileEvent,
31
+ FileChangeType,
32
+ type TextDocumentChangeEvent,
33
+ type TextDocumentWillSaveEvent,
34
+ type TextEdit
35
+ } from 'vscode-languageserver';
20
36
  import { type TextDocument } from 'vscode-languageserver-textdocument';
21
37
 
22
- /**
23
- * Default LSP-event reasons stamped by {@link HydraniumDocumentUpdateHandler}
24
- * onto the next `documentBuilder.update` call via `markNextReason`. Exposed
25
- * so adopters subclassing the handler can layer additional reasons or rename
26
- * existing ones without losing the canonical names the framework emits.
27
- */
28
- export const HYDRANIUM_BUILD_REASONS = Object.freeze({
29
- didOpen: 'didOpen',
30
- didChangeContent: 'didChangeContent',
31
- didChangeWatchedFiles: 'didChangeWatchedFiles',
32
- didClose: 'didClose'
33
- } as const);
38
+ export { HYDRANIUM_BUILD_REASONS };
34
39
 
35
40
  /**
36
41
  * Construction options for {@link HydraniumDocumentUpdateHandler}.
@@ -56,6 +61,17 @@ export interface HydraniumDocumentUpdateHandlerOptions {
56
61
  * load tests).
57
62
  */
58
63
  readonly bypassNonLanguageClientChanges?: boolean;
64
+ /**
65
+ * Longest an editor's save waits on the server, in milliseconds, at each of
66
+ * its two steps: the `willSaveWaitUntil` answer waits for the server's disk
67
+ * writes of the document already queued, and server writes queued after the
68
+ * answer wait for the editor's `didSave`. Either wait that runs out is
69
+ * logged, and the editor's write and the server's can then land in either
70
+ * order. Default `1000`: VS Code gives up on an answer after about 1.5 s,
71
+ * and switches the listener off for the session once four answers, over
72
+ * all documents, timed out or failed.
73
+ */
74
+ readonly willSaveGateMs?: number;
59
75
  }
60
76
 
61
77
  /**
@@ -64,37 +80,44 @@ export interface HydraniumDocumentUpdateHandlerOptions {
64
80
  *
65
81
  * 1. **Self-save filter** ({@link filterSelfSaves}) — drops
66
82
  * watched-file-change echoes for the server's own writes via
67
- * {@link SelfSaveRegistry}, keyed by `fsPath` + mtime.
83
+ * {@link SelfSaveRegistry}, keyed by `fsPath` + mtime, and
84
+ * ({@link filterStaleDeletions}) deletions the disk contradicts.
68
85
  * 2. **Trailing-edge debouncing** — collapses rapid
69
86
  * `didChangeContent` calls into one rebuild on the trailing
70
87
  * edge of the configured window. Non-language-client author
71
88
  * changes and watched-file changes bypass the debounce (their
72
89
  * producers are already coalesced).
73
90
  * 3. **Build-reason stamping** — the LSP event overrides
74
- * (`didOpenDocument`, `didChangeContent`, `didChangeWatchedFiles`,
75
- * `didCloseDocument`) populate {@link nextReason} with a canonical
76
- * reason string. {@link fireDocumentUpdate} captures the reason;
77
- * {@link dispatch} stages it on the builder via
78
- * {@link HydraniumDocumentBuilder.markNextReason}, so a subclass that
79
- * formats build logs can tag its line with the event that caused the
80
- * build without per-adopter wiring to capture it.
81
- * 4. **Last-client-close rebuild trigger** ({@link didCloseDocument}) —
82
- * when the final client closes a document, dispatch a build so the
83
- * LangiumDocument's `textDocument` is refreshed (from disk for `file:`
84
- * URIs, or removed from the index for ephemeral URIs). Langium's
85
- * default handler does not implement `didCloseDocument`, so the
86
- * in-memory text of the last writer would otherwise persist.
91
+ * (`didOpenDocument`, `didChangeContent`, `didChangeWatchedFiles`)
92
+ * populate {@link nextReason} with a canonical reason string.
93
+ * {@link fireDocumentUpdate} captures the reason; {@link dispatch} hands
94
+ * it to {@link HydraniumDocumentBuilder.scheduleUpdate}, which stages it
95
+ * through {@link HydraniumDocumentBuilder.markNextReason} when the build
96
+ * runs, so a subclass that formats build logs can tag its line with the
97
+ * event that caused the build without per-adopter wiring to capture it.
98
+ * 4. **Editor save gate** ({@link willSaveDocumentWaitUntil}) — the editor
99
+ * writes the file itself, so the server's disk writes of that document
100
+ * are ordered around it: the editor's save waits for the ones already
101
+ * queued, and the ones queued during its save wait for its `didSave`.
102
+ * Both waits are capped by
103
+ * {@link HydraniumDocumentUpdateHandlerOptions.willSaveGateMs}.
104
+ *
105
+ * What the build keeps after a document's last close is not dispatched here:
106
+ * the store hands the released document to the `DocumentReleaseHandler` for
107
+ * every head, the LSP head included, so a `didCloseDocument` added in a
108
+ * subclass would build the document twice. A change still debounced for the
109
+ * document is dropped when the store releases it: the release handler rebuilds
110
+ * the document from the file system provider or removes it.
87
111
  *
88
112
  * Adopters with their own handler subclass should extend this class
89
113
  * (not Langium's `DefaultDocumentUpdateHandler`) so all of them are
90
114
  * preserved. The {@link dispatch} hook is the canonical override
91
- * point for adopters that need to stamp additional per-build metadata
92
- * inside the workspace-lock callback.
115
+ * point for adopters that need to stamp additional per-build metadata.
93
116
  */
94
117
  export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler {
95
118
  /**
96
119
  * Narrow Langium's `DefaultDocumentUpdateHandler.documentBuilder` typing to
97
- * the framework subclass: `markNextReason` is the only method this handler
120
+ * the framework subclass: `scheduleUpdate` is the only method this handler
98
121
  * reaches for beyond the Langium interface.
99
122
  */
100
123
  declare protected readonly documentBuilder: HydraniumDocumentBuilder;
@@ -126,13 +149,27 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
126
149
  protected nextReason?: string;
127
150
  /**
128
151
  * Build-reason captured at `fireDocumentUpdate` time, drained by
129
- * {@link dispatch} into `markNextReason`. Survives across debounced
130
- * batches (`?? pendingReason` in `fireDocumentUpdate` retains the
131
- * first reason in a coalesced burst).
152
+ * {@link dispatch} into the scheduled build. Survives across debounced
153
+ * batches: `fireDocumentUpdate` replaces it with each event's reason, so a
154
+ * coalesced burst carries its latest.
132
155
  */
133
156
  protected pendingReason?: string;
134
157
 
135
- constructor(services: ServerSharedServices, options: HydraniumDocumentUpdateHandlerOptions = {}) {
158
+ protected readonly willSaveGateMs: number;
159
+ /**
160
+ * Per document URI, the release of the hold an editor's save in progress
161
+ * keeps on the document's disk queue. A second save of the document
162
+ * releases the first: its hold would otherwise keep the second's answer
163
+ * waiting until the cap. The key is the document, not the save, so for a
164
+ * client that sends its next `willSaveWaitUntil` before the previous
165
+ * `didSave`, that late `didSave` releases the next save's hold.
166
+ */
167
+ protected readonly editorSaves = new Map<string, () => void>();
168
+
169
+ constructor(
170
+ protected readonly services: ServerSharedServices,
171
+ options: HydraniumDocumentUpdateHandlerOptions = {}
172
+ ) {
136
173
  super(services);
137
174
  this.logger = services.Logger;
138
175
  this.selfSaveRegistry = services.workspace.SelfSaveRegistry;
@@ -141,6 +178,21 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
141
178
  this.debounce = ObservableValue.from(options.debounceMs ?? 0);
142
179
  this.flushDebouncer = new Debouncer(services.Clock, () => this.flushPending(), { delayMs: this.debounce });
143
180
  this.bypassNonLanguageClientChanges = options.bypassNonLanguageClientChanges ?? true;
181
+ this.willSaveGateMs = options.willSaveGateMs ?? 1000;
182
+ this.textDocuments.onDidSaveInLanguageClient(event => this.editorSaves.get(event.uri)?.());
183
+ services.workspace.VersionSyncService.registerDeferredBuilds(
184
+ uri => this.pendingChanged.has(uri.toString()) || this.pendingDeleted.has(uri.toString())
185
+ );
186
+ // A change still debounced for a document the store has released would
187
+ // build it once more after the release handler's build: from the
188
+ // provider again, or, for a document the release removed, by reading a
189
+ // file that is not there.
190
+ this.textDocuments.onDidReleaseDocument(event => {
191
+ this.pendingChanged.delete(URI.parse(event.uri).toString());
192
+ if (this.pendingChanged.size === 0 && this.pendingDeleted.size === 0) {
193
+ this.pendingReason = undefined;
194
+ }
195
+ });
144
196
  }
145
197
 
146
198
  didOpenDocument(_change: TextDocumentChangeEvent<TextDocument>): void {
@@ -165,61 +217,24 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
165
217
  super.didChangeContent(change);
166
218
  }
167
219
 
168
- /**
169
- * Last-client close is the missing rebuild trigger in Langium's
170
- * `DefaultDocumentUpdateHandler`: `documents.onDidClose` fires on every
171
- * per-client close, but the default handler ignores the event entirely.
172
- * For multi-client servers this leaves the LangiumDocument carrying the
173
- * unsaved in-memory `textDocument` of the last writer until something
174
- * else triggers a rebuild — integrity rules walking `langiumDocuments.all`
175
- * then see stale text long after the user discarded their edits.
176
- *
177
- * We funnel the last-client transition through the same dispatch path
178
- * the other LSP events use, so the rebuild gets debouncing, workspace
179
- * locking, build-reason stamping, and `markNextReason` for free. The
180
- * scheme split governs the `DocumentBuilder.update` shape:
181
- *
182
- * - **`file:` URI** → `update([uri], [])`. Routes through
183
- * `LangiumDocuments.invalidateDocument` (doc stays in the trie) and
184
- * `LangiumDocumentFactory.update`, which consults the LSP-tracked
185
- * open-documents map first. That map is cleared LATER in the same
186
- * synchronous `notifyDidCloseTextDocument` call that fires this event,
187
- * and {@link dispatch} defers the build behind `workspaceManager.ready`
188
- * — so by the time the factory looks, the URI is gone: it falls back to
189
- * `FileSystemProvider.readFile` and the doc rebuilds from disk,
190
- * Langium's canonical close-without-save semantic. A dispatch made
191
- * synchronously here would still see the open document and re-read the
192
- * in-memory text instead.
193
- * - **non-`file:` URI** (`builtin:`, `untitled:`) → no dispatch.
194
- * Adopter-loaded schemes — documents pulled in via
195
- * `loadAdditionalDocuments` — need to stay in the workspace index;
196
- * dropping them on close would break every cross-reference that
197
- * targets them. The framework cannot enumerate adopter schemes, so the
198
- * safe default is "leave alone unless it's a file." Adopters that need
199
- * ephemeral-URI cleanup handle it explicitly.
200
- *
201
- * Per-client closes (where other clients still hold the URI) are
202
- * suppressed via {@link HydraniumTextDocuments.isOpenInAnyClient}.
203
- */
204
- didCloseDocument(change: TextDocumentChangeEvent<TextDocument>): void {
205
- if (this.textDocuments.isOpenInAnyClient(change.document.uri)) {
206
- return;
207
- }
208
- const uri = URI.parse(change.document.uri);
209
- if (uri.scheme !== 'file') {
210
- return;
211
- }
212
- this.nextReason = HYDRANIUM_BUILD_REASONS.didClose;
213
- this.immediateFlush = true;
214
- this.fireDocumentUpdate([uri], []);
215
- }
216
-
217
220
  override didChangeWatchedFiles(params: DidChangeWatchedFilesParams): void {
218
221
  void this.filterSelfSaves(params)
222
+ .then(unsaved => this.filterStaleDeletions(unsaved))
219
223
  .then(filtered => {
220
224
  if (filtered.changes.length === 0) {
221
225
  return;
222
226
  }
227
+ // Only an open document keeps the file's text as its disk
228
+ // baseline; the store ignores the rest. The self-save filter has
229
+ // dropped the server's own writes, which set the baseline when
230
+ // they wrote.
231
+ for (const change of filtered.changes) {
232
+ this.textDocuments
233
+ .reloadDiskBaseline(change.uri)
234
+ .catch((err: unknown) =>
235
+ this.logger.error(`Disk baseline not reloaded for ${change.uri}. ${describeErrorWithStack(err)}`)
236
+ );
237
+ }
223
238
  // External file-system changes are authoritative — overwrite any
224
239
  // pending reason (typically empty here; could be `didChangeContent`
225
240
  // if a watcher event raced an in-flight Monaco edit, in which case
@@ -235,12 +250,81 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
235
250
  // `unhandledRejection` listener, which reports neither the URIs nor
236
251
  // the fact that a watched-file rebuild was dropped — leaving the
237
252
  // workspace diverged from disk with no diagnostic and no retry.
238
- const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
253
+ const detail = describeErrorWithStack(err);
239
254
  const uris = params.changes.map(change => change.uri).join(', ');
240
255
  this.logger.error(`Watched-file update dropped for ${uris}. ${detail}`);
241
256
  });
242
257
  }
243
258
 
259
+ /**
260
+ * Answer an editor's `willSaveWaitUntil` with no edits once the server's
261
+ * disk writes of the document already queued have landed, or after
262
+ * {@link willSaveGateMs}, whichever is first. From the moment the queue
263
+ * reaches this save, disk tasks of the document queued behind it wait for
264
+ * the editor's `didSave`, reported through
265
+ * `HydraniumTextDocuments.onDidSaveInLanguageClient`, or for
266
+ * {@link willSaveGateMs} more.
267
+ *
268
+ * The hold is a disk task that waits only for that signal or its timer:
269
+ * waiting on a build, a save or anything else queued for the document would
270
+ * wedge its queue. Resolves in every case, since a failed request counts
271
+ * against the listener in VS Code; Langium drops the request's cancellation,
272
+ * so an abandoned request still runs to the cap. A hold that runs out is
273
+ * logged at debug only: an editor skips `didSave` for a save it cancels or
274
+ * that changed nothing.
275
+ */
276
+ willSaveDocumentWaitUntil(event: TextDocumentWillSaveEvent<TextDocument>): Promise<TextEdit[]> {
277
+ const uri = event.document.uri;
278
+ this.editorSaves.get(uri)?.();
279
+ const hold = new Deferred();
280
+ const release = (): void => {
281
+ if (this.editorSaves.get(uri) === release) {
282
+ this.editorSaves.delete(uri);
283
+ }
284
+ hold.resolve();
285
+ };
286
+ this.editorSaves.set(uri, release);
287
+ return new Promise<TextEdit[]>(resolve => {
288
+ const clock = this.services.Clock;
289
+ const cap = clock.setTimer(() => {
290
+ this.logger.warn(
291
+ `willSaveWaitUntil for ${uri} answered after ${this.willSaveGateMs} ms with server writes of it still queued; the editor's save may race them.`
292
+ );
293
+ resolve([]);
294
+ }, this.willSaveGateMs);
295
+ try {
296
+ void this.services.workspace.FileSystemTaskQueue.enqueue(uri, async () => {
297
+ cap.dispose();
298
+ resolve([]);
299
+ if ((await clock.raceTimer(hold.promise, this.willSaveGateMs)) === TIMED_OUT) {
300
+ this.logger.debug(
301
+ `No didSave for ${uri} within ${this.willSaveGateMs} ms; server writes of it no longer wait for the editor's save.`
302
+ );
303
+ release();
304
+ }
305
+ });
306
+ } catch (err) {
307
+ cap.dispose();
308
+ this.logger.error(`willSaveWaitUntil for ${uri} answered without waiting. ${describeErrorWithStack(err)}`);
309
+ release();
310
+ resolve([]);
311
+ }
312
+ });
313
+ }
314
+
315
+ /**
316
+ * Present so that Langium advertises `save` and editors send `didSave`;
317
+ * without it every hold of {@link willSaveDocumentWaitUntil} waits out its
318
+ * cap. The hold is released on
319
+ * `HydraniumTextDocuments.onDidSaveInLanguageClient` instead: it fires as
320
+ * soon as the editor reports the save, while `onDidSave`, and so this
321
+ * method, follows only once the file has been read back, and not at all
322
+ * when the file does not hold the store's text.
323
+ */
324
+ didSaveDocument(_event: TextDocumentChangeEvent<TextDocument>): void {
325
+ // Nothing to do; see the doc comment.
326
+ }
327
+
244
328
  /**
245
329
  * Drop watched-file changes whose path + mtime match a recent self-save
246
330
  * record. Deletions always pass (no mtime); stat failures pass (the
@@ -257,7 +341,7 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
257
341
  }
258
342
  const uri = UriUtils.toUri(change.uri);
259
343
  const mtimeMs = await this.fileSystemProvider.mtimeMs?.(uri);
260
- if (mtimeMs !== undefined && this.selfSaveRegistry.matches(uri.fsPath, mtimeMs)) {
344
+ if (mtimeMs !== undefined && this.selfSaveRegistry.isRegistered(uri.fsPath, mtimeMs)) {
261
345
  return undefined;
262
346
  }
263
347
  return change;
@@ -266,20 +350,45 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
266
350
  return { changes: kept.filter((change): change is FileEvent => change !== undefined) };
267
351
  }
268
352
 
353
+ /**
354
+ * Drop a deletion the disk contradicts: the file is there, or the document
355
+ * at the URI was created from a session's text and its file not seen since,
356
+ * as one created again after a delete. A watcher reports a delete late, the
357
+ * server's own included, and applied to a document created again since, it
358
+ * would close every open of it. A missing disk baseline cannot stand in for
359
+ * the creation: a report that finds the file gone clears it too. A record
360
+ * of the server's own unlinks could not tell its echo from a later real
361
+ * delete, since a delete leaves no mtime to match. A miss the provider
362
+ * reports in error keeps the deletion.
363
+ */
364
+ protected async filterStaleDeletions(params: DidChangeWatchedFilesParams): Promise<DidChangeWatchedFilesParams> {
365
+ const kept = await Promise.all(
366
+ params.changes.map(async change => {
367
+ if (change.type !== FileChangeType.Deleted) {
368
+ return change;
369
+ }
370
+ if (this.textDocuments.isUnsavedCreation(change.uri)) {
371
+ return undefined;
372
+ }
373
+ const exists = await this.fileSystemProvider.exists(UriUtils.toUri(change.uri)).catch(() => false);
374
+ return exists ? undefined : change;
375
+ })
376
+ );
377
+ return { changes: kept.filter((change): change is FileEvent => change !== undefined) };
378
+ }
379
+
269
380
  /**
270
381
  * Coalesce `changed` / `deleted` into the pending sets, then either
271
382
  * flush immediately (`immediateFlush` or `debounceMs <= 0`) or restart
272
383
  * the trailing-edge timer. Subclasses that need to stamp per-build
273
384
  * metadata can override and inspect the merged sets — but the canonical
274
- * override point for the workspace-lock callback is {@link dispatch},
275
- * not this method.
385
+ * override point for the build is {@link dispatch}, not this method.
276
386
  */
277
387
  protected override fireDocumentUpdate(changed: URI[], deleted: URI[]): void {
278
388
  // Capture the reason set by the LSP event handler immediately before
279
- // we merge into the pending sets. `?? pendingReason` keeps the
280
- // first reason in a coalesced burst (LSP events arriving inside an
281
- // active debounce window all stamp the same `pendingReason` once,
282
- // because subsequent stamps see the field already non-undefined).
389
+ // we merge into the pending sets. Each event stamps its own reason, so
390
+ // a coalesced burst carries its latest; `?? pendingReason` keeps the
391
+ // earlier one only for a call no event stamped.
283
392
  this.pendingReason = this.nextReason ?? this.pendingReason;
284
393
  this.nextReason = undefined;
285
394
  for (const uri of changed) {
@@ -317,28 +426,35 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
317
426
  }
318
427
 
319
428
  /**
320
- * Workspace-lock + `documentBuilder.update` call for the merged sets.
321
- * Mirrors Langium's `super.fireDocumentUpdate` body plus
322
- * `markNextReason(pendingReason)` inside the write-lock callback, so the
323
- * build the lock is about to run carries the LSP event that triggered it.
324
- * Adopters override to stamp additional per-build metadata — the canonical
325
- * pattern is to read the reason via `this.pendingReason`, call
326
- * `super.dispatch(...)` or replicate the
327
- * `workspaceManager.ready -> workspaceLock.write` block, and add
328
- * adopter-specific behaviour inside the write callback.
429
+ * Build the merged sets once the workspace is ready, through
430
+ * {@link HydraniumDocumentBuilder.scheduleUpdate} with the pending reason,
431
+ * so the build carries the LSP event that triggered it. A session's write
432
+ * fires the store's change event before the session rebuilds the document
433
+ * itself, and the scheduled build is what the two share.
434
+ *
435
+ * Adopters override to stamp additional per-build metadata: read the reason
436
+ * via `this.pendingReason` and call `super.dispatch(...)`; the build may
437
+ * be shared with other requests, so metadata stamped for it describes
438
+ * theirs too. An override that needs code inside the write action takes
439
+ * `workspaceLock.write` itself, as Langium's `fireDocumentUpdate` does, and
440
+ * stages the reason through `markNextReason` there; its build then cancels
441
+ * a scheduled one it coincides with rather than sharing it.
329
442
  */
330
443
  protected dispatch(changed: URI[], deleted: URI[]): void {
331
444
  const reason = this.pendingReason;
332
445
  this.pendingReason = undefined;
333
446
  this.workspaceManager.ready
334
- .then(() =>
335
- this.workspaceLock.write(token => {
336
- this.documentBuilder.markNextReason(reason);
337
- return this.documentBuilder.update(changed, deleted, token);
338
- })
339
- )
447
+ .then(() => this.documentBuilder.scheduleUpdate(changed, deleted, reason))
340
448
  .catch(err => {
341
- const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
449
+ // A deferred rebuild can finish after the LSP peer has gone away.
450
+ // Unless the head was started through `startLanguageServer`, whose
451
+ // guard absorbs it, the diagnostics publish then fails this build:
452
+ // a routine teardown race, not a failed workspace update. Keep
453
+ // genuine update failures visible.
454
+ if (isConnectionGoneError(err)) {
455
+ return;
456
+ }
457
+ const detail = describeErrorWithStack(err);
342
458
  this.logger.error(`Workspace initialization failed. Could not perform document update. ${detail}`);
343
459
  });
344
460
  }
package/src/lsp/index.ts CHANGED
@@ -8,7 +8,9 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  export * from './completion/hydranium-completion-provider.js';
11
- export * from './instrument-connection.js';
11
+ export * from './lsp-latency.js';
12
+ export * from './connection-features.js';
13
+ export * from './diagnostics-connection.js';
12
14
  export * from './semantic-token-provider.js';
13
15
  export * from './language-module.js';
14
16
  export * from './shared-module.js';
@@ -0,0 +1,62 @@
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 { LatencyCollector } from '@hydranium/protocol';
11
+ import type { ConnectionOptions, Message } from 'vscode-jsonrpc';
12
+
13
+ /**
14
+ * Connection options that time every inbound LSP message into `latency` under
15
+ * its method name — the LSP analog of the data-server RPC chokepoint.
16
+ *
17
+ * Pass the result to `createConnection` where the head builds its connection:
18
+ * `createConnection(ProposedFeatures.all, lspLatencyOptions(latency))`. The
19
+ * transport is untouched, so a head keeps whatever `--stdio` / `--socket`
20
+ * selection its arguments make.
21
+ *
22
+ * **`messageStrategy` is the seam because it is the only one the handlers
23
+ * actually pass through.** `vscode-languageserver` builds its `Connection` as an
24
+ * object whose `onHover`, `onCompletion` and every other named helper register
25
+ * against the inner protocol connection captured in their closure — not against
26
+ * the returned object's own `onRequest`. Langium registers exclusively through
27
+ * those helpers, so decorating the `Connection` reaches none of them and reports
28
+ * an empty LSP half no matter how much traffic ran. `handleMessage` sits on the
29
+ * dispatch path itself, which every request and notification crosses, so it also
30
+ * catches `initialize` — special-cased into `onInitialize` and invisible to any
31
+ * `onRequest` decoration.
32
+ *
33
+ * What it measures is **dispatch plus handler**, not handler alone: the wait a
34
+ * client actually experiences, including time queued behind other work.
35
+ *
36
+ * When `latency` is `undefined` the seam is off and this returns `undefined`, so
37
+ * a head can pass the result of an env-gated factory (`latencyFromEnv()`)
38
+ * straight through and pay nothing when timing is not enabled.
39
+ */
40
+ export function lspLatencyOptions(latency: LatencyCollector | undefined): ConnectionOptions | undefined {
41
+ if (!latency) {
42
+ return undefined;
43
+ }
44
+ return {
45
+ messageStrategy: {
46
+ handleMessage: (message: Message, next: (message: Message) => void | Promise<void>) => {
47
+ // Responses to requests the SERVER sent carry no method and are not
48
+ // work this head performed; timing them would report the client's
49
+ // latency under a name this collector cannot supply.
50
+ if (!hasMethod(message)) {
51
+ return next(message);
52
+ }
53
+ return latency.time(message.method, () => next(message));
54
+ }
55
+ }
56
+ };
57
+ }
58
+
59
+ /** Narrow to the messages that name an operation — requests and notifications. */
60
+ function hasMethod(message: Message): message is Message & { method: string } {
61
+ return typeof (message as { method?: unknown }).method === 'string';
62
+ }
@@ -14,7 +14,9 @@ import {
14
14
  CstUtils,
15
15
  GrammarAST,
16
16
  interruptAndCheck,
17
+ isLeafCstNode,
17
18
  type LangiumDocument,
19
+ type LeafCstNode,
18
20
  type ReferenceInfo
19
21
  } from '@hydranium/langium';
20
22
  import { AbstractSemanticTokenProvider, type SemanticTokenAcceptor } from '@hydranium/langium/lsp';
@@ -54,6 +56,23 @@ export interface HydraniumSemanticTokenProviderOptions {
54
56
  * render in the editor's default foreground.
55
57
  */
56
58
  readonly highlightKeywords?: boolean;
59
+
60
+ /**
61
+ * Also emit a `comment` token for every comment leaf of the CST.
62
+ *
63
+ * OFF by default for the same reason as {@link highlightKeywords}, and the
64
+ * loss is larger: a TextMate grammar distinguishes `comment.line` from
65
+ * `comment.block` and scopes the delimiters separately, where a semantic
66
+ * token carries one flat `comment` that overrides all of them. It exists
67
+ * for the host that ships no client-side grammar, where a comment otherwise
68
+ * renders in the editor's default foreground.
69
+ *
70
+ * What counts as a comment is every hidden terminal the lexer retains,
71
+ * which is every hidden terminal whose pattern is not whitespace. A grammar
72
+ * whose hidden non-whitespace terminal means something other than a comment
73
+ * is miscoloured, and this option is the place to say no.
74
+ */
75
+ readonly highlightComments?: boolean;
57
76
  }
58
77
 
59
78
  /**
@@ -133,7 +152,9 @@ export abstract class AbstractHydraniumSemanticTokenProvider extends AbstractSem
133
152
  cancelToken: CancellationToken
134
153
  ): Promise<void> {
135
154
  await super.computeHighlighting(document, acceptor, cancelToken);
136
- if (this.options.highlightKeywords !== true) {
155
+ const keywords = this.options.highlightKeywords === true;
156
+ const comments = this.options.highlightComments === true;
157
+ if (!keywords && !comments) {
137
158
  return;
138
159
  }
139
160
  const root = document.parseResult.value.$cstNode;
@@ -142,14 +163,60 @@ export abstract class AbstractHydraniumSemanticTokenProvider extends AbstractSem
142
163
  }
143
164
  for (const cst of CstUtils.streamCst(root)) {
144
165
  await interruptAndCheck(cancelToken);
145
- // The grammar source is the whole filter. A keyword is always a leaf,
146
- // and the hidden leaves a comment or a run of whitespace contributes
147
- // are sourced from a terminal rule rather than a `Keyword` — so
148
- // neither a composite-node check nor a hidden-token check adds
149
- // anything here.
150
- if (GrammarAST.isKeyword(cst.grammarSource)) {
166
+ // A keyword is always a leaf with a `Keyword` grammar source, so that
167
+ // check alone separates it from everything else in the walk.
168
+ if (keywords && GrammarAST.isKeyword(cst.grammarSource)) {
151
169
  acceptor({ cst, type: SemanticTokenTypes.keyword });
152
170
  }
171
+ // A comment leaf cannot be recognised the same way — the CST builder
172
+ // adds hidden nodes from the token alone, so `grammarSource` is
173
+ // undefined, which is also why the keyword filter never matches one.
174
+ //
175
+ // `hidden` alone IS the comment test, and nothing narrower is needed:
176
+ // the token builder groups a hidden terminal as `Lexer.SKIPPED` when
177
+ // its pattern matches whitespace and as `hidden` otherwise, so the
178
+ // lexer discards whitespace before a CST node is ever built and every
179
+ // hidden leaf that survives is a comment. Classifying the terminal
180
+ // again here would be a second guard for the same property, which no
181
+ // test could then distinguish. An adopter whose token builder RETAINS
182
+ // whitespace breaks that equivalence and would colour its gaps.
183
+ if (comments && isLeafCstNode(cst) && cst.hidden) {
184
+ this.acceptComment(cst, acceptor);
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Emit a comment as ONE TOKEN PER LINE, never as one multi-line range.
191
+ *
192
+ * A block comment is the first token this provider emits that can span
193
+ * lines, and the upstream encoder mishandles that for a client which does
194
+ * not advertise `multilineTokenSupport` — the split path computes the first
195
+ * line's length as `nextLineOffset - range.start.character - 1`, subtracting
196
+ * a COLUMN from a document OFFSET, so the length is right only for a token
197
+ * starting on line 0 and overruns its line everywhere else. No client in
198
+ * this repository advertises that capability, so the broken path is the one
199
+ * taken. Splitting here means every range handed over starts and ends on one
200
+ * line and the arithmetic is never reached.
201
+ *
202
+ * Lines come from the leaf's own text rather than from the document, so
203
+ * nothing has to re-derive where the comment ends.
204
+ */
205
+ protected acceptComment(cst: LeafCstNode, acceptor: SemanticTokenAcceptor): void {
206
+ const lines = cst.text.split('\n');
207
+ for (let index = 0; index < lines.length; index++) {
208
+ // A `\r\n` document leaves the carriage return on the line's end;
209
+ // colouring it would extend the token past the visible text.
210
+ const length = lines[index].replace(/\r$/, '').length;
211
+ const character = index === 0 ? cst.range.start.character : 0;
212
+ if (length === 0) {
213
+ continue;
214
+ }
215
+ const line = cst.range.start.line + index;
216
+ acceptor({
217
+ range: { start: { line, character }, end: { line, character: character + length } },
218
+ type: SemanticTokenTypes.comment
219
+ });
153
220
  }
154
221
  }
155
222