@adecore/editor-react 0.31.12 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/AnchoredPopup.js +73 -19
  2. package/dist/AttributionCard.js +162 -4
  3. package/dist/BaselineStatus.js +62 -8
  4. package/dist/CallHierarchyPanel.js +977 -60
  5. package/dist/ChangeReview.js +76 -25
  6. package/dist/CodeAuthorsCard.js +314 -14
  7. package/dist/CompletionPopup.js +490 -83
  8. package/dist/DiffView.js +548 -181
  9. package/dist/EditorContextMenu.js +352 -34
  10. package/dist/EditorView.js +276 -99
  11. package/dist/FindReplace.js +525 -67
  12. package/dist/HoverCard.js +378 -38
  13. package/dist/HoverSections.js +367 -56
  14. package/dist/LanguagePopups.js +95 -34
  15. package/dist/Markdown.js +41 -6
  16. package/dist/PanelResizeHandle.js +199 -66
  17. package/dist/PathText.js +49 -7
  18. package/dist/PeekPanel.js +675 -72
  19. package/dist/PickPopup.js +304 -34
  20. package/dist/RenameCard.js +679 -85
  21. package/dist/RenderedDocs.js +329 -58
  22. package/dist/SignatureCard.js +91 -7
  23. package/dist/SplitDiffView.js +344 -254
  24. package/dist/SymbolPicker.js +440 -85
  25. package/dist/call-hierarchy-model.js +102 -68
  26. package/dist/call-hierarchy.js +458 -359
  27. package/dist/code-actions-model.js +88 -76
  28. package/dist/code-actions.js +372 -283
  29. package/dist/code-authors.js +64 -55
  30. package/dist/code-vision-model.js +134 -127
  31. package/dist/code-vision.js +224 -206
  32. package/dist/completion-call.js +94 -67
  33. package/dist/completion-model.js +334 -244
  34. package/dist/completion.js +840 -649
  35. package/dist/conflict-model.js +35 -29
  36. package/dist/context-menu-rows.js +42 -17
  37. package/dist/context-menu.js +64 -46
  38. package/dist/definition-link.js +88 -85
  39. package/dist/diagnostics-model.js +74 -55
  40. package/dist/diagnostics.js +121 -100
  41. package/dist/diff-expansion.js +38 -35
  42. package/dist/diff-overlays.js +144 -22
  43. package/dist/diff-syntax.js +65 -42
  44. package/dist/diff-wordmarks.js +26 -23
  45. package/dist/doc-comment-model.js +265 -216
  46. package/dist/editor-language.js +177 -152
  47. package/dist/error-message.js +2 -2
  48. package/dist/find-query.js +49 -36
  49. package/dist/folding.js +81 -62
  50. package/dist/format-on-type.js +86 -67
  51. package/dist/highlight-layers.js +19 -20
  52. package/dist/highlights.js +105 -83
  53. package/dist/history.js +44 -38
  54. package/dist/holder.js +18 -18
  55. package/dist/host-types.js +1 -1
  56. package/dist/hover-content.js +167 -129
  57. package/dist/hover.js +285 -245
  58. package/dist/index.js +10 -10
  59. package/dist/inlay-hints.js +369 -324
  60. package/dist/key-priority.js +34 -31
  61. package/dist/language-ids.js +45 -42
  62. package/dist/line-edits.js +74 -28
  63. package/dist/line-text.js +18 -3
  64. package/dist/locales/en.json +38 -38
  65. package/dist/locales/nl.json +41 -41
  66. package/dist/models.js +1 -1
  67. package/dist/navigation-history.js +40 -41
  68. package/dist/navigation.js +141 -123
  69. package/dist/panel-size.js +8 -8
  70. package/dist/patch-decorations.js +236 -160
  71. package/dist/patch-layout.js +331 -262
  72. package/dist/paths.js +3 -3
  73. package/dist/peek-model.js +86 -69
  74. package/dist/peek.js +254 -192
  75. package/dist/pick.js +164 -157
  76. package/dist/popup-focus.js +5 -5
  77. package/dist/popup-placement.js +36 -21
  78. package/dist/popups.js +13 -13
  79. package/dist/project-language.js +228 -211
  80. package/dist/project-problems.js +81 -69
  81. package/dist/proposal-model.js +163 -126
  82. package/dist/recent-choices.js +25 -25
  83. package/dist/refresher.js +44 -49
  84. package/dist/rename-model.js +113 -113
  85. package/dist/rename.js +321 -233
  86. package/dist/rendered-docs.d.ts +4 -2
  87. package/dist/rendered-docs.js +384 -318
  88. package/dist/rendering-context.js +5 -3
  89. package/dist/rendering.js +22 -4
  90. package/dist/review-group.js +42 -39
  91. package/dist/row-host.d.ts +4 -2
  92. package/dist/row-host.js +90 -78
  93. package/dist/selection-ranges.js +21 -17
  94. package/dist/semantic-delta.js +22 -19
  95. package/dist/semantic-model.js +86 -73
  96. package/dist/semantic-tokens.js +201 -162
  97. package/dist/shortcut-keys.js +16 -10
  98. package/dist/signature-model.js +34 -28
  99. package/dist/signature.js +177 -129
  100. package/dist/snippet-field-transforms.js +118 -106
  101. package/dist/snippet-indent.js +48 -43
  102. package/dist/snippet-range-order.js +11 -11
  103. package/dist/snippet-session.js +703 -667
  104. package/dist/snippet-transform-client.js +59 -59
  105. package/dist/snippet-transform-format.js +285 -263
  106. package/dist/snippet-transform-protocol.js +1 -1
  107. package/dist/snippet-transform-queue.js +163 -153
  108. package/dist/snippet-transform-worker.js +42 -35
  109. package/dist/snippet-variable-names.js +1 -36
  110. package/dist/snippet-variables.js +53 -63
  111. package/dist/snippet.js +477 -405
  112. package/dist/split-alignment.js +47 -35
  113. package/dist/split-scroll.js +42 -40
  114. package/dist/symbol-links.js +33 -25
  115. package/dist/symbol-picker-model.js +126 -116
  116. package/dist/symbol-picker.js +98 -59
  117. package/dist/symbols.js +117 -88
  118. package/dist/testing.js +248 -165
  119. package/dist/timers.js +35 -30
  120. package/dist/use-panel-body.js +49 -8
  121. package/dist/use-problem-counts.js +29 -15
  122. package/dist/view-state.js +54 -33
  123. package/dist/word-diff.js +18 -18
  124. package/dist/workspace-edit.js +300 -249
  125. package/package.json +6 -6
  126. package/src/CallHierarchyPanel.tsx +2 -2
  127. package/src/DiffView.tsx +3 -3
  128. package/src/FindReplace.tsx +2 -2
  129. package/src/LanguagePopups.tsx +2 -0
  130. package/src/PeekPanel.tsx +3 -3
  131. package/src/RenderedDocs.tsx +9 -10
  132. package/src/SymbolPicker.tsx +2 -2
  133. package/src/diff-overlays.tsx +6 -4
  134. package/src/locales/en.json +38 -38
  135. package/src/locales/nl.json +41 -41
  136. package/src/rendered-docs.ts +14 -3
  137. package/src/row-host.ts +14 -3
@@ -1,48 +1,64 @@
1
1
  import { diffLines } from '@adecore/merge';
2
2
  import { replacedWords } from './word-diff.js';
3
3
  export function lineSpanOf(range) {
4
- const endsOnBreak = range.end.character === 0 && range.end.line > range.start.line;
5
- return { startLine: range.start.line + 1, endLine: endsOnBreak ? range.end.line : range.end.line + 1 };
4
+ const endsOnBreak = range.end.character === 0 && range.end.line > range.start.line;
5
+ return {
6
+ startLine: range.start.line + 1,
7
+ endLine: endsOnBreak ? range.end.line : range.end.line + 1
8
+ };
6
9
  }
7
10
  export function isEmptyRange(range) {
8
- return range.start.line === range.end.line && range.start.character === range.end.character;
11
+ return range.start.line === range.end.line && range.start.character === range.end.character;
9
12
  }
10
13
  /* The selection, or the whole line under the caret while nothing is selected. */
11
14
  export function inlineRangeOf(selection, lineLength) {
12
- if (!isEmptyRange(selection)) {
13
- return selection;
15
+ if (!isEmptyRange(selection)) {
16
+ return selection;
17
+ }
18
+ const {
19
+ line
20
+ } = selection.start;
21
+ return {
22
+ start: {
23
+ line,
24
+ character: 0
25
+ },
26
+ end: {
27
+ line,
28
+ character: lineLength(line)
14
29
  }
15
- const { line } = selection.start;
16
- return { start: { line, character: 0 }, end: { line, character: lineLength(line) } };
30
+ };
17
31
  }
18
32
  export function problemsOnLines(diagnostics, span, describe) {
19
- return diagnostics
20
- .filter((diagnostic) => diagnostic.range.start.line + 1 <= span.endLine && diagnostic.range.end.line + 1 >= span.startLine)
21
- .map((diagnostic) => ({ line: Math.max(diagnostic.range.start.line + 1, span.startLine), ...describe(diagnostic) }))
22
- .sort((left, right) => left.line - right.line);
33
+ return diagnostics.filter(diagnostic => diagnostic.range.start.line + 1 <= span.endLine && diagnostic.range.end.line + 1 >= span.startLine).map(diagnostic => ({
34
+ line: Math.max(diagnostic.range.start.line + 1, span.startLine),
35
+ ...describe(diagnostic)
36
+ })).sort((left, right) => left.line - right.line);
23
37
  }
24
38
  const OPENING = /^( {0,3})(`{3,}|~{3,})(.*)$/;
25
39
  function openingOf(line) {
26
- const match = OPENING.exec(line);
27
- if (match === null) {
28
- return null;
29
- }
30
- const [, indent = '', marks = '', info = ''] = match;
31
- // The info string of a backtick fence holds no backtick, which is what keeps a line of inline code from opening one.
32
- if (marks.startsWith('`') && info.includes('`')) {
33
- return null;
34
- }
35
- return { char: marks[0], length: marks.length, indent: indent.length, info: info.trim() };
40
+ const match = OPENING.exec(line);
41
+ if (match === null) {
42
+ return null;
43
+ }
44
+ const [, indent = '', marks = '', info = ''] = match;
45
+ // The info string of a backtick fence holds no backtick, which is what keeps a line of inline code from opening one.
46
+ if (marks.startsWith('`') && info.includes('`')) {
47
+ return null;
48
+ }
49
+ return {
50
+ char: marks[0],
51
+ length: marks.length,
52
+ indent: indent.length,
53
+ info: info.trim()
54
+ };
36
55
  }
37
56
  function closes(line, start) {
38
- const match = /^ {0,3}(`+|~+)\s*$/.exec(line);
39
- return match !== null && match[1][0] === start.char && match[1].length >= start.length;
57
+ const match = /^ {0,3}(`+|~+)\s*$/.exec(line);
58
+ return match !== null && match[1][0] === start.char && match[1].length >= start.length;
40
59
  }
41
60
  function isReplacement(info) {
42
- return info
43
- .toLowerCase()
44
- .split(/[\s,:=]+/)
45
- .includes('replacement');
61
+ return info.toLowerCase().split(/[\s,:=]+/).includes('replacement');
46
62
  }
47
63
  /*
48
64
  * Reads the answer the way a markdown reader does: a fence closes at a line of at least as many marks,
@@ -50,53 +66,60 @@ function isReplacement(info) {
50
66
  * applying half of it would be worse than showing the answer as text, so it counts as no block.
51
67
  */
52
68
  export function parseAnswer(text) {
53
- const lines = text.replace(/\r\n/g, '\n').split('\n');
54
- let open = null;
55
- let found = null;
56
- for (const [index, line] of lines.entries()) {
57
- if (open === null) {
58
- const start = openingOf(line);
59
- if (start !== null) {
60
- open = { start, from: index, body: [] };
61
- }
62
- continue;
63
- }
64
- if (closes(line, open.start)) {
65
- if (isReplacement(open.start.info)) {
66
- found = { from: open.from, to: index, body: open.body };
67
- }
68
- open = null;
69
- continue;
70
- }
71
- open.body.push(line.replace(new RegExp(`^ {0,${open.start.indent}}`), ''));
69
+ const lines = text.replace(/\r\n/g, '\n').split('\n');
70
+ let open = null;
71
+ let found = null;
72
+ for (const [index, line] of lines.entries()) {
73
+ if (open === null) {
74
+ const start = openingOf(line);
75
+ if (start !== null) {
76
+ open = {
77
+ start,
78
+ from: index,
79
+ body: []
80
+ };
81
+ }
82
+ continue;
72
83
  }
73
- if (found === null) {
74
- return { replacement: null, rest: text.trim() };
84
+ if (closes(line, open.start)) {
85
+ if (isReplacement(open.start.info)) {
86
+ found = {
87
+ from: open.from,
88
+ to: index,
89
+ body: open.body
90
+ };
91
+ }
92
+ open = null;
93
+ continue;
75
94
  }
95
+ open.body.push(line.replace(new RegExp(`^ {0,${open.start.indent}}`), ''));
96
+ }
97
+ if (found === null) {
76
98
  return {
77
- replacement: found.body.join('\n'),
78
- rest: [...lines.slice(0, found.from), ...lines.slice(found.to + 1)]
79
- .join('\n')
80
- .replace(/\n{3,}/g, '\n\n')
81
- .trim()
99
+ replacement: null,
100
+ rest: text.trim()
82
101
  };
102
+ }
103
+ return {
104
+ replacement: found.body.join('\n'),
105
+ rest: [...lines.slice(0, found.from), ...lines.slice(found.to + 1)].join('\n').replace(/\n{3,}/g, '\n\n').trim()
106
+ };
83
107
  }
84
108
  /* The proposal in the shape of the text it replaces: its line breaks and whether it ends on one. */
85
109
  export function fitReplacement(selected, replacement) {
86
- const breaks = selected.includes('\r\n') ? '\r\n' : '\n';
87
- let fitted = replacement.replace(/\r\n/g, '\n');
88
- const endsOnBreak = selected.endsWith('\n');
89
- if (fitted !== '' && endsOnBreak && !fitted.endsWith('\n')) {
90
- fitted += '\n';
91
- }
92
- else if (!endsOnBreak && fitted.endsWith('\n')) {
93
- fitted = fitted.slice(0, -1);
94
- }
95
- return breaks === '\n' ? fitted : fitted.replace(/\n/g, breaks);
110
+ const breaks = selected.includes('\r\n') ? '\r\n' : '\n';
111
+ let fitted = replacement.replace(/\r\n/g, '\n');
112
+ const endsOnBreak = selected.endsWith('\n');
113
+ if (fitted !== '' && endsOnBreak && !fitted.endsWith('\n')) {
114
+ fitted += '\n';
115
+ } else if (!endsOnBreak && fitted.endsWith('\n')) {
116
+ fitted = fitted.slice(0, -1);
117
+ }
118
+ return breaks === '\n' ? fitted : fitted.replace(/\n/g, breaks);
96
119
  }
97
120
  function linesOf(text) {
98
- const lines = text.replace(/\r\n/g, '\n').split('\n');
99
- return lines.length > 1 && lines.at(-1) === '' ? lines.slice(0, -1) : lines;
121
+ const lines = text.replace(/\r\n/g, '\n').split('\n');
122
+ return lines.length > 1 && lines.at(-1) === '' ? lines.slice(0, -1) : lines;
100
123
  }
101
124
  /*
102
125
  * The proposal against the selection, line by line. Lines the proposal changes show as added, since
@@ -104,86 +127,100 @@ function linesOf(text) {
104
127
  * only removed ones, because nothing in the proposal would show them gone.
105
128
  */
106
129
  export function diffSegments(selected, proposal, startLine) {
107
- const base = linesOf(selected);
108
- const other = linesOf(proposal);
109
- const segments = [];
110
- let cursor = 0;
111
- const same = (until) => {
112
- if (until > cursor) {
113
- segments.push({ kind: 'same', text: other.slice(cursor, until).join('\n'), firstLine: startLine + cursor });
114
- }
115
- };
116
- for (const change of diffLines(base, other)) {
117
- same(change.otherStart);
118
- if (change.otherEnd > change.otherStart) {
119
- segments.push({
120
- kind: 'added',
121
- text: other.slice(change.otherStart, change.otherEnd).join('\n'),
122
- firstLine: startLine + change.otherStart,
123
- ...(change.baseEnd > change.baseStart ? { replaces: base.slice(change.baseStart, change.baseEnd).join('\n') } : {})
124
- });
125
- }
126
- else {
127
- segments.push({ kind: 'removed', text: base.slice(change.baseStart, change.baseEnd).join('\n') });
128
- }
129
- cursor = change.otherEnd;
130
+ const base = linesOf(selected);
131
+ const other = linesOf(proposal);
132
+ const segments = [];
133
+ let cursor = 0;
134
+ const same = until => {
135
+ if (until > cursor) {
136
+ segments.push({
137
+ kind: 'same',
138
+ text: other.slice(cursor, until).join('\n'),
139
+ firstLine: startLine + cursor
140
+ });
141
+ }
142
+ };
143
+ for (const change of diffLines(base, other)) {
144
+ same(change.otherStart);
145
+ if (change.otherEnd > change.otherStart) {
146
+ segments.push({
147
+ kind: 'added',
148
+ text: other.slice(change.otherStart, change.otherEnd).join('\n'),
149
+ firstLine: startLine + change.otherStart,
150
+ ...(change.baseEnd > change.baseStart ? {
151
+ replaces: base.slice(change.baseStart, change.baseEnd).join('\n')
152
+ } : {})
153
+ });
154
+ } else {
155
+ segments.push({
156
+ kind: 'removed',
157
+ text: base.slice(change.baseStart, change.baseEnd).join('\n')
158
+ });
130
159
  }
131
- same(other.length);
132
- return segments;
160
+ cursor = change.otherEnd;
161
+ }
162
+ same(other.length);
163
+ return segments;
133
164
  }
134
165
  /* Per line of an added stretch, the character ranges of the words that differ from the line it replaces, for the stronger tint; undefined when none do. */
135
166
  export function emphasisOf(segment) {
136
- if (segment.kind !== 'added' || segment.replaces === undefined) {
137
- return undefined;
138
- }
139
- const ranges = replacedWords(linesOf(segment.text), linesOf(segment.replaces));
140
- return ranges.some((line) => line.length > 0) ? ranges : undefined;
167
+ if (segment.kind !== 'added' || segment.replaces === undefined) {
168
+ return undefined;
169
+ }
170
+ const ranges = replacedWords(linesOf(segment.text), linesOf(segment.replaces));
171
+ return ranges.some(line => line.length > 0) ? ranges : undefined;
141
172
  }
142
173
  /* The offset of a position in a text whose lines end in `\n` or `\r\n`; null when the text is not that long. */
143
174
  export function offsetOf(text, position) {
144
- let offset = 0;
145
- for (let line = 0; line < position.line; line++) {
146
- const end = text.indexOf('\n', offset);
147
- if (end === -1) {
148
- return null;
149
- }
150
- offset = end + 1;
175
+ let offset = 0;
176
+ for (let line = 0; line < position.line; line++) {
177
+ const end = text.indexOf('\n', offset);
178
+ if (end === -1) {
179
+ return null;
151
180
  }
152
- const lineEnd = text.indexOf('\n', offset);
153
- const length = (lineEnd === -1 ? text.length : lineEnd) - offset;
154
- return position.character > length ? null : offset + position.character;
181
+ offset = end + 1;
182
+ }
183
+ const lineEnd = text.indexOf('\n', offset);
184
+ const length = (lineEnd === -1 ? text.length : lineEnd) - offset;
185
+ return position.character > length ? null : offset + position.character;
155
186
  }
156
187
  /* The text in a range of `text`, or null when the range is not in it. */
157
188
  export function textInRange(text, range) {
158
- const from = offsetOf(text, range.start);
159
- const to = offsetOf(text, range.end);
160
- return from === null || to === null || to < from ? null : text.slice(from, to);
189
+ const from = offsetOf(text, range.start);
190
+ const to = offsetOf(text, range.end);
191
+ return from === null || to === null || to < from ? null : text.slice(from, to);
161
192
  }
162
193
  /* `text` with the range replaced; null when the range is not in it. */
163
194
  export function replaceRange(text, range, replacement) {
164
- const from = offsetOf(text, range.start);
165
- const to = offsetOf(text, range.end);
166
- return from === null || to === null || to < from ? null : `${text.slice(0, from)}${replacement}${text.slice(to)}`;
195
+ const from = offsetOf(text, range.start);
196
+ const to = offsetOf(text, range.end);
197
+ return from === null || to === null || to < from ? null : `${text.slice(0, from)}${replacement}${text.slice(to)}`;
167
198
  }
168
199
  /*
169
200
  * Where `selected` stands in `text` now: its own range while it still holds, and otherwise the one
170
201
  * place it occurs when lines moved. Null when it is gone or ambiguous, which is a selection that changed.
171
202
  */
172
203
  export function locateSelection(text, range, selected) {
173
- if (textInRange(text, range) === selected) {
174
- return range;
175
- }
176
- if (selected === '') {
177
- return null;
178
- }
179
- const first = text.indexOf(selected);
180
- if (first === -1 || text.indexOf(selected, first + 1) !== -1) {
181
- return null;
182
- }
183
- return { start: positionAt(text, first), end: positionAt(text, first + selected.length) };
204
+ if (textInRange(text, range) === selected) {
205
+ return range;
206
+ }
207
+ if (selected === '') {
208
+ return null;
209
+ }
210
+ const first = text.indexOf(selected);
211
+ if (first === -1 || text.indexOf(selected, first + 1) !== -1) {
212
+ return null;
213
+ }
214
+ return {
215
+ start: positionAt(text, first),
216
+ end: positionAt(text, first + selected.length)
217
+ };
184
218
  }
185
219
  function positionAt(text, offset) {
186
- const before = text.slice(0, offset);
187
- const line = before.split('\n').length - 1;
188
- return { line, character: offset - (before.lastIndexOf('\n') + 1) };
189
- }
220
+ const before = text.slice(0, offset);
221
+ const line = before.split('\n').length - 1;
222
+ return {
223
+ line,
224
+ character: offset - (before.lastIndexOf('\n') + 1)
225
+ };
226
+ }
@@ -5,35 +5,35 @@ const LIMIT = 200;
5
5
  * memory only, one per language, and forgets the oldest choice past a few hundred.
6
6
  */
7
7
  export class RecentChoices {
8
- order = new Map();
9
- tick = 0;
10
- /* An item is told by its label, its kind and where it comes from, so two `Property` of two namespaces are two choices. */
11
- static keyOf(item) {
12
- return `${item.label}\0${item.kind ?? ''}\0${qualifierOf(item)}`;
13
- }
14
- record(item) {
15
- const key = RecentChoices.keyOf(item);
16
- this.order.delete(key);
17
- this.order.set(key, ++this.tick);
18
- if (this.order.size > LIMIT) {
19
- this.order.delete(this.order.keys().next().value);
20
- }
21
- }
22
- /* Higher for a later choice, 0 for an item never chosen. */
23
- recency(item) {
24
- return this.order.get(RecentChoices.keyOf(item)) ?? 0;
8
+ order = new Map();
9
+ tick = 0;
10
+ /* An item is told by its label, its kind and where it comes from, so two `Property` of two namespaces are two choices. */
11
+ static keyOf(item) {
12
+ return `${item.label}\0${item.kind ?? ''}\0${qualifierOf(item)}`;
13
+ }
14
+ record(item) {
15
+ const key = RecentChoices.keyOf(item);
16
+ this.order.delete(key);
17
+ this.order.set(key, ++this.tick);
18
+ if (this.order.size > LIMIT) {
19
+ this.order.delete(this.order.keys().next().value);
25
20
  }
21
+ }
22
+ /* Higher for a later choice, 0 for an item never chosen. */
23
+ recency(item) {
24
+ return this.order.get(RecentChoices.keyOf(item)) ?? 0;
25
+ }
26
26
  }
27
27
  const stores = new Map();
28
28
  export function recentChoicesOf(languageId) {
29
- let store = stores.get(languageId);
30
- if (store === undefined) {
31
- store = new RecentChoices();
32
- stores.set(languageId, store);
33
- }
34
- return store;
29
+ let store = stores.get(languageId);
30
+ if (store === undefined) {
31
+ store = new RecentChoices();
32
+ stores.set(languageId, store);
33
+ }
34
+ return store;
35
35
  }
36
36
  /* For a test that must not hear the choices an earlier one made. */
37
37
  export function forgetRecentChoices() {
38
- stores.clear();
39
- }
38
+ stores.clear();
39
+ }
package/dist/refresher.js CHANGED
@@ -5,56 +5,51 @@ import { realTimers } from './timers.js';
5
5
  * A newer ask aborts the one before it, and an answer for a text that moved on is dropped.
6
6
  */
7
7
  export class Refresher {
8
- timer;
9
- controller = null;
10
- disposed = false;
11
- timers;
12
- delay;
13
- run;
14
- constructor(run, delay, timers = realTimers) {
15
- this.run = run;
16
- this.delay = delay;
17
- this.timers = timers;
18
- }
19
- /* After a pause: every call starts the wait again. */
20
- later() {
21
- this.timers.clear(this.timer);
22
- this.timer = this.timers.set(() => this.now(), this.delay);
23
- }
24
- now() {
25
- if (this.disposed) {
26
- return;
27
- }
28
- this.timers.clear(this.timer);
29
- this.controller?.abort();
30
- const controller = new AbortController();
31
- this.controller = controller;
32
- this.run(controller.signal).catch((error) => {
33
- // A server that cannot answer yet is asked again when it says it can; a stale text is asked again by its own change.
34
- if (!(error instanceof StaleResultError) && !controller.signal.aborted && !isQuiet(error)) {
35
- console.warn('Language request failed', error);
36
- }
37
- });
38
- }
39
- /* Drops the wait and the ask in flight, and keeps the refresher usable. */
40
- cancel() {
41
- this.timers.clear(this.timer);
42
- this.controller?.abort();
43
- }
44
- dispose() {
45
- this.disposed = true;
46
- this.timers.clear(this.timer);
47
- this.controller?.abort();
8
+ timer;
9
+ controller = null;
10
+ disposed = false;
11
+ timers;
12
+ delay;
13
+ run;
14
+ constructor(run, delay, timers = realTimers) {
15
+ this.run = run;
16
+ this.delay = delay;
17
+ this.timers = timers;
18
+ }
19
+ /* After a pause: every call starts the wait again. */
20
+ later() {
21
+ this.timers.clear(this.timer);
22
+ this.timer = this.timers.set(() => this.now(), this.delay);
23
+ }
24
+ now() {
25
+ if (this.disposed) {
26
+ return;
48
27
  }
28
+ this.timers.clear(this.timer);
29
+ this.controller?.abort();
30
+ const controller = new AbortController();
31
+ this.controller = controller;
32
+ this.run(controller.signal).catch(error => {
33
+ // A server that cannot answer yet is asked again when it says it can; a stale text is asked again by its own change.
34
+ if (!(error instanceof StaleResultError) && !controller.signal.aborted && !isQuiet(error)) {
35
+ console.warn('Language request failed', error);
36
+ }
37
+ });
38
+ }
39
+ /* Drops the wait and the ask in flight, and keeps the refresher usable. */
40
+ cancel() {
41
+ this.timers.clear(this.timer);
42
+ this.controller?.abort();
43
+ }
44
+ dispose() {
45
+ this.disposed = true;
46
+ this.timers.clear(this.timer);
47
+ this.controller?.abort();
48
+ }
49
49
  }
50
- const QUIET_CODES = new Set([
51
- ErrorCodes.ServerNotInitialized,
52
- ErrorCodes.MethodNotFound,
53
- ErrorCodes.RequestCancelled,
54
- ErrorCodes.ContentModified
55
- ]);
50
+ const QUIET_CODES = new Set([ErrorCodes.ServerNotInitialized, ErrorCodes.MethodNotFound, ErrorCodes.RequestCancelled, ErrorCodes.ContentModified]);
56
51
  /* A server that is not up, does not offer the feature or was asked to stop is not worth a line in the console. */
57
52
  function isQuiet(error) {
58
- const code = error?.code;
59
- return code !== undefined && QUIET_CODES.has(code);
60
- }
53
+ const code = error?.code;
54
+ return code !== undefined && QUIET_CODES.has(code);
55
+ }