@hydranium/core 1.0.0-next.39 → 1.0.0-next.390
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 +78 -82
- package/lib/browser/host-heads-in-worker.d.ts +77 -0
- package/lib/browser/host-heads-in-worker.d.ts.map +1 -0
- package/lib/browser/host-heads-in-worker.js +169 -0
- package/lib/browser/host-heads-in-worker.js.map +1 -0
- package/lib/browser/index.d.ts +12 -0
- package/lib/browser/index.d.ts.map +1 -0
- package/lib/browser/index.js +17 -0
- package/lib/browser/index.js.map +1 -0
- package/lib/browser/indexeddb-file-system-store.d.ts +82 -0
- package/lib/browser/indexeddb-file-system-store.d.ts.map +1 -0
- package/lib/browser/indexeddb-file-system-store.js +181 -0
- package/lib/browser/indexeddb-file-system-store.js.map +1 -0
- package/lib/browser/start-language-server-in-worker.d.ts +32 -0
- package/lib/browser/start-language-server-in-worker.d.ts.map +1 -0
- package/lib/browser/start-language-server-in-worker.js +40 -0
- package/lib/browser/start-language-server-in-worker.js.map +1 -0
- package/lib/documents/ast-document-manager.d.ts +254 -140
- package/lib/documents/ast-document-manager.d.ts.map +1 -1
- package/lib/documents/ast-document-manager.js +311 -128
- package/lib/documents/ast-document-manager.js.map +1 -1
- package/lib/documents/client-ids.d.ts +5 -19
- package/lib/documents/client-ids.d.ts.map +1 -1
- package/lib/documents/client-ids.js +5 -19
- package/lib/documents/client-ids.js.map +1 -1
- package/lib/documents/client-session-errors.d.ts +15 -0
- package/lib/documents/client-session-errors.d.ts.map +1 -0
- package/lib/documents/client-session-errors.js +15 -0
- package/lib/documents/client-session-errors.js.map +1 -0
- package/lib/documents/client-session-registry.d.ts +146 -0
- package/lib/documents/client-session-registry.d.ts.map +1 -0
- package/lib/documents/client-session-registry.js +207 -0
- package/lib/documents/client-session-registry.js.map +1 -0
- package/lib/documents/dirty-state-tracker.d.ts +101 -0
- package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
- package/lib/documents/dirty-state-tracker.js +85 -0
- package/lib/documents/dirty-state-tracker.js.map +1 -0
- package/lib/documents/document-release-handler.d.ts +204 -0
- package/lib/documents/document-release-handler.d.ts.map +1 -0
- package/lib/documents/document-release-handler.js +317 -0
- package/lib/documents/document-release-handler.js.map +1 -0
- package/lib/documents/document-release-scheduler.d.ts +67 -0
- package/lib/documents/document-release-scheduler.d.ts.map +1 -0
- package/lib/documents/document-release-scheduler.js +80 -0
- package/lib/documents/document-release-scheduler.js.map +1 -0
- package/lib/documents/file-system-task-queue.d.ts +52 -0
- package/lib/documents/file-system-task-queue.d.ts.map +1 -0
- package/lib/documents/file-system-task-queue.js +40 -0
- package/lib/documents/file-system-task-queue.js.map +1 -0
- package/lib/documents/hydranium-text-documents.d.ts +453 -282
- package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
- package/lib/documents/hydranium-text-documents.js +918 -504
- package/lib/documents/hydranium-text-documents.js.map +1 -1
- package/lib/documents/index.d.ts +10 -2
- package/lib/documents/index.d.ts.map +1 -1
- package/lib/documents/index.js +10 -2
- package/lib/documents/index.js.map +1 -1
- package/lib/documents/language-client-shadow.d.ts +234 -0
- package/lib/documents/language-client-shadow.d.ts.map +1 -0
- package/lib/documents/language-client-shadow.js +306 -0
- package/lib/documents/language-client-shadow.js.map +1 -0
- package/lib/documents/model-ledger.d.ts +47 -0
- package/lib/documents/model-ledger.d.ts.map +1 -0
- package/lib/documents/model-ledger.js +30 -0
- package/lib/documents/model-ledger.js.map +1 -0
- package/lib/documents/text-ledger.d.ts +64 -0
- package/lib/documents/text-ledger.d.ts.map +1 -0
- package/lib/documents/text-ledger.js +63 -0
- package/lib/documents/text-ledger.js.map +1 -0
- package/lib/documents/version-sync-service.d.ts +153 -0
- package/lib/documents/version-sync-service.d.ts.map +1 -0
- package/lib/documents/version-sync-service.js +186 -0
- package/lib/documents/version-sync-service.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/langium/ast-extension/ast-extension-service.d.ts +42 -31
- package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
- package/lib/langium/ast-extension/ast-extension-service.js +45 -19
- package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
- package/lib/langium/ast-extension/ast-node-builder.d.ts +12 -7
- package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
- package/lib/langium/ast-extension/ast-node-builder.js +25 -9
- package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
- package/lib/langium/bootstrap.d.ts +49 -36
- package/lib/langium/bootstrap.d.ts.map +1 -1
- package/lib/langium/bootstrap.js +75 -36
- package/lib/langium/bootstrap.js.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts +9 -9
- package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass-service.js +25 -16
- package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass.d.ts +20 -8
- package/lib/langium/build-phase-pass/build-phase-pass.d.ts.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass.js +20 -0
- package/lib/langium/build-phase-pass/build-phase-pass.js.map +1 -1
- package/lib/langium/composite-ast-reflection.d.ts +46 -0
- package/lib/langium/composite-ast-reflection.d.ts.map +1 -0
- package/lib/langium/composite-ast-reflection.js +97 -0
- package/lib/langium/composite-ast-reflection.js.map +1 -0
- package/lib/langium/config/configuration-provider.d.ts +81 -0
- package/lib/langium/config/configuration-provider.d.ts.map +1 -0
- package/lib/langium/config/configuration-provider.js +112 -0
- package/lib/langium/config/configuration-provider.js.map +1 -0
- package/lib/langium/config/index.d.ts +1 -0
- package/lib/langium/config/index.d.ts.map +1 -1
- package/lib/langium/config/index.js +1 -0
- package/lib/langium/config/index.js.map +1 -1
- package/lib/langium/config/settings.js.map +1 -1
- package/lib/langium/diagnostics/console-tee.d.ts +27 -0
- package/lib/langium/diagnostics/console-tee.d.ts.map +1 -0
- package/lib/langium/diagnostics/console-tee.js +141 -0
- package/lib/langium/diagnostics/console-tee.js.map +1 -0
- package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts +9 -20
- package/lib/langium/diagnostics/hydranium-langium-profiler.d.ts.map +1 -1
- package/lib/langium/diagnostics/hydranium-langium-profiler.js +15 -24
- package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
- package/lib/langium/diagnostics/log-preamble.js +1 -1
- package/lib/langium/diagnostics/log-preamble.js.map +1 -1
- package/lib/langium/diagnostics/logger.d.ts +25 -6
- package/lib/langium/diagnostics/logger.d.ts.map +1 -1
- package/lib/langium/diagnostics/logger.js +49 -17
- package/lib/langium/diagnostics/logger.js.map +1 -1
- package/lib/langium/diagnostics/lsp-logger.d.ts +25 -0
- package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
- package/lib/langium/diagnostics/lsp-logger.js +81 -46
- package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
- package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
- package/lib/langium/diagnostics/server-tracer.js.map +1 -1
- package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
- package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
- package/lib/langium/document-builder/build-pipeline-integration.js +43 -30
- package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
- package/lib/langium/document-builder/build-session.d.ts +6 -5
- package/lib/langium/document-builder/build-session.d.ts.map +1 -1
- package/lib/langium/document-builder/build-session.js +5 -5
- package/lib/langium/document-builder/build-session.js.map +1 -1
- package/lib/langium/document-builder/document-builder.d.ts +390 -40
- package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
- package/lib/langium/document-builder/document-builder.js +635 -102
- package/lib/langium/document-builder/document-builder.js.map +1 -1
- package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
- package/lib/langium/documentation/comment-provider.js.map +1 -1
- package/lib/langium/integration-services.d.ts +20 -23
- package/lib/langium/integration-services.d.ts.map +1 -1
- package/lib/langium/integration-services.js.map +1 -1
- package/lib/langium/integrity/integrity-rule.d.ts +22 -8
- package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-rule.js.map +1 -1
- package/lib/langium/integrity/integrity-service.d.ts +217 -29
- package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-service.js +588 -84
- package/lib/langium/integrity/integrity-service.js.map +1 -1
- package/lib/langium/keys/containment.d.ts +3 -2
- package/lib/langium/keys/containment.d.ts.map +1 -1
- package/lib/langium/keys/containment.js.map +1 -1
- package/lib/langium/keys/name-based-key-provider.d.ts +17 -10
- package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/name-based-key-provider.js +24 -12
- package/lib/langium/keys/name-based-key-provider.js.map +1 -1
- package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/positional-key-provider.js.map +1 -1
- package/lib/langium/labeling/label-provider.d.ts.map +1 -1
- package/lib/langium/labeling/label-provider.js.map +1 -1
- package/lib/langium/language-module.d.ts +30 -5
- package/lib/langium/language-module.d.ts.map +1 -1
- package/lib/langium/language-module.js +21 -5
- package/lib/langium/language-module.js.map +1 -1
- package/lib/langium/model-service/client-session.d.ts +405 -0
- package/lib/langium/model-service/client-session.d.ts.map +1 -0
- package/lib/langium/model-service/client-session.js +479 -0
- package/lib/langium/model-service/client-session.js.map +1 -0
- package/lib/langium/model-service/index.d.ts +2 -0
- package/lib/langium/model-service/index.d.ts.map +1 -1
- package/lib/langium/model-service/index.js +2 -0
- package/lib/langium/model-service/index.js.map +1 -1
- package/lib/langium/model-service/model-events.d.ts +68 -0
- package/lib/langium/model-service/model-events.d.ts.map +1 -0
- package/lib/langium/model-service/model-events.js +10 -0
- package/lib/langium/model-service/model-events.js.map +1 -0
- package/lib/langium/model-service/model-service.d.ts +441 -323
- package/lib/langium/model-service/model-service.d.ts.map +1 -1
- package/lib/langium/model-service/model-service.js +602 -407
- package/lib/langium/model-service/model-service.js.map +1 -1
- package/lib/langium/module.d.ts +96 -37
- package/lib/langium/module.d.ts.map +1 -1
- package/lib/langium/module.js +41 -29
- package/lib/langium/module.js.map +1 -1
- package/lib/langium/naming/name-provider.d.ts +32 -7
- package/lib/langium/naming/name-provider.d.ts.map +1 -1
- package/lib/langium/naming/name-provider.js +10 -4
- package/lib/langium/naming/name-provider.js.map +1 -1
- package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
- package/lib/langium/project/abstract-project-manager.d.ts +184 -13
- package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
- package/lib/langium/project/abstract-project-manager.js +336 -16
- package/lib/langium/project/abstract-project-manager.js.map +1 -1
- package/lib/langium/project/project-change-event.d.ts +22 -3
- package/lib/langium/project/project-change-event.d.ts.map +1 -1
- package/lib/langium/project/project-manager.d.ts +28 -2
- package/lib/langium/project/project-manager.d.ts.map +1 -1
- package/lib/langium/project/single-project-manager.d.ts +7 -1
- package/lib/langium/project/single-project-manager.d.ts.map +1 -1
- package/lib/langium/project/single-project-manager.js +12 -0
- package/lib/langium/project/single-project-manager.js.map +1 -1
- package/lib/langium/residency/cst-residency-service.d.ts +92 -52
- package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
- package/lib/langium/residency/cst-residency-service.js +154 -58
- package/lib/langium/residency/cst-residency-service.js.map +1 -1
- package/lib/langium/scope/ast-node-description-provider.d.ts +46 -10
- package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
- package/lib/langium/scope/ast-node-description-provider.js +88 -15
- package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
- package/lib/langium/scope/built-local-symbols.d.ts +12 -0
- package/lib/langium/scope/built-local-symbols.d.ts.map +1 -0
- package/lib/langium/scope/built-local-symbols.js +11 -0
- package/lib/langium/scope/built-local-symbols.js.map +1 -0
- package/lib/langium/scope/fallback-scope.d.ts +27 -0
- package/lib/langium/scope/fallback-scope.d.ts.map +1 -0
- package/lib/langium/scope/fallback-scope.js +35 -0
- package/lib/langium/scope/fallback-scope.js.map +1 -0
- package/lib/langium/scope/hydranium-scope-computation.d.ts +21 -18
- package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
- package/lib/langium/scope/hydranium-scope-computation.js +38 -39
- package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
- package/lib/langium/scope/hydranium-scope-provider.d.ts +122 -32
- package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
- package/lib/langium/scope/hydranium-scope-provider.js +217 -39
- package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
- package/lib/langium/scope/index.d.ts +1 -0
- package/lib/langium/scope/index.d.ts.map +1 -1
- package/lib/langium/scope/index.js +1 -0
- package/lib/langium/scope/index.js.map +1 -1
- package/lib/langium/scope/reference-builder.d.ts.map +1 -1
- package/lib/langium/scope/reference-builder.js.map +1 -1
- package/lib/langium/scope/reference-candidate-provider.d.ts +6 -5
- package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
- package/lib/langium/scope/reference-candidate-provider.js +3 -2
- package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
- package/lib/langium/scope/scope-extension-service.d.ts +69 -37
- package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
- package/lib/langium/scope/scope-extension-service.js +102 -29
- package/lib/langium/scope/scope-extension-service.js.map +1 -1
- package/lib/langium/scope/scoped-ast-node-description.d.ts +1 -3
- package/lib/langium/scope/scoped-ast-node-description.d.ts.map +1 -1
- package/lib/langium/scope/scoped-ast-node-description.js +1 -3
- package/lib/langium/scope/scoped-ast-node-description.js.map +1 -1
- package/lib/langium/serialization/abstract-serializer.d.ts +38 -27
- package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/abstract-serializer.js +54 -30
- package/lib/langium/serialization/abstract-serializer.js.map +1 -1
- package/lib/langium/serialization/json-serializer.d.ts +8 -1
- package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/json-serializer.js +13 -3
- package/lib/langium/serialization/json-serializer.js.map +1 -1
- package/lib/langium/serialization/serializer.d.ts +1 -1
- package/lib/langium/serialization/yaml-serializer.d.ts +12 -0
- package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/yaml-serializer.js +24 -4
- package/lib/langium/serialization/yaml-serializer.js.map +1 -1
- package/lib/langium/service-registry.d.ts +29 -1
- package/lib/langium/service-registry.d.ts.map +1 -1
- package/lib/langium/service-registry.js +37 -0
- package/lib/langium/service-registry.js.map +1 -1
- package/lib/langium/shared-services.d.ts +10 -4
- package/lib/langium/shared-services.d.ts.map +1 -1
- package/lib/langium/shared-services.js.map +1 -1
- package/lib/langium/single-langium-copy.d.ts +22 -0
- package/lib/langium/single-langium-copy.d.ts.map +1 -0
- package/lib/langium/single-langium-copy.js +36 -0
- package/lib/langium/single-langium-copy.js.map +1 -0
- package/lib/langium/transfer/transfer-encoder.d.ts +60 -39
- package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
- package/lib/langium/transfer/transfer-encoder.js +35 -24
- package/lib/langium/transfer/transfer-encoder.js.map +1 -1
- package/lib/langium/trivia/comment-preserver.d.ts +543 -0
- package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/comment-preserver.js +1165 -0
- package/lib/langium/trivia/comment-preserver.js.map +1 -0
- package/lib/langium/trivia/document-ending-preserver.d.ts +51 -0
- package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/document-ending-preserver.js +62 -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 +52 -0
- package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-preserver.js +10 -0
- package/lib/langium/trivia/trivia-preserver.js.map +1 -0
- package/lib/langium/trivia/trivia-service.d.ts +70 -0
- package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-service.js +56 -0
- package/lib/langium/trivia/trivia-service.js.map +1 -0
- package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.d.ts +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
- package/lib/langium/validation/document-validator.d.ts +168 -23
- package/lib/langium/validation/document-validator.d.ts.map +1 -1
- package/lib/langium/validation/document-validator.js +264 -26
- package/lib/langium/validation/document-validator.js.map +1 -1
- package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
- package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
- package/lib/langium/validation/validation-contribution-collector.js +1 -1
- package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
- package/lib/langium/workspace/ast-node-locator.d.ts +24 -0
- package/lib/langium/workspace/ast-node-locator.d.ts.map +1 -0
- package/lib/langium/workspace/ast-node-locator.js +32 -0
- package/lib/langium/workspace/ast-node-locator.js.map +1 -0
- package/lib/langium/workspace/document-uri-policy.d.ts +24 -15
- package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
- package/lib/langium/workspace/document-uri-policy.js +22 -13
- package/lib/langium/workspace/document-uri-policy.js.map +1 -1
- package/lib/langium/workspace/file-not-found.d.ts +23 -0
- package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
- package/lib/langium/workspace/file-not-found.js +31 -0
- package/lib/langium/workspace/file-not-found.js.map +1 -0
- package/lib/langium/workspace/file-system-provider.d.ts +167 -8
- package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/file-system-provider.js +115 -13
- package/lib/langium/workspace/file-system-provider.js.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +78 -4
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.js +188 -5
- package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts +50 -1
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js +73 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts +105 -21
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.js +186 -31
- package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -9
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.js +45 -22
- package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
- package/lib/langium/workspace/index-manager.d.ts.map +1 -1
- package/lib/langium/workspace/index-manager.js.map +1 -1
- package/lib/langium/workspace/index.d.ts +3 -0
- package/lib/langium/workspace/index.d.ts.map +1 -1
- package/lib/langium/workspace/index.js +3 -0
- package/lib/langium/workspace/index.js.map +1 -1
- package/lib/langium/workspace/initialize-workspace.d.ts +40 -3
- package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
- package/lib/langium/workspace/initialize-workspace.js +68 -3
- package/lib/langium/workspace/initialize-workspace.js.map +1 -1
- package/lib/langium/workspace/langium-documents.d.ts +7 -0
- package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
- package/lib/langium/workspace/langium-documents.js +18 -1
- package/lib/langium/workspace/langium-documents.js.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.d.ts +16 -10
- package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.js +25 -13
- package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
- package/lib/{documents → langium/workspace}/self-save-registry.d.ts +7 -9
- package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
- package/lib/{documents → langium/workspace}/self-save-registry.js +9 -11
- package/lib/langium/workspace/self-save-registry.js.map +1 -0
- package/lib/langium/workspace/syntax-errors.d.ts +23 -0
- package/lib/langium/workspace/syntax-errors.d.ts.map +1 -0
- package/lib/langium/workspace/syntax-errors.js +29 -0
- package/lib/langium/workspace/syntax-errors.js.map +1 -0
- package/lib/langium/workspace/virtual-document.d.ts +55 -21
- package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
- package/lib/langium/workspace/virtual-document.js +87 -24
- package/lib/langium/workspace/virtual-document.js.map +1 -1
- package/lib/langium/workspace/write-lock-scope.d.ts +22 -10
- package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
- package/lib/langium/workspace/write-lock-scope.js +15 -5
- package/lib/langium/workspace/write-lock-scope.js.map +1 -1
- package/lib/launcher/integrated-server.d.ts +3 -1
- package/lib/launcher/integrated-server.d.ts.map +1 -1
- package/lib/locale/server-locale.d.ts +6 -6
- package/lib/locale/server-locale.d.ts.map +1 -1
- package/lib/locale/server-locale.js.map +1 -1
- 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/edit-requests-guard.d.ts +31 -0
- package/lib/lsp/edit-requests-guard.d.ts.map +1 -0
- package/lib/lsp/edit-requests-guard.js +125 -0
- package/lib/lsp/edit-requests-guard.js.map +1 -0
- package/lib/lsp/hydranium-document-update-handler.d.ts +126 -82
- package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.js +234 -101
- package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
- package/lib/lsp/index.d.ts +6 -2
- package/lib/lsp/index.d.ts.map +1 -1
- package/lib/lsp/index.js +6 -2
- 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/save-text-document.d.ts +31 -0
- package/lib/lsp/save-text-document.d.ts.map +1 -0
- package/lib/lsp/save-text-document.js +52 -0
- package/lib/lsp/save-text-document.js.map +1 -0
- package/lib/lsp/semantic-token-provider.d.ts +58 -2
- package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
- package/lib/lsp/semantic-token-provider.js +98 -9
- 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 +12 -7
- package/lib/lsp/start-language-server.d.ts.map +1 -1
- package/lib/lsp/start-language-server.js +21 -7
- package/lib/lsp/start-language-server.js.map +1 -1
- package/lib/messages/carriers.d.ts +4 -6
- package/lib/messages/carriers.d.ts.map +1 -1
- package/lib/messages/carriers.js +4 -6
- package/lib/messages/carriers.js.map +1 -1
- package/lib/messages/index.d.ts +2 -2
- package/lib/messages/index.d.ts.map +1 -1
- package/lib/messages/index.js +2 -2
- package/lib/messages/index.js.map +1 -1
- package/lib/messages/renderer.d.ts +10 -4
- package/lib/messages/renderer.d.ts.map +1 -1
- package/lib/messages/renderer.js +6 -0
- package/lib/messages/renderer.js.map +1 -1
- package/lib/node/event-loop-monitor.d.ts.map +1 -1
- package/lib/node/event-loop-monitor.js +3 -2
- package/lib/node/event-loop-monitor.js.map +1 -1
- package/lib/node/heap-ceiling.d.ts +61 -0
- package/lib/node/heap-ceiling.d.ts.map +1 -0
- package/lib/node/heap-ceiling.js +72 -0
- package/lib/node/heap-ceiling.js.map +1 -0
- package/lib/node/index.d.ts +1 -1
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +5 -1
- package/lib/node/index.js.map +1 -1
- package/lib/node/latency-from-env.d.ts +1 -1
- package/lib/node/latency-from-env.js +1 -1
- package/lib/node/lint-grammar.js.map +1 -1
- package/lib/node/log-file-sink.d.ts +3 -2
- package/lib/node/log-file-sink.d.ts.map +1 -1
- package/lib/node/log-file-sink.js +6 -2
- package/lib/node/log-file-sink.js.map +1 -1
- package/lib/node/log-preamble-node.d.ts +5 -3
- package/lib/node/log-preamble-node.d.ts.map +1 -1
- package/lib/node/log-preamble-node.js +13 -10
- package/lib/node/log-preamble-node.js.map +1 -1
- package/lib/node/measure-memory.d.ts.map +1 -1
- package/lib/node/measure-memory.js +5 -4
- package/lib/node/measure-memory.js.map +1 -1
- package/lib/node/memory-monitor.d.ts +2 -2
- package/lib/node/memory-monitor.d.ts.map +1 -1
- package/lib/node/memory-monitor.js +9 -10
- package/lib/node/memory-monitor.js.map +1 -1
- package/lib/node/node-file-system-provider.d.ts +67 -9
- package/lib/node/node-file-system-provider.d.ts.map +1 -1
- package/lib/node/node-file-system-provider.js +198 -53
- package/lib/node/node-file-system-provider.js.map +1 -1
- package/lib/node/profile-capture.d.ts +12 -4
- package/lib/node/profile-capture.d.ts.map +1 -1
- package/lib/node/profile-capture.js +8 -6
- package/lib/node/profile-capture.js.map +1 -1
- package/lib/node/profile-digest.js.map +1 -1
- package/lib/node/profiling-run.d.ts +13 -3
- package/lib/node/profiling-run.d.ts.map +1 -1
- package/lib/node/profiling-run.js +17 -8
- package/lib/node/profiling-run.js.map +1 -1
- package/lib/node/rename-over-open-readers.d.ts +61 -0
- package/lib/node/rename-over-open-readers.d.ts.map +1 -0
- package/lib/node/rename-over-open-readers.js +80 -0
- package/lib/node/rename-over-open-readers.js.map +1 -0
- package/lib/node/server-diagnostics.js +1 -1
- package/lib/node/server-diagnostics.js.map +1 -1
- package/lib/node/server-state-snapshot.d.ts +6 -5
- package/lib/node/server-state-snapshot.d.ts.map +1 -1
- package/lib/node/server-state-snapshot.js +20 -17
- package/lib/node/server-state-snapshot.js.map +1 -1
- package/lib/node/socket-launcher.d.ts +43 -7
- package/lib/node/socket-launcher.d.ts.map +1 -1
- package/lib/node/socket-launcher.js +42 -7
- package/lib/node/socket-launcher.js.map +1 -1
- package/lib/node/startup-cpu-profile.d.ts +29 -0
- package/lib/node/startup-cpu-profile.d.ts.map +1 -0
- package/lib/node/startup-cpu-profile.js +91 -0
- package/lib/node/startup-cpu-profile.js.map +1 -0
- package/lib/node/stdio-launcher.d.ts +13 -13
- package/lib/node/stdio-launcher.d.ts.map +1 -1
- package/lib/node/stdio-launcher.js +21 -11
- package/lib/node/stdio-launcher.js.map +1 -1
- package/lib/node/validate-workspace.d.ts +1 -1
- package/lib/node/validate-workspace.d.ts.map +1 -1
- package/lib/node/validate-workspace.js +5 -1
- package/lib/node/validate-workspace.js.map +1 -1
- package/lib/testing/document-uri-policy-conformance.js +1 -1
- package/lib/testing/document-uri-policy-conformance.js.map +1 -1
- package/lib/testing/fake-description.js.map +1 -1
- package/lib/testing/fake-document.d.ts +2 -1
- package/lib/testing/fake-document.d.ts.map +1 -1
- package/lib/testing/fake-document.js.map +1 -1
- package/lib/testing/index.d.ts +1 -1
- package/lib/testing/index.d.ts.map +1 -1
- package/lib/testing/index.js +2 -1
- package/lib/testing/index.js.map +1 -1
- package/lib/testing/langium-test-helpers.d.ts.map +1 -1
- package/lib/testing/langium-test-helpers.js +1 -0
- package/lib/testing/langium-test-helpers.js.map +1 -1
- package/lib/testing/make-noop-language-services.js.map +1 -1
- package/lib/testing/make-noop-shared-services.js.map +1 -1
- package/lib/testing/make-test-services.d.ts +45 -14
- package/lib/testing/make-test-services.d.ts.map +1 -1
- package/lib/testing/make-test-services.js +23 -7
- package/lib/testing/make-test-services.js.map +1 -1
- package/lib/testing/make-test-tracer.d.ts +12 -0
- package/lib/testing/make-test-tracer.d.ts.map +1 -1
- package/lib/testing/make-test-tracer.js +13 -0
- package/lib/testing/make-test-tracer.js.map +1 -1
- package/lib/testing/node/applied-edit-capture.d.ts +29 -0
- package/lib/testing/node/applied-edit-capture.d.ts.map +1 -0
- package/lib/testing/node/applied-edit-capture.js +117 -0
- package/lib/testing/node/applied-edit-capture.js.map +1 -0
- package/lib/testing/node/golden-corpus.js.map +1 -1
- package/lib/testing/node/index.d.ts +4 -1
- package/lib/testing/node/index.d.ts.map +1 -1
- package/lib/testing/node/index.js +4 -1
- 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 +21 -6
- package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
- package/lib/testing/node/lsp-server-connection.js +49 -106
- package/lib/testing/node/lsp-server-connection.js.map +1 -1
- package/lib/testing/node/scratch-workspace.d.ts +2 -1
- package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
- package/lib/testing/node/scratch-workspace.js +12 -6
- package/lib/testing/node/scratch-workspace.js.map +1 -1
- package/lib/testing/node/settle-server.d.ts +33 -0
- package/lib/testing/node/settle-server.d.ts.map +1 -0
- package/lib/testing/node/settle-server.js +84 -0
- package/lib/testing/node/settle-server.js.map +1 -0
- package/lib/testing/node/spawned-server.d.ts +30 -1
- package/lib/testing/node/spawned-server.d.ts.map +1 -1
- package/lib/testing/node/spawned-server.js +39 -2
- package/lib/testing/node/spawned-server.js.map +1 -1
- package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
- package/lib/testing/playwright/e2e-profiling.js.map +1 -1
- package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
- package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
- package/lib/testing/playwright/flaky-network-proxy.js +164 -0
- package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
- package/lib/testing/playwright/index.d.ts +1 -0
- package/lib/testing/playwright/index.d.ts.map +1 -1
- package/lib/testing/playwright/index.js +1 -0
- package/lib/testing/playwright/index.js.map +1 -1
- package/lib/testing/playwright/server-log-capture.d.ts +46 -16
- package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-capture.js +111 -40
- package/lib/testing/playwright/server-log-capture.js.map +1 -1
- package/lib/testing/playwright/server-log-fixture.d.ts +16 -0
- package/lib/testing/playwright/server-log-fixture.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-fixture.js +25 -6
- package/lib/testing/playwright/server-log-fixture.js.map +1 -1
- package/lib/testing/playwright/server-log-region.d.ts +15 -0
- package/lib/testing/playwright/server-log-region.d.ts.map +1 -0
- package/lib/testing/playwright/server-log-region.js +30 -0
- package/lib/testing/playwright/server-log-region.js.map +1 -0
- package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-rename-reporter.js +4 -3
- package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
- package/lib/testing/run-update-pipeline.d.ts +8 -5
- package/lib/testing/run-update-pipeline.d.ts.map +1 -1
- package/lib/testing/run-update-pipeline.js.map +1 -1
- package/lib/testing/stub-ast-document-manager.d.ts +11 -51
- package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.js +31 -59
- package/lib/testing/stub-ast-document-manager.js.map +1 -1
- package/lib/testing/stub-document-builder.d.ts +25 -11
- package/lib/testing/stub-document-builder.d.ts.map +1 -1
- package/lib/testing/stub-document-builder.js +91 -2
- package/lib/testing/stub-document-builder.js.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
- package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.js +132 -16
- package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
- package/lib/testing/stub-index-manager.js.map +1 -1
- package/lib/testing/stub-langium-documents.d.ts +3 -2
- package/lib/testing/stub-langium-documents.d.ts.map +1 -1
- package/lib/testing/stub-langium-documents.js.map +1 -1
- package/lib/testing/stub-model-service.d.ts +8 -7
- package/lib/testing/stub-model-service.d.ts.map +1 -1
- package/lib/testing/stub-model-service.js +4 -4
- package/lib/testing/stub-model-service.js.map +1 -1
- package/lib/testing/stub-project-manager.d.ts.map +1 -1
- package/lib/testing/stub-project-manager.js +10 -0
- package/lib/testing/stub-project-manager.js.map +1 -1
- package/lib/testing/stub-self-save-registry.d.ts +1 -1
- package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
- package/lib/testing/stub-service-registry.d.ts +1 -1
- package/lib/testing/stub-service-registry.js.map +1 -1
- package/lib/testing/stub-writable-file-system.d.ts +1 -1
- package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
- package/lib/testing/stub-writable-file-system.js +2 -1
- package/lib/testing/stub-writable-file-system.js.map +1 -1
- package/lib/util/connection-liveness.d.ts +22 -6
- package/lib/util/connection-liveness.d.ts.map +1 -1
- package/lib/util/connection-liveness.js +75 -15
- package/lib/util/connection-liveness.js.map +1 -1
- package/lib/util/environment.d.ts +7 -0
- package/lib/util/environment.d.ts.map +1 -1
- package/lib/util/environment.js +15 -1
- package/lib/util/environment.js.map +1 -1
- package/lib/util/registry.d.ts.map +1 -1
- package/package.json +41 -60
- package/src/browser/host-heads-in-worker.ts +218 -0
- package/src/browser/index.ts +17 -0
- package/src/browser/indexeddb-file-system-store.ts +192 -0
- package/src/browser/start-language-server-in-worker.ts +56 -0
- package/src/documents/ast-document-manager.ts +477 -250
- package/src/documents/client-ids.ts +5 -22
- package/src/documents/client-session-errors.ts +26 -0
- package/src/documents/client-session-registry.ts +262 -0
- package/src/documents/dirty-state-tracker.ts +167 -0
- package/src/documents/document-release-handler.ts +404 -0
- package/src/documents/document-release-scheduler.ts +121 -0
- package/src/documents/file-system-task-queue.ts +77 -0
- package/src/documents/hydranium-text-documents.ts +1044 -615
- package/src/documents/index.ts +10 -2
- package/src/documents/language-client-shadow.ts +501 -0
- package/src/documents/model-ledger.ts +66 -0
- package/src/documents/text-ledger.ts +112 -0
- package/src/documents/version-sync-service.ts +304 -0
- package/src/index.ts +3 -0
- package/src/langium/ast-extension/ast-extension-service.ts +77 -41
- package/src/langium/ast-extension/ast-node-builder.ts +35 -13
- package/src/langium/bootstrap.ts +79 -43
- package/src/langium/build-phase-pass/build-phase-pass-service.ts +29 -19
- package/src/langium/build-phase-pass/build-phase-pass.ts +37 -8
- package/src/langium/composite-ast-reflection.ts +112 -0
- package/src/langium/config/configuration-provider.ts +119 -0
- package/src/langium/config/index.ts +1 -0
- package/src/langium/diagnostics/console-tee.ts +150 -0
- package/src/langium/diagnostics/hydranium-langium-profiler.ts +15 -39
- package/src/langium/diagnostics/log-preamble.ts +1 -1
- package/src/langium/diagnostics/logger.ts +51 -17
- package/src/langium/diagnostics/lsp-logger.ts +83 -45
- package/src/langium/document-builder/build-pipeline-integration.ts +57 -32
- package/src/langium/document-builder/build-session.ts +4 -3
- package/src/langium/document-builder/document-builder.ts +773 -106
- package/src/langium/integration-services.ts +20 -23
- package/src/langium/integrity/integrity-rule.ts +22 -8
- package/src/langium/integrity/integrity-service.ts +656 -90
- package/src/langium/keys/containment.ts +3 -2
- package/src/langium/keys/name-based-key-provider.ts +24 -12
- package/src/langium/language-module.ts +52 -9
- package/src/langium/model-service/client-session.ts +769 -0
- package/src/langium/model-service/index.ts +2 -0
- package/src/langium/model-service/model-events.ts +82 -0
- package/src/langium/model-service/model-service.ts +885 -532
- package/src/langium/module.ts +141 -65
- package/src/langium/naming/name-provider.ts +34 -8
- package/src/langium/project/abstract-project-manager.ts +409 -20
- package/src/langium/project/project-change-event.ts +25 -3
- package/src/langium/project/project-manager.ts +31 -2
- package/src/langium/project/single-project-manager.ts +16 -1
- package/src/langium/residency/cst-residency-service.ts +210 -87
- package/src/langium/scope/ast-node-description-provider.ts +111 -16
- package/src/langium/scope/built-local-symbols.ts +13 -0
- package/src/langium/scope/fallback-scope.ts +38 -0
- package/src/langium/scope/hydranium-scope-computation.ts +45 -44
- package/src/langium/scope/hydranium-scope-provider.ts +245 -41
- package/src/langium/scope/index.ts +1 -0
- package/src/langium/scope/reference-candidate-provider.ts +6 -5
- package/src/langium/scope/scope-extension-service.ts +148 -56
- package/src/langium/scope/scoped-ast-node-description.ts +1 -3
- package/src/langium/serialization/abstract-serializer.ts +57 -41
- package/src/langium/serialization/json-serializer.ts +14 -3
- package/src/langium/serialization/serializer.ts +1 -1
- package/src/langium/serialization/yaml-serializer.ts +26 -4
- package/src/langium/service-registry.ts +41 -2
- package/src/langium/shared-services.ts +13 -4
- package/src/langium/single-langium-copy.ts +42 -0
- package/src/langium/transfer/transfer-encoder.ts +76 -50
- package/src/langium/trivia/comment-preserver.ts +1410 -0
- package/src/langium/trivia/document-ending-preserver.ts +71 -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 +56 -0
- package/src/langium/trivia/trivia-service.ts +99 -0
- package/src/langium/update-rewrite/update-rewrite-service.ts +1 -1
- package/src/langium/update-rewrite/update-rewrite.ts +1 -1
- package/src/langium/validation/document-validator.ts +312 -31
- package/src/langium/validation/validation-contribution-collector.ts +10 -1
- package/src/langium/workspace/ast-node-locator.ts +33 -0
- package/src/langium/workspace/document-uri-policy.ts +32 -18
- package/src/langium/workspace/file-not-found.ts +35 -0
- package/src/langium/workspace/file-system-provider.ts +258 -16
- package/src/langium/workspace/hydranium-langium-document-factory.ts +239 -4
- package/src/langium/workspace/hydranium-workspace-lock.ts +101 -2
- package/src/langium/workspace/hydranium-workspace-manager.ts +214 -35
- package/src/langium/workspace/in-memory-file-system-provider.ts +54 -23
- package/src/langium/workspace/index.ts +3 -0
- package/src/langium/workspace/initialize-workspace.ts +96 -4
- package/src/langium/workspace/langium-documents.ts +19 -1
- package/src/langium/workspace/persistent-file-system-provider.ts +27 -15
- package/src/{documents → langium/workspace}/self-save-registry.ts +12 -14
- package/src/langium/workspace/syntax-errors.ts +34 -0
- package/src/langium/workspace/virtual-document.ts +106 -25
- package/src/langium/workspace/write-lock-scope.ts +27 -12
- package/src/launcher/integrated-server.ts +3 -1
- package/src/locale/server-locale.ts +6 -6
- 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/edit-requests-guard.ts +152 -0
- package/src/lsp/hydranium-document-update-handler.ts +284 -110
- package/src/lsp/index.ts +6 -2
- package/src/lsp/lsp-latency.ts +62 -0
- package/src/lsp/save-text-document.ts +63 -0
- package/src/lsp/semantic-token-provider.ts +146 -8
- package/src/lsp/shared-module.ts +4 -8
- package/src/lsp/start-language-server.ts +21 -7
- package/src/messages/carriers.ts +4 -6
- package/src/messages/index.ts +11 -2
- package/src/messages/renderer.ts +11 -3
- package/src/node/event-loop-monitor.ts +3 -4
- package/src/node/heap-ceiling.ts +108 -0
- package/src/node/index.ts +5 -1
- package/src/node/latency-from-env.ts +1 -1
- package/src/node/log-file-sink.ts +6 -2
- package/src/node/log-preamble-node.ts +20 -10
- package/src/node/measure-memory.ts +5 -4
- package/src/node/memory-monitor.ts +10 -10
- package/src/node/node-file-system-provider.ts +214 -57
- package/src/node/profile-capture.ts +16 -15
- package/src/node/profiling-run.ts +30 -8
- package/src/node/rename-over-open-readers.ts +94 -0
- package/src/node/server-diagnostics.ts +1 -1
- package/src/node/server-state-snapshot.ts +28 -20
- package/src/node/socket-launcher.ts +78 -14
- package/src/node/startup-cpu-profile.ts +94 -0
- package/src/node/stdio-launcher.ts +29 -19
- package/src/node/validate-workspace.ts +8 -2
- package/src/testing/document-uri-policy-conformance.ts +1 -1
- package/src/testing/fake-document.ts +2 -1
- package/src/testing/index.ts +2 -1
- package/src/testing/langium-test-helpers.ts +1 -0
- package/src/testing/make-test-services.ts +83 -31
- package/src/testing/make-test-tracer.ts +26 -0
- package/src/testing/node/applied-edit-capture.ts +141 -0
- package/src/testing/node/index.ts +4 -1
- package/src/testing/node/lsp-harness.ts +2 -0
- package/src/testing/node/lsp-server-connection.ts +83 -119
- package/src/testing/node/scratch-workspace.ts +12 -6
- package/src/testing/node/settle-server.ts +89 -0
- package/src/testing/node/spawned-server.ts +57 -3
- package/src/testing/parse-semantic-root.ts +1 -1
- package/src/testing/playwright/flaky-network-proxy.ts +240 -0
- package/src/testing/playwright/index.ts +1 -0
- package/src/testing/playwright/server-log-capture.ts +137 -47
- package/src/testing/playwright/server-log-fixture.ts +46 -6
- package/src/testing/playwright/server-log-region.ts +32 -0
- package/src/testing/playwright/server-log-rename-reporter.ts +4 -3
- package/src/testing/run-update-pipeline.ts +8 -5
- package/src/testing/stub-ast-document-manager.ts +47 -123
- package/src/testing/stub-document-builder.ts +128 -15
- package/src/testing/stub-hydranium-text-documents.ts +184 -27
- package/src/testing/stub-langium-documents.ts +3 -2
- package/src/testing/stub-model-service.ts +9 -8
- package/src/testing/stub-project-manager.ts +10 -0
- package/src/testing/stub-self-save-registry.ts +1 -1
- package/src/testing/stub-service-registry.ts +1 -1
- package/src/testing/stub-writable-file-system.ts +3 -2
- package/src/util/connection-liveness.ts +81 -15
- package/src/util/environment.ts +24 -2
- package/lib/documents/language-client-text-shadow.d.ts +0 -124
- package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
- package/lib/documents/language-client-text-shadow.js +0 -190
- package/lib/documents/language-client-text-shadow.js.map +0 -1
- package/lib/documents/self-save-registry.d.ts.map +0 -1
- package/lib/documents/self-save-registry.js.map +0 -1
- package/lib/lsp/instrument-connection.d.ts +0 -36
- package/lib/lsp/instrument-connection.d.ts.map +0 -1
- package/lib/lsp/instrument-connection.js +0 -62
- package/lib/lsp/instrument-connection.js.map +0 -1
- package/lib/node/process-memory.d.ts +0 -66
- package/lib/node/process-memory.d.ts.map +0 -1
- package/lib/node/process-memory.js +0 -252
- package/lib/node/process-memory.js.map +0 -1
- package/src/documents/language-client-text-shadow.ts +0 -211
- package/src/lsp/instrument-connection.ts +0 -66
- package/src/node/process-memory.ts +0 -299
|
@@ -8,81 +8,30 @@
|
|
|
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
|
+
asModelVersion,
|
|
18
|
+
type ModelVersion,
|
|
19
|
+
type TextVersion,
|
|
20
|
+
UNRECORDED_VERSION,
|
|
21
|
+
describeErrorWithStack
|
|
16
22
|
} from '@hydranium/protocol';
|
|
17
|
-
import {
|
|
18
|
-
type AstNode,
|
|
19
|
-
type DocumentBuilder,
|
|
20
|
-
DocumentState,
|
|
21
|
-
type FileSystemProvider,
|
|
22
|
-
type LangiumDocument,
|
|
23
|
-
type LangiumDocuments,
|
|
24
|
-
UriUtils
|
|
25
|
-
} from '@hydranium/langium';
|
|
23
|
+
import { type AstNode, DocumentState, type LangiumDocument, type LangiumDocuments, URI, UriUtils } from '@hydranium/langium';
|
|
26
24
|
import { type LogNameOptions } from '../langium/diagnostics/logger.js';
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* {@link FileSystemProvider} is read-only; the manager needs to persist saves,
|
|
31
|
-
* so consumers wire in a provider that implements this superset.
|
|
32
|
-
*
|
|
33
|
-
* Implementations may optionally hold a reference to a
|
|
34
|
-
* {@link SelfSaveRegistry} so they can record their own write mtimes and
|
|
35
|
-
* help downstream file-watchers suppress echo events for those writes.
|
|
36
|
-
* The framework's `DefaultFileSystemProvider` takes the registry as
|
|
37
|
-
* a constructor parameter; alternative implementations can either follow
|
|
38
|
-
* the same pattern or leave the field unset.
|
|
39
|
-
*/
|
|
40
|
-
export interface WritableFileSystemProvider extends FileSystemProvider {
|
|
41
|
-
writeFile(uri: URI, content: string): Promise<void>;
|
|
42
|
-
/**
|
|
43
|
-
* Last-modified time (ms) of the file at `uri`, or `undefined` if it can't
|
|
44
|
-
* be determined (missing file, or a provider with no disk — in-memory /
|
|
45
|
-
* browser). Optional: the only consumer is self-save echo suppression
|
|
46
|
-
* (`didChangeWatchedFiles`), which simply lets a change through when the
|
|
47
|
-
* mtime is unavailable. Distinct from Langium's `stat` (whose
|
|
48
|
-
* `FileSystemNode` carries no mtime). Keeping disk access on the provider
|
|
49
|
-
* seam is what lets the LSP update handler avoid a direct `node:fs` import.
|
|
50
|
-
*/
|
|
51
|
-
mtimeMs?(uri: URI): Promise<number | undefined>;
|
|
52
|
-
/**
|
|
53
|
-
* Resolve `uri` to its real on-disk identity (symlinks collapsed, `..`/`.`
|
|
54
|
-
* walked, case-folded on case-insensitive filesystems), or `undefined` *iff
|
|
55
|
-
* the filesystem knows the path is absent*. The single source of the
|
|
56
|
-
* "nothing loadable here" signal `RealpathDocumentUriPolicy` turns into
|
|
57
|
-
* the synthetic-placeholder branch of `getOrCreateDocument`.
|
|
58
|
-
*
|
|
59
|
-
* Contract for implementers:
|
|
60
|
-
* - A `file:`-backed provider returns the resolved URI when the file exists,
|
|
61
|
-
* and `undefined` when it cannot resolve the path (missing / unreadable).
|
|
62
|
-
* - A non-`file:` URI (or any URI the provider cannot stat) passes through
|
|
63
|
-
* **unchanged** — it is treated as present, never reported absent.
|
|
64
|
-
* - A provider with no disk to check (in-memory / browser / empty) simply
|
|
65
|
-
* omits this method; `RealpathDocumentUriPolicy` then degrades to the
|
|
66
|
-
* syntactic `DefaultDocumentUriPolicy` behaviour automatically.
|
|
67
|
-
*
|
|
68
|
-
* Synchronous (a `realpath` is a kernel-cached syscall) and optional — the
|
|
69
|
-
* only consumers are the document-identity policy's `canonicalUri`/`loadUri`.
|
|
70
|
-
* Keeping the syscall on the provider seam is what lets the policy stay
|
|
71
|
-
* browser-neutral (no `node:fs` import).
|
|
72
|
-
*/
|
|
73
|
-
realpath?(uri: URI): URI | undefined;
|
|
74
|
-
/** Registry the provider records its own writes against. Optional — providers without watcher integration may omit. */
|
|
75
|
-
readonly selfSaveRegistry?: SelfSaveRegistry;
|
|
76
|
-
}
|
|
25
|
+
import { type AstDiagnostic } from '../langium/validation/document-validator.js';
|
|
26
|
+
import { type WritableFileSystemProvider } from '../langium/workspace/file-system-provider.js';
|
|
27
|
+
import { ReentrantWriteLockError, isInsideWriteLock } from '../langium/workspace/write-lock-scope.js';
|
|
77
28
|
import { Disposable } from 'vscode-languageserver';
|
|
78
29
|
import { TextDocumentIdentifier, type TextDocumentItem } from 'vscode-languageserver-protocol';
|
|
79
30
|
import { type TextDocument } from 'vscode-languageserver-textdocument';
|
|
80
|
-
import { URI } from '@hydranium/langium';
|
|
81
31
|
import { type ServerSharedServices } from '../langium/module.js';
|
|
82
|
-
import {
|
|
32
|
+
import { type HydraniumDocumentBuilder } from '../langium/document-builder/index.js';
|
|
83
33
|
import { UNKNOWN_CLIENT_ID } from './client-ids.js';
|
|
84
34
|
import { type HydraniumTextDocuments } from './hydranium-text-documents.js';
|
|
85
|
-
import { type SelfSaveRegistry } from './self-save-registry.js';
|
|
86
35
|
import { type DocumentUriPolicy } from '../langium/workspace/document-uri-policy.js';
|
|
87
36
|
|
|
88
37
|
export interface UpdateInfo {
|
|
@@ -91,124 +40,186 @@ export interface UpdateInfo {
|
|
|
91
40
|
}
|
|
92
41
|
|
|
93
42
|
/**
|
|
94
|
-
* Server-internal document envelope at the AST layer
|
|
95
|
-
*
|
|
96
|
-
* for in-process subscribers (`ModelService`, integrity service, etc.).
|
|
43
|
+
* Server-internal document envelope at the AST layer, which `ModelService`
|
|
44
|
+
* reads and events hand to in-process callers.
|
|
97
45
|
*
|
|
98
|
-
*
|
|
99
|
-
* `TransferDocument
|
|
100
|
-
* `@hydranium/protocol`, which carries the wire-transfer shape (no
|
|
101
|
-
* `$container` cycles, references as strings). The two are structural
|
|
102
|
-
* twins; the type-system distinction is the generic constraint, and the
|
|
103
|
-
* conversion seam between them is the framework `TransferEncoder`.
|
|
46
|
+
* `root` is the live AST the build holds, not an encoded copy like
|
|
47
|
+
* `TransferDocument.model`, so mutating it changes the model every reader sees.
|
|
104
48
|
*/
|
|
105
|
-
export interface AstDocument<TAst extends AstNode, TDiagnostic> {
|
|
49
|
+
export interface AstDocument<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> {
|
|
106
50
|
root: TAst;
|
|
107
|
-
|
|
51
|
+
/** Absent until the document is validated, and on any `ModelService` read below `Validated`; `[]` means validated and clean. */
|
|
52
|
+
diagnostics?: TDiagnostic[];
|
|
108
53
|
uri: string;
|
|
109
54
|
/**
|
|
110
|
-
*
|
|
111
|
-
* `
|
|
112
|
-
*
|
|
113
|
-
* that hold an `AstDocument` and mutate it pass this value back as
|
|
114
|
-
* `TransferUpdateArgs.baseVersion` / `TransferSaveArgs.baseVersion` to opt
|
|
115
|
-
* into the conflict gate.
|
|
55
|
+
* The version of the text `root` was parsed from (`ModelLedger.versionOf`).
|
|
56
|
+
* A caller that mutates the document sends it back as the `baseVersion` of
|
|
57
|
+
* its session's write, and the conflict gate arms on it.
|
|
116
58
|
*/
|
|
117
|
-
version:
|
|
59
|
+
version: ModelVersion;
|
|
118
60
|
}
|
|
119
61
|
|
|
62
|
+
/**
|
|
63
|
+
* What a session's write resolves to: the document, and in `written` the
|
|
64
|
+
* version its text took. A `version` past it means the document was built
|
|
65
|
+
* from a later text, which holds another client's edit too.
|
|
66
|
+
*/
|
|
67
|
+
export type WrittenAstDocument<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> = AstDocument<TAst, TDiagnostic> & {
|
|
68
|
+
written: { version: TextVersion };
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* What a session's save resolves to: the written document, and in
|
|
73
|
+
* `persisted` the version of the text it wrote to the file. That can differ
|
|
74
|
+
* from `version` either way, since writes land between the build and the
|
|
75
|
+
* take.
|
|
76
|
+
*/
|
|
77
|
+
export type SavedAstDocument<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> = WrittenAstDocument<
|
|
78
|
+
TAst,
|
|
79
|
+
TDiagnostic
|
|
80
|
+
> & {
|
|
81
|
+
persisted: { version: TextVersion };
|
|
82
|
+
};
|
|
83
|
+
|
|
120
84
|
export namespace AstDocument {
|
|
121
85
|
/**
|
|
122
|
-
* Construct an {@link AstDocument} envelope
|
|
123
|
-
*
|
|
124
|
-
* don't need to repeat the empty array at every call site. Mirrors
|
|
125
|
-
* `TransferDocument.create` on the wire side.
|
|
86
|
+
* Construct an {@link AstDocument} envelope, its version marked as coming
|
|
87
|
+
* from a read. `diagnostics` absent means not validated.
|
|
126
88
|
*/
|
|
127
|
-
export function create<TAst extends AstNode, TDiagnostic =
|
|
89
|
+
export function create<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic>(
|
|
128
90
|
uri: string,
|
|
129
91
|
version: number,
|
|
130
92
|
root: TAst,
|
|
131
|
-
diagnostics
|
|
93
|
+
diagnostics?: TDiagnostic[]
|
|
132
94
|
): AstDocument<TAst, TDiagnostic> {
|
|
133
|
-
return { uri, version, root, diagnostics };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Project a {@link LangiumDocument} into its {@link AstDocument}
|
|
138
|
-
* envelope — the single place that reads `root` / `diagnostics` /
|
|
139
|
-
* `version` / `uri` off a built document. Both the event path
|
|
140
|
-
* ({@link AstDocumentManager.onUpdate} / `onSave`) and the read path
|
|
141
|
-
* (`ModelService`'s snapshot accessors) go through here so the
|
|
142
|
-
* field mapping lives once.
|
|
143
|
-
*
|
|
144
|
-
* The emitted `uri` is always the document's own `textDocument.uri` — the
|
|
145
|
-
* canonical document-identity form (see {@link DocumentUriPolicy}). Events
|
|
146
|
-
* carry that identity, not the subscriber's (possibly non-canonical) URI:
|
|
147
|
-
* a subscriber already knows the URI it subscribed with, so the useful
|
|
148
|
-
* thing to surface is the canonical one every other layer keys by.
|
|
149
|
-
*/
|
|
150
|
-
export function from<TAst extends AstNode, TDiagnostic = unknown>(document: LangiumDocument): AstDocument<TAst, TDiagnostic> {
|
|
151
|
-
return create<TAst, TDiagnostic>(
|
|
152
|
-
document.textDocument.uri,
|
|
153
|
-
document.textDocument.version,
|
|
154
|
-
document.parseResult.value as TAst,
|
|
155
|
-
(document.diagnostics ?? []) as unknown as TDiagnostic[]
|
|
156
|
-
);
|
|
95
|
+
return { uri, version: asModelVersion(version), root, ...(diagnostics === undefined ? {} : { diagnostics }) };
|
|
157
96
|
}
|
|
158
97
|
}
|
|
159
98
|
|
|
160
|
-
/**
|
|
161
|
-
export type AstDocumentUpdatedEvent<TAst extends AstNode, TDiagnostic> = TransferUpdatedEvent<
|
|
99
|
+
/** The update event a document's build delivers, typed over the generic event wrapper. */
|
|
100
|
+
export type AstDocumentUpdatedEvent<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> = TransferUpdatedEvent<
|
|
101
|
+
AstDocument<TAst, TDiagnostic>
|
|
102
|
+
>;
|
|
162
103
|
|
|
163
|
-
/**
|
|
164
|
-
export type AstDocumentSavedEvent<TAst extends AstNode, TDiagnostic> = TransferSavedEvent<
|
|
104
|
+
/** The event a save delivers, typed over the generic event wrapper. */
|
|
105
|
+
export type AstDocumentSavedEvent<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> = TransferSavedEvent<
|
|
106
|
+
AstDocument<TAst, TDiagnostic>
|
|
107
|
+
>;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Why an update event fired and whose write it echoes, as
|
|
111
|
+
* {@link AstDocumentManager.attributeUpdate} answers for a document. The
|
|
112
|
+
* fields mean what they mean on `TransferUpdatedEvent`.
|
|
113
|
+
*/
|
|
114
|
+
export interface UpdateAttribution {
|
|
115
|
+
reason: 'changed' | 'rebuilt';
|
|
116
|
+
sourceClientId: string;
|
|
117
|
+
causedBy: string;
|
|
118
|
+
}
|
|
165
119
|
|
|
166
120
|
/** Construction options for {@link AstDocumentManager}. */
|
|
167
|
-
export
|
|
121
|
+
export interface AstDocumentManagerOptions extends LogNameOptions {
|
|
122
|
+
/**
|
|
123
|
+
* Skip a queued save of a URI when a newer save of it is queued behind. The
|
|
124
|
+
* newer save took its text later, so disk ends the same with fewer writes.
|
|
125
|
+
* A skipped save announces nothing and takes the newer save's outcome: it
|
|
126
|
+
* resolves when that one lands and rejects with its error when it fails,
|
|
127
|
+
* since disk then holds neither text. Defaults to `false`: every save
|
|
128
|
+
* writes. The framework binds the manager without options, so turning this
|
|
129
|
+
* on means rebinding `AstDocumentManager` with them.
|
|
130
|
+
*/
|
|
131
|
+
readonly coalesceSaves?: boolean;
|
|
132
|
+
}
|
|
168
133
|
|
|
169
134
|
/**
|
|
170
135
|
* The document slot the model server and the integrity service talk to:
|
|
171
|
-
* open/close/update/save
|
|
172
|
-
* plumbing hidden.
|
|
136
|
+
* open/close/update/save and the attribution of update events, with the LSP
|
|
137
|
+
* plumbing hidden. Events are `ModelService`'s, which builds them from here.
|
|
173
138
|
*
|
|
174
139
|
* Generic over `<TAst extends AstNode, TDiagnostic>` so each consumer projects
|
|
175
140
|
* its own AST root type and diagnostic shape into the emitted
|
|
176
|
-
* {@link AstDocument} envelopes.
|
|
141
|
+
* {@link AstDocument} envelopes. A diagnostic shape narrower than
|
|
142
|
+
* `AstDiagnostic` is asserted unchecked; see {@link toAstDocument}.
|
|
177
143
|
*
|
|
178
144
|
* **URI contract.** Every URI-accepting member takes a URI in *any* spelling
|
|
179
145
|
* (canonical, symlinked, `..`/case-divergent) and canonicalizes internally
|
|
180
146
|
* through the {@link DocumentUriPolicy}, so a caller never has to canonicalize
|
|
181
147
|
* first and an implementation may not require it.
|
|
182
148
|
*/
|
|
183
|
-
export interface AstDocumentManager<TAst extends AstNode, TDiagnostic =
|
|
149
|
+
export interface AstDocumentManager<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> {
|
|
184
150
|
open(args: OpenModelArgs): Promise<Disposable>;
|
|
185
151
|
close(args: CloseModelArgs): Promise<void>;
|
|
186
152
|
isOpen(uri: string): boolean;
|
|
187
153
|
|
|
188
154
|
/** Apply `text` as `clientId`'s edit. Resolves to the resulting text-document version. */
|
|
189
|
-
update(uri: string, text: string, clientId: string): Promise<
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
155
|
+
update(uri: string, text: string, clientId: string): Promise<TextVersion>;
|
|
156
|
+
/**
|
|
157
|
+
* Write the document's current text to disk through `FileSystemTaskQueue`.
|
|
158
|
+
* The text is taken when this is called, so saves of one file land in the
|
|
159
|
+
* order they were called.
|
|
160
|
+
*
|
|
161
|
+
* Resolves to the version of the text on disk once it lands: the version
|
|
162
|
+
* taken, or under `coalesceSaves` the version of the newer save that wrote
|
|
163
|
+
* in its place. A caller reporting what it persisted takes it from here,
|
|
164
|
+
* since a version read beside the call names text a coalesced save never
|
|
165
|
+
* wrote.
|
|
166
|
+
*/
|
|
167
|
+
save(uri: string, clientId: string): Promise<TextVersion>;
|
|
168
|
+
/**
|
|
169
|
+
* Remove the document's file through `FileSystemTaskQueue`, then the
|
|
170
|
+
* document, in a build that closes every open of it but the editor's.
|
|
171
|
+
* Resolves once that build has run, also when it fails after removing the
|
|
172
|
+
* document; rejects, having changed nothing, when the file cannot be
|
|
173
|
+
* removed.
|
|
174
|
+
*
|
|
175
|
+
* From the call until it settles, {@link isDeleting} answers `true`, which
|
|
176
|
+
* refuses every session's write of the document: one landing before the
|
|
177
|
+
* build would be lost with it, or, as a save, write the file back. Marked
|
|
178
|
+
* before the first await, so checks a caller runs in the same step as the
|
|
179
|
+
* call hold up to the removal. A second delete of the document while one is
|
|
180
|
+
* under way is refused, and so is a delete from inside a holder of the write
|
|
181
|
+
* lock, with `ReentrantWriteLockError`, since its builds take that lock.
|
|
182
|
+
*
|
|
183
|
+
* A change requested before the build starts merges over the deletion, and
|
|
184
|
+
* the document lives on with every open but `clientId`'s, which is closed.
|
|
185
|
+
*/
|
|
186
|
+
delete(uri: string, clientId: string): Promise<void>;
|
|
187
|
+
/** Whether a {@link delete} of `uri` is under way. */
|
|
188
|
+
isDeleting(uri: string): boolean;
|
|
189
|
+
/**
|
|
190
|
+
* The client a deletion event for `uri` names: the one whose {@link delete}
|
|
191
|
+
* of it is under way, or the unknown-client id for a file removed outside
|
|
192
|
+
* any, as a file watcher reports one.
|
|
193
|
+
*/
|
|
194
|
+
attributeDeletion(uri: string): string;
|
|
195
195
|
|
|
196
196
|
getDocument(uri: string): LangiumDocument | undefined;
|
|
197
197
|
|
|
198
|
+
/**
|
|
199
|
+
* `document` as the envelope every event and snapshot read hands out, its
|
|
200
|
+
* `version` the one `ModelLedger` recorded for its root.
|
|
201
|
+
*
|
|
202
|
+
* The `uri` is the document's own canonical one, not a subscriber's
|
|
203
|
+
* spelling, so it matches the key every other layer uses. The diagnostics
|
|
204
|
+
* are asserted to be `TDiagnostic` unchecked: a lexer error or another
|
|
205
|
+
* validator's diagnostic satisfies the declared type and not a narrower one.
|
|
206
|
+
*/
|
|
207
|
+
toAstDocument(document: LangiumDocument): AstDocument<TAst, TDiagnostic>;
|
|
208
|
+
|
|
198
209
|
/** Client id that authored the document's current version, or `undefined` for a framework-internal build. */
|
|
199
210
|
getAuthor(document: LangiumDocument): string | undefined;
|
|
200
211
|
|
|
201
212
|
/**
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
213
|
+
* The reason, source and cause of an update event for `document` emitted
|
|
214
|
+
* now, from a phase listener of the build that carries it. `ModelService`
|
|
215
|
+
* takes its update events' attribution from here, once per document and
|
|
216
|
+
* phase, so every subscriber names the same client for one build. For a
|
|
217
|
+
* document a client opened, while rebuilds validate, the answer changes
|
|
218
|
+
* once its `Validated` listeners have all run: a later event at that
|
|
219
|
+
* version is `'rebuilt'`. `TransferDocumentUpdateReason` names the cases
|
|
220
|
+
* that fall back to the last update.
|
|
210
221
|
*/
|
|
211
|
-
|
|
222
|
+
attributeUpdate(document: LangiumDocument): UpdateAttribution;
|
|
212
223
|
}
|
|
213
224
|
|
|
214
225
|
/**
|
|
@@ -219,8 +230,9 @@ export interface AstDocumentManager<TAst extends AstNode, TDiagnostic = unknown>
|
|
|
219
230
|
*
|
|
220
231
|
* Generic over `<TAst extends AstNode, TDiagnostic>` so each consumer
|
|
221
232
|
* projects its own AST root type and diagnostic shape into the emitted
|
|
222
|
-
* `AstDocument` envelopes. `TDiagnostic` defaults to `
|
|
223
|
-
*
|
|
233
|
+
* `AstDocument` envelopes. `TDiagnostic` defaults to `AstDiagnostic`; a
|
|
234
|
+
* narrower one is asserted unchecked, as
|
|
235
|
+
* {@link AstDocumentManager.toAstDocument} says.
|
|
224
236
|
*
|
|
225
237
|
* **URI contract.** Every URI-accepting method takes a URI in *any* spelling
|
|
226
238
|
* (canonical, symlinked, `..`/case-divergent) and canonicalizes internally
|
|
@@ -231,13 +243,58 @@ export interface AstDocumentManager<TAst extends AstNode, TDiagnostic = unknown>
|
|
|
231
243
|
* resolution (the egress `applyEditToLanguageClient`) stay on
|
|
232
244
|
* {@link HydraniumTextDocuments}, their owner.
|
|
233
245
|
*/
|
|
234
|
-
export class DefaultAstDocumentManager<
|
|
246
|
+
export class DefaultAstDocumentManager<
|
|
247
|
+
TAst extends AstNode,
|
|
248
|
+
TDiagnostic extends AstDiagnostic = AstDiagnostic
|
|
249
|
+
> implements AstDocumentManager<TAst, TDiagnostic> {
|
|
250
|
+
/** The last `DocumentBuilder.update`'s URIs; the reason for a document the store does not track. */
|
|
235
251
|
protected lastUpdate?: UpdateInfo;
|
|
252
|
+
/**
|
|
253
|
+
* Canonical URIs a client has opened since the file was last deleted,
|
|
254
|
+
* whose versions the store keeps. One no client has opened keeps Langium's
|
|
255
|
+
* version `0` through every change of its content, so its version says
|
|
256
|
+
* nothing. Kept past the last close, since the store continues the version
|
|
257
|
+
* sequence on the next open; a delivery can land after that close.
|
|
258
|
+
*/
|
|
259
|
+
protected readonly trackedUris = new Set<CanonicalUri>();
|
|
260
|
+
/**
|
|
261
|
+
* Per tracked URI, the version whose `Validated` listeners last all ran,
|
|
262
|
+
* which is the version an update event was delivered for. Dropped on
|
|
263
|
+
* deletion, so a file created again with the same text is changed again.
|
|
264
|
+
*/
|
|
265
|
+
protected readonly deliveredVersions = new Map<CanonicalUri, number>();
|
|
266
|
+
/**
|
|
267
|
+
* Whose writes the build under way carries, set when it starts: the author
|
|
268
|
+
* of every open document's undelivered version, and the unknown-client id
|
|
269
|
+
* for a change no write explains, such as a deletion no session's delete
|
|
270
|
+
* made, a document no client has open, or a write that changed nothing.
|
|
271
|
+
* An undelivered version is one whose build has not validated it yet, so a
|
|
272
|
+
* write whose build was cancelled stays a cause of the build that takes
|
|
273
|
+
* over.
|
|
274
|
+
*
|
|
275
|
+
* Errs toward more than one cause, and so toward the unknown client, which
|
|
276
|
+
* a reader treats as foreign: an answer it repeats, never one it misses.
|
|
277
|
+
* A change no write explains counts for its own build only, so a build
|
|
278
|
+
* that takes over from a cancelled one loses it. One field for every build:
|
|
279
|
+
* a build started outside the workspace lock, such as a re-queue of an
|
|
280
|
+
* orphaned document, reads the causes of whichever build started last.
|
|
281
|
+
* An open document no build delivers, one a `shouldValidate` override
|
|
282
|
+
* skips, stays undelivered after its first write, so it is a cause of every
|
|
283
|
+
* build from then on while open.
|
|
284
|
+
*/
|
|
285
|
+
protected readonly buildCauses = new Set<string>();
|
|
286
|
+
|
|
287
|
+
/** Per canonical URI, the client whose {@link delete} of it is under way. */
|
|
288
|
+
protected readonly deletions = new Map<CanonicalUri, string>();
|
|
289
|
+
|
|
290
|
+
/** Per canonical URI, the newest save queued for it, which {@link coalesceSaves} lets older queued saves defer to. */
|
|
291
|
+
protected readonly newestSaves = new Map<CanonicalUri, Promise<TextVersion>>();
|
|
292
|
+
protected readonly coalesceSaves: boolean;
|
|
236
293
|
|
|
237
294
|
protected readonly textDocuments: HydraniumTextDocuments<TextDocument>;
|
|
238
295
|
protected readonly fileSystemProvider: WritableFileSystemProvider;
|
|
239
296
|
protected readonly langiumDocs: LangiumDocuments;
|
|
240
|
-
protected readonly documentBuilder:
|
|
297
|
+
protected readonly documentBuilder: HydraniumDocumentBuilder;
|
|
241
298
|
protected readonly uriPolicy: DocumentUriPolicy;
|
|
242
299
|
protected readonly tracer: Tracer;
|
|
243
300
|
|
|
@@ -251,32 +308,42 @@ export class DefaultAstDocumentManager<TAst extends AstNode, TDiagnostic = unkno
|
|
|
251
308
|
this.documentBuilder = services.workspace.DocumentBuilder;
|
|
252
309
|
this.uriPolicy = services.workspace.DocumentUriPolicy;
|
|
253
310
|
this.tracer = services.Tracer.for(options.logName ?? 'AstDocumentManager').trace('instantiated');
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
311
|
+
this.coalesceSaves = options.coalesceSaves ?? false;
|
|
312
|
+
this.textDocuments.onDidOpen(event => {
|
|
313
|
+
this.trackedUris.add(this.uriPolicy.canonicalUri(event.document.uri));
|
|
314
|
+
return this.open({ clientId: event.clientId, uri: event.document.uri, languageId: event.document.languageId });
|
|
315
|
+
});
|
|
257
316
|
this.textDocuments.onDidClose(event => this.close({ clientId: event.clientId, uri: event.document.uri }));
|
|
258
317
|
this.documentBuilder.onUpdate((changed, deleted) => {
|
|
259
318
|
this.lastUpdate = { changed, deleted };
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
// Parsed transition (the earliest phase with text, and one only re-read
|
|
265
|
-
// documents pass through — cascade relinks re-enter later), reconcile the
|
|
266
|
-
// store's persisted version sequence with the rebuilt content and
|
|
267
|
-
// re-stamp the document so every downstream envelope (revert broadcast,
|
|
268
|
-
// snapshot reads) carries the continued sequence. An empty-changes
|
|
269
|
-
// update only re-stamps the version. Previously-untracked URIs exit on a
|
|
270
|
-
// map lookup, so workspace-wide builds don't hash untouched documents.
|
|
271
|
-
this.documentBuilder.onDocumentPhase(
|
|
272
|
-
DocumentState.Parsed,
|
|
273
|
-
labelPhaseListener(document => {
|
|
274
|
-
const sequenceVersion = this.textDocuments.reconcileExternalContent(document.textDocument.uri, document.textDocument.getText());
|
|
275
|
-
if (sequenceVersion !== undefined && document.textDocument.version !== sequenceVersion) {
|
|
276
|
-
this.textDocuments.update(document.textDocument, [], sequenceVersion);
|
|
319
|
+
this.buildCauses.clear();
|
|
320
|
+
for (const textDocument of this.textDocuments.all()) {
|
|
321
|
+
if (!this.isDelivered(textDocument.uri, textDocument.version)) {
|
|
322
|
+
this.buildCauses.add(this.textDocuments.getAuthor(textDocument.uri, textDocument.version) ?? UNKNOWN_CLIENT_ID);
|
|
277
323
|
}
|
|
278
|
-
}
|
|
279
|
-
|
|
324
|
+
}
|
|
325
|
+
const unexplained = changed.some(uri => {
|
|
326
|
+
const textDocument = this.textDocuments.get(uri.toString());
|
|
327
|
+
return textDocument === undefined || this.isDelivered(textDocument.uri, textDocument.version);
|
|
328
|
+
});
|
|
329
|
+
if (unexplained) {
|
|
330
|
+
this.buildCauses.add(UNKNOWN_CLIENT_ID);
|
|
331
|
+
}
|
|
332
|
+
deleted.forEach(uri => this.buildCauses.add(this.attributeDeletion(uri.toString())));
|
|
333
|
+
// The only place a deletion is observable: `DocumentBuilder.update`
|
|
334
|
+
// removes a deleted document before it builds anything, so no phase
|
|
335
|
+
// listener ever sees it.
|
|
336
|
+
for (const uri of deleted) {
|
|
337
|
+
const key = this.uriPolicy.canonicalUri(uri.toString());
|
|
338
|
+
this.trackedUris.delete(key);
|
|
339
|
+
this.deliveredVersions.delete(key);
|
|
340
|
+
this.textDocuments.notifyDocumentDeleted(uri.toString());
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
// Once every listener ran, not in a listener of its own: listeners after
|
|
344
|
+
// it could still be skipped by a cancel, and the next build would then
|
|
345
|
+
// report as rebuilt a version they never delivered.
|
|
346
|
+
this.documentBuilder.onDocumentPhaseDelivered(DocumentState.Validated, (document, version) => this.markDelivered(document, version));
|
|
280
347
|
}
|
|
281
348
|
|
|
282
349
|
/**
|
|
@@ -308,87 +375,102 @@ export class DefaultAstDocumentManager<TAst extends AstNode, TDiagnostic = unkno
|
|
|
308
375
|
}
|
|
309
376
|
|
|
310
377
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
378
|
+
* The client that authored `document`'s current version, or `undefined` when
|
|
379
|
+
* no client wrote it: a document no client has open. A rebuild that keeps
|
|
380
|
+
* the version keeps its author, so this does not say who caused a build;
|
|
381
|
+
* {@link attributeUpdate} does.
|
|
382
|
+
* Honest about absence so a routing consumer tests `undefined` directly
|
|
383
|
+
* rather than against a sentinel; the presentation default
|
|
384
|
+
* ({@link UNKNOWN_CLIENT_ID}) is applied where an event needs a value.
|
|
313
385
|
*/
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return this.textDocuments.onDidSave(async event => {
|
|
317
|
-
if (this.uriPolicy.canonicalUri(event.document.uri) !== target) {
|
|
318
|
-
return undefined;
|
|
319
|
-
}
|
|
320
|
-
// Look the document up by its canonical URI: the adopter's
|
|
321
|
-
// `LangiumDocuments` keys by the canonical form, while the saved
|
|
322
|
-
// event carries the (possibly symlinked) client-facing URI.
|
|
323
|
-
const documentURI = UriUtils.toUri(target);
|
|
324
|
-
if (documentURI !== undefined && this.langiumDocs.hasDocument(documentURI)) {
|
|
325
|
-
const document = await this.langiumDocs.getOrCreateDocument(documentURI);
|
|
326
|
-
return listener({
|
|
327
|
-
document: this.toAstDocument(document),
|
|
328
|
-
sourceClientId: event.clientId
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
return undefined;
|
|
332
|
-
});
|
|
386
|
+
getAuthor(document: LangiumDocument): string | undefined {
|
|
387
|
+
return this.textDocuments.getAuthor(document.textDocument.uri, document.textDocument.version);
|
|
333
388
|
}
|
|
334
389
|
|
|
335
|
-
/**
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
390
|
+
/**
|
|
391
|
+
* `'changed'` for the first delivery of the document's version, crediting
|
|
392
|
+
* its author; `'rebuilt'` for a later one, crediting nobody, since it echoes
|
|
393
|
+
* no write, and naming the build's single cause if it has one. A version an
|
|
394
|
+
* open made from the text a build already parsed counts as delivered, as it
|
|
395
|
+
* echoes no write either.
|
|
396
|
+
*
|
|
397
|
+
* A document the rule does not apply to (see {@link isTracked}) falls back
|
|
398
|
+
* to the last update: it is `'changed'` when its URI was passed to
|
|
399
|
+
* `DocumentBuilder.update`. An open document that a validating build skips,
|
|
400
|
+
* through a `shouldValidate` override, is never delivered after its first
|
|
401
|
+
* write, so each of its events from then on is its author's change.
|
|
402
|
+
*/
|
|
403
|
+
attributeUpdate(document: LangiumDocument): UpdateAttribution {
|
|
404
|
+
const key = this.uriPolicy.canonicalUri(document.uri.toString());
|
|
405
|
+
const changed = this.isTracked(key)
|
|
406
|
+
? this.deliveredVersions.get(key) !== document.textDocument.version
|
|
407
|
+
: this.lastUpdate?.changed.some(uri => UriUtils.equals(uri, document.uri)) === true;
|
|
408
|
+
if (changed) {
|
|
409
|
+
// Presentation boundary: the event field is a concrete `string`, so an
|
|
410
|
+
// unauthored document surfaces the readable default rather than
|
|
411
|
+
// `undefined` to subscribers and logs.
|
|
412
|
+
const author = this.getAuthor(document) ?? UNKNOWN_CLIENT_ID;
|
|
413
|
+
return { reason: 'changed', sourceClientId: author, causedBy: author };
|
|
414
|
+
}
|
|
415
|
+
const [cause] = this.buildCauses;
|
|
416
|
+
return { reason: 'rebuilt', sourceClientId: UNKNOWN_CLIENT_ID, causedBy: this.buildCauses.size === 1 ? cause : UNKNOWN_CLIENT_ID };
|
|
343
417
|
}
|
|
344
418
|
|
|
345
|
-
/**
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
// unauthored (framework-rebuilt) document surfaces the readable default
|
|
354
|
-
// rather than `undefined` to subscribers and logs.
|
|
355
|
-
const sourceClientId = this.getAuthor(document) ?? UNKNOWN_CLIENT_ID;
|
|
356
|
-
const event: TransferUpdatedEvent<AstDocument<TAst, TDiagnostic>> = {
|
|
357
|
-
document: this.toAstDocument(document),
|
|
358
|
-
sourceClientId,
|
|
359
|
-
// No `'deleted'` arm: `DocumentBuilder.update` drops a deleted
|
|
360
|
-
// document from `LangiumDocuments` before deriving the rebuild set
|
|
361
|
-
// from it, so a deleted URI is never built and never reaches this
|
|
362
|
-
// phase listener. A subscriber needing deletions has to be told on
|
|
363
|
-
// a channel that does not require a built document.
|
|
364
|
-
reason: this.lastUpdate?.changed.some(changed => UriUtils.equals(changed, document.uri)) ? 'changed' : 'rebuilt'
|
|
365
|
-
};
|
|
366
|
-
this.tracer.with(uri).trace(`emitUpdate start: source=${sourceClientId}, reason=${event.reason}`);
|
|
367
|
-
listener(event);
|
|
368
|
-
this.tracer.with(uri).trace('emitUpdate listener returned');
|
|
369
|
-
};
|
|
370
|
-
return this.documentBuilder.onDocumentPhase(DocumentState.Validated, labelPhaseListener(emitUpdate, 'AstDocumentManager.onUpdate'));
|
|
419
|
+
/**
|
|
420
|
+
* Whether the version rule applies to `uri`: the store keeps its version,
|
|
421
|
+
* and rebuilds validate. With `updateBuildOptions.validation` off no version
|
|
422
|
+
* is ever delivered, and the rule would report every event of an open
|
|
423
|
+
* document as its author's change.
|
|
424
|
+
*/
|
|
425
|
+
protected isTracked(uri: CanonicalUri): boolean {
|
|
426
|
+
return this.keepsVersion(uri) && Boolean(this.documentBuilder.updateBuildOptions.validation);
|
|
371
427
|
}
|
|
372
428
|
|
|
373
429
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
* absence so routing consumers (`ModelService.isNonLanguageClientEdit`)
|
|
378
|
-
* test `undefined` directly rather than against a sentinel; the presentation
|
|
379
|
-
* default ({@link UNKNOWN_CLIENT_ID}) is applied at the boundary that needs a
|
|
380
|
-
* concrete value (the `onUpdate` event's `sourceClientId`, the data-server's
|
|
381
|
-
* `resolveSourceClientId`).
|
|
430
|
+
* Whether the store keeps `uri`'s version: a client opened it since its
|
|
431
|
+
* file was last deleted, or has it open still, as an editor keeps a
|
|
432
|
+
* deleted file's buffer.
|
|
382
433
|
*/
|
|
383
|
-
|
|
384
|
-
return this.
|
|
434
|
+
protected keepsVersion(uri: CanonicalUri): boolean {
|
|
435
|
+
return this.trackedUris.has(uri) || this.textDocuments.isOpen(uri);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Record that `version` of `document` was delivered, when the store tracks
|
|
440
|
+
* it. The version the listeners saw, not the document's current one: a
|
|
441
|
+
* write during them has moved that on, and marking it would report the
|
|
442
|
+
* write's own build as rebuilt.
|
|
443
|
+
*/
|
|
444
|
+
protected markDelivered(document: LangiumDocument, version: number): void {
|
|
445
|
+
const key = this.uriPolicy.canonicalUri(document.uri.toString());
|
|
446
|
+
if (this.keepsVersion(key)) {
|
|
447
|
+
this.deliveredVersions.set(key, version);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Whether the store holds for `uri` the text a build parsed into `built`,
|
|
453
|
+
* compared as the store compares a first open's text. A placeholder was
|
|
454
|
+
* parsed from nothing.
|
|
455
|
+
*/
|
|
456
|
+
protected holdsParsedText(uri: string, built: LangiumDocument): boolean {
|
|
457
|
+
const ledger = this.services.workspace.ModelLedger;
|
|
458
|
+
const root = built.parseResult.value;
|
|
459
|
+
return (
|
|
460
|
+
!ledger.isPlaceholder(root) && (ledger.textOf(root) ?? built.textDocument.getText()) === this.textDocuments.get(uri)?.getText()
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** Whether `version` of `uri` was delivered. */
|
|
465
|
+
protected isDelivered(uri: string, version: number): boolean {
|
|
466
|
+
return this.deliveredVersions.get(this.uriPolicy.canonicalUri(uri)) === version;
|
|
385
467
|
}
|
|
386
468
|
|
|
387
469
|
async open(args: OpenModelArgs): Promise<Disposable> {
|
|
388
470
|
// `open()` is the RPC-level "ensure this document is loaded" call. It is issued
|
|
389
|
-
// by a
|
|
390
|
-
//
|
|
391
|
-
//
|
|
471
|
+
// by a session opening the document, including by every additional client
|
|
472
|
+
// attaching to the same URI and the several sub-editors a composite view
|
|
473
|
+
// opens. When the document is already loaded there is nothing to
|
|
392
474
|
// do here but hand back the close-disposable — callers that want the current
|
|
393
475
|
// state read it from this method's surrounding RPC response, not from a re-build.
|
|
394
476
|
//
|
|
@@ -401,10 +483,42 @@ export class DefaultAstDocumentManager<TAst extends AstNode, TDiagnostic = unkno
|
|
|
401
483
|
// transiently breaks cross-document linking mid-rebuild (a dependent briefly
|
|
402
484
|
// seeing an `extends`/`type` reference unresolved). And because the constructor
|
|
403
485
|
// wires `onDidOpen -> this.open`, it would fire a second, identical rebuild on
|
|
404
|
-
// every first open.
|
|
486
|
+
// every first open.
|
|
487
|
+
//
|
|
488
|
+
// So an already-open `open()` records the attaching client's open and nothing
|
|
489
|
+
// else. The open is per `(uri, clientId)` and the store releases the document
|
|
490
|
+
// only once none is left, so skipping it lets the first client's close tear down a document
|
|
491
|
+
// another client is still reading. A document waiting out the release grace
|
|
492
|
+
// is still loaded: a client lost from it within its own grace attaches and
|
|
493
|
+
// keeps its text, and for any other client the attach releases it, so the
|
|
494
|
+
// open reads the file.
|
|
495
|
+
if (this.isOpen(args.uri)) {
|
|
496
|
+
this.textDocuments.attachClient(args.uri, args.clientId);
|
|
497
|
+
}
|
|
405
498
|
if (!this.isOpen(args.uri)) {
|
|
406
499
|
const textDocument = await this.createDocumentFromTextOrFileSystem(args.uri, args.languageId, args.version, args.text);
|
|
500
|
+
const creates = !this.isOpen(args.uri);
|
|
407
501
|
this.textDocuments.notifyDidOpenTextDocument({ textDocument }, args.clientId);
|
|
502
|
+
if (creates && args.text !== undefined) {
|
|
503
|
+
// Text the caller supplies was not read from the file, so no file
|
|
504
|
+
// is assumed: the document is dirty until its first save, whatever
|
|
505
|
+
// the file holds.
|
|
506
|
+
this.textDocuments.markCreated(args.uri);
|
|
507
|
+
}
|
|
508
|
+
const built = this.getDocument(args.uri);
|
|
509
|
+
if (creates && built) {
|
|
510
|
+
if (args.text === undefined && this.holdsParsedText(args.uri, built)) {
|
|
511
|
+
// The open writes nothing, so its first delivery would
|
|
512
|
+
// otherwise credit the opener, whose client then drops a
|
|
513
|
+
// dependency's relink as its own echo.
|
|
514
|
+
this.markDelivered(built, this.textDocuments.version(args.uri));
|
|
515
|
+
}
|
|
516
|
+
// Without an LSP head nothing else builds the opened text. Nothing
|
|
517
|
+
// waits on the build either, so its failure ends here.
|
|
518
|
+
this.services.workspace.VersionSyncService.syncTo(built.uri, this.textDocuments.version(args.uri))?.catch((error: unknown) =>
|
|
519
|
+
this.tracer.with(args.uri).error(`The build of the opened text failed. ${describeErrorWithStack(error)}`)
|
|
520
|
+
);
|
|
521
|
+
}
|
|
408
522
|
}
|
|
409
523
|
return Disposable.create(() => this.close(args));
|
|
410
524
|
}
|
|
@@ -424,7 +538,7 @@ export class DefaultAstDocumentManager<TAst extends AstNode, TDiagnostic = unkno
|
|
|
424
538
|
* correlate the change against subsequent build events can. Throws if the
|
|
425
539
|
* document isn't open.
|
|
426
540
|
*/
|
|
427
|
-
async update(uri: string, text: string, clientId: string): Promise<
|
|
541
|
+
async update(uri: string, text: string, clientId: string): Promise<TextVersion> {
|
|
428
542
|
if (!this.isOpen(uri)) {
|
|
429
543
|
throw new Error(`Document ${uri} hasn't been opened for updating yet`);
|
|
430
544
|
}
|
|
@@ -439,30 +553,128 @@ export class DefaultAstDocumentManager<TAst extends AstNode, TDiagnostic = unkno
|
|
|
439
553
|
* callers don't need to pass it — the manager owns content and version
|
|
440
554
|
* sequencing.
|
|
441
555
|
*
|
|
556
|
+
* The text is taken synchronously, before the save waits in the file's task
|
|
557
|
+
* queue; the compare and the write run in the queue. Taken later, a save
|
|
558
|
+
* that waits behind another writes whatever the store holds when its turn
|
|
559
|
+
* comes, edits made after the call included, and announces that text under
|
|
560
|
+
* its own client id.
|
|
561
|
+
*
|
|
562
|
+
* **The write is skipped when the file already holds that text; the
|
|
563
|
+
* notification is not.** A save announces that the content is on disk, which
|
|
564
|
+
* is true either way — so a subscriber clearing a dirty marker or reacting to
|
|
565
|
+
* a persist behaves the same, while an mtime is not moved for byte-identical
|
|
566
|
+
* content that a downstream mtime-keyed build would then read as new work.
|
|
567
|
+
*
|
|
442
568
|
* Throws if no document is open for `uri`.
|
|
443
569
|
*/
|
|
444
|
-
async save(uri: string, clientId: string): Promise<
|
|
445
|
-
|
|
570
|
+
async save(uri: string, clientId: string): Promise<TextVersion> {
|
|
571
|
+
// Canonical throughout: the write and the read that gates it must address
|
|
572
|
+
// the same file the store was keyed by, or a divergent spelling compares
|
|
573
|
+
// one file and writes another.
|
|
574
|
+
const canonical = this.uriPolicy.canonicalUri(uri);
|
|
575
|
+
const document = this.textDocuments.get(canonical);
|
|
446
576
|
if (!document) {
|
|
447
577
|
throw new Error(`Document ${uri} hasn't been opened for saving yet`);
|
|
448
578
|
}
|
|
449
579
|
const text = document.getText();
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
580
|
+
const version = document.version;
|
|
581
|
+
let supersededBy: Promise<TextVersion> | undefined;
|
|
582
|
+
const saved: Promise<TextVersion> = this.services.workspace.FileSystemTaskQueue.enqueue(canonical, async () => {
|
|
583
|
+
const newest = this.newestSaves.get(canonical);
|
|
584
|
+
if (this.coalesceSaves && newest !== saved) {
|
|
585
|
+
supersededBy = newest;
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
await this.writeSave(canonical, text, clientId);
|
|
589
|
+
})
|
|
590
|
+
.then(() => supersededBy ?? version)
|
|
591
|
+
.finally(() => {
|
|
592
|
+
if (this.newestSaves.get(canonical) === saved) {
|
|
593
|
+
this.newestSaves.delete(canonical);
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
this.newestSaves.set(canonical, saved);
|
|
597
|
+
return saved;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
async delete(uri: string, clientId: string): Promise<void> {
|
|
601
|
+
const canonical = this.uriPolicy.canonicalUri(uri);
|
|
602
|
+
const target = UriUtils.toUri(canonical);
|
|
603
|
+
// The builds below wait for a holder of the write lock, which would be
|
|
604
|
+
// waiting for this delete.
|
|
605
|
+
if (isInsideWriteLock()) {
|
|
606
|
+
throw new ReentrantWriteLockError(canonical);
|
|
607
|
+
}
|
|
608
|
+
// The mark holds one client: a second delete would share it, and the
|
|
609
|
+
// first to settle would clear it under the other.
|
|
610
|
+
if (this.deletions.has(canonical)) {
|
|
611
|
+
throw new Error(`Cannot delete ${uri}: a delete of it is under way`);
|
|
612
|
+
}
|
|
613
|
+
this.deletions.set(canonical, clientId);
|
|
614
|
+
try {
|
|
615
|
+
// A document no build has reached yet is not registered, and the
|
|
616
|
+
// deletion build would remove nothing and leave every open of it.
|
|
617
|
+
if (!this.langiumDocs.getDocument(target)) {
|
|
618
|
+
await this.documentBuilder.scheduleUpdate([target], []);
|
|
619
|
+
}
|
|
620
|
+
await this.services.workspace.FileSystemTaskQueue.enqueue(canonical, () => this.fileSystemProvider.deleteFile(target));
|
|
621
|
+
// Langium removes the document before the build's first await, so a
|
|
622
|
+
// failure is the dependents' build, and reaches no one else.
|
|
623
|
+
await this.documentBuilder
|
|
624
|
+
.scheduleUpdate([], [target])
|
|
625
|
+
.catch((error: unknown) =>
|
|
626
|
+
this.tracer.with(canonical).error(`The build after a deletion failed. ${describeErrorWithStack(error)}`)
|
|
627
|
+
);
|
|
628
|
+
// A change requested before that build started merges over the
|
|
629
|
+
// deletion, and the document lives on; the deleting client takes it as
|
|
630
|
+
// gone, so its open ends here.
|
|
631
|
+
if (this.textDocuments.isOpenInClient(canonical, clientId)) {
|
|
632
|
+
await this.close({ uri: canonical, clientId });
|
|
633
|
+
}
|
|
634
|
+
} finally {
|
|
635
|
+
this.deletions.delete(canonical);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
isDeleting(uri: string): boolean {
|
|
640
|
+
return this.deletions.has(this.uriPolicy.canonicalUri(uri));
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
attributeDeletion(uri: string): string {
|
|
644
|
+
return this.deletions.get(this.uriPolicy.canonicalUri(uri)) ?? UNKNOWN_CLIENT_ID;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/** Write `text` to `uri` unless the file already holds it, then announce the save. Runs inside the file's task queue. */
|
|
648
|
+
protected async writeSave(uri: CanonicalUri, text: string, clientId: string): Promise<void> {
|
|
649
|
+
if (!(await this.matchesDisk(uri, text))) {
|
|
650
|
+
await this.tracer.with(uri).time(
|
|
651
|
+
`Write file (${text.length} bytes, from ${clientId})`,
|
|
652
|
+
// Async write so a slow disk does not block the event loop for the duration of the fs call.
|
|
653
|
+
() => this.fileSystemProvider.writeFile(UriUtils.toUri(uri), text),
|
|
654
|
+
'debug'
|
|
655
|
+
);
|
|
656
|
+
}
|
|
456
657
|
this.textDocuments.notifyDidSaveTextDocument({ textDocument: TextDocumentIdentifier.create(uri), text }, clientId);
|
|
457
658
|
}
|
|
458
659
|
|
|
459
|
-
|
|
460
|
-
|
|
660
|
+
/**
|
|
661
|
+
* Whether the file at `uri` already holds `text`.
|
|
662
|
+
*
|
|
663
|
+
* Compared by CONTENT rather than against a remembered version, so a write
|
|
664
|
+
* from outside this server is still corrected: a version this manager already
|
|
665
|
+
* saved says nothing about what is on disk now. `false` when the file cannot
|
|
666
|
+
* be read at all, which is the answer that writes — a document whose file does
|
|
667
|
+
* not exist yet is exactly the one a first save has to create.
|
|
668
|
+
*/
|
|
669
|
+
protected async matchesDisk(uri: string, text: string): Promise<boolean> {
|
|
670
|
+
return this.fileSystemProvider
|
|
671
|
+
.readFile(UriUtils.toUri(uri))
|
|
672
|
+
.then(onDisk => onDisk === text)
|
|
673
|
+
.catch(() => false);
|
|
461
674
|
}
|
|
462
675
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
return this.lastUpdate?.changed.some(changed => this.uriPolicy.canonicalUri(changed) === canonical) ?? false;
|
|
676
|
+
isOpen(uri: string): boolean {
|
|
677
|
+
return !!this.textDocuments.get(uri);
|
|
466
678
|
}
|
|
467
679
|
|
|
468
680
|
/**
|
|
@@ -482,15 +694,30 @@ export class DefaultAstDocumentManager<TAst extends AstNode, TDiagnostic = unkno
|
|
|
482
694
|
version = 0,
|
|
483
695
|
text?: string
|
|
484
696
|
): Promise<TextDocumentItem> {
|
|
485
|
-
|
|
697
|
+
// Read in the file's task queue: a read beside a queued save of the file
|
|
698
|
+
// returns the text from before it, and the document then opens on that.
|
|
699
|
+
return {
|
|
700
|
+
uri,
|
|
701
|
+
languageId,
|
|
702
|
+
version,
|
|
703
|
+
text:
|
|
704
|
+
text ??
|
|
705
|
+
(await this.services.workspace.FileSystemTaskQueue.enqueue(uri, () => this.fileSystemProvider.readFile(UriUtils.toUri(uri))))
|
|
706
|
+
};
|
|
486
707
|
}
|
|
487
708
|
|
|
488
709
|
/**
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* {@link AstDocument.from}, the shared LangiumDocument→envelope projection.
|
|
710
|
+
* Events and the model service's snapshot reads both come through here, so
|
|
711
|
+
* an override that re-shapes the document re-shapes both.
|
|
492
712
|
*/
|
|
493
|
-
|
|
494
|
-
|
|
713
|
+
toAstDocument(document: LangiumDocument): AstDocument<TAst, TDiagnostic> {
|
|
714
|
+
const uri = document.textDocument.uri;
|
|
715
|
+
const root = document.parseResult.value as TAst;
|
|
716
|
+
const ledger = this.services.workspace.ModelLedger;
|
|
717
|
+
const version = ledger.versionOf(root);
|
|
718
|
+
if (version === UNRECORDED_VERSION && !ledger.isPlaceholder(root)) {
|
|
719
|
+
this.tracer.with(uri).warn('No model version recorded for the root: it was built outside the document factory');
|
|
720
|
+
}
|
|
721
|
+
return AstDocument.create<TAst, TDiagnostic>(uri, version, root, document.diagnostics as TDiagnostic[] | undefined);
|
|
495
722
|
}
|
|
496
723
|
}
|