From 84709127b4f8b0797e10b4a2807a1c12305a877d Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Mon, 4 Nov 2024 18:36:40 +0100 Subject: [PATCH 1/2] fix: multiple document-builder listeners Signed-off-by: Christian Dietrich --- .../langium/src/workspace/document-builder.ts | 6 +++-- .../test/workspace/document-builder.test.ts | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/langium/src/workspace/document-builder.ts b/packages/langium/src/workspace/document-builder.ts index efda59692..fedd687a4 100644 --- a/packages/langium/src/workspace/document-builder.ts +++ b/packages/langium/src/workspace/document-builder.ts @@ -452,7 +452,8 @@ export class DefaultDocumentBuilder implements DocumentBuilder { protected async notifyDocumentPhase(document: LangiumDocument, state: DocumentState, cancelToken: CancellationToken): Promise { const listeners = this.documentPhaseListeners.get(state); - for (const listener of listeners) { + const listenersCopy = listeners.slice(); + for (const listener of listenersCopy) { try { await listener(document, cancelToken); } catch (err) { @@ -471,7 +472,8 @@ export class DefaultDocumentBuilder implements DocumentBuilder { return; } const listeners = this.buildPhaseListeners.get(state); - for (const listener of listeners) { + const listenersCopy = listeners.slice(); + for (const listener of listenersCopy) { await interruptAndCheck(cancelToken); await listener(documents, cancelToken); } diff --git a/packages/langium/test/workspace/document-builder.test.ts b/packages/langium/test/workspace/document-builder.test.ts index 74c64a71a..4affca2b0 100644 --- a/packages/langium/test/workspace/document-builder.test.ts +++ b/packages/langium/test/workspace/document-builder.test.ts @@ -283,6 +283,30 @@ describe('DefaultDocumentBuilder', () => { ]); }); + test('can handle multiple listeners', async () => { + const services = await createServices(); + const workspace = services.shared.workspace; + const documentFactory = workspace.LangiumDocumentFactory; + const documents = workspace.LangiumDocuments; + const uri = URI.parse('file:///test1.txt'); + const document1 = documentFactory.fromString(` + foo 1 A + foo 11 B + bar A + bar B + `, uri); + documents.addDocument(document1); + + const builder = workspace.DocumentBuilder; + const p1 = builder.waitUntil(DocumentState.IndexedReferences, uri).then(() => { + }); + const p2 = builder.waitUntil(DocumentState.IndexedReferences, uri).then(() => { + }); + await builder.build([document1], {}); + await Promise.all([p1, p2]); + expect(document1.state).toBe(DocumentState.IndexedReferences); + }); + test('waits until a specific workspace stage has been reached', async () => { const services = await createServices(); const documentFactory = services.shared.workspace.LangiumDocumentFactory; From 5c2985f7bb86cf6cff132588caf2928e0ebad232 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Mon, 4 Nov 2024 19:26:24 +0100 Subject: [PATCH 2/2] More tests Signed-off-by: Christian Dietrich --- .../test/workspace/document-builder.test.ts | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/langium/test/workspace/document-builder.test.ts b/packages/langium/test/workspace/document-builder.test.ts index 4affca2b0..1241bb44e 100644 --- a/packages/langium/test/workspace/document-builder.test.ts +++ b/packages/langium/test/workspace/document-builder.test.ts @@ -283,7 +283,7 @@ describe('DefaultDocumentBuilder', () => { ]); }); - test('can handle multiple listeners', async () => { + test('can handle multiple listeners (buildPhase)', async () => { const services = await createServices(); const workspace = services.shared.workspace; const documentFactory = workspace.LangiumDocumentFactory; @@ -307,6 +307,36 @@ describe('DefaultDocumentBuilder', () => { expect(document1.state).toBe(DocumentState.IndexedReferences); }); + test('can handle multiple listeners (documentPhase)', async () => { + const services = await createServices(); + const workspace = services.shared.workspace; + const documentFactory = workspace.LangiumDocumentFactory; + const documents = workspace.LangiumDocuments; + const uri = URI.parse('file:///test1.txt'); + const document1 = documentFactory.fromString(` + foo 1 A + foo 11 B + bar A + bar B + `, uri); + documents.addDocument(document1); + + const builder = workspace.DocumentBuilder; + let p1called = false; + const p1 = builder.onDocumentPhase(DocumentState.IndexedReferences, (_d) => { + p1called = true; + p1.dispose(); + }); + let p2called = false; + const p2 = builder.onDocumentPhase(DocumentState.IndexedReferences, (_d) => { + p2called = true; + p2.dispose(); + }); + await builder.build([document1], {}); + expect(p1called).toBe(true); + expect(p2called).toBe(true); + }); + test('waits until a specific workspace stage has been reached', async () => { const services = await createServices(); const documentFactory = services.shared.workspace.LangiumDocumentFactory;