diff options
author | 2023-09-12 21:59:50 +0200 | |
---|---|---|
committer | 2023-09-12 21:59:50 +0200 | |
commit | a2a4696fdbd6440269d576aeba7b25b2ea40d9bf (patch) | |
tree | 5cbdf981a51a09fbe162e7748555d213ca518ff4 /subprojects/frontend/src/xtext | |
parent | fix: avoid GLOP error message on stderr (diff) | |
download | refinery-a2a4696fdbd6440269d576aeba7b25b2ea40d9bf.tar.gz refinery-a2a4696fdbd6440269d576aeba7b25b2ea40d9bf.tar.zst refinery-a2a4696fdbd6440269d576aeba7b25b2ea40d9bf.zip |
feat: connect model generator to UI
Diffstat (limited to 'subprojects/frontend/src/xtext')
-rw-r--r-- | subprojects/frontend/src/xtext/ModelGenerationService.ts | 46 | ||||
-rw-r--r-- | subprojects/frontend/src/xtext/UpdateService.ts | 39 | ||||
-rw-r--r-- | subprojects/frontend/src/xtext/XtextClient.ts | 21 | ||||
-rw-r--r-- | subprojects/frontend/src/xtext/xtextMessages.ts | 1 | ||||
-rw-r--r-- | subprojects/frontend/src/xtext/xtextServiceResults.ts | 24 |
5 files changed, 130 insertions, 1 deletions
diff --git a/subprojects/frontend/src/xtext/ModelGenerationService.ts b/subprojects/frontend/src/xtext/ModelGenerationService.ts new file mode 100644 index 00000000..1e9f837a --- /dev/null +++ b/subprojects/frontend/src/xtext/ModelGenerationService.ts | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | import type EditorStore from '../editor/EditorStore'; | ||
8 | |||
9 | import type UpdateService from './UpdateService'; | ||
10 | import { ModelGenerationResult } from './xtextServiceResults'; | ||
11 | |||
12 | export default class ModelGenerationService { | ||
13 | constructor( | ||
14 | private readonly store: EditorStore, | ||
15 | private readonly updateService: UpdateService, | ||
16 | ) {} | ||
17 | |||
18 | onPush(push: unknown): void { | ||
19 | const result = ModelGenerationResult.parse(push); | ||
20 | if ('status' in result) { | ||
21 | this.store.setGeneratedModelMessage(result.uuid, result.status); | ||
22 | } else if ('error' in result) { | ||
23 | this.store.setGeneratedModelError(result.uuid, result.error); | ||
24 | } else { | ||
25 | this.store.setGeneratedModelSemantics(result.uuid, result); | ||
26 | } | ||
27 | } | ||
28 | |||
29 | onDisconnect(): void { | ||
30 | this.store.modelGenerationCancelled(); | ||
31 | } | ||
32 | |||
33 | async start(): Promise<void> { | ||
34 | const result = await this.updateService.startModelGeneration(); | ||
35 | if (!result.cancelled) { | ||
36 | this.store.addGeneratedModel(result.data.uuid); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | async cancel(): Promise<void> { | ||
41 | const result = await this.updateService.cancelModelGeneration(); | ||
42 | if (!result.cancelled) { | ||
43 | this.store.modelGenerationCancelled(); | ||
44 | } | ||
45 | } | ||
46 | } | ||
diff --git a/subprojects/frontend/src/xtext/UpdateService.ts b/subprojects/frontend/src/xtext/UpdateService.ts index 1ac722e1..d1246d5e 100644 --- a/subprojects/frontend/src/xtext/UpdateService.ts +++ b/subprojects/frontend/src/xtext/UpdateService.ts | |||
@@ -22,6 +22,7 @@ import { | |||
22 | FormattingResult, | 22 | FormattingResult, |
23 | isConflictResult, | 23 | isConflictResult, |
24 | OccurrencesResult, | 24 | OccurrencesResult, |
25 | ModelGenerationStartedResult, | ||
25 | } from './xtextServiceResults'; | 26 | } from './xtextServiceResults'; |
26 | 27 | ||
27 | const UPDATE_TIMEOUT_MS = 500; | 28 | const UPDATE_TIMEOUT_MS = 500; |
@@ -341,4 +342,42 @@ export default class UpdateService { | |||
341 | } | 342 | } |
342 | return { cancelled: false, data: parsedOccurrencesResult }; | 343 | return { cancelled: false, data: parsedOccurrencesResult }; |
343 | } | 344 | } |
345 | |||
346 | async startModelGeneration(): Promise< | ||
347 | CancellableResult<ModelGenerationStartedResult> | ||
348 | > { | ||
349 | try { | ||
350 | await this.updateOrThrow(); | ||
351 | } catch (error) { | ||
352 | if (error instanceof CancelledError || error instanceof TimeoutError) { | ||
353 | return { cancelled: true }; | ||
354 | } | ||
355 | throw error; | ||
356 | } | ||
357 | log.debug('Starting model generation'); | ||
358 | const data = await this.webSocketClient.send({ | ||
359 | resource: this.resourceName, | ||
360 | serviceType: 'modelGeneration', | ||
361 | requiredStateId: this.xtextStateId, | ||
362 | start: true, | ||
363 | }); | ||
364 | if (isConflictResult(data)) { | ||
365 | return { cancelled: true }; | ||
366 | } | ||
367 | const parsedResult = ModelGenerationStartedResult.parse(data); | ||
368 | return { cancelled: false, data: parsedResult }; | ||
369 | } | ||
370 | |||
371 | async cancelModelGeneration(): Promise<CancellableResult<unknown>> { | ||
372 | log.debug('Cancelling model generation'); | ||
373 | const data = await this.webSocketClient.send({ | ||
374 | resource: this.resourceName, | ||
375 | serviceType: 'modelGeneration', | ||
376 | cancel: true, | ||
377 | }); | ||
378 | if (isConflictResult(data)) { | ||
379 | return { cancelled: true }; | ||
380 | } | ||
381 | return { cancelled: false, data }; | ||
382 | } | ||
344 | } | 383 | } |
diff --git a/subprojects/frontend/src/xtext/XtextClient.ts b/subprojects/frontend/src/xtext/XtextClient.ts index 87778084..77980d35 100644 --- a/subprojects/frontend/src/xtext/XtextClient.ts +++ b/subprojects/frontend/src/xtext/XtextClient.ts | |||
@@ -16,6 +16,7 @@ import getLogger from '../utils/getLogger'; | |||
16 | 16 | ||
17 | import ContentAssistService from './ContentAssistService'; | 17 | import ContentAssistService from './ContentAssistService'; |
18 | import HighlightingService from './HighlightingService'; | 18 | import HighlightingService from './HighlightingService'; |
19 | import ModelGenerationService from './ModelGenerationService'; | ||
19 | import OccurrencesService from './OccurrencesService'; | 20 | import OccurrencesService from './OccurrencesService'; |
20 | import SemanticsService from './SemanticsService'; | 21 | import SemanticsService from './SemanticsService'; |
21 | import UpdateService from './UpdateService'; | 22 | import UpdateService from './UpdateService'; |
@@ -40,6 +41,8 @@ export default class XtextClient { | |||
40 | 41 | ||
41 | private readonly semanticsService: SemanticsService; | 42 | private readonly semanticsService: SemanticsService; |
42 | 43 | ||
44 | private readonly modelGenerationService: ModelGenerationService; | ||
45 | |||
43 | constructor( | 46 | constructor( |
44 | private readonly store: EditorStore, | 47 | private readonly store: EditorStore, |
45 | private readonly pwaStore: PWAStore, | 48 | private readonly pwaStore: PWAStore, |
@@ -58,6 +61,10 @@ export default class XtextClient { | |||
58 | this.validationService = new ValidationService(store, this.updateService); | 61 | this.validationService = new ValidationService(store, this.updateService); |
59 | this.occurrencesService = new OccurrencesService(store, this.updateService); | 62 | this.occurrencesService = new OccurrencesService(store, this.updateService); |
60 | this.semanticsService = new SemanticsService(store, this.validationService); | 63 | this.semanticsService = new SemanticsService(store, this.validationService); |
64 | this.modelGenerationService = new ModelGenerationService( | ||
65 | store, | ||
66 | this.updateService, | ||
67 | ); | ||
61 | } | 68 | } |
62 | 69 | ||
63 | start(): void { | 70 | start(): void { |
@@ -75,6 +82,7 @@ export default class XtextClient { | |||
75 | this.highlightingService.onDisconnect(); | 82 | this.highlightingService.onDisconnect(); |
76 | this.validationService.onDisconnect(); | 83 | this.validationService.onDisconnect(); |
77 | this.occurrencesService.onDisconnect(); | 84 | this.occurrencesService.onDisconnect(); |
85 | this.modelGenerationService.onDisconnect(); | ||
78 | } | 86 | } |
79 | 87 | ||
80 | onTransaction(transaction: Transaction): void { | 88 | onTransaction(transaction: Transaction): void { |
@@ -101,7 +109,7 @@ export default class XtextClient { | |||
101 | ); | 109 | ); |
102 | return; | 110 | return; |
103 | } | 111 | } |
104 | if (stateId !== xtextStateId) { | 112 | if (stateId !== xtextStateId && service !== 'modelGeneration') { |
105 | log.error( | 113 | log.error( |
106 | 'Unexpected xtext state id: expected:', | 114 | 'Unexpected xtext state id: expected:', |
107 | xtextStateId, | 115 | xtextStateId, |
@@ -122,6 +130,9 @@ export default class XtextClient { | |||
122 | case 'semantics': | 130 | case 'semantics': |
123 | this.semanticsService.onPush(push); | 131 | this.semanticsService.onPush(push); |
124 | return; | 132 | return; |
133 | case 'modelGeneration': | ||
134 | this.modelGenerationService.onPush(push); | ||
135 | return; | ||
125 | default: | 136 | default: |
126 | throw new Error('Unknown service'); | 137 | throw new Error('Unknown service'); |
127 | } | 138 | } |
@@ -131,6 +142,14 @@ export default class XtextClient { | |||
131 | return this.contentAssistService.contentAssist(context); | 142 | return this.contentAssistService.contentAssist(context); |
132 | } | 143 | } |
133 | 144 | ||
145 | startModelGeneration(): Promise<void> { | ||
146 | return this.modelGenerationService.start(); | ||
147 | } | ||
148 | |||
149 | cancelModelGeneration(): Promise<void> { | ||
150 | return this.modelGenerationService.cancel(); | ||
151 | } | ||
152 | |||
134 | formatText(): void { | 153 | formatText(): void { |
135 | this.updateService.formatText().catch((e) => { | 154 | this.updateService.formatText().catch((e) => { |
136 | log.error('Error while formatting text', e); | 155 | log.error('Error while formatting text', e); |
diff --git a/subprojects/frontend/src/xtext/xtextMessages.ts b/subprojects/frontend/src/xtext/xtextMessages.ts index 971720e1..15831c5a 100644 --- a/subprojects/frontend/src/xtext/xtextMessages.ts +++ b/subprojects/frontend/src/xtext/xtextMessages.ts | |||
@@ -38,6 +38,7 @@ export const XtextWebPushService = z.enum([ | |||
38 | 'highlight', | 38 | 'highlight', |
39 | 'validate', | 39 | 'validate', |
40 | 'semantics', | 40 | 'semantics', |
41 | 'modelGeneration', | ||
41 | ]); | 42 | ]); |
42 | 43 | ||
43 | export type XtextWebPushService = z.infer<typeof XtextWebPushService>; | 44 | export type XtextWebPushService = z.infer<typeof XtextWebPushService>; |
diff --git a/subprojects/frontend/src/xtext/xtextServiceResults.ts b/subprojects/frontend/src/xtext/xtextServiceResults.ts index caf2cf0b..e473bd48 100644 --- a/subprojects/frontend/src/xtext/xtextServiceResults.ts +++ b/subprojects/frontend/src/xtext/xtextServiceResults.ts | |||
@@ -126,6 +126,14 @@ export const FormattingResult = DocumentStateResult.extend({ | |||
126 | 126 | ||
127 | export type FormattingResult = z.infer<typeof FormattingResult>; | 127 | export type FormattingResult = z.infer<typeof FormattingResult>; |
128 | 128 | ||
129 | export const ModelGenerationStartedResult = z.object({ | ||
130 | uuid: z.string().nonempty(), | ||
131 | }); | ||
132 | |||
133 | export type ModelGenerationStartedResult = z.infer< | ||
134 | typeof ModelGenerationStartedResult | ||
135 | >; | ||
136 | |||
129 | export const NodeMetadata = z.object({ | 137 | export const NodeMetadata = z.object({ |
130 | name: z.string(), | 138 | name: z.string(), |
131 | simpleName: z.string(), | 139 | simpleName: z.string(), |
@@ -171,3 +179,19 @@ export const SemanticsResult = z.union([ | |||
171 | ]); | 179 | ]); |
172 | 180 | ||
173 | export type SemanticsResult = z.infer<typeof SemanticsResult>; | 181 | export type SemanticsResult = z.infer<typeof SemanticsResult>; |
182 | |||
183 | export const ModelGenerationResult = z.union([ | ||
184 | z.object({ | ||
185 | uuid: z.string().nonempty(), | ||
186 | status: z.string(), | ||
187 | }), | ||
188 | z.object({ | ||
189 | uuid: z.string().nonempty(), | ||
190 | error: z.string(), | ||
191 | }), | ||
192 | SemanticsSuccessResult.extend({ | ||
193 | uuid: z.string().nonempty(), | ||
194 | }), | ||
195 | ]); | ||
196 | |||
197 | export type ModelGenerationResult = z.infer<typeof ModelGenerationResult>; | ||