@hydranium/core 1.0.0-next.31 → 1.0.0-next.313

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 (769) hide show
  1. package/README.md +78 -82
  2. package/lib/browser/host-heads-in-worker.d.ts +77 -0
  3. package/lib/browser/host-heads-in-worker.d.ts.map +1 -0
  4. package/lib/browser/host-heads-in-worker.js +169 -0
  5. package/lib/browser/host-heads-in-worker.js.map +1 -0
  6. package/lib/browser/index.d.ts +12 -0
  7. package/lib/browser/index.d.ts.map +1 -0
  8. package/lib/browser/index.js +17 -0
  9. package/lib/browser/index.js.map +1 -0
  10. package/lib/browser/indexeddb-file-system-store.d.ts +82 -0
  11. package/lib/browser/indexeddb-file-system-store.d.ts.map +1 -0
  12. package/lib/browser/indexeddb-file-system-store.js +181 -0
  13. package/lib/browser/indexeddb-file-system-store.js.map +1 -0
  14. package/lib/browser/start-language-server-in-worker.d.ts +32 -0
  15. package/lib/browser/start-language-server-in-worker.d.ts.map +1 -0
  16. package/lib/browser/start-language-server-in-worker.js +40 -0
  17. package/lib/browser/start-language-server-in-worker.js.map +1 -0
  18. package/lib/documents/ast-document-manager.d.ts +256 -124
  19. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  20. package/lib/documents/ast-document-manager.js +293 -132
  21. package/lib/documents/ast-document-manager.js.map +1 -1
  22. package/lib/documents/client-ids.d.ts +5 -19
  23. package/lib/documents/client-ids.d.ts.map +1 -1
  24. package/lib/documents/client-ids.js +5 -19
  25. package/lib/documents/client-ids.js.map +1 -1
  26. package/lib/documents/client-session-errors.d.ts +15 -0
  27. package/lib/documents/client-session-errors.d.ts.map +1 -0
  28. package/lib/documents/client-session-errors.js +15 -0
  29. package/lib/documents/client-session-errors.js.map +1 -0
  30. package/lib/documents/client-session-registry.d.ts +146 -0
  31. package/lib/documents/client-session-registry.d.ts.map +1 -0
  32. package/lib/documents/client-session-registry.js +207 -0
  33. package/lib/documents/client-session-registry.js.map +1 -0
  34. package/lib/documents/dirty-state-tracker.d.ts +101 -0
  35. package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
  36. package/lib/documents/dirty-state-tracker.js +85 -0
  37. package/lib/documents/dirty-state-tracker.js.map +1 -0
  38. package/lib/documents/document-release-handler.d.ts +204 -0
  39. package/lib/documents/document-release-handler.d.ts.map +1 -0
  40. package/lib/documents/document-release-handler.js +317 -0
  41. package/lib/documents/document-release-handler.js.map +1 -0
  42. package/lib/documents/document-release-scheduler.d.ts +67 -0
  43. package/lib/documents/document-release-scheduler.d.ts.map +1 -0
  44. package/lib/documents/document-release-scheduler.js +80 -0
  45. package/lib/documents/document-release-scheduler.js.map +1 -0
  46. package/lib/documents/file-system-task-queue.d.ts +52 -0
  47. package/lib/documents/file-system-task-queue.d.ts.map +1 -0
  48. package/lib/documents/file-system-task-queue.js +37 -0
  49. package/lib/documents/file-system-task-queue.js.map +1 -0
  50. package/lib/documents/hydranium-text-documents.d.ts +436 -282
  51. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  52. package/lib/documents/hydranium-text-documents.js +897 -483
  53. package/lib/documents/hydranium-text-documents.js.map +1 -1
  54. package/lib/documents/index.d.ts +10 -2
  55. package/lib/documents/index.d.ts.map +1 -1
  56. package/lib/documents/index.js +10 -2
  57. package/lib/documents/index.js.map +1 -1
  58. package/lib/documents/language-client-shadow.d.ts +234 -0
  59. package/lib/documents/language-client-shadow.d.ts.map +1 -0
  60. package/lib/documents/language-client-shadow.js +306 -0
  61. package/lib/documents/language-client-shadow.js.map +1 -0
  62. package/lib/documents/model-ledger.d.ts +47 -0
  63. package/lib/documents/model-ledger.d.ts.map +1 -0
  64. package/lib/documents/model-ledger.js +30 -0
  65. package/lib/documents/model-ledger.js.map +1 -0
  66. package/lib/documents/text-ledger.d.ts +64 -0
  67. package/lib/documents/text-ledger.d.ts.map +1 -0
  68. package/lib/documents/text-ledger.js +63 -0
  69. package/lib/documents/text-ledger.js.map +1 -0
  70. package/lib/documents/version-sync-service.d.ts +138 -0
  71. package/lib/documents/version-sync-service.d.ts.map +1 -0
  72. package/lib/documents/version-sync-service.js +173 -0
  73. package/lib/documents/version-sync-service.js.map +1 -0
  74. package/lib/index.d.ts +5 -0
  75. package/lib/index.d.ts.map +1 -1
  76. package/lib/index.js +8 -0
  77. package/lib/index.js.map +1 -1
  78. package/lib/langium/ast-extension/ast-extension-service.d.ts +42 -31
  79. package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
  80. package/lib/langium/ast-extension/ast-extension-service.js +45 -19
  81. package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
  82. package/lib/langium/bootstrap.d.ts +49 -36
  83. package/lib/langium/bootstrap.d.ts.map +1 -1
  84. package/lib/langium/bootstrap.js +91 -45
  85. package/lib/langium/bootstrap.js.map +1 -1
  86. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts +9 -9
  87. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
  88. package/lib/langium/build-phase-pass/build-phase-pass-service.js +25 -16
  89. package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
  90. package/lib/langium/build-phase-pass/build-phase-pass.d.ts +20 -8
  91. package/lib/langium/build-phase-pass/build-phase-pass.d.ts.map +1 -1
  92. package/lib/langium/build-phase-pass/build-phase-pass.js +20 -0
  93. package/lib/langium/build-phase-pass/build-phase-pass.js.map +1 -1
  94. package/lib/langium/composite-ast-reflection.d.ts +46 -0
  95. package/lib/langium/composite-ast-reflection.d.ts.map +1 -0
  96. package/lib/langium/composite-ast-reflection.js +97 -0
  97. package/lib/langium/composite-ast-reflection.js.map +1 -0
  98. package/lib/langium/config/configuration-provider.d.ts +81 -0
  99. package/lib/langium/config/configuration-provider.d.ts.map +1 -0
  100. package/lib/langium/config/configuration-provider.js +112 -0
  101. package/lib/langium/config/configuration-provider.js.map +1 -0
  102. package/lib/langium/config/index.d.ts +1 -0
  103. package/lib/langium/config/index.d.ts.map +1 -1
  104. package/lib/langium/config/index.js +1 -0
  105. package/lib/langium/config/index.js.map +1 -1
  106. package/lib/langium/config/settings.js.map +1 -1
  107. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts +9 -20
  108. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
  109. package/lib/langium/diagnostics/hydranium-langium-profiler.js +15 -24
  110. package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
  111. package/lib/langium/diagnostics/log-preamble.js +1 -1
  112. package/lib/langium/diagnostics/log-preamble.js.map +1 -1
  113. package/lib/langium/diagnostics/logger.d.ts +19 -4
  114. package/lib/langium/diagnostics/logger.d.ts.map +1 -1
  115. package/lib/langium/diagnostics/logger.js +36 -11
  116. package/lib/langium/diagnostics/logger.js.map +1 -1
  117. package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
  118. package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
  119. package/lib/langium/diagnostics/lsp-logger.js +58 -17
  120. package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
  121. package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
  122. package/lib/langium/diagnostics/server-tracer.js.map +1 -1
  123. package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
  124. package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
  125. package/lib/langium/document-builder/build-pipeline-integration.js +28 -30
  126. package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
  127. package/lib/langium/document-builder/build-session.d.ts +6 -5
  128. package/lib/langium/document-builder/build-session.d.ts.map +1 -1
  129. package/lib/langium/document-builder/build-session.js +5 -5
  130. package/lib/langium/document-builder/build-session.js.map +1 -1
  131. package/lib/langium/document-builder/document-builder.d.ts +309 -35
  132. package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
  133. package/lib/langium/document-builder/document-builder.js +511 -75
  134. package/lib/langium/document-builder/document-builder.js.map +1 -1
  135. package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
  136. package/lib/langium/documentation/comment-provider.js.map +1 -1
  137. package/lib/langium/integration-services.d.ts +40 -24
  138. package/lib/langium/integration-services.d.ts.map +1 -1
  139. package/lib/langium/integration-services.js +7 -4
  140. package/lib/langium/integration-services.js.map +1 -1
  141. package/lib/langium/integrity/integrity-rule.d.ts +16 -8
  142. package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
  143. package/lib/langium/integrity/integrity-rule.js.map +1 -1
  144. package/lib/langium/integrity/integrity-service.d.ts +83 -27
  145. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  146. package/lib/langium/integrity/integrity-service.js +273 -63
  147. package/lib/langium/integrity/integrity-service.js.map +1 -1
  148. package/lib/langium/keys/containment.d.ts +64 -0
  149. package/lib/langium/keys/containment.d.ts.map +1 -0
  150. package/lib/langium/keys/containment.js +53 -0
  151. package/lib/langium/keys/containment.js.map +1 -0
  152. package/lib/langium/keys/index.d.ts +1 -0
  153. package/lib/langium/keys/index.d.ts.map +1 -1
  154. package/lib/langium/keys/index.js +1 -0
  155. package/lib/langium/keys/index.js.map +1 -1
  156. package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
  157. package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
  158. package/lib/langium/keys/name-based-key-provider.js +4 -0
  159. package/lib/langium/keys/name-based-key-provider.js.map +1 -1
  160. package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
  161. package/lib/langium/keys/positional-key-provider.js.map +1 -1
  162. package/lib/langium/labeling/label-provider.d.ts.map +1 -1
  163. package/lib/langium/labeling/label-provider.js.map +1 -1
  164. package/lib/langium/language-module.d.ts +30 -5
  165. package/lib/langium/language-module.d.ts.map +1 -1
  166. package/lib/langium/language-module.js +18 -4
  167. package/lib/langium/language-module.js.map +1 -1
  168. package/lib/langium/model-service/client-session.d.ts +383 -0
  169. package/lib/langium/model-service/client-session.d.ts.map +1 -0
  170. package/lib/langium/model-service/client-session.js +455 -0
  171. package/lib/langium/model-service/client-session.js.map +1 -0
  172. package/lib/langium/model-service/index.d.ts +2 -0
  173. package/lib/langium/model-service/index.d.ts.map +1 -1
  174. package/lib/langium/model-service/index.js +2 -0
  175. package/lib/langium/model-service/index.js.map +1 -1
  176. package/lib/langium/model-service/model-events.d.ts +66 -0
  177. package/lib/langium/model-service/model-events.d.ts.map +1 -0
  178. package/lib/langium/model-service/model-events.js +10 -0
  179. package/lib/langium/model-service/model-events.js.map +1 -0
  180. package/lib/langium/model-service/model-service.d.ts +480 -289
  181. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  182. package/lib/langium/model-service/model-service.js +597 -456
  183. package/lib/langium/model-service/model-service.js.map +1 -1
  184. package/lib/langium/module.d.ts +158 -37
  185. package/lib/langium/module.d.ts.map +1 -1
  186. package/lib/langium/module.js +52 -36
  187. package/lib/langium/module.js.map +1 -1
  188. package/lib/langium/naming/name-provider.d.ts +42 -7
  189. package/lib/langium/naming/name-provider.d.ts.map +1 -1
  190. package/lib/langium/naming/name-provider.js +10 -4
  191. package/lib/langium/naming/name-provider.js.map +1 -1
  192. package/lib/langium/naming/name-separator-validation.d.ts +23 -1
  193. package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
  194. package/lib/langium/naming/name-separator-validation.js +22 -0
  195. package/lib/langium/naming/name-separator-validation.js.map +1 -1
  196. package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
  197. package/lib/langium/project/abstract-project-manager.js +13 -6
  198. package/lib/langium/project/abstract-project-manager.js.map +1 -1
  199. package/lib/langium/project/project-change-event.d.ts +2 -2
  200. package/lib/langium/project/single-project-manager.d.ts.map +1 -1
  201. package/lib/langium/project/single-project-manager.js.map +1 -1
  202. package/lib/langium/residency/cst-residency-service.d.ts +38 -14
  203. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  204. package/lib/langium/residency/cst-residency-service.js +24 -58
  205. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  206. package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
  207. package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
  208. package/lib/langium/scope/fallback-scope.d.ts +27 -0
  209. package/lib/langium/scope/fallback-scope.d.ts.map +1 -0
  210. package/lib/langium/scope/fallback-scope.js +35 -0
  211. package/lib/langium/scope/fallback-scope.js.map +1 -0
  212. package/lib/langium/scope/hydranium-scope-computation.d.ts +21 -18
  213. package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
  214. package/lib/langium/scope/hydranium-scope-computation.js +38 -39
  215. package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
  216. package/lib/langium/scope/hydranium-scope-provider.d.ts +29 -11
  217. package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
  218. package/lib/langium/scope/hydranium-scope-provider.js +37 -15
  219. package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
  220. package/lib/langium/scope/index.d.ts +1 -0
  221. package/lib/langium/scope/index.d.ts.map +1 -1
  222. package/lib/langium/scope/index.js +1 -0
  223. package/lib/langium/scope/index.js.map +1 -1
  224. package/lib/langium/scope/reference-builder.d.ts.map +1 -1
  225. package/lib/langium/scope/reference-builder.js.map +1 -1
  226. package/lib/langium/scope/reference-candidate-provider.d.ts +6 -5
  227. package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
  228. package/lib/langium/scope/reference-candidate-provider.js +3 -2
  229. package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
  230. package/lib/langium/scope/scope-extension-service.d.ts +41 -37
  231. package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
  232. package/lib/langium/scope/scope-extension-service.js +57 -29
  233. package/lib/langium/scope/scope-extension-service.js.map +1 -1
  234. package/lib/langium/scope/scoped-ast-node-description.d.ts +1 -3
  235. package/lib/langium/scope/scoped-ast-node-description.d.ts.map +1 -1
  236. package/lib/langium/scope/scoped-ast-node-description.js +1 -3
  237. package/lib/langium/scope/scoped-ast-node-description.js.map +1 -1
  238. package/lib/langium/serialization/abstract-serializer.d.ts +38 -27
  239. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  240. package/lib/langium/serialization/abstract-serializer.js +54 -30
  241. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  242. package/lib/langium/serialization/json-serializer.d.ts +8 -1
  243. package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
  244. package/lib/langium/serialization/json-serializer.js +13 -3
  245. package/lib/langium/serialization/json-serializer.js.map +1 -1
  246. package/lib/langium/serialization/serializer.d.ts +1 -1
  247. package/lib/langium/serialization/yaml-serializer.d.ts +4 -0
  248. package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
  249. package/lib/langium/serialization/yaml-serializer.js +4 -0
  250. package/lib/langium/serialization/yaml-serializer.js.map +1 -1
  251. package/lib/langium/service-registry.d.ts +29 -1
  252. package/lib/langium/service-registry.d.ts.map +1 -1
  253. package/lib/langium/service-registry.js +37 -0
  254. package/lib/langium/service-registry.js.map +1 -1
  255. package/lib/langium/shared-services.d.ts +23 -6
  256. package/lib/langium/shared-services.d.ts.map +1 -1
  257. package/lib/langium/shared-services.js.map +1 -1
  258. package/lib/langium/single-langium-copy.d.ts +22 -0
  259. package/lib/langium/single-langium-copy.d.ts.map +1 -0
  260. package/lib/langium/single-langium-copy.js +36 -0
  261. package/lib/langium/single-langium-copy.js.map +1 -0
  262. package/lib/langium/transfer/transfer-encoder.d.ts +84 -35
  263. package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
  264. package/lib/langium/transfer/transfer-encoder.js +34 -23
  265. package/lib/langium/transfer/transfer-encoder.js.map +1 -1
  266. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  267. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  268. package/lib/langium/trivia/comment-preserver.js +906 -0
  269. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  270. package/lib/langium/trivia/document-ending-preserver.d.ts +51 -0
  271. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  272. package/lib/langium/trivia/document-ending-preserver.js +62 -0
  273. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  274. package/lib/langium/trivia/index.d.ts +14 -0
  275. package/lib/langium/trivia/index.d.ts.map +1 -0
  276. package/lib/langium/trivia/index.js +14 -0
  277. package/lib/langium/trivia/index.js.map +1 -0
  278. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  279. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  280. package/lib/langium/trivia/trivia-contribution.js +10 -0
  281. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  282. package/lib/langium/trivia/trivia-preserver.d.ts +52 -0
  283. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  284. package/lib/langium/trivia/trivia-preserver.js +10 -0
  285. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  286. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  287. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  288. package/lib/langium/trivia/trivia-service.js +56 -0
  289. package/lib/langium/trivia/trivia-service.js.map +1 -0
  290. package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
  291. package/lib/langium/update-rewrite/update-rewrite-service.d.ts +1 -1
  292. package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
  293. package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
  294. package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
  295. package/lib/langium/validation/document-validator.d.ts +280 -9
  296. package/lib/langium/validation/document-validator.d.ts.map +1 -1
  297. package/lib/langium/validation/document-validator.js +453 -8
  298. package/lib/langium/validation/document-validator.js.map +1 -1
  299. package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
  300. package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
  301. package/lib/langium/validation/validation-contribution-collector.js +1 -1
  302. package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
  303. package/lib/langium/workspace/document-uri-policy.d.ts +24 -15
  304. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  305. package/lib/langium/workspace/document-uri-policy.js +22 -13
  306. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  307. package/lib/langium/workspace/file-not-found.d.ts +23 -0
  308. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  309. package/lib/langium/workspace/file-not-found.js +31 -0
  310. package/lib/langium/workspace/file-not-found.js.map +1 -0
  311. package/lib/langium/workspace/file-system-provider.d.ts +167 -8
  312. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  313. package/lib/langium/workspace/file-system-provider.js +115 -13
  314. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  315. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +31 -1
  316. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
  317. package/lib/langium/workspace/hydranium-langium-document-factory.js +54 -0
  318. package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
  319. package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
  320. package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
  321. package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
  322. package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
  323. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +124 -22
  324. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  325. package/lib/langium/workspace/hydranium-workspace-manager.js +212 -31
  326. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  327. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -9
  328. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  329. package/lib/langium/workspace/in-memory-file-system-provider.js +45 -22
  330. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  331. package/lib/langium/workspace/index-manager.d.ts.map +1 -1
  332. package/lib/langium/workspace/index-manager.js.map +1 -1
  333. package/lib/langium/workspace/index.d.ts +1 -0
  334. package/lib/langium/workspace/index.d.ts.map +1 -1
  335. package/lib/langium/workspace/index.js +1 -0
  336. package/lib/langium/workspace/index.js.map +1 -1
  337. package/lib/langium/workspace/initialize-workspace.d.ts +61 -4
  338. package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
  339. package/lib/langium/workspace/initialize-workspace.js +80 -7
  340. package/lib/langium/workspace/initialize-workspace.js.map +1 -1
  341. package/lib/langium/workspace/langium-documents.d.ts +7 -0
  342. package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
  343. package/lib/langium/workspace/langium-documents.js +18 -1
  344. package/lib/langium/workspace/langium-documents.js.map +1 -1
  345. package/lib/langium/workspace/persistent-file-system-provider.d.ts +16 -10
  346. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  347. package/lib/langium/workspace/persistent-file-system-provider.js +25 -13
  348. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  349. package/lib/langium/workspace/self-save-registry.d.ts +84 -0
  350. package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
  351. package/lib/{documents → langium/workspace}/self-save-registry.js +33 -22
  352. package/lib/langium/workspace/self-save-registry.js.map +1 -0
  353. package/lib/langium/workspace/virtual-document.d.ts +55 -21
  354. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  355. package/lib/langium/workspace/virtual-document.js +87 -24
  356. package/lib/langium/workspace/virtual-document.js.map +1 -1
  357. package/lib/langium/workspace/write-lock-scope.d.ts +22 -10
  358. package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
  359. package/lib/langium/workspace/write-lock-scope.js +15 -5
  360. package/lib/langium/workspace/write-lock-scope.js.map +1 -1
  361. package/lib/launcher/integrated-server.d.ts +3 -1
  362. package/lib/launcher/integrated-server.d.ts.map +1 -1
  363. package/lib/locale/index.d.ts +10 -0
  364. package/lib/locale/index.d.ts.map +1 -0
  365. package/lib/locale/index.js +10 -0
  366. package/lib/locale/index.js.map +1 -0
  367. package/lib/locale/server-locale.d.ts +73 -0
  368. package/lib/locale/server-locale.d.ts.map +1 -0
  369. package/lib/locale/server-locale.js +61 -0
  370. package/lib/locale/server-locale.js.map +1 -0
  371. package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
  372. package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
  373. package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
  374. package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
  375. package/lib/lsp/connection-features.d.ts +23 -0
  376. package/lib/lsp/connection-features.d.ts.map +1 -0
  377. package/lib/lsp/connection-features.js +60 -0
  378. package/lib/lsp/connection-features.js.map +1 -0
  379. package/lib/lsp/diagnostics-connection.d.ts +27 -0
  380. package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
  381. package/lib/lsp/diagnostics-connection.js +53 -0
  382. package/lib/lsp/diagnostics-connection.js.map +1 -0
  383. package/lib/lsp/hydranium-document-update-handler.d.ts +126 -82
  384. package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
  385. package/lib/lsp/hydranium-document-update-handler.js +235 -102
  386. package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
  387. package/lib/lsp/index.d.ts +4 -1
  388. package/lib/lsp/index.d.ts.map +1 -1
  389. package/lib/lsp/index.js +4 -1
  390. package/lib/lsp/index.js.map +1 -1
  391. package/lib/lsp/lsp-latency.d.ts +39 -0
  392. package/lib/lsp/lsp-latency.d.ts.map +1 -0
  393. package/lib/lsp/lsp-latency.js +58 -0
  394. package/lib/lsp/lsp-latency.js.map +1 -0
  395. package/lib/lsp/save-text-document.d.ts +31 -0
  396. package/lib/lsp/save-text-document.d.ts.map +1 -0
  397. package/lib/lsp/save-text-document.js +52 -0
  398. package/lib/lsp/save-text-document.js.map +1 -0
  399. package/lib/lsp/semantic-token-provider.d.ts +34 -1
  400. package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
  401. package/lib/lsp/semantic-token-provider.js +55 -8
  402. package/lib/lsp/semantic-token-provider.js.map +1 -1
  403. package/lib/lsp/shared-module.d.ts +4 -8
  404. package/lib/lsp/shared-module.d.ts.map +1 -1
  405. package/lib/lsp/shared-module.js.map +1 -1
  406. package/lib/lsp/start-language-server.d.ts +8 -7
  407. package/lib/lsp/start-language-server.d.ts.map +1 -1
  408. package/lib/lsp/start-language-server.js +13 -7
  409. package/lib/lsp/start-language-server.js.map +1 -1
  410. package/lib/messages/carriers.d.ts +18 -12
  411. package/lib/messages/carriers.d.ts.map +1 -1
  412. package/lib/messages/carriers.js +22 -13
  413. package/lib/messages/carriers.js.map +1 -1
  414. package/lib/messages/index.d.ts +4 -1
  415. package/lib/messages/index.d.ts.map +1 -1
  416. package/lib/messages/index.js +4 -1
  417. package/lib/messages/index.js.map +1 -1
  418. package/lib/messages/renderer.d.ts +142 -0
  419. package/lib/messages/renderer.d.ts.map +1 -0
  420. package/lib/messages/renderer.js +165 -0
  421. package/lib/messages/renderer.js.map +1 -0
  422. package/lib/node/event-loop-monitor.d.ts.map +1 -1
  423. package/lib/node/event-loop-monitor.js +2 -1
  424. package/lib/node/event-loop-monitor.js.map +1 -1
  425. package/lib/node/heap-ceiling.d.ts +61 -0
  426. package/lib/node/heap-ceiling.d.ts.map +1 -0
  427. package/lib/node/heap-ceiling.js +72 -0
  428. package/lib/node/heap-ceiling.js.map +1 -0
  429. package/lib/node/index.d.ts +1 -1
  430. package/lib/node/index.d.ts.map +1 -1
  431. package/lib/node/index.js +5 -1
  432. package/lib/node/index.js.map +1 -1
  433. package/lib/node/latency-from-env.d.ts +1 -1
  434. package/lib/node/latency-from-env.js +1 -1
  435. package/lib/node/lint-grammar.js.map +1 -1
  436. package/lib/node/log-preamble-node.d.ts +5 -3
  437. package/lib/node/log-preamble-node.d.ts.map +1 -1
  438. package/lib/node/log-preamble-node.js +13 -10
  439. package/lib/node/log-preamble-node.js.map +1 -1
  440. package/lib/node/measure-memory.d.ts.map +1 -1
  441. package/lib/node/measure-memory.js +5 -4
  442. package/lib/node/measure-memory.js.map +1 -1
  443. package/lib/node/memory-monitor.d.ts +2 -2
  444. package/lib/node/memory-monitor.d.ts.map +1 -1
  445. package/lib/node/memory-monitor.js +9 -10
  446. package/lib/node/memory-monitor.js.map +1 -1
  447. package/lib/node/node-file-system-provider.d.ts +67 -9
  448. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  449. package/lib/node/node-file-system-provider.js +198 -53
  450. package/lib/node/node-file-system-provider.js.map +1 -1
  451. package/lib/node/profile-capture.d.ts +12 -4
  452. package/lib/node/profile-capture.d.ts.map +1 -1
  453. package/lib/node/profile-capture.js +8 -6
  454. package/lib/node/profile-capture.js.map +1 -1
  455. package/lib/node/profile-digest.js.map +1 -1
  456. package/lib/node/profiling-run.d.ts +13 -3
  457. package/lib/node/profiling-run.d.ts.map +1 -1
  458. package/lib/node/profiling-run.js +17 -8
  459. package/lib/node/profiling-run.js.map +1 -1
  460. package/lib/node/rename-over-open-readers.d.ts +61 -0
  461. package/lib/node/rename-over-open-readers.d.ts.map +1 -0
  462. package/lib/node/rename-over-open-readers.js +80 -0
  463. package/lib/node/rename-over-open-readers.js.map +1 -0
  464. package/lib/node/server-diagnostics.js +1 -1
  465. package/lib/node/server-diagnostics.js.map +1 -1
  466. package/lib/node/server-state-snapshot.js +4 -4
  467. package/lib/node/server-state-snapshot.js.map +1 -1
  468. package/lib/node/socket-launcher.d.ts +43 -7
  469. package/lib/node/socket-launcher.d.ts.map +1 -1
  470. package/lib/node/socket-launcher.js +42 -7
  471. package/lib/node/socket-launcher.js.map +1 -1
  472. package/lib/node/startup-cpu-profile.d.ts +29 -0
  473. package/lib/node/startup-cpu-profile.d.ts.map +1 -0
  474. package/lib/node/startup-cpu-profile.js +91 -0
  475. package/lib/node/startup-cpu-profile.js.map +1 -0
  476. package/lib/node/stdio-launcher.d.ts +13 -13
  477. package/lib/node/stdio-launcher.d.ts.map +1 -1
  478. package/lib/node/stdio-launcher.js +21 -11
  479. package/lib/node/stdio-launcher.js.map +1 -1
  480. package/lib/testing/document-uri-policy-conformance.js +1 -1
  481. package/lib/testing/document-uri-policy-conformance.js.map +1 -1
  482. package/lib/testing/fake-description.js.map +1 -1
  483. package/lib/testing/fake-document.d.ts +2 -1
  484. package/lib/testing/fake-document.d.ts.map +1 -1
  485. package/lib/testing/fake-document.js.map +1 -1
  486. package/lib/testing/index.d.ts +1 -1
  487. package/lib/testing/index.d.ts.map +1 -1
  488. package/lib/testing/index.js +2 -1
  489. package/lib/testing/index.js.map +1 -1
  490. package/lib/testing/langium-test-helpers.d.ts.map +1 -1
  491. package/lib/testing/langium-test-helpers.js +1 -0
  492. package/lib/testing/langium-test-helpers.js.map +1 -1
  493. package/lib/testing/make-noop-language-services.js.map +1 -1
  494. package/lib/testing/make-noop-shared-services.d.ts +14 -0
  495. package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
  496. package/lib/testing/make-noop-shared-services.js +28 -2
  497. package/lib/testing/make-noop-shared-services.js.map +1 -1
  498. package/lib/testing/make-test-services.d.ts +72 -14
  499. package/lib/testing/make-test-services.d.ts.map +1 -1
  500. package/lib/testing/make-test-services.js +42 -10
  501. package/lib/testing/make-test-services.js.map +1 -1
  502. package/lib/testing/make-test-tracer.d.ts +12 -0
  503. package/lib/testing/make-test-tracer.d.ts.map +1 -1
  504. package/lib/testing/make-test-tracer.js +13 -0
  505. package/lib/testing/make-test-tracer.js.map +1 -1
  506. package/lib/testing/node/applied-edit-capture.d.ts +29 -0
  507. package/lib/testing/node/applied-edit-capture.d.ts.map +1 -0
  508. package/lib/testing/node/applied-edit-capture.js +117 -0
  509. package/lib/testing/node/applied-edit-capture.js.map +1 -0
  510. package/lib/testing/node/golden-corpus.js.map +1 -1
  511. package/lib/testing/node/index.d.ts +1 -0
  512. package/lib/testing/node/index.d.ts.map +1 -1
  513. package/lib/testing/node/index.js +1 -0
  514. package/lib/testing/node/index.js.map +1 -1
  515. package/lib/testing/node/lsp-harness.d.ts.map +1 -1
  516. package/lib/testing/node/lsp-harness.js +2 -0
  517. package/lib/testing/node/lsp-harness.js.map +1 -1
  518. package/lib/testing/node/lsp-server-connection.d.ts +21 -6
  519. package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
  520. package/lib/testing/node/lsp-server-connection.js +49 -106
  521. package/lib/testing/node/lsp-server-connection.js.map +1 -1
  522. package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
  523. package/lib/testing/node/scratch-workspace.js +10 -5
  524. package/lib/testing/node/scratch-workspace.js.map +1 -1
  525. package/lib/testing/node/spawned-server.d.ts +30 -1
  526. package/lib/testing/node/spawned-server.d.ts.map +1 -1
  527. package/lib/testing/node/spawned-server.js +39 -2
  528. package/lib/testing/node/spawned-server.js.map +1 -1
  529. package/lib/testing/node/unhandled-rejections.d.ts +20 -0
  530. package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
  531. package/lib/testing/node/unhandled-rejections.js +32 -0
  532. package/lib/testing/node/unhandled-rejections.js.map +1 -0
  533. package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
  534. package/lib/testing/playwright/e2e-profiling.js.map +1 -1
  535. package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
  536. package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
  537. package/lib/testing/playwright/flaky-network-proxy.js +164 -0
  538. package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
  539. package/lib/testing/playwright/index.d.ts +1 -0
  540. package/lib/testing/playwright/index.d.ts.map +1 -1
  541. package/lib/testing/playwright/index.js +1 -0
  542. package/lib/testing/playwright/index.js.map +1 -1
  543. package/lib/testing/playwright/server-log-capture.d.ts +46 -16
  544. package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
  545. package/lib/testing/playwright/server-log-capture.js +111 -40
  546. package/lib/testing/playwright/server-log-capture.js.map +1 -1
  547. package/lib/testing/playwright/server-log-fixture.d.ts +16 -0
  548. package/lib/testing/playwright/server-log-fixture.d.ts.map +1 -1
  549. package/lib/testing/playwright/server-log-fixture.js +25 -6
  550. package/lib/testing/playwright/server-log-fixture.js.map +1 -1
  551. package/lib/testing/playwright/server-log-region.d.ts +15 -0
  552. package/lib/testing/playwright/server-log-region.d.ts.map +1 -0
  553. package/lib/testing/playwright/server-log-region.js +30 -0
  554. package/lib/testing/playwright/server-log-region.js.map +1 -0
  555. package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
  556. package/lib/testing/playwright/server-log-rename-reporter.js +4 -3
  557. package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
  558. package/lib/testing/run-update-pipeline.d.ts +8 -5
  559. package/lib/testing/run-update-pipeline.d.ts.map +1 -1
  560. package/lib/testing/run-update-pipeline.js.map +1 -1
  561. package/lib/testing/stub-ast-document-manager.d.ts +11 -52
  562. package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
  563. package/lib/testing/stub-ast-document-manager.js +31 -62
  564. package/lib/testing/stub-ast-document-manager.js.map +1 -1
  565. package/lib/testing/stub-document-builder.d.ts +33 -11
  566. package/lib/testing/stub-document-builder.d.ts.map +1 -1
  567. package/lib/testing/stub-document-builder.js +103 -5
  568. package/lib/testing/stub-document-builder.js.map +1 -1
  569. package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
  570. package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
  571. package/lib/testing/stub-hydranium-text-documents.js +132 -16
  572. package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
  573. package/lib/testing/stub-index-manager.js.map +1 -1
  574. package/lib/testing/stub-langium-documents.d.ts +3 -2
  575. package/lib/testing/stub-langium-documents.d.ts.map +1 -1
  576. package/lib/testing/stub-langium-documents.js.map +1 -1
  577. package/lib/testing/stub-model-service.d.ts +9 -8
  578. package/lib/testing/stub-model-service.d.ts.map +1 -1
  579. package/lib/testing/stub-model-service.js +6 -6
  580. package/lib/testing/stub-model-service.js.map +1 -1
  581. package/lib/testing/stub-project-manager.js.map +1 -1
  582. package/lib/testing/stub-self-save-registry.d.ts +1 -1
  583. package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
  584. package/lib/testing/stub-service-registry.d.ts +1 -1
  585. package/lib/testing/stub-service-registry.js.map +1 -1
  586. package/lib/testing/stub-writable-file-system.d.ts +1 -1
  587. package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
  588. package/lib/testing/stub-writable-file-system.js +2 -1
  589. package/lib/testing/stub-writable-file-system.js.map +1 -1
  590. package/lib/util/connection-liveness.d.ts +19 -6
  591. package/lib/util/connection-liveness.d.ts.map +1 -1
  592. package/lib/util/connection-liveness.js +61 -15
  593. package/lib/util/connection-liveness.js.map +1 -1
  594. package/lib/util/environment.d.ts.map +1 -1
  595. package/lib/util/environment.js.map +1 -1
  596. package/lib/util/registry.d.ts.map +1 -1
  597. package/package.json +38 -57
  598. package/src/browser/host-heads-in-worker.ts +218 -0
  599. package/src/browser/index.ts +17 -0
  600. package/src/browser/indexeddb-file-system-store.ts +192 -0
  601. package/src/browser/start-language-server-in-worker.ts +56 -0
  602. package/src/documents/ast-document-manager.ts +467 -233
  603. package/src/documents/client-ids.ts +5 -22
  604. package/src/documents/client-session-errors.ts +24 -0
  605. package/src/documents/client-session-registry.ts +262 -0
  606. package/src/documents/dirty-state-tracker.ts +167 -0
  607. package/src/documents/document-release-handler.ts +404 -0
  608. package/src/documents/document-release-scheduler.ts +121 -0
  609. package/src/documents/file-system-task-queue.ts +74 -0
  610. package/src/documents/hydranium-text-documents.ts +1022 -595
  611. package/src/documents/index.ts +10 -2
  612. package/src/documents/language-client-shadow.ts +501 -0
  613. package/src/documents/model-ledger.ts +66 -0
  614. package/src/documents/text-ledger.ts +112 -0
  615. package/src/documents/version-sync-service.ts +275 -0
  616. package/src/index.ts +8 -0
  617. package/src/langium/ast-extension/ast-extension-service.ts +77 -41
  618. package/src/langium/bootstrap.ts +95 -52
  619. package/src/langium/build-phase-pass/build-phase-pass-service.ts +29 -19
  620. package/src/langium/build-phase-pass/build-phase-pass.ts +37 -8
  621. package/src/langium/composite-ast-reflection.ts +112 -0
  622. package/src/langium/config/configuration-provider.ts +119 -0
  623. package/src/langium/config/index.ts +1 -0
  624. package/src/langium/diagnostics/hydranium-langium-profiler.ts +15 -39
  625. package/src/langium/diagnostics/log-preamble.ts +1 -1
  626. package/src/langium/diagnostics/logger.ts +38 -11
  627. package/src/langium/diagnostics/lsp-logger.ts +61 -16
  628. package/src/langium/document-builder/build-pipeline-integration.ts +46 -32
  629. package/src/langium/document-builder/build-session.ts +4 -3
  630. package/src/langium/document-builder/document-builder.ts +616 -73
  631. package/src/langium/integration-services.ts +59 -28
  632. package/src/langium/integrity/integrity-rule.ts +16 -8
  633. package/src/langium/integrity/integrity-service.ts +296 -69
  634. package/src/langium/keys/containment.ts +87 -0
  635. package/src/langium/keys/index.ts +1 -0
  636. package/src/langium/keys/name-based-key-provider.ts +4 -0
  637. package/src/langium/language-module.ts +49 -8
  638. package/src/langium/model-service/client-session.ts +718 -0
  639. package/src/langium/model-service/index.ts +2 -0
  640. package/src/langium/model-service/model-events.ts +80 -0
  641. package/src/langium/model-service/model-service.ts +908 -485
  642. package/src/langium/module.ts +212 -67
  643. package/src/langium/naming/name-provider.ts +44 -8
  644. package/src/langium/naming/name-separator-validation.ts +25 -3
  645. package/src/langium/project/abstract-project-manager.ts +13 -5
  646. package/src/langium/project/project-change-event.ts +2 -2
  647. package/src/langium/residency/cst-residency-service.ts +54 -19
  648. package/src/langium/scope/fallback-scope.ts +38 -0
  649. package/src/langium/scope/hydranium-scope-computation.ts +45 -44
  650. package/src/langium/scope/hydranium-scope-provider.ts +49 -16
  651. package/src/langium/scope/index.ts +1 -0
  652. package/src/langium/scope/reference-candidate-provider.ts +6 -5
  653. package/src/langium/scope/scope-extension-service.ts +74 -59
  654. package/src/langium/scope/scoped-ast-node-description.ts +1 -3
  655. package/src/langium/serialization/abstract-serializer.ts +57 -41
  656. package/src/langium/serialization/json-serializer.ts +14 -3
  657. package/src/langium/serialization/serializer.ts +1 -1
  658. package/src/langium/serialization/yaml-serializer.ts +4 -0
  659. package/src/langium/service-registry.ts +41 -2
  660. package/src/langium/shared-services.ts +26 -6
  661. package/src/langium/single-langium-copy.ts +42 -0
  662. package/src/langium/transfer/transfer-encoder.ts +102 -45
  663. package/src/langium/trivia/comment-preserver.ts +1100 -0
  664. package/src/langium/trivia/document-ending-preserver.ts +71 -0
  665. package/src/langium/trivia/index.ts +14 -0
  666. package/src/langium/trivia/trivia-contribution.ts +39 -0
  667. package/src/langium/trivia/trivia-preserver.ts +56 -0
  668. package/src/langium/trivia/trivia-service.ts +99 -0
  669. package/src/langium/update-rewrite/update-rewrite-service.ts +1 -1
  670. package/src/langium/update-rewrite/update-rewrite.ts +1 -1
  671. package/src/langium/validation/document-validator.ts +528 -13
  672. package/src/langium/validation/validation-contribution-collector.ts +10 -1
  673. package/src/langium/workspace/document-uri-policy.ts +32 -18
  674. package/src/langium/workspace/file-not-found.ts +35 -0
  675. package/src/langium/workspace/file-system-provider.ts +258 -16
  676. package/src/langium/workspace/hydranium-langium-document-factory.ts +83 -0
  677. package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
  678. package/src/langium/workspace/hydranium-workspace-manager.ts +241 -35
  679. package/src/langium/workspace/in-memory-file-system-provider.ts +54 -23
  680. package/src/langium/workspace/index.ts +1 -0
  681. package/src/langium/workspace/initialize-workspace.ts +129 -8
  682. package/src/langium/workspace/langium-documents.ts +19 -1
  683. package/src/langium/workspace/persistent-file-system-provider.ts +27 -15
  684. package/src/langium/workspace/self-save-registry.ts +118 -0
  685. package/src/langium/workspace/virtual-document.ts +106 -25
  686. package/src/langium/workspace/write-lock-scope.ts +27 -12
  687. package/src/launcher/integrated-server.ts +3 -1
  688. package/src/locale/index.ts +10 -0
  689. package/src/locale/server-locale.ts +86 -0
  690. package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
  691. package/src/lsp/connection-features.ts +67 -0
  692. package/src/lsp/diagnostics-connection.ts +56 -0
  693. package/src/lsp/hydranium-document-update-handler.ts +285 -111
  694. package/src/lsp/index.ts +4 -1
  695. package/src/lsp/lsp-latency.ts +62 -0
  696. package/src/lsp/save-text-document.ts +63 -0
  697. package/src/lsp/semantic-token-provider.ts +74 -7
  698. package/src/lsp/shared-module.ts +4 -8
  699. package/src/lsp/start-language-server.ts +13 -7
  700. package/src/messages/carriers.ts +23 -15
  701. package/src/messages/index.ts +13 -1
  702. package/src/messages/renderer.ts +212 -0
  703. package/src/node/event-loop-monitor.ts +2 -1
  704. package/src/node/heap-ceiling.ts +108 -0
  705. package/src/node/index.ts +5 -1
  706. package/src/node/latency-from-env.ts +1 -1
  707. package/src/node/log-preamble-node.ts +20 -10
  708. package/src/node/measure-memory.ts +5 -4
  709. package/src/node/memory-monitor.ts +10 -10
  710. package/src/node/node-file-system-provider.ts +214 -57
  711. package/src/node/profile-capture.ts +16 -15
  712. package/src/node/profiling-run.ts +30 -8
  713. package/src/node/rename-over-open-readers.ts +94 -0
  714. package/src/node/server-diagnostics.ts +1 -1
  715. package/src/node/server-state-snapshot.ts +5 -5
  716. package/src/node/socket-launcher.ts +78 -14
  717. package/src/node/startup-cpu-profile.ts +94 -0
  718. package/src/node/stdio-launcher.ts +29 -19
  719. package/src/testing/document-uri-policy-conformance.ts +1 -1
  720. package/src/testing/fake-document.ts +2 -1
  721. package/src/testing/index.ts +2 -1
  722. package/src/testing/langium-test-helpers.ts +1 -0
  723. package/src/testing/make-noop-shared-services.ts +50 -2
  724. package/src/testing/make-test-services.ts +125 -31
  725. package/src/testing/make-test-tracer.ts +26 -0
  726. package/src/testing/node/applied-edit-capture.ts +141 -0
  727. package/src/testing/node/index.ts +1 -0
  728. package/src/testing/node/lsp-harness.ts +2 -0
  729. package/src/testing/node/lsp-server-connection.ts +83 -119
  730. package/src/testing/node/scratch-workspace.ts +10 -5
  731. package/src/testing/node/spawned-server.ts +57 -3
  732. package/src/testing/node/unhandled-rejections.ts +31 -0
  733. package/src/testing/parse-semantic-root.ts +1 -1
  734. package/src/testing/playwright/flaky-network-proxy.ts +240 -0
  735. package/src/testing/playwright/index.ts +1 -0
  736. package/src/testing/playwright/server-log-capture.ts +137 -47
  737. package/src/testing/playwright/server-log-fixture.ts +46 -6
  738. package/src/testing/playwright/server-log-region.ts +32 -0
  739. package/src/testing/playwright/server-log-rename-reporter.ts +4 -3
  740. package/src/testing/run-update-pipeline.ts +8 -5
  741. package/src/testing/stub-ast-document-manager.ts +47 -128
  742. package/src/testing/stub-document-builder.ts +133 -18
  743. package/src/testing/stub-hydranium-text-documents.ts +184 -27
  744. package/src/testing/stub-langium-documents.ts +3 -2
  745. package/src/testing/stub-model-service.ts +11 -10
  746. package/src/testing/stub-self-save-registry.ts +1 -1
  747. package/src/testing/stub-service-registry.ts +1 -1
  748. package/src/testing/stub-writable-file-system.ts +3 -2
  749. package/src/util/connection-liveness.ts +67 -15
  750. package/src/util/environment.ts +9 -1
  751. package/lib/documents/language-client-text-shadow.d.ts +0 -101
  752. package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
  753. package/lib/documents/language-client-text-shadow.js +0 -156
  754. package/lib/documents/language-client-text-shadow.js.map +0 -1
  755. package/lib/documents/self-save-registry.d.ts +0 -55
  756. package/lib/documents/self-save-registry.d.ts.map +0 -1
  757. package/lib/documents/self-save-registry.js.map +0 -1
  758. package/lib/lsp/instrument-connection.d.ts +0 -36
  759. package/lib/lsp/instrument-connection.d.ts.map +0 -1
  760. package/lib/lsp/instrument-connection.js +0 -62
  761. package/lib/lsp/instrument-connection.js.map +0 -1
  762. package/lib/node/process-memory.d.ts +0 -66
  763. package/lib/node/process-memory.d.ts.map +0 -1
  764. package/lib/node/process-memory.js +0 -252
  765. package/lib/node/process-memory.js.map +0 -1
  766. package/src/documents/language-client-text-shadow.ts +0 -175
  767. package/src/documents/self-save-registry.ts +0 -81
  768. package/src/lsp/instrument-connection.ts +0 -66
  769. package/src/node/process-memory.ts +0 -299
@@ -8,15 +8,24 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  import { isPromiseLike, Logger, type ProfileSession, type Tracer } from '@hydranium/protocol';
11
- import { type AstNode, AstUtils, DocumentState, interruptAndCheck, type LangiumDocument, UriUtils } from '@hydranium/langium';
12
- import { type CancellationToken, type Disposable } from 'vscode-languageserver';
11
+ import {
12
+ type AstNode,
13
+ AstUtils,
14
+ DocumentState,
15
+ interruptAndCheck,
16
+ isOperationCancelled,
17
+ type LangiumDocument,
18
+ UriUtils
19
+ } from '@hydranium/langium';
20
+ import { CancellationToken, type Disposable } from 'vscode-languageserver';
13
21
  import { type HydraniumDocumentBuilder } from '../document-builder/document-builder.js';
14
22
  import { type TextDocument } from 'vscode-languageserver-textdocument';
15
- import { type WritableFileSystemProvider } from '../../documents/ast-document-manager.js';
23
+ import { type WritableFileSystemProvider } from '../workspace/file-system-provider.js';
16
24
  import { type LogNameOptions } from '../diagnostics/logger.js';
17
25
  import { type HydraniumTextDocuments } from '../../documents/hydranium-text-documents.js';
18
26
  import { Registry } from '../../util/registry.js';
19
27
  import { type ServerLanguageServices } from '../language-module.js';
28
+ import { isVirtualUri } from '../workspace/virtual-document.js';
20
29
  import { type IntegrityRuleRegistry } from './integrity-contribution.js';
21
30
  import { IntegrityPhase, type IntegrityRule, type IntegritySyncMode } from './integrity-rule.js';
22
31
 
@@ -75,6 +84,11 @@ export namespace IntegrityService {
75
84
  * at `DocumentState.Validated` and delivered separately via `publishDiagnostics`
76
85
  * or the `onModelUpdated` event.
77
86
  *
87
+ * The AST is what this guarantees, not the text. For a closed document whose
88
+ * repair was STAGED rather than written (`'editor'` sync mode),
89
+ * `textDocument` still mirrors disk — read the repair off the AST, or from
90
+ * the staged content the next open consumes.
91
+ *
78
92
  * Invariant: integrity rules only register at Parsed or Linked, so the build
79
93
  * is guaranteed post-integrity once it advances past `onBuildPhase(Linked)`
80
94
  * into `IndexedReferences`. {@link IntegrityService.register} enforces this at
@@ -123,15 +137,16 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
123
137
  protected ruleLoggers = new Map<string, Logger>();
124
138
 
125
139
  /**
126
- * Rules bucketed by the phase they target, preserving the registry's
127
- * priority order within each bucket. Rebuilt lazily on the first
128
- * `enforceIntegrity` call after a registry mutation — staleness is detected
129
- * via reference identity of the registry's cached array (see
130
- * {@link Registry.all}). Filtering the rule list per call would instead
131
- * allocate one transient array per document per phase, which a workspace
132
- * whose documents all settle at the same phase pays on every build.
140
+ * Rules bucketed by the phase they target, then by each `$type` from
141
+ * {@link nodeTypesFor}, preserving the registry's priority order within
142
+ * each bucket. Rebuilt lazily on the first `enforceIntegrity` call after a
143
+ * registry mutation — staleness is detected via reference identity of the
144
+ * registry's cached array (see {@link Registry.all}). Filtering the rule
145
+ * list per call would instead allocate one transient array per document per
146
+ * phase, which a workspace whose documents all settle at the same phase pays
147
+ * on every build.
133
148
  */
134
- protected phaseBuckets = new Map<DocumentState, readonly IntegrityRule[]>();
149
+ protected phaseBuckets = new Map<DocumentState, ReadonlyMap<string, readonly IntegrityRule[]>>();
135
150
  protected phaseBucketsFor: readonly IntegrityRule[] | undefined;
136
151
 
137
152
  /** Controls how corrections are persisted for closed files. See {@link IntegritySyncMode}. */
@@ -142,9 +157,7 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
142
157
  protected readonly tracer: Tracer;
143
158
  /**
144
159
  * The framework document builder, used to re-parse + re-link a document in place after a
145
- * Linked-phase correction (see {@link resyncDocument}). The framework binds
146
- * `shared.workspace.DocumentBuilder` to {@link HydraniumDocumentBuilder}; the narrowing
147
- * cast surfaces its single-document phase runner.
160
+ * Linked-phase correction (see {@link resyncDocument}).
148
161
  */
149
162
  protected readonly documentBuilder: HydraniumDocumentBuilder;
150
163
 
@@ -155,7 +168,7 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
155
168
  this.textDocuments = services.shared.workspace.TextDocuments;
156
169
  this.fileSystemProvider = services.shared.workspace.FileSystemProvider;
157
170
  this.tracer = services.shared.Tracer.for(options.logName ?? 'Integrity').trace('instantiated');
158
- this.documentBuilder = services.shared.workspace.DocumentBuilder as HydraniumDocumentBuilder;
171
+ this.documentBuilder = services.shared.workspace.DocumentBuilder;
159
172
  this.syncMode = options.syncMode ?? 'silent';
160
173
 
161
174
  // Read the language's IntegrityRuleContribution group and let each
@@ -184,7 +197,7 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
184
197
  * rule set to completion against a doomed build.
185
198
  */
186
199
  async enforceBatch(documents: readonly LangiumDocument[], phase: DocumentState, cancelToken: CancellationToken): Promise<void> {
187
- const phaseStart = performance.now();
200
+ const sincePhaseStart = this.services.shared.Clock.stopwatch();
188
201
  let mutatedCount = 0;
189
202
  // Per-rule self-time profiling is opt-in: only spin up a session when the
190
203
  // debug threshold is active, so the production `info` path allocates
@@ -194,13 +207,17 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
194
207
  const changed = await this.enforceIntegrity(document, phase, cancelToken, session);
195
208
  if (changed) {
196
209
  mutatedCount++;
197
- await this.resyncDocument(document, cancelToken);
210
+ // Not cancellable: see `resyncDocument`.
211
+ await this.resyncDocument(document, CancellationToken.None);
198
212
  }
199
213
  await interruptAndCheck(cancelToken);
200
214
  }
201
- const totalMs = Math.round(performance.now() - phaseStart);
202
- if (totalMs >= 25 || mutatedCount > 0) {
215
+ const totalMs = Math.round(sincePhaseStart.elapsedMs);
216
+ // A repair is the operator's to know of; the timing alone is diagnosis.
217
+ if (mutatedCount > 0) {
203
218
  this.tracer.info(`enforce ${DocumentState[phase]}: docs=${documents.length}, mutated=${mutatedCount} [${totalMs}ms]`);
219
+ } else if (totalMs >= 25) {
220
+ this.tracer.debug(`enforce ${DocumentState[phase]}: docs=${documents.length}, mutated=${mutatedCount} [${totalMs}ms]`);
204
221
  }
205
222
  // One line per rule (count + self-% + self-ms), sorted by cost — only when profiling.
206
223
  session?.report('debug');
@@ -219,6 +236,14 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
219
236
  );
220
237
  }
221
238
  const disposable = this.rules.register(rule);
239
+ // No parsed node carries a type the reflection does not know, so such a
240
+ // rule never runs. A warning, not a throw: a test reflection may omit the type.
241
+ if (!this.services.shared.AstReflection.getAllTypes().includes(rule.nodeType)) {
242
+ this.tracer.warn(
243
+ `Integrity rule '${this.formatRule(rule)}' is keyed on node type '${rule.nodeType}', ` +
244
+ 'which the AST reflection does not know, so no parsed node matches it.'
245
+ );
246
+ }
222
247
  this.ruleLoggers.set(rule.id, this.tracer.sub(IntegrityPhase.toString(rule.phase)).sub(rule.label ?? rule.id));
223
248
  return {
224
249
  dispose: () => {
@@ -255,8 +280,10 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
255
280
  * full rule sweep) — coarser than per (node × rule) to avoid a microtask
256
281
  * per inner iteration, finer than per-document so a long-running rule set
257
282
  * on a large file can still interrupt mid-stream. Throws
258
- * `OperationCancelled` when the token is cancelled; Langium's build
259
- * pipeline absorbs the throw at the lock-holder.
283
+ * `OperationCancelled` when the token is cancelled before any rule mutated
284
+ * the AST; Langium's build pipeline absorbs the throw at the lock-holder.
285
+ * After a mutation it stops the sweep and returns `true` instead, so the
286
+ * caller can resync what was mutated before the cancellation unwinds.
260
287
  */
261
288
  async enforceIntegrity(
262
289
  document: LangiumDocument,
@@ -268,29 +295,34 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
268
295
  return false;
269
296
  }
270
297
  let changed = false;
271
- const rulesForPhase = this.getPhaseBucket(phase);
272
- if (rulesForPhase.length === 0) {
298
+ const rulesByType = this.getPhaseBucket(phase);
299
+ if (rulesByType.size === 0) {
273
300
  return false;
274
301
  }
275
302
  const relativeUri = this.services.shared.workspace.WorkspaceManager.wsRelativePath(document.uri);
276
303
  for (const node of AstUtils.streamAst(document.parseResult.value)) {
277
- for (const rule of rulesForPhase) {
278
- if (node.$type === rule.nodeType) {
279
- const ruleLogger = this.ruleLoggers.get(rule.id)!.with(relativeUri);
280
- // Scope per rule so the session aggregates self-time by rule id across all
281
- // nodes; off the profiling path `session` is undefined and we call directly.
282
- const enforced = session
283
- ? session.scope(rule.id, () => rule.enforce(node, document, ruleLogger))
284
- : rule.enforce(node, document, ruleLogger);
285
- const mutated = isPromiseLike(enforced) ? await enforced : enforced;
286
- if (mutated) {
287
- ruleLogger.trace(`[${relativeUri}] Mutated ${this.formatNode(node)}`);
288
- }
289
- changed = mutated || changed;
304
+ for (const rule of rulesByType.get(node.$type) ?? NO_RULES) {
305
+ const ruleLogger = this.ruleLoggers.get(rule.id)!.with(relativeUri);
306
+ // Scope per rule so the session aggregates self-time by rule id across all
307
+ // nodes; off the profiling path `session` is undefined and we call directly.
308
+ const enforced = session
309
+ ? session.scope(rule.id, () => rule.enforce(node, document, ruleLogger))
310
+ : rule.enforce(node, document, ruleLogger);
311
+ const mutated = isPromiseLike(enforced) ? await enforced : enforced;
312
+ if (mutated) {
313
+ ruleLogger.trace(`[${relativeUri}] Mutated ${this.formatNode(node)}`);
290
314
  }
315
+ changed = mutated || changed;
291
316
  }
292
317
  if (cancelToken !== undefined) {
293
- await interruptAndCheck(cancelToken);
318
+ try {
319
+ await interruptAndCheck(cancelToken);
320
+ } catch (err: unknown) {
321
+ if (changed && isOperationCancelled(err)) {
322
+ return true;
323
+ }
324
+ throw err;
325
+ }
294
326
  }
295
327
  }
296
328
  return changed;
@@ -300,34 +332,120 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
300
332
  * Re-serialise the document text after AST mutations, propagate corrections,
301
333
  * and re-parse at Parsed phase (safe because linking hasn't occurred yet).
302
334
  *
303
- * `cancelToken` is checked at entry so a preempted build skips the
304
- * serialise / disk-write atomic; the steps inside resync are not further
305
- * subdivided because each is a single fast operation that does not yield
306
- * a natural interruption point.
335
+ * Runs to the end whatever `cancelToken` says: the AST is already mutated,
336
+ * and skipping the resync leaves it against unchanged text that the next
337
+ * build does not re-parse. `cancelToken` reaches only the re-parse.
307
338
  */
308
339
  protected async resyncDocument(document: LangiumDocument, cancelToken?: CancellationToken): Promise<void> {
309
- if (cancelToken?.isCancellationRequested) {
310
- return;
311
- }
312
340
  const root = document.parseResult.value as TRoot;
313
- const newText = await this.services.serializer.Serializer.serializeAst(root);
341
+ // Extracted while `document` still holds the text being replaced — the
342
+ // resync that follows overwrites it with `newText`. Absent on a test
343
+ // stub that binds no trivia group; `createServerLanguageModule` always
344
+ // provides it, and an empty registry is already the no-op.
345
+ const trivia = this.services.trivia?.TriviaService;
346
+ const extracted = trivia?.extract(document);
347
+ const serialized = await this.services.serializer.Serializer.serializeAst(root);
348
+ const newText =
349
+ extracted === undefined ? serialized : trivia!.apply(serialized, extracted, UriUtils.toUri(document.textDocument.uri));
314
350
 
315
351
  const oldText = document.textDocument.getText();
316
352
  if (oldText === newText) {
317
353
  return;
318
354
  }
319
355
 
320
- // Keep the same version so HydraniumTextDocuments doesn't reject subsequent client edits.
321
- // Use manager.update so the `instanceof FullTextDocument` gate in the bare
322
- // `TextDocument.update` doesn't trip on adopter-custom text-document types.
323
- const textDocument = this.textDocuments.update(document.textDocument, [{ text: newText }], document.textDocument.version);
356
+ const version = document.textDocument.version;
357
+ // Commit into the store's own document when the URI is open there, rather
358
+ // than into whichever text-document object this build is holding. The two
359
+ // are the same on the LSP path and are NOT when the document was built for
360
+ // an already-open URI through `fromString`: repairing only the build's copy
361
+ // leaves the store — the server's authority on what an open document says —
362
+ // on the unrepaired text, and the reconciling re-parse then redefines
363
+ // `textDocument` onto the store's object and discards the repair with it.
364
+ //
365
+ // Compared against the CST's own text, not against `document.textDocument`.
366
+ // That object IS the store's on the LSP path, so asking it whether the
367
+ // store still agrees compares the store with itself and can only ever say
368
+ // yes — the guard would be vacuous exactly where an editor race can happen.
369
+ // The CST's `fullText` is the text that actually produced this AST, which
370
+ // is the only thing a repair derived from it is valid against. A document
371
+ // with no CST (built from a model rather than parsed) has no better answer
372
+ // than the text it is carrying.
373
+ const parsedFrom = document.parseResult.value.$cstNode?.root.fullText ?? oldText;
374
+ const commit = this.textDocuments.commitRepair(document.textDocument.uri, parsedFrom, newText);
375
+ if (commit.status === 'stale') {
376
+ // An edit landed after the parse this repair came from, so the repair
377
+ // describes text the store has already replaced. Abandon it rather than
378
+ // hand it to `syncCorrections`: an override that persists from there
379
+ // would write a correction over the edit that superseded it. That edit
380
+ // drives a build of its own, which re-runs these rules against what the
381
+ // document actually says.
382
+ //
383
+ // Abandoning the WRITE is only half of it. The build carries on to its
384
+ // settled phase with whatever AST is registered, and every settled
385
+ // consumer reads that AST rather than the store — so leaving the rule's
386
+ // mutation in place would answer questions about this document from a
387
+ // parse of text nobody has. Reconciling discards it by re-reading the
388
+ // store, which is what the document now has to agree with.
389
+ await this.reconcileDocument(document, cancelToken);
390
+ return;
391
+ }
392
+
393
+ // A committed repair is a new version; a document no client has open keeps
394
+ // its number here, and the re-versioning below moves it once the build
395
+ // has reconciled. Through the store's `update`, so the `instanceof
396
+ // FullTextDocument` gate in the bare `TextDocument.update` does not trip
397
+ // on adopter-custom text-document types.
398
+ const textDocument =
399
+ commit.status === 'committed' ? commit.document : this.textDocuments.update(document.textDocument, [{ text: newText }], version);
400
+
401
+ await this.syncCorrections(textDocument, parsedFrom);
402
+
403
+ await this.reconcileDocument(document, cancelToken);
324
404
 
325
- await this.syncCorrections(textDocument);
405
+ // Re-version against the REPAIRED text, after either branch. The repair is
406
+ // a content change the store has not seen: whatever reconciliation ran
407
+ // during the re-parse saw the text on disk, which in `'editor'` sync mode
408
+ // is the PRE-repair text. Leave the sequence describing that and the next
409
+ // open hashes the repair, finds a mismatch and steps the version again, so
410
+ // every base version taken from this build is stale before it is used.
411
+ // An open document keeps the store's own version, which is not this
412
+ // method's to move.
413
+ //
414
+ // Deliberately NOT gated on cancellation, unlike the entry to this method:
415
+ // `syncCorrections` has already written or staged the repair by now, so a
416
+ // preempted build that skipped this would leave the sequence describing
417
+ // text that is no longer there.
418
+ if (!this.textDocuments.isOpen(document.textDocument.uri)) {
419
+ // The root describes the repair too; left at the re-parse's number, a
420
+ // syncing read waits for a build nothing requests. The CST is still
421
+ // the unrepaired text, so the repair is reported as the parsed text.
422
+ this.services.shared.workspace.VersionSyncService.modelProduced(document, { text: newText });
423
+ }
424
+ }
326
425
 
426
+ /**
427
+ * Bring `document` back into agreement with the text it is supposed to
428
+ * describe, after a rule has mutated its AST.
429
+ *
430
+ * Used for a correction that was applied and for one that was abandoned,
431
+ * because the document is left inconsistent either way: applied, the text
432
+ * moved under the CST; abandoned, the AST carries a mutation the text never
433
+ * had. Both are the same question — re-read and re-derive — and the phase is
434
+ * what decides how far that has to go.
435
+ */
436
+ protected async reconcileDocument(document: LangiumDocument, cancelToken?: CancellationToken): Promise<void> {
327
437
  if (document.state <= DocumentState.Parsed) {
328
438
  // Parsed-phase correction: re-parse only. The build pipeline still runs
329
439
  // IndexedContent → ComputedScopes → Linked → … on the fresh AST afterwards,
330
440
  // so the document reconciles naturally with no extra work here.
441
+ //
442
+ // Except for a closed document whose repair did not reach disk — `'editor'`
443
+ // sync mode stages it instead of writing it — where the re-parse is SKIPPED:
444
+ // Langium's factory gates the parse on the CST's `fullText`, which still
445
+ // equals the disk text the same call re-reads and redefines `textDocument`
446
+ // over. So `document.textDocument` is NOT post-integrity for such a
447
+ // document — it mirrors disk, and the AST is the only place the repair is
448
+ // legible, until an open consumes the staging.
331
449
  await this.documentBuilder.reparse(document, cancelToken);
332
450
  } else {
333
451
  // Linked-phase (or later) correction. The rule mutated the AST in place but
@@ -347,34 +465,122 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
347
465
  * already in the synced store (in-place in {@link resyncDocument}); this
348
466
  * method routes the out-of-band part by document registration:
349
467
  *
350
- * - **Open in the language client** → nothing to push here. The AST mutation
351
- * rode the current build, so `ModelService.syncToLanguageClient` (the
352
- * persistent integrity-settled listener) mirrors the corrected text to the
353
- * client by *content* (shadow diff) — no authorship rewrite, no second
354
- * rebuild.
468
+ * - **Open in the language client** → nothing to push here. The AST
469
+ * mutation rode the current build, so
470
+ * `DefaultModelService.syncToLanguageClient` (the persistent
471
+ * integrity-settled listener) mirrors it to the client by
472
+ * *content* (shadow diff), and the editor shows it as an unsaved change.
473
+ * - **Held only through the data or GLSP head**, or waiting out the release
474
+ * grace after its last client's connection was lost → the store is the
475
+ * authority, and those heads read the correction from the settled build.
476
+ * In silent mode it is also written to disk when the text it was computed
477
+ * from is what disk holds, since the repair is then the only difference;
478
+ * otherwise it waits for the next save. Editor mode always waits, and the
479
+ * repair leaves the document dirty until a save.
355
480
  * - **Closed, silent mode** → write to disk directly (disk is authoritative).
356
- * - **Closed, editor mode** → stage so the next open picks it up via applyEdit.
481
+ * - **Closed, editor mode** → stage, so the next open takes the correction
482
+ * over the disk text.
483
+ *
484
+ * A held URI is not closed. Writing it as one persists the holder's unsaved
485
+ * edits with the repair, and staging it leaves text no open reads, because
486
+ * only a first open consumes the stage.
487
+ *
488
+ * `parsedFrom` is the text the repaired AST was parsed from. Without it a
489
+ * held URI's repair is left to the next save.
357
490
  */
358
- protected async syncCorrections(document: TextDocument): Promise<void> {
359
- // Open files: delivery is the ModelService settled listener's job (by
360
- // content, via the shadow) — nothing to do here. Only the open/closed
361
- // question is asked, so no reverse address resolution is needed: a file
362
- // open under a symlinked path still answers `true`.
491
+ protected async syncCorrections(document: TextDocument, parsedFrom?: string): Promise<void> {
492
+ // Only the open/closed question is asked, so no reverse address
493
+ // resolution is needed: a file open under a symlinked path still answers
494
+ // `true`.
363
495
  if (this.textDocuments.isOpenInLanguageClient(document.uri)) {
364
496
  return;
365
497
  }
366
498
 
499
+ // A virtual document has no disk backing, so neither persisting nor
500
+ // staging applies: there is no file to write and no editor that could open
501
+ // one. `URI.fsPath` yields a path for any scheme, so handing this to the
502
+ // provider would address `<cwd>/<contributor>/<name>` — an unrelated
503
+ // location a disk-backed provider refuses outright, turning a repair that
504
+ // was never persistable into a build failure. The correction is already on
505
+ // the AST and in the text store, which is the whole of where a virtual
506
+ // document lives, so there is nothing further to propagate.
507
+ if (isVirtualUri(document.uri)) {
508
+ this.tracer.with(document.uri).debug('Virtual document: correction kept in memory, nothing to persist');
509
+ return;
510
+ }
511
+
512
+ // A document waiting out the release grace still holds its lost client's
513
+ // unsaved text, so writing it as a closed file would persist that text.
514
+ if (this.textDocuments.isOpenInAnyClient(document.uri) || this.textDocuments.isReleaseDeferred(document.uri)) {
515
+ if (this.syncMode === 'silent' && parsedFrom !== undefined) {
516
+ await this.persistIfDiskMatches(document, parsedFrom);
517
+ }
518
+ return;
519
+ }
520
+
367
521
  // Closed files, silent mode: write to disk directly.
368
522
  if (this.syncMode === 'silent') {
523
+ const repaired = document.getText();
369
524
  // Async write so the integrity pass does not block the event loop on a slow filesystem.
370
- await this.fileSystemProvider.writeFile(UriUtils.toUri(document.uri), document.getText());
525
+ // In the file's task queue, behind any save already queued: written
526
+ // beside one, the older repair can land last and stay on disk.
527
+ await this.services.shared.workspace.FileSystemTaskQueue.enqueue(document.uri, () =>
528
+ this.fileSystemProvider.writeFile(UriUtils.toUri(document.uri), repaired)
529
+ );
371
530
  return;
372
531
  }
373
532
 
374
- // Closed files, editor mode: stage content so the next open picks it up via applyEdit.
533
+ // Closed files, editor mode: stage content for the next open.
375
534
  this.textDocuments.stagePendingContent(document.uri, document.getText());
376
535
  }
377
536
 
537
+ /**
538
+ * Write the repair in `document` to disk when disk still holds `parsedFrom`,
539
+ * the text the repair was computed from — so the write carries the repair
540
+ * and nothing a holder could still discard.
541
+ *
542
+ * The read, the compare and the write run as one task in the file's task
543
+ * queue, so no save of the file lands between them. The store is compared
544
+ * again once the read returns, and the write is skipped if it no longer
545
+ * holds the repair: an edit does not wait for the queue, and writing the
546
+ * older repair then puts text on disk that no participant holds. The
547
+ * skipped repair loses nothing: the edit drives a build of its own, and a
548
+ * save writes the store's text. A file that cannot be read is left alone
549
+ * too: there is no evidence it matches. So is a file an editor opened in the
550
+ * meantime: the editor receives the repair as an unsaved change, and writing
551
+ * it would change the file under the editor.
552
+ */
553
+ protected async persistIfDiskMatches(document: TextDocument, parsedFrom: string): Promise<void> {
554
+ const uri = UriUtils.toUri(document.uri);
555
+ const repaired = document.getText();
556
+ await this.services.shared.workspace.FileSystemTaskQueue.enqueue(document.uri, async () => {
557
+ let onDisk: string;
558
+ try {
559
+ onDisk = await this.fileSystemProvider.readFile(uri);
560
+ } catch (error: unknown) {
561
+ this.tracer.with(document.uri).debug(`Held document unreadable on disk, repair left to the next save: ${String(error)}`);
562
+ return;
563
+ }
564
+ // The file itself, not the store's disk baseline: the baseline moves
565
+ // only when the server hears of a change, so it can still hold the
566
+ // parsed text after another process rewrote the file and before the
567
+ // watcher reports it, and this write would then replace that change.
568
+ if (onDisk !== parsedFrom) {
569
+ return;
570
+ }
571
+ if (this.textDocuments.get(document.uri)?.getText() !== repaired) {
572
+ this.tracer.with(document.uri).debug('Held document changed while disk was read, repair left to that change');
573
+ return;
574
+ }
575
+ if (this.textDocuments.isOpenInLanguageClient(document.uri)) {
576
+ this.tracer.with(document.uri).debug('Editor attached while disk was read, repair left to its save');
577
+ return;
578
+ }
579
+ await this.fileSystemProvider.writeFile(uri, repaired);
580
+ this.textDocuments.setDiskBaseline(document.uri, repaired);
581
+ });
582
+ }
583
+
378
584
  /**
379
585
  * Format a rule's name for inclusion in user-facing diagnostic strings
380
586
  * (error messages thrown during registration). Defaults to
@@ -400,17 +606,37 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
400
606
  return label ? `${node.$type}('${label}')` : node.$type;
401
607
  }
402
608
 
403
- protected getPhaseBucket(phase: DocumentState): readonly IntegrityRule[] {
609
+ /**
610
+ * The `$type`s `rule` runs on. Defaults to its `nodeType` and every subtype,
611
+ * as Langium's validation registry does: no node carries an abstract or union
612
+ * type as its `$type`, so an exact match never runs a rule keyed on one.
613
+ * Read only when the phase buckets rebuild after a registration change, so an
614
+ * override must not depend on anything else.
615
+ */
616
+ protected nodeTypesFor(rule: IntegrityRule): Iterable<string> {
617
+ // A type the reflection does not know still matches itself.
618
+ return [rule.nodeType, ...this.services.shared.AstReflection.getAllSubTypes(rule.nodeType)];
619
+ }
620
+
621
+ protected getPhaseBucket(phase: DocumentState): ReadonlyMap<string, readonly IntegrityRule[]> {
404
622
  const current = this.rules.all();
405
623
  if (this.phaseBucketsFor !== current) {
406
- const next = new Map<DocumentState, IntegrityRule[]>();
624
+ const next = new Map<DocumentState, Map<string, IntegrityRule[]>>();
407
625
  for (const rule of current) {
408
626
  let bucket = next.get(rule.phase);
409
627
  if (!bucket) {
410
- bucket = [];
628
+ bucket = new Map();
411
629
  next.set(rule.phase, bucket);
412
630
  }
413
- bucket.push(rule);
631
+ // Deduplicated, or a rule runs twice on a node of its own type.
632
+ for (const nodeType of new Set(this.nodeTypesFor(rule))) {
633
+ let rules = bucket.get(nodeType);
634
+ if (!rules) {
635
+ rules = [];
636
+ bucket.set(nodeType, rules);
637
+ }
638
+ rules.push(rule);
639
+ }
414
640
  }
415
641
  this.phaseBuckets = next;
416
642
  this.phaseBucketsFor = current;
@@ -419,5 +645,6 @@ export class DefaultIntegrityService<TRoot extends AstNode = AstNode> implements
419
645
  }
420
646
  }
421
647
 
422
- /** Shared empty result so `getPhaseBucket` doesn't allocate per call on the cold path. */
423
- const EMPTY_PHASE_BUCKET: readonly IntegrityRule[] = Object.freeze([]);
648
+ // Shared empty results so neither the cold path nor a node no rule matches allocates.
649
+ const EMPTY_PHASE_BUCKET: ReadonlyMap<string, readonly IntegrityRule[]> = new Map();
650
+ const NO_RULES: readonly IntegrityRule[] = Object.freeze([]);
@@ -0,0 +1,87 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ /**
11
+ * Containment-array maintenance for callers that build or delete AST nodes
12
+ * programmatically — a GLSP operation handler being the usual one.
13
+ *
14
+ * **These live beside the key provider because the constraint is the key
15
+ * provider's.** `NameBasedKeyProvider` keys a node the `NameProvider` gives no
16
+ * name from its position, as `` `${$containerProperty}@${$containerIndex}` ``,
17
+ * so a node appended with a bare `array.push` carries neither and
18
+ * `getElementKey` answers `undefined` — the element has no key at all, and the
19
+ * GLSP index cannot address it. Deleting from the middle of such a list must
20
+ * renumber the survivors, or an id derived later in the same command names the
21
+ * wrong node. Shipping the constraint's statement without the code that
22
+ * discharges it leaves every adopter in that position re-deriving thirty lines
23
+ * from prose, and both failures are silent.
24
+ *
25
+ * The population is narrower than "anyone creating elements from a diagram": it
26
+ * takes a grammar with UNNAMED element types, programmatic creation or deletion
27
+ * of them, and this key provider. A grammar whose diagram elements are all
28
+ * named never reaches it, and the two ways out are named on the provider —
29
+ * give the type a name, or bind a provider whose fallback is content-derived.
30
+ *
31
+ * **Free functions, and deliberately not a step on the AST builder.** Building a
32
+ * node detached and appending it later is legitimate, so a containment step
33
+ * cannot be mandatory; and an optional fluent step could not check the index
34
+ * against the array unless it were handed the array, at which point it is these
35
+ * signatures with more ceremony. `AstNodeInit` already accepts the three fields
36
+ * for a caller who has them, which is the case these cover: it is the INDEX that
37
+ * cannot be known without reading the array.
38
+ */
39
+
40
+ import type { AstNode } from '@hydranium/langium';
41
+ import type { Mutable } from '@hydranium/protocol';
42
+
43
+ /**
44
+ * Append `child` to `children`, stamping the Langium containment plumbing
45
+ * (`$container`, `$containerProperty`, `$containerIndex`) so a positional key
46
+ * can address it.
47
+ *
48
+ * `property` and `children` are separate parameters rather than one property
49
+ * name the function dereferences: the array is what the index is derived from,
50
+ * so taking it directly is what makes the two agree by construction instead of
51
+ * by a lookup that a typo could point elsewhere.
52
+ *
53
+ * @returns `child`, so a caller can append and use it in one expression.
54
+ */
55
+ export function appendChild<TChild extends AstNode>(container: AstNode, property: string, children: TChild[], child: TChild): TChild {
56
+ const mutable = child as Mutable<TChild>;
57
+ mutable.$container = container;
58
+ mutable.$containerProperty = property;
59
+ mutable.$containerIndex = children.length;
60
+ children.push(child);
61
+ return child;
62
+ }
63
+
64
+ /**
65
+ * Remove every entry of `children` that is in `toRemove`, then renumber the
66
+ * survivors' `$containerIndex`.
67
+ *
68
+ * Mutates `children` in place rather than returning a new array, because the
69
+ * caller's array IS the AST's containment list — replacing the reference would
70
+ * leave the parent pointing at the old one.
71
+ *
72
+ * @returns how many entries were removed, so a caller can tell a no-op delete
73
+ * from one that changed the model without comparing lengths itself.
74
+ */
75
+ export function removeChildren<TChild extends AstNode>(children: TChild[], toRemove: ReadonlySet<TChild>): number {
76
+ if (toRemove.size === 0) {
77
+ return 0;
78
+ }
79
+ const survivors = children.filter(child => !toRemove.has(child));
80
+ const removed = children.length - survivors.length;
81
+ children.length = 0;
82
+ for (const [index, child] of survivors.entries()) {
83
+ (child as Mutable<TChild>).$containerIndex = index;
84
+ children.push(child);
85
+ }
86
+ return removed;
87
+ }
@@ -7,6 +7,7 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
+ export * from './containment.js';
10
11
  export * from './element-key-provider.js';
11
12
  export * from './name-based-key-provider.js';
12
13
  export * from './positional-key-provider.js';
@@ -55,6 +55,10 @@ import { type NameProvider } from '../naming/name-provider.js';
55
55
  * - After a removal, surviving siblings need their `$containerIndex`
56
56
  * renumbered, or a key derived afterwards addresses the wrong node.
57
57
  *
58
+ * {@link appendChild} and {@link removeChildren} discharge both, and ship
59
+ * beside this provider because the constraint is this provider's rather than
60
+ * any caller's.
61
+ *
58
62
  * Adopters that need insert / delete stability for unnamed types should
59
63
  * give those types a name in the grammar, or bind a key provider whose
60
64
  * fallback is content-derived rather than positional.