@hydranium/core 1.0.0-next.24 → 1.0.0-next.242

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 (649) hide show
  1. package/README.md +23 -18
  2. package/lib/documents/ast-document-manager.d.ts +219 -122
  3. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  4. package/lib/documents/ast-document-manager.js +241 -130
  5. package/lib/documents/ast-document-manager.js.map +1 -1
  6. package/lib/documents/client-ids.d.ts +5 -19
  7. package/lib/documents/client-ids.d.ts.map +1 -1
  8. package/lib/documents/client-ids.js +5 -19
  9. package/lib/documents/client-ids.js.map +1 -1
  10. package/lib/documents/client-session-errors.d.ts +15 -0
  11. package/lib/documents/client-session-errors.d.ts.map +1 -0
  12. package/lib/documents/client-session-errors.js +15 -0
  13. package/lib/documents/client-session-errors.js.map +1 -0
  14. package/lib/documents/client-session-registry.d.ts +146 -0
  15. package/lib/documents/client-session-registry.d.ts.map +1 -0
  16. package/lib/documents/client-session-registry.js +207 -0
  17. package/lib/documents/client-session-registry.js.map +1 -0
  18. package/lib/documents/dirty-state-tracker.d.ts +79 -0
  19. package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
  20. package/lib/documents/dirty-state-tracker.js +69 -0
  21. package/lib/documents/dirty-state-tracker.js.map +1 -0
  22. package/lib/documents/document-release-handler.d.ts +179 -0
  23. package/lib/documents/document-release-handler.d.ts.map +1 -0
  24. package/lib/documents/document-release-handler.js +283 -0
  25. package/lib/documents/document-release-handler.js.map +1 -0
  26. package/lib/documents/document-release-scheduler.d.ts +67 -0
  27. package/lib/documents/document-release-scheduler.d.ts.map +1 -0
  28. package/lib/documents/document-release-scheduler.js +80 -0
  29. package/lib/documents/document-release-scheduler.js.map +1 -0
  30. package/lib/documents/file-system-task-queue.d.ts +49 -0
  31. package/lib/documents/file-system-task-queue.d.ts.map +1 -0
  32. package/lib/documents/file-system-task-queue.js +34 -0
  33. package/lib/documents/file-system-task-queue.js.map +1 -0
  34. package/lib/documents/hydranium-text-documents.d.ts +399 -282
  35. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  36. package/lib/documents/hydranium-text-documents.js +816 -483
  37. package/lib/documents/hydranium-text-documents.js.map +1 -1
  38. package/lib/documents/index.d.ts +10 -2
  39. package/lib/documents/index.d.ts.map +1 -1
  40. package/lib/documents/index.js +10 -2
  41. package/lib/documents/index.js.map +1 -1
  42. package/lib/documents/language-client-shadow.d.ts +218 -0
  43. package/lib/documents/language-client-shadow.d.ts.map +1 -0
  44. package/lib/documents/language-client-shadow.js +283 -0
  45. package/lib/documents/language-client-shadow.js.map +1 -0
  46. package/lib/documents/model-ledger.d.ts +47 -0
  47. package/lib/documents/model-ledger.d.ts.map +1 -0
  48. package/lib/documents/model-ledger.js +30 -0
  49. package/lib/documents/model-ledger.js.map +1 -0
  50. package/lib/documents/text-ledger.d.ts +64 -0
  51. package/lib/documents/text-ledger.d.ts.map +1 -0
  52. package/lib/documents/text-ledger.js +63 -0
  53. package/lib/documents/text-ledger.js.map +1 -0
  54. package/lib/documents/version-sync-service.d.ts +134 -0
  55. package/lib/documents/version-sync-service.d.ts.map +1 -0
  56. package/lib/documents/version-sync-service.js +171 -0
  57. package/lib/documents/version-sync-service.js.map +1 -0
  58. package/lib/index.d.ts +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.map +1 -1
  63. package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
  64. package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
  65. package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
  66. package/lib/langium/ast-extension/ast-node-builder.js +60 -22
  67. package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
  68. package/lib/langium/bootstrap.d.ts +23 -16
  69. package/lib/langium/bootstrap.d.ts.map +1 -1
  70. package/lib/langium/bootstrap.js +66 -28
  71. package/lib/langium/bootstrap.js.map +1 -1
  72. package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
  73. package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
  74. package/lib/langium/composite-ast-reflection.d.ts +46 -0
  75. package/lib/langium/composite-ast-reflection.d.ts.map +1 -0
  76. package/lib/langium/composite-ast-reflection.js +97 -0
  77. package/lib/langium/composite-ast-reflection.js.map +1 -0
  78. package/lib/langium/config/configuration-provider.d.ts +81 -0
  79. package/lib/langium/config/configuration-provider.d.ts.map +1 -0
  80. package/lib/langium/config/configuration-provider.js +112 -0
  81. package/lib/langium/config/configuration-provider.js.map +1 -0
  82. package/lib/langium/config/index.d.ts +1 -0
  83. package/lib/langium/config/index.d.ts.map +1 -1
  84. package/lib/langium/config/index.js +1 -0
  85. package/lib/langium/config/index.js.map +1 -1
  86. package/lib/langium/config/settings.js.map +1 -1
  87. package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
  88. package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
  89. package/lib/langium/diagnostics/logger.d.ts +10 -3
  90. package/lib/langium/diagnostics/logger.d.ts.map +1 -1
  91. package/lib/langium/diagnostics/logger.js +12 -5
  92. package/lib/langium/diagnostics/logger.js.map +1 -1
  93. package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
  94. package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
  95. package/lib/langium/diagnostics/lsp-logger.js +57 -16
  96. package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
  97. package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
  98. package/lib/langium/diagnostics/server-tracer.js.map +1 -1
  99. package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
  100. package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
  101. package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
  102. package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
  103. package/lib/langium/document-builder/build-session.d.ts.map +1 -1
  104. package/lib/langium/document-builder/build-session.js.map +1 -1
  105. package/lib/langium/document-builder/document-builder.d.ts +294 -33
  106. package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
  107. package/lib/langium/document-builder/document-builder.js +477 -61
  108. package/lib/langium/document-builder/document-builder.js.map +1 -1
  109. package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
  110. package/lib/langium/documentation/comment-provider.js.map +1 -1
  111. package/lib/langium/integration-services.d.ts +61 -19
  112. package/lib/langium/integration-services.d.ts.map +1 -1
  113. package/lib/langium/integration-services.js +10 -5
  114. package/lib/langium/integration-services.js.map +1 -1
  115. package/lib/langium/integrity/integrity-rule.d.ts +16 -8
  116. package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
  117. package/lib/langium/integrity/integrity-rule.js.map +1 -1
  118. package/lib/langium/integrity/integrity-service.d.ts +81 -24
  119. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  120. package/lib/langium/integrity/integrity-service.js +264 -57
  121. package/lib/langium/integrity/integrity-service.js.map +1 -1
  122. package/lib/langium/keys/containment.d.ts +64 -0
  123. package/lib/langium/keys/containment.d.ts.map +1 -0
  124. package/lib/langium/keys/containment.js +53 -0
  125. package/lib/langium/keys/containment.js.map +1 -0
  126. package/lib/langium/keys/index.d.ts +1 -0
  127. package/lib/langium/keys/index.d.ts.map +1 -1
  128. package/lib/langium/keys/index.js +1 -0
  129. package/lib/langium/keys/index.js.map +1 -1
  130. package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
  131. package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
  132. package/lib/langium/keys/name-based-key-provider.js +4 -0
  133. package/lib/langium/keys/name-based-key-provider.js.map +1 -1
  134. package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
  135. package/lib/langium/keys/positional-key-provider.js.map +1 -1
  136. package/lib/langium/labeling/label-provider.d.ts.map +1 -1
  137. package/lib/langium/labeling/label-provider.js.map +1 -1
  138. package/lib/langium/language-module.d.ts +29 -4
  139. package/lib/langium/language-module.d.ts.map +1 -1
  140. package/lib/langium/language-module.js +18 -4
  141. package/lib/langium/language-module.js.map +1 -1
  142. package/lib/langium/model-service/client-session.d.ts +343 -0
  143. package/lib/langium/model-service/client-session.d.ts.map +1 -0
  144. package/lib/langium/model-service/client-session.js +411 -0
  145. package/lib/langium/model-service/client-session.js.map +1 -0
  146. package/lib/langium/model-service/index.d.ts +2 -0
  147. package/lib/langium/model-service/index.d.ts.map +1 -1
  148. package/lib/langium/model-service/index.js +2 -0
  149. package/lib/langium/model-service/index.js.map +1 -1
  150. package/lib/langium/model-service/model-events.d.ts +61 -0
  151. package/lib/langium/model-service/model-events.d.ts.map +1 -0
  152. package/lib/langium/model-service/model-events.js +10 -0
  153. package/lib/langium/model-service/model-events.js.map +1 -0
  154. package/lib/langium/model-service/model-service.d.ts +432 -282
  155. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  156. package/lib/langium/model-service/model-service.js +504 -438
  157. package/lib/langium/model-service/model-service.js.map +1 -1
  158. package/lib/langium/module.d.ts +150 -35
  159. package/lib/langium/module.d.ts.map +1 -1
  160. package/lib/langium/module.js +47 -35
  161. package/lib/langium/module.js.map +1 -1
  162. package/lib/langium/naming/name-provider.d.ts +25 -4
  163. package/lib/langium/naming/name-provider.d.ts.map +1 -1
  164. package/lib/langium/naming/name-provider.js +2 -1
  165. package/lib/langium/naming/name-provider.js.map +1 -1
  166. package/lib/langium/naming/name-separator-validation.d.ts +23 -0
  167. package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
  168. package/lib/langium/naming/name-separator-validation.js +30 -1
  169. package/lib/langium/naming/name-separator-validation.js.map +1 -1
  170. package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
  171. package/lib/langium/project/abstract-project-manager.js +9 -2
  172. package/lib/langium/project/abstract-project-manager.js.map +1 -1
  173. package/lib/langium/project/project-change-event.d.ts +2 -2
  174. package/lib/langium/project/single-project-manager.d.ts.map +1 -1
  175. package/lib/langium/project/single-project-manager.js.map +1 -1
  176. package/lib/langium/residency/cst-residency-service.d.ts +30 -10
  177. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  178. package/lib/langium/residency/cst-residency-service.js +23 -57
  179. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  180. package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
  181. package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
  182. package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
  183. package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
  184. package/lib/langium/scope/hydranium-scope-provider.d.ts +48 -13
  185. package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
  186. package/lib/langium/scope/hydranium-scope-provider.js +56 -20
  187. package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
  188. package/lib/langium/scope/reference-builder.d.ts.map +1 -1
  189. package/lib/langium/scope/reference-builder.js.map +1 -1
  190. package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
  191. package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
  192. package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
  193. package/lib/langium/scope/scope-extension-service.js.map +1 -1
  194. package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
  195. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  196. package/lib/langium/serialization/abstract-serializer.js +12 -21
  197. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  198. package/lib/langium/serialization/json-serializer.d.ts +1 -1
  199. package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
  200. package/lib/langium/serialization/json-serializer.js.map +1 -1
  201. package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
  202. package/lib/langium/serialization/yaml-serializer.js.map +1 -1
  203. package/lib/langium/service-registry.d.ts +29 -1
  204. package/lib/langium/service-registry.d.ts.map +1 -1
  205. package/lib/langium/service-registry.js +37 -0
  206. package/lib/langium/service-registry.js.map +1 -1
  207. package/lib/langium/shared-services.d.ts +21 -6
  208. package/lib/langium/shared-services.d.ts.map +1 -1
  209. package/lib/langium/shared-services.js.map +1 -1
  210. package/lib/langium/single-langium-copy.d.ts +22 -0
  211. package/lib/langium/single-langium-copy.d.ts.map +1 -0
  212. package/lib/langium/single-langium-copy.js +36 -0
  213. package/lib/langium/single-langium-copy.js.map +1 -0
  214. package/lib/langium/transfer/transfer-encoder.d.ts +77 -26
  215. package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
  216. package/lib/langium/transfer/transfer-encoder.js +46 -24
  217. package/lib/langium/transfer/transfer-encoder.js.map +1 -1
  218. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  219. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  220. package/lib/langium/trivia/comment-preserver.js +906 -0
  221. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  222. package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
  223. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  224. package/lib/langium/trivia/document-ending-preserver.js +48 -0
  225. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  226. package/lib/langium/trivia/index.d.ts +14 -0
  227. package/lib/langium/trivia/index.d.ts.map +1 -0
  228. package/lib/langium/trivia/index.js +14 -0
  229. package/lib/langium/trivia/index.js.map +1 -0
  230. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  231. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  232. package/lib/langium/trivia/trivia-contribution.js +10 -0
  233. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  234. package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
  235. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  236. package/lib/langium/trivia/trivia-preserver.js +10 -0
  237. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  238. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  239. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  240. package/lib/langium/trivia/trivia-service.js +56 -0
  241. package/lib/langium/trivia/trivia-service.js.map +1 -0
  242. package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
  243. package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
  244. package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
  245. package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
  246. package/lib/langium/validation/document-validator.d.ts +280 -9
  247. package/lib/langium/validation/document-validator.d.ts.map +1 -1
  248. package/lib/langium/validation/document-validator.js +448 -5
  249. package/lib/langium/validation/document-validator.js.map +1 -1
  250. package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
  251. package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
  252. package/lib/langium/validation/validation-contribution-collector.js +1 -1
  253. package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
  254. package/lib/langium/workspace/document-uri-policy.d.ts +15 -10
  255. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  256. package/lib/langium/workspace/document-uri-policy.js +7 -5
  257. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  258. package/lib/langium/workspace/file-not-found.d.ts +23 -0
  259. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  260. package/lib/langium/workspace/file-not-found.js +31 -0
  261. package/lib/langium/workspace/file-not-found.js.map +1 -0
  262. package/lib/langium/workspace/file-system-provider.d.ts +135 -9
  263. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  264. package/lib/langium/workspace/file-system-provider.js +93 -14
  265. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  266. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
  267. package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
  268. package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
  269. package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
  270. package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
  271. package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
  272. package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
  273. package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
  274. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +82 -9
  275. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  276. package/lib/langium/workspace/hydranium-workspace-manager.js +128 -10
  277. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  278. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -3
  279. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  280. package/lib/langium/workspace/in-memory-file-system-provider.js +41 -15
  281. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  282. package/lib/langium/workspace/index-manager.d.ts.map +1 -1
  283. package/lib/langium/workspace/index-manager.js.map +1 -1
  284. package/lib/langium/workspace/index.d.ts +1 -0
  285. package/lib/langium/workspace/index.d.ts.map +1 -1
  286. package/lib/langium/workspace/index.js +1 -0
  287. package/lib/langium/workspace/index.js.map +1 -1
  288. package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
  289. package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
  290. package/lib/langium/workspace/initialize-workspace.js +13 -5
  291. package/lib/langium/workspace/initialize-workspace.js.map +1 -1
  292. package/lib/langium/workspace/langium-documents.d.ts +46 -4
  293. package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
  294. package/lib/langium/workspace/langium-documents.js +60 -5
  295. package/lib/langium/workspace/langium-documents.js.map +1 -1
  296. package/lib/langium/workspace/persistent-file-system-provider.d.ts +1 -8
  297. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  298. package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
  299. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  300. package/lib/{documents → langium/workspace}/self-save-registry.d.ts +38 -7
  301. package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
  302. package/lib/{documents → langium/workspace}/self-save-registry.js +29 -16
  303. package/lib/langium/workspace/self-save-registry.js.map +1 -0
  304. package/lib/langium/workspace/virtual-document.d.ts +48 -15
  305. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  306. package/lib/langium/workspace/virtual-document.js +78 -18
  307. package/lib/langium/workspace/virtual-document.js.map +1 -1
  308. package/lib/langium/workspace/write-lock-scope.d.ts +20 -10
  309. package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
  310. package/lib/langium/workspace/write-lock-scope.js +12 -4
  311. package/lib/langium/workspace/write-lock-scope.js.map +1 -1
  312. package/lib/locale/index.d.ts +10 -0
  313. package/lib/locale/index.d.ts.map +1 -0
  314. package/lib/locale/index.js +10 -0
  315. package/lib/locale/index.js.map +1 -0
  316. package/lib/locale/server-locale.d.ts +73 -0
  317. package/lib/locale/server-locale.d.ts.map +1 -0
  318. package/lib/locale/server-locale.js +61 -0
  319. package/lib/locale/server-locale.js.map +1 -0
  320. package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
  321. package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
  322. package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
  323. package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
  324. package/lib/lsp/connection-features.d.ts +23 -0
  325. package/lib/lsp/connection-features.d.ts.map +1 -0
  326. package/lib/lsp/connection-features.js +60 -0
  327. package/lib/lsp/connection-features.js.map +1 -0
  328. package/lib/lsp/diagnostics-connection.d.ts +27 -0
  329. package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
  330. package/lib/lsp/diagnostics-connection.js +53 -0
  331. package/lib/lsp/diagnostics-connection.js.map +1 -0
  332. package/lib/lsp/hydranium-document-update-handler.d.ts +92 -81
  333. package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
  334. package/lib/lsp/hydranium-document-update-handler.js +153 -99
  335. package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
  336. package/lib/lsp/index.d.ts +3 -1
  337. package/lib/lsp/index.d.ts.map +1 -1
  338. package/lib/lsp/index.js +3 -1
  339. package/lib/lsp/index.js.map +1 -1
  340. package/lib/lsp/lsp-latency.d.ts +39 -0
  341. package/lib/lsp/lsp-latency.d.ts.map +1 -0
  342. package/lib/lsp/lsp-latency.js +58 -0
  343. package/lib/lsp/lsp-latency.js.map +1 -0
  344. package/lib/lsp/semantic-token-provider.d.ts +34 -1
  345. package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
  346. package/lib/lsp/semantic-token-provider.js +55 -8
  347. package/lib/lsp/semantic-token-provider.js.map +1 -1
  348. package/lib/lsp/shared-module.d.ts +4 -8
  349. package/lib/lsp/shared-module.d.ts.map +1 -1
  350. package/lib/lsp/shared-module.js.map +1 -1
  351. package/lib/lsp/start-language-server.d.ts +8 -7
  352. package/lib/lsp/start-language-server.d.ts.map +1 -1
  353. package/lib/lsp/start-language-server.js +13 -7
  354. package/lib/lsp/start-language-server.js.map +1 -1
  355. package/lib/messages/carriers.d.ts +54 -0
  356. package/lib/messages/carriers.d.ts.map +1 -0
  357. package/lib/messages/carriers.js +62 -0
  358. package/lib/messages/carriers.js.map +1 -0
  359. package/lib/messages/index.d.ts +25 -0
  360. package/lib/messages/index.d.ts.map +1 -0
  361. package/lib/messages/index.js +25 -0
  362. package/lib/messages/index.js.map +1 -0
  363. package/lib/messages/renderer.d.ts +142 -0
  364. package/lib/messages/renderer.d.ts.map +1 -0
  365. package/lib/messages/renderer.js +165 -0
  366. package/lib/messages/renderer.js.map +1 -0
  367. package/lib/node/event-loop-monitor.js.map +1 -1
  368. package/lib/node/heap-ceiling.d.ts +61 -0
  369. package/lib/node/heap-ceiling.d.ts.map +1 -0
  370. package/lib/node/heap-ceiling.js +72 -0
  371. package/lib/node/heap-ceiling.js.map +1 -0
  372. package/lib/node/index.d.ts +1 -1
  373. package/lib/node/index.d.ts.map +1 -1
  374. package/lib/node/index.js +1 -1
  375. package/lib/node/index.js.map +1 -1
  376. package/lib/node/latency-from-env.d.ts +1 -1
  377. package/lib/node/latency-from-env.js +1 -1
  378. package/lib/node/lint-grammar.js.map +1 -1
  379. package/lib/node/measure-memory.d.ts.map +1 -1
  380. package/lib/node/measure-memory.js +1 -0
  381. package/lib/node/measure-memory.js.map +1 -1
  382. package/lib/node/memory-monitor.js.map +1 -1
  383. package/lib/node/node-file-system-provider.d.ts +41 -6
  384. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  385. package/lib/node/node-file-system-provider.js +109 -49
  386. package/lib/node/node-file-system-provider.js.map +1 -1
  387. package/lib/node/profile-capture.d.ts +8 -2
  388. package/lib/node/profile-capture.d.ts.map +1 -1
  389. package/lib/node/profile-capture.js +1 -1
  390. package/lib/node/profile-capture.js.map +1 -1
  391. package/lib/node/profile-digest.js.map +1 -1
  392. package/lib/node/profiling-run.d.ts +13 -3
  393. package/lib/node/profiling-run.d.ts.map +1 -1
  394. package/lib/node/profiling-run.js +17 -8
  395. package/lib/node/profiling-run.js.map +1 -1
  396. package/lib/node/rename-over-open-readers.d.ts +52 -0
  397. package/lib/node/rename-over-open-readers.d.ts.map +1 -0
  398. package/lib/node/rename-over-open-readers.js +66 -0
  399. package/lib/node/rename-over-open-readers.js.map +1 -0
  400. package/lib/node/socket-launcher.d.ts +20 -4
  401. package/lib/node/socket-launcher.d.ts.map +1 -1
  402. package/lib/node/socket-launcher.js +5 -4
  403. package/lib/node/socket-launcher.js.map +1 -1
  404. package/lib/node/stdio-launcher.d.ts +6 -5
  405. package/lib/node/stdio-launcher.d.ts.map +1 -1
  406. package/lib/node/stdio-launcher.js +2 -2
  407. package/lib/node/stdio-launcher.js.map +1 -1
  408. package/lib/testing/document-uri-policy-conformance.js.map +1 -1
  409. package/lib/testing/fake-description.js.map +1 -1
  410. package/lib/testing/fake-document.d.ts +16 -4
  411. package/lib/testing/fake-document.d.ts.map +1 -1
  412. package/lib/testing/fake-document.js +18 -3
  413. package/lib/testing/fake-document.js.map +1 -1
  414. package/lib/testing/index.d.ts +1 -1
  415. package/lib/testing/index.d.ts.map +1 -1
  416. package/lib/testing/index.js +2 -1
  417. package/lib/testing/index.js.map +1 -1
  418. package/lib/testing/langium-test-helpers.d.ts.map +1 -1
  419. package/lib/testing/langium-test-helpers.js +1 -0
  420. package/lib/testing/langium-test-helpers.js.map +1 -1
  421. package/lib/testing/make-noop-language-services.js.map +1 -1
  422. package/lib/testing/make-noop-shared-services.d.ts +14 -0
  423. package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
  424. package/lib/testing/make-noop-shared-services.js +28 -2
  425. package/lib/testing/make-noop-shared-services.js.map +1 -1
  426. package/lib/testing/make-test-services.d.ts +72 -14
  427. package/lib/testing/make-test-services.d.ts.map +1 -1
  428. package/lib/testing/make-test-services.js +42 -10
  429. package/lib/testing/make-test-services.js.map +1 -1
  430. package/lib/testing/make-test-tracer.d.ts +12 -0
  431. package/lib/testing/make-test-tracer.d.ts.map +1 -1
  432. package/lib/testing/make-test-tracer.js +13 -0
  433. package/lib/testing/make-test-tracer.js.map +1 -1
  434. package/lib/testing/node/golden-corpus.js.map +1 -1
  435. package/lib/testing/node/index.d.ts +1 -0
  436. package/lib/testing/node/index.d.ts.map +1 -1
  437. package/lib/testing/node/index.js +1 -0
  438. package/lib/testing/node/index.js.map +1 -1
  439. package/lib/testing/node/lsp-harness.d.ts.map +1 -1
  440. package/lib/testing/node/lsp-harness.js +2 -0
  441. package/lib/testing/node/lsp-harness.js.map +1 -1
  442. package/lib/testing/node/lsp-server-connection.d.ts +11 -3
  443. package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
  444. package/lib/testing/node/lsp-server-connection.js +43 -10
  445. package/lib/testing/node/lsp-server-connection.js.map +1 -1
  446. package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
  447. package/lib/testing/node/scratch-workspace.js +10 -5
  448. package/lib/testing/node/scratch-workspace.js.map +1 -1
  449. package/lib/testing/node/spawned-server.d.ts +14 -0
  450. package/lib/testing/node/spawned-server.d.ts.map +1 -1
  451. package/lib/testing/node/spawned-server.js +34 -2
  452. package/lib/testing/node/spawned-server.js.map +1 -1
  453. package/lib/testing/node/unhandled-rejections.d.ts +20 -0
  454. package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
  455. package/lib/testing/node/unhandled-rejections.js +32 -0
  456. package/lib/testing/node/unhandled-rejections.js.map +1 -0
  457. package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
  458. package/lib/testing/playwright/e2e-profiling.js.map +1 -1
  459. package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
  460. package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
  461. package/lib/testing/playwright/flaky-network-proxy.js +164 -0
  462. package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
  463. package/lib/testing/playwright/index.d.ts +1 -0
  464. package/lib/testing/playwright/index.d.ts.map +1 -1
  465. package/lib/testing/playwright/index.js +1 -0
  466. package/lib/testing/playwright/index.js.map +1 -1
  467. package/lib/testing/playwright/server-log-capture.d.ts +24 -8
  468. package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
  469. package/lib/testing/playwright/server-log-capture.js +27 -6
  470. package/lib/testing/playwright/server-log-capture.js.map +1 -1
  471. package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
  472. package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
  473. package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
  474. package/lib/testing/run-update-pipeline.d.ts +4 -4
  475. package/lib/testing/run-update-pipeline.d.ts.map +1 -1
  476. package/lib/testing/stub-ast-document-manager.d.ts +11 -52
  477. package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
  478. package/lib/testing/stub-ast-document-manager.js +24 -65
  479. package/lib/testing/stub-ast-document-manager.js.map +1 -1
  480. package/lib/testing/stub-document-builder.d.ts +26 -11
  481. package/lib/testing/stub-document-builder.d.ts.map +1 -1
  482. package/lib/testing/stub-document-builder.js +78 -5
  483. package/lib/testing/stub-document-builder.js.map +1 -1
  484. package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
  485. package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
  486. package/lib/testing/stub-hydranium-text-documents.js +115 -16
  487. package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
  488. package/lib/testing/stub-index-manager.js.map +1 -1
  489. package/lib/testing/stub-langium-documents.d.ts +3 -2
  490. package/lib/testing/stub-langium-documents.d.ts.map +1 -1
  491. package/lib/testing/stub-langium-documents.js.map +1 -1
  492. package/lib/testing/stub-model-service.d.ts +7 -6
  493. package/lib/testing/stub-model-service.d.ts.map +1 -1
  494. package/lib/testing/stub-model-service.js +4 -4
  495. package/lib/testing/stub-model-service.js.map +1 -1
  496. package/lib/testing/stub-project-manager.js.map +1 -1
  497. package/lib/testing/stub-self-save-registry.d.ts +1 -1
  498. package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
  499. package/lib/testing/stub-service-registry.d.ts +1 -1
  500. package/lib/testing/stub-service-registry.js.map +1 -1
  501. package/lib/testing/stub-writable-file-system.d.ts +1 -1
  502. package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
  503. package/lib/util/connection-liveness.d.ts +7 -6
  504. package/lib/util/connection-liveness.d.ts.map +1 -1
  505. package/lib/util/connection-liveness.js +35 -14
  506. package/lib/util/connection-liveness.js.map +1 -1
  507. package/lib/util/environment.d.ts.map +1 -1
  508. package/lib/util/environment.js.map +1 -1
  509. package/lib/util/registry.d.ts.map +1 -1
  510. package/package.json +32 -48
  511. package/src/documents/ast-document-manager.ts +379 -231
  512. package/src/documents/client-ids.ts +5 -22
  513. package/src/documents/client-session-errors.ts +24 -0
  514. package/src/documents/client-session-registry.ts +262 -0
  515. package/src/documents/dirty-state-tracker.ts +130 -0
  516. package/src/documents/document-release-handler.ts +365 -0
  517. package/src/documents/document-release-scheduler.ts +121 -0
  518. package/src/documents/file-system-task-queue.ts +68 -0
  519. package/src/documents/hydranium-text-documents.ts +931 -595
  520. package/src/documents/index.ts +10 -2
  521. package/src/documents/language-client-shadow.ts +451 -0
  522. package/src/documents/model-ledger.ts +66 -0
  523. package/src/documents/text-ledger.ts +112 -0
  524. package/src/documents/version-sync-service.ts +267 -0
  525. package/src/index.ts +8 -0
  526. package/src/langium/ast-extension/ast-node-builder.ts +66 -22
  527. package/src/langium/bootstrap.ts +66 -28
  528. package/src/langium/composite-ast-reflection.ts +112 -0
  529. package/src/langium/config/configuration-provider.ts +119 -0
  530. package/src/langium/config/index.ts +1 -0
  531. package/src/langium/diagnostics/logger.ts +12 -5
  532. package/src/langium/diagnostics/lsp-logger.ts +59 -15
  533. package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
  534. package/src/langium/document-builder/document-builder.ts +565 -59
  535. package/src/langium/integration-services.ts +83 -24
  536. package/src/langium/integrity/integrity-rule.ts +16 -8
  537. package/src/langium/integrity/integrity-service.ts +287 -62
  538. package/src/langium/keys/containment.ts +87 -0
  539. package/src/langium/keys/index.ts +1 -0
  540. package/src/langium/keys/name-based-key-provider.ts +4 -0
  541. package/src/langium/language-module.ts +48 -7
  542. package/src/langium/model-service/client-session.ts +644 -0
  543. package/src/langium/model-service/index.ts +2 -0
  544. package/src/langium/model-service/model-events.ts +75 -0
  545. package/src/langium/model-service/model-service.ts +790 -468
  546. package/src/langium/module.ts +199 -64
  547. package/src/langium/naming/name-provider.ts +27 -5
  548. package/src/langium/naming/name-separator-validation.ts +34 -5
  549. package/src/langium/project/abstract-project-manager.ts +9 -1
  550. package/src/langium/project/project-change-event.ts +2 -2
  551. package/src/langium/residency/cst-residency-service.ts +45 -14
  552. package/src/langium/scope/hydranium-scope-provider.ts +60 -22
  553. package/src/langium/serialization/abstract-serializer.ts +13 -32
  554. package/src/langium/service-registry.ts +41 -2
  555. package/src/langium/shared-services.ts +21 -6
  556. package/src/langium/single-langium-copy.ts +42 -0
  557. package/src/langium/transfer/transfer-encoder.ts +104 -37
  558. package/src/langium/trivia/comment-preserver.ts +1100 -0
  559. package/src/langium/trivia/document-ending-preserver.ts +55 -0
  560. package/src/langium/trivia/index.ts +14 -0
  561. package/src/langium/trivia/trivia-contribution.ts +39 -0
  562. package/src/langium/trivia/trivia-preserver.ts +54 -0
  563. package/src/langium/trivia/trivia-service.ts +99 -0
  564. package/src/langium/update-rewrite/update-rewrite.ts +1 -1
  565. package/src/langium/validation/document-validator.ts +523 -10
  566. package/src/langium/validation/validation-contribution-collector.ts +10 -1
  567. package/src/langium/workspace/document-uri-policy.ts +15 -10
  568. package/src/langium/workspace/file-not-found.ts +35 -0
  569. package/src/langium/workspace/file-system-provider.ts +205 -17
  570. package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
  571. package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
  572. package/src/langium/workspace/hydranium-workspace-manager.ts +154 -14
  573. package/src/langium/workspace/in-memory-file-system-provider.ts +48 -17
  574. package/src/langium/workspace/index.ts +1 -0
  575. package/src/langium/workspace/initialize-workspace.ts +43 -5
  576. package/src/langium/workspace/langium-documents.ts +75 -6
  577. package/src/langium/workspace/persistent-file-system-provider.ts +1 -8
  578. package/src/{documents → langium/workspace}/self-save-registry.ts +54 -15
  579. package/src/langium/workspace/virtual-document.ts +96 -19
  580. package/src/langium/workspace/write-lock-scope.ts +24 -11
  581. package/src/locale/index.ts +10 -0
  582. package/src/locale/server-locale.ts +86 -0
  583. package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
  584. package/src/lsp/connection-features.ts +67 -0
  585. package/src/lsp/diagnostics-connection.ts +56 -0
  586. package/src/lsp/hydranium-document-update-handler.ts +187 -108
  587. package/src/lsp/index.ts +3 -1
  588. package/src/lsp/lsp-latency.ts +62 -0
  589. package/src/lsp/semantic-token-provider.ts +74 -7
  590. package/src/lsp/shared-module.ts +4 -8
  591. package/src/lsp/start-language-server.ts +13 -7
  592. package/src/messages/carriers.ts +78 -0
  593. package/src/messages/index.ts +36 -0
  594. package/src/messages/renderer.ts +212 -0
  595. package/src/node/heap-ceiling.ts +108 -0
  596. package/src/node/index.ts +1 -1
  597. package/src/node/latency-from-env.ts +1 -1
  598. package/src/node/measure-memory.ts +1 -0
  599. package/src/node/node-file-system-provider.ts +124 -53
  600. package/src/node/profile-capture.ts +9 -3
  601. package/src/node/profiling-run.ts +30 -8
  602. package/src/node/rename-over-open-readers.ts +78 -0
  603. package/src/node/socket-launcher.ts +24 -8
  604. package/src/node/stdio-launcher.ts +8 -7
  605. package/src/testing/fake-document.ts +24 -5
  606. package/src/testing/index.ts +2 -1
  607. package/src/testing/langium-test-helpers.ts +1 -0
  608. package/src/testing/make-noop-shared-services.ts +50 -2
  609. package/src/testing/make-test-services.ts +125 -31
  610. package/src/testing/make-test-tracer.ts +26 -0
  611. package/src/testing/node/index.ts +1 -0
  612. package/src/testing/node/lsp-harness.ts +2 -0
  613. package/src/testing/node/lsp-server-connection.ts +66 -12
  614. package/src/testing/node/scratch-workspace.ts +10 -5
  615. package/src/testing/node/spawned-server.ts +36 -2
  616. package/src/testing/node/unhandled-rejections.ts +31 -0
  617. package/src/testing/parse-semantic-root.ts +1 -1
  618. package/src/testing/playwright/flaky-network-proxy.ts +240 -0
  619. package/src/testing/playwright/index.ts +1 -0
  620. package/src/testing/playwright/server-log-capture.ts +45 -11
  621. package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
  622. package/src/testing/run-update-pipeline.ts +4 -4
  623. package/src/testing/stub-ast-document-manager.ts +36 -138
  624. package/src/testing/stub-document-builder.ts +102 -18
  625. package/src/testing/stub-hydranium-text-documents.ts +165 -27
  626. package/src/testing/stub-langium-documents.ts +3 -2
  627. package/src/testing/stub-model-service.ts +9 -8
  628. package/src/testing/stub-self-save-registry.ts +1 -1
  629. package/src/testing/stub-service-registry.ts +1 -1
  630. package/src/testing/stub-writable-file-system.ts +1 -1
  631. package/src/util/connection-liveness.ts +37 -14
  632. package/src/util/environment.ts +9 -1
  633. package/lib/documents/language-client-text-shadow.d.ts +0 -101
  634. package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
  635. package/lib/documents/language-client-text-shadow.js +0 -156
  636. package/lib/documents/language-client-text-shadow.js.map +0 -1
  637. package/lib/documents/self-save-registry.d.ts.map +0 -1
  638. package/lib/documents/self-save-registry.js.map +0 -1
  639. package/lib/lsp/instrument-connection.d.ts +0 -36
  640. package/lib/lsp/instrument-connection.d.ts.map +0 -1
  641. package/lib/lsp/instrument-connection.js +0 -62
  642. package/lib/lsp/instrument-connection.js.map +0 -1
  643. package/lib/node/process-memory.d.ts +0 -66
  644. package/lib/node/process-memory.d.ts.map +0 -1
  645. package/lib/node/process-memory.js +0 -252
  646. package/lib/node/process-memory.js.map +0 -1
  647. package/src/documents/language-client-text-shadow.ts +0 -175
  648. package/src/lsp/instrument-connection.ts +0 -66
  649. package/src/node/process-memory.ts +0 -299
@@ -7,28 +7,54 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
- import { type LogThreshold, type MaybeObservableValue, ObservableValue, type Tracer, TransferDiagnostic } from '@hydranium/protocol';
10
+ import {
11
+ defineMessage,
12
+ describeError,
13
+ interpolate,
14
+ type MessageDefinition,
15
+ type MessageParams,
16
+ messageData,
17
+ type ParamsArg,
18
+ type ParamsOf,
19
+ type LogThreshold,
20
+ type MaybeObservableValue,
21
+ ObservableValue,
22
+ type Tracer,
23
+ TransferDiagnostic
24
+ } from '@hydranium/protocol';
11
25
  import {
12
26
  type AstNode,
13
27
  type AstNodeLocator,
28
+ type AstReflection,
14
29
  DefaultDocumentValidator,
15
30
  type DiagnosticInfo,
31
+ DocumentValidator,
16
32
  type LangiumDocument,
17
33
  type LangiumCoreServices,
34
+ type Lexer,
18
35
  type ValidateSingleNodeOptions,
19
36
  type ValidationOptions,
20
37
  type ValidationSeverity
21
38
  } from '@hydranium/langium';
22
39
  import type { CancellationToken } from 'vscode-languageserver-protocol';
23
- import type { Diagnostic } from 'vscode-languageserver-types';
40
+ // A VALUE import, for `Diagnostic.getMessageString`: `message` is
41
+ // `string | MarkupContent` in LSP 3.17+, so upstream's own reader is what
42
+ // narrows it rather than a hand-rolled union check here.
43
+ import { Diagnostic } from 'vscode-languageserver-types';
24
44
  import { type LogNameOptions } from '../diagnostics/logger.js';
25
45
  import { isSyntheticNode } from '../workspace/synthetic.js';
26
46
  import { isVirtualUri } from '../workspace/virtual-document.js';
27
47
 
28
48
  /**
29
- * Diagnostic read off a `LangiumDocument`: an LSP {@link Diagnostic} that MAY
30
- * carry the protocol-level `element` path and `property` name from
31
- * {@link TransferDiagnostic}.
49
+ * The AST-layer diagnostic: what the build left on `LangiumDocument`, and what
50
+ * an `AstDocument` carries. An LSP {@link Diagnostic} that MAY also carry the
51
+ * `element` path and `property` name from {@link TransferDiagnostic}.
52
+ *
53
+ * **Not interchangeable with {@link TransferDiagnostic}, which is the other end
54
+ * of the same conversion.** They disagree on field types as well as on which
55
+ * fields exist — `severity` is LSP's numeric enum here and a string union there
56
+ * — so a slot typed with the wrong one still accepts the value and then reads
57
+ * `undefined`, or compares equal to nothing.
32
58
  *
33
59
  * `element` is optional because a document's diagnostics do not all come from
34
60
  * this validator. {@link HydraniumDocumentValidator.toDiagnostic} always sets
@@ -43,11 +69,182 @@ import { isVirtualUri } from '../workspace/virtual-document.js';
43
69
  * condition. Consumers therefore cast at the read, and the cast is sound only
44
70
  * because this field is optional.
45
71
  */
46
- export interface TransferLspDiagnostic extends Diagnostic {
72
+ export interface AstDiagnostic extends Diagnostic {
47
73
  element?: string;
48
74
  property?: string;
49
75
  }
50
76
 
77
+ /**
78
+ * A reference resolved to nothing.
79
+ *
80
+ * **The English is byte-identical to Langium's `DefaultLinker.createLinkingError`
81
+ * sentence, and must stay so.** The identity is attached to a diagnostic Langium
82
+ * already worded, so a divergence here would silently change the text every
83
+ * adopter without a catalogue sees. {@link HydraniumDocumentValidator.processLinkingErrors}
84
+ * attaches it only when the two match exactly, which is also what keeps an
85
+ * adopter's own reworded linking error from being mislabelled as this one.
86
+ *
87
+ * It exists because this is the most-seen validation error in any language built
88
+ * on the framework, and Langium puts its own code in `data.code` rather than on
89
+ * `Diagnostic.code` — so without a framework identity every adopter wanting to
90
+ * render it has to special-case Langium's shape.
91
+ */
92
+ export const UNRESOLVED_REFERENCE = defineMessage(
93
+ 'hydranium/core/unresolved-reference',
94
+ "Could not resolve reference to {referenceType} named '{refText}'."
95
+ );
96
+
97
+ /**
98
+ * A character no token of the grammar can start with.
99
+ *
100
+ * **The English is byte-identical to CHEVROTAIN's
101
+ * `defaultLexerErrorProvider.buildUnexpectedCharactersMessage`, and must stay
102
+ * so** — one layer further out than {@link UNRESOLVED_REFERENCE}, whose sentence
103
+ * is Langium's. Langium words neither: `processLexingErrors` copies
104
+ * `lexerDiagnostic.message` through untouched, so the text an adopter sees today
105
+ * is produced two dependencies down and is the only thing this identity may
106
+ * claim to be. {@link HydraniumDocumentValidator.identifyLexingError} attaches
107
+ * it only when the two match exactly, which is also what keeps a custom lexer's
108
+ * own diagnostics — Langium admits any of them through `lexerReport` — from
109
+ * being mislabelled as this one.
110
+ *
111
+ * It exists because a lexing error is the FIRST message a user of a new language
112
+ * sees and the one an adopter cannot reach: every other diagnostic worth
113
+ * translating either carries an identity already or is raised by adopter code,
114
+ * while this one arrives with a Langium `data.code` naming a KIND and no
115
+ * parameters at all — so a catalogue had nothing to key on and nothing to
116
+ * interpolate.
117
+ *
118
+ * `skipped` rather than `length`, matching what the sentence says the number
119
+ * means: chevrotain reports how many characters the lexer discarded to recover,
120
+ * which for a single stray character is one and for a run of them is the run.
121
+ */
122
+ export const UNEXPECTED_CHARACTER = defineMessage(
123
+ 'hydranium/core/unexpected-character',
124
+ 'unexpected character: ->{character}<- at offset: {offset}, skipped {skipped} characters.'
125
+ );
126
+
127
+ /**
128
+ * A token the grammar does not admit at this position.
129
+ *
130
+ * **The English is byte-identical to Langium's
131
+ * `LangiumParserErrorMessageProvider.buildMismatchTokenMessage`, and must stay
132
+ * so**, on the same rule as {@link UNRESOLVED_REFERENCE}.
133
+ *
134
+ * `expected` is a token type name, which is grammar vocabulary rather than
135
+ * translatable text — only the frame around it is. Promoting it into the code
136
+ * instead would make the catalogue as large as the grammar.
137
+ */
138
+ export const UNEXPECTED_TOKEN = defineMessage(
139
+ 'hydranium/core/unexpected-token',
140
+ "Expecting token of type '{expected}' but found `{found}`."
141
+ );
142
+
143
+ /**
144
+ * Input left over once the entry rule had matched.
145
+ *
146
+ * **The English is byte-identical to Langium's
147
+ * `LangiumParserErrorMessageProvider.buildNotAllInputParsedMessage`, and must
148
+ * stay so.**
149
+ */
150
+ export const TRAILING_INPUT = defineMessage('hydranium/core/trailing-input', 'Expecting end of file but found `{found}`.');
151
+
152
+ /**
153
+ * A mode-popping token reached with nothing on the lexer's mode stack.
154
+ *
155
+ * **The English is byte-identical to CHEVROTAIN's
156
+ * `defaultLexerErrorProvider.buildUnableToPopLexerModeMessage`, and must stay
157
+ * so**, the closing clause running on without punctuation exactly as upstream
158
+ * writes it.
159
+ *
160
+ * Reachable only from a multi-mode lexer, which a grammar opts into through a
161
+ * custom token builder.
162
+ */
163
+ export const UNPOPPABLE_LEXER_MODE = defineMessage(
164
+ 'hydranium/core/unpoppable-lexer-mode',
165
+ 'Unable to pop Lexer Mode after encountering Token ->{image}<- The Mode Stack is empty'
166
+ );
167
+
168
+ /**
169
+ * A dedent that lines up with no enclosing indentation level.
170
+ *
171
+ * **The English is byte-identical to LANGIUM's `IndentationAwareTokenBuilder`,
172
+ * and must stay so** — the one lexing sentence Langium words itself rather than
173
+ * relaying from chevrotain, which is why it renders through no
174
+ * `ILexerErrorMessageProvider` and an adopter cannot reach it by replacing one.
175
+ *
176
+ * `stack` is the indentation stack as the template literal upstream stringifies
177
+ * it, comma-joined: structure would have to survive {@link MessageParams}, which
178
+ * holds scalars, and a translation has nothing to say about the numbers anyway.
179
+ */
180
+ export const INVALID_DEDENT = defineMessage(
181
+ 'hydranium/core/invalid-dedent',
182
+ 'Invalid dedent level {level} at offset: {offset}. Current indentation stack: {stack}'
183
+ );
184
+
185
+ /**
186
+ * A position where none of a rule's alternatives can start.
187
+ *
188
+ * **The English is byte-identical to CHEVROTAIN's
189
+ * `defaultParserErrorProvider.buildNoViableAltMessage`, and must stay so** —
190
+ * one layer further out than {@link UNEXPECTED_TOKEN}, because Langium overrides
191
+ * only two of the four parser sentences and passes this one straight through.
192
+ *
193
+ * `sequences` is the token-sequence list chevrotain generated, carried whole
194
+ * rather than as structure: {@link MessageParams} holds scalars, and the list is
195
+ * token names in any case, so only the frame around it is translatable.
196
+ */
197
+ export const NO_VIABLE_ALTERNATIVE = defineMessage(
198
+ 'hydranium/core/no-viable-alternative',
199
+ "Expecting: one of these possible Token sequences:\n{sequences}\nbut found: '{found}'"
200
+ );
201
+
202
+ /**
203
+ * A repetition that had to match at least once and matched nothing.
204
+ *
205
+ * **The English is byte-identical to CHEVROTAIN's
206
+ * `defaultParserErrorProvider.buildEarlyExitMessage`, and must stay so**,
207
+ * including the doubled colon after `sequences::`, which is upstream's and not a
208
+ * typo to repair here — a divergence would silently stop the identity attaching.
209
+ *
210
+ * Named for the empty repetition rather than for chevrotain's `EarlyExit`, which
211
+ * describes its own control flow rather than the reader's problem.
212
+ */
213
+ export const MISSING_ITERATION = defineMessage(
214
+ 'hydranium/core/missing-iteration',
215
+ "Expecting: expecting at least one iteration which starts with one of these possible Token sequences::\n <{sequences}>\nbut found: '{found}'"
216
+ );
217
+
218
+ /**
219
+ * The two sentences whose only free parameter is a generated list, in the order
220
+ * {@link HydraniumDocumentValidator.identifyParsingError} tries them. Order is
221
+ * free: their frames share a prefix but diverge before the list begins, so at
222
+ * most one can match.
223
+ */
224
+ const SEQUENCE_LISTING_MESSAGES = [NO_VIABLE_ALTERNATIVE, MISSING_ITERATION];
225
+
226
+ /**
227
+ * Splits a template into alternating frame and placeholder NAME, for
228
+ * {@link HydraniumDocumentValidator.sliceFramed}. The capturing group is what
229
+ * keeps the names in the result rather than discarding them.
230
+ */
231
+ const PLACEHOLDER_CAPTURE = /\{([^}]+)\}/;
232
+
233
+ /**
234
+ * Langium's own `data.code` values for a diagnostic that came out of the lexer.
235
+ *
236
+ * All four severities, not just the error one: `lexerReport` admits warnings and
237
+ * below, and a token builder that downgrades a stray character still produces
238
+ * the same sentence. Gating on the error code alone would leave the identity off
239
+ * a message that is word-for-word the one it names.
240
+ */
241
+ const LEXING_CODES: ReadonlySet<unknown> = new Set([
242
+ DocumentValidator.LexingError,
243
+ DocumentValidator.LexingWarning,
244
+ DocumentValidator.LexingInfo,
245
+ DocumentValidator.LexingHint
246
+ ]);
247
+
51
248
  export interface DocumentValidatorOptions extends LogNameOptions {
52
249
  /**
53
250
  * Level at which the `validateDocument` timing line is emitted, or `'off'`
@@ -86,7 +283,7 @@ export interface DocumentValidatorOptions extends LogNameOptions {
86
283
  * - **Skip-validation hook** via the virtual {@link shouldSkipValidation}
87
284
  * predicate, which adopters override to compose additional skip reasons.
88
285
  * - **Diagnostic mapping** to {@link TransferDiagnostic}-shaped
89
- * {@link TransferLspDiagnostic}: every emitted diagnostic carries the AST
286
+ * {@link AstDiagnostic}: every emitted diagnostic carries the AST
90
287
  * node's path (built via Langium's `AstNodeLocator`) plus the optional
91
288
  * offending property name.
92
289
  * - **Optional timing wrap** on `validateDocument`, on by default.
@@ -94,6 +291,13 @@ export interface DocumentValidatorOptions extends LogNameOptions {
94
291
  export class HydraniumDocumentValidator extends DefaultDocumentValidator {
95
292
  protected readonly tracer: Tracer;
96
293
  protected readonly astNodeLocator: AstNodeLocator;
294
+ protected readonly reflection: AstReflection;
295
+ protected readonly lexer: Lexer;
296
+ /**
297
+ * {@link tokenTypeNames}' answer. Nothing invalidates it: the vocabulary
298
+ * comes from the grammar, which is fixed once the DI tree is composed.
299
+ */
300
+ protected expectedNames?: readonly string[];
97
301
  protected readonly logLevel: ObservableValue<LogThreshold>;
98
302
  protected readonly logAfterMs: ObservableValue<number>;
99
303
  protected readonly validateVirtualDocuments: ObservableValue<boolean>;
@@ -103,6 +307,8 @@ export class HydraniumDocumentValidator extends DefaultDocumentValidator {
103
307
  super(services);
104
308
  this.tracer = services.shared.Tracer.for(options.logName ?? 'DocumentValidator').trace('instantiated');
105
309
  this.astNodeLocator = services.workspace.AstNodeLocator;
310
+ this.reflection = services.shared.AstReflection;
311
+ this.lexer = services.parser.Lexer;
106
312
  this.logLevel = ObservableValue.from(options.logLevel ?? 'debug');
107
313
  this.logAfterMs = ObservableValue.from(options.logAfterMs ?? 20);
108
314
  this.validateVirtualDocuments = ObservableValue.from(options.validateVirtualDocuments ?? false);
@@ -124,16 +330,239 @@ export class HydraniumDocumentValidator extends DefaultDocumentValidator {
124
330
  }
125
331
  const level = this.logLevel.value;
126
332
  if (level === 'off') {
127
- return super.validateDocument(document, options, cancelToken);
333
+ return this.validateAndIdentify(document, options, cancelToken);
128
334
  }
129
335
  // `level` is narrowed to `LogLevel` past the early-return.
130
336
  return this.tracer
131
337
  .withUri(document.uri.toString())
132
- .time('validateDocument', () => super.validateDocument(document, options, cancelToken), level, {
338
+ .time('validateDocument', () => this.validateAndIdentify(document, options, cancelToken), level, {
133
339
  logAfterMs: this.logAfterMs.value
134
340
  });
135
341
  }
136
342
 
343
+ /**
344
+ * Langium's validation pass, plus the framework identity on the lexing and
345
+ * parsing diagnostics it produced.
346
+ *
347
+ * **Here rather than in an override of `processLexingErrors` /
348
+ * `processParsingErrors`, and the reason is that neither seam can see what
349
+ * the identity needs.** Langium hands them a `ParseResult`, which carries the
350
+ * AST and the error lists but not the source text — and the offending
351
+ * CHARACTER, or the offending TOKEN, is the parameter a translation exists to
352
+ * interpolate. The document does carry it, and this is the innermost point
353
+ * that still holds one.
354
+ *
355
+ * Correlating the finished diagnostics back to the `ParseResult`'s error
356
+ * lists positionally is the alternative, and it is unsound for the parsing
357
+ * half: `processParsingErrors` DROPS an error whose token offsets are `NaN`
358
+ * and whose exception carries no `previousToken`, so the two lists differ in
359
+ * length exactly when recovery has been at work.
360
+ *
361
+ * Inside the timing span rather than around it, so the line accounts for the
362
+ * whole pass.
363
+ */
364
+ protected async validateAndIdentify(
365
+ document: LangiumDocument,
366
+ options?: ValidationOptions,
367
+ cancelToken?: CancellationToken
368
+ ): Promise<Diagnostic[]> {
369
+ const diagnostics = await super.validateDocument(document, options, cancelToken);
370
+ // Mapped in place over the array Langium built, rather than filtered and
371
+ // re-concatenated: the publish order is the diagnostic order and a
372
+ // reordering would move a squiggle's entry in the problems list.
373
+ // Each pass guards on its own `data.code`, so at most one can claim a
374
+ // given diagnostic and the order between them carries no meaning.
375
+ for (let index = 0; index < diagnostics.length; index++) {
376
+ diagnostics[index] = this.identifyLexingError(document, diagnostics[index]);
377
+ diagnostics[index] = this.identifyParsingError(document, diagnostics[index]);
378
+ }
379
+ return diagnostics;
380
+ }
381
+
382
+ /**
383
+ * Add whichever lexing identity renders `diagnostic`'s sentence, or return it
384
+ * untouched when none of them does — a custom lexer's own report, which
385
+ * Langium admits through `lexerReport`, being the case that reaches the end.
386
+ *
387
+ * The parameters come from the diagnostic's own RANGE, not from
388
+ * `parseResult.lexerErrors`. Both hold the same numbers, and the range is the
389
+ * one that needs no assumption about upstream: correlating the two lists
390
+ * would depend on Langium appending one diagnostic per lexer error in order,
391
+ * which is true today and is an internal of the method being wrapped.
392
+ *
393
+ * **The format-and-compare is the whole discriminator, and it validates the
394
+ * reconstruction as well as the identity.** A range that did not round-trip
395
+ * to the offset chevrotain reported would produce a different sentence and be
396
+ * declined, so a wrong parameter set can never be attached to a right-looking
397
+ * message.
398
+ */
399
+ protected identifyLexingError(document: LangiumDocument, diagnostic: Diagnostic): Diagnostic {
400
+ const data = diagnostic.data as { code?: unknown } | undefined;
401
+ if (!LEXING_CODES.has(data?.code)) {
402
+ return diagnostic;
403
+ }
404
+ const text = document.textDocument;
405
+ const message = Diagnostic.getMessageString(diagnostic);
406
+ const offset = text.offsetAt(diagnostic.range.start);
407
+ const stray = {
408
+ character: text.getText().charAt(offset),
409
+ offset,
410
+ skipped: text.offsetAt(diagnostic.range.end) - offset
411
+ };
412
+ if (message === UNEXPECTED_CHARACTER.format(stray)) {
413
+ return this.identified(diagnostic, UNEXPECTED_CHARACTER, stray);
414
+ }
415
+ // The mode-pop error's range spans the offending token exactly, upstream
416
+ // reporting its `startOffset` with the image's own length.
417
+ const image = text.getText(diagnostic.range);
418
+ if (message === UNPOPPABLE_LEXER_MODE.format({ image })) {
419
+ return this.identified(diagnostic, UNPOPPABLE_LEXER_MODE, { image });
420
+ }
421
+ // `level` and `stack` are lexer state that reaches no field here, so they
422
+ // are sliced; `offset` is given, which is what anchors the slice.
423
+ const dedent = this.sliceFramed(message, INVALID_DEDENT, { offset });
424
+ return dedent === undefined ? diagnostic : this.identified(diagnostic, INVALID_DEDENT, dedent);
425
+ }
426
+
427
+ /**
428
+ * Add whichever parser identity renders `diagnostic`'s sentence, or return it
429
+ * untouched when none of them does — an adopter that replaced the parser
430
+ * error-message provider being the case that reaches the last branch.
431
+ *
432
+ * `found` comes from the diagnostic's own RANGE, for the same reason
433
+ * {@link identifyLexingError} reads its parameters there. A token whose
434
+ * offsets chevrotain could not report collapses to a zero-width range, which
435
+ * yields the empty string the sentence already renders for it.
436
+ *
437
+ * **`expected` is recovered by SEARCHING the vocabulary, because nothing
438
+ * carries it.** Chevrotain hands the expected token type to the message
439
+ * provider and keeps it on neither the exception nor the diagnostic, so the
440
+ * only structured source left is the grammar's own vocabulary: every token
441
+ * type is offered to the same `format` the identity renders with, and the one
442
+ * that reproduces the message supplies the parameter. Matching it out of the
443
+ * prose instead would derive a parameter from a sentence that a Langium
444
+ * reword can change without warning. Two distinct names cannot render one
445
+ * sentence, so the match is unique where it exists.
446
+ */
447
+ protected identifyParsingError(document: LangiumDocument, diagnostic: Diagnostic): Diagnostic {
448
+ const data = diagnostic.data as { code?: unknown } | undefined;
449
+ if (data?.code !== DocumentValidator.ParsingError) {
450
+ return diagnostic;
451
+ }
452
+ const message = Diagnostic.getMessageString(diagnostic);
453
+ const found = document.textDocument.getText(diagnostic.range);
454
+ if (message === TRAILING_INPUT.format({ found })) {
455
+ return this.identified(diagnostic, TRAILING_INPUT, { found });
456
+ }
457
+ const expected = this.tokenTypeNames().find(name => UNEXPECTED_TOKEN.format({ expected: name, found }) === message);
458
+ if (expected !== undefined) {
459
+ return this.identified(diagnostic, UNEXPECTED_TOKEN, { expected, found });
460
+ }
461
+ for (const definition of SEQUENCE_LISTING_MESSAGES) {
462
+ const params = this.sliceFramed(message, definition, { found });
463
+ if (params !== undefined) {
464
+ return this.identified(diagnostic, definition, params);
465
+ }
466
+ }
467
+ return diagnostic;
468
+ }
469
+
470
+ /** `diagnostic` carrying `definition`'s identity, over whatever `data` it already had. */
471
+ protected identified<S extends string>(diagnostic: Diagnostic, definition: MessageDefinition<S>, ...params: ParamsArg<S>): Diagnostic {
472
+ // Merged OVER the existing data, so Langium's `code` survives for the
473
+ // readers that switch on it — `stopAfterParsingErrors` is one, and the
474
+ // GLSP head's read-only decision is another.
475
+ const data = diagnostic.data as object | undefined;
476
+ return { ...diagnostic, code: definition.code, data: { ...data, ...messageData(definition, ...params) } };
477
+ }
478
+
479
+ /**
480
+ * `definition`'s parameters as they appear in `message`, taking the ones in
481
+ * `known` as given, or `undefined` when `message` is not that sentence.
482
+ *
483
+ * **The only parameters in this file taken OUT of the prose rather than
484
+ * derived and checked against it, and the bound on that is what `known`
485
+ * is for.** A generated token-sequence list, a lexer's indentation stack: for
486
+ * these there is no finite candidate set to offer to `format` the way a token
487
+ * type name can be, and no structured field carries them. What keeps the read
488
+ * honest is that everything else in the sentence is either a fixed literal or
489
+ * a parameter the caller derived independently, so the frame either matches
490
+ * exactly or the sentence is declined.
491
+ *
492
+ * **The trailing format-and-compare is load-bearing once more than one
493
+ * parameter is unknown.** Each is captured up to the NEXT fixed separator, so
494
+ * a separator that also occurs inside a value would cut early — re-rendering
495
+ * catches that, where for a single unknown between two affixes it could not
496
+ * fail. Two adjacent placeholders are declined outright: nothing marks the
497
+ * boundary, so no capture is recoverable.
498
+ *
499
+ * The frame is split off the declaration's own `text`, so it cannot drift
500
+ * from the sentence `format` renders.
501
+ */
502
+ protected sliceFramed<S extends string>(
503
+ message: string,
504
+ definition: MessageDefinition<S>,
505
+ known: MessageParams
506
+ ): ParamsOf<S> | undefined {
507
+ // `split` with a capturing group interleaves literals and placeholder
508
+ // names, so even indices are frame and odd ones are parameters.
509
+ const parts = definition.text.split(PLACEHOLDER_CAPTURE);
510
+ const params: Record<string, string | number> = { ...known };
511
+ let cursor = 0;
512
+ for (let index = 0; index < parts.length; index += 2) {
513
+ const literal = parts[index];
514
+ if (!message.startsWith(literal, cursor)) {
515
+ return undefined;
516
+ }
517
+ cursor += literal.length;
518
+ const name = parts[index + 1];
519
+ if (name === undefined) {
520
+ break;
521
+ }
522
+ const given = params[name];
523
+ if (given !== undefined) {
524
+ const rendered = String(given);
525
+ if (!message.startsWith(rendered, cursor)) {
526
+ return undefined;
527
+ }
528
+ cursor += rendered.length;
529
+ continue;
530
+ }
531
+ const separator = parts[index + 2];
532
+ const trailing = parts[index + 3] === undefined;
533
+ if (separator === '' && !trailing) {
534
+ return undefined;
535
+ }
536
+ const at = trailing && separator === '' ? message.length : message.indexOf(separator, cursor);
537
+ if (at < cursor) {
538
+ return undefined;
539
+ }
540
+ params[name] = message.slice(cursor, at);
541
+ cursor = at;
542
+ }
543
+ if (cursor !== message.length || interpolate(definition.text, params) !== message) {
544
+ return undefined;
545
+ }
546
+ // Narrowing only: every placeholder the template names was either given or
547
+ // captured above, which is precisely what `ParamsOf` requires.
548
+ return params as ParamsOf<S>;
549
+ }
550
+
551
+ /**
552
+ * Every token type name the grammar declares, as
553
+ * {@link identifyParsingError} candidates.
554
+ *
555
+ * Read off the lexer, whose `definition` the `Lexer` INTERFACE declares —
556
+ * the parser holds the same vocabulary only behind Langium's default class,
557
+ * where an adopter's replacement need not keep it. A token type the parser
558
+ * expects but the lexer does not declare yields no match, which declines the
559
+ * identity rather than attaching a wrong one.
560
+ */
561
+ protected tokenTypeNames(): readonly string[] {
562
+ this.expectedNames ??= Object.keys(this.lexer.definition);
563
+ return this.expectedNames;
564
+ }
565
+
137
566
  /**
138
567
  * Skip validation for a node **and its children** when
139
568
  * {@link shouldSkipValidation} returns true.
@@ -157,11 +586,95 @@ export class HydraniumDocumentValidator extends DefaultDocumentValidator {
157
586
  return !this.validateSyntheticNodes.value && isSyntheticNode(node);
158
587
  }
159
588
 
589
+ /**
590
+ * Langium's linking-error pass, plus the framework identity on each
591
+ * diagnostic it produced.
592
+ *
593
+ * Langium puts its own `linking-error` marker in `data.code` and leaves
594
+ * `Diagnostic.code` unset, so nothing identifies the message on a surface
595
+ * that drops `data` — which is every editor surface. This adds the framework
596
+ * identity to both `code` and `data.hydranium` while LEAVING `data.code` in
597
+ * place: `stopAfterLinkingErrors` and Langium's code-action dispatch both
598
+ * read it.
599
+ *
600
+ * **The identity is attached only when the message is the one
601
+ * {@link UNRESOLVED_REFERENCE} renders.** Two other sentences reach this
602
+ * list: the linker's exception form, raised when resolution itself throws,
603
+ * and whatever an adopter overriding `createLinkingError` chose. Labelling
604
+ * either would make a catalogue render the wrong sentence — and for the
605
+ * exception form it would discard the underlying cause. Comparing against
606
+ * the locally rendered English is what discriminates; there is no structural
607
+ * field that does.
608
+ */
609
+ protected override processLinkingErrors(document: LangiumDocument, diagnostics: Diagnostic[], options: ValidationOptions): void {
610
+ const from = diagnostics.length;
611
+ super.processLinkingErrors(document, diagnostics, options);
612
+ for (let index = from; index < diagnostics.length; index++) {
613
+ diagnostics[index] = this.identifyLinkingError(diagnostics[index]);
614
+ }
615
+ }
616
+
617
+ /**
618
+ * Add the {@link UNRESOLVED_REFERENCE} identity to one linking diagnostic,
619
+ * or return it untouched when its message is not the sentence that identity
620
+ * renders.
621
+ *
622
+ * `refText` comes from the `data` Langium populated; `referenceType` is not
623
+ * in it, so it is recovered the same way `createLinkingError` produced it —
624
+ * through the reflection, from the container type and property.
625
+ */
626
+ protected identifyLinkingError(diagnostic: Diagnostic): Diagnostic {
627
+ const data = diagnostic.data as { code?: unknown; refText?: unknown; containerType?: unknown; property?: unknown } | undefined;
628
+ if (typeof data?.refText !== 'string' || typeof data.containerType !== 'string' || typeof data.property !== 'string') {
629
+ return diagnostic;
630
+ }
631
+ const referenceType = this.referenceTypeOf(data.containerType, data.property, data.refText);
632
+ if (referenceType === undefined) {
633
+ return diagnostic;
634
+ }
635
+ const params = { referenceType, refText: data.refText };
636
+ if (diagnostic.message !== UNRESOLVED_REFERENCE.format(params)) {
637
+ return diagnostic;
638
+ }
639
+ // Merged OVER Langium's data rather than replacing it, so `data.code`
640
+ // survives for the readers that switch on it.
641
+ return { ...diagnostic, code: UNRESOLVED_REFERENCE.code, data: { ...data, ...messageData(UNRESOLVED_REFERENCE, params) } };
642
+ }
643
+
644
+ /**
645
+ * The declared target type of the reference this diagnostic came from, or
646
+ * `undefined` when the reflection cannot name one.
647
+ *
648
+ * **The lookup can throw, and that is the reason this is a method rather
649
+ * than an inline call.** `AbstractAstReflection.getReferenceType` raises on
650
+ * an unknown container `$type` and on a property that is not a reference —
651
+ * and the linking error whose type it cannot name is the one most likely to
652
+ * reach here, because `DefaultLinker` catches its OWN failed lookup and
653
+ * turns it into the exception-form message. Rethrowing would take
654
+ * `validateDocument` with it, since Langium wraps `processLinkingErrors` in
655
+ * no try: a diagnostic Langium degraded gracefully would become a failed
656
+ * build. Declining is also the right answer on the merits — a reference
657
+ * whose type cannot be named is not the message
658
+ * {@link UNRESOLVED_REFERENCE} claims.
659
+ */
660
+ protected referenceTypeOf(containerType: string, property: string, refText: string): string | undefined {
661
+ try {
662
+ return this.reflection.getReferenceType({
663
+ container: { $type: containerType } as AstNode,
664
+ property,
665
+ reference: { $refText: refText }
666
+ } as Parameters<AstReflection['getReferenceType']>[0]);
667
+ } catch (err: unknown) {
668
+ this.tracer.debug(`cannot name the reference type for ${containerType}.${property}: ${describeError(err)}`);
669
+ return undefined;
670
+ }
671
+ }
672
+
160
673
  protected override toDiagnostic<N extends AstNode>(
161
674
  severity: ValidationSeverity,
162
675
  message: string,
163
676
  info: DiagnosticInfo<N, string>
164
- ): TransferLspDiagnostic {
677
+ ): AstDiagnostic {
165
678
  const base = super.toDiagnostic(severity, message, info);
166
679
  const node = info.node;
167
680
  if (!node) {
@@ -15,6 +15,15 @@ import { type ValidationCheckRegistry } from './validation-contribution.js';
15
15
 
16
16
  export type ValidationContributionCollectorOptions = LogNameOptions;
17
17
 
18
+ /**
19
+ * The validation-collector slot. Empty because the service registers checks in
20
+ * its constructor and nothing calls it; typing the slot by the class would stop
21
+ * an adopter's subclass from a second package copy satisfying it. The cost: any
22
+ * non-null value satisfies it, so a mis-bound slot compiles and registers no check.
23
+ */
24
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- the slot has no public member to name
25
+ export interface ValidationContributionCollector {}
26
+
18
27
  /**
19
28
  * Per-language eager collector that wires `ValidationCheckContribution`s
20
29
  * declared under `services.validation.checks` into Langium's native
@@ -32,7 +41,7 @@ export type ValidationContributionCollectorOptions = LogNameOptions;
32
41
  * DI proxy. That is what gets the checks into the registry before Langium
33
42
  * reaches the `Validated` phase — nothing else constructs this service.
34
43
  */
35
- export class ValidationContributionCollector {
44
+ export class DefaultValidationContributionCollector implements ValidationContributionCollector {
36
45
  protected readonly tracer: Tracer;
37
46
 
38
47
  constructor(services: ServerLanguageServices, options: ValidationContributionCollectorOptions = {}) {