@hydranium/core 1.0.0-next.11 → 1.0.0-next.112
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/lib/documents/ast-document-manager.d.ts +75 -16
- package/lib/documents/ast-document-manager.d.ts.map +1 -1
- package/lib/documents/ast-document-manager.js +57 -19
- 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/hydranium-text-documents.d.ts +132 -42
- package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
- package/lib/documents/hydranium-text-documents.js +199 -57
- package/lib/documents/hydranium-text-documents.js.map +1 -1
- package/lib/documents/language-client-text-shadow.d.ts +41 -9
- package/lib/documents/language-client-text-shadow.d.ts.map +1 -1
- package/lib/documents/language-client-text-shadow.js +56 -11
- package/lib/documents/language-client-text-shadow.js.map +1 -1
- package/lib/documents/self-save-registry.d.ts +37 -6
- package/lib/documents/self-save-registry.d.ts.map +1 -1
- package/lib/documents/self-save-registry.js +28 -15
- package/lib/documents/self-save-registry.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +6 -0
- package/lib/index.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.map +1 -1
- package/lib/langium/bootstrap.js +16 -9
- package/lib/langium/bootstrap.js.map +1 -1
- 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/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 +40 -6
- package/lib/langium/diagnostics/lsp-logger.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 +150 -7
- package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
- package/lib/langium/document-builder/document-builder.js +298 -11
- 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/integration-services.d.ts +45 -1
- 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-service.d.ts +16 -0
- package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-service.js +110 -2
- 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/language-module.d.ts +25 -0
- package/lib/langium/language-module.d.ts.map +1 -1
- package/lib/langium/language-module.js +14 -0
- package/lib/langium/language-module.js.map +1 -1
- package/lib/langium/model-service/model-service.d.ts +161 -10
- package/lib/langium/model-service/model-service.d.ts.map +1 -1
- package/lib/langium/model-service/model-service.js +176 -97
- package/lib/langium/model-service/model-service.js.map +1 -1
- package/lib/langium/module.d.ts +84 -15
- package/lib/langium/module.d.ts.map +1 -1
- package/lib/langium/module.js +26 -12
- 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/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 +13 -56
- package/lib/langium/residency/cst-residency-service.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/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/service-registry.d.ts +15 -1
- package/lib/langium/service-registry.d.ts.map +1 -1
- package/lib/langium/service-registry.js +16 -0
- package/lib/langium/service-registry.js.map +1 -1
- package/lib/langium/shared-services.d.ts +15 -2
- 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 +60 -17
- package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
- package/lib/langium/transfer/transfer-encoder.js +38 -16
- 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/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/workspace/document-uri-policy.d.ts +3 -4
- package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
- package/lib/langium/workspace/document-uri-policy.js +3 -4
- package/lib/langium/workspace/document-uri-policy.js.map +1 -1
- package/lib/langium/workspace/file-system-provider.d.ts +9 -1
- package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/file-system-provider.js +40 -7
- package/lib/langium/workspace/file-system-provider.js.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +25 -0
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.js +25 -0
- package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts +21 -1
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.js +28 -0
- package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts +23 -0
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.js +47 -9
- package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
- package/lib/langium/workspace/initialize-workspace.d.ts +23 -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 +79 -17
- package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
- package/lib/langium/workspace/langium-documents.js +83 -28
- package/lib/langium/workspace/langium-documents.js.map +1 -1
- package/lib/langium/workspace/virtual-document.d.ts +18 -3
- package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
- package/lib/langium/workspace/virtual-document.js +19 -2
- package/lib/langium/workspace/virtual-document.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.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.js +10 -1
- 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/start-language-server.d.ts +5 -3
- package/lib/lsp/start-language-server.d.ts.map +1 -1
- package/lib/lsp/start-language-server.js +10 -3
- 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 +136 -0
- package/lib/messages/renderer.d.ts.map +1 -0
- package/lib/messages/renderer.js +159 -0
- package/lib/messages/renderer.js.map +1 -0
- 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 -0
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +1 -0
- 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/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/node-file-system-provider.d.ts +35 -1
- package/lib/node/node-file-system-provider.d.ts.map +1 -1
- package/lib/node/node-file-system-provider.js +140 -45
- 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.map +1 -1
- package/lib/node/profiling-run.d.ts +2 -2
- package/lib/node/profiling-run.js +1 -1
- 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 +15 -0
- package/lib/node/socket-launcher.d.ts.map +1 -1
- package/lib/node/socket-launcher.js +3 -2
- package/lib/node/socket-launcher.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/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 +45 -9
- package/lib/testing/make-test-services.d.ts.map +1 -1
- package/lib/testing/make-test-services.js +19 -3
- package/lib/testing/make-test-services.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 +10 -2
- package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
- package/lib/testing/node/lsp-server-connection.js +42 -9
- 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 +9 -4
- 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 +33 -1
- 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/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 +14 -4
- package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-capture.js +21 -4
- 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/stub-ast-document-manager.d.ts +5 -5
- package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.js +4 -6
- package/lib/testing/stub-ast-document-manager.js.map +1 -1
- package/lib/testing/stub-document-builder.d.ts +8 -0
- package/lib/testing/stub-document-builder.d.ts.map +1 -1
- package/lib/testing/stub-document-builder.js +22 -3
- package/lib/testing/stub-document-builder.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 +5 -4
- package/lib/testing/stub-model-service.d.ts.map +1 -1
- package/lib/testing/stub-model-service.js +2 -2
- package/lib/testing/stub-model-service.js.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/package.json +17 -8
- package/src/documents/ast-document-manager.ts +129 -36
- package/src/documents/client-ids.ts +5 -22
- package/src/documents/hydranium-text-documents.ts +256 -81
- package/src/documents/language-client-text-shadow.ts +59 -11
- package/src/documents/self-save-registry.ts +52 -13
- package/src/index.ts +6 -0
- package/src/langium/ast-extension/ast-node-builder.ts +66 -22
- package/src/langium/bootstrap.ts +16 -9
- package/src/langium/config/configuration-provider.ts +119 -0
- package/src/langium/config/index.ts +1 -0
- package/src/langium/diagnostics/lsp-logger.ts +41 -6
- 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 +339 -11
- package/src/langium/document-builder/index.ts +1 -0
- package/src/langium/integration-services.ts +67 -6
- package/src/langium/integrity/integrity-service.ts +116 -2
- 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 +38 -0
- package/src/langium/model-service/model-service.ts +266 -34
- package/src/langium/module.ts +106 -21
- package/src/langium/naming/name-provider.ts +27 -5
- package/src/langium/naming/name-separator-validation.ts +34 -5
- package/src/langium/residency/cst-residency-service.ts +36 -14
- 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 +19 -2
- package/src/langium/shared-services.ts +19 -2
- package/src/langium/transfer/transfer-encoder.ts +85 -24
- 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/validation/document-validator.ts +537 -11
- package/src/langium/workspace/document-uri-policy.ts +3 -4
- package/src/langium/workspace/file-system-provider.ts +48 -8
- package/src/langium/workspace/hydranium-langium-document-factory.ts +34 -0
- package/src/langium/workspace/hydranium-workspace-manager.ts +30 -1
- package/src/langium/workspace/in-memory-file-system-provider.ts +53 -10
- package/src/langium/workspace/initialize-workspace.ts +35 -5
- package/src/langium/workspace/langium-documents.ts +106 -33
- package/src/langium/workspace/virtual-document.ts +21 -3
- 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 +10 -1
- 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/start-language-server.ts +10 -3
- package/src/messages/carriers.ts +78 -0
- package/src/messages/index.ts +36 -0
- package/src/messages/renderer.ts +206 -0
- package/src/node/heap-ceiling.ts +108 -0
- package/src/node/index.ts +1 -0
- 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 +154 -47
- package/src/node/profile-capture.ts +8 -2
- package/src/node/profiling-run.ts +3 -3
- package/src/node/rename-over-open-readers.ts +78 -0
- package/src/node/socket-launcher.ts +18 -2
- package/src/testing/fake-document.ts +24 -5
- package/src/testing/make-noop-shared-services.ts +50 -2
- package/src/testing/make-test-services.ts +74 -18
- 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 +60 -10
- package/src/testing/node/scratch-workspace.ts +9 -4
- package/src/testing/node/spawned-server.ts +35 -1
- package/src/testing/node/unhandled-rejections.ts +31 -0
- 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 +24 -5
- package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
- package/src/testing/stub-ast-document-manager.ts +10 -14
- package/src/testing/stub-document-builder.ts +32 -3
- package/src/testing/stub-langium-documents.ts +3 -2
- package/src/testing/stub-model-service.ts +7 -6
- package/src/util/connection-liveness.ts +37 -14
- 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/src/lsp/instrument-connection.ts +0 -66
|
@@ -11,11 +11,12 @@ import {
|
|
|
11
11
|
type CanonicalUri,
|
|
12
12
|
type CloseModelArgs,
|
|
13
13
|
ConflictError,
|
|
14
|
+
isSnapshotVersion,
|
|
15
|
+
defineMessage,
|
|
14
16
|
Logger,
|
|
15
17
|
type MaybeObservableValue,
|
|
16
18
|
type MaybePromise,
|
|
17
19
|
ObservableValue,
|
|
18
|
-
type TransferDiagnostic,
|
|
19
20
|
type TransferElement,
|
|
20
21
|
type OpenModelArgs,
|
|
21
22
|
type Tracer,
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
type TransferUpdateArgs
|
|
24
25
|
} from '@hydranium/protocol';
|
|
25
26
|
import { type AstNode, DocumentState, type LangiumDocument, UriUtils, type URI } from '@hydranium/langium';
|
|
27
|
+
import { type AstDiagnostic } from '../validation/document-validator.js';
|
|
26
28
|
import { type DocumentUriPolicy } from '../workspace/document-uri-policy.js';
|
|
27
29
|
import { ReentrantWriteLockError, isInsideWriteLock } from '../workspace/write-lock-scope.js';
|
|
28
30
|
import { type CancellationToken, type Disposable } from 'vscode-languageserver';
|
|
@@ -34,6 +36,23 @@ import { labelPhaseListener } from '../document-builder/labeled-phase-listener.j
|
|
|
34
36
|
import { LANGUAGE_CLIENT_ID } from '../../documents/client-ids.js';
|
|
35
37
|
import { type ServerSharedServices } from '../module.js';
|
|
36
38
|
|
|
39
|
+
/**
|
|
40
|
+
* The undo-stack entry for a server-authored write pushed to the editor.
|
|
41
|
+
*
|
|
42
|
+
* **A user-facing LABEL, not a log string**, which is easy to miss because it
|
|
43
|
+
* travels as an options field rather than as a message: LSP specifies
|
|
44
|
+
* `ApplyWorkspaceEditParams.label` as "presented in the user interface for
|
|
45
|
+
* example on an undo stack to undo the workspace edit". So a user who edits
|
|
46
|
+
* through a form or drags a diagram node reads this in their editor's undo menu
|
|
47
|
+
* — which is why it is rendered like any other message the server sends rather
|
|
48
|
+
* than left as the English literal it was.
|
|
49
|
+
*
|
|
50
|
+
* Parameterless deliberately. The obvious improvement is to name the document,
|
|
51
|
+
* and it is the wrong one: an undo menu is already grouped under the file, so
|
|
52
|
+
* the URI would be noise in the one place it is redundant.
|
|
53
|
+
*/
|
|
54
|
+
export const MODEL_UPDATE_EDIT = defineMessage('hydranium/core/model-update-edit', 'Update Model');
|
|
55
|
+
|
|
37
56
|
/** Max time {@link ModelService.settleSave} waits for the build to settle and the sync chain to drain. */
|
|
38
57
|
const SAVE_SETTLE_TIMEOUT_MS = 10_000;
|
|
39
58
|
|
|
@@ -115,6 +134,10 @@ export interface ModelServiceOptions extends LogNameOptions {
|
|
|
115
134
|
}
|
|
116
135
|
|
|
117
136
|
/**
|
|
137
|
+
* The seam every non-LSP head talks to: the data server, the GLSP head and an
|
|
138
|
+
* adopter's own services reach documents through this slot rather than through
|
|
139
|
+
* the workspace stores.
|
|
140
|
+
*
|
|
118
141
|
* In-process facade over the framework's document plumbing
|
|
119
142
|
* (`HydraniumTextDocuments`, `LangiumDocuments`,
|
|
120
143
|
* `DocumentBuilder`, `WritableFileSystemProvider`). Owns the
|
|
@@ -173,18 +196,89 @@ export interface ModelServiceOptions extends LogNameOptions {
|
|
|
173
196
|
* by URI happens here so consumers can subscribe per-document without
|
|
174
197
|
* implementing the URI gate at each callsite.
|
|
175
198
|
*
|
|
199
|
+
* **Two families, and the distinction matters more than the names suggest.**
|
|
200
|
+
* `waitFor*` is a pure wait — it never triggers a build, so a caller waiting on
|
|
201
|
+
* a document no build has touched waits until something else builds it.
|
|
202
|
+
* `ensureDocumentState` and the phase shorthands over it *dispatch*: warm
|
|
203
|
+
* documents are awaited, cold ones are built.
|
|
204
|
+
*
|
|
205
|
+
* **Diagnostics are typed `never` below `Validated`.** Validation is the last
|
|
206
|
+
* phase, so at any earlier landmark the array either is not yet computed or
|
|
207
|
+
* still holds the previous build's, and reading it would take stale results
|
|
208
|
+
* for fresh ones. A caller that needs diagnostics asks for {@link validated}.
|
|
209
|
+
*
|
|
210
|
+
* What the `never` buys, exactly: reading a field off an element is a compile
|
|
211
|
+
* error, and nothing can be appended. It does NOT stop a caller assigning an
|
|
212
|
+
* element to a typed variable, because `never` is assignable to everything — so
|
|
213
|
+
* this is a guard against reaching for diagnostics by accident, not a seal
|
|
214
|
+
* against doing it deliberately.
|
|
215
|
+
*
|
|
216
|
+
* The waits resolve at or ABOVE their target, so an already-validated document
|
|
217
|
+
* does carry usable diagnostics and the `never` over-forbids there. That
|
|
218
|
+
* direction is the safe one: the alternative permits stale reads silently. A
|
|
219
|
+
* member taking a phase as a PARAMETER cannot judge statically and so returns
|
|
220
|
+
* `TDiagnostic`, leaving the choice to the caller.
|
|
221
|
+
*
|
|
176
222
|
* **Generic parameters.**
|
|
177
223
|
* - `TAst` — the AST root type each consumer expects on the returned
|
|
178
224
|
* {@link AstDocument}. Constrained to {@link AstNode}.
|
|
179
|
-
* - `TDiagnostic` —
|
|
180
|
-
* `
|
|
225
|
+
* - `TDiagnostic` — the AST-layer diagnostic: whatever the build left on
|
|
226
|
+
* `LangiumDocument.diagnostics`, carried through on the returned
|
|
227
|
+
* {@link AstDocument}. Defaults to {@link AstDiagnostic}.
|
|
228
|
+
* **Not the `TransferEncoder`'s parameter of the same name**, which is
|
|
229
|
+
* that encoder's OUTPUT and so names the wire shape. This one names its
|
|
230
|
+
* input, and an adopter binds the two to different types.
|
|
181
231
|
* - `TTransfer` — transfer-model root accepted by `update` / `save`
|
|
182
232
|
* args. Constrained to {@link TransferElement}. Defaults to the
|
|
183
233
|
* structural base.
|
|
184
234
|
*/
|
|
185
|
-
export
|
|
235
|
+
export interface ModelService<
|
|
236
|
+
TAst extends AstNode,
|
|
237
|
+
TDiagnostic extends AstDiagnostic = AstDiagnostic,
|
|
238
|
+
TTransfer extends TransferElement = TransferElement
|
|
239
|
+
> {
|
|
240
|
+
/**
|
|
241
|
+
* Resolves once the workspace has been initialised and its first build has
|
|
242
|
+
* completed — the gate every read should wait behind, since a document
|
|
243
|
+
* queried before it may be unbuilt and reach no phase.
|
|
244
|
+
*
|
|
245
|
+
* A property rather than a method, matching `ProjectManager.ready` and
|
|
246
|
+
* Langium's `WorkspaceManager.ready`. An implementation needing a stricter
|
|
247
|
+
* gate supplies a Promise that awaits its own concern as well.
|
|
248
|
+
*/
|
|
249
|
+
readonly ready: Promise<void>;
|
|
250
|
+
|
|
251
|
+
// Pure waits — never trigger a build.
|
|
252
|
+
waitForDocumentState(uri: string, state: DocumentState, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
|
|
253
|
+
waitForDocumentSettled(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>>;
|
|
254
|
+
waitForBuilderState(state: DocumentState, cancelToken?: CancellationToken): Promise<void>;
|
|
255
|
+
|
|
256
|
+
// Wait if warm, build if cold.
|
|
257
|
+
ensureDocumentState(uri: string, state?: DocumentState, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
|
|
258
|
+
rebuild(uri: string, state?: DocumentState, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
|
|
259
|
+
parsed(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>>;
|
|
260
|
+
linked(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>>;
|
|
261
|
+
settled(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>>;
|
|
262
|
+
indexed(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>>;
|
|
263
|
+
validated(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
|
|
264
|
+
|
|
265
|
+
update(args: TransferUpdateArgs<TTransfer>, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
|
|
266
|
+
save(args: TransferSaveArgs<TTransfer>, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>>;
|
|
267
|
+
|
|
268
|
+
open(args: OpenModelArgs): Promise<Disposable>;
|
|
269
|
+
close(args: CloseModelArgs): Promise<void>;
|
|
270
|
+
isOpen(uri: string): boolean;
|
|
271
|
+
snapshot(uri: string): AstDocument<TAst, TDiagnostic> | undefined;
|
|
272
|
+
getDocument(uri: string): LangiumDocument | undefined;
|
|
273
|
+
|
|
274
|
+
onModelUpdated(uri: string, listener: (event: AstDocumentUpdatedEvent<TAst, TDiagnostic>) => void): Disposable;
|
|
275
|
+
onModelSaved(uri: string, listener: (event: AstDocumentSavedEvent<TAst, TDiagnostic>) => void): Disposable;
|
|
276
|
+
onClientClosed(uri: string, clientId: string, listener: () => void): Disposable;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export class DefaultModelService<
|
|
186
280
|
TAst extends AstNode,
|
|
187
|
-
TDiagnostic =
|
|
281
|
+
TDiagnostic extends AstDiagnostic = AstDiagnostic,
|
|
188
282
|
/**
|
|
189
283
|
* Structured payload accepted by `update` / `save`. Constrained to
|
|
190
284
|
* {@link TransferElement} — the minimal `{ readonly $type: string }`
|
|
@@ -195,7 +289,7 @@ export class ModelService<
|
|
|
195
289
|
* integrity service) that pass AST roots remain compatible.
|
|
196
290
|
*/
|
|
197
291
|
TTransfer extends TransferElement = TransferElement
|
|
198
|
-
> {
|
|
292
|
+
> implements ModelService<TAst, TDiagnostic, TTransfer> {
|
|
199
293
|
protected readonly tracer: Tracer;
|
|
200
294
|
/**
|
|
201
295
|
* The single document-identity seam (`services.workspace.DocumentUriPolicy`),
|
|
@@ -329,8 +423,12 @@ export class ModelService<
|
|
|
329
423
|
* {@link waitForDocumentState} for the common "wait until content is stable"
|
|
330
424
|
* case (e.g. settling a save). Pure wait — does not trigger a build.
|
|
331
425
|
*/
|
|
332
|
-
async waitForDocumentSettled(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst,
|
|
333
|
-
return this.waitForDocumentStateCanonical(
|
|
426
|
+
async waitForDocumentSettled(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>> {
|
|
427
|
+
return (await this.waitForDocumentStateCanonical(
|
|
428
|
+
this.uriPolicy.canonicalUri(uri),
|
|
429
|
+
IntegrityService.SettledState,
|
|
430
|
+
cancelToken
|
|
431
|
+
)) as AstDocument<TAst, never>;
|
|
334
432
|
}
|
|
335
433
|
|
|
336
434
|
/**
|
|
@@ -484,11 +582,19 @@ export class ModelService<
|
|
|
484
582
|
*
|
|
485
583
|
* Phase invariants encoded in the return type:
|
|
486
584
|
* - `parsed` / `linked` / `settled` / `indexed` return
|
|
487
|
-
* `AstDocument<TAst, never>` — diagnostics
|
|
488
|
-
*
|
|
585
|
+
* `AstDocument<TAst, never>` — no diagnostics have been computed at
|
|
586
|
+
* those phases.
|
|
489
587
|
* - `validated` returns `AstDocument<TAst, TDiagnostic>` — diagnostics
|
|
490
588
|
* are populated.
|
|
491
589
|
*
|
|
590
|
+
* **The `never` is enforced, not merely declared.** The wait underneath
|
|
591
|
+
* resolves at or ABOVE the requested state, so a document something else
|
|
592
|
+
* already carried past `Validated` would otherwise come back from
|
|
593
|
+
* `settled()` carrying a full diagnostics array typed `never`; these four
|
|
594
|
+
* strip it. An empty array here therefore means "this read does not report
|
|
595
|
+
* diagnostics", never "this document is clean" — call {@link validated}
|
|
596
|
+
* when the answer has to mean the second.
|
|
597
|
+
*
|
|
492
598
|
* `settled` is the integrity-overlay name for "all integrity rules
|
|
493
599
|
* have fired"; it maps to {@link IntegrityService.SettledState} (which
|
|
494
600
|
* equals `DocumentState.IndexedReferences`), but the dedicated method
|
|
@@ -496,19 +602,19 @@ export class ModelService<
|
|
|
496
602
|
* ever moves.
|
|
497
603
|
*/
|
|
498
604
|
async parsed(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>> {
|
|
499
|
-
return this.ensureDocumentState(uri, DocumentState.Parsed, cancelToken)
|
|
605
|
+
return this.withoutDiagnostics(await this.ensureDocumentState(uri, DocumentState.Parsed, cancelToken));
|
|
500
606
|
}
|
|
501
607
|
|
|
502
608
|
async linked(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>> {
|
|
503
|
-
return this.ensureDocumentState(uri, DocumentState.Linked, cancelToken)
|
|
609
|
+
return this.withoutDiagnostics(await this.ensureDocumentState(uri, DocumentState.Linked, cancelToken));
|
|
504
610
|
}
|
|
505
611
|
|
|
506
612
|
async settled(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>> {
|
|
507
|
-
return this.ensureDocumentState(uri, IntegrityService.SettledState, cancelToken)
|
|
613
|
+
return this.withoutDiagnostics(await this.ensureDocumentState(uri, IntegrityService.SettledState, cancelToken));
|
|
508
614
|
}
|
|
509
615
|
|
|
510
616
|
async indexed(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, never>> {
|
|
511
|
-
return this.ensureDocumentState(uri, DocumentState.IndexedReferences, cancelToken)
|
|
617
|
+
return this.withoutDiagnostics(await this.ensureDocumentState(uri, DocumentState.IndexedReferences, cancelToken));
|
|
512
618
|
}
|
|
513
619
|
|
|
514
620
|
async validated(uri: string, cancelToken?: CancellationToken): Promise<AstDocument<TAst, TDiagnostic>> {
|
|
@@ -596,22 +702,44 @@ export class ModelService<
|
|
|
596
702
|
const run = async <T>(stage: string, fn: () => MaybePromise<T>): Promise<T> => (session ? session.scope(stage, fn) : fn());
|
|
597
703
|
// Open WITH the new text so a cold URI (no open editor, no file on disk) is
|
|
598
704
|
// created from the payload rather than read from the filesystem — `update`
|
|
599
|
-
// is an upsert. For an already-open document `open`
|
|
600
|
-
// text is ignored on that branch),
|
|
601
|
-
//
|
|
602
|
-
// create stays at its initial version
|
|
603
|
-
//
|
|
705
|
+
// is an upsert. For an already-open document `open` only attaches the
|
|
706
|
+
// client (the text is ignored on that branch), and the actual update is
|
|
707
|
+
// `AstDocumentManager.update`'s. `version` is intentionally NOT
|
|
708
|
+
// forwarded to `open`, so a cold create stays at its initial version
|
|
709
|
+
// rather than adopting a number the caller chose.
|
|
710
|
+
//
|
|
711
|
+
// The gate reads the version and decides BEFORE the open, and both halves
|
|
712
|
+
// of that matter.
|
|
713
|
+
//
|
|
714
|
+
// Reading first, because for a document no client holds open the open
|
|
715
|
+
// assigns the shared version from the INCOMING text, so a version read
|
|
716
|
+
// afterwards has already absorbed the caller's own write. Gating on it
|
|
717
|
+
// rejects every modifying write to a closed document, comparing the
|
|
718
|
+
// caller's `basedOn` against a number the caller itself produced — and a
|
|
719
|
+
// serialised round-trip that is not byte-identical to the stored text is
|
|
720
|
+
// enough to trigger that. Reading first keeps both cases the gate exists
|
|
721
|
+
// for: an unknown URI answers 0, so a based-on-version update of a
|
|
722
|
+
// not-yet-existing document still trips it, and a genuine conflict still
|
|
723
|
+
// trips it, another writer having advanced the sequence past the version
|
|
724
|
+
// the caller read.
|
|
725
|
+
//
|
|
726
|
+
// Deciding first, because the open is a mutation and `update` is an
|
|
727
|
+
// upsert: for a cold URI it installs the payload in the shared text store
|
|
728
|
+
// and records a hold for the writing client. Throwing after it hands the
|
|
729
|
+
// caller its rejection while the server keeps the refused text — and the
|
|
730
|
+
// hold outlives the call, because a client whose write failed has no
|
|
731
|
+
// reason to close a document it never asked to open. Serialisation is
|
|
732
|
+
// held back too; it is the adopter's code and need not be side-effect
|
|
733
|
+
// free.
|
|
734
|
+
const currentVersion = this.services.workspace.TextDocuments.version(uri);
|
|
735
|
+
if (isSnapshotVersion(args.basedOn) && currentVersion !== args.basedOn) {
|
|
736
|
+
// Distinct from the post-build "superseded" debug line below: this is a
|
|
737
|
+
// based-on-stale rejection (the write never applies), not two writes racing.
|
|
738
|
+
this.tracer.debug(`Conflict on ${uri}: based-on v${args.basedOn} stale, server at v${currentVersion}`);
|
|
739
|
+
throw new ConflictError(uri, args.basedOn, currentVersion);
|
|
740
|
+
}
|
|
604
741
|
const text = await run('serialize', () => this.modelToText(uri, args.model, cancelToken));
|
|
605
742
|
await run('open', () => this.open({ uri, clientId: args.clientId, text }));
|
|
606
|
-
if (args.baseVersion !== undefined) {
|
|
607
|
-
const current = this.services.workspace.TextDocuments.version(uri);
|
|
608
|
-
if (current !== args.baseVersion) {
|
|
609
|
-
// Distinct from the post-build "superseded" debug line below: this is a
|
|
610
|
-
// based-on-stale rejection (the write never applies), not two writes racing.
|
|
611
|
-
this.tracer.debug(`Conflict on ${uri}: based-on v${args.baseVersion} stale, server at v${current}`);
|
|
612
|
-
throw new ConflictError(uri, args.baseVersion, current);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
743
|
const appliedVersion = await run('apply', () => this.services.workspace.AstDocumentManager.update(uri, text, args.clientId));
|
|
616
744
|
// Dispatch through the public `rebuild` (which re-canonicalizes the already-
|
|
617
745
|
// canonical `uri` once, idempotently) rather than `rebuildCanonical`, so an
|
|
@@ -733,6 +861,31 @@ export class ModelService<
|
|
|
733
861
|
return this.services.workspace.AstDocumentManager.isOpen(uri);
|
|
734
862
|
}
|
|
735
863
|
|
|
864
|
+
/**
|
|
865
|
+
* Snapshot of `uri` as it stands RIGHT NOW — the synchronous sibling of the
|
|
866
|
+
* phase reads, which all wait. `undefined` when no document is registered.
|
|
867
|
+
*
|
|
868
|
+
* **This is what a writer wants, and {@link getDocument} is not.** The
|
|
869
|
+
* envelope's `version` is copied by value at projection time, so it cannot
|
|
870
|
+
* move afterwards; a version read off the live document at write time is
|
|
871
|
+
* whatever the server is at *now*, which is the number an optimistic gate is
|
|
872
|
+
* about to compare it against.
|
|
873
|
+
*
|
|
874
|
+
* Diagnostics only from a document that has reached `Validated`, and an
|
|
875
|
+
* empty array otherwise. Unlike the phase reads this one names no phase, so
|
|
876
|
+
* the state it finds is the only thing that can say whether the array
|
|
877
|
+
* describes the content being handed back or whatever an earlier build left.
|
|
878
|
+
* A caller that needs them unconditionally waits, via {@link validated}.
|
|
879
|
+
*/
|
|
880
|
+
snapshot(uri: string): AstDocument<TAst, TDiagnostic> | undefined {
|
|
881
|
+
const document = this.getDocument(uri);
|
|
882
|
+
if (!document) {
|
|
883
|
+
return undefined;
|
|
884
|
+
}
|
|
885
|
+
const envelope = AstDocument.from<TAst, TDiagnostic>(document);
|
|
886
|
+
return document.state >= DocumentState.Validated ? envelope : this.withoutDiagnostics(envelope);
|
|
887
|
+
}
|
|
888
|
+
|
|
736
889
|
/**
|
|
737
890
|
* The built {@link LangiumDocument} for `uri`, looked up by canonical identity —
|
|
738
891
|
* the synchronous, phase-agnostic sibling of {@link ensureDocumentState} /
|
|
@@ -741,6 +894,13 @@ export class ModelService<
|
|
|
741
894
|
* into `LangiumDocuments` directly: a symlinked / `..` / case-divergent URI
|
|
742
895
|
* still resolves to the one document the build keys by its real path. Returns
|
|
743
896
|
* `undefined` if no document is registered for `uri`.
|
|
897
|
+
*
|
|
898
|
+
* **Live, so do not take a based-on version off it.** `textDocument` is the
|
|
899
|
+
* store's own object rather than a copy, so `.version` read here answers for
|
|
900
|
+
* the moment of the READ, not the moment of the earlier content — pass it to
|
|
901
|
+
* a write and the server compares its current version against itself, the
|
|
902
|
+
* gate passes unconditionally, and a concurrent edit is overwritten with
|
|
903
|
+
* nothing logged. Use {@link snapshot} for that, or a phase read.
|
|
744
904
|
*/
|
|
745
905
|
getDocument(uri: string): LangiumDocument | undefined {
|
|
746
906
|
return this.services.workspace.AstDocumentManager.getDocument(uri);
|
|
@@ -834,17 +994,17 @@ export class ModelService<
|
|
|
834
994
|
*
|
|
835
995
|
* The signal is "a known client other than the language client authored this
|
|
836
996
|
* version **and** the URI was in the last build's changed set
|
|
837
|
-
* (`
|
|
997
|
+
* (`isTriggeringEdit`)". A framework-internal rebuild reports no author
|
|
838
998
|
* (`getAuthor` → `undefined`), so it fails `hasKnownAuthor` without comparing
|
|
839
999
|
* against a sentinel. This is NOT redundant with content/registration — it
|
|
840
1000
|
* distinguishes "client edited" from "framework rebuilt", which neither the
|
|
841
|
-
* shadow nor `
|
|
1001
|
+
* shadow nor `isTriggeringEdit` alone can.
|
|
842
1002
|
*/
|
|
843
1003
|
protected isNonLanguageClientEdit(document: LangiumDocument): boolean {
|
|
844
1004
|
const documents = this.services.workspace.AstDocumentManager;
|
|
845
1005
|
const author = documents.getAuthor(document);
|
|
846
1006
|
const hasKnownAuthor = !!author && author !== LANGUAGE_CLIENT_ID;
|
|
847
|
-
return hasKnownAuthor && documents.
|
|
1007
|
+
return hasKnownAuthor && documents.isTriggeringEdit(document.textDocument.uri);
|
|
848
1008
|
}
|
|
849
1009
|
|
|
850
1010
|
/**
|
|
@@ -878,13 +1038,26 @@ export class ModelService<
|
|
|
878
1038
|
this.syncChains.set(uri, chain);
|
|
879
1039
|
}
|
|
880
1040
|
|
|
1041
|
+
/**
|
|
1042
|
+
* The undo-stack label for a server-authored write, in the locale the server
|
|
1043
|
+
* was handed at init.
|
|
1044
|
+
*
|
|
1045
|
+
* One method rather than the literal at each `applyEdit`, because the two
|
|
1046
|
+
* call sites are the same edit — a push and its full-replace retry — and an
|
|
1047
|
+
* undo menu showing two different words for one operation would read as two
|
|
1048
|
+
* operations.
|
|
1049
|
+
*/
|
|
1050
|
+
protected editLabel(): string {
|
|
1051
|
+
return this.services.MessageRenderer.renderMessage(MODEL_UPDATE_EDIT);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
881
1054
|
protected async drainSyncQueue(uri: string): Promise<void> {
|
|
882
1055
|
const uriLogger = this.tracer.withUri(uri);
|
|
883
1056
|
while (this.pendingSync.has(uri)) {
|
|
884
1057
|
const text = this.pendingSync.get(uri)!;
|
|
885
1058
|
this.pendingSync.delete(uri);
|
|
886
1059
|
try {
|
|
887
|
-
let result = await this.services.workspace.TextDocuments.applyEditToLanguageClient(uri, text, { label:
|
|
1060
|
+
let result = await this.services.workspace.TextDocuments.applyEditToLanguageClient(uri, text, { label: this.editLabel() });
|
|
888
1061
|
if (result?.applied === false && !this.pendingSync.has(uri)) {
|
|
889
1062
|
// The push is addressed at the client's LAST DECLARED VERSION, so a
|
|
890
1063
|
// rejection normally means the client's buffer moved while the
|
|
@@ -905,7 +1078,7 @@ export class ModelService<
|
|
|
905
1078
|
// queued — best-effort, since a settle arriving later simply pushes
|
|
906
1079
|
// after this and still wins.
|
|
907
1080
|
uriLogger.warn(`Language client rejected applyEdit at its declared version — re-pushing a full replace`);
|
|
908
|
-
result = await this.services.workspace.TextDocuments.applyEditToLanguageClient(uri, text, { label:
|
|
1081
|
+
result = await this.services.workspace.TextDocuments.applyEditToLanguageClient(uri, text, { label: this.editLabel() });
|
|
909
1082
|
if (result?.applied === false) {
|
|
910
1083
|
uriLogger.warn(`Language client rejected the full-replace retry too — client content is stale`);
|
|
911
1084
|
}
|
|
@@ -1013,7 +1186,47 @@ export class ModelService<
|
|
|
1013
1186
|
return model;
|
|
1014
1187
|
}
|
|
1015
1188
|
const rewritten = await this.rewriteModel(uri, model, cancelToken);
|
|
1016
|
-
|
|
1189
|
+
const target = UriUtils.toUri(uri);
|
|
1190
|
+
const trivia = this.services.ServiceRegistry?.getServices(target)?.trivia?.TriviaService;
|
|
1191
|
+
// Extracted BEFORE serializing, so it reads the document the write is
|
|
1192
|
+
// about to replace rather than whatever a concurrent build left behind.
|
|
1193
|
+
let document = this.services.workspace.LangiumDocuments.getDocument(target);
|
|
1194
|
+
if (trivia !== undefined && document === undefined) {
|
|
1195
|
+
const source = await this.textToTakeTriviaFrom(uri, target);
|
|
1196
|
+
if (source !== undefined) {
|
|
1197
|
+
document = this.services.workspace.LangiumDocumentFactory.fromString(source, target);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
const extracted = trivia !== undefined && document !== undefined ? trivia.extract(document) : undefined;
|
|
1201
|
+
const serialized = await this.serialize(uri, rewritten);
|
|
1202
|
+
return extracted === undefined ? serialized : trivia!.apply(serialized, extracted, target);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/**
|
|
1206
|
+
* The text a write into an unloaded document should take its trivia from —
|
|
1207
|
+
* the open editor's if one holds it, the file's otherwise, and `undefined`
|
|
1208
|
+
* when neither can supply it.
|
|
1209
|
+
*
|
|
1210
|
+
* **A read that fails answers `undefined` rather than throwing.** `getDocument`
|
|
1211
|
+
* is a store read, so an ordinary create answers nothing here and must still
|
|
1212
|
+
* write; letting a permission error or a path that turned into a directory
|
|
1213
|
+
* escape would fail the user's write instead, having found nothing to preserve
|
|
1214
|
+
* in a file the write is about to replace anyway. Losing the comments is
|
|
1215
|
+
* recoverable, and traced; losing the write is neither.
|
|
1216
|
+
*/
|
|
1217
|
+
protected async textToTakeTriviaFrom(uri: string, target: URI): Promise<string | undefined> {
|
|
1218
|
+
const open = this.services.workspace.TextDocuments.get(uri)?.getText();
|
|
1219
|
+
if (open !== undefined) {
|
|
1220
|
+
return open;
|
|
1221
|
+
}
|
|
1222
|
+
const fileSystem = this.services.workspace.FileSystemProvider;
|
|
1223
|
+
try {
|
|
1224
|
+
return (await fileSystem.exists(target)) ? await fileSystem.readFile(target) : undefined;
|
|
1225
|
+
} catch (err: unknown) {
|
|
1226
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1227
|
+
this.tracer.withUri(uri).debug(`Could not read the file to take trivia from; writing as emitted. ${detail}`);
|
|
1228
|
+
return undefined;
|
|
1229
|
+
}
|
|
1017
1230
|
}
|
|
1018
1231
|
|
|
1019
1232
|
/**
|
|
@@ -1048,4 +1261,23 @@ export class ModelService<
|
|
|
1048
1261
|
? AstDocument.from<TAst, TDiagnostic>(document)
|
|
1049
1262
|
: AstDocument.create<TAst, TDiagnostic>(uri.toString(), 0, undefined as unknown as TAst, []);
|
|
1050
1263
|
}
|
|
1264
|
+
|
|
1265
|
+
/**
|
|
1266
|
+
* The same envelope with no diagnostics, for a read that names a phase below
|
|
1267
|
+
* `Validated`.
|
|
1268
|
+
*
|
|
1269
|
+
* Langium fills `LangiumDocument.diagnostics` from inside `validateDocument`
|
|
1270
|
+
* and from nowhere else, so below that phase the array holds whatever an
|
|
1271
|
+
* EARLIER build left — a verdict about text the document may no longer have.
|
|
1272
|
+
* The wait underneath resolves at or above the phase asked for, so a document
|
|
1273
|
+
* something else carried past `Validated` would otherwise hand a full array
|
|
1274
|
+
* back from `parsed()`.
|
|
1275
|
+
*
|
|
1276
|
+
* A copy rather than a clear: the envelope is freshly built here, but
|
|
1277
|
+
* {@link toAstDocument} is overridable and an adopter's version may return
|
|
1278
|
+
* one it also keeps.
|
|
1279
|
+
*/
|
|
1280
|
+
protected withoutDiagnostics(document: AstDocument<TAst, TDiagnostic>): AstDocument<TAst, never> {
|
|
1281
|
+
return { ...document, diagnostics: [] };
|
|
1282
|
+
}
|
|
1051
1283
|
}
|