@hydranium/core 1.0.0-next.23 → 1.0.0-next.232
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 +21 -13
- package/lib/documents/ast-document-manager.d.ts +219 -122
- package/lib/documents/ast-document-manager.d.ts.map +1 -1
- package/lib/documents/ast-document-manager.js +241 -130
- package/lib/documents/ast-document-manager.js.map +1 -1
- package/lib/documents/client-ids.d.ts +5 -19
- package/lib/documents/client-ids.d.ts.map +1 -1
- package/lib/documents/client-ids.js +5 -19
- package/lib/documents/client-ids.js.map +1 -1
- package/lib/documents/client-session-errors.d.ts +15 -0
- package/lib/documents/client-session-errors.d.ts.map +1 -0
- package/lib/documents/client-session-errors.js +15 -0
- package/lib/documents/client-session-errors.js.map +1 -0
- package/lib/documents/client-session-registry.d.ts +146 -0
- package/lib/documents/client-session-registry.d.ts.map +1 -0
- package/lib/documents/client-session-registry.js +207 -0
- package/lib/documents/client-session-registry.js.map +1 -0
- package/lib/documents/dirty-state-tracker.d.ts +79 -0
- package/lib/documents/dirty-state-tracker.d.ts.map +1 -0
- package/lib/documents/dirty-state-tracker.js +69 -0
- package/lib/documents/dirty-state-tracker.js.map +1 -0
- package/lib/documents/document-release-handler.d.ts +179 -0
- package/lib/documents/document-release-handler.d.ts.map +1 -0
- package/lib/documents/document-release-handler.js +283 -0
- package/lib/documents/document-release-handler.js.map +1 -0
- package/lib/documents/document-release-scheduler.d.ts +67 -0
- package/lib/documents/document-release-scheduler.d.ts.map +1 -0
- package/lib/documents/document-release-scheduler.js +80 -0
- package/lib/documents/document-release-scheduler.js.map +1 -0
- package/lib/documents/file-system-task-queue.d.ts +49 -0
- package/lib/documents/file-system-task-queue.d.ts.map +1 -0
- package/lib/documents/file-system-task-queue.js +34 -0
- package/lib/documents/file-system-task-queue.js.map +1 -0
- package/lib/documents/hydranium-text-documents.d.ts +399 -282
- package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
- package/lib/documents/hydranium-text-documents.js +816 -483
- package/lib/documents/hydranium-text-documents.js.map +1 -1
- package/lib/documents/index.d.ts +10 -2
- package/lib/documents/index.d.ts.map +1 -1
- package/lib/documents/index.js +10 -2
- package/lib/documents/index.js.map +1 -1
- package/lib/documents/language-client-shadow.d.ts +218 -0
- package/lib/documents/language-client-shadow.d.ts.map +1 -0
- package/lib/documents/language-client-shadow.js +283 -0
- package/lib/documents/language-client-shadow.js.map +1 -0
- package/lib/documents/model-ledger.d.ts +47 -0
- package/lib/documents/model-ledger.d.ts.map +1 -0
- package/lib/documents/model-ledger.js +30 -0
- package/lib/documents/model-ledger.js.map +1 -0
- package/lib/documents/text-ledger.d.ts +64 -0
- package/lib/documents/text-ledger.d.ts.map +1 -0
- package/lib/documents/text-ledger.js +63 -0
- package/lib/documents/text-ledger.js.map +1 -0
- package/lib/documents/version-sync-service.d.ts +134 -0
- package/lib/documents/version-sync-service.d.ts.map +1 -0
- package/lib/documents/version-sync-service.js +171 -0
- package/lib/documents/version-sync-service.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -1
- package/lib/langium/ast-extension/ast-extension-service.d.ts.map +1 -1
- package/lib/langium/ast-extension/ast-extension-service.js.map +1 -1
- package/lib/langium/ast-extension/ast-node-builder.d.ts +32 -9
- package/lib/langium/ast-extension/ast-node-builder.d.ts.map +1 -1
- package/lib/langium/ast-extension/ast-node-builder.js +60 -22
- package/lib/langium/ast-extension/ast-node-builder.js.map +1 -1
- package/lib/langium/bootstrap.d.ts +23 -16
- package/lib/langium/bootstrap.d.ts.map +1 -1
- package/lib/langium/bootstrap.js +66 -28
- package/lib/langium/bootstrap.js.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass-service.d.ts.map +1 -1
- package/lib/langium/build-phase-pass/build-phase-pass-service.js.map +1 -1
- package/lib/langium/composite-ast-reflection.d.ts +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/hydranium-langium-profiler.d.ts.map +1 -1
- package/lib/langium/diagnostics/hydranium-langium-profiler.js.map +1 -1
- package/lib/langium/diagnostics/logger.d.ts +10 -3
- package/lib/langium/diagnostics/logger.d.ts.map +1 -1
- package/lib/langium/diagnostics/logger.js +12 -5
- package/lib/langium/diagnostics/logger.js.map +1 -1
- package/lib/langium/diagnostics/lsp-logger.d.ts +17 -0
- package/lib/langium/diagnostics/lsp-logger.d.ts.map +1 -1
- package/lib/langium/diagnostics/lsp-logger.js +57 -16
- package/lib/langium/diagnostics/lsp-logger.js.map +1 -1
- package/lib/langium/diagnostics/server-tracer.d.ts.map +1 -1
- package/lib/langium/diagnostics/server-tracer.js.map +1 -1
- package/lib/langium/document-builder/build-pipeline-integration.d.ts +21 -1
- package/lib/langium/document-builder/build-pipeline-integration.d.ts.map +1 -1
- package/lib/langium/document-builder/build-pipeline-integration.js +32 -5
- package/lib/langium/document-builder/build-pipeline-integration.js.map +1 -1
- package/lib/langium/document-builder/build-session.d.ts +93 -0
- package/lib/langium/document-builder/build-session.d.ts.map +1 -0
- package/lib/langium/document-builder/build-session.js +72 -0
- package/lib/langium/document-builder/build-session.js.map +1 -0
- package/lib/langium/document-builder/document-builder.d.ts +401 -29
- package/lib/langium/document-builder/document-builder.d.ts.map +1 -1
- package/lib/langium/document-builder/document-builder.js +698 -61
- package/lib/langium/document-builder/document-builder.js.map +1 -1
- package/lib/langium/document-builder/index.d.ts +1 -0
- package/lib/langium/document-builder/index.d.ts.map +1 -1
- package/lib/langium/document-builder/index.js +1 -0
- package/lib/langium/document-builder/index.js.map +1 -1
- package/lib/langium/documentation/comment-provider.d.ts.map +1 -1
- package/lib/langium/documentation/comment-provider.js.map +1 -1
- package/lib/langium/integration-services.d.ts +61 -19
- package/lib/langium/integration-services.d.ts.map +1 -1
- package/lib/langium/integration-services.js +10 -5
- package/lib/langium/integration-services.js.map +1 -1
- package/lib/langium/integrity/integrity-rule.d.ts +16 -8
- package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-rule.js.map +1 -1
- package/lib/langium/integrity/integrity-service.d.ts +81 -24
- package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-service.js +264 -57
- package/lib/langium/integrity/integrity-service.js.map +1 -1
- package/lib/langium/keys/containment.d.ts +64 -0
- package/lib/langium/keys/containment.d.ts.map +1 -0
- package/lib/langium/keys/containment.js +53 -0
- package/lib/langium/keys/containment.js.map +1 -0
- package/lib/langium/keys/index.d.ts +1 -0
- package/lib/langium/keys/index.d.ts.map +1 -1
- package/lib/langium/keys/index.js +1 -0
- package/lib/langium/keys/index.js.map +1 -1
- package/lib/langium/keys/name-based-key-provider.d.ts +4 -0
- package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/name-based-key-provider.js +4 -0
- package/lib/langium/keys/name-based-key-provider.js.map +1 -1
- package/lib/langium/keys/positional-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/positional-key-provider.js.map +1 -1
- package/lib/langium/labeling/label-provider.d.ts.map +1 -1
- package/lib/langium/labeling/label-provider.js.map +1 -1
- package/lib/langium/language-module.d.ts +29 -4
- package/lib/langium/language-module.d.ts.map +1 -1
- package/lib/langium/language-module.js +18 -4
- package/lib/langium/language-module.js.map +1 -1
- package/lib/langium/model-service/client-session.d.ts +343 -0
- package/lib/langium/model-service/client-session.d.ts.map +1 -0
- package/lib/langium/model-service/client-session.js +411 -0
- package/lib/langium/model-service/client-session.js.map +1 -0
- package/lib/langium/model-service/index.d.ts +2 -0
- package/lib/langium/model-service/index.d.ts.map +1 -1
- package/lib/langium/model-service/index.js +2 -0
- package/lib/langium/model-service/index.js.map +1 -1
- package/lib/langium/model-service/model-events.d.ts +61 -0
- package/lib/langium/model-service/model-events.d.ts.map +1 -0
- package/lib/langium/model-service/model-events.js +10 -0
- package/lib/langium/model-service/model-events.js.map +1 -0
- package/lib/langium/model-service/model-service.d.ts +432 -282
- package/lib/langium/model-service/model-service.d.ts.map +1 -1
- package/lib/langium/model-service/model-service.js +504 -438
- package/lib/langium/model-service/model-service.js.map +1 -1
- package/lib/langium/module.d.ts +157 -35
- package/lib/langium/module.d.ts.map +1 -1
- package/lib/langium/module.js +52 -35
- package/lib/langium/module.js.map +1 -1
- package/lib/langium/naming/name-provider.d.ts +25 -4
- package/lib/langium/naming/name-provider.d.ts.map +1 -1
- package/lib/langium/naming/name-provider.js +2 -1
- package/lib/langium/naming/name-provider.js.map +1 -1
- package/lib/langium/naming/name-separator-validation.d.ts +23 -0
- package/lib/langium/naming/name-separator-validation.d.ts.map +1 -1
- package/lib/langium/naming/name-separator-validation.js +30 -1
- package/lib/langium/naming/name-separator-validation.js.map +1 -1
- package/lib/langium/project/abstract-project-manager.d.ts.map +1 -1
- package/lib/langium/project/abstract-project-manager.js +9 -2
- package/lib/langium/project/abstract-project-manager.js.map +1 -1
- package/lib/langium/project/project-change-event.d.ts +2 -2
- package/lib/langium/project/single-project-manager.d.ts.map +1 -1
- package/lib/langium/project/single-project-manager.js.map +1 -1
- package/lib/langium/residency/cst-residency-service.d.ts +31 -11
- package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
- package/lib/langium/residency/cst-residency-service.js +23 -57
- package/lib/langium/residency/cst-residency-service.js.map +1 -1
- package/lib/langium/scope/ast-node-description-provider.d.ts.map +1 -1
- package/lib/langium/scope/ast-node-description-provider.js.map +1 -1
- package/lib/langium/scope/hydranium-scope-computation.d.ts.map +1 -1
- package/lib/langium/scope/hydranium-scope-computation.js.map +1 -1
- package/lib/langium/scope/hydranium-scope-provider.d.ts +48 -13
- package/lib/langium/scope/hydranium-scope-provider.d.ts.map +1 -1
- package/lib/langium/scope/hydranium-scope-provider.js +56 -20
- package/lib/langium/scope/hydranium-scope-provider.js.map +1 -1
- package/lib/langium/scope/reference-builder.d.ts.map +1 -1
- package/lib/langium/scope/reference-builder.js.map +1 -1
- package/lib/langium/scope/reference-candidate-provider.d.ts.map +1 -1
- package/lib/langium/scope/reference-candidate-provider.js.map +1 -1
- package/lib/langium/scope/scope-extension-service.d.ts.map +1 -1
- package/lib/langium/scope/scope-extension-service.js.map +1 -1
- package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
- package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/abstract-serializer.js +12 -21
- package/lib/langium/serialization/abstract-serializer.js.map +1 -1
- package/lib/langium/serialization/json-serializer.d.ts +1 -1
- package/lib/langium/serialization/json-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/json-serializer.js.map +1 -1
- package/lib/langium/serialization/yaml-serializer.d.ts.map +1 -1
- package/lib/langium/serialization/yaml-serializer.js.map +1 -1
- package/lib/langium/service-registry.d.ts +29 -1
- package/lib/langium/service-registry.d.ts.map +1 -1
- package/lib/langium/service-registry.js +37 -0
- package/lib/langium/service-registry.js.map +1 -1
- package/lib/langium/shared-services.d.ts +23 -6
- package/lib/langium/shared-services.d.ts.map +1 -1
- package/lib/langium/shared-services.js.map +1 -1
- package/lib/langium/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 +77 -26
- package/lib/langium/transfer/transfer-encoder.d.ts.map +1 -1
- package/lib/langium/transfer/transfer-encoder.js +46 -24
- package/lib/langium/transfer/transfer-encoder.js.map +1 -1
- package/lib/langium/trivia/comment-preserver.d.ts +423 -0
- package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/comment-preserver.js +906 -0
- package/lib/langium/trivia/comment-preserver.js.map +1 -0
- package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
- package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/document-ending-preserver.js +48 -0
- package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
- package/lib/langium/trivia/index.d.ts +14 -0
- package/lib/langium/trivia/index.d.ts.map +1 -0
- package/lib/langium/trivia/index.js +14 -0
- package/lib/langium/trivia/index.js.map +1 -0
- package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
- package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-contribution.js +10 -0
- package/lib/langium/trivia/trivia-contribution.js.map +1 -0
- package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
- package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-preserver.js +10 -0
- package/lib/langium/trivia/trivia-preserver.js.map +1 -0
- package/lib/langium/trivia/trivia-service.d.ts +70 -0
- package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
- package/lib/langium/trivia/trivia-service.js +56 -0
- package/lib/langium/trivia/trivia-service.js.map +1 -0
- package/lib/langium/update-rewrite/normalize-empty-strings.d.ts.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.d.ts.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite-service.js.map +1 -1
- package/lib/langium/update-rewrite/update-rewrite.d.ts +1 -1
- package/lib/langium/validation/document-validator.d.ts +294 -10
- package/lib/langium/validation/document-validator.d.ts.map +1 -1
- package/lib/langium/validation/document-validator.js +448 -5
- package/lib/langium/validation/document-validator.js.map +1 -1
- package/lib/langium/validation/validation-contribution-collector.d.ts +9 -1
- package/lib/langium/validation/validation-contribution-collector.d.ts.map +1 -1
- package/lib/langium/validation/validation-contribution-collector.js +1 -1
- package/lib/langium/validation/validation-contribution-collector.js.map +1 -1
- package/lib/langium/workspace/document-uri-policy.d.ts +18 -14
- package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
- package/lib/langium/workspace/document-uri-policy.js +10 -9
- package/lib/langium/workspace/document-uri-policy.js.map +1 -1
- package/lib/langium/workspace/file-not-found.d.ts +23 -0
- package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
- package/lib/langium/workspace/file-not-found.js +31 -0
- package/lib/langium/workspace/file-not-found.js.map +1 -0
- package/lib/langium/workspace/file-system-provider.d.ts +135 -9
- package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/file-system-provider.js +93 -14
- package/lib/langium/workspace/file-system-provider.js.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts +56 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-langium-document-factory.js +79 -0
- package/lib/langium/workspace/hydranium-langium-document-factory.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts +43 -1
- package/lib/langium/workspace/hydranium-workspace-lock.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js +58 -1
- package/lib/langium/workspace/hydranium-workspace-lock.js.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts +82 -9
- package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
- package/lib/langium/workspace/hydranium-workspace-manager.js +128 -10
- package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts +26 -3
- package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/in-memory-file-system-provider.js +41 -15
- package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
- package/lib/langium/workspace/index-manager.d.ts.map +1 -1
- package/lib/langium/workspace/index-manager.js.map +1 -1
- package/lib/langium/workspace/index.d.ts +1 -0
- package/lib/langium/workspace/index.d.ts.map +1 -1
- package/lib/langium/workspace/index.js +1 -0
- package/lib/langium/workspace/index.js.map +1 -1
- package/lib/langium/workspace/initialize-workspace.d.ts +31 -2
- package/lib/langium/workspace/initialize-workspace.d.ts.map +1 -1
- package/lib/langium/workspace/initialize-workspace.js +13 -5
- package/lib/langium/workspace/initialize-workspace.js.map +1 -1
- package/lib/langium/workspace/langium-documents.d.ts +86 -17
- package/lib/langium/workspace/langium-documents.d.ts.map +1 -1
- package/lib/langium/workspace/langium-documents.js +101 -29
- package/lib/langium/workspace/langium-documents.js.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.d.ts +1 -8
- package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
- package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
- package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
- package/lib/{documents → langium/workspace}/self-save-registry.d.ts +38 -7
- package/lib/langium/workspace/self-save-registry.d.ts.map +1 -0
- package/lib/{documents → langium/workspace}/self-save-registry.js +29 -16
- package/lib/langium/workspace/self-save-registry.js.map +1 -0
- package/lib/langium/workspace/virtual-document.d.ts +48 -15
- package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
- package/lib/langium/workspace/virtual-document.js +78 -18
- package/lib/langium/workspace/virtual-document.js.map +1 -1
- package/lib/langium/workspace/write-lock-scope.d.ts +20 -10
- package/lib/langium/workspace/write-lock-scope.d.ts.map +1 -1
- package/lib/langium/workspace/write-lock-scope.js +12 -4
- package/lib/langium/workspace/write-lock-scope.js.map +1 -1
- package/lib/locale/index.d.ts +10 -0
- package/lib/locale/index.d.ts.map +1 -0
- package/lib/locale/index.js +10 -0
- package/lib/locale/index.js.map +1 -0
- package/lib/locale/server-locale.d.ts +73 -0
- package/lib/locale/server-locale.d.ts.map +1 -0
- package/lib/locale/server-locale.js +61 -0
- package/lib/locale/server-locale.js.map +1 -0
- package/lib/lsp/completion/hydranium-completion-provider.d.ts +44 -2
- package/lib/lsp/completion/hydranium-completion-provider.d.ts.map +1 -1
- package/lib/lsp/completion/hydranium-completion-provider.js +68 -0
- package/lib/lsp/completion/hydranium-completion-provider.js.map +1 -1
- package/lib/lsp/connection-features.d.ts +23 -0
- package/lib/lsp/connection-features.d.ts.map +1 -0
- package/lib/lsp/connection-features.js +60 -0
- package/lib/lsp/connection-features.js.map +1 -0
- package/lib/lsp/diagnostics-connection.d.ts +27 -0
- package/lib/lsp/diagnostics-connection.d.ts.map +1 -0
- package/lib/lsp/diagnostics-connection.js +53 -0
- package/lib/lsp/diagnostics-connection.js.map +1 -0
- package/lib/lsp/hydranium-document-update-handler.d.ts +92 -81
- package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.js +153 -99
- package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
- package/lib/lsp/index.d.ts +3 -1
- package/lib/lsp/index.d.ts.map +1 -1
- package/lib/lsp/index.js +3 -1
- package/lib/lsp/index.js.map +1 -1
- package/lib/lsp/lsp-latency.d.ts +39 -0
- package/lib/lsp/lsp-latency.d.ts.map +1 -0
- package/lib/lsp/lsp-latency.js +58 -0
- package/lib/lsp/lsp-latency.js.map +1 -0
- package/lib/lsp/semantic-token-provider.d.ts +34 -1
- package/lib/lsp/semantic-token-provider.d.ts.map +1 -1
- package/lib/lsp/semantic-token-provider.js +55 -8
- package/lib/lsp/semantic-token-provider.js.map +1 -1
- package/lib/lsp/shared-module.d.ts +4 -8
- package/lib/lsp/shared-module.d.ts.map +1 -1
- package/lib/lsp/shared-module.js.map +1 -1
- package/lib/lsp/start-language-server.d.ts +8 -7
- package/lib/lsp/start-language-server.d.ts.map +1 -1
- package/lib/lsp/start-language-server.js +13 -7
- package/lib/lsp/start-language-server.js.map +1 -1
- package/lib/messages/carriers.d.ts +54 -0
- package/lib/messages/carriers.d.ts.map +1 -0
- package/lib/messages/carriers.js +62 -0
- package/lib/messages/carriers.js.map +1 -0
- package/lib/messages/index.d.ts +25 -0
- package/lib/messages/index.d.ts.map +1 -0
- package/lib/messages/index.js +25 -0
- package/lib/messages/index.js.map +1 -0
- package/lib/messages/renderer.d.ts +142 -0
- package/lib/messages/renderer.d.ts.map +1 -0
- package/lib/messages/renderer.js +165 -0
- package/lib/messages/renderer.js.map +1 -0
- package/lib/node/event-loop-monitor.js.map +1 -1
- package/lib/node/heap-ceiling.d.ts +61 -0
- package/lib/node/heap-ceiling.d.ts.map +1 -0
- package/lib/node/heap-ceiling.js +72 -0
- package/lib/node/heap-ceiling.js.map +1 -0
- package/lib/node/index.d.ts +1 -1
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +1 -1
- package/lib/node/index.js.map +1 -1
- package/lib/node/latency-from-env.d.ts +1 -1
- package/lib/node/latency-from-env.js +1 -1
- package/lib/node/lint-grammar.js.map +1 -1
- package/lib/node/measure-memory.d.ts.map +1 -1
- package/lib/node/measure-memory.js +1 -0
- package/lib/node/measure-memory.js.map +1 -1
- package/lib/node/memory-monitor.js.map +1 -1
- package/lib/node/node-file-system-provider.d.ts +41 -6
- package/lib/node/node-file-system-provider.d.ts.map +1 -1
- package/lib/node/node-file-system-provider.js +109 -49
- package/lib/node/node-file-system-provider.js.map +1 -1
- package/lib/node/profile-capture.d.ts +8 -2
- package/lib/node/profile-capture.d.ts.map +1 -1
- package/lib/node/profile-capture.js +1 -1
- package/lib/node/profile-capture.js.map +1 -1
- package/lib/node/profile-digest.js.map +1 -1
- package/lib/node/profiling-run.d.ts +13 -3
- package/lib/node/profiling-run.d.ts.map +1 -1
- package/lib/node/profiling-run.js +17 -8
- package/lib/node/profiling-run.js.map +1 -1
- package/lib/node/rename-over-open-readers.d.ts +52 -0
- package/lib/node/rename-over-open-readers.d.ts.map +1 -0
- package/lib/node/rename-over-open-readers.js +66 -0
- package/lib/node/rename-over-open-readers.js.map +1 -0
- package/lib/node/socket-launcher.d.ts +20 -4
- package/lib/node/socket-launcher.d.ts.map +1 -1
- package/lib/node/socket-launcher.js +5 -4
- package/lib/node/socket-launcher.js.map +1 -1
- package/lib/node/stdio-launcher.d.ts +6 -5
- package/lib/node/stdio-launcher.d.ts.map +1 -1
- package/lib/node/stdio-launcher.js +2 -2
- package/lib/node/stdio-launcher.js.map +1 -1
- package/lib/testing/document-uri-policy-conformance.js.map +1 -1
- package/lib/testing/fake-description.js.map +1 -1
- package/lib/testing/fake-document.d.ts +16 -4
- package/lib/testing/fake-document.d.ts.map +1 -1
- package/lib/testing/fake-document.js +18 -3
- package/lib/testing/fake-document.js.map +1 -1
- package/lib/testing/index.d.ts +1 -1
- package/lib/testing/index.d.ts.map +1 -1
- package/lib/testing/index.js +2 -1
- package/lib/testing/index.js.map +1 -1
- package/lib/testing/langium-test-helpers.d.ts.map +1 -1
- package/lib/testing/langium-test-helpers.js +1 -0
- package/lib/testing/langium-test-helpers.js.map +1 -1
- package/lib/testing/make-noop-language-services.js.map +1 -1
- package/lib/testing/make-noop-shared-services.d.ts +14 -0
- package/lib/testing/make-noop-shared-services.d.ts.map +1 -1
- package/lib/testing/make-noop-shared-services.js +28 -2
- package/lib/testing/make-noop-shared-services.js.map +1 -1
- package/lib/testing/make-test-services.d.ts +72 -14
- package/lib/testing/make-test-services.d.ts.map +1 -1
- package/lib/testing/make-test-services.js +42 -10
- package/lib/testing/make-test-services.js.map +1 -1
- package/lib/testing/make-test-tracer.d.ts +12 -0
- package/lib/testing/make-test-tracer.d.ts.map +1 -1
- package/lib/testing/make-test-tracer.js +13 -0
- package/lib/testing/make-test-tracer.js.map +1 -1
- package/lib/testing/node/golden-corpus.js.map +1 -1
- package/lib/testing/node/index.d.ts +1 -0
- package/lib/testing/node/index.d.ts.map +1 -1
- package/lib/testing/node/index.js +1 -0
- package/lib/testing/node/index.js.map +1 -1
- package/lib/testing/node/lsp-harness.d.ts.map +1 -1
- package/lib/testing/node/lsp-harness.js +2 -0
- package/lib/testing/node/lsp-harness.js.map +1 -1
- package/lib/testing/node/lsp-server-connection.d.ts +11 -3
- package/lib/testing/node/lsp-server-connection.d.ts.map +1 -1
- package/lib/testing/node/lsp-server-connection.js +43 -10
- package/lib/testing/node/lsp-server-connection.js.map +1 -1
- package/lib/testing/node/scratch-workspace.d.ts.map +1 -1
- package/lib/testing/node/scratch-workspace.js +10 -5
- package/lib/testing/node/scratch-workspace.js.map +1 -1
- package/lib/testing/node/spawned-server.d.ts +14 -0
- package/lib/testing/node/spawned-server.d.ts.map +1 -1
- package/lib/testing/node/spawned-server.js +34 -2
- package/lib/testing/node/spawned-server.js.map +1 -1
- package/lib/testing/node/unhandled-rejections.d.ts +20 -0
- package/lib/testing/node/unhandled-rejections.d.ts.map +1 -0
- package/lib/testing/node/unhandled-rejections.js +32 -0
- package/lib/testing/node/unhandled-rejections.js.map +1 -0
- package/lib/testing/playwright/browser-capture-bridge.js.map +1 -1
- package/lib/testing/playwright/e2e-profiling.js.map +1 -1
- package/lib/testing/playwright/flaky-network-proxy.d.ts +76 -0
- package/lib/testing/playwright/flaky-network-proxy.d.ts.map +1 -0
- package/lib/testing/playwright/flaky-network-proxy.js +164 -0
- package/lib/testing/playwright/flaky-network-proxy.js.map +1 -0
- package/lib/testing/playwright/index.d.ts +1 -0
- package/lib/testing/playwright/index.d.ts.map +1 -1
- package/lib/testing/playwright/index.js +1 -0
- package/lib/testing/playwright/index.js.map +1 -1
- package/lib/testing/playwright/server-log-capture.d.ts +24 -8
- package/lib/testing/playwright/server-log-capture.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-capture.js +27 -6
- package/lib/testing/playwright/server-log-capture.js.map +1 -1
- package/lib/testing/playwright/server-log-rename-reporter.d.ts.map +1 -1
- package/lib/testing/playwright/server-log-rename-reporter.js +10 -1
- package/lib/testing/playwright/server-log-rename-reporter.js.map +1 -1
- package/lib/testing/run-update-pipeline.d.ts +4 -4
- package/lib/testing/run-update-pipeline.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.d.ts +11 -52
- package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.js +24 -65
- package/lib/testing/stub-ast-document-manager.js.map +1 -1
- package/lib/testing/stub-document-builder.d.ts +26 -11
- package/lib/testing/stub-document-builder.d.ts.map +1 -1
- package/lib/testing/stub-document-builder.js +78 -5
- package/lib/testing/stub-document-builder.js.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.d.ts +33 -10
- package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.js +115 -16
- package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
- package/lib/testing/stub-index-manager.js.map +1 -1
- package/lib/testing/stub-langium-documents.d.ts +3 -2
- package/lib/testing/stub-langium-documents.d.ts.map +1 -1
- package/lib/testing/stub-langium-documents.js.map +1 -1
- package/lib/testing/stub-model-service.d.ts +7 -6
- package/lib/testing/stub-model-service.d.ts.map +1 -1
- package/lib/testing/stub-model-service.js +4 -4
- package/lib/testing/stub-model-service.js.map +1 -1
- package/lib/testing/stub-project-manager.js.map +1 -1
- package/lib/testing/stub-self-save-registry.d.ts +1 -1
- package/lib/testing/stub-self-save-registry.d.ts.map +1 -1
- package/lib/testing/stub-service-registry.d.ts +1 -1
- package/lib/testing/stub-service-registry.js.map +1 -1
- package/lib/testing/stub-writable-file-system.d.ts +1 -1
- package/lib/testing/stub-writable-file-system.d.ts.map +1 -1
- package/lib/util/connection-liveness.d.ts +7 -6
- package/lib/util/connection-liveness.d.ts.map +1 -1
- package/lib/util/connection-liveness.js +35 -14
- package/lib/util/connection-liveness.js.map +1 -1
- package/lib/util/environment.d.ts.map +1 -1
- package/lib/util/environment.js.map +1 -1
- package/lib/util/registry.d.ts.map +1 -1
- package/package.json +32 -48
- package/src/documents/ast-document-manager.ts +379 -231
- package/src/documents/client-ids.ts +5 -22
- package/src/documents/client-session-errors.ts +24 -0
- package/src/documents/client-session-registry.ts +262 -0
- package/src/documents/dirty-state-tracker.ts +130 -0
- package/src/documents/document-release-handler.ts +365 -0
- package/src/documents/document-release-scheduler.ts +121 -0
- package/src/documents/file-system-task-queue.ts +68 -0
- package/src/documents/hydranium-text-documents.ts +931 -595
- package/src/documents/index.ts +10 -2
- package/src/documents/language-client-shadow.ts +451 -0
- package/src/documents/model-ledger.ts +66 -0
- package/src/documents/text-ledger.ts +112 -0
- package/src/documents/version-sync-service.ts +267 -0
- package/src/index.ts +8 -0
- package/src/langium/ast-extension/ast-node-builder.ts +66 -22
- package/src/langium/bootstrap.ts +66 -28
- 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/logger.ts +12 -5
- package/src/langium/diagnostics/lsp-logger.ts +59 -15
- package/src/langium/document-builder/build-pipeline-integration.ts +50 -5
- package/src/langium/document-builder/build-session.ts +87 -0
- package/src/langium/document-builder/document-builder.ts +825 -59
- package/src/langium/document-builder/index.ts +1 -0
- package/src/langium/integration-services.ts +83 -24
- package/src/langium/integrity/integrity-rule.ts +16 -8
- package/src/langium/integrity/integrity-service.ts +287 -62
- package/src/langium/keys/containment.ts +87 -0
- package/src/langium/keys/index.ts +1 -0
- package/src/langium/keys/name-based-key-provider.ts +4 -0
- package/src/langium/language-module.ts +48 -7
- package/src/langium/model-service/client-session.ts +644 -0
- package/src/langium/model-service/index.ts +2 -0
- package/src/langium/model-service/model-events.ts +75 -0
- package/src/langium/model-service/model-service.ts +790 -468
- package/src/langium/module.ts +210 -64
- package/src/langium/naming/name-provider.ts +27 -5
- package/src/langium/naming/name-separator-validation.ts +34 -5
- package/src/langium/project/abstract-project-manager.ts +9 -1
- package/src/langium/project/project-change-event.ts +2 -2
- package/src/langium/residency/cst-residency-service.ts +46 -15
- package/src/langium/scope/hydranium-scope-provider.ts +60 -22
- package/src/langium/serialization/abstract-serializer.ts +13 -32
- package/src/langium/service-registry.ts +41 -2
- package/src/langium/shared-services.ts +27 -6
- package/src/langium/single-langium-copy.ts +42 -0
- package/src/langium/transfer/transfer-encoder.ts +104 -37
- package/src/langium/trivia/comment-preserver.ts +1100 -0
- package/src/langium/trivia/document-ending-preserver.ts +55 -0
- package/src/langium/trivia/index.ts +14 -0
- package/src/langium/trivia/trivia-contribution.ts +39 -0
- package/src/langium/trivia/trivia-preserver.ts +54 -0
- package/src/langium/trivia/trivia-service.ts +99 -0
- package/src/langium/update-rewrite/update-rewrite.ts +1 -1
- package/src/langium/validation/document-validator.ts +537 -11
- package/src/langium/validation/validation-contribution-collector.ts +10 -1
- package/src/langium/workspace/document-uri-policy.ts +18 -14
- package/src/langium/workspace/file-not-found.ts +35 -0
- package/src/langium/workspace/file-system-provider.ts +205 -17
- package/src/langium/workspace/hydranium-langium-document-factory.ts +117 -0
- package/src/langium/workspace/hydranium-workspace-lock.ts +86 -2
- package/src/langium/workspace/hydranium-workspace-manager.ts +154 -14
- package/src/langium/workspace/in-memory-file-system-provider.ts +48 -17
- package/src/langium/workspace/index.ts +1 -0
- package/src/langium/workspace/initialize-workspace.ts +43 -5
- package/src/langium/workspace/langium-documents.ts +124 -33
- package/src/langium/workspace/persistent-file-system-provider.ts +1 -8
- package/src/{documents → langium/workspace}/self-save-registry.ts +54 -15
- package/src/langium/workspace/virtual-document.ts +96 -19
- package/src/langium/workspace/write-lock-scope.ts +24 -11
- package/src/locale/index.ts +10 -0
- package/src/locale/server-locale.ts +86 -0
- package/src/lsp/completion/hydranium-completion-provider.ts +82 -2
- package/src/lsp/connection-features.ts +67 -0
- package/src/lsp/diagnostics-connection.ts +56 -0
- package/src/lsp/hydranium-document-update-handler.ts +187 -108
- package/src/lsp/index.ts +3 -1
- package/src/lsp/lsp-latency.ts +62 -0
- package/src/lsp/semantic-token-provider.ts +74 -7
- package/src/lsp/shared-module.ts +4 -8
- package/src/lsp/start-language-server.ts +13 -7
- package/src/messages/carriers.ts +78 -0
- package/src/messages/index.ts +36 -0
- package/src/messages/renderer.ts +212 -0
- package/src/node/heap-ceiling.ts +108 -0
- package/src/node/index.ts +1 -1
- package/src/node/latency-from-env.ts +1 -1
- package/src/node/measure-memory.ts +1 -0
- package/src/node/node-file-system-provider.ts +124 -53
- package/src/node/profile-capture.ts +9 -3
- package/src/node/profiling-run.ts +30 -8
- package/src/node/rename-over-open-readers.ts +78 -0
- package/src/node/socket-launcher.ts +24 -8
- package/src/node/stdio-launcher.ts +8 -7
- package/src/testing/fake-document.ts +24 -5
- package/src/testing/index.ts +2 -1
- package/src/testing/langium-test-helpers.ts +1 -0
- package/src/testing/make-noop-shared-services.ts +50 -2
- package/src/testing/make-test-services.ts +125 -31
- package/src/testing/make-test-tracer.ts +26 -0
- package/src/testing/node/index.ts +1 -0
- package/src/testing/node/lsp-harness.ts +2 -0
- package/src/testing/node/lsp-server-connection.ts +66 -12
- package/src/testing/node/scratch-workspace.ts +10 -5
- package/src/testing/node/spawned-server.ts +36 -2
- package/src/testing/node/unhandled-rejections.ts +31 -0
- package/src/testing/parse-semantic-root.ts +1 -1
- package/src/testing/playwright/flaky-network-proxy.ts +240 -0
- package/src/testing/playwright/index.ts +1 -0
- package/src/testing/playwright/server-log-capture.ts +45 -11
- package/src/testing/playwright/server-log-rename-reporter.ts +12 -1
- package/src/testing/run-update-pipeline.ts +4 -4
- package/src/testing/stub-ast-document-manager.ts +36 -138
- package/src/testing/stub-document-builder.ts +102 -18
- package/src/testing/stub-hydranium-text-documents.ts +165 -27
- package/src/testing/stub-langium-documents.ts +3 -2
- package/src/testing/stub-model-service.ts +9 -8
- package/src/testing/stub-self-save-registry.ts +1 -1
- package/src/testing/stub-service-registry.ts +1 -1
- package/src/testing/stub-writable-file-system.ts +1 -1
- package/src/util/connection-liveness.ts +37 -14
- package/src/util/environment.ts +9 -1
- package/lib/documents/language-client-text-shadow.d.ts +0 -101
- package/lib/documents/language-client-text-shadow.d.ts.map +0 -1
- package/lib/documents/language-client-text-shadow.js +0 -156
- package/lib/documents/language-client-text-shadow.js.map +0 -1
- package/lib/documents/self-save-registry.d.ts.map +0 -1
- package/lib/documents/self-save-registry.js.map +0 -1
- package/lib/lsp/instrument-connection.d.ts +0 -36
- package/lib/lsp/instrument-connection.d.ts.map +0 -1
- package/lib/lsp/instrument-connection.js +0 -62
- package/lib/lsp/instrument-connection.js.map +0 -1
- package/lib/node/process-memory.d.ts +0 -66
- package/lib/node/process-memory.d.ts.map +0 -1
- package/lib/node/process-memory.js +0 -252
- package/lib/node/process-memory.js.map +0 -1
- package/src/documents/language-client-text-shadow.ts +0 -175
- package/src/lsp/instrument-connection.ts +0 -66
- package/src/node/process-memory.ts +0 -299
|
@@ -8,17 +8,16 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
10
|
import { type Harness } from '@hydranium/protocol/testing';
|
|
11
|
-
import {
|
|
11
|
+
import { PassThrough, type TransformCallback } from 'node:stream';
|
|
12
12
|
import { StreamMessageReader, StreamMessageWriter } from 'vscode-jsonrpc/node';
|
|
13
13
|
import { type Connection, ProposedFeatures } from 'vscode-languageserver/node';
|
|
14
|
+
import { withHydraniumLspFeatures } from '../../lsp/connection-features.js';
|
|
14
15
|
// The node `createConnection` from `vscode-languageserver/node` is built for a
|
|
15
16
|
// standalone server PROCESS: it wires `process.exit()` onto the input stream's
|
|
16
17
|
// `end`/`close` events, onto the `exit` notification (via its watchDog), and onto
|
|
17
|
-
// a parent-pid liveness timer
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// stream (an uncatchable synchronous `ERR_STREAM_DESTROYED`) and/or exits the host
|
|
21
|
-
// test runner. The lower-level common `createConnection(connectionFactory,
|
|
18
|
+
// a parent-pid liveness timer. In-process every one of those is fatal —
|
|
19
|
+
// destroying the streams at teardown trips the `close` handler, which exits the
|
|
20
|
+
// host test runner. The lower-level common `createConnection(connectionFactory,
|
|
22
21
|
// watchDog, features)` form does none of that: it lets us inject a no-op-`exit`
|
|
23
22
|
// WatchDog and build the connection over the in-memory streams, so teardown is the
|
|
24
23
|
// primitive's responsibility alone.
|
|
@@ -30,6 +29,7 @@ import {
|
|
|
30
29
|
ApplyWorkspaceEditRequest,
|
|
31
30
|
CompletionRequest,
|
|
32
31
|
DidChangeTextDocumentNotification,
|
|
32
|
+
DidCloseTextDocumentNotification,
|
|
33
33
|
DidOpenTextDocumentNotification,
|
|
34
34
|
HoverRequest,
|
|
35
35
|
InitializeRequest,
|
|
@@ -170,8 +170,8 @@ function insertedText(edit: WorkspaceEdit): string {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
|
-
* The in-process LSP transport seam — a real `Connection` over
|
|
174
|
-
*
|
|
173
|
+
* The in-process LSP transport seam — a real `Connection` over a crossed pair
|
|
174
|
+
* of in-memory streams, plus the client side, the diagnostics capture,
|
|
175
175
|
* and the typed request facades — with NO services attached. It is the lower
|
|
176
176
|
* half of `makeLspHarness`, factored out so a caller can OWN the services
|
|
177
177
|
* tree: build the tree around {@link serverConnection} (`createXxxServices({
|
|
@@ -226,6 +226,12 @@ export interface LspServerConnection extends Harness {
|
|
|
226
226
|
* unhandled method.
|
|
227
227
|
*/
|
|
228
228
|
readonly appliedEdits: ReadonlyArray<AppliedEdit>;
|
|
229
|
+
/** Bytes written in each direction of the in-process JSON-RPC wire. */
|
|
230
|
+
readonly wireBytes: () => {
|
|
231
|
+
readonly clientToServer: number;
|
|
232
|
+
readonly serverToClient: number;
|
|
233
|
+
readonly total: number;
|
|
234
|
+
};
|
|
229
235
|
|
|
230
236
|
/**
|
|
231
237
|
* Drive the real LSP `initialize` → `initialized` handshake and return the
|
|
@@ -247,6 +253,8 @@ export interface LspServerConnection extends Harness {
|
|
|
247
253
|
* associates with a language (silent no-diagnostics). `version` defaults to 1.
|
|
248
254
|
*/
|
|
249
255
|
openDocument(uri: string, text: string, languageId: string, version?: number): void;
|
|
256
|
+
/** Send `textDocument/didClose` for a document opened through this harness. */
|
|
257
|
+
closeDocument(uri: string): Promise<void>;
|
|
250
258
|
/** Send `textDocument/didChange` for `uri` as a single full-text replacement at `version`. */
|
|
251
259
|
changeDocument(uri: string, text: string, version: number): void;
|
|
252
260
|
|
|
@@ -293,7 +301,7 @@ export interface LspServerConnection extends Harness {
|
|
|
293
301
|
*
|
|
294
302
|
* **An egress push is asynchronous well past the call that triggers it** —
|
|
295
303
|
* the framework coalesces per URI and drives the sync from a build-phase
|
|
296
|
-
* settle, so a `
|
|
304
|
+
* settle, so a session's `update` resolves long before the push is sent.
|
|
297
305
|
* Record `appliedEdits.length`, drive the edit, then await this; reading the
|
|
298
306
|
* capture on the line after the write proves nothing.
|
|
299
307
|
*/
|
|
@@ -319,6 +327,39 @@ export interface LspServerConnection extends Harness {
|
|
|
319
327
|
dispose(): void;
|
|
320
328
|
}
|
|
321
329
|
|
|
330
|
+
/**
|
|
331
|
+
* A `PassThrough` that counts the bytes written through it. Counting here
|
|
332
|
+
* rather than in a `'data'` listener is what keeps the wire buffering: a
|
|
333
|
+
* listener switches the stream to flowing mode, and a message written before
|
|
334
|
+
* the server calls `listen()` is then delivered to the counter alone and lost.
|
|
335
|
+
*/
|
|
336
|
+
class CountingPassThrough extends PassThrough {
|
|
337
|
+
bytes = 0;
|
|
338
|
+
|
|
339
|
+
override _transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback): void {
|
|
340
|
+
this.bytes += chunk.length;
|
|
341
|
+
callback(null, chunk);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** A crossed pair of {@link CountingPassThrough}s, disposed as one. */
|
|
346
|
+
function makeCountingStreamPair(): {
|
|
347
|
+
readonly clientToServer: CountingPassThrough;
|
|
348
|
+
readonly serverToClient: CountingPassThrough;
|
|
349
|
+
dispose(): void;
|
|
350
|
+
} {
|
|
351
|
+
const clientToServer = new CountingPassThrough();
|
|
352
|
+
const serverToClient = new CountingPassThrough();
|
|
353
|
+
return {
|
|
354
|
+
clientToServer,
|
|
355
|
+
serverToClient,
|
|
356
|
+
dispose(): void {
|
|
357
|
+
clientToServer.destroy();
|
|
358
|
+
serverToClient.destroy();
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
322
363
|
/**
|
|
323
364
|
* Build the in-process LSP transport seam (server `Connection` + client + wire +
|
|
324
365
|
* diagnostics capture + typed facades) WITHOUT attaching a server. The caller
|
|
@@ -331,7 +372,7 @@ export interface LspServerConnection extends Harness {
|
|
|
331
372
|
* additional protocol heads (data-server, GLSP) onto the same `shared` services.
|
|
332
373
|
*/
|
|
333
374
|
export function makeLspServerConnection(): LspServerConnection {
|
|
334
|
-
const pair =
|
|
375
|
+
const pair = makeCountingStreamPair();
|
|
335
376
|
|
|
336
377
|
// No-op watchDog: in-process, no LSP lifecycle event (parent-pid liveness, the
|
|
337
378
|
// `exit` notification, …) may exit the host test runner — `dispose()` owns
|
|
@@ -347,11 +388,15 @@ export function makeLspServerConnection(): LspServerConnection {
|
|
|
347
388
|
logger =>
|
|
348
389
|
createProtocolConnection(new StreamMessageReader(pair.clientToServer), new StreamMessageWriter(pair.serverToClient), logger),
|
|
349
390
|
watchDog,
|
|
350
|
-
ProposedFeatures.all
|
|
391
|
+
withHydraniumLspFeatures(ProposedFeatures.all)
|
|
351
392
|
);
|
|
352
393
|
|
|
353
394
|
// Client side mirrors the directions: reads serverToClient, writes clientToServer.
|
|
354
|
-
const client = createProtocolConnection(
|
|
395
|
+
const client = createProtocolConnection(
|
|
396
|
+
new StreamMessageReader(pair.serverToClient),
|
|
397
|
+
new StreamMessageWriter(pair.clientToServer),
|
|
398
|
+
console
|
|
399
|
+
);
|
|
355
400
|
client.listen();
|
|
356
401
|
|
|
357
402
|
const diagnostics: PublishDiagnosticsParams[] = [];
|
|
@@ -415,6 +460,11 @@ export function makeLspServerConnection(): LspServerConnection {
|
|
|
415
460
|
client,
|
|
416
461
|
diagnostics,
|
|
417
462
|
appliedEdits,
|
|
463
|
+
wireBytes: () => ({
|
|
464
|
+
clientToServer: pair.clientToServer.bytes,
|
|
465
|
+
serverToClient: pair.serverToClient.bytes,
|
|
466
|
+
total: pair.clientToServer.bytes + pair.serverToClient.bytes
|
|
467
|
+
}),
|
|
418
468
|
|
|
419
469
|
async initialize(params?: Partial<InitializeParams>): Promise<InitializeResult> {
|
|
420
470
|
const initializeParams: InitializeParams = {
|
|
@@ -455,6 +505,10 @@ export function makeLspServerConnection(): LspServerConnection {
|
|
|
455
505
|
});
|
|
456
506
|
},
|
|
457
507
|
|
|
508
|
+
async closeDocument(uri: string): Promise<void> {
|
|
509
|
+
await client.sendNotification(DidCloseTextDocumentNotification.type, { textDocument: { uri } });
|
|
510
|
+
},
|
|
511
|
+
|
|
458
512
|
changeDocument(uri: string, text: string, version: number): void {
|
|
459
513
|
client.sendNotification(DidChangeTextDocumentNotification.type, {
|
|
460
514
|
textDocument: { uri, version },
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Any test that drives a **write path** needs one, and the reason is not
|
|
16
16
|
* obvious enough to rediscover per suite. The writes themselves are usually
|
|
17
|
-
* in-memory — `
|
|
17
|
+
* in-memory — a session's `update` goes to the multi-client text store, and
|
|
18
18
|
* only `save` reaches disk — but a rebuild also runs the integrity rules, and
|
|
19
19
|
* their default `'silent'` sync mode persists repairs through
|
|
20
20
|
* `WritableFileSystemProvider.writeFile`. So a write-path test pointed at a
|
|
21
21
|
* committed sample workspace can **rewrite the sample files**, after which
|
|
22
22
|
* every later run asserts against already-repaired input: a suite that passes
|
|
23
23
|
* while testing nothing. The same applies to a fixture built in place, which
|
|
24
|
-
* additionally
|
|
25
|
-
* through
|
|
24
|
+
* additionally comes back in the serializer's layout, because the write-back
|
|
25
|
+
* goes through it.
|
|
26
26
|
*
|
|
27
27
|
* The second reason is cleanup. Hand-rolled `mkdtempSync` without a matching
|
|
28
28
|
* `rmSync` leaks a directory per test run into the OS temp dir, which nobody
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
51
|
import { URI } from '@hydranium/langium';
|
|
52
|
-
import { cpSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
52
|
+
import { cpSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
53
53
|
import { tmpdir } from 'node:os';
|
|
54
54
|
import * as path from 'node:path';
|
|
55
55
|
|
|
@@ -106,7 +106,12 @@ export interface ScratchWorkspace {
|
|
|
106
106
|
* returned {@link ScratchWorkspace.dispose} with an `afterEach`.
|
|
107
107
|
*/
|
|
108
108
|
export function makeScratchWorkspace(options: ScratchWorkspaceOptions = {}): ScratchWorkspace {
|
|
109
|
-
|
|
109
|
+
// RESOLVED, because `tmpdir()` can itself be a symlink — on macOS it answers
|
|
110
|
+
// `/tmp`, which links to `/private/tmp`. A root the server canonicalises to a
|
|
111
|
+
// different path than the one it was handed registers documents under one
|
|
112
|
+
// spelling and reads them under the other, failing initialization with an
|
|
113
|
+
// ENOENT that names neither the link nor this call.
|
|
114
|
+
const root = realpathSync(mkdtempSync(path.join(tmpdir(), options.prefix ?? 'hydranium-scratch-')));
|
|
110
115
|
if (options.seed) {
|
|
111
116
|
cpSync(options.seed, root, { recursive: true });
|
|
112
117
|
}
|
|
@@ -203,6 +203,37 @@ export interface SpawnedServer extends Harness {
|
|
|
203
203
|
dispose(): Promise<number | null>;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Every server started and not yet disposed, so {@link disposeSpawnedServers}
|
|
208
|
+
* can reach one a test forgot.
|
|
209
|
+
*
|
|
210
|
+
* Holds the server — and through it the `ChildProcess` — rather than a pid. A
|
|
211
|
+
* pid identifies a process only while that process is alive: once it exits the
|
|
212
|
+
* OS may reissue the number, and Windows does so within seconds. A teardown
|
|
213
|
+
* that signalled a recorded pid would therefore reach whatever holds it now,
|
|
214
|
+
* which on a concurrent build is another task's compiler or test runner.
|
|
215
|
+
*/
|
|
216
|
+
const liveServers = new Set<SpawnedServer>();
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Terminate every server this module started that has not been disposed, and
|
|
220
|
+
* forget them.
|
|
221
|
+
*
|
|
222
|
+
* Safe to call when none are outstanding, and safe to call twice. Nothing here
|
|
223
|
+
* can reach a process this module did not spawn, because every kill goes
|
|
224
|
+
* through the `ChildProcess` handle libuv holds and libuv will not signal a
|
|
225
|
+
* child it has already reaped.
|
|
226
|
+
*
|
|
227
|
+
* A suite that disposes each server as it finishes needs this only as a net; a
|
|
228
|
+
* suite that does not needs it, because an orphan holding a port or a pipe
|
|
229
|
+
* makes the NEXT run's verdict meaningless.
|
|
230
|
+
*/
|
|
231
|
+
export async function disposeSpawnedServers(): Promise<void> {
|
|
232
|
+
const outstanding = [...liveServers];
|
|
233
|
+
liveServers.clear();
|
|
234
|
+
await Promise.all(outstanding.map(server => server.dispose()));
|
|
235
|
+
}
|
|
236
|
+
|
|
206
237
|
/** The captured streams, quoted into a boot-failure message. */
|
|
207
238
|
function bootDiagnosis(stdoutPrefix: string, stderr: string): string {
|
|
208
239
|
return (
|
|
@@ -253,7 +284,7 @@ export async function startSpawnedServer(options: SpawnedServerOptions): Promise
|
|
|
253
284
|
}
|
|
254
285
|
});
|
|
255
286
|
|
|
256
|
-
const connection = createProtocolConnection(child.stdout, child.stdin);
|
|
287
|
+
const connection = createProtocolConnection(child.stdout, child.stdin, console);
|
|
257
288
|
const diagnostics: PublishDiagnosticsParams[] = [];
|
|
258
289
|
/**
|
|
259
290
|
* Waiters armed by {@link SpawnedServer.nextDiagnostics}, fanned out to from
|
|
@@ -390,7 +421,7 @@ export async function startSpawnedServer(options: SpawnedServerOptions): Promise
|
|
|
390
421
|
return exitCode;
|
|
391
422
|
}
|
|
392
423
|
|
|
393
|
-
|
|
424
|
+
const server: SpawnedServer = {
|
|
394
425
|
connection,
|
|
395
426
|
pid: child.pid,
|
|
396
427
|
initializeResult,
|
|
@@ -440,8 +471,11 @@ export async function startSpawnedServer(options: SpawnedServerOptions): Promise
|
|
|
440
471
|
});
|
|
441
472
|
},
|
|
442
473
|
dispose(): Promise<number | null> {
|
|
474
|
+
liveServers.delete(server);
|
|
443
475
|
disposal ??= terminate();
|
|
444
476
|
return disposal;
|
|
445
477
|
}
|
|
446
478
|
};
|
|
479
|
+
liveServers.add(server);
|
|
480
|
+
return server;
|
|
447
481
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Run a Node-only assertion while collecting process-level unhandled rejection
|
|
12
|
+
* events. The callback owns the event-loop drain and can therefore choose the
|
|
13
|
+
* right observation window for the operation under test.
|
|
14
|
+
*
|
|
15
|
+
* Inside the window a rejection reaches only the array: while any listener is
|
|
16
|
+
* registered, Node hands none to its default handler and Vitest reports none as
|
|
17
|
+
* an error. A callback that never asserts on the array therefore hides every
|
|
18
|
+
* rejection it provokes.
|
|
19
|
+
*/
|
|
20
|
+
export async function captureUnhandledRejections<T>(callback: (rejections: unknown[]) => Promise<T>): Promise<T> {
|
|
21
|
+
const rejections: unknown[] = [];
|
|
22
|
+
const listener = (reason: unknown): void => {
|
|
23
|
+
rejections.push(reason);
|
|
24
|
+
};
|
|
25
|
+
process.on('unhandledRejection', listener);
|
|
26
|
+
try {
|
|
27
|
+
return await callback(rejections);
|
|
28
|
+
} finally {
|
|
29
|
+
process.off('unhandledRejection', listener);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
|
|
56
56
|
import { type AstNode, AstUtils, type LangiumCoreServices, URI } from '@hydranium/langium';
|
|
57
57
|
import { type ParseHelperOptions, parseHelper } from '@hydranium/langium/test';
|
|
58
|
-
import type { WritableFileSystemProvider } from '../
|
|
58
|
+
import type { WritableFileSystemProvider } from '../langium/workspace/file-system-provider.js';
|
|
59
59
|
|
|
60
60
|
/** The one field this module reads off a lexer or parser error. */
|
|
61
61
|
interface ParseErrorMessage {
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
import { createServer as createHttpServer, type Server as HttpServer } from 'node:http';
|
|
11
|
+
import { connect, createServer as createTcpServer, type Server as TcpServer, type Socket } from 'node:net';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A TCP proxy that can half-close a connection, so an e2e suite can reproduce a
|
|
15
|
+
* flaky network against a real browser session.
|
|
16
|
+
*
|
|
17
|
+
* Toggling the browser offline is not enough. On localhost the server sees the
|
|
18
|
+
* close immediately and reaps the socket before the browser reconnects, so the
|
|
19
|
+
* window where both sides disagree about the session — the one where reconnect
|
|
20
|
+
* defects live — never opens. Reaching it needs the browser's socket to die
|
|
21
|
+
* while the server still believes it is alive, and nothing inside the app or in
|
|
22
|
+
* Playwright's offline emulation can produce that asymmetry: both close cleanly
|
|
23
|
+
* at both ends.
|
|
24
|
+
*
|
|
25
|
+
* The proxy holds both halves of every connection and lets a test kill them
|
|
26
|
+
* independently:
|
|
27
|
+
*
|
|
28
|
+
* `break` destroy the BROWSER-side sockets, keep the server-side ones open.
|
|
29
|
+
* The browser reconnects through a fresh pair while the server
|
|
30
|
+
* still holds the old one.
|
|
31
|
+
* `release` destroy the orphaned server-side sockets `break` left. The
|
|
32
|
+
* server's disconnect handler fires at once, rather than whenever
|
|
33
|
+
* its next heartbeat write would have failed.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** Where the proxy listens, and the application it fronts. */
|
|
37
|
+
export interface FlakyNetworkProxyOptions {
|
|
38
|
+
/** Port the browser connects to. */
|
|
39
|
+
readonly listenPort: number;
|
|
40
|
+
/** Port of the application being proxied. */
|
|
41
|
+
readonly targetPort: number;
|
|
42
|
+
/** Host of the application being proxied. Defaults to loopback. */
|
|
43
|
+
readonly targetHost?: string;
|
|
44
|
+
/** Port the HTTP control channel listens on. Defaults to `listenPort + 1000`. */
|
|
45
|
+
readonly controlPort?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The commands the control channel accepts, and the proxy's own vocabulary. */
|
|
49
|
+
export type FlakyNetworkCommand = 'break' | 'release' | 'status';
|
|
50
|
+
|
|
51
|
+
/** Drives a running proxy. Implemented both in-process and over HTTP. */
|
|
52
|
+
export interface FlakyNetworkControl {
|
|
53
|
+
/** Kill the browser side of every live connection; leave the server side up. */
|
|
54
|
+
break(): Promise<string>;
|
|
55
|
+
/** Kill the server side of every connection `break` orphaned. */
|
|
56
|
+
release(): Promise<string>;
|
|
57
|
+
/** How many connections are live and how many are orphaned. */
|
|
58
|
+
status(): Promise<string>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface FlakyNetworkProxy extends FlakyNetworkControl {
|
|
62
|
+
/** Base URL a browser should be pointed at, i.e. Playwright's `baseURL`. */
|
|
63
|
+
readonly url: string;
|
|
64
|
+
/** Control channel, for workers that cannot reach this object directly. */
|
|
65
|
+
readonly controlUrl: string;
|
|
66
|
+
close(): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface ConnectionPair {
|
|
70
|
+
readonly id: number;
|
|
71
|
+
readonly browserSocket: Socket;
|
|
72
|
+
readonly targetSocket: Socket;
|
|
73
|
+
orphaned: boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Starts the proxy in the calling process.
|
|
78
|
+
*
|
|
79
|
+
* Call it from a Playwright config, which runs in the main process before any
|
|
80
|
+
* worker forks. Workers are separate processes and cannot reach the returned
|
|
81
|
+
* object, which is what {@link controlUrl} and {@link flakyNetworkControlClient}
|
|
82
|
+
* are for.
|
|
83
|
+
*/
|
|
84
|
+
export async function startFlakyNetworkProxy(options: FlakyNetworkProxyOptions): Promise<FlakyNetworkProxy> {
|
|
85
|
+
const targetHost = options.targetHost ?? '127.0.0.1';
|
|
86
|
+
const controlPort = options.controlPort ?? options.listenPort + 1000;
|
|
87
|
+
const pairs = new Set<ConnectionPair>();
|
|
88
|
+
let sequence = 0;
|
|
89
|
+
let transcript: string[] = [];
|
|
90
|
+
|
|
91
|
+
const log = (message: string): void => {
|
|
92
|
+
transcript.push(message);
|
|
93
|
+
console.log(`[flaky-network] ${message}`);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const proxyServer: TcpServer = createTcpServer(browserSocket => {
|
|
97
|
+
const id = ++sequence;
|
|
98
|
+
const targetSocket = connect(options.targetPort, targetHost);
|
|
99
|
+
const pair: ConnectionPair = { id, browserSocket, targetSocket, orphaned: false };
|
|
100
|
+
pairs.add(pair);
|
|
101
|
+
|
|
102
|
+
// Forwarded by hand rather than with `pipe()`, so killing one side does not
|
|
103
|
+
// tear the other down — which is the entire point of the proxy.
|
|
104
|
+
browserSocket.on('data', chunk => {
|
|
105
|
+
if (!targetSocket.destroyed) {
|
|
106
|
+
targetSocket.write(chunk);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
targetSocket.on('data', chunk => {
|
|
110
|
+
if (!pair.orphaned && !browserSocket.destroyed) {
|
|
111
|
+
browserSocket.write(chunk);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const teardown = (origin: 'browser' | 'target'): void => {
|
|
116
|
+
if (pair.orphaned && origin === 'browser') {
|
|
117
|
+
// Expected: `break` killed this side deliberately. The server side
|
|
118
|
+
// stays up until `release`.
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
pairs.delete(pair);
|
|
122
|
+
browserSocket.destroy();
|
|
123
|
+
targetSocket.destroy();
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
browserSocket.on('close', () => teardown('browser'));
|
|
127
|
+
targetSocket.on('close', () => teardown('target'));
|
|
128
|
+
// A half-killed pair reliably raises ECONNRESET on the surviving side; an
|
|
129
|
+
// unhandled 'error' would take the whole runner down with it.
|
|
130
|
+
browserSocket.on('error', () => undefined);
|
|
131
|
+
targetSocket.on('error', () => undefined);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const commands: Record<FlakyNetworkCommand, () => void> = {
|
|
135
|
+
break: () => {
|
|
136
|
+
const live = [...pairs].filter(pair => !pair.orphaned);
|
|
137
|
+
if (live.length === 0) {
|
|
138
|
+
log('nothing to break');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
for (const pair of live) {
|
|
142
|
+
pair.orphaned = true;
|
|
143
|
+
pair.browserSocket.destroy();
|
|
144
|
+
}
|
|
145
|
+
log(`${live.length} connection(s) broken; the browser should reconnect shortly`);
|
|
146
|
+
},
|
|
147
|
+
release: () => {
|
|
148
|
+
const orphans = [...pairs].filter(pair => pair.orphaned);
|
|
149
|
+
if (orphans.length === 0) {
|
|
150
|
+
log('no orphaned connections; run `break` first');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
for (const pair of orphans) {
|
|
154
|
+
pairs.delete(pair);
|
|
155
|
+
pair.targetSocket.destroy();
|
|
156
|
+
}
|
|
157
|
+
log(`${orphans.length} orphaned connection(s) destroyed; their late disconnect fires now`);
|
|
158
|
+
},
|
|
159
|
+
status: () => {
|
|
160
|
+
const live = [...pairs].filter(pair => !pair.orphaned).length;
|
|
161
|
+
const orphaned = pairs.size - live;
|
|
162
|
+
log(`${live} live, ${orphaned} orphaned`);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const run = (name: string): string => {
|
|
167
|
+
transcript = [];
|
|
168
|
+
const command = commands[name as FlakyNetworkCommand];
|
|
169
|
+
if (command) {
|
|
170
|
+
command();
|
|
171
|
+
} else {
|
|
172
|
+
log(`unknown command '${name}'; use: ${Object.keys(commands).join(' | ')}`);
|
|
173
|
+
}
|
|
174
|
+
return transcript.join('\n');
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const controlServer: HttpServer = createHttpServer((request, response) => {
|
|
178
|
+
const output = run((request.url ?? '').replace(/^\//, '').split('?')[0]);
|
|
179
|
+
response.writeHead(200, { 'content-type': 'text/plain' });
|
|
180
|
+
response.end(`${output}\n`);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await Promise.all([listen(proxyServer, options.listenPort), listen(controlServer, controlPort)]);
|
|
184
|
+
// Neither server keeps the process alive, so a runner that starts one from a
|
|
185
|
+
// config does not need a teardown hook to exit — and a caller that wants a
|
|
186
|
+
// deterministic shutdown still has `close()`.
|
|
187
|
+
proxyServer.unref();
|
|
188
|
+
controlServer.unref();
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
url: `http://localhost:${options.listenPort}`,
|
|
192
|
+
controlUrl: `http://localhost:${controlPort}`,
|
|
193
|
+
break: async () => run('break'),
|
|
194
|
+
release: async () => run('release'),
|
|
195
|
+
status: async () => run('status'),
|
|
196
|
+
close: async () => {
|
|
197
|
+
for (const pair of pairs) {
|
|
198
|
+
pair.browserSocket.destroy();
|
|
199
|
+
pair.targetSocket.destroy();
|
|
200
|
+
}
|
|
201
|
+
pairs.clear();
|
|
202
|
+
await Promise.all([close(proxyServer), close(controlServer)]);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Drives a proxy running in another process, over its control channel.
|
|
209
|
+
*
|
|
210
|
+
* This is what a spec uses: Playwright workers are separate processes from the
|
|
211
|
+
* config that started the proxy.
|
|
212
|
+
*/
|
|
213
|
+
export function flakyNetworkControlClient(controlUrl: string): FlakyNetworkControl {
|
|
214
|
+
const send = async (command: FlakyNetworkCommand): Promise<string> => {
|
|
215
|
+
const response = await fetch(`${controlUrl}/${command}`);
|
|
216
|
+
if (!response.ok) {
|
|
217
|
+
throw new Error(`flaky-network proxy rejected '${command}': ${response.status}`);
|
|
218
|
+
}
|
|
219
|
+
return (await response.text()).trim();
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
break: () => send('break'),
|
|
223
|
+
release: () => send('release'),
|
|
224
|
+
status: () => send('status')
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function listen(server: TcpServer | HttpServer, port: number): Promise<void> {
|
|
229
|
+
return new Promise((resolve, reject) => {
|
|
230
|
+
server.once('error', reject);
|
|
231
|
+
server.listen(port, () => {
|
|
232
|
+
server.off('error', reject);
|
|
233
|
+
resolve();
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function close(server: TcpServer | HttpServer): Promise<void> {
|
|
239
|
+
return new Promise(resolve => server.close(() => resolve()));
|
|
240
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// `@hydranium/core/testing` barrel) so importing the framework's unit-test
|
|
12
12
|
// helpers never pulls in `@playwright/test` — which is an OPTIONAL peer here.
|
|
13
13
|
export * from './e2e-profiling.js';
|
|
14
|
+
export * from './flaky-network-proxy.js';
|
|
14
15
|
export * from './browser-capture-bridge.js';
|
|
15
16
|
export * from './server-log-capture.js';
|
|
16
17
|
export * from './server-log-fixture.js';
|
|
@@ -10,7 +10,13 @@
|
|
|
10
10
|
import { appendFileSync, existsSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
11
11
|
import { join } from 'node:path';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
DEFAULT_LOG_FILE_ENV,
|
|
15
|
+
DEFAULT_LOG_FILE_LEVEL_ENV,
|
|
16
|
+
DEFAULT_LOG_LEVEL_ENV,
|
|
17
|
+
type LogThreshold,
|
|
18
|
+
parseLogLevel
|
|
19
|
+
} from '@hydranium/protocol';
|
|
14
20
|
import { toLogFileWorkspaceToken } from '../../langium/diagnostics/log-file-token.js';
|
|
15
21
|
|
|
16
22
|
/**
|
|
@@ -69,11 +75,16 @@ export interface CaptureServerLogOptions {
|
|
|
69
75
|
*/
|
|
70
76
|
dir?: string;
|
|
71
77
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
78
|
+
* Threshold the log file is written at, set on `HYDRANIUM_LOG_FILE_LEVEL`;
|
|
79
|
+
* the client's log-level setting does not change it. When omitted, respects a
|
|
80
|
+
* pre-set `HYDRANIUM_LOG_FILE_LEVEL`, then `HYDRANIUM_LOG_LEVEL` env (so a run
|
|
81
|
+
* can pick the level without editing the config), then falls back to `'debug'`
|
|
82
|
+
* (a capture at `'info'` is too thin).
|
|
83
|
+
*
|
|
84
|
+
* The server's own threshold is left alone: it governs what the client sees,
|
|
85
|
+
* not the file, and the setting replaces it within moments of startup.
|
|
75
86
|
*/
|
|
76
|
-
level?:
|
|
87
|
+
level?: LogThreshold;
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
/** A Playwright `reporter` config entry: `[modulePath, options]`. */
|
|
@@ -119,7 +130,11 @@ export function captureServerLog(options: CaptureServerLogOptions = {}): Capture
|
|
|
119
130
|
const env: Record<string, string> = {
|
|
120
131
|
[DEFAULT_LOG_FILE_ENV]: join(dir, `${WORKSPACE_PLACEHOLDER}.log`)
|
|
121
132
|
};
|
|
122
|
-
env[
|
|
133
|
+
env[DEFAULT_LOG_FILE_LEVEL_ENV] =
|
|
134
|
+
options.level ??
|
|
135
|
+
parseLogLevel(process.env[DEFAULT_LOG_FILE_LEVEL_ENV]) ??
|
|
136
|
+
parseLogLevel(process.env[DEFAULT_LOG_LEVEL_ENV]) ??
|
|
137
|
+
'debug';
|
|
123
138
|
const reporterModule = fileURLToPath(new URL('./server-log-rename-reporter.js', import.meta.url));
|
|
124
139
|
return { env, reporter: [reporterModule, { dir }] };
|
|
125
140
|
}
|
|
@@ -160,16 +175,28 @@ export function serverLogSpecName(file: string): string {
|
|
|
160
175
|
* Rename each `<token>.log` (backend) and `<token>.browser.log` (forwarded
|
|
161
176
|
* browser console) to the spec name recorded in its `<token>.spec` sidecar
|
|
162
177
|
* (written by {@link markServerLog}), then delete the sidecar. Colliding names —
|
|
163
|
-
* a spec that opened more than one workspace — get a `-2`, `-3`, … suffix.
|
|
164
|
-
*
|
|
165
|
-
*
|
|
178
|
+
* a spec that opened more than one workspace — get a `-2`, `-3`, … suffix. Run
|
|
179
|
+
* once, after all server processes have exited (e.g. a reporter's `onEnd`).
|
|
180
|
+
* Best-effort.
|
|
181
|
+
*
|
|
182
|
+
* Returns the workspace tokens left UNATTRIBUTED — a log the capture wrote that
|
|
183
|
+
* no test claimed, because that spec never reached
|
|
184
|
+
* {@link markServerLog} (no `serverLog` fixture, no `beforeEach` call).
|
|
185
|
+
*
|
|
186
|
+
* **Returned rather than ignored, because the unattributed state is the
|
|
187
|
+
* misleading one.** Such a log still exists, still has content, and is named by
|
|
188
|
+
* an opaque token with no test boundaries in it — so a capture run that covered
|
|
189
|
+
* nothing looks exactly like one that covered everything, and the logs are
|
|
190
|
+
* there to be read. A caller that can warn should warn.
|
|
166
191
|
*/
|
|
167
|
-
export function renameServerLogs(dir: string):
|
|
192
|
+
export function renameServerLogs(dir: string): string[] {
|
|
168
193
|
let entries: string[];
|
|
169
194
|
try {
|
|
170
195
|
entries = readdirSync(dir);
|
|
171
196
|
} catch {
|
|
172
|
-
|
|
197
|
+
// An unreadable capture dir has nothing to report — including nothing
|
|
198
|
+
// unattributed, since no log was observed at all.
|
|
199
|
+
return [];
|
|
173
200
|
}
|
|
174
201
|
// Per suffix (`.log`, `.browser.log`) a `taken` set guards collisions, so the
|
|
175
202
|
// backend and browser logs for one spec share the same friendly base name.
|
|
@@ -190,6 +217,11 @@ export function renameServerLogs(dir: string): void {
|
|
|
190
217
|
// ignore
|
|
191
218
|
}
|
|
192
219
|
};
|
|
220
|
+
// Every token the capture produced a backend log for, so the ones no sidecar
|
|
221
|
+
// claims can be reported rather than silently left behind.
|
|
222
|
+
const unattributed = new Set(
|
|
223
|
+
entries.filter(entry => entry.endsWith('.log') && !entry.endsWith('.browser.log')).map(entry => entry.slice(0, -'.log'.length))
|
|
224
|
+
);
|
|
193
225
|
for (const entry of entries) {
|
|
194
226
|
if (!entry.endsWith('.spec')) {
|
|
195
227
|
continue;
|
|
@@ -210,9 +242,11 @@ export function renameServerLogs(dir: string): void {
|
|
|
210
242
|
if (!name) {
|
|
211
243
|
continue;
|
|
212
244
|
}
|
|
245
|
+
unattributed.delete(token);
|
|
213
246
|
rename(token, name, '.log');
|
|
214
247
|
rename(token, name, '.browser.log');
|
|
215
248
|
}
|
|
249
|
+
return [...unattributed];
|
|
216
250
|
}
|
|
217
251
|
|
|
218
252
|
/**
|