diff options
Diffstat (limited to 'language-web/src/main/js/xtext')
-rw-r--r-- | language-web/src/main/js/xtext/HighlightingService.ts | 43 | ||||
-rw-r--r-- | language-web/src/main/js/xtext/ValidationService.ts | 17 | ||||
-rw-r--r-- | language-web/src/main/js/xtext/XtextClient.ts | 10 | ||||
-rw-r--r-- | language-web/src/main/js/xtext/xtextServiceResults.ts | 26 |
4 files changed, 87 insertions, 9 deletions
diff --git a/language-web/src/main/js/xtext/HighlightingService.ts b/language-web/src/main/js/xtext/HighlightingService.ts new file mode 100644 index 00000000..b8ceed20 --- /dev/null +++ b/language-web/src/main/js/xtext/HighlightingService.ts | |||
@@ -0,0 +1,43 @@ | |||
1 | import { Decoration } from '@codemirror/view'; | ||
2 | import { Range, RangeSet } from '@codemirror/rangeset'; | ||
3 | |||
4 | import type { EditorStore } from '../editor/EditorStore'; | ||
5 | import type { UpdateService } from './UpdateService'; | ||
6 | import { getLogger } from '../utils/logger'; | ||
7 | import { isHighlightingResult } from './xtextServiceResults'; | ||
8 | |||
9 | const log = getLogger('xtext.ValidationService'); | ||
10 | |||
11 | export class HighlightingService { | ||
12 | private store: EditorStore; | ||
13 | |||
14 | private updateService: UpdateService; | ||
15 | |||
16 | constructor(store: EditorStore, updateService: UpdateService) { | ||
17 | this.store = store; | ||
18 | this.updateService = updateService; | ||
19 | } | ||
20 | |||
21 | onPush(push: unknown): void { | ||
22 | if (!isHighlightingResult(push)) { | ||
23 | log.error('Invalid highlighting result', push); | ||
24 | return; | ||
25 | } | ||
26 | const allChanges = this.updateService.computeChangesSinceLastUpdate(); | ||
27 | const decorations: Range<Decoration>[] = []; | ||
28 | push.regions.forEach(({ offset, length, styleClasses }) => { | ||
29 | if (styleClasses.length === 0) { | ||
30 | return; | ||
31 | } | ||
32 | const from = allChanges.mapPos(offset); | ||
33 | const to = allChanges.mapPos(offset + length); | ||
34 | if (to <= from) { | ||
35 | return; | ||
36 | } | ||
37 | decorations.push(Decoration.mark({ | ||
38 | class: styleClasses.map((c) => `cmt-problem-${c}`).join(' '), | ||
39 | }).range(from, to)); | ||
40 | }); | ||
41 | this.store.updateSemanticHighlighting(RangeSet.of(decorations, true)); | ||
42 | } | ||
43 | } | ||
diff --git a/language-web/src/main/js/xtext/ValidationService.ts b/language-web/src/main/js/xtext/ValidationService.ts index 163b5535..31c8f716 100644 --- a/language-web/src/main/js/xtext/ValidationService.ts +++ b/language-web/src/main/js/xtext/ValidationService.ts | |||
@@ -24,15 +24,20 @@ export class ValidationService { | |||
24 | } | 24 | } |
25 | const allChanges = this.updateService.computeChangesSinceLastUpdate(); | 25 | const allChanges = this.updateService.computeChangesSinceLastUpdate(); |
26 | const diagnostics: Diagnostic[] = []; | 26 | const diagnostics: Diagnostic[] = []; |
27 | push.issues.forEach((issue) => { | 27 | push.issues.forEach(({ |
28 | if (issue.severity === 'ignore') { | 28 | offset, |
29 | length, | ||
30 | severity, | ||
31 | description, | ||
32 | }) => { | ||
33 | if (severity === 'ignore') { | ||
29 | return; | 34 | return; |
30 | } | 35 | } |
31 | diagnostics.push({ | 36 | diagnostics.push({ |
32 | from: allChanges.mapPos(issue.offset), | 37 | from: allChanges.mapPos(offset), |
33 | to: allChanges.mapPos(issue.offset + issue.length), | 38 | to: allChanges.mapPos(offset + length), |
34 | severity: issue.severity, | 39 | severity, |
35 | message: issue.description, | 40 | message: description, |
36 | }); | 41 | }); |
37 | }); | 42 | }); |
38 | this.store.updateDiagnostics(diagnostics); | 43 | this.store.updateDiagnostics(diagnostics); |
diff --git a/language-web/src/main/js/xtext/XtextClient.ts b/language-web/src/main/js/xtext/XtextClient.ts index 7683a8ef..ccb58ab4 100644 --- a/language-web/src/main/js/xtext/XtextClient.ts +++ b/language-web/src/main/js/xtext/XtextClient.ts | |||
@@ -6,6 +6,7 @@ import type { Transaction } from '@codemirror/state'; | |||
6 | 6 | ||
7 | import type { EditorStore } from '../editor/EditorStore'; | 7 | import type { EditorStore } from '../editor/EditorStore'; |
8 | import { ContentAssistService } from './ContentAssistService'; | 8 | import { ContentAssistService } from './ContentAssistService'; |
9 | import { HighlightingService } from './HighlightingService'; | ||
9 | import { UpdateService } from './UpdateService'; | 10 | import { UpdateService } from './UpdateService'; |
10 | import { getLogger } from '../utils/logger'; | 11 | import { getLogger } from '../utils/logger'; |
11 | import { ValidationService } from './ValidationService'; | 12 | import { ValidationService } from './ValidationService'; |
@@ -20,6 +21,8 @@ export class XtextClient { | |||
20 | 21 | ||
21 | private contentAssistService: ContentAssistService; | 22 | private contentAssistService: ContentAssistService; |
22 | 23 | ||
24 | private highlightingService: HighlightingService; | ||
25 | |||
23 | private validationService: ValidationService; | 26 | private validationService: ValidationService; |
24 | 27 | ||
25 | constructor(store: EditorStore) { | 28 | constructor(store: EditorStore) { |
@@ -29,6 +32,7 @@ export class XtextClient { | |||
29 | ); | 32 | ); |
30 | this.updateService = new UpdateService(store, this.webSocketClient); | 33 | this.updateService = new UpdateService(store, this.webSocketClient); |
31 | this.contentAssistService = new ContentAssistService(this.updateService); | 34 | this.contentAssistService = new ContentAssistService(this.updateService); |
35 | this.highlightingService = new HighlightingService(store, this.updateService); | ||
32 | this.validationService = new ValidationService(store, this.updateService); | 36 | this.validationService = new ValidationService(store, this.updateService); |
33 | } | 37 | } |
34 | 38 | ||
@@ -50,12 +54,12 @@ export class XtextClient { | |||
50 | await this.updateService.updateFullText(); | 54 | await this.updateService.updateFullText(); |
51 | } | 55 | } |
52 | switch (service) { | 56 | switch (service) { |
57 | case 'highlight': | ||
58 | this.highlightingService.onPush(push); | ||
59 | return; | ||
53 | case 'validate': | 60 | case 'validate': |
54 | this.validationService.onPush(push); | 61 | this.validationService.onPush(push); |
55 | return; | 62 | return; |
56 | case 'highlight': | ||
57 | // TODO | ||
58 | return; | ||
59 | default: | 63 | default: |
60 | log.error('Unknown push service:', service); | 64 | log.error('Unknown push service:', service); |
61 | break; | 65 | break; |
diff --git a/language-web/src/main/js/xtext/xtextServiceResults.ts b/language-web/src/main/js/xtext/xtextServiceResults.ts index 6c3d9daf..e32d49c3 100644 --- a/language-web/src/main/js/xtext/xtextServiceResults.ts +++ b/language-web/src/main/js/xtext/xtextServiceResults.ts | |||
@@ -198,3 +198,29 @@ export function isContentAssistResult(result: unknown): result is IContentAssist | |||
198 | return isDocumentStateResult(result) | 198 | return isDocumentStateResult(result) |
199 | && isArrayOfType(contentAssistResult.entries, isContentAssistEntry); | 199 | && isArrayOfType(contentAssistResult.entries, isContentAssistEntry); |
200 | } | 200 | } |
201 | |||
202 | export interface IHighlightingRegion { | ||
203 | offset: number; | ||
204 | |||
205 | length: number; | ||
206 | |||
207 | styleClasses: string[]; | ||
208 | } | ||
209 | |||
210 | export function isHighlightingRegion(value: unknown): value is IHighlightingRegion { | ||
211 | const region = value as IHighlightingRegion; | ||
212 | return typeof region === 'object' | ||
213 | && typeof region.offset === 'number' | ||
214 | && typeof region.length === 'number' | ||
215 | && isArrayOfType(region.styleClasses, (s): s is string => typeof s === 'string'); | ||
216 | } | ||
217 | |||
218 | export interface IHighlightingResult { | ||
219 | regions: IHighlightingRegion[]; | ||
220 | } | ||
221 | |||
222 | export function isHighlightingResult(result: unknown): result is IHighlightingResult { | ||
223 | const highlightingResult = result as IHighlightingResult; | ||
224 | return typeof highlightingResult === 'object' | ||
225 | && isArrayOfType(highlightingResult.regions, isHighlightingRegion); | ||
226 | } | ||