aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/xtext/XtextClient.ts
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/frontend/src/xtext/XtextClient.ts')
-rw-r--r--subprojects/frontend/src/xtext/XtextClient.ts86
1 files changed, 86 insertions, 0 deletions
diff --git a/subprojects/frontend/src/xtext/XtextClient.ts b/subprojects/frontend/src/xtext/XtextClient.ts
new file mode 100644
index 00000000..0898e725
--- /dev/null
+++ b/subprojects/frontend/src/xtext/XtextClient.ts
@@ -0,0 +1,86 @@
1import type {
2 CompletionContext,
3 CompletionResult,
4} from '@codemirror/autocomplete';
5import type { Transaction } from '@codemirror/state';
6
7import type { EditorStore } from '../editor/EditorStore';
8import { ContentAssistService } from './ContentAssistService';
9import { HighlightingService } from './HighlightingService';
10import { OccurrencesService } from './OccurrencesService';
11import { UpdateService } from './UpdateService';
12import { getLogger } from '../utils/logger';
13import { ValidationService } from './ValidationService';
14import { XtextWebSocketClient } from './XtextWebSocketClient';
15import { XtextWebPushService } from './xtextMessages';
16
17const log = getLogger('xtext.XtextClient');
18
19export class XtextClient {
20 private readonly webSocketClient: XtextWebSocketClient;
21
22 private readonly updateService: UpdateService;
23
24 private readonly contentAssistService: ContentAssistService;
25
26 private readonly highlightingService: HighlightingService;
27
28 private readonly validationService: ValidationService;
29
30 private readonly occurrencesService: OccurrencesService;
31
32 constructor(store: EditorStore) {
33 this.webSocketClient = new XtextWebSocketClient(
34 () => this.updateService.onReconnect(),
35 (resource, stateId, service, push) => this.onPush(resource, stateId, service, push),
36 );
37 this.updateService = new UpdateService(store, this.webSocketClient);
38 this.contentAssistService = new ContentAssistService(this.updateService);
39 this.highlightingService = new HighlightingService(store, this.updateService);
40 this.validationService = new ValidationService(store, this.updateService);
41 this.occurrencesService = new OccurrencesService(
42 store,
43 this.webSocketClient,
44 this.updateService,
45 );
46 }
47
48 onTransaction(transaction: Transaction): void {
49 // `ContentAssistService.prototype.onTransaction` needs the dirty change desc
50 // _before_ the current edit, so we call it before `updateService`.
51 this.contentAssistService.onTransaction(transaction);
52 this.updateService.onTransaction(transaction);
53 this.occurrencesService.onTransaction(transaction);
54 }
55
56 private onPush(resource: string, stateId: string, service: XtextWebPushService, push: unknown) {
57 const { resourceName, xtextStateId } = this.updateService;
58 if (resource !== resourceName) {
59 log.error('Unknown resource name: expected:', resourceName, 'got:', resource);
60 return;
61 }
62 if (stateId !== xtextStateId) {
63 log.error('Unexpected xtext state id: expected:', xtextStateId, 'got:', stateId);
64 // The current push message might be stale (referring to a previous state),
65 // so this is not neccessarily an error and there is no need to force-reconnect.
66 return;
67 }
68 switch (service) {
69 case 'highlight':
70 this.highlightingService.onPush(push);
71 return;
72 case 'validate':
73 this.validationService.onPush(push);
74 }
75 }
76
77 contentAssist(context: CompletionContext): Promise<CompletionResult> {
78 return this.contentAssistService.contentAssist(context);
79 }
80
81 formatText(): void {
82 this.updateService.formatText().catch((e) => {
83 log.error('Error while formatting text', e);
84 });
85 }
86}