From a96c52b21e7e590bbdd70b80896780a446fa2e8b Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 13 Dec 2021 02:07:04 +0100 Subject: build: separate module for frontend This allows us to simplify the webpack configuration and the gradle build scripts. --- subprojects/frontend/src/xtext/XtextClient.ts | 86 +++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 subprojects/frontend/src/xtext/XtextClient.ts (limited to 'subprojects/frontend/src/xtext/XtextClient.ts') 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 @@ +import type { + CompletionContext, + CompletionResult, +} from '@codemirror/autocomplete'; +import type { Transaction } from '@codemirror/state'; + +import type { EditorStore } from '../editor/EditorStore'; +import { ContentAssistService } from './ContentAssistService'; +import { HighlightingService } from './HighlightingService'; +import { OccurrencesService } from './OccurrencesService'; +import { UpdateService } from './UpdateService'; +import { getLogger } from '../utils/logger'; +import { ValidationService } from './ValidationService'; +import { XtextWebSocketClient } from './XtextWebSocketClient'; +import { XtextWebPushService } from './xtextMessages'; + +const log = getLogger('xtext.XtextClient'); + +export class XtextClient { + private readonly webSocketClient: XtextWebSocketClient; + + private readonly updateService: UpdateService; + + private readonly contentAssistService: ContentAssistService; + + private readonly highlightingService: HighlightingService; + + private readonly validationService: ValidationService; + + private readonly occurrencesService: OccurrencesService; + + constructor(store: EditorStore) { + this.webSocketClient = new XtextWebSocketClient( + () => this.updateService.onReconnect(), + (resource, stateId, service, push) => this.onPush(resource, stateId, service, push), + ); + this.updateService = new UpdateService(store, this.webSocketClient); + this.contentAssistService = new ContentAssistService(this.updateService); + this.highlightingService = new HighlightingService(store, this.updateService); + this.validationService = new ValidationService(store, this.updateService); + this.occurrencesService = new OccurrencesService( + store, + this.webSocketClient, + this.updateService, + ); + } + + onTransaction(transaction: Transaction): void { + // `ContentAssistService.prototype.onTransaction` needs the dirty change desc + // _before_ the current edit, so we call it before `updateService`. + this.contentAssistService.onTransaction(transaction); + this.updateService.onTransaction(transaction); + this.occurrencesService.onTransaction(transaction); + } + + private onPush(resource: string, stateId: string, service: XtextWebPushService, push: unknown) { + const { resourceName, xtextStateId } = this.updateService; + if (resource !== resourceName) { + log.error('Unknown resource name: expected:', resourceName, 'got:', resource); + return; + } + if (stateId !== xtextStateId) { + log.error('Unexpected xtext state id: expected:', xtextStateId, 'got:', stateId); + // The current push message might be stale (referring to a previous state), + // so this is not neccessarily an error and there is no need to force-reconnect. + return; + } + switch (service) { + case 'highlight': + this.highlightingService.onPush(push); + return; + case 'validate': + this.validationService.onPush(push); + } + } + + contentAssist(context: CompletionContext): Promise { + return this.contentAssistService.contentAssist(context); + } + + formatText(): void { + this.updateService.formatText().catch((e) => { + log.error('Error while formatting text', e); + }); + } +} -- cgit v1.2.3-70-g09d2