@adecore/editor-react 0.31.12 → 0.32.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.
- package/dist/AnchoredPopup.js +73 -19
- package/dist/AttributionCard.js +162 -4
- package/dist/BaselineStatus.js +62 -8
- package/dist/CallHierarchyPanel.js +977 -60
- package/dist/ChangeReview.js +76 -25
- package/dist/CodeAuthorsCard.js +314 -14
- package/dist/CompletionPopup.js +490 -83
- package/dist/DiffView.js +548 -181
- package/dist/EditorContextMenu.js +352 -34
- package/dist/EditorView.js +276 -99
- package/dist/FindReplace.js +525 -67
- package/dist/HoverCard.js +378 -38
- package/dist/HoverSections.js +367 -56
- package/dist/LanguagePopups.js +95 -34
- package/dist/Markdown.js +41 -6
- package/dist/PanelResizeHandle.js +199 -66
- package/dist/PathText.js +49 -7
- package/dist/PeekPanel.js +675 -72
- package/dist/PickPopup.js +304 -34
- package/dist/RenameCard.js +679 -85
- package/dist/RenderedDocs.js +329 -58
- package/dist/SignatureCard.js +91 -7
- package/dist/SplitDiffView.js +344 -254
- package/dist/SymbolPicker.js +440 -85
- package/dist/call-hierarchy-model.js +102 -68
- package/dist/call-hierarchy.js +458 -359
- package/dist/code-actions-model.js +88 -76
- package/dist/code-actions.js +372 -283
- package/dist/code-authors.js +64 -55
- package/dist/code-vision-model.js +134 -127
- package/dist/code-vision.js +224 -206
- package/dist/completion-call.js +94 -67
- package/dist/completion-model.js +334 -244
- package/dist/completion.js +840 -649
- package/dist/conflict-model.js +35 -29
- package/dist/context-menu-rows.js +42 -17
- package/dist/context-menu.js +64 -46
- package/dist/definition-link.js +88 -85
- package/dist/diagnostics-model.js +74 -55
- package/dist/diagnostics.js +121 -100
- package/dist/diff-expansion.js +38 -35
- package/dist/diff-overlays.js +144 -22
- package/dist/diff-syntax.js +65 -42
- package/dist/diff-wordmarks.js +26 -23
- package/dist/doc-comment-model.js +265 -216
- package/dist/editor-language.js +177 -152
- package/dist/error-message.js +2 -2
- package/dist/find-query.js +49 -36
- package/dist/folding.js +81 -62
- package/dist/format-on-type.js +86 -67
- package/dist/highlight-layers.js +19 -20
- package/dist/highlights.js +105 -83
- package/dist/history.js +44 -38
- package/dist/holder.js +18 -18
- package/dist/host-types.js +1 -1
- package/dist/hover-content.js +167 -129
- package/dist/hover.js +285 -245
- package/dist/index.js +10 -10
- package/dist/inlay-hints.js +369 -324
- package/dist/key-priority.js +34 -31
- package/dist/language-ids.js +45 -42
- package/dist/line-edits.js +74 -28
- package/dist/line-text.js +18 -3
- package/dist/locales/en.json +38 -38
- package/dist/locales/nl.json +41 -41
- package/dist/models.js +1 -1
- package/dist/navigation-history.js +40 -41
- package/dist/navigation.js +141 -123
- package/dist/panel-size.js +8 -8
- package/dist/patch-decorations.js +236 -160
- package/dist/patch-layout.js +331 -262
- package/dist/paths.js +3 -3
- package/dist/peek-model.js +86 -69
- package/dist/peek.js +254 -192
- package/dist/pick.js +164 -157
- package/dist/popup-focus.js +5 -5
- package/dist/popup-placement.js +36 -21
- package/dist/popups.js +13 -13
- package/dist/project-language.js +228 -211
- package/dist/project-problems.js +81 -69
- package/dist/proposal-model.js +163 -126
- package/dist/recent-choices.js +25 -25
- package/dist/refresher.js +44 -49
- package/dist/rename-model.js +113 -113
- package/dist/rename.js +321 -233
- package/dist/rendered-docs.d.ts +4 -2
- package/dist/rendered-docs.js +384 -318
- package/dist/rendering-context.js +5 -3
- package/dist/rendering.js +22 -4
- package/dist/review-group.js +42 -39
- package/dist/row-host.d.ts +4 -2
- package/dist/row-host.js +90 -78
- package/dist/selection-ranges.js +21 -17
- package/dist/semantic-delta.js +22 -19
- package/dist/semantic-model.js +86 -73
- package/dist/semantic-tokens.js +201 -162
- package/dist/shortcut-keys.js +16 -10
- package/dist/signature-model.js +34 -28
- package/dist/signature.js +177 -129
- package/dist/snippet-field-transforms.js +118 -106
- package/dist/snippet-indent.js +48 -43
- package/dist/snippet-range-order.js +11 -11
- package/dist/snippet-session.js +703 -667
- package/dist/snippet-transform-client.js +59 -59
- package/dist/snippet-transform-format.js +285 -263
- package/dist/snippet-transform-protocol.js +1 -1
- package/dist/snippet-transform-queue.js +163 -153
- package/dist/snippet-transform-worker.js +42 -35
- package/dist/snippet-variable-names.js +1 -36
- package/dist/snippet-variables.js +53 -63
- package/dist/snippet.js +477 -405
- package/dist/split-alignment.js +47 -35
- package/dist/split-scroll.js +42 -40
- package/dist/symbol-links.js +33 -25
- package/dist/symbol-picker-model.js +126 -116
- package/dist/symbol-picker.js +98 -59
- package/dist/symbols.js +117 -88
- package/dist/testing.js +248 -165
- package/dist/timers.js +35 -30
- package/dist/use-panel-body.js +49 -8
- package/dist/use-problem-counts.js +29 -15
- package/dist/view-state.js +54 -33
- package/dist/word-diff.js +18 -18
- package/dist/workspace-edit.js +300 -249
- package/package.json +6 -6
- package/src/CallHierarchyPanel.tsx +2 -2
- package/src/DiffView.tsx +3 -3
- package/src/FindReplace.tsx +2 -2
- package/src/LanguagePopups.tsx +2 -0
- package/src/PeekPanel.tsx +3 -3
- package/src/RenderedDocs.tsx +9 -10
- package/src/SymbolPicker.tsx +2 -2
- package/src/diff-overlays.tsx +6 -4
- package/src/locales/en.json +38 -38
- package/src/locales/nl.json +41 -41
- package/src/rendered-docs.ts +14 -3
- package/src/row-host.ts +14 -3
package/dist/conflict-model.js
CHANGED
|
@@ -4,33 +4,39 @@ import { splitBlocks, splitLines } from '@adecore/merge';
|
|
|
4
4
|
* are ours to take without asking; only a stretch both sides changed needs a person.
|
|
5
5
|
*/
|
|
6
6
|
export function planConflict(base, ours, theirs) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
7
|
+
const blocks = splitBlocks(splitLines(base), splitLines(ours), splitLines(theirs));
|
|
8
|
+
const merges = [];
|
|
9
|
+
const conflicts = [];
|
|
10
|
+
let oursAt = 0;
|
|
11
|
+
let theirsAt = 0;
|
|
12
|
+
let mergedAt = 0;
|
|
13
|
+
for (const block of blocks) {
|
|
14
|
+
if (block.kind === 'theirs') {
|
|
15
|
+
merges.push({
|
|
16
|
+
from: oursAt,
|
|
17
|
+
to: oursAt + block.ours.length,
|
|
18
|
+
lines: block.theirs
|
|
19
|
+
});
|
|
20
|
+
mergedAt += block.theirs.length;
|
|
21
|
+
} else {
|
|
22
|
+
if (block.kind === 'conflict') {
|
|
23
|
+
conflicts.push({
|
|
24
|
+
base: block.base,
|
|
25
|
+
ours: block.ours,
|
|
26
|
+
theirs: block.theirs,
|
|
27
|
+
from: mergedAt,
|
|
28
|
+
to: mergedAt + block.ours.length,
|
|
29
|
+
theirsStart: theirsAt + 1,
|
|
30
|
+
theirsEnd: theirsAt + block.theirs.length
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
mergedAt += block.ours.length;
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
oursAt += block.ours.length;
|
|
36
|
+
theirsAt += block.theirs.length;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
merges,
|
|
40
|
+
conflicts
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -1,20 +1,45 @@
|
|
|
1
1
|
/* The rows of the Go to submenu. Declaration has no key of its own in the table. */
|
|
2
|
-
const GO_TO = [
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
const GO_TO = [{
|
|
3
|
+
id: 'definition',
|
|
4
|
+
method: 'textDocument/definition',
|
|
5
|
+
shortcut: 'goToDefinition'
|
|
6
|
+
}, {
|
|
7
|
+
id: 'declaration',
|
|
8
|
+
method: 'textDocument/declaration',
|
|
9
|
+
shortcut: null
|
|
10
|
+
}, {
|
|
11
|
+
id: 'typeDefinition',
|
|
12
|
+
method: 'textDocument/typeDefinition',
|
|
13
|
+
shortcut: 'goToTypeDefinition'
|
|
14
|
+
}, {
|
|
15
|
+
id: 'implementation',
|
|
16
|
+
method: 'textDocument/implementation',
|
|
17
|
+
shortcut: 'goToImplementation'
|
|
18
|
+
}];
|
|
19
|
+
const REFERENCES = [{
|
|
20
|
+
id: 'peekReferences',
|
|
21
|
+
method: 'textDocument/references',
|
|
22
|
+
shortcut: 'peekReferences'
|
|
23
|
+
}, {
|
|
24
|
+
id: 'callHierarchy',
|
|
25
|
+
method: 'textDocument/prepareCallHierarchy',
|
|
26
|
+
shortcut: 'callHierarchy'
|
|
27
|
+
}];
|
|
28
|
+
const CHANGES = [{
|
|
29
|
+
id: 'renameSymbol',
|
|
30
|
+
method: 'textDocument/rename',
|
|
31
|
+
shortcut: 'renameSymbol'
|
|
32
|
+
}, {
|
|
33
|
+
id: 'codeActions',
|
|
34
|
+
method: 'textDocument/codeAction',
|
|
35
|
+
shortcut: 'codeActions'
|
|
36
|
+
}];
|
|
16
37
|
/* The language rows of the context menu in their groups, each holding only the rows a server answers. */
|
|
17
38
|
export function menuGroupsOf(supports) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
39
|
+
const supported = rows => rows.filter(row => supports(row.method));
|
|
40
|
+
return {
|
|
41
|
+
goTo: supported(GO_TO),
|
|
42
|
+
references: supported(REFERENCES),
|
|
43
|
+
changes: supported(CHANGES)
|
|
44
|
+
};
|
|
45
|
+
}
|
package/dist/context-menu.js
CHANGED
|
@@ -3,52 +3,70 @@
|
|
|
3
3
|
* servers support at the caret. The refactors are asked for while it opens, so it never waits for them.
|
|
4
4
|
*/
|
|
5
5
|
export class ContextMenuFeature {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
language;
|
|
7
|
+
request = 0;
|
|
8
|
+
constructor(language) {
|
|
9
|
+
this.language = language;
|
|
10
|
+
const off = language.editor.onContextMenu(menu => {
|
|
11
|
+
// A right click outside the selection moves the caret first, so the menu is about what was clicked.
|
|
12
|
+
if (!menu.inSelection) {
|
|
13
|
+
language.editor.setCaret(menu.position);
|
|
14
|
+
}
|
|
15
|
+
this.open(menu.x, menu.y);
|
|
16
|
+
});
|
|
17
|
+
language.onDispose(() => {
|
|
18
|
+
off();
|
|
19
|
+
this.close();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
close() {
|
|
23
|
+
this.request++;
|
|
24
|
+
if (this.language.popups.getState().menu !== null) {
|
|
25
|
+
this.language.popups.setState({
|
|
26
|
+
menu: null
|
|
27
|
+
});
|
|
21
28
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
}
|
|
30
|
+
/* The browser's own commands on the editor's input, which keep the clipboard and the undo history one thing. */
|
|
31
|
+
clipboard(action) {
|
|
32
|
+
const {
|
|
33
|
+
editor
|
|
34
|
+
} = this.language;
|
|
35
|
+
editor.focus();
|
|
36
|
+
const done = document.execCommand(action);
|
|
37
|
+
if (!done && action === 'paste') {
|
|
38
|
+
void navigator.clipboard?.readText().then(text => {
|
|
39
|
+
const range = editor.getSelection();
|
|
40
|
+
editor.applyEdits([{
|
|
41
|
+
range,
|
|
42
|
+
text
|
|
43
|
+
}]);
|
|
44
|
+
}).catch(() => undefined);
|
|
27
45
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
popups.setState({ menu: { ...shown, refactors: entries } });
|
|
51
|
-
}
|
|
46
|
+
}
|
|
47
|
+
open(x, y) {
|
|
48
|
+
const request = ++this.request;
|
|
49
|
+
const {
|
|
50
|
+
popups,
|
|
51
|
+
codeActions
|
|
52
|
+
} = this.language;
|
|
53
|
+
popups.setState({
|
|
54
|
+
menu: {
|
|
55
|
+
x,
|
|
56
|
+
y,
|
|
57
|
+
refactors: []
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
void codeActions.list(['refactor']).then(entries => {
|
|
61
|
+
const shown = popups.getState().menu;
|
|
62
|
+
if (request === this.request && shown !== null && entries !== null) {
|
|
63
|
+
popups.setState({
|
|
64
|
+
menu: {
|
|
65
|
+
...shown,
|
|
66
|
+
refactors: entries
|
|
67
|
+
}
|
|
52
68
|
});
|
|
53
|
-
|
|
54
|
-
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
package/dist/definition-link.js
CHANGED
|
@@ -8,93 +8,96 @@ import { wordRangeAt } from './rename-model.js';
|
|
|
8
8
|
* key comes from the window.
|
|
9
9
|
*/
|
|
10
10
|
export class DefinitionLinkFeature {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (event.key === modKey) {
|
|
33
|
-
this.setModHeld(event.type === 'keydown');
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
const lost = () => this.setModHeld(false);
|
|
37
|
-
window.addEventListener('keydown', keys);
|
|
38
|
-
window.addEventListener('keyup', keys);
|
|
39
|
-
window.addEventListener('blur', lost);
|
|
40
|
-
offs.push(() => {
|
|
41
|
-
window.removeEventListener('keydown', keys);
|
|
42
|
-
window.removeEventListener('keyup', keys);
|
|
43
|
-
window.removeEventListener('blur', lost);
|
|
44
|
-
});
|
|
11
|
+
language;
|
|
12
|
+
held = false;
|
|
13
|
+
pointer = null;
|
|
14
|
+
shownKey = '';
|
|
15
|
+
drawn = false;
|
|
16
|
+
request = 0;
|
|
17
|
+
lookup = null;
|
|
18
|
+
constructor(language) {
|
|
19
|
+
this.language = language;
|
|
20
|
+
const {
|
|
21
|
+
editor
|
|
22
|
+
} = language;
|
|
23
|
+
const offs = [editor.onHover(hover => {
|
|
24
|
+
this.pointer = hover?.position ?? null;
|
|
25
|
+
this.update();
|
|
26
|
+
}), editor.onTextChange(() => this.clear()), editor.onViewChange(() => this.clear())];
|
|
27
|
+
if (typeof window !== 'undefined') {
|
|
28
|
+
const modKey = language.apple ? 'Meta' : 'Control';
|
|
29
|
+
const keys = event => {
|
|
30
|
+
if (event.key === modKey) {
|
|
31
|
+
this.setModHeld(event.type === 'keydown');
|
|
45
32
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
33
|
+
};
|
|
34
|
+
const lost = () => this.setModHeld(false);
|
|
35
|
+
window.addEventListener('keydown', keys);
|
|
36
|
+
window.addEventListener('keyup', keys);
|
|
37
|
+
window.addEventListener('blur', lost);
|
|
38
|
+
offs.push(() => {
|
|
39
|
+
window.removeEventListener('keydown', keys);
|
|
40
|
+
window.removeEventListener('keyup', keys);
|
|
41
|
+
window.removeEventListener('blur', lost);
|
|
42
|
+
});
|
|
52
43
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
language.onDispose(() => {
|
|
45
|
+
for (const off of offs) {
|
|
46
|
+
off();
|
|
47
|
+
}
|
|
48
|
+
this.clear();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
setModHeld(held) {
|
|
52
|
+
if (held !== this.held) {
|
|
53
|
+
this.held = held;
|
|
54
|
+
this.update();
|
|
58
55
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
}
|
|
57
|
+
clear() {
|
|
58
|
+
this.request++;
|
|
59
|
+
this.lookup?.abort();
|
|
60
|
+
this.shownKey = '';
|
|
61
|
+
if (this.drawn) {
|
|
62
|
+
this.drawn = false;
|
|
63
|
+
this.language.editor.setLink(null);
|
|
67
64
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
.definition(uri, pointer, { signal: controller.signal })
|
|
92
|
-
.then((result) => {
|
|
93
|
-
if (request === this.request && locationsOf(result).length > 0) {
|
|
94
|
-
this.drawn = true;
|
|
95
|
-
editor.setLink(word);
|
|
96
|
-
}
|
|
97
|
-
})
|
|
98
|
-
.catch(() => undefined);
|
|
65
|
+
}
|
|
66
|
+
update() {
|
|
67
|
+
const {
|
|
68
|
+
pointer
|
|
69
|
+
} = this;
|
|
70
|
+
if (!this.held || pointer === null || !this.language.project.service.supports('textDocument/definition', this.language.uri)) {
|
|
71
|
+
this.clear();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const {
|
|
75
|
+
editor,
|
|
76
|
+
project,
|
|
77
|
+
uri
|
|
78
|
+
} = this.language;
|
|
79
|
+
const line = lineTextOf(editor, pointer.line);
|
|
80
|
+
const word = isIdentifierCharacter(line[pointer.character] ?? '') ? wordRangeAt(line, pointer) : null;
|
|
81
|
+
if (word === null) {
|
|
82
|
+
this.clear();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const key = `${word.start.line}:${word.start.character}`;
|
|
86
|
+
if (key === this.shownKey) {
|
|
87
|
+
return;
|
|
99
88
|
}
|
|
100
|
-
|
|
89
|
+
this.clear();
|
|
90
|
+
this.shownKey = key;
|
|
91
|
+
const request = ++this.request;
|
|
92
|
+
const controller = new AbortController();
|
|
93
|
+
this.lookup = controller;
|
|
94
|
+
project.service.definition(uri, pointer, {
|
|
95
|
+
signal: controller.signal
|
|
96
|
+
}).then(result => {
|
|
97
|
+
if (request === this.request && locationsOf(result).length > 0) {
|
|
98
|
+
this.drawn = true;
|
|
99
|
+
editor.setLink(word);
|
|
100
|
+
}
|
|
101
|
+
}).catch(() => undefined);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
const SEVERITIES = {
|
|
1
|
+
const SEVERITIES = {
|
|
2
|
+
1: 'error',
|
|
3
|
+
2: 'warning',
|
|
4
|
+
3: 'info',
|
|
5
|
+
4: 'hint'
|
|
6
|
+
};
|
|
2
7
|
const HINT = 4;
|
|
3
8
|
const UNNECESSARY = 1;
|
|
4
9
|
const DEPRECATED = 2;
|
|
@@ -6,84 +11,98 @@ const DEPRECATED = 2;
|
|
|
6
11
|
const TICK_MESSAGE_LENGTH = 300;
|
|
7
12
|
/* A report that names no severity is an error, which is the safer side to be wrong on. */
|
|
8
13
|
export function severityOf(diagnostic) {
|
|
9
|
-
|
|
14
|
+
return SEVERITIES[diagnostic.severity ?? 1] ?? 'error';
|
|
10
15
|
}
|
|
11
16
|
export function markerOf(diagnostic) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
return {
|
|
18
|
+
range: diagnostic.range,
|
|
19
|
+
severity: severityOf(diagnostic),
|
|
20
|
+
unnecessary: diagnostic.tags?.includes(UNNECESSARY) === true,
|
|
21
|
+
deprecated: diagnostic.tags?.includes(DEPRECATED) === true,
|
|
22
|
+
message: diagnostic.message.length > TICK_MESSAGE_LENGTH ? `${diagnostic.message.slice(0, TICK_MESSAGE_LENGTH)}…` : diagnostic.message
|
|
23
|
+
};
|
|
19
24
|
}
|
|
20
25
|
/* A diagnostic that names no severity counts as an error. */
|
|
21
26
|
export function problemCountsOf(diagnostics) {
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
const count = severity => diagnostics.filter(diagnostic => (diagnostic.severity ?? 1) === severity).length;
|
|
28
|
+
return {
|
|
29
|
+
error: count(1),
|
|
30
|
+
warning: count(2),
|
|
31
|
+
info: count(3)
|
|
32
|
+
};
|
|
24
33
|
}
|
|
25
34
|
export function comparePositions(left, right) {
|
|
26
|
-
|
|
35
|
+
return left.line === right.line ? left.character - right.character : left.line - right.line;
|
|
27
36
|
}
|
|
28
37
|
/* Where an insertion of `text` at `start` ends, counting a line break of any kind once. */
|
|
29
38
|
export function endOfInsertion(start, text) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
const lines = text.split(/\r\n|\r|\n/);
|
|
40
|
+
return lines.length === 1 ? {
|
|
41
|
+
line: start.line,
|
|
42
|
+
character: start.character + text.length
|
|
43
|
+
} : {
|
|
44
|
+
line: start.line + lines.length - 1,
|
|
45
|
+
character: lines[lines.length - 1].length
|
|
46
|
+
};
|
|
34
47
|
}
|
|
35
48
|
/* Where a position is once one change is applied to the text it was in. One inside the replaced range lands after the new text. */
|
|
36
49
|
export function shiftPosition(position, change) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
const {
|
|
51
|
+
start,
|
|
52
|
+
end
|
|
53
|
+
} = change.range;
|
|
54
|
+
if (comparePositions(position, start) < 0) {
|
|
55
|
+
return position;
|
|
56
|
+
}
|
|
57
|
+
const inserted = endOfInsertion(start, change.text);
|
|
58
|
+
if (comparePositions(position, end) < 0) {
|
|
59
|
+
return inserted;
|
|
60
|
+
}
|
|
61
|
+
return position.line === end.line ? {
|
|
62
|
+
line: inserted.line,
|
|
63
|
+
character: inserted.character + (position.character - end.character)
|
|
64
|
+
} : {
|
|
65
|
+
line: position.line + (inserted.line - end.line),
|
|
66
|
+
character: position.character
|
|
67
|
+
};
|
|
48
68
|
}
|
|
49
69
|
export function shiftRange(range, changes) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
70
|
+
let start = range.start;
|
|
71
|
+
let end = range.end;
|
|
72
|
+
for (const change of changes) {
|
|
73
|
+
start = shiftPosition(start, change);
|
|
74
|
+
end = shiftPosition(end, change);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
start,
|
|
78
|
+
end
|
|
79
|
+
};
|
|
57
80
|
}
|
|
58
81
|
/* A range holds a position from its start up to and including its end, so a caret at either edge of a word is on it. An empty range holds only its own place. */
|
|
59
82
|
export function rangeHolds(range, position) {
|
|
60
|
-
|
|
83
|
+
return comparePositions(range.start, position) <= 0 && comparePositions(position, range.end) <= 0;
|
|
61
84
|
}
|
|
62
85
|
/* The problems under a position, worst first. A hint is not a problem, so it is left to the colors and the faded text. */
|
|
63
86
|
export function problemsAt(problems, position) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.filter((problem) => (problem.diagnostic.severity ?? 1) < HINT && rangeHolds(problem.diagnostic.range, position))
|
|
67
|
-
.sort((left, right) => rank(left) - rank(right));
|
|
87
|
+
const rank = problem => problem.diagnostic.severity ?? 1;
|
|
88
|
+
return problems.filter(problem => (problem.diagnostic.severity ?? 1) < HINT && rangeHolds(problem.diagnostic.range, position)).sort((left, right) => rank(left) - rank(right));
|
|
68
89
|
}
|
|
69
90
|
/* The start of the first problem after the position, or the last one before it when `direction` is back; it wraps round the document. */
|
|
70
91
|
export function neighborProblem(problems, from, direction) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
return [...candidates].reverse().find((problem) => comparePositions(problem.diagnostic.range.start, from) < 0) ?? candidates[candidates.length - 1];
|
|
92
|
+
const candidates = problems.filter(problem => (problem.diagnostic.severity ?? 1) < HINT).sort((left, right) => comparePositions(left.diagnostic.range.start, right.diagnostic.range.start));
|
|
93
|
+
if (candidates.length === 0) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
if (direction === 1) {
|
|
97
|
+
return candidates.find(problem => comparePositions(problem.diagnostic.range.start, from) > 0) ?? candidates[0];
|
|
98
|
+
}
|
|
99
|
+
return [...candidates].reverse().find(problem => comparePositions(problem.diagnostic.range.start, from) < 0) ?? candidates[candidates.length - 1];
|
|
81
100
|
}
|
|
82
101
|
/* `ts(2551)`, or the code alone, or the source alone, whichever the server gave. */
|
|
83
102
|
export function codeLabelOf(diagnostic) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
103
|
+
const code = diagnostic.code === undefined ? '' : String(diagnostic.code);
|
|
104
|
+
if (diagnostic.source !== undefined && code !== '') {
|
|
105
|
+
return `${diagnostic.source}(${code})`;
|
|
106
|
+
}
|
|
107
|
+
return code !== '' ? code : diagnostic.source ?? '';
|
|
108
|
+
}
|