@hydranium/core 1.0.0-next.22 → 1.0.0-next.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -8
- package/lib/documents/ast-document-manager.d.ts +219 -122
- package/lib/documents/ast-document-manager.d.ts.map +1 -1
- package/lib/documents/ast-document-manager.js +241 -130
- package/lib/documents/ast-document-manager.js.map +1 -1
- package/lib/documents/client-ids.d.ts +5 -19
- package/lib/documents/client-ids.d.ts.map +1 -1
- package/lib/documents/client-ids.js +5 -19
- package/lib/documents/client-ids.js.map +1 -1
- package/lib/documents/client-session-errors.d.ts +15 -0
- package/lib/documents/client-session-errors.d.ts.map +1 -0
- package/lib/documents/client-session-errors.js +15 -0
- package/lib/documents/client-session-errors.js.map +1 -0
- package/lib/documents/client-session-registry.d.ts +146 -0
- package/lib/documents/client-session-registry.d.ts.map +1 -0
- package/lib/documents/client-session-registry.js +207 -0
- package/lib/documents/client-session-registry.js.map +1 -0
- package/lib/documents/dirty-state-tracker.d.ts +79 -0
- package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
- package/lib/documents/dirty-state-tracker.js +69 -0
- package/lib/documents/dirty-state-tracker.js.map +1 -0
- package/lib/documents/document-release-handler.d.ts +179 -0
- package/lib/documents/document-release-handler.d.ts.map +1 -0
- package/lib/documents/document-release-handler.js +283 -0
- package/lib/documents/document-release-handler.js.map +1 -0
- package/lib/documents/document-release-scheduler.d.ts +67 -0
- package/lib/documents/document-release-scheduler.d.ts.map +1 -0
- package/lib/documents/document-release-scheduler.js +80 -0
- package/lib/documents/document-release-scheduler.js.map +1 -0
- package/lib/documents/file-system-task-queue.d.ts +49 -0
- package/lib/documents/file-system-task-queue.d.ts.map +1 -0
- package/lib/documents/file-system-task-queue.js +34 -0
- package/lib/documents/file-system-task-queue.js.map +1 -0
- package/lib/documents/hydranium-text-documents.d.ts +399 -282
- package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
- package/lib/documents/hydranium-text-documents.js +816 -483
- package/lib/documents/hydranium-text-documents.js.map +1 -1
- package/lib/documents/index.d.ts +10 -2
- package/lib/documents/index.d.ts.map +1 -1
- package/lib/documents/index.js +10 -2
- package/lib/documents/index.js.map +1 -1
- package/lib/documents/language-client-shadow.d.ts +218 -0
- package/lib/documents/language-client-shadow.d.ts.map +1 -0
- package/lib/documents/language-client-shadow.js +283 -0
- package/lib/documents/language-client-shadow.js.map +1 -0
- package/lib/documents/model-ledger.d.ts +47 -0
- package/lib/documents/model-ledger.d.ts.map +1 -0
- package/lib/documents/model-ledger.js +30 -0
- package/lib/documents/model-ledger.js.map +1 -0
- package/lib/documents/text-ledger.d.ts +64 -0
- package/lib/documents/text-ledger.d.ts.map +1 -0
- package/lib/documents/text-ledger.js +63 -0
- package/lib/documents/text-ledger.js.map +1 -0
- package/lib/documents/version-sync-service.d.ts +134 -0
- package/lib/documents/version-sync-service.d.ts.map +1 -0
- package/lib/documents/version-sync-service.js +171 -0
- package/lib/documents/version-sync-service.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -0
- package/lib/index.js.map +1 -1
- package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
- package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
- package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
- package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
- package/lib/langium/ast-extension/ast-node-builder.js +60 -22
- package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
- package/lib/langium/bootstrap.d.ts +5 -5
- package/lib/langium/bootstrap.d.ts.map +1 -1
- package/lib/langium/bootstrap.js +42 -17
- package/lib/langium/bootstrap.js.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
- package/lib/langium/composite-ast-reflection.d.ts +43 -0
- package/lib/langium/composite-ast-reflection.d.ts.map +1 -0
- package/lib/langium/composite-ast-reflection.js +92 -0
- package/lib/langium/composite-ast-reflection.js.map +1 -0
- package/lib/langium/config/configuration-provider.d.ts +81 -0
- package/lib/langium/config/configuration-provider.d.ts.map +1 -0
- package/lib/langium/config/configuration-provider.js +112 -0
- package/lib/langium/config/configuration-provider.js.map +1 -0
- package/lib/langium/config/index.d.ts +1 -0
- package/lib/langium/config/index.d.ts.map +1 -1
- package/lib/langium/config/index.js +1 -0
- package/lib/langium/config/index.js.map +1 -1
- package/lib/langium/config/settings.js.map +1 -1
- package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
- package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
- package/lib/langium/diagnostics/logger.d.ts +10 -3
- package/lib/langium/diagnostics/logger.d.ts.map +1 -1
- package/lib/langium/diagnostics/logger.js +12 -5
- package/lib/langium/diagnostics/logger.js.map +1 -1
- package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
- package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
- package/lib/langium/diagnostics/lsp-logger.js +57 -16
- package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
- package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
- package/lib/langium/diagnostics/server-tracer.js.map +1 -1
- package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
- package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
- package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
- package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
- package/lib/langium/document-builder/build-session.d.ts +93 -0
- package/lib/langium/document-builder/build-session.d.ts.map +1 -0
- package/lib/langium/document-builder/build-session.js +72 -0
- package/lib/langium/document-builder/build-session.js.map +1 -0
- package/lib/langium/document-builder/document-builder.d.ts +401 -29
- package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
- package/lib/langium/document-builder/document-builder.js +698 -61
- package/lib/langium/document-builder/document-builder.js.map +1 -1
- package/lib/langium/document-builder/index.d.ts +1 -0
- package/lib/langium/document-builder/index.d.ts.map +1 -1
- package/lib/langium/document-builder/index.js +1 -0
- package/lib/langium/document-builder/index.js.map +1 -1
- package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
- package/lib/langium/documentation/comment-provider.js.map +1 -1
- package/lib/langium/integration-services.d.ts +61 -19
- package/lib/langium/integration-services.d.ts.map +1 -1
- package/lib/langium/integration-services.js +10 -5
- package/lib/langium/integration-services.js.map +1 -1
- package/lib/langium/integrity/integrity-rule.d.ts +16 -8
- package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-rule.js.map +1 -1
- package/lib/langium/integrity/integrity-service.d.ts +81 -24
- package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-service.js +264 -57
- package/lib/langium/integrity/integrity-service.js.map +1 -1
- package/lib/langium/keys/containment.d.ts +64 -0
- package/lib/langium/keys/containment.d.ts.map +1 -0
- package/lib/langium/keys/containment.js +53 -0
- package/lib/langium/keys/containment.js.map +1 -0
- package/lib/langium/keys/index.d.ts +1 -0
- package/lib/langium/keys/index.d.ts.map +1 -1
- package/lib/langium/keys/index.js +1 -0
- package/lib/langium/keys/index.js.map +1 -1
- package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
- package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/name-based-key-provider.js +4 -0
- package/lib/langium/keys/name-based-key-provider.js.map +1 -1
- package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/positional-key-provider.js.map +1 -1
- package/lib/langium/labeling/label-provider.d.ts.map +1 -1
- package/lib/langium/labeling/label-provider.js.map +1 -1
- package/lib/langium/language-module.d.ts +29 -4
- package/lib/langium/language-module.d.ts.map +1 -1
- package/lib/langium/language-module.js +18 -4
- package/lib/langium/language-module.js.map +1 -1
- package/lib/langium/model-service/client-session.d.ts +343 -0
- package/lib/langium/model-service/client-session.d.ts.map +1 -0
- package/lib/langium/model-service/client-session.js +411 -0
- package/lib/langium/model-service/client-session.js.map +1 -0
- package/lib/langium/model-service/index.d.ts +2 -0
- package/lib/langium/model-service/index.d.ts.map +1 -1
- package/lib/langium/model-service/index.js +2 -0
- package/lib/langium/model-service/index.js.map +1 -1
- package/lib/langium/model-service/model-events.d.ts +61 -0
- package/lib/langium/model-service/model-events.d.ts.map +1 -0
- package/lib/langium/model-service/model-events.js +10 -0
- package/lib/langium/model-service/model-events.js.map +1 -0
- package/lib/langium/model-service/model-service.d.ts +432 -282
- package/lib/langium/model-service/model-service.d.ts.map +1 -1
- package/lib/langium/model-service/model-service.js +504 -438
- package/lib/langium/model-service/model-service.js.map +1 -1
- package/lib/langium/module.d.ts +157 -35
- package/lib/langium/module.d.ts.map +1 -1
- package/lib/langium/module.js +52 -35
- package/lib/langium/module.js.map +1 -1
- package/lib/langium/naming/name-provider.d.ts +25 -4
- package/lib/langium/naming/name-provider.d.ts.map +1 -1
- package/lib/langium/naming/name-provider.js +2 -1
- package/lib/langium/naming/name-provider.js.map +1 -1
- package/lib/langium/naming/name-separator-validation.d.ts +23 -0
- package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
- package/lib/langium/naming/name-separator-validation.js +30 -1
- package/lib/langium/naming/name-separator-validation.js.map +1 -1
- package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
- package/lib/langium/project/abstract-project-manager.js +9 -2
- package/lib/langium/project/abstract-project-manager.js.map +1 -1
- package/lib/langium/project/project-change-event.d.ts +2 -2
- package/lib/langium/project/single-project-manager.d.ts.map +1 -1
- package/lib/langium/project/single-project-manager.js.map +1 -1
- package/lib/langium/residency/cst-residency-service.d.ts +31 -11
- package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
- package/lib/langium/residency/cst-residency-service.js +23 -57
- package/lib/langium/residency/cst-residency-service.js.map +1 -1
- package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
- package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
- package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
- package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
- package/lib/langium/scope/hydranium-scope-provider.d.ts +48 -13
- package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
- package/lib/langium/scope/hydranium-scope-provider.js +56 -20
- package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
- package/lib/langium/scope/reference-builder.d.ts.map +1 -1
- package/lib/langium/scope/reference-builder.js.map +1 -1
- package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
- package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
- package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
- package/lib/langium/scope/scope-extension-service.js.map +1 -1
- package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
- package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/abstract-serializer.js +12 -21
- package/lib/langium/serialization/abstract-serializer.js.map +1 -1
- package/lib/langium/serialization/json-serializer.d.ts +1 -1
- package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/json-serializer.js.map +1 -1
- package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/yaml-serializer.js.map +1 -1
- package/lib/langium/service-registry.d.ts +29 -1
- package/lib/langium/service-registry.d.ts.map +1 -1
- package/lib/langium/service-registry.js +37 -0
- package/lib/langium/service-registry.js.map +1 -1
- package/lib/langium/shared-services.d.ts +23 -6
- package/lib/langium/shared-services.d.ts.map +1 -1
- package/lib/langium/shared-services.js.map +1 -1
- package/lib/langium/transfer/transfer-encoder.d.ts +77 -26
- package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
- package/lib/langium/transfer/transfer-encoder.js +46 -24
- package/lib/langium/transfer/transfer-encoder.js.map +1 -1
- package/lib/langium/trivia/comment-preserver.d.ts +423 -0
- package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/comment-preserver.js +906 -0
- package/lib/langium/trivia/comment-preserver.js.map +1 -0
- package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
- package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/document-ending-preserver.js +48 -0
- package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
- package/lib/langium/trivia/index.d.ts +14 -0
- package/lib/langium/trivia/index.d.ts.map +1 -0
- package/lib/langium/trivia/index.js +14 -0
- package/lib/langium/trivia/index.js.map +1 -0
- package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
- package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-contribution.js +10 -0
- package/lib/langium/trivia/trivia-contribution.js.map +1 -0
- package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
- package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-preserver.js +10 -0
- package/lib/langium/trivia/trivia-preserver.js.map +1 -0
- package/lib/langium/trivia/trivia-service.d.ts +70 -0
- package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-service.js +56 -0
- package/lib/langium/trivia/trivia-service.js.map +1 -0
- package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
- package/lib/langium/validation/document-validator.d.ts +294 -10
- package/lib/langium/validation/document-validator.d.ts.map +1 -1
- package/lib/langium/validation/document-validator.js +448 -5
- package/lib/langium/validation/document-validator.js.map +1 -1
- package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
- package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
- package/lib/langium/validation/validation-contribution-collector.js +1 -1
- package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
- package/lib/langium/workspace/document-uri-policy.d.ts +18 -14
- package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
- package/lib/langium/workspace/document-uri-policy.js +10 -9
- package/lib/langium/workspace/document-uri-policy.js.map +1 -1
- package/lib/langium/workspace/file-not-found.d.ts +23 -0
- package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
- package/lib/langium/workspace/file-not-found.js +31 -0
- package/lib/langium/workspace/file-not-found.js.map +1 -0
- package/lib/langium/workspace/file-system-provider.d.ts +135 -9
- package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/file-system-provider.js +93 -14
- package/lib/langium/workspace/file-system-provider.js.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
- package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts +82 -9
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.js +128 -10
- package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -3
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.js +41 -15
- package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
- package/lib/langium/workspace/index-manager.d.ts.map +1 -1
- package/lib/langium/workspace/index-manager.js.map +1 -1
- package/lib/langium/workspace/index.d.ts +1 -0
- package/lib/langium/workspace/index.d.ts.map +1 -1
- package/lib/langium/workspace/index.js +1 -0
- package/lib/langium/workspace/index.js.map +1 -1
- package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
- package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
- package/lib/langium/workspace/initialize-workspace.js +13 -5
- package/lib/langium/workspace/initialize-workspace.js.map +1 -1
- package/lib/langium/workspace/langium-documents.d.ts +86 -17
- package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
- package/lib/langium/workspace/langium-documents.js +101 -29
- package/lib/langium/workspace/langium-documents.js.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.d.ts +1 -8
- package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
- package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
- package/lib/{documents → langium/workspace}/self-save-registry.d.ts +38 -7
- package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
- package/lib/{documents → langium/workspace}/self-save-registry.js +29 -16
- package/lib/langium/workspace/self-save-registry.js.map +1 -0
- package/lib/langium/workspace/virtual-document.d.ts +48 -15
- package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
- package/lib/langium/workspace/virtual-document.js +78 -18
- package/lib/langium/workspace/virtual-document.js.map +1 -1
- package/lib/langium/workspace/write-lock-scope.d.ts +20 -10
- package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
- package/lib/langium/workspace/write-lock-scope.js +12 -4
- package/lib/langium/workspace/write-lock-scope.js.map +1 -1
- package/lib/locale/index.d.ts +10 -0
- package/lib/locale/index.d.ts.map +1 -0
- package/lib/locale/index.js +10 -0
- package/lib/locale/index.js.map +1 -0
- package/lib/locale/server-locale.d.ts +73 -0
- package/lib/locale/server-locale.d.ts.map +1 -0
- package/lib/locale/server-locale.js +61 -0
- package/lib/locale/server-locale.js.map +1 -0
- package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
- package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
- package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
- package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
- package/lib/lsp/connection-features.d.ts +23 -0
- package/lib/lsp/connection-features.d.ts.map +1 -0
- package/lib/lsp/connection-features.js +60 -0
- package/lib/lsp/connection-features.js.map +1 -0
- package/lib/lsp/diagnostics-connection.d.ts +27 -0
- package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
- package/lib/lsp/diagnostics-connection.js +53 -0
- package/lib/lsp/diagnostics-connection.js.map +1 -0
- package/lib/lsp/hydranium-document-update-handler.d.ts +92 -81
- package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.js +153 -99
- package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
- package/lib/lsp/index.d.ts +3 -1
- package/lib/lsp/index.d.ts.map +1 -1
- package/lib/lsp/index.js +3 -1
- package/lib/lsp/index.js.map +1 -1
- package/lib/lsp/lsp-latency.d.ts +39 -0
- package/lib/lsp/lsp-latency.d.ts.map +1 -0
- package/lib/lsp/lsp-latency.js +58 -0
- package/lib/lsp/lsp-latency.js.map +1 -0
- package/lib/lsp/semantic-token-provider.d.ts +34 -1
- package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
- package/lib/lsp/semantic-token-provider.js +55 -8
- package/lib/lsp/semantic-token-provider.js.map +1 -1
- package/lib/lsp/shared-module.d.ts +4 -8
- package/lib/lsp/shared-module.d.ts.map +1 -1
- package/lib/lsp/shared-module.js.map +1 -1
- package/lib/lsp/start-language-server.d.ts +8 -7
- package/lib/lsp/start-language-server.d.ts.map +1 -1
- package/lib/lsp/start-language-server.js +13 -7
- package/lib/lsp/start-language-server.js.map +1 -1
- package/lib/messages/carriers.d.ts +54 -0
- package/lib/messages/carriers.d.ts.map +1 -0
- package/lib/messages/carriers.js +62 -0
- package/lib/messages/carriers.js.map +1 -0
- package/lib/messages/index.d.ts +25 -0
- package/lib/messages/index.d.ts.map +1 -0
- package/lib/messages/index.js +25 -0
- package/lib/messages/index.js.map +1 -0
- package/lib/messages/renderer.d.ts +142 -0
- package/lib/messages/renderer.d.ts.map +1 -0
- package/lib/messages/renderer.js +165 -0
- package/lib/messages/renderer.js.map +1 -0
- package/lib/node/event-loop-monitor.js.map +1 -1
- package/lib/node/heap-ceiling.d.ts +61 -0
- package/lib/node/heap-ceiling.d.ts.map +1 -0
- package/lib/node/heap-ceiling.js +72 -0
- package/lib/node/heap-ceiling.js.map +1 -0
- package/lib/node/index.d.ts +1 -1
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +1 -1
- package/lib/node/index.js.map +1 -1
- package/lib/node/latency-from-env.d.ts +1 -1
- package/lib/node/latency-from-env.js +1 -1
- package/lib/node/lint-grammar.js.map +1 -1
- package/lib/node/measure-memory.d.ts.map +1 -1
- package/lib/node/measure-memory.js +1 -0
- package/lib/node/measure-memory.js.map +1 -1
- package/lib/node/memory-monitor.js.map +1 -1
- package/lib/node/node-file-system-provider.d.ts +41 -6
- package/lib/node/node-file-system-provider.d.ts.map +1 -1
- package/lib/node/node-file-system-provider.js +109 -49
- package/lib/node/node-file-system-provider.js.map +1 -1
- package/lib/node/profile-capture.d.ts +8 -2
- package/lib/node/profile-capture.d.ts.map +1 -1
- package/lib/node/profile-capture.js +1 -1
- package/lib/node/profile-capture.js.map +1 -1
- package/lib/node/profile-digest.js.map +1 -1
- package/lib/node/profiling-run.d.ts +13 -3
- package/lib/node/profiling-run.d.ts.map +1 -1
- package/lib/node/profiling-run.js +17 -8
- package/lib/node/profiling-run.js.map +1 -1
- package/lib/node/rename-over-open-readers.d.ts +52 -0
- package/lib/node/rename-over-open-readers.d.ts.map +1 -0
- package/lib/node/rename-over-open-readers.js +66 -0
- package/lib/node/rename-over-open-readers.js.map +1 -0
- package/lib/node/socket-launcher.d.ts +20 -4
- package/lib/node/socket-launcher.d.ts.map +1 -1
- package/lib/node/socket-launcher.js +5 -4
- package/lib/node/socket-launcher.js.map +1 -1
- package/lib/node/stdio-launcher.d.ts +6 -5
- package/lib/node/stdio-launcher.d.ts.map +1 -1
- package/lib/node/stdio-launcher.js +2 -2
- package/lib/node/stdio-launcher.js.map +1 -1
- package/lib/testing/document-uri-policy-conformance.js.map +1 -1
- package/lib/testing/fake-description.js.map +1 -1
- package/lib/testing/fake-document.d.ts +16 -4
- package/lib/testing/fake-document.d.ts.map +1 -1
- package/lib/testing/fake-document.js +18 -3
- package/lib/testing/fake-document.js.map +1 -1
- package/lib/testing/index.d.ts +1 -1
- package/lib/testing/index.d.ts.map +1 -1
- package/lib/testing/index.js +2 -1
- package/lib/testing/index.js.map +1 -1
- package/lib/testing/langium-test-helpers.d.ts.map +1 -1
- package/lib/testing/langium-test-helpers.js +1 -0
- package/lib/testing/langium-test-helpers.js.map +1 -1
- package/lib/testing/make-noop-language-services.js.map +1 -1
- package/lib/testing/make-noop-shared-services.d.ts +14 -0
- package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
- package/lib/testing/make-noop-shared-services.js +28 -2
- package/lib/testing/make-noop-shared-services.js.map +1 -1
- package/lib/testing/make-test-services.d.ts +72 -14
- package/lib/testing/make-test-services.d.ts.map +1 -1
- package/lib/testing/make-test-services.js +42 -10
- package/lib/testing/make-test-services.js.map +1 -1
- package/lib/testing/make-test-tracer.d.ts +12 -0
- package/lib/testing/make-test-tracer.d.ts.map +1 -1
- package/lib/testing/make-test-tracer.js +13 -0
- package/lib/testing/make-test-tracer.js.map +1 -1
- package/lib/testing/node/golden-corpus.js.map +1 -1
- package/lib/testing/node/index.d.ts +1 -0
- package/lib/testing/node/index.d.ts.map +1 -1
- package/lib/testing/node/index.js +1 -0
- package/lib/testing/node/index.js.map +1 -1
- package/lib/testing/node/lsp-harness.d.ts.map +1 -1
- package/lib/testing/node/lsp-harness.js +2 -0
- package/lib/testing/node/lsp-harness.js.map +1 -1
- package/lib/testing/node/lsp-server-connection.d.ts +11 -3
- package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
- package/lib/testing/node/lsp-server-connection.js +43 -10
- package/lib/testing/node/lsp-server-connection.js.map +1 -1
- package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
- package/lib/testing/node/scratch-workspace.js +10 -5
- package/lib/testing/node/scratch-workspace.js.map +1 -1
- package/lib/testing/node/spawned-server.d.ts +14 -0
- package/lib/testing/node/spawned-server.d.ts.map +1 -1
- package/lib/testing/node/spawned-server.js +34 -2
- package/lib/testing/node/spawned-server.js.map +1 -1
- package/lib/testing/node/unhandled-rejections.d.ts +20 -0
- package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
- package/lib/testing/node/unhandled-rejections.js +32 -0
- package/lib/testing/node/unhandled-rejections.js.map +1 -0
- package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
- package/lib/testing/playwright/e2e-profiling.js.map +1 -1
- package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
- package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
- package/lib/testing/playwright/flaky-network-proxy.js +164 -0
- package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
- package/lib/testing/playwright/index.d.ts +1 -0
- package/lib/testing/playwright/index.d.ts.map +1 -1
- package/lib/testing/playwright/index.js +1 -0
- package/lib/testing/playwright/index.js.map +1 -1
- package/lib/testing/playwright/server-log-capture.d.ts +24 -8
- package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-capture.js +27 -6
- package/lib/testing/playwright/server-log-capture.js.map +1 -1
- package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
- package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
- package/lib/testing/run-update-pipeline.d.ts +4 -4
- package/lib/testing/run-update-pipeline.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.d.ts +11 -52
- package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.js +24 -65
- package/lib/testing/stub-ast-document-manager.js.map +1 -1
- package/lib/testing/stub-document-builder.d.ts +26 -11
- package/lib/testing/stub-document-builder.d.ts.map +1 -1
- package/lib/testing/stub-document-builder.js +78 -5
- package/lib/testing/stub-document-builder.js.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
- package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.js +115 -16
- package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
- package/lib/testing/stub-index-manager.js.map +1 -1
- package/lib/testing/stub-langium-documents.d.ts +3 -2
- package/lib/testing/stub-langium-documents.d.ts.map +1 -1
- package/lib/testing/stub-langium-documents.js.map +1 -1
- package/lib/testing/stub-model-service.d.ts +7 -6
- package/lib/testing/stub-model-service.d.ts.map +1 -1
- package/lib/testing/stub-model-service.js +4 -4
- package/lib/testing/stub-model-service.js.map +1 -1
- package/lib/testing/stub-project-manager.js.map +1 -1
- package/lib/testing/stub-self-save-registry.d.ts +1 -1
- package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
- package/lib/testing/stub-service-registry.d.ts +1 -1
- package/lib/testing/stub-service-registry.js.map +1 -1
- package/lib/testing/stub-writable-file-system.d.ts +1 -1
- package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
- package/lib/util/connection-liveness.d.ts +7 -6
- package/lib/util/connection-liveness.d.ts.map +1 -1
- package/lib/util/connection-liveness.js +35 -14
- package/lib/util/connection-liveness.js.map +1 -1
- package/lib/util/environment.d.ts.map +1 -1
- package/lib/util/environment.js.map +1 -1
- package/lib/util/registry.d.ts.map +1 -1
- package/package.json +32 -48
- package/src/documents/ast-document-manager.ts +379 -231
- package/src/documents/client-ids.ts +5 -22
- package/src/documents/client-session-errors.ts +24 -0
- package/src/documents/client-session-registry.ts +262 -0
- package/src/documents/dirty-state-tracker.ts +130 -0
- package/src/documents/document-release-handler.ts +365 -0
- package/src/documents/document-release-scheduler.ts +121 -0
- package/src/documents/file-system-task-queue.ts +68 -0
- package/src/documents/hydranium-text-documents.ts +931 -595
- package/src/documents/index.ts +10 -2
- package/src/documents/language-client-shadow.ts +451 -0
- package/src/documents/model-ledger.ts +66 -0
- package/src/documents/text-ledger.ts +112 -0
- package/src/documents/version-sync-service.ts +267 -0
- package/src/index.ts +7 -0
- package/src/langium/ast-extension/ast-node-builder.ts +66 -22
- package/src/langium/bootstrap.ts +42 -17
- package/src/langium/composite-ast-reflection.ts +107 -0
- package/src/langium/config/configuration-provider.ts +119 -0
- package/src/langium/config/index.ts +1 -0
- package/src/langium/diagnostics/logger.ts +12 -5
- package/src/langium/diagnostics/lsp-logger.ts +59 -15
- package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
- package/src/langium/document-builder/build-session.ts +87 -0
- package/src/langium/document-builder/document-builder.ts +825 -59
- package/src/langium/document-builder/index.ts +1 -0
- package/src/langium/integration-services.ts +83 -24
- package/src/langium/integrity/integrity-rule.ts +16 -8
- package/src/langium/integrity/integrity-service.ts +287 -62
- package/src/langium/keys/containment.ts +87 -0
- package/src/langium/keys/index.ts +1 -0
- package/src/langium/keys/name-based-key-provider.ts +4 -0
- package/src/langium/language-module.ts +48 -7
- package/src/langium/model-service/client-session.ts +644 -0
- package/src/langium/model-service/index.ts +2 -0
- package/src/langium/model-service/model-events.ts +75 -0
- package/src/langium/model-service/model-service.ts +790 -468
- package/src/langium/module.ts +210 -64
- package/src/langium/naming/name-provider.ts +27 -5
- package/src/langium/naming/name-separator-validation.ts +34 -5
- package/src/langium/project/abstract-project-manager.ts +9 -1
- package/src/langium/project/project-change-event.ts +2 -2
- package/src/langium/residency/cst-residency-service.ts +46 -15
- package/src/langium/scope/hydranium-scope-provider.ts +60 -22
- package/src/langium/serialization/abstract-serializer.ts +13 -32
- package/src/langium/service-registry.ts +41 -2
- package/src/langium/shared-services.ts +27 -6
- package/src/langium/transfer/transfer-encoder.ts +104 -37
- package/src/langium/trivia/comment-preserver.ts +1100 -0
- package/src/langium/trivia/document-ending-preserver.ts +55 -0
- package/src/langium/trivia/index.ts +14 -0
- package/src/langium/trivia/trivia-contribution.ts +39 -0
- package/src/langium/trivia/trivia-preserver.ts +54 -0
- package/src/langium/trivia/trivia-service.ts +99 -0
- package/src/langium/update-rewrite/update-rewrite.ts +1 -1
- package/src/langium/validation/document-validator.ts +537 -11
- package/src/langium/validation/validation-contribution-collector.ts +10 -1
- package/src/langium/workspace/document-uri-policy.ts +18 -14
- package/src/langium/workspace/file-not-found.ts +35 -0
- package/src/langium/workspace/file-system-provider.ts +205 -17
- package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
- package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
- package/src/langium/workspace/hydranium-workspace-manager.ts +154 -14
- package/src/langium/workspace/in-memory-file-system-provider.ts +48 -17
- package/src/langium/workspace/index.ts +1 -0
- package/src/langium/workspace/initialize-workspace.ts +43 -5
- package/src/langium/workspace/langium-documents.ts +124 -33
- package/src/langium/workspace/persistent-file-system-provider.ts +1 -8
- package/src/{documents → langium/workspace}/self-save-registry.ts +54 -15
- package/src/langium/workspace/virtual-document.ts +96 -19
- package/src/langium/workspace/write-lock-scope.ts +24 -11
- package/src/locale/index.ts +10 -0
- package/src/locale/server-locale.ts +86 -0
- package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
- package/src/lsp/connection-features.ts +67 -0
- package/src/lsp/diagnostics-connection.ts +56 -0
- package/src/lsp/hydranium-document-update-handler.ts +187 -108
- package/src/lsp/index.ts +3 -1
- package/src/lsp/lsp-latency.ts +62 -0
- package/src/lsp/semantic-token-provider.ts +74 -7
- package/src/lsp/shared-module.ts +4 -8
- package/src/lsp/start-language-server.ts +13 -7
- package/src/messages/carriers.ts +78 -0
- package/src/messages/index.ts +36 -0
- package/src/messages/renderer.ts +212 -0
- package/src/node/heap-ceiling.ts +108 -0
- package/src/node/index.ts +1 -1
- package/src/node/latency-from-env.ts +1 -1
- package/src/node/measure-memory.ts +1 -0
- package/src/node/node-file-system-provider.ts +124 -53
- package/src/node/profile-capture.ts +9 -3
- package/src/node/profiling-run.ts +30 -8
- package/src/node/rename-over-open-readers.ts +78 -0
- package/src/node/socket-launcher.ts +24 -8
- package/src/node/stdio-launcher.ts +8 -7
- package/src/testing/fake-document.ts +24 -5
- package/src/testing/index.ts +2 -1
- package/src/testing/langium-test-helpers.ts +1 -0
- package/src/testing/make-noop-shared-services.ts +50 -2
- package/src/testing/make-test-services.ts +125 -31
- package/src/testing/make-test-tracer.ts +26 -0
- package/src/testing/node/index.ts +1 -0
- package/src/testing/node/lsp-harness.ts +2 -0
- package/src/testing/node/lsp-server-connection.ts +66 -12
- package/src/testing/node/scratch-workspace.ts +10 -5
- package/src/testing/node/spawned-server.ts +36 -2
- package/src/testing/node/unhandled-rejections.ts +31 -0
- package/src/testing/parse-semantic-root.ts +1 -1
- package/src/testing/playwright/flaky-network-proxy.ts +240 -0
- package/src/testing/playwright/index.ts +1 -0
- package/src/testing/playwright/server-log-capture.ts +45 -11
- package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
- package/src/testing/run-update-pipeline.ts +4 -4
- package/src/testing/stub-ast-document-manager.ts +36 -138
- package/src/testing/stub-document-builder.ts +102 -18
- package/src/testing/stub-hydranium-text-documents.ts +165 -27
- package/src/testing/stub-langium-documents.ts +3 -2
- package/src/testing/stub-model-service.ts +9 -8
- package/src/testing/stub-self-save-registry.ts +1 -1
- package/src/testing/stub-service-registry.ts +1 -1
- package/src/testing/stub-writable-file-system.ts +1 -1
- package/src/util/connection-liveness.ts +37 -14
- package/src/util/environment.ts +9 -1
- package/lib/documents/language-client-text-shadow.d.ts +0 -101
- package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
- package/lib/documents/language-client-text-shadow.js +0 -156
- package/lib/documents/language-client-text-shadow.js.map +0 -1
- package/lib/documents/self-save-registry.d.ts.map +0 -1
- package/lib/documents/self-save-registry.js.map +0 -1
- package/lib/lsp/instrument-connection.d.ts +0 -36
- package/lib/lsp/instrument-connection.d.ts.map +0 -1
- package/lib/lsp/instrument-connection.js +0 -62
- package/lib/lsp/instrument-connection.js.map +0 -1
- package/lib/node/process-memory.d.ts +0 -66
- package/lib/node/process-memory.d.ts.map +0 -1
- package/lib/node/process-memory.js +0 -252
- package/lib/node/process-memory.js.map +0 -1
- package/src/documents/language-client-text-shadow.ts +0 -175
- package/src/lsp/instrument-connection.ts +0 -66
- package/src/node/process-memory.ts +0 -299
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
import { DocumentState, type LangiumDocument, type URI } from '@hydranium/langium';
|
|
11
|
+
import { type Tracer, UNRECORDED_VERSION } from '@hydranium/protocol';
|
|
12
|
+
import { Disposable, Emitter, type Event } from 'vscode-languageserver-protocol';
|
|
13
|
+
import { type LogNameOptions } from '../langium/diagnostics/logger.js';
|
|
14
|
+
import { type ServerSharedServices } from '../langium/module.js';
|
|
15
|
+
import { HydraniumWorkspaceLock } from '../langium/workspace/hydranium-workspace-lock.js';
|
|
16
|
+
import { HydraniumTextDocuments } from './hydranium-text-documents.js';
|
|
17
|
+
|
|
18
|
+
/** A build {@link VersionSyncService.requestRecoveryBuild} schedules. */
|
|
19
|
+
export interface RecoveryBuildRequest {
|
|
20
|
+
/** Remove the document instead of building it. */
|
|
21
|
+
readonly deleted?: boolean;
|
|
22
|
+
/** Staged for the build, as `HydraniumDocumentBuilder.scheduleUpdate` takes it. */
|
|
23
|
+
readonly reason?: string;
|
|
24
|
+
/** Asked again inside the lock, where a build that ran meanwhile may have made the request moot. */
|
|
25
|
+
readonly stillNeeded: () => boolean;
|
|
26
|
+
/** Build even while a {@link VersionSyncService.registerDeferredBuilds} check holds the URI back. */
|
|
27
|
+
readonly ignoreDeferred?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Keeps each workspace root's `ModelLedger` record in step with the
|
|
32
|
+
* text store, and owns every build that syncs a root to its text or recovers
|
|
33
|
+
* one a build left behind.
|
|
34
|
+
*/
|
|
35
|
+
export interface VersionSyncService {
|
|
36
|
+
/**
|
|
37
|
+
* Report a root a factory, registry, integrity repair or other producer
|
|
38
|
+
* made. Below `Parsed` it is marked a placeholder. Otherwise `origin.version`,
|
|
39
|
+
* the store's version read before the parse, is recorded; a registered
|
|
40
|
+
* document is then reconciled with the store, re-versioned and recorded at
|
|
41
|
+
* the store's version of its text, built if behind, and announced on
|
|
42
|
+
* {@link onDidRecordModel}. `origin.text` stands for a root whose CST is not
|
|
43
|
+
* the text it describes.
|
|
44
|
+
*/
|
|
45
|
+
modelProduced(document: LangiumDocument, origin?: { version?: number; text?: string }): void;
|
|
46
|
+
/**
|
|
47
|
+
* Build `uri` from a `WorkspaceLock` read, so the build queues behind a
|
|
48
|
+
* running one rather than cancelling it. Requests made while one for `uri`
|
|
49
|
+
* is pending share its next build. Resolves `true` once a build that carried
|
|
50
|
+
* this request completed, or once a check before a build found it no longer
|
|
51
|
+
* needed or deferred. A build a later write cancelled does not count: the
|
|
52
|
+
* request rides the next one. Resolves `false` once builds carrying this
|
|
53
|
+
* request have failed more often than it may retry, so a caller waiting on
|
|
54
|
+
* the build can stop. Never rejects.
|
|
55
|
+
*/
|
|
56
|
+
requestRecoveryBuild(uri: URI, request: RecoveryBuildRequest): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Build `uri` unless it is {@link isSyncedTo synced to} `textVersion`, asked
|
|
59
|
+
* again inside the lock. `undefined` when no build is needed, else the
|
|
60
|
+
* {@link requestRecoveryBuild} answer.
|
|
61
|
+
*/
|
|
62
|
+
syncTo(uri: URI, textVersion: number): Promise<boolean> | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Whether `uri`'s root was parsed from text at `textVersion` or later; requests
|
|
65
|
+
* nothing. A root with no recorded version or a placeholder counts as synced,
|
|
66
|
+
* since no build records a version for it, and so does a URI with no document.
|
|
67
|
+
*/
|
|
68
|
+
isSyncedTo(uri: URI, textVersion: number): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Register `isDeferred`, which answers whether its caller holds back a build
|
|
71
|
+
* of a URI it will request later, as the update handler does for a debounced
|
|
72
|
+
* editor change. A caller that drops a held change has to leave the URI to
|
|
73
|
+
* another build.
|
|
74
|
+
*/
|
|
75
|
+
registerDeferredBuilds(isDeferred: (uri: URI) => boolean): Disposable;
|
|
76
|
+
/**
|
|
77
|
+
* Fires for every reconciled root. A cancel cannot skip it, unlike a
|
|
78
|
+
* `Parsed` phase listener. It can fire inside a build's write lock, so a
|
|
79
|
+
* listener that requests a build must not await it.
|
|
80
|
+
*/
|
|
81
|
+
readonly onDidRecordModel: Event<LangiumDocument>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** A request waiting in {@link PendingRecoveryBuilds}, with the failed builds that carried it. */
|
|
85
|
+
export interface QueuedRecoveryBuild {
|
|
86
|
+
readonly request: RecoveryBuildRequest;
|
|
87
|
+
failures: number;
|
|
88
|
+
readonly answer: (built: boolean) => void;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** The requests waiting on one URI's builds in {@link DefaultVersionSyncService}. */
|
|
92
|
+
export interface PendingRecoveryBuilds {
|
|
93
|
+
readonly queued: QueuedRecoveryBuild[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Collaborators are resolved per call: the registry and its document factory,
|
|
98
|
+
* which construct each other, report roots to this service.
|
|
99
|
+
*/
|
|
100
|
+
export class DefaultVersionSyncService implements VersionSyncService {
|
|
101
|
+
protected readonly tracer: Tracer;
|
|
102
|
+
protected readonly recordedEmitter = new Emitter<LangiumDocument>();
|
|
103
|
+
protected readonly deferredBuildChecks = new Set<(uri: URI) => boolean>();
|
|
104
|
+
protected readonly pendingBuilds = new Map<string, PendingRecoveryBuilds>();
|
|
105
|
+
/** Retries of each request after a failed build before it is answered `false`. */
|
|
106
|
+
protected readonly maxBuildRetries: number = 1;
|
|
107
|
+
|
|
108
|
+
constructor(
|
|
109
|
+
protected readonly services: ServerSharedServices,
|
|
110
|
+
options: LogNameOptions = {}
|
|
111
|
+
) {
|
|
112
|
+
this.tracer = services.Tracer.for(options.logName ?? 'VersionSyncService').trace('instantiated');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get onDidRecordModel(): Event<LangiumDocument> {
|
|
116
|
+
return this.recordedEmitter.event;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
modelProduced(document: LangiumDocument, origin: { version?: number; text?: string } = {}): void {
|
|
120
|
+
const workspace = this.services.workspace;
|
|
121
|
+
const ledger = workspace.ModelLedger;
|
|
122
|
+
const root = document.parseResult.value;
|
|
123
|
+
if (document.state < DocumentState.Parsed) {
|
|
124
|
+
ledger.markPlaceholder(root);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (origin.version !== undefined) {
|
|
128
|
+
ledger.record(root, origin.version, origin.text);
|
|
129
|
+
}
|
|
130
|
+
const store = workspace.TextDocuments;
|
|
131
|
+
// Unregistered, it is a probe or a load whose registration reports it again.
|
|
132
|
+
if (!(store instanceof HydraniumTextDocuments) || workspace.LangiumDocuments.getDocument(document.uri) !== document) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const uri = document.uri.toString();
|
|
136
|
+
// Against the parsed text: the text document may already hold a newer edit.
|
|
137
|
+
const version = store.reconcileExternalContent(uri, origin.text ?? this.parsedText(document));
|
|
138
|
+
if (version !== undefined) {
|
|
139
|
+
if (document.textDocument.version !== version) {
|
|
140
|
+
// An empty-changes update only re-stamps the version.
|
|
141
|
+
store.update(document.textDocument, [], version);
|
|
142
|
+
}
|
|
143
|
+
ledger.record(root, version, origin.text);
|
|
144
|
+
}
|
|
145
|
+
void this.syncTo(document.uri, store.version(uri));
|
|
146
|
+
this.recordedEmitter.fire(document);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
syncTo(uri: URI, textVersion: number): Promise<boolean> | undefined {
|
|
150
|
+
const behind = (): boolean => !this.isSyncedTo(uri, textVersion);
|
|
151
|
+
return behind() ? this.requestRecoveryBuild(uri, { stillNeeded: behind }) : undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
requestRecoveryBuild(uri: URI, request: RecoveryBuildRequest): Promise<boolean> {
|
|
155
|
+
return new Promise<boolean>(answer => {
|
|
156
|
+
const key = uri.toString();
|
|
157
|
+
const queued: QueuedRecoveryBuild = { request, failures: 0, answer };
|
|
158
|
+
const pending = this.pendingBuilds.get(key);
|
|
159
|
+
if (pending) {
|
|
160
|
+
// Not dropped: the pending build may have read the text before this request's change.
|
|
161
|
+
pending.queued.push(queued);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const entry: PendingRecoveryBuilds = { queued: [queued] };
|
|
165
|
+
this.pendingBuilds.set(key, entry);
|
|
166
|
+
void this.runBuilds(key, uri, entry);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
registerDeferredBuilds(isDeferred: (uri: URI) => boolean): Disposable {
|
|
171
|
+
this.deferredBuildChecks.add(isDeferred);
|
|
172
|
+
return Disposable.create(() => this.deferredBuildChecks.delete(isDeferred));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
isSyncedTo(uri: URI, textVersion: number): boolean {
|
|
176
|
+
const root = this.services.workspace.LangiumDocuments.getDocument(uri)?.parseResult.value;
|
|
177
|
+
if (root === undefined) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
const ledger = this.services.workspace.ModelLedger;
|
|
181
|
+
const recorded = ledger.versionOf(root);
|
|
182
|
+
return recorded === UNRECORDED_VERSION || ledger.isPlaceholder(root) || recorded >= textVersion;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** The text `document`'s root was parsed from, or for a root built without either record or CST, the document's own. */
|
|
186
|
+
protected parsedText(document: LangiumDocument): string {
|
|
187
|
+
return this.services.workspace.ModelLedger.textOf(document.parseResult.value) ?? document.textDocument.getText();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Run `entry`'s requests, one build per batch, until none is queued, and
|
|
192
|
+
* answer each. A request a failed build carried is queued again
|
|
193
|
+
* {@link maxBuildRetries} times, then answered `false`; one a cancelled
|
|
194
|
+
* build carried is queued again without counting. The entry is dropped
|
|
195
|
+
* in the same tick as the last check of the queue, so no request lands in
|
|
196
|
+
* an entry nothing runs any more.
|
|
197
|
+
*/
|
|
198
|
+
protected async runBuilds(key: string, uri: URI, entry: PendingRecoveryBuilds): Promise<void> {
|
|
199
|
+
const tracer = this.tracer.withUri(key);
|
|
200
|
+
const lock = this.services.workspace.WorkspaceLock;
|
|
201
|
+
// Any other lock resolves a cancelled write as if it had completed, unnoticed.
|
|
202
|
+
const counting = lock instanceof HydraniumWorkspaceLock ? lock : undefined;
|
|
203
|
+
while (entry.queued.length > 0) {
|
|
204
|
+
let carried: QueuedRecoveryBuild[] = [];
|
|
205
|
+
let build: Promise<void> | undefined;
|
|
206
|
+
let cancellations: number | undefined;
|
|
207
|
+
try {
|
|
208
|
+
// The read waits until no write runs or is queued. It must not await
|
|
209
|
+
// the build, a write that queues behind it.
|
|
210
|
+
await lock.read(() => {
|
|
211
|
+
carried = entry.queued.splice(0);
|
|
212
|
+
const needed = carried.filter(queued => this.isStillNeeded(uri, queued.request));
|
|
213
|
+
carried.filter(queued => !needed.includes(queued)).forEach(queued => queued.answer(true));
|
|
214
|
+
carried = needed;
|
|
215
|
+
if (needed.length > 0) {
|
|
216
|
+
build = this.scheduleBatch(
|
|
217
|
+
uri,
|
|
218
|
+
needed.map(queued => queued.request)
|
|
219
|
+
);
|
|
220
|
+
// Read after the build is queued, which cancels the write before it.
|
|
221
|
+
cancellations = counting?.writeCancellations;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
await build;
|
|
225
|
+
// A write cancelled the build, before it ran or while it did.
|
|
226
|
+
if (cancellations !== undefined && counting?.writeCancellations !== cancellations) {
|
|
227
|
+
entry.queued.unshift(...carried);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
carried.forEach(queued => queued.answer(true));
|
|
231
|
+
} catch (err: unknown) {
|
|
232
|
+
const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
233
|
+
const retried = carried.filter(queued => queued.failures++ < this.maxBuildRetries);
|
|
234
|
+
const givenUp = carried.filter(queued => !retried.includes(queued));
|
|
235
|
+
if (retried.length > 0) {
|
|
236
|
+
tracer.warn(`Requested build failed; retrying. ${detail}`);
|
|
237
|
+
entry.queued.unshift(...retried);
|
|
238
|
+
}
|
|
239
|
+
if (givenUp.length > 0) {
|
|
240
|
+
tracer.error(`Requested build failed again; giving up. ${detail}`);
|
|
241
|
+
givenUp.forEach(queued => queued.answer(false));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
this.pendingBuilds.delete(key);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Whether `request` still needs its build, and no deferral it heeds holds it back. Runs inside the lock read. */
|
|
249
|
+
protected isStillNeeded(uri: URI, request: RecoveryBuildRequest): boolean {
|
|
250
|
+
return request.stillNeeded() && (request.ignoreDeferred === true || !this.isDeferred(uri));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* One build for every request of `batch`, removing the document when the
|
|
255
|
+
* latest of them asks to, as `HydraniumDocumentBuilder.scheduleUpdate`
|
|
256
|
+
* merges a change and a deletion. Runs inside the lock read.
|
|
257
|
+
*/
|
|
258
|
+
protected scheduleBatch(uri: URI, batch: readonly RecoveryBuildRequest[]): Promise<void> {
|
|
259
|
+
const deleted = batch.at(-1)?.deleted === true;
|
|
260
|
+
const reason = batch.find(request => request.reason !== undefined)?.reason;
|
|
261
|
+
return this.services.workspace.DocumentBuilder.scheduleUpdate(deleted ? [] : [uri], deleted ? [uri] : [], reason);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
protected isDeferred(uri: URI): boolean {
|
|
265
|
+
return [...this.deferredBuildChecks].some(isDeferred => isDeferred(uri));
|
|
266
|
+
}
|
|
267
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -28,12 +28,19 @@ export * from './langium/project/index.js';
|
|
|
28
28
|
export * from './langium/residency/index.js';
|
|
29
29
|
export * from './langium/scope/index.js';
|
|
30
30
|
export * from './langium/serialization/index.js';
|
|
31
|
+
export * from './langium/trivia/index.js';
|
|
31
32
|
export * from './langium/transfer/index.js';
|
|
32
33
|
export * from './langium/update-rewrite/index.js';
|
|
33
34
|
export * from './langium/validation/index.js';
|
|
34
35
|
export * from './langium/workspace/index.js';
|
|
35
36
|
export * from './langium/service-registry.js';
|
|
36
37
|
export * from './langium/language-types.js';
|
|
38
|
+
export * from './langium/composite-ast-reflection.js';
|
|
37
39
|
export * from './launcher/index.js';
|
|
40
|
+
export * from './locale/index.js';
|
|
41
|
+
// The renderer only. The `./messages` subpath additionally enumerates this
|
|
42
|
+
// package's own declarations, which the root barrel already re-exports through
|
|
43
|
+
// the modules that raise them.
|
|
44
|
+
export * from './messages/renderer.js';
|
|
38
45
|
export * from './documents/index.js';
|
|
39
46
|
export * from './util/index.js';
|
|
@@ -78,15 +78,13 @@ export type AstNodeBuilder<TMap> = <TType extends string & keyof TMap>(
|
|
|
78
78
|
* AST-interface mapping, so call sites get full inference from the type
|
|
79
79
|
* constant alone — no explicit generic parameter at every call site.
|
|
80
80
|
*
|
|
81
|
-
* Runtime behaviour:
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* TS-augmented fields (declared via `declare module './generated/ast.js'`)
|
|
89
|
-
* are unaffected by the runtime defaulting but remain typed at call sites.
|
|
81
|
+
* Runtime behaviour: pre-fills every grammar-declared default (see
|
|
82
|
+
* {@link withTypeDefaults}) before merging the caller's `init`, so containment
|
|
83
|
+
* lists and `?=`-style boolean flags default automatically. TS-augmented fields
|
|
84
|
+
* (declared via `declare module './generated/ast.js'`) are unaffected by the
|
|
85
|
+
* runtime defaulting but remain typed at call sites.
|
|
86
|
+
*
|
|
87
|
+
* Use {@link buildAstNode} instead when the type name is only known at runtime.
|
|
90
88
|
*
|
|
91
89
|
* The init shape only relaxes array-typed fields to optional (via
|
|
92
90
|
* {@link ArrayKeys}) — there is no equivalent structural signal for "this
|
|
@@ -101,19 +99,7 @@ export function makeAstNodeBuilder<TMap>(reflection: AstReflection): AstNodeBuil
|
|
|
101
99
|
init: AstNodeInit<Extract<TMap[TType], AstNode>>,
|
|
102
100
|
extras?: Record<string, unknown>
|
|
103
101
|
): Extract<TMap[TType], AstNode> {
|
|
104
|
-
const
|
|
105
|
-
const result: Record<string, unknown> = { $type: typeConstant.$type };
|
|
106
|
-
if (meta?.properties) {
|
|
107
|
-
for (const [propName, propInfo] of Object.entries(meta.properties)) {
|
|
108
|
-
const defaultValue = propInfo.defaultValue;
|
|
109
|
-
if (defaultValue === undefined) {
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
// Arrays are duplicated so each node carries its own mutable instance;
|
|
113
|
-
// scalars are immutable and safe to copy by reference.
|
|
114
|
-
result[propName] = Array.isArray(defaultValue) ? [...defaultValue] : defaultValue;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
102
|
+
const result = withTypeDefaults(reflection, typeConstant.$type);
|
|
117
103
|
Object.assign(result, init);
|
|
118
104
|
if (extras) {
|
|
119
105
|
// Extras win over init: this is the explicit escape hatch, so when a
|
|
@@ -123,3 +109,61 @@ export function makeAstNodeBuilder<TMap>(reflection: AstReflection): AstNodeBuil
|
|
|
123
109
|
return result as unknown as Extract<TMap[TType], AstNode>;
|
|
124
110
|
};
|
|
125
111
|
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Build a node whose type is only known as a RUNTIME string.
|
|
115
|
+
*
|
|
116
|
+
* The typed {@link makeAstNodeBuilder} cannot express this: its `TMap` generic
|
|
117
|
+
* resolves the AST interface from a `$type` literal, and a type name that
|
|
118
|
+
* arrives over the wire — a protocol-layer reference request naming a node that
|
|
119
|
+
* does not exist yet — has no literal to resolve from. Callers that DO know the
|
|
120
|
+
* type at compile time want the typed builder, which checks their mandatory
|
|
121
|
+
* fields; this one checks nothing beyond the reflection lookup.
|
|
122
|
+
*
|
|
123
|
+
* Applies the same reflection-driven defaulting, so a node built here carries
|
|
124
|
+
* grammar-declared containment arrays rather than leaving them `undefined`. An
|
|
125
|
+
* unknown type name yields a node with `$type` and whatever `init` supplied,
|
|
126
|
+
* because reflection answers no metadata for it and refusing would turn a
|
|
127
|
+
* permissive lookup into a throw at a call site that can only guess.
|
|
128
|
+
*
|
|
129
|
+
* **The `type` argument is authoritative: `init` cannot rebind `$type`.** The
|
|
130
|
+
* typed builder gets this for free — `AstNodeInit` omits `$type`, so a call site
|
|
131
|
+
* cannot reach it — but here `init` is loosely typed, and the case that needs
|
|
132
|
+
* the guarantee is RETYPING: a caller spreading an existing node to produce one
|
|
133
|
+
* of a different type (`{ ...source }`) carries the SOURCE's `$type` in, which
|
|
134
|
+
* would silently win over the type actually requested and hand back a node of
|
|
135
|
+
* the wrong type with no error anywhere.
|
|
136
|
+
*/
|
|
137
|
+
export function buildAstNode<TAst extends AstNode = AstNode>(
|
|
138
|
+
reflection: AstReflection,
|
|
139
|
+
type: string,
|
|
140
|
+
init?: Partial<AstNode> & Record<string, unknown>
|
|
141
|
+
): TAst {
|
|
142
|
+
const result = withTypeDefaults(reflection, type);
|
|
143
|
+
if (init) {
|
|
144
|
+
Object.assign(result, init);
|
|
145
|
+
result.$type = type;
|
|
146
|
+
}
|
|
147
|
+
return result as unknown as TAst;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Seed a node with `$type` plus every property the grammar declares a default
|
|
152
|
+
* for. Array defaults are materialised as a fresh `[]` per call — never shared
|
|
153
|
+
* with the metadata's own array instance, which downstream callers mutate —
|
|
154
|
+
* while scalar defaults are copied as-is since they are immutable.
|
|
155
|
+
*/
|
|
156
|
+
function withTypeDefaults(reflection: AstReflection, type: string): Record<string, unknown> {
|
|
157
|
+
const result: Record<string, unknown> = { $type: type };
|
|
158
|
+
const meta = reflection.getTypeMetaData(type);
|
|
159
|
+
if (meta?.properties) {
|
|
160
|
+
for (const [propName, propInfo] of Object.entries(meta.properties)) {
|
|
161
|
+
const defaultValue = propInfo.defaultValue;
|
|
162
|
+
if (defaultValue === undefined) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
result[propName] = Array.isArray(defaultValue) ? [...defaultValue] : defaultValue;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
package/src/langium/bootstrap.ts
CHANGED
|
@@ -12,15 +12,17 @@ import { type LangiumSharedCoreServices } from '@hydranium/langium';
|
|
|
12
12
|
import { type LangiumServices, type LangiumSharedServices } from '@hydranium/langium/lsp';
|
|
13
13
|
import type { ServerSharedServicesMinimal } from './shared-services.js';
|
|
14
14
|
import { collectProducibleTypes } from './language-types.js';
|
|
15
|
-
import {
|
|
15
|
+
import { DefaultAstDocumentManager } from '../documents/ast-document-manager.js';
|
|
16
16
|
import { HydraniumTextDocuments } from '../documents/hydranium-text-documents.js';
|
|
17
|
-
import {
|
|
17
|
+
import { DefaultBuildPipelineIntegration } from './document-builder/build-pipeline-integration.js';
|
|
18
18
|
import { HydraniumDocumentBuilder } from './document-builder/document-builder.js';
|
|
19
|
-
import {
|
|
19
|
+
import { DefaultModelService } from './model-service/model-service.js';
|
|
20
20
|
import { HydraniumScopeComputation } from './scope/hydranium-scope-computation.js';
|
|
21
21
|
import { HydraniumScopeProvider } from './scope/hydranium-scope-provider.js';
|
|
22
22
|
import { processEnv } from '../util/environment.js';
|
|
23
|
-
import {
|
|
23
|
+
import { DefaultTransferEncoder } from './transfer/transfer-encoder.js';
|
|
24
|
+
import { HydraniumLangiumDocumentFactory } from './workspace/hydranium-langium-document-factory.js';
|
|
25
|
+
import { HydraniumLangiumDocuments } from './workspace/langium-documents.js';
|
|
24
26
|
import { HydraniumWorkspaceManager } from './workspace/hydranium-workspace-manager.js';
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -73,7 +75,14 @@ const EXPECTED_SHARED_SLOTS: readonly ExpectedSlot[] = [
|
|
|
73
75
|
side: 'shared',
|
|
74
76
|
path: 'workspace.BuildPipelineIntegration',
|
|
75
77
|
get: services => nested(services, 'workspace', 'BuildPipelineIntegration')
|
|
76
|
-
}
|
|
78
|
+
},
|
|
79
|
+
// Unbound, this fails where the cause is least visible: the render pass runs
|
|
80
|
+
// inside the `Validated` phase, so a `TypeError` there propagates out of
|
|
81
|
+
// `notifyDocumentPhase` and the document reaches `Validated` with Langium's
|
|
82
|
+
// publisher never invoked — the client receives no diagnostics for the file
|
|
83
|
+
// and the stack names the document builder.
|
|
84
|
+
{ side: 'shared', path: 'MessageRenderer', get: services => nested(services, 'MessageRenderer') },
|
|
85
|
+
{ side: 'shared', path: 'ServerLocale', get: services => nested(services, 'ServerLocale') }
|
|
77
86
|
];
|
|
78
87
|
|
|
79
88
|
/**
|
|
@@ -184,6 +193,20 @@ interface StrictSlot {
|
|
|
184
193
|
|
|
185
194
|
const STRICT_SHARED_SLOTS: readonly StrictSlot[] = [
|
|
186
195
|
{ side: 'shared', path: 'workspace.TextDocuments', base: HydraniumTextDocuments, get: s => nested(s, 'workspace', 'TextDocuments') },
|
|
196
|
+
// Every root it builds records no version, so every write gated on one conflicts.
|
|
197
|
+
{
|
|
198
|
+
side: 'shared',
|
|
199
|
+
path: 'workspace.LangiumDocumentFactory',
|
|
200
|
+
base: HydraniumLangiumDocumentFactory,
|
|
201
|
+
get: s => nested(s, 'workspace', 'LangiumDocumentFactory')
|
|
202
|
+
},
|
|
203
|
+
// It reports no registered root, so none is reconciled with the text store or announced.
|
|
204
|
+
{
|
|
205
|
+
side: 'shared',
|
|
206
|
+
path: 'workspace.LangiumDocuments',
|
|
207
|
+
base: HydraniumLangiumDocuments,
|
|
208
|
+
get: s => nested(s, 'workspace', 'LangiumDocuments')
|
|
209
|
+
},
|
|
187
210
|
{
|
|
188
211
|
side: 'shared',
|
|
189
212
|
path: 'workspace.WorkspaceManager',
|
|
@@ -199,17 +222,17 @@ const STRICT_SHARED_SLOTS: readonly StrictSlot[] = [
|
|
|
199
222
|
{
|
|
200
223
|
side: 'shared',
|
|
201
224
|
path: 'workspace.AstDocumentManager',
|
|
202
|
-
base:
|
|
225
|
+
base: DefaultAstDocumentManager,
|
|
203
226
|
get: s => nested(s, 'workspace', 'AstDocumentManager')
|
|
204
227
|
},
|
|
205
228
|
{
|
|
206
229
|
side: 'shared',
|
|
207
230
|
path: 'workspace.BuildPipelineIntegration',
|
|
208
|
-
base:
|
|
231
|
+
base: DefaultBuildPipelineIntegration,
|
|
209
232
|
get: s => nested(s, 'workspace', 'BuildPipelineIntegration')
|
|
210
233
|
},
|
|
211
|
-
{ side: 'shared', path: 'model.TransferEncoder', base:
|
|
212
|
-
{ side: 'shared', path: 'model.ModelService', base:
|
|
234
|
+
{ side: 'shared', path: 'model.TransferEncoder', base: DefaultTransferEncoder, get: s => nested(s, 'model', 'TransferEncoder') },
|
|
235
|
+
{ side: 'shared', path: 'model.ModelService', base: DefaultModelService, get: s => nested(s, 'model', 'ModelService') }
|
|
213
236
|
];
|
|
214
237
|
|
|
215
238
|
const STRICT_LANGUAGE_SLOTS: readonly StrictSlot[] = [
|
|
@@ -521,11 +544,11 @@ export function assertDistinctFileRouting(languages: ReadonlyArray<LangiumServic
|
|
|
521
544
|
*
|
|
522
545
|
* The check is per language, on the types its grammar can produce, and costs
|
|
523
546
|
* one grammar walk per language at boot; a single-language composition, which
|
|
524
|
-
* nothing can clobber, is skipped entirely. It cannot repair the situation
|
|
525
|
-
* reflection
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
547
|
+
* nothing can clobber, is skipped entirely. It cannot repair the situation, since
|
|
548
|
+
* the losing reflection is already gone; the point is to turn a silent runtime
|
|
549
|
+
* misbehaviour into a boot failure that names the language and the mistake. The
|
|
550
|
+
* repair is the adopter's: bind a `CompositeAstReflection` over every package's
|
|
551
|
+
* generated reflection, or generate all grammars in one `langium-cli` run.
|
|
529
552
|
*
|
|
530
553
|
* **Two severities, because a clobber is not always total.** Throwing only when
|
|
531
554
|
* NONE of a language's types are known misses the realistic case: two grammars
|
|
@@ -567,8 +590,9 @@ export function assertReflectionCoversLanguages(shared: LangiumSharedServices, l
|
|
|
567
590
|
`[hydranium] the shared AstReflection knows NONE of the ${produced.size} types the language ` +
|
|
568
591
|
`'${languageId}' can produce (e.g. ${missing.slice(0, 3).join(', ')}). ` +
|
|
569
592
|
'AstReflection is a single shared slot, so composing two independently generated language ' +
|
|
570
|
-
|
|
571
|
-
'
|
|
593
|
+
"packages leaves only the last one bound. Bind a CompositeAstReflection over every package's " +
|
|
594
|
+
'generated reflection, or generate all grammars in ONE langium-cli run (one langium-config with ' +
|
|
595
|
+
'several entry grammars) so a single combined reflection covers them all.'
|
|
572
596
|
);
|
|
573
597
|
}
|
|
574
598
|
}
|
|
@@ -590,7 +614,8 @@ function warnPartialReflectionCoverage(
|
|
|
590
614
|
'For those types `isSubtype` answers false and `getTypeMetaData` is empty, so `IndexManager.allElements` ' +
|
|
591
615
|
'finds nothing, reference routing misses, and the encoder emits nothing. Most likely two independently ' +
|
|
592
616
|
'generated language packages each bound the single shared AstReflection slot and the last one won — ' +
|
|
593
|
-
|
|
617
|
+
"bind a CompositeAstReflection over every package's generated reflection, or generate all grammars in " +
|
|
618
|
+
'ONE langium-cli run so a single combined reflection covers them. If instead ' +
|
|
594
619
|
'these are rules your generator legitimately folded away, this warning is expected.';
|
|
595
620
|
if (logger) {
|
|
596
621
|
logger.warn(message);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
import { AbstractAstReflection, type AstMetaData, type AstReflection, type PropertyMetaData, type TypeMetaData } from '@hydranium/langium';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* One `AstReflection` over the reflections of separately generated language
|
|
14
|
+
* packages. The shared `AstReflection` slot holds a single reflection, so
|
|
15
|
+
* binding each package's generated shared module keeps only the last one's
|
|
16
|
+
* types; bind this over all of them instead.
|
|
17
|
+
*
|
|
18
|
+
* A name several reflections share is taken to be one type, reached through a
|
|
19
|
+
* shared imported grammar, and keeps every super type any of them gives it:
|
|
20
|
+
* each grammar may declare its own union over the type. Only properties that
|
|
21
|
+
* differ in name, reference type or default value throw; two unrelated unions,
|
|
22
|
+
* or same-shaped interfaces, that share a name merge silently, so keep other
|
|
23
|
+
* type names distinct across packages.
|
|
24
|
+
*
|
|
25
|
+
* Only each reflection's `types` is read, so behaviour a reflection overrides
|
|
26
|
+
* is lost. Each package's generated `isX` guards keep using that package's own
|
|
27
|
+
* reflection and answer false for subtypes only another package declares.
|
|
28
|
+
*
|
|
29
|
+
* The protected merge methods run from the constructor, so an override cannot
|
|
30
|
+
* read its own class's fields.
|
|
31
|
+
*/
|
|
32
|
+
export class CompositeAstReflection extends AbstractAstReflection {
|
|
33
|
+
override readonly types: AstMetaData = {};
|
|
34
|
+
|
|
35
|
+
constructor(reflections: readonly AstReflection[]) {
|
|
36
|
+
super();
|
|
37
|
+
const firstDefinedAt = new Map<string, number>();
|
|
38
|
+
reflections.forEach((reflection, index) => {
|
|
39
|
+
for (const [type, metaData] of Object.entries(reflection.types)) {
|
|
40
|
+
const ownerIndex = firstDefinedAt.get(type);
|
|
41
|
+
if (ownerIndex === undefined) {
|
|
42
|
+
this.types[type] = metaData;
|
|
43
|
+
firstDefinedAt.set(type, index);
|
|
44
|
+
} else {
|
|
45
|
+
this.types[type] = this.mergeTypeMetaData(
|
|
46
|
+
this.types[type],
|
|
47
|
+
metaData,
|
|
48
|
+
this.formatReflection(reflections, ownerIndex),
|
|
49
|
+
this.formatReflection(reflections, index)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected mergeTypeMetaData(known: TypeMetaData, added: TypeMetaData, knownFrom: string, addedFrom: string): TypeMetaData {
|
|
57
|
+
const properties: TypeMetaData['properties'] = {};
|
|
58
|
+
const propertyNames = new Set([...Object.keys(known.properties), ...Object.keys(added.properties)]);
|
|
59
|
+
for (const property of propertyNames) {
|
|
60
|
+
const knownProperty = known.properties[property];
|
|
61
|
+
const addedProperty = added.properties[property];
|
|
62
|
+
if (!knownProperty || !addedProperty || !this.sameProperty(knownProperty, addedProperty)) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`[hydranium] ${knownFrom} and ${addedFrom} define the type ` +
|
|
65
|
+
`'${known.name}' differently (property '${property}'). A name the composed reflections share must ` +
|
|
66
|
+
'denote one type, so rename one of them, or have every grammar take the type unchanged from one ' +
|
|
67
|
+
'shared imported grammar.'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
properties[property] = addedProperty.optional && !knownProperty.optional ? addedProperty : knownProperty;
|
|
71
|
+
}
|
|
72
|
+
// `Required` so a field Langium adds fails compilation until this merge decides on it.
|
|
73
|
+
const merged: Required<TypeMetaData> = {
|
|
74
|
+
name: known.name,
|
|
75
|
+
properties,
|
|
76
|
+
superTypes: [...new Set([...known.superTypes, ...added.superTypes])]
|
|
77
|
+
};
|
|
78
|
+
return merged;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected sameProperty(left: PropertyMetaData, right: PropertyMetaData): boolean {
|
|
82
|
+
return COMPARED_PROPERTY_FIELDS.every(field => JSON.stringify(left[field]) === JSON.stringify(right[field]));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Names `reflections[index]` for the clash error: its position and class
|
|
87
|
+
* name. The position is needed because minified bundles and scaffolds
|
|
88
|
+
* sharing a project name leave class names that do not tell reflections
|
|
89
|
+
* apart. An override can name the package each reflection came from.
|
|
90
|
+
*/
|
|
91
|
+
protected formatReflection(reflections: readonly AstReflection[], index: number): string {
|
|
92
|
+
return `reflections[${index}] (${reflections[index].constructor.name})`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** How the merge treats each property field; a field Langium adds fails compilation here until decided. */
|
|
97
|
+
const PROPERTY_FIELDS = {
|
|
98
|
+
name: 'compared',
|
|
99
|
+
referenceType: 'compared',
|
|
100
|
+
defaultValue: 'compared',
|
|
101
|
+
// Older generators emit no `optional`, so its absence proves nothing.
|
|
102
|
+
optional: 'merged'
|
|
103
|
+
} as const satisfies Record<keyof PropertyMetaData, 'compared' | 'merged'>;
|
|
104
|
+
|
|
105
|
+
const COMPARED_PROPERTY_FIELDS = (Object.keys(PROPERTY_FIELDS) as Array<keyof PropertyMetaData>).filter(
|
|
106
|
+
field => PROPERTY_FIELDS[field] === 'compared'
|
|
107
|
+
);
|