@hydranium/core 1.0.0-next.16 → 1.0.0-next.168
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 +5 -1
- package/lib/documents/ast-document-manager.d.ts +190 -29
- package/lib/documents/ast-document-manager.d.ts.map +1 -1
- package/lib/documents/ast-document-manager.js +235 -38
- 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 +138 -0
- package/lib/documents/client-session-registry.d.ts.map +1 -0
- package/lib/documents/client-session-registry.js +187 -0
- package/lib/documents/client-session-registry.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 +439 -82
- package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
- package/lib/documents/hydranium-text-documents.js +769 -159
- package/lib/documents/hydranium-text-documents.js.map +1 -1
- package/lib/documents/index.d.ts +3 -0
- package/lib/documents/index.d.ts.map +1 -1
- package/lib/documents/index.js +3 -0
- package/lib/documents/index.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 +365 -19
- package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
- package/lib/langium/document-builder/document-builder.js +637 -44
- 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-rule.d.ts +13 -5
- 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 +50 -6
- package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-service.js +193 -17
- 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 +27 -2
- package/lib/langium/language-module.d.ts.map +1 -1
- package/lib/langium/language-module.js +16 -2
- package/lib/langium/language-module.js.map +1 -1
- package/lib/langium/model-service/client-session.d.ts +307 -0
- package/lib/langium/model-service/client-session.d.ts.map +1 -0
- package/lib/langium/model-service/client-session.js +395 -0
- package/lib/langium/model-service/client-session.js.map +1 -0
- package/lib/langium/model-service/index.d.ts +1 -0
- package/lib/langium/model-service/index.d.ts.map +1 -1
- package/lib/langium/model-service/index.js +1 -0
- package/lib/langium/model-service/index.js.map +1 -1
- package/lib/langium/model-service/model-service.d.ts +261 -198
- package/lib/langium/model-service/model-service.d.ts.map +1 -1
- package/lib/langium/model-service/model-service.js +234 -346
- package/lib/langium/model-service/model-service.js.map +1 -1
- package/lib/langium/module.d.ts +144 -35
- package/lib/langium/module.d.ts.map +1 -1
- package/lib/langium/module.js +45 -34
- 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/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/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/workspace/document-uri-policy.d.ts +17 -12
- 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 +17 -0
- package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
- package/lib/langium/workspace/file-not-found.js +20 -0
- package/lib/langium/workspace/file-not-found.js.map +1 -0
- package/lib/langium/workspace/file-system-provider.d.ts +84 -8
- 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 +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-lock.d.ts +13 -0
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js +18 -0
- package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts +77 -8
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.js +115 -9
- package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts +25 -2
- 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/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 +79 -17
- package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
- package/lib/langium/workspace/langium-documents.js +91 -29
- package/lib/langium/workspace/langium-documents.js.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.d.ts +0 -7
- 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/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 +4 -3
- package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
- package/lib/langium/workspace/write-lock-scope.js +4 -3
- 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 +90 -79
- package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.js +152 -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/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 +39 -4
- 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.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 +16 -1
- package/lib/node/socket-launcher.d.ts.map +1 -1
- package/lib/node/socket-launcher.js +4 -3
- package/lib/node/socket-launcher.js.map +1 -1
- package/lib/node/stdio-launcher.d.ts +1 -1
- package/lib/node/stdio-launcher.d.ts.map +1 -1
- package/lib/node/stdio-launcher.js +1 -1
- package/lib/node/stdio-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 +62 -14
- package/lib/testing/make-test-services.d.ts.map +1 -1
- package/lib/testing/make-test-services.js +27 -6
- 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 +11 -3
- 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 +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 +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/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 +10 -9
- package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.js +17 -9
- 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 +57 -4
- package/lib/testing/stub-document-builder.js.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.d.ts +22 -7
- package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.js +92 -15
- package/lib/testing/stub-hydranium-text-documents.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/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 +348 -64
- package/src/documents/client-ids.ts +5 -22
- package/src/documents/client-session-errors.ts +24 -0
- package/src/documents/client-session-registry.ts +240 -0
- package/src/documents/file-system-task-queue.ts +68 -0
- package/src/documents/hydranium-text-documents.ts +959 -201
- package/src/documents/index.ts +3 -0
- 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 +720 -43
- package/src/langium/document-builder/index.ts +1 -0
- package/src/langium/integration-services.ts +67 -6
- package/src/langium/integrity/integrity-rule.ts +13 -5
- package/src/langium/integrity/integrity-service.ts +202 -17
- 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 +42 -4
- package/src/langium/model-service/client-session.ts +606 -0
- package/src/langium/model-service/index.ts +1 -0
- package/src/langium/model-service/model-service.ts +395 -351
- package/src/langium/module.ts +192 -63
- 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 +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/update-rewrite/update-rewrite.ts +1 -1
- package/src/langium/validation/document-validator.ts +537 -11
- package/src/langium/workspace/document-uri-policy.ts +17 -12
- package/src/langium/workspace/file-not-found.ts +23 -0
- package/src/langium/workspace/file-system-provider.ts +153 -16
- package/src/langium/workspace/hydranium-langium-document-factory.ts +34 -0
- package/src/langium/workspace/hydranium-workspace-lock.ts +21 -0
- package/src/langium/workspace/hydranium-workspace-manager.ts +133 -12
- package/src/langium/workspace/in-memory-file-system-provider.ts +47 -16
- package/src/langium/workspace/initialize-workspace.ts +43 -5
- package/src/langium/workspace/langium-documents.ts +113 -33
- package/src/langium/workspace/persistent-file-system-provider.ts +0 -7
- package/src/langium/workspace/virtual-document.ts +96 -19
- package/src/langium/workspace/write-lock-scope.ts +4 -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 +182 -106
- 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 -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 +122 -51
- 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 +19 -4
- package/src/node/stdio-launcher.ts +1 -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 +103 -27
- 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 +61 -11
- package/src/testing/node/scratch-workspace.ts +10 -5
- 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/run-update-pipeline.ts +4 -4
- package/src/testing/stub-ast-document-manager.ts +28 -21
- package/src/testing/stub-document-builder.ts +83 -17
- package/src/testing/stub-hydranium-text-documents.ts +127 -22
- package/src/testing/stub-langium-documents.ts +3 -2
- package/src/testing/stub-model-service.ts +9 -8
- 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
|
@@ -8,15 +8,17 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
+
type CanonicalUri,
|
|
11
12
|
type CloseModelArgs,
|
|
12
13
|
type Tracer,
|
|
13
14
|
type TransferSavedEvent,
|
|
14
15
|
type TransferUpdatedEvent,
|
|
15
|
-
type OpenModelArgs
|
|
16
|
+
type OpenModelArgs,
|
|
17
|
+
asSnapshotVersion,
|
|
18
|
+
type SnapshotVersion
|
|
16
19
|
} from '@hydranium/protocol';
|
|
17
20
|
import {
|
|
18
21
|
type AstNode,
|
|
19
|
-
type DocumentBuilder,
|
|
20
22
|
DocumentState,
|
|
21
23
|
type FileSystemProvider,
|
|
22
24
|
type LangiumDocument,
|
|
@@ -24,6 +26,7 @@ import {
|
|
|
24
26
|
UriUtils
|
|
25
27
|
} from '@hydranium/langium';
|
|
26
28
|
import { type LogNameOptions } from '../langium/diagnostics/logger.js';
|
|
29
|
+
import { type AstDiagnostic } from '../langium/validation/document-validator.js';
|
|
27
30
|
|
|
28
31
|
/**
|
|
29
32
|
* File-system provider extension that supports writes. Langium's standard
|
|
@@ -62,8 +65,9 @@ export interface WritableFileSystemProvider extends FileSystemProvider {
|
|
|
62
65
|
* - A non-`file:` URI (or any URI the provider cannot stat) passes through
|
|
63
66
|
* **unchanged** — it is treated as present, never reported absent.
|
|
64
67
|
* - A provider with no disk to check (in-memory / browser / empty) simply
|
|
65
|
-
* omits this method; `
|
|
66
|
-
*
|
|
68
|
+
* omits this method; the framework's `FileSystemProviderRegistry` then
|
|
69
|
+
* returns the URI unchanged, and `RealpathDocumentUriPolicy` answers as
|
|
70
|
+
* the syntactic `DefaultDocumentUriPolicy` does.
|
|
67
71
|
*
|
|
68
72
|
* Synchronous (a `realpath` is a kernel-cached syscall) and optional — the
|
|
69
73
|
* only consumers are the document-identity policy's `canonicalUri`/`loadUri`.
|
|
@@ -79,7 +83,7 @@ import { TextDocumentIdentifier, type TextDocumentItem } from 'vscode-languagese
|
|
|
79
83
|
import { type TextDocument } from 'vscode-languageserver-textdocument';
|
|
80
84
|
import { URI } from '@hydranium/langium';
|
|
81
85
|
import { type ServerSharedServices } from '../langium/module.js';
|
|
82
|
-
import { labelPhaseListener } from '../langium/document-builder/index.js';
|
|
86
|
+
import { type HydraniumDocumentBuilder, labelPhaseListener } from '../langium/document-builder/index.js';
|
|
83
87
|
import { UNKNOWN_CLIENT_ID } from './client-ids.js';
|
|
84
88
|
import { type HydraniumTextDocuments } from './hydranium-text-documents.js';
|
|
85
89
|
import { type SelfSaveRegistry } from './self-save-registry.js';
|
|
@@ -102,19 +106,18 @@ export interface UpdateInfo {
|
|
|
102
106
|
* twins; the type-system distinction is the generic constraint, and the
|
|
103
107
|
* conversion seam between them is the framework `TransferEncoder`.
|
|
104
108
|
*/
|
|
105
|
-
export interface AstDocument<TAst extends AstNode, TDiagnostic> {
|
|
109
|
+
export interface AstDocument<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> {
|
|
106
110
|
root: TAst;
|
|
107
111
|
diagnostics: TDiagnostic[];
|
|
108
112
|
uri: string;
|
|
109
113
|
/**
|
|
110
114
|
* Text-document version this snapshot was taken at — read from
|
|
111
115
|
* `LangiumDocument.textDocument.version`. Symmetric with
|
|
112
|
-
* `TransferDocument.version` on the wire side: in-process
|
|
113
|
-
*
|
|
114
|
-
* `
|
|
115
|
-
* into the conflict gate.
|
|
116
|
+
* `TransferDocument.version` on the wire side: an in-process caller that
|
|
117
|
+
* holds an `AstDocument` and mutates it sends this straight back as the
|
|
118
|
+
* `basedOn` of its session's write, and the conflict gate arms on it.
|
|
116
119
|
*/
|
|
117
|
-
version:
|
|
120
|
+
version: SnapshotVersion;
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
export namespace AstDocument {
|
|
@@ -124,13 +127,13 @@ export namespace AstDocument {
|
|
|
124
127
|
* don't need to repeat the empty array at every call site. Mirrors
|
|
125
128
|
* `TransferDocument.create` on the wire side.
|
|
126
129
|
*/
|
|
127
|
-
export function create<TAst extends AstNode, TDiagnostic =
|
|
130
|
+
export function create<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic>(
|
|
128
131
|
uri: string,
|
|
129
132
|
version: number,
|
|
130
133
|
root: TAst,
|
|
131
134
|
diagnostics: TDiagnostic[] = []
|
|
132
135
|
): AstDocument<TAst, TDiagnostic> {
|
|
133
|
-
return { uri, version, root, diagnostics };
|
|
136
|
+
return { uri, version: asSnapshotVersion(version), root, diagnostics };
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
/**
|
|
@@ -146,25 +149,107 @@ export namespace AstDocument {
|
|
|
146
149
|
* carry that identity, not the subscriber's (possibly non-canonical) URI:
|
|
147
150
|
* a subscriber already knows the URI it subscribed with, so the useful
|
|
148
151
|
* thing to surface is the canonical one every other layer keys by.
|
|
152
|
+
*
|
|
153
|
+
* Narrowing `TDiagnostic` below the constraint asserts that the validators
|
|
154
|
+
* in play produce that shape, and nothing here checks it: the build fills the
|
|
155
|
+
* array, so a document carrying a diagnostic from elsewhere — a lexer error,
|
|
156
|
+
* another validator — satisfies the declared type and not the narrowed one.
|
|
149
157
|
*/
|
|
150
|
-
export function from<TAst extends AstNode, TDiagnostic =
|
|
158
|
+
export function from<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic>(
|
|
159
|
+
document: LangiumDocument
|
|
160
|
+
): AstDocument<TAst, TDiagnostic> {
|
|
151
161
|
return create<TAst, TDiagnostic>(
|
|
152
162
|
document.textDocument.uri,
|
|
153
163
|
document.textDocument.version,
|
|
154
164
|
document.parseResult.value as TAst,
|
|
155
|
-
(document.diagnostics ?? []) as
|
|
165
|
+
(document.diagnostics ?? []) as TDiagnostic[]
|
|
156
166
|
);
|
|
157
167
|
}
|
|
158
168
|
}
|
|
159
169
|
|
|
160
170
|
/** Update event delivered by {@link AstDocumentManager.onUpdate} — typed alias over the generic event wrapper. */
|
|
161
|
-
export type AstDocumentUpdatedEvent<TAst extends AstNode, TDiagnostic> = TransferUpdatedEvent<
|
|
171
|
+
export type AstDocumentUpdatedEvent<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> = TransferUpdatedEvent<
|
|
172
|
+
AstDocument<TAst, TDiagnostic>
|
|
173
|
+
>;
|
|
162
174
|
|
|
163
175
|
/** Save event delivered by {@link AstDocumentManager.onSave} — typed alias over the generic event wrapper. */
|
|
164
|
-
export type AstDocumentSavedEvent<TAst extends AstNode, TDiagnostic> = TransferSavedEvent<
|
|
176
|
+
export type AstDocumentSavedEvent<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> = TransferSavedEvent<
|
|
177
|
+
AstDocument<TAst, TDiagnostic>
|
|
178
|
+
>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Why an update event fired and whose write it echoes, as
|
|
182
|
+
* {@link AstDocumentManager.attributeUpdate} answers for a document. The
|
|
183
|
+
* fields mean what they mean on `TransferUpdatedEvent`.
|
|
184
|
+
*/
|
|
185
|
+
export interface UpdateAttribution {
|
|
186
|
+
reason: 'changed' | 'rebuilt';
|
|
187
|
+
sourceClientId: string;
|
|
188
|
+
causedBy: string;
|
|
189
|
+
}
|
|
165
190
|
|
|
166
191
|
/** Construction options for {@link AstDocumentManager}. */
|
|
167
|
-
export
|
|
192
|
+
export interface AstDocumentManagerOptions extends LogNameOptions {
|
|
193
|
+
/**
|
|
194
|
+
* Skip a queued save of a URI when a newer save of it is queued behind. The
|
|
195
|
+
* newer save took its text later, so disk ends the same with fewer writes.
|
|
196
|
+
* A skipped save announces nothing and takes the newer save's outcome: it
|
|
197
|
+
* resolves when that one lands and rejects with its error when it fails,
|
|
198
|
+
* since disk then holds neither text. Defaults to `false`: every save
|
|
199
|
+
* writes. The framework binds the manager without options, so turning this
|
|
200
|
+
* on means rebinding `AstDocumentManager` with them.
|
|
201
|
+
*/
|
|
202
|
+
readonly coalesceSaves?: boolean;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* The document slot the model server and the integrity service talk to:
|
|
207
|
+
* open/close/update/save plus the AST-typed event streams, with the LSP
|
|
208
|
+
* plumbing hidden.
|
|
209
|
+
*
|
|
210
|
+
* Generic over `<TAst extends AstNode, TDiagnostic>` so each consumer projects
|
|
211
|
+
* its own AST root type and diagnostic shape into the emitted
|
|
212
|
+
* {@link AstDocument} envelopes.
|
|
213
|
+
*
|
|
214
|
+
* **URI contract.** Every URI-accepting member takes a URI in *any* spelling
|
|
215
|
+
* (canonical, symlinked, `..`/case-divergent) and canonicalizes internally
|
|
216
|
+
* through the {@link DocumentUriPolicy}, so a caller never has to canonicalize
|
|
217
|
+
* first and an implementation may not require it.
|
|
218
|
+
*/
|
|
219
|
+
export interface AstDocumentManager<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> {
|
|
220
|
+
open(args: OpenModelArgs): Promise<Disposable>;
|
|
221
|
+
close(args: CloseModelArgs): Promise<void>;
|
|
222
|
+
isOpen(uri: string): boolean;
|
|
223
|
+
|
|
224
|
+
/** Apply `text` as `clientId`'s edit. Resolves to the resulting text-document version. */
|
|
225
|
+
update(uri: string, text: string, clientId: string): Promise<number>;
|
|
226
|
+
/**
|
|
227
|
+
* Write the document's current text to disk through `FileSystemTaskQueue`.
|
|
228
|
+
* The text is taken when this is called, so saves of one file land in the
|
|
229
|
+
* order they were called.
|
|
230
|
+
*/
|
|
231
|
+
save(uri: string, clientId: string): Promise<void>;
|
|
232
|
+
|
|
233
|
+
onUpdate(uri: string, listener: (event: AstDocumentUpdatedEvent<TAst, TDiagnostic>) => void): Disposable;
|
|
234
|
+
onSave(uri: string, listener: (event: AstDocumentSavedEvent<TAst, TDiagnostic>) => void | Promise<void>): Disposable;
|
|
235
|
+
onClientClosed(uri: string, clientId: string, listener: () => void): Disposable;
|
|
236
|
+
|
|
237
|
+
getDocument(uri: string): LangiumDocument | undefined;
|
|
238
|
+
|
|
239
|
+
/** Client id that authored the document's current version, or `undefined` for a framework-internal build. */
|
|
240
|
+
getAuthor(document: LangiumDocument): string | undefined;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* The reason, source and cause of an update event for `document` emitted
|
|
244
|
+
* now, from a phase listener of the build that carries it. Every head takes
|
|
245
|
+
* its update events' attribution from here, so they name the same client
|
|
246
|
+
* for one build. For a document a client opened, while rebuilds validate,
|
|
247
|
+
* the answer changes once its `Validated` listeners have all run: a later
|
|
248
|
+
* event at that version is `'rebuilt'`. `TransferDocumentUpdateReason`
|
|
249
|
+
* names the cases that fall back to the last update.
|
|
250
|
+
*/
|
|
251
|
+
attributeUpdate(document: LangiumDocument): UpdateAttribution;
|
|
252
|
+
}
|
|
168
253
|
|
|
169
254
|
/**
|
|
170
255
|
* Higher-level facade over {@link HydraniumTextDocuments} that speaks the
|
|
@@ -186,13 +271,53 @@ export type AstDocumentManagerOptions = LogNameOptions;
|
|
|
186
271
|
* resolution (the egress `applyEditToLanguageClient`) stay on
|
|
187
272
|
* {@link HydraniumTextDocuments}, their owner.
|
|
188
273
|
*/
|
|
189
|
-
export class
|
|
274
|
+
export class DefaultAstDocumentManager<
|
|
275
|
+
TAst extends AstNode,
|
|
276
|
+
TDiagnostic extends AstDiagnostic = AstDiagnostic
|
|
277
|
+
> implements AstDocumentManager<TAst, TDiagnostic> {
|
|
278
|
+
/** The last `DocumentBuilder.update`'s URIs; the reason for a document the store does not track. */
|
|
190
279
|
protected lastUpdate?: UpdateInfo;
|
|
280
|
+
/**
|
|
281
|
+
* Canonical URIs a client has opened since the file was last deleted,
|
|
282
|
+
* whose versions the store keeps. One no client has opened keeps Langium's
|
|
283
|
+
* version `0` through every change of its content, so its version says
|
|
284
|
+
* nothing. Kept past the last close, since the store continues the version
|
|
285
|
+
* sequence on the next open; a delivery can land after that close.
|
|
286
|
+
*/
|
|
287
|
+
protected readonly trackedUris = new Set<CanonicalUri>();
|
|
288
|
+
/**
|
|
289
|
+
* Per tracked URI, the version whose `Validated` listeners last all ran,
|
|
290
|
+
* which is the version an update event was delivered for. Dropped on
|
|
291
|
+
* deletion, so a file created again with the same text is changed again.
|
|
292
|
+
*/
|
|
293
|
+
protected readonly deliveredVersions = new Map<CanonicalUri, number>();
|
|
294
|
+
/**
|
|
295
|
+
* Whose writes the build under way carries, set when it starts: the author
|
|
296
|
+
* of every open document's undelivered version, and the unknown-client id
|
|
297
|
+
* for a change no write explains, such as a deletion, a document no client
|
|
298
|
+
* has open, or a write that changed nothing. An undelivered version is one
|
|
299
|
+
* whose build has not validated it yet, so a write whose build was
|
|
300
|
+
* cancelled stays a cause of the build that takes over.
|
|
301
|
+
*
|
|
302
|
+
* Errs toward more than one cause, and so toward the unknown client, which
|
|
303
|
+
* a reader treats as foreign: an answer it repeats, never one it misses.
|
|
304
|
+
* A change no write explains counts for its own build only, so a build
|
|
305
|
+
* that takes over from a cancelled one loses it. One field for every build:
|
|
306
|
+
* a build started outside the workspace lock, such as a re-queue of an
|
|
307
|
+
* orphaned document, reads the causes of whichever build started last.
|
|
308
|
+
* An open document no build delivers, one a `shouldValidate` override
|
|
309
|
+
* skips, stays undelivered, so it is a cause of every build while open.
|
|
310
|
+
*/
|
|
311
|
+
protected readonly buildCauses = new Set<string>();
|
|
312
|
+
|
|
313
|
+
/** Per canonical URI, the newest save queued for it, which {@link coalesceSaves} lets older queued saves defer to. */
|
|
314
|
+
protected readonly newestSaves = new Map<CanonicalUri, Promise<void>>();
|
|
315
|
+
protected readonly coalesceSaves: boolean;
|
|
191
316
|
|
|
192
317
|
protected readonly textDocuments: HydraniumTextDocuments<TextDocument>;
|
|
193
318
|
protected readonly fileSystemProvider: WritableFileSystemProvider;
|
|
194
319
|
protected readonly langiumDocs: LangiumDocuments;
|
|
195
|
-
protected readonly documentBuilder:
|
|
320
|
+
protected readonly documentBuilder: HydraniumDocumentBuilder;
|
|
196
321
|
protected readonly uriPolicy: DocumentUriPolicy;
|
|
197
322
|
protected readonly tracer: Tracer;
|
|
198
323
|
|
|
@@ -206,13 +331,41 @@ export class AstDocumentManager<TAst extends AstNode = AstNode, TDiagnostic = un
|
|
|
206
331
|
this.documentBuilder = services.workspace.DocumentBuilder;
|
|
207
332
|
this.uriPolicy = services.workspace.DocumentUriPolicy;
|
|
208
333
|
this.tracer = services.Tracer.for(options.logName ?? 'AstDocumentManager').trace('instantiated');
|
|
209
|
-
this.
|
|
210
|
-
|
|
211
|
-
|
|
334
|
+
this.coalesceSaves = options.coalesceSaves ?? false;
|
|
335
|
+
this.textDocuments.onDidOpen(event => {
|
|
336
|
+
this.trackedUris.add(this.uriPolicy.canonicalUri(event.document.uri));
|
|
337
|
+
return this.open({ clientId: event.clientId, uri: event.document.uri, languageId: event.document.languageId });
|
|
338
|
+
});
|
|
212
339
|
this.textDocuments.onDidClose(event => this.close({ clientId: event.clientId, uri: event.document.uri }));
|
|
213
340
|
this.documentBuilder.onUpdate((changed, deleted) => {
|
|
214
341
|
this.lastUpdate = { changed, deleted };
|
|
342
|
+
this.buildCauses.clear();
|
|
343
|
+
for (const textDocument of this.textDocuments.all()) {
|
|
344
|
+
if (!this.isDelivered(textDocument.uri, textDocument.version)) {
|
|
345
|
+
this.buildCauses.add(this.textDocuments.getAuthor(textDocument.uri, textDocument.version) ?? UNKNOWN_CLIENT_ID);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const unexplained = changed.some(uri => {
|
|
349
|
+
const textDocument = this.textDocuments.get(uri.toString());
|
|
350
|
+
return textDocument === undefined || this.isDelivered(textDocument.uri, textDocument.version);
|
|
351
|
+
});
|
|
352
|
+
if (unexplained || deleted.length > 0) {
|
|
353
|
+
this.buildCauses.add(UNKNOWN_CLIENT_ID);
|
|
354
|
+
}
|
|
355
|
+
// The only place a deletion is observable: `DocumentBuilder.update`
|
|
356
|
+
// removes a deleted document before it builds anything, so no phase
|
|
357
|
+
// listener ever sees it.
|
|
358
|
+
for (const uri of deleted) {
|
|
359
|
+
const key = this.uriPolicy.canonicalUri(uri.toString());
|
|
360
|
+
this.trackedUris.delete(key);
|
|
361
|
+
this.deliveredVersions.delete(key);
|
|
362
|
+
this.textDocuments.notifyDocumentDeleted(uri.toString());
|
|
363
|
+
}
|
|
215
364
|
});
|
|
365
|
+
// Once every listener ran, not in a listener of its own: listeners after
|
|
366
|
+
// it could still be skipped by a cancel, and the next build would then
|
|
367
|
+
// report as rebuilt a version they never delivered.
|
|
368
|
+
this.documentBuilder.onDocumentPhaseDelivered(DocumentState.Validated, (document, version) => this.markDelivered(document, version));
|
|
216
369
|
// Content transitions for CLOSED documents bypass the text store: the
|
|
217
370
|
// last-close revert and watched-file changes rebuild from disk into a
|
|
218
371
|
// factory-fresh text document carrying the factory's own version. At the
|
|
@@ -304,20 +457,16 @@ export class AstDocumentManager<TAst extends AstNode = AstNode, TDiagnostic = un
|
|
|
304
457
|
if (this.uriPolicy.canonicalUri(document.uri) !== target) {
|
|
305
458
|
return;
|
|
306
459
|
}
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
|
|
460
|
+
// No `'deleted'` reason: `DocumentBuilder.update` drops a deleted
|
|
461
|
+
// document from `LangiumDocuments` before deriving the rebuild set
|
|
462
|
+
// from it, so a deleted URI is never built and never reaches this
|
|
463
|
+
// phase listener. A subscriber needing deletions has to be told on
|
|
464
|
+
// a channel that does not require a built document.
|
|
311
465
|
const event: TransferUpdatedEvent<AstDocument<TAst, TDiagnostic>> = {
|
|
312
466
|
document: this.toAstDocument(document),
|
|
313
|
-
|
|
314
|
-
reason: this.lastUpdate?.changed.find(changed => UriUtils.equals(changed, document.uri))
|
|
315
|
-
? 'changed'
|
|
316
|
-
: this.lastUpdate?.deleted.find(deleted => UriUtils.equals(deleted, document.uri))
|
|
317
|
-
? 'deleted'
|
|
318
|
-
: 'rebuilt'
|
|
467
|
+
...this.attributeUpdate(document)
|
|
319
468
|
};
|
|
320
|
-
this.tracer.with(uri).trace(`emitUpdate start: source=${sourceClientId}, reason=${event.reason}`);
|
|
469
|
+
this.tracer.with(uri).trace(`emitUpdate start: source=${event.sourceClientId}, reason=${event.reason}, cause=${event.causedBy}`);
|
|
321
470
|
listener(event);
|
|
322
471
|
this.tracer.with(uri).trace('emitUpdate listener returned');
|
|
323
472
|
};
|
|
@@ -326,23 +475,86 @@ export class AstDocumentManager<TAst extends AstNode = AstNode, TDiagnostic = un
|
|
|
326
475
|
|
|
327
476
|
/**
|
|
328
477
|
* The client that authored `document`'s current version, or `undefined` when
|
|
329
|
-
* no client wrote it
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
* `resolveSourceClientId`).
|
|
478
|
+
* no client wrote it: a document no client has open. A rebuild that keeps
|
|
479
|
+
* the version keeps its author, so this does not say who caused a build;
|
|
480
|
+
* {@link attributeUpdate} does.
|
|
481
|
+
* Honest about absence so a routing consumer tests `undefined` directly
|
|
482
|
+
* rather than against a sentinel; the presentation default
|
|
483
|
+
* ({@link UNKNOWN_CLIENT_ID}) is applied where an event needs a value.
|
|
336
484
|
*/
|
|
337
|
-
getAuthor(document: LangiumDocument
|
|
485
|
+
getAuthor(document: LangiumDocument): string | undefined {
|
|
338
486
|
return this.textDocuments.getAuthor(document.textDocument.uri, document.textDocument.version);
|
|
339
487
|
}
|
|
340
488
|
|
|
489
|
+
/**
|
|
490
|
+
* `'changed'` for the first delivery of the document's version, crediting
|
|
491
|
+
* its author; `'rebuilt'` for a later one, crediting nobody, since it echoes
|
|
492
|
+
* no write, and naming the build's single cause if it has one.
|
|
493
|
+
*
|
|
494
|
+
* A document the rule does not apply to (see {@link isTracked}) falls back
|
|
495
|
+
* to the last update: it is `'changed'` when its URI was passed to
|
|
496
|
+
* `DocumentBuilder.update`. An open document that a validating build skips,
|
|
497
|
+
* through a `shouldValidate` override, is never delivered, so each of its
|
|
498
|
+
* events is its author's change.
|
|
499
|
+
*/
|
|
500
|
+
attributeUpdate(document: LangiumDocument): UpdateAttribution {
|
|
501
|
+
const key = this.uriPolicy.canonicalUri(document.uri.toString());
|
|
502
|
+
const changed = this.isTracked(key)
|
|
503
|
+
? this.deliveredVersions.get(key) !== document.textDocument.version
|
|
504
|
+
: this.lastUpdate?.changed.some(uri => UriUtils.equals(uri, document.uri)) === true;
|
|
505
|
+
if (changed) {
|
|
506
|
+
// Presentation boundary: the event field is a concrete `string`, so an
|
|
507
|
+
// unauthored document surfaces the readable default rather than
|
|
508
|
+
// `undefined` to subscribers and logs.
|
|
509
|
+
const author = this.getAuthor(document) ?? UNKNOWN_CLIENT_ID;
|
|
510
|
+
return { reason: 'changed', sourceClientId: author, causedBy: author };
|
|
511
|
+
}
|
|
512
|
+
const [cause] = this.buildCauses;
|
|
513
|
+
return { reason: 'rebuilt', sourceClientId: UNKNOWN_CLIENT_ID, causedBy: this.buildCauses.size === 1 ? cause : UNKNOWN_CLIENT_ID };
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Whether the version rule applies to `uri`: the store keeps its version,
|
|
518
|
+
* and rebuilds validate. With `updateBuildOptions.validation` off no version
|
|
519
|
+
* is ever delivered, and the rule would report every event of an open
|
|
520
|
+
* document as its author's change.
|
|
521
|
+
*/
|
|
522
|
+
protected isTracked(uri: CanonicalUri): boolean {
|
|
523
|
+
return this.keepsVersion(uri) && Boolean(this.documentBuilder.updateBuildOptions.validation);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Whether the store keeps `uri`'s version: a client opened it since its
|
|
528
|
+
* file was last deleted, or has it open still, as an editor keeps a
|
|
529
|
+
* deleted file's buffer.
|
|
530
|
+
*/
|
|
531
|
+
protected keepsVersion(uri: CanonicalUri): boolean {
|
|
532
|
+
return this.trackedUris.has(uri) || this.textDocuments.isOpen(uri);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Record that `version` of `document` was delivered, when the store tracks
|
|
537
|
+
* it. The version the listeners saw, not the document's current one: a
|
|
538
|
+
* write during them has moved that on, and marking it would report the
|
|
539
|
+
* write's own build as rebuilt.
|
|
540
|
+
*/
|
|
541
|
+
protected markDelivered(document: LangiumDocument, version: number): void {
|
|
542
|
+
const key = this.uriPolicy.canonicalUri(document.uri.toString());
|
|
543
|
+
if (this.keepsVersion(key)) {
|
|
544
|
+
this.deliveredVersions.set(key, version);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/** Whether `version` of `uri` was delivered. */
|
|
549
|
+
protected isDelivered(uri: string, version: number): boolean {
|
|
550
|
+
return this.deliveredVersions.get(this.uriPolicy.canonicalUri(uri)) === version;
|
|
551
|
+
}
|
|
552
|
+
|
|
341
553
|
async open(args: OpenModelArgs): Promise<Disposable> {
|
|
342
554
|
// `open()` is the RPC-level "ensure this document is loaded" call. It is issued
|
|
343
|
-
// by a
|
|
344
|
-
//
|
|
345
|
-
//
|
|
555
|
+
// by a session opening the document, including by every additional client
|
|
556
|
+
// attaching to the same URI and the several sub-editors a composite view
|
|
557
|
+
// opens. When the document is already loaded there is nothing to
|
|
346
558
|
// do here but hand back the close-disposable — callers that want the current
|
|
347
559
|
// state read it from this method's surrounding RPC response, not from a re-build.
|
|
348
560
|
//
|
|
@@ -355,10 +567,28 @@ export class AstDocumentManager<TAst extends AstNode = AstNode, TDiagnostic = un
|
|
|
355
567
|
// transiently breaks cross-document linking mid-rebuild (a dependent briefly
|
|
356
568
|
// seeing an `extends`/`type` reference unresolved). And because the constructor
|
|
357
569
|
// wires `onDidOpen -> this.open`, it would fire a second, identical rebuild on
|
|
358
|
-
// every first open.
|
|
570
|
+
// every first open.
|
|
571
|
+
//
|
|
572
|
+
// So an already-open `open()` records the attaching client's open and nothing
|
|
573
|
+
// else. The open is per `(uri, clientId)` and the last-close revert counts down
|
|
574
|
+
// to it, so skipping it lets the first client's close tear down a document
|
|
575
|
+
// another client is still reading. A document waiting out the revert grace
|
|
576
|
+
// is still loaded: a client lost from it within its own grace attaches and
|
|
577
|
+
// keeps its text, and for any other client the attach releases it, so the
|
|
578
|
+
// open reads the file.
|
|
579
|
+
if (this.isOpen(args.uri)) {
|
|
580
|
+
this.textDocuments.attachClient(args.uri, args.clientId);
|
|
581
|
+
}
|
|
359
582
|
if (!this.isOpen(args.uri)) {
|
|
360
583
|
const textDocument = await this.createDocumentFromTextOrFileSystem(args.uri, args.languageId, args.version, args.text);
|
|
584
|
+
const creates = !this.isOpen(args.uri);
|
|
361
585
|
this.textDocuments.notifyDidOpenTextDocument({ textDocument }, args.clientId);
|
|
586
|
+
if (creates && args.text !== undefined) {
|
|
587
|
+
// Text the caller supplies was not read from the file, so no file
|
|
588
|
+
// is assumed: the document is dirty until its first save, whatever
|
|
589
|
+
// the file holds.
|
|
590
|
+
this.textDocuments.updateDiskBaseline(args.uri, undefined);
|
|
591
|
+
}
|
|
362
592
|
}
|
|
363
593
|
return Disposable.create(() => this.close(args));
|
|
364
594
|
}
|
|
@@ -393,31 +623,80 @@ export class AstDocumentManager<TAst extends AstNode = AstNode, TDiagnostic = un
|
|
|
393
623
|
* callers don't need to pass it — the manager owns content and version
|
|
394
624
|
* sequencing.
|
|
395
625
|
*
|
|
626
|
+
* The text is taken synchronously, before the save waits in the file's task
|
|
627
|
+
* queue; the compare and the write run in the queue. Taken later, a save
|
|
628
|
+
* that waits behind another writes whatever the store holds when its turn
|
|
629
|
+
* comes, edits made after the call included, and announces that text under
|
|
630
|
+
* its own client id.
|
|
631
|
+
*
|
|
632
|
+
* **The write is skipped when the file already holds that text; the
|
|
633
|
+
* notification is not.** A save announces that the content is on disk, which
|
|
634
|
+
* is true either way — so a subscriber clearing a dirty marker or reacting to
|
|
635
|
+
* a persist behaves the same, while an mtime is not moved for byte-identical
|
|
636
|
+
* content that a downstream mtime-keyed build would then read as new work.
|
|
637
|
+
*
|
|
396
638
|
* Throws if no document is open for `uri`.
|
|
397
639
|
*/
|
|
398
640
|
async save(uri: string, clientId: string): Promise<void> {
|
|
399
|
-
|
|
641
|
+
// Canonical throughout: the write and the read that gates it must address
|
|
642
|
+
// the same file the store was keyed by, or a divergent spelling compares
|
|
643
|
+
// one file and writes another.
|
|
644
|
+
const canonical = this.uriPolicy.canonicalUri(uri);
|
|
645
|
+
const document = this.textDocuments.get(canonical);
|
|
400
646
|
if (!document) {
|
|
401
647
|
throw new Error(`Document ${uri} hasn't been opened for saving yet`);
|
|
402
648
|
}
|
|
403
649
|
const text = document.getText();
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
(
|
|
408
|
-
|
|
409
|
-
|
|
650
|
+
let supersededBy: Promise<void> | undefined;
|
|
651
|
+
const saved: Promise<void> = this.services.workspace.FileSystemTaskQueue.enqueue(canonical, async () => {
|
|
652
|
+
const newest = this.newestSaves.get(canonical);
|
|
653
|
+
if (this.coalesceSaves && newest !== saved) {
|
|
654
|
+
supersededBy = newest;
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
await this.writeSave(canonical, text, clientId);
|
|
658
|
+
})
|
|
659
|
+
.then(() => supersededBy)
|
|
660
|
+
.finally(() => {
|
|
661
|
+
if (this.newestSaves.get(canonical) === saved) {
|
|
662
|
+
this.newestSaves.delete(canonical);
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
this.newestSaves.set(canonical, saved);
|
|
666
|
+
return saved;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/** Write `text` to `uri` unless the file already holds it, then announce the save. Runs inside the file's task queue. */
|
|
670
|
+
protected async writeSave(uri: CanonicalUri, text: string, clientId: string): Promise<void> {
|
|
671
|
+
if (!(await this.matchesDisk(uri, text))) {
|
|
672
|
+
await this.tracer.with(uri).time(
|
|
673
|
+
`Write file (${text.length} bytes, from ${clientId})`,
|
|
674
|
+
// Async write so a slow disk does not block the event loop for the duration of the fs call.
|
|
675
|
+
() => this.fileSystemProvider.writeFile(UriUtils.toUri(uri), text),
|
|
676
|
+
'debug'
|
|
677
|
+
);
|
|
678
|
+
}
|
|
410
679
|
this.textDocuments.notifyDidSaveTextDocument({ textDocument: TextDocumentIdentifier.create(uri), text }, clientId);
|
|
411
680
|
}
|
|
412
681
|
|
|
413
|
-
|
|
414
|
-
|
|
682
|
+
/**
|
|
683
|
+
* Whether the file at `uri` already holds `text`.
|
|
684
|
+
*
|
|
685
|
+
* Compared by CONTENT rather than against a remembered version, so a write
|
|
686
|
+
* from outside this server is still corrected: a version this manager already
|
|
687
|
+
* saved says nothing about what is on disk now. `false` when the file cannot
|
|
688
|
+
* be read at all, which is the answer that writes — a document whose file does
|
|
689
|
+
* not exist yet is exactly the one a first save has to create.
|
|
690
|
+
*/
|
|
691
|
+
protected async matchesDisk(uri: string, text: string): Promise<boolean> {
|
|
692
|
+
return this.fileSystemProvider
|
|
693
|
+
.readFile(UriUtils.toUri(uri))
|
|
694
|
+
.then(onDisk => onDisk === text)
|
|
695
|
+
.catch(() => false);
|
|
415
696
|
}
|
|
416
697
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const canonical = this.uriPolicy.canonicalUri(uri);
|
|
420
|
-
return this.lastUpdate?.changed.some(changed => this.uriPolicy.canonicalUri(changed) === canonical) ?? false;
|
|
698
|
+
isOpen(uri: string): boolean {
|
|
699
|
+
return !!this.textDocuments.get(uri);
|
|
421
700
|
}
|
|
422
701
|
|
|
423
702
|
/**
|
|
@@ -437,11 +716,16 @@ export class AstDocumentManager<TAst extends AstNode = AstNode, TDiagnostic = un
|
|
|
437
716
|
version = 0,
|
|
438
717
|
text?: string
|
|
439
718
|
): Promise<TextDocumentItem> {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
719
|
+
// Read in the file's task queue: a read beside a queued save of the file
|
|
720
|
+
// returns the text from before it, and the document then opens on that.
|
|
721
|
+
return {
|
|
722
|
+
uri,
|
|
723
|
+
languageId,
|
|
724
|
+
version,
|
|
725
|
+
text:
|
|
726
|
+
text ??
|
|
727
|
+
(await this.services.workspace.FileSystemTaskQueue.enqueue(uri, () => this.fileSystemProvider.readFile(UriUtils.toUri(uri))))
|
|
728
|
+
};
|
|
445
729
|
}
|
|
446
730
|
|
|
447
731
|
/**
|
|
@@ -8,26 +8,9 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* client, and/or a structured-form client. Each kind carries a stable id so
|
|
16
|
-
* the server can route outbound corrections, edits, and notifications to the
|
|
17
|
-
* right transport.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/** Identifier for an LSP-text client (Monaco, VS Code, …). */
|
|
21
|
-
export const LANGUAGE_CLIENT_ID = 'language-client';
|
|
22
|
-
|
|
23
|
-
/** Fallback identifier when a document's author is unknown (e.g. cold workspace-init load). */
|
|
24
|
-
export const UNKNOWN_CLIENT_ID = 'unknown';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Synthetic author id on the `onDocumentUpdated` broadcast a data-server
|
|
28
|
-
* emits after the LAST client closed a document and the framework rebuilt it
|
|
29
|
-
* from its disk content (discarding unsaved in-session edits). Not a real
|
|
30
|
-
* client: it lets consumers distinguish the revert broadcast from
|
|
31
|
-
* client-authored updates.
|
|
11
|
+
* Re-export, because these are WIRE values and the side that has to recognise
|
|
12
|
+
* them is the client. They are defined in `@hydranium/protocol` so a frontend
|
|
13
|
+
* can name them without depending on the server tier; this path stays so
|
|
14
|
+
* server-side code keeps importing them from where it already does.
|
|
32
15
|
*/
|
|
33
|
-
export
|
|
16
|
+
export { FRAMEWORK_CLIENT_IDS, LANGUAGE_CLIENT_ID, REVERT_ON_CLOSE_CLIENT_ID, UNKNOWN_CLIENT_ID } from '@hydranium/protocol';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Re-export, because these errors cross the wire and the side that has to
|
|
12
|
+
* recognise them is the client. They are defined in `@hydranium/protocol` so a
|
|
13
|
+
* frontend can name them without depending on the server tier.
|
|
14
|
+
*/
|
|
15
|
+
export {
|
|
16
|
+
DocumentNotOpenError,
|
|
17
|
+
DuplicateClientIdError,
|
|
18
|
+
ReservedClientIdError,
|
|
19
|
+
SessionClosedError,
|
|
20
|
+
isDocumentNotOpenError,
|
|
21
|
+
isDuplicateClientIdError,
|
|
22
|
+
isReservedClientIdError,
|
|
23
|
+
isSessionClosedError
|
|
24
|
+
} from '@hydranium/protocol';
|