Skip to content

Commit f3cf206

Browse files
authored
Emit onUpdate event on DocumentBuilder#build (#1190)
1 parent 03da179 commit f3cf206

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

packages/langium/src/workspace/document-builder.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface DocumentBuilder {
8181
onBuildPhase(targetState: DocumentState, callback: DocumentBuildListener): Disposable;
8282
}
8383

84-
export type DocumentUpdateListener = (changed: URI[], deleted: URI[]) => void
84+
export type DocumentUpdateListener = (changed: URI[], deleted: URI[]) => void | Promise<void>
8585
export type DocumentBuildListener = (built: LangiumDocument[], cancelToken: CancellationToken) => void | Promise<void>
8686
export class DefaultDocumentBuilder implements DocumentBuilder {
8787

@@ -144,6 +144,7 @@ export class DefaultDocumentBuilder implements DocumentBuilder {
144144
this.buildState.delete(key);
145145
}
146146
}
147+
await this.emitUpdate(documents.map(e => e.uri), []);
147148
await this.buildDocuments(documents, options, cancelToken);
148149
}
149150

@@ -173,9 +174,7 @@ export class DefaultDocumentBuilder implements DocumentBuilder {
173174
doc.diagnostics = undefined;
174175
});
175176
// Notify listeners of the update
176-
for (const listener of this.updateListeners) {
177-
listener(changed, deleted);
178-
}
177+
await this.emitUpdate(changed, deleted);
179178
// Only allow interrupting the execution after all state changes are done
180179
await interruptAndCheck(cancelToken);
181180

@@ -191,6 +190,10 @@ export class DefaultDocumentBuilder implements DocumentBuilder {
191190
await this.buildDocuments(rebuildDocuments, this.updateBuildOptions, cancelToken);
192191
}
193192

193+
protected async emitUpdate(changed: URI[], deleted: URI[]): Promise<void> {
194+
await Promise.all(this.updateListeners.map(listener => listener(changed, deleted)));
195+
}
196+
194197
/**
195198
* Check whether the given document should be relinked after changes were found in the given URIs.
196199
*/

packages/langium/test/grammar/type-system/inferred-types.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ describe('Inferred types', () => {
292292
});
293293

294294
test('Should infer data type rules as unions', async () => {
295-
expectTypes(`
295+
await expectTypes(`
296296
Strings returns string: 'a' | 'b' | 'c';
297297
MoreStrings returns string: Strings | 'd' | 'e';
298298
Complex returns string: ID ('.' ID)*;
@@ -323,7 +323,7 @@ describe('Inferred types', () => {
323323
});
324324

325325
test('Infers X as a super interface of Y and Z with property `id`', async () => {
326-
expectTypes(`
326+
await expectTypes(`
327327
entry X: id=ID ({infer Y} 'a' | {infer Z} 'b');
328328
terminal ID: /[a-zA-Z_][a-zA-Z0-9_]*/;
329329
`, expandToString`
@@ -343,7 +343,7 @@ describe('Inferred types', () => {
343343

344344
describe('inferred types that are used by the grammar', () => {
345345
test('B is defined and A is not', async () => {
346-
expectTypes(`
346+
await expectTypes(`
347347
A infers B: 'a' name=ID (otherA=[B])?;
348348
hidden terminal WS: /\\s+/;
349349
terminal ID: /[a-zA-Z_][a-zA-Z0-9_]*/;
@@ -359,7 +359,7 @@ describe('inferred types that are used by the grammar', () => {
359359

360360
describe('inferred and declared types', () => {
361361
test('Declared interfaces should be preserved as interfaces', async () => {
362-
expectTypes(`
362+
await expectTypes(`
363363
X returns X: Y | Z;
364364
Y: y='y';
365365
Z: z='z';
@@ -881,10 +881,10 @@ describe('generated types from declared types include all of them', () => {
881881
// });
882882

883883
const services = createLangiumGrammarServices(EmptyFileSystem).grammar;
884+
const helper = parseHelper<Grammar>(services);
884885

885886
async function getTypes(grammar: string): Promise<AstTypes> {
886887
await clearDocuments(services);
887-
const helper = parseHelper<Grammar>(services);
888888
const result = await helper(grammar);
889889
const gram = result.parseResult.value;
890890
return collectAst(gram);

packages/langium/test/workspace/document-builder.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,42 @@ describe('DefaultDocumentBuilder', () => {
4545
return services;
4646
}
4747

48+
test('emits `onUpdate` on `update` call', async () => {
49+
const services = await createServices();
50+
const documentFactory = services.shared.workspace.LangiumDocumentFactory;
51+
const documents = services.shared.workspace.LangiumDocuments;
52+
const document = documentFactory.fromString('', URI.parse('file:///test1.txt'));
53+
documents.addDocument(document);
54+
55+
const builder = services.shared.workspace.DocumentBuilder;
56+
await builder.build([document], {});
57+
addTextDocument(document, services);
58+
let called = false;
59+
builder.onUpdate(() => {
60+
called = true;
61+
});
62+
await builder.update([document.uri], []);
63+
expect(called).toBe(true);
64+
});
65+
66+
test('emits `onUpdate` on `build` call', async () => {
67+
const services = await createServices();
68+
const documentFactory = services.shared.workspace.LangiumDocumentFactory;
69+
const documents = services.shared.workspace.LangiumDocuments;
70+
const document = documentFactory.fromString('', URI.parse('file:///test1.txt'));
71+
documents.addDocument(document);
72+
73+
const builder = services.shared.workspace.DocumentBuilder;
74+
await builder.build([document], {});
75+
addTextDocument(document, services);
76+
let called = false;
77+
builder.onUpdate(() => {
78+
called = true;
79+
});
80+
await builder.build([document]);
81+
expect(called).toBe(true);
82+
});
83+
4884
test('resumes document build after cancellation', async () => {
4985
const services = await createServices();
5086
const documentFactory = services.shared.workspace.LangiumDocumentFactory;

0 commit comments

Comments
 (0)