@hydranium/core 1.0.0-next.114 → 1.0.0-next.117
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 +3 -1
- package/lib/documents/ast-document-manager.d.ts +52 -2
- package/lib/documents/ast-document-manager.d.ts.map +1 -1
- package/lib/documents/ast-document-manager.js +67 -5
- package/lib/documents/ast-document-manager.js.map +1 -1
- package/lib/documents/client-session-errors.d.ts +44 -0
- package/lib/documents/client-session-errors.d.ts.map +1 -0
- package/lib/documents/client-session-errors.js +57 -0
- package/lib/documents/client-session-errors.js.map +1 -0
- package/lib/documents/client-session-registry.d.ts +118 -0
- package/lib/documents/client-session-registry.d.ts.map +1 -0
- package/lib/documents/client-session-registry.js +171 -0
- package/lib/documents/client-session-registry.js.map +1 -0
- package/lib/documents/hydranium-text-documents.d.ts +77 -25
- package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
- package/lib/documents/hydranium-text-documents.js +143 -52
- package/lib/documents/hydranium-text-documents.js.map +1 -1
- package/lib/documents/index.d.ts +2 -0
- package/lib/documents/index.d.ts.map +1 -1
- package/lib/documents/index.js +2 -0
- package/lib/documents/index.js.map +1 -1
- package/lib/langium/integrity/integrity-rule.d.ts +13 -5
- package/lib/langium/integrity/integrity-rule.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-rule.js.map +1 -1
- package/lib/langium/integrity/integrity-service.d.ts +37 -6
- package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
- package/lib/langium/integrity/integrity-service.js +81 -17
- package/lib/langium/integrity/integrity-service.js.map +1 -1
- package/lib/langium/model-service/client-session.d.ts +120 -0
- package/lib/langium/model-service/client-session.d.ts.map +1 -0
- package/lib/langium/model-service/client-session.js +175 -0
- package/lib/langium/model-service/client-session.js.map +1 -0
- package/lib/langium/model-service/index.d.ts +1 -0
- package/lib/langium/model-service/index.d.ts.map +1 -1
- package/lib/langium/model-service/index.js +1 -0
- package/lib/langium/model-service/index.js.map +1 -1
- package/lib/langium/model-service/model-service.d.ts +76 -8
- package/lib/langium/model-service/model-service.d.ts.map +1 -1
- package/lib/langium/model-service/model-service.js +148 -21
- package/lib/langium/model-service/model-service.js.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.d.ts +6 -0
- package/lib/lsp/hydranium-document-update-handler.d.ts.map +1 -1
- package/lib/lsp/hydranium-document-update-handler.js +20 -3
- package/lib/lsp/hydranium-document-update-handler.js.map +1 -1
- package/lib/testing/stub-ast-document-manager.d.ts +4 -3
- package/lib/testing/stub-ast-document-manager.d.ts.map +1 -1
- package/lib/testing/stub-ast-document-manager.js +3 -0
- package/lib/testing/stub-ast-document-manager.js.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.d.ts +13 -5
- package/lib/testing/stub-hydranium-text-documents.d.ts.map +1 -1
- package/lib/testing/stub-hydranium-text-documents.js +45 -14
- package/lib/testing/stub-hydranium-text-documents.js.map +1 -1
- package/package.json +5 -5
- package/src/documents/ast-document-manager.ts +107 -6
- package/src/documents/client-session-errors.ts +54 -0
- package/src/documents/client-session-registry.ts +211 -0
- package/src/documents/hydranium-text-documents.ts +158 -55
- package/src/documents/index.ts +2 -0
- package/src/langium/integrity/integrity-rule.ts +13 -5
- package/src/langium/integrity/integrity-service.ts +84 -17
- package/src/langium/model-service/client-session.ts +257 -0
- package/src/langium/model-service/index.ts +1 -0
- package/src/langium/model-service/model-service.ts +176 -21
- package/src/lsp/hydranium-document-update-handler.ts +22 -4
- package/src/testing/stub-ast-document-manager.ts +7 -2
- package/src/testing/stub-hydranium-text-documents.ts +62 -18
|
@@ -58,6 +58,7 @@ export const HYDRANIUM_BUILD_REASONS = Object.freeze({
|
|
|
58
58
|
* inside the workspace-lock callback.
|
|
59
59
|
*/
|
|
60
60
|
export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler {
|
|
61
|
+
services;
|
|
61
62
|
logger;
|
|
62
63
|
selfSaveRegistry;
|
|
63
64
|
fileSystemProvider;
|
|
@@ -89,6 +90,7 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
|
|
|
89
90
|
pendingReason;
|
|
90
91
|
constructor(services, options = {}) {
|
|
91
92
|
super(services);
|
|
93
|
+
this.services = services;
|
|
92
94
|
this.logger = services.Logger;
|
|
93
95
|
this.selfSaveRegistry = services.workspace.SelfSaveRegistry;
|
|
94
96
|
this.fileSystemProvider = services.workspace.FileSystemProvider;
|
|
@@ -152,6 +154,11 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
|
|
|
152
154
|
*
|
|
153
155
|
* Per-client closes (where other clients still hold the URI) are
|
|
154
156
|
* suppressed via {@link HydraniumTextDocuments.isOpenInAnyClient}.
|
|
157
|
+
*
|
|
158
|
+
* The dispatch waits for the URI's disk queue to drain, because the rebuild
|
|
159
|
+
* re-reads the file: dispatched while a save is still queued, it reads the
|
|
160
|
+
* text from before that save, and the document reverts past it. A client
|
|
161
|
+
* that opens the URI meanwhile holds the text, so no revert follows.
|
|
155
162
|
*/
|
|
156
163
|
didCloseDocument(change) {
|
|
157
164
|
if (this.textDocuments.isOpenInAnyClient(change.document.uri)) {
|
|
@@ -161,9 +168,19 @@ export class HydraniumDocumentUpdateHandler extends DefaultDocumentUpdateHandler
|
|
|
161
168
|
if (uri.scheme !== 'file') {
|
|
162
169
|
return;
|
|
163
170
|
}
|
|
164
|
-
this.
|
|
165
|
-
|
|
166
|
-
|
|
171
|
+
this.services.workspace.AstDocumentManager.queueDiskTask(change.document.uri, async () => undefined)
|
|
172
|
+
.then(() => {
|
|
173
|
+
if (this.textDocuments.isOpenInAnyClient(change.document.uri)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
this.nextReason = HYDRANIUM_BUILD_REASONS.didClose;
|
|
177
|
+
this.immediateFlush = true;
|
|
178
|
+
this.fireDocumentUpdate([uri], []);
|
|
179
|
+
})
|
|
180
|
+
.catch((err) => {
|
|
181
|
+
const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
182
|
+
this.logger.error(`Revert on last close dropped for ${change.document.uri}. ${detail}`);
|
|
183
|
+
});
|
|
167
184
|
}
|
|
168
185
|
didChangeWatchedFiles(params) {
|
|
169
186
|
void this.filterSelfSaves(params)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hydranium-document-update-handler.js","sourceRoot":"","sources":["../../src/lsp/hydranium-document-update-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,SAAS,EAAe,eAAe,EAA6B,MAAM,qBAAqB,CAAC;AACzG,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAGtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAIhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAoD,cAAc,EAAgC,MAAM,uBAAuB,CAAC;AAGvI;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC;IAClD,OAAO,EAAE,SAAS;IAClB,gBAAgB,EAAE,kBAAkB;IACpC,qBAAqB,EAAE,uBAAuB;IAC9C,QAAQ,EAAE,UAAU;CACb,CAAC,CAAC;AA4BZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,OAAO,8BAA+B,SAAQ,4BAA4B;
|
|
1
|
+
{"version":3,"file":"hydranium-document-update-handler.js","sourceRoot":"","sources":["../../src/lsp/hydranium-document-update-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,8 +15,9 @@ import type { StubLangiumDocuments } from './stub-langium-documents.js';
|
|
|
15
15
|
* Minimal stub of {@link AstDocumentManager} for use in test
|
|
16
16
|
* harnesses. Implements just the methods the framework's
|
|
17
17
|
* `ModelService` calls (`open` / `close` / `update` / `save` /
|
|
18
|
-
* `isOpen` / `getDocument`)
|
|
19
|
-
* underlying stub text
|
|
18
|
+
* `isOpen` / `getDocument`) and a disk queue that runs each task at once;
|
|
19
|
+
* `onSave` / `onClientClosed` forward to the underlying stub text store,
|
|
20
|
+
* `onUpdate` is driven explicitly
|
|
20
21
|
* through {@link StubAstDocumentManager.emitUpdate} because the stub tree runs
|
|
21
22
|
* no build phases to emit from, and the remaining read helpers
|
|
22
23
|
* (`isTriggeringEdit`, `getAuthor`) throw if invoked — tests that need them
|
|
@@ -36,7 +37,7 @@ import type { StubLangiumDocuments } from './stub-langium-documents.js';
|
|
|
36
37
|
* are still picked so signature drift on them produces a compile
|
|
37
38
|
* error rather than silent divergence.
|
|
38
39
|
*/
|
|
39
|
-
export interface StubAstDocumentManager<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> extends Pick<AstDocumentManager<TAst, TDiagnostic>, 'open' | 'close' | 'isOpen' | 'update' | 'save' | 'onUpdate' | 'onSave' | 'onClientClosed' | 'getAuthor' | 'getDocument' | 'isTriggeringEdit'> {
|
|
40
|
+
export interface StubAstDocumentManager<TAst extends AstNode, TDiagnostic extends AstDiagnostic = AstDiagnostic> extends Pick<AstDocumentManager<TAst, TDiagnostic>, 'open' | 'close' | 'isOpen' | 'update' | 'save' | 'queueDiskTask' | 'onUpdate' | 'onSave' | 'onClientClosed' | 'getAuthor' | 'getDocument' | 'isTriggeringEdit'> {
|
|
40
41
|
readonly openClients: Map<string, Set<string>>;
|
|
41
42
|
/**
|
|
42
43
|
* Deliver an update event to every live {@link StubAstDocumentManager.onUpdate}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub-ast-document-manager.d.ts","sourceRoot":"","sources":["../../src/testing/stub-ast-document-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,OAAO,EAAkC,MAAM,oBAAoB,CAAC;AAElF,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAEJ,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EACjC,MAAM,sCAAsC,CAAC;AAE9C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE
|
|
1
|
+
{"version":3,"file":"stub-ast-document-manager.d.ts","sourceRoot":"","sources":["../../src/testing/stub-ast-document-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,OAAO,EAAkC,MAAM,oBAAoB,CAAC;AAElF,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAEJ,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EACjC,MAAM,sCAAsC,CAAC;AAE9C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,sBAAsB,CAAC,IAAI,SAAS,OAAO,EAAE,WAAW,SAAS,aAAa,GAAG,aAAa,CAAE,SAAQ,IAAI,CAC1H,kBAAkB,CAAC,IAAI,EAAE,WAAW,CAAC,EACnC,MAAM,GACN,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,eAAe,GACf,UAAU,GACV,QAAQ,GACR,gBAAgB,GAChB,WAAW,GACX,aAAa,GACb,kBAAkB,CACtB;IACE,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC;IAEnF;;;;;;OAMG;IACH,mBAAmB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5C;AAED,wBAAgB,0BAA0B,CAAC,IAAI,SAAS,OAAO,EAAE,WAAW,SAAS,aAAa,GAAG,aAAa,EAC/G,aAAa,EAAE,0BAA0B,EACzC,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,WAAW,CAAC,EACzD,SAAS,CAAC,EAAE,oBAAoB,CAAC,IAAI,EAAE,WAAW,CAAC,GACnD,sBAAsB,CAAC,IAAI,EAAE,WAAW,CAAC,CAiH3C"}
|
|
@@ -53,6 +53,9 @@ export function makeStubAstDocumentManager(textDocuments, fileSystem, documents)
|
|
|
53
53
|
await fileSystem.writeFile(UriUtils.toUri(uri), text);
|
|
54
54
|
textDocuments.notifyDidSaveTextDocument({ textDocument: { uri }, text }, clientId);
|
|
55
55
|
},
|
|
56
|
+
queueDiskTask(_uri, task) {
|
|
57
|
+
return task();
|
|
58
|
+
},
|
|
56
59
|
// Registers the listener but never calls it by itself — the real manager
|
|
57
60
|
// emits from a `DocumentBuilder.onDocumentPhase(Validated)` hook and the
|
|
58
61
|
// stub tree runs no phases. `emitUpdate` is the only thing that fires it;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub-ast-document-manager.js","sourceRoot":"","sources":["../../src/testing/stub-ast-document-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAsC,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EACJ,WAAW,EAIb,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"stub-ast-document-manager.js","sourceRoot":"","sources":["../../src/testing/stub-ast-document-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,9 +22,11 @@ export interface StubTextDocumentEntry {
|
|
|
22
22
|
* reads from on test paths — the content channel
|
|
23
23
|
* (`notifyDidChangeTextDocument` / `applyContentChange` / `version` /
|
|
24
24
|
* `getAuthor`), the open-state probes (`isOpenInLanguageClient` /
|
|
25
|
-
* `isOpenInAnyClient` / `openDocuments`), the push channel
|
|
26
|
-
* client (`applyEditToLanguageClient` / `stagePendingContent`)
|
|
27
|
-
* save / close notifications
|
|
25
|
+
* `isOpenInAnyClient` / `isOpenInClient` / `openDocuments`), the push channel
|
|
26
|
+
* to the language client (`applyEditToLanguageClient` / `stagePendingContent`),
|
|
27
|
+
* the save / close notifications, and the client-session table
|
|
28
|
+
* (`registerSession` / `closeSession` / `onDidCloseSession` and the open
|
|
29
|
+
* options), which is a real `ClientSessionRegistry` — plus test-only helpers:
|
|
28
30
|
*
|
|
29
31
|
* - {@link seedOpen} — pre-populate an open document without firing change
|
|
30
32
|
* events. Use to set up a baseline version before exercising an `update`.
|
|
@@ -53,7 +55,7 @@ export interface StubTextDocumentEntry {
|
|
|
53
55
|
* {@link applyContentChange} mirrors the real server-assigned write path:
|
|
54
56
|
* the version steps iff the text differs from the current content.
|
|
55
57
|
*/
|
|
56
|
-
export interface StubHydraniumTextDocuments extends Pick<HydraniumTextDocuments<TextDocument>, 'version' | 'notifyDidChangeTextDocument' | 'applyContentChange' | 'getAuthor' | 'isOpenInLanguageClient' | 'isOpenInAnyClient' | 'applyEditToLanguageClient' | 'stagePendingContent' | 'openDocuments'> {
|
|
58
|
+
export interface StubHydraniumTextDocuments extends Pick<HydraniumTextDocuments<TextDocument>, 'version' | 'notifyDidChangeTextDocument' | 'applyContentChange' | 'getAuthor' | 'isOpenInLanguageClient' | 'isOpenInAnyClient' | 'applyEditToLanguageClient' | 'stagePendingContent' | 'openDocuments' | 'isOpenInClient' | 'registerSession' | 'closeSession' | 'onDidCloseSession' | 'openOptions' | 'setOpenOptions'> {
|
|
57
59
|
/**
|
|
58
60
|
* Stub-tailored read accessor. Returns just the surface the framework's
|
|
59
61
|
* save path reads (`version` + `getText()`), rather than the real `get`'s
|
|
@@ -90,7 +92,13 @@ export interface StubHydraniumTextDocuments extends Pick<HydraniumTextDocuments<
|
|
|
90
92
|
seedOpenInLanguageClient(uri: string): void;
|
|
91
93
|
/** Synchronously deliver `onDidClose` to subscribers. */
|
|
92
94
|
fireClose(uri: string, clientId: string): void;
|
|
93
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Drop recorded state. Useful for `beforeEach` resets.
|
|
97
|
+
*
|
|
98
|
+
* Sessions end without announcing it, so a model service built on this
|
|
99
|
+
* stub still holds the handles it started before the reset. Build a fresh
|
|
100
|
+
* service after a reset rather than reusing one across it.
|
|
101
|
+
*/
|
|
94
102
|
reset(): void;
|
|
95
103
|
readonly changes: readonly StubTextDocumentEntry[];
|
|
96
104
|
readonly saves: readonly {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub-hydranium-text-documents.d.ts","sourceRoot":"","sources":["../../src/testing/stub-hydranium-text-documents.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"stub-hydranium-text-documents.d.ts","sourceRoot":"","sources":["../../src/testing/stub-hydranium-text-documents.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
import { Disposable } from 'vscode-languageserver';
|
|
10
10
|
import { LANGUAGE_CLIENT_ID } from '../documents/client-ids.js';
|
|
11
|
+
import { ClientSessionRegistry } from '../documents/client-session-registry.js';
|
|
11
12
|
/** Build a {@link StubHydraniumTextDocuments}. */
|
|
12
13
|
export function makeStubHydraniumTextDocuments() {
|
|
13
14
|
const docs = new Map();
|
|
@@ -19,7 +20,12 @@ export function makeStubHydraniumTextDocuments() {
|
|
|
19
20
|
let applyEditHandler = () => ({ applied: true });
|
|
20
21
|
const saveListeners = [];
|
|
21
22
|
const closeListeners = [];
|
|
22
|
-
|
|
23
|
+
// The real registry, so the session table, the opens, the closing state and
|
|
24
|
+
// the open options behave as the store's do. The stub's plain-string keys
|
|
25
|
+
// stand in for canonical URIs (one stub-boundary cast, like `fireClose`).
|
|
26
|
+
const sessions = new ClientSessionRegistry();
|
|
27
|
+
const key = (uri) => uri;
|
|
28
|
+
const stub = {
|
|
23
29
|
get changes() {
|
|
24
30
|
return changes;
|
|
25
31
|
},
|
|
@@ -100,21 +106,38 @@ export function makeStubHydraniumTextDocuments() {
|
|
|
100
106
|
isOpenInAnyClient(uri) {
|
|
101
107
|
return docs.has(uri) || languageClientOpen.has(uri);
|
|
102
108
|
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
isOpenInClient(uri, clientId) {
|
|
110
|
+
return sessions.isOpenIn(key(uri), clientId);
|
|
111
|
+
},
|
|
112
|
+
registerSession(clientId) {
|
|
113
|
+
sessions.register(clientId);
|
|
114
|
+
},
|
|
115
|
+
closeSession(clientId) {
|
|
116
|
+
if (!sessions.isRegistered(clientId)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
for (const uri of sessions.beginClose(clientId)) {
|
|
121
|
+
stub.fireClose(uri, clientId);
|
|
122
|
+
}
|
|
109
123
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
clients.add(LANGUAGE_CLIENT_ID);
|
|
113
|
-
clientsByUri.set(uri, clients);
|
|
124
|
+
finally {
|
|
125
|
+
sessions.unregister(clientId);
|
|
114
126
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return
|
|
127
|
+
},
|
|
128
|
+
get onDidCloseSession() {
|
|
129
|
+
return sessions.onDidCloseSession;
|
|
130
|
+
},
|
|
131
|
+
openOptions(uri, clientId) {
|
|
132
|
+
return sessions.openOptions(key(uri), clientId);
|
|
133
|
+
},
|
|
134
|
+
setOpenOptions(uri, clientId, options) {
|
|
135
|
+
sessions.setOpenOptions(key(uri), clientId, options);
|
|
136
|
+
},
|
|
137
|
+
openDocuments() {
|
|
138
|
+
// From the registry that also answers `isOpenInClient`, which both
|
|
139
|
+
// seeding channels feed, so the two never disagree about an open.
|
|
140
|
+
return sessions.openDocuments();
|
|
118
141
|
},
|
|
119
142
|
setApplyEditHandler(handler) {
|
|
120
143
|
applyEditHandler = handler;
|
|
@@ -127,9 +150,11 @@ export function makeStubHydraniumTextDocuments() {
|
|
|
127
150
|
staged.push({ uri, text });
|
|
128
151
|
},
|
|
129
152
|
seedOpen(uri, text, clientId) {
|
|
153
|
+
sessions.addOpen(key(uri), clientId);
|
|
130
154
|
docs.set(uri, { uri, version: 1, text, clientId });
|
|
131
155
|
},
|
|
132
156
|
seedOpenInLanguageClient(uri) {
|
|
157
|
+
sessions.addOpen(key(uri), LANGUAGE_CLIENT_ID);
|
|
133
158
|
languageClientOpen.add(uri);
|
|
134
159
|
},
|
|
135
160
|
fireClose(uri, clientId) {
|
|
@@ -140,6 +165,7 @@ export function makeStubHydraniumTextDocuments() {
|
|
|
140
165
|
if (holder && holder.clientId === clientId) {
|
|
141
166
|
docs.delete(uri);
|
|
142
167
|
}
|
|
168
|
+
sessions.removeOpen(key(uri), clientId);
|
|
143
169
|
if (clientId === LANGUAGE_CLIENT_ID) {
|
|
144
170
|
languageClientOpen.delete(uri);
|
|
145
171
|
}
|
|
@@ -158,7 +184,12 @@ export function makeStubHydraniumTextDocuments() {
|
|
|
158
184
|
saveListeners.length = 0;
|
|
159
185
|
closeListeners.length = 0;
|
|
160
186
|
applyEditHandler = () => ({ applied: true });
|
|
187
|
+
// Cleared in place rather than replaced: a model service built on the
|
|
188
|
+
// stub subscribed to `onDidCloseSession` once, and a new registry would
|
|
189
|
+
// leave that subscription on one nothing fires.
|
|
190
|
+
sessions.clear();
|
|
161
191
|
}
|
|
162
192
|
};
|
|
193
|
+
return stub;
|
|
163
194
|
}
|
|
164
195
|
//# sourceMappingURL=stub-hydranium-text-documents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub-hydranium-text-documents.js","sourceRoot":"","sources":["../../src/testing/stub-hydranium-text-documents.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"stub-hydranium-text-documents.js","sourceRoot":"","sources":["../../src/testing/stub-hydranium-text-documents.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydranium/core",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.117",
|
|
4
4
|
"description": "Foundational runtime of the hydranium framework: AST coordination layer (services, integrity, AST extension, serialization, multi-client documents) plus the LSP textual head at the /lsp subpath. Consumed by protocol-head packages (@hydranium/data-server, @hydranium/glsp-server).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hydranium",
|
|
@@ -104,8 +104,8 @@
|
|
|
104
104
|
"diff": "^5.2.0"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
|
-
"@hydranium/langium": "1.0.0-next.
|
|
108
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
107
|
+
"@hydranium/langium": "1.0.0-next.117",
|
|
108
|
+
"@hydranium/protocol": "1.0.0-next.117",
|
|
109
109
|
"@playwright/test": "^1.40.0",
|
|
110
110
|
"@types/diff": "^5.2.0",
|
|
111
111
|
"rimraf": "^5.0.0",
|
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"vscode-languageserver-types": "^3.17.5"
|
|
118
118
|
},
|
|
119
119
|
"peerDependencies": {
|
|
120
|
-
"@hydranium/langium": "1.0.0-next.
|
|
121
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
120
|
+
"@hydranium/langium": "1.0.0-next.117",
|
|
121
|
+
"@hydranium/protocol": "1.0.0-next.117",
|
|
122
122
|
"@playwright/test": "^1.40.0",
|
|
123
123
|
"vscode-jsonrpc": "9.0.1",
|
|
124
124
|
"vscode-languageserver": "~10.0.1",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
+
type CanonicalUri,
|
|
11
12
|
type CloseModelArgs,
|
|
12
13
|
type Tracer,
|
|
13
14
|
type TransferSavedEvent,
|
|
@@ -178,7 +179,18 @@ export type AstDocumentSavedEvent<TAst extends AstNode, TDiagnostic extends AstD
|
|
|
178
179
|
>;
|
|
179
180
|
|
|
180
181
|
/** Construction options for {@link AstDocumentManager}. */
|
|
181
|
-
export
|
|
182
|
+
export interface AstDocumentManagerOptions extends LogNameOptions {
|
|
183
|
+
/**
|
|
184
|
+
* Skip a queued save of a URI when a newer save of it is queued behind. The
|
|
185
|
+
* newer save took its text later, so disk ends the same with fewer writes.
|
|
186
|
+
* A skipped save announces nothing and takes the newer save's outcome: it
|
|
187
|
+
* resolves when that one lands and rejects with its error when it fails,
|
|
188
|
+
* since disk then holds neither text. Defaults to `false`: every save
|
|
189
|
+
* writes. The framework binds the manager without options, so turning this
|
|
190
|
+
* on means rebinding `AstDocumentManager` with them.
|
|
191
|
+
*/
|
|
192
|
+
readonly coalesceSaves?: boolean;
|
|
193
|
+
}
|
|
182
194
|
|
|
183
195
|
/**
|
|
184
196
|
* The document slot the model server and the integrity service talk to:
|
|
@@ -201,8 +213,29 @@ export interface AstDocumentManager<TAst extends AstNode, TDiagnostic extends As
|
|
|
201
213
|
|
|
202
214
|
/** Apply `text` as `clientId`'s edit. Resolves to the resulting text-document version. */
|
|
203
215
|
update(uri: string, text: string, clientId: string): Promise<number>;
|
|
216
|
+
/**
|
|
217
|
+
* Write the document's current text to disk through the URI's disk queue.
|
|
218
|
+
* The text is taken when this is called, so saves of one URI land in the
|
|
219
|
+
* order they were called.
|
|
220
|
+
*/
|
|
204
221
|
save(uri: string, clientId: string): Promise<void>;
|
|
205
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Run `task` once every disk task already queued for `uri` has settled, and
|
|
225
|
+
* before any queued after it. Every server-side disk access of a file that
|
|
226
|
+
* must not interleave with its saves goes through here: two writes of one
|
|
227
|
+
* file that bypass it can land in either order, and the older text then
|
|
228
|
+
* stays on disk. Tasks of different URIs run in parallel. A task that has
|
|
229
|
+
* nothing to do still resolves once the tasks before it have settled.
|
|
230
|
+
*
|
|
231
|
+
* A task must not await a build, nor a save, another disk task or an open
|
|
232
|
+
* of a document no client has open, all of the same URI: a build's
|
|
233
|
+
* integrity repair queues its own write here and the build waits for it,
|
|
234
|
+
* and such an open reads the file here, so a task waiting on either queued
|
|
235
|
+
* behind it never resolves, which wedges the URI's queue for good.
|
|
236
|
+
*/
|
|
237
|
+
queueDiskTask<T>(uri: string, task: () => Promise<T>): Promise<T>;
|
|
238
|
+
|
|
206
239
|
onUpdate(uri: string, listener: (event: AstDocumentUpdatedEvent<TAst, TDiagnostic>) => void): Disposable;
|
|
207
240
|
onSave(uri: string, listener: (event: AstDocumentSavedEvent<TAst, TDiagnostic>) => void | Promise<void>): Disposable;
|
|
208
241
|
onClientClosed(uri: string, clientId: string, listener: () => void): Disposable;
|
|
@@ -251,6 +284,17 @@ export class DefaultAstDocumentManager<
|
|
|
251
284
|
> implements AstDocumentManager<TAst, TDiagnostic> {
|
|
252
285
|
protected lastUpdate?: UpdateInfo;
|
|
253
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Per canonical URI, the settling of the last disk task queued for it; the
|
|
289
|
+
* next task chains behind it. An entry leaves once its URI's queue is idle.
|
|
290
|
+
* Kept outside the workspace lock, whose `write` cancels the write before
|
|
291
|
+
* it: a save cancelled that way reports success for text it never wrote.
|
|
292
|
+
*/
|
|
293
|
+
protected readonly diskQueues = new Map<CanonicalUri, Promise<void>>();
|
|
294
|
+
/** Per canonical URI, the newest save queued for it, which {@link coalesceSaves} lets older queued saves defer to. */
|
|
295
|
+
protected readonly newestSaves = new Map<CanonicalUri, Promise<void>>();
|
|
296
|
+
protected readonly coalesceSaves: boolean;
|
|
297
|
+
|
|
254
298
|
protected readonly textDocuments: HydraniumTextDocuments<TextDocument>;
|
|
255
299
|
protected readonly fileSystemProvider: WritableFileSystemProvider;
|
|
256
300
|
protected readonly langiumDocs: LangiumDocuments;
|
|
@@ -268,12 +312,19 @@ export class DefaultAstDocumentManager<
|
|
|
268
312
|
this.documentBuilder = services.workspace.DocumentBuilder;
|
|
269
313
|
this.uriPolicy = services.workspace.DocumentUriPolicy;
|
|
270
314
|
this.tracer = services.Tracer.for(options.logName ?? 'AstDocumentManager').trace('instantiated');
|
|
315
|
+
this.coalesceSaves = options.coalesceSaves ?? false;
|
|
271
316
|
this.textDocuments.onDidOpen(event =>
|
|
272
317
|
this.open({ clientId: event.clientId, uri: event.document.uri, languageId: event.document.languageId })
|
|
273
318
|
);
|
|
274
319
|
this.textDocuments.onDidClose(event => this.close({ clientId: event.clientId, uri: event.document.uri }));
|
|
275
320
|
this.documentBuilder.onUpdate((changed, deleted) => {
|
|
276
321
|
this.lastUpdate = { changed, deleted };
|
|
322
|
+
// The only place a deletion is observable: `DocumentBuilder.update`
|
|
323
|
+
// removes a deleted document before it builds anything, so no phase
|
|
324
|
+
// listener ever sees it.
|
|
325
|
+
for (const uri of deleted) {
|
|
326
|
+
this.textDocuments.notifyDocumentDeleted(uri.toString());
|
|
327
|
+
}
|
|
277
328
|
});
|
|
278
329
|
// Content transitions for CLOSED documents bypass the text store: the
|
|
279
330
|
// last-close revert and watched-file changes rebuild from disk into a
|
|
@@ -463,6 +514,12 @@ export class DefaultAstDocumentManager<
|
|
|
463
514
|
* callers don't need to pass it — the manager owns content and version
|
|
464
515
|
* sequencing.
|
|
465
516
|
*
|
|
517
|
+
* The text is taken synchronously, before the save waits in the URI's disk
|
|
518
|
+
* queue; the compare and the write run in the queue. Taken later, a save
|
|
519
|
+
* that waits behind another writes whatever the store holds when its turn
|
|
520
|
+
* comes, edits made after the call included, and announces that text under
|
|
521
|
+
* its own client id.
|
|
522
|
+
*
|
|
466
523
|
* **The write is skipped when the file already holds that text; the
|
|
467
524
|
* notification is not.** A save announces that the content is on disk, which
|
|
468
525
|
* is true either way — so a subscriber clearing a dirty marker or reacting to
|
|
@@ -481,15 +538,52 @@ export class DefaultAstDocumentManager<
|
|
|
481
538
|
throw new Error(`Document ${uri} hasn't been opened for saving yet`);
|
|
482
539
|
}
|
|
483
540
|
const text = document.getText();
|
|
484
|
-
|
|
485
|
-
|
|
541
|
+
let supersededBy: Promise<void> | undefined;
|
|
542
|
+
const saved: Promise<void> = this.queueDiskTask(canonical, async () => {
|
|
543
|
+
const newest = this.newestSaves.get(canonical);
|
|
544
|
+
if (this.coalesceSaves && newest !== saved) {
|
|
545
|
+
supersededBy = newest;
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
await this.writeSave(canonical, text, clientId);
|
|
549
|
+
})
|
|
550
|
+
.then(() => supersededBy)
|
|
551
|
+
.finally(() => {
|
|
552
|
+
if (this.newestSaves.get(canonical) === saved) {
|
|
553
|
+
this.newestSaves.delete(canonical);
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
this.newestSaves.set(canonical, saved);
|
|
557
|
+
return saved;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/** Write `text` to `uri` unless the file already holds it, then announce the save. Runs inside the URI's disk queue. */
|
|
561
|
+
protected async writeSave(uri: CanonicalUri, text: string, clientId: string): Promise<void> {
|
|
562
|
+
if (!(await this.matchesDisk(uri, text))) {
|
|
563
|
+
await this.tracer.with(uri).time(
|
|
486
564
|
`Write file (${text.length} bytes, from ${clientId})`,
|
|
487
565
|
// Async write so a slow disk does not block the event loop for the duration of the fs call.
|
|
488
|
-
() => this.fileSystemProvider.writeFile(UriUtils.toUri(
|
|
566
|
+
() => this.fileSystemProvider.writeFile(UriUtils.toUri(uri), text),
|
|
489
567
|
'debug'
|
|
490
568
|
);
|
|
491
569
|
}
|
|
492
|
-
this.textDocuments.notifyDidSaveTextDocument({ textDocument: TextDocumentIdentifier.create(
|
|
570
|
+
this.textDocuments.notifyDidSaveTextDocument({ textDocument: TextDocumentIdentifier.create(uri), text }, clientId);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
queueDiskTask<T>(uri: string, task: () => Promise<T>): Promise<T> {
|
|
574
|
+
const key = this.uriPolicy.canonicalUri(uri);
|
|
575
|
+
const result = (this.diskQueues.get(key) ?? Promise.resolve()).then(task);
|
|
576
|
+
const settled = result.then(
|
|
577
|
+
() => undefined,
|
|
578
|
+
() => undefined
|
|
579
|
+
);
|
|
580
|
+
this.diskQueues.set(key, settled);
|
|
581
|
+
void settled.then(() => {
|
|
582
|
+
if (this.diskQueues.get(key) === settled) {
|
|
583
|
+
this.diskQueues.delete(key);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
return result;
|
|
493
587
|
}
|
|
494
588
|
|
|
495
589
|
/**
|
|
@@ -534,7 +628,14 @@ export class DefaultAstDocumentManager<
|
|
|
534
628
|
version = 0,
|
|
535
629
|
text?: string
|
|
536
630
|
): Promise<TextDocumentItem> {
|
|
537
|
-
|
|
631
|
+
// Read in the disk queue: a read beside a queued save of the file returns
|
|
632
|
+
// the text from before it, and the document then opens on that.
|
|
633
|
+
return {
|
|
634
|
+
uri,
|
|
635
|
+
languageId,
|
|
636
|
+
version,
|
|
637
|
+
text: text ?? (await this.queueDiskTask(uri, () => this.fileSystemProvider.readFile(UriUtils.toUri(uri))))
|
|
638
|
+
};
|
|
538
639
|
}
|
|
539
640
|
|
|
540
641
|
/**
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
* Thrown by every call on a client session after it ended, and by an open that
|
|
12
|
+
* was still in flight when its session ended.
|
|
13
|
+
*
|
|
14
|
+
* The message names the client id, so it is addressed to whoever composes the
|
|
15
|
+
* system rather than to an end user.
|
|
16
|
+
*/
|
|
17
|
+
export class SessionClosedError extends Error {
|
|
18
|
+
constructor(readonly clientId: string) {
|
|
19
|
+
super(`Client session ${clientId} is closed`);
|
|
20
|
+
this.name = 'SessionClosedError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when a client session writes a document it does not have open.
|
|
26
|
+
*
|
|
27
|
+
* A session writes only what it has open, so this is the answer both to a write
|
|
28
|
+
* that never opened and to one whose open was closed underneath it — by the
|
|
29
|
+
* session itself, or by the document being deleted.
|
|
30
|
+
*/
|
|
31
|
+
export class DocumentNotOpenError extends Error {
|
|
32
|
+
constructor(
|
|
33
|
+
readonly uri: string,
|
|
34
|
+
readonly clientId: string
|
|
35
|
+
) {
|
|
36
|
+
super(`Document ${uri} is not open in client session ${clientId}`);
|
|
37
|
+
this.name = 'DocumentNotOpenError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Thrown when a client session is started under an id that is already live in
|
|
43
|
+
* the process, or that the framework reserves for itself.
|
|
44
|
+
*
|
|
45
|
+
* Ids are unique process-wide because the id is also the author label on every
|
|
46
|
+
* version and the key a client recognises its own echoes by; two participants
|
|
47
|
+
* sharing one would each take the other's writes for their own.
|
|
48
|
+
*/
|
|
49
|
+
export class DuplicateClientIdError extends Error {
|
|
50
|
+
constructor(readonly clientId: string) {
|
|
51
|
+
super(`Client id ${clientId} is already in use`);
|
|
52
|
+
this.name = 'DuplicateClientIdError';
|
|
53
|
+
}
|
|
54
|
+
}
|