aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main/js/xtext/HighlightingService.ts
diff options
context:
space:
mode:
Diffstat (limited to 'language-web/src/main/js/xtext/HighlightingService.ts')
-rw-r--r--language-web/src/main/js/xtext/HighlightingService.ts43
1 files changed, 43 insertions, 0 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 @@
1import { Decoration } from '@codemirror/view';
2import { Range, RangeSet } from '@codemirror/rangeset';
3
4import type { EditorStore } from '../editor/EditorStore';
5import type { UpdateService } from './UpdateService';
6import { getLogger } from '../utils/logger';
7import { isHighlightingResult } from './xtextServiceResults';
8
9const log = getLogger('xtext.ValidationService');
10
11export 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}