@adecore/editor-react 0.41.1 → 0.43.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/CallHierarchyPanel.js +177 -181
- package/dist/EditorContextMenu.js +118 -105
- package/dist/EditorView.js +7 -1
- package/dist/LanguagePopups.js +7 -0
- package/dist/PickPopup.js +190 -70
- package/dist/WrapCard.d.ts +8 -0
- package/dist/WrapCard.js +172 -0
- package/dist/call-hierarchy-model.d.ts +4 -2
- package/dist/call-hierarchy-model.js +20 -0
- package/dist/call-hierarchy.d.ts +3 -0
- package/dist/call-hierarchy.js +54 -22
- package/dist/clipboard-history.d.ts +31 -0
- package/dist/clipboard-history.js +70 -0
- package/dist/code-actions.d.ts +3 -1
- package/dist/code-actions.js +50 -10
- package/dist/code-vision.js +2 -3
- package/dist/completion.js +10 -15
- package/dist/context-menu-rows.d.ts +1 -1
- package/dist/context-menu-rows.js +4 -0
- package/dist/definition-link.js +15 -5
- package/dist/document-colors.d.ts +24 -0
- package/dist/document-colors.js +194 -0
- package/dist/document-links.d.ts +22 -0
- package/dist/document-links.js +133 -0
- package/dist/document-query.d.ts +15 -0
- package/dist/document-query.js +54 -0
- package/dist/edit-locations.d.ts +20 -0
- package/dist/edit-locations.js +136 -0
- package/dist/editor-language.d.ts +19 -1
- package/dist/editor-language.js +77 -2
- package/dist/emmet.d.ts +13 -0
- package/dist/emmet.js +62 -0
- package/dist/folding.js +2 -3
- package/dist/format-on-type.js +3 -5
- package/dist/highlights.js +2 -3
- package/dist/history.d.ts +7 -0
- package/dist/history.js +79 -1
- package/dist/host-types.d.ts +6 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +8 -0
- package/dist/inlay-hints.js +2 -2
- package/dist/inline-completion.d.ts +39 -0
- package/dist/inline-completion.js +221 -0
- package/dist/key-priority.d.ts +8 -5
- package/dist/key-priority.js +9 -6
- package/dist/linked-editing.d.ts +26 -0
- package/dist/linked-editing.js +215 -0
- package/dist/locales/en.json +31 -2
- package/dist/locales/nl.json +31 -2
- package/dist/markup-context.d.ts +37 -0
- package/dist/markup-context.js +291 -0
- package/dist/markup.d.ts +36 -0
- package/dist/markup.js +453 -0
- package/dist/navigation.js +4 -6
- package/dist/paste-history.d.ts +7 -0
- package/dist/paste-history.js +104 -0
- package/dist/peek.js +3 -4
- package/dist/pick.d.ts +20 -2
- package/dist/pick.js +141 -18
- package/dist/popups.d.ts +9 -0
- package/dist/popups.js +2 -1
- package/dist/project-language.d.ts +18 -1
- package/dist/project-language.js +129 -18
- package/dist/rename.js +8 -11
- package/dist/rendered-docs.js +1 -2
- package/dist/selection-ranges.js +2 -3
- package/dist/shortcut-keys.d.ts +27 -0
- package/dist/signature.js +3 -6
- package/dist/snippet-session.d.ts +2 -2
- package/dist/snippet-session.js +3 -3
- package/dist/symbol-picker.js +4 -6
- package/dist/symbols.js +22 -3
- package/dist/testing.d.ts +23 -1
- package/dist/testing.js +114 -0
- package/package.json +7 -6
- package/src/CallHierarchyPanel.tsx +26 -11
- package/src/EditorContextMenu.tsx +7 -0
- package/src/EditorView.tsx +9 -0
- package/src/LanguagePopups.tsx +4 -0
- package/src/PickPopup.tsx +40 -5
- package/src/WrapCard.tsx +64 -0
- package/src/call-hierarchy-model.ts +25 -3
- package/src/call-hierarchy.ts +62 -20
- package/src/clipboard-history.ts +102 -0
- package/src/code-actions.ts +48 -11
- package/src/code-vision.ts +3 -3
- package/src/completion.ts +15 -15
- package/src/context-menu-rows.ts +3 -2
- package/src/definition-link.ts +17 -5
- package/src/document-colors.ts +189 -0
- package/src/document-links.ts +129 -0
- package/src/document-query.ts +71 -0
- package/src/edit-locations.ts +162 -0
- package/src/editor-language.ts +80 -3
- package/src/emmet-module.d.ts +44 -0
- package/src/emmet.ts +73 -0
- package/src/folding.ts +3 -3
- package/src/format-on-type.ts +5 -5
- package/src/highlights.ts +3 -3
- package/src/history.ts +81 -1
- package/src/host-types.ts +10 -0
- package/src/index.ts +12 -3
- package/src/inlay-hints.ts +2 -2
- package/src/inline-completion.ts +221 -0
- package/src/key-priority.ts +9 -6
- package/src/linked-editing.ts +199 -0
- package/src/locales/en.json +31 -2
- package/src/locales/nl.json +31 -2
- package/src/markup-context.ts +262 -0
- package/src/markup.ts +367 -0
- package/src/navigation.ts +6 -6
- package/src/paste-history.ts +111 -0
- package/src/peek.ts +4 -4
- package/src/pick.ts +201 -19
- package/src/popups.ts +19 -1
- package/src/project-language.ts +136 -19
- package/src/rename.ts +11 -11
- package/src/rendered-docs.ts +2 -2
- package/src/selection-ranges.ts +3 -3
- package/src/signature.ts +6 -6
- package/src/snippet-session.ts +9 -4
- package/src/symbol-picker.ts +6 -6
- package/src/symbols.ts +30 -4
- package/src/testing.ts +126 -1
package/dist/call-hierarchy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StaleResultError } from '@adecore/lsp';
|
|
2
2
|
import { KEY_PRIORITY } from './key-priority.js';
|
|
3
|
-
import { CALL_LEVEL_LIMIT, childrenOf, moreIdOf, rootsOf, rowsOf, statusIdOf, stepsOf, targetOf } from './call-hierarchy-model.js';
|
|
3
|
+
import { CALL_LEVEL_LIMIT, childrenOf, isTypeDirection, moreIdOf, rootsOf, rowsOf, statusIdOf, stepsOf, targetOf, typeChildrenOf } from './call-hierarchy-model.js';
|
|
4
4
|
import { PEEK_HEIGHT } from './peek.js';
|
|
5
5
|
import { snippetOf } from './peek-model.js';
|
|
6
6
|
import { isShortcut } from './shortcut-keys.js';
|
|
@@ -8,6 +8,7 @@ import { messageOf } from './error-message.js';
|
|
|
8
8
|
import { realTimers, revealRow } from './timers.js';
|
|
9
9
|
const TOAST_ID = 'language-call-hierarchy';
|
|
10
10
|
const PREPARE = 'textDocument/prepareCallHierarchy';
|
|
11
|
+
const PREPARE_TYPES = 'textDocument/prepareTypeHierarchy';
|
|
11
12
|
/* The row the panel stands in is as tall as a peek's, plus the segmented control that is a pixel taller than the peek's title bar. */
|
|
12
13
|
export const CALL_HIERARCHY_HEIGHT = PEEK_HEIGHT + 2;
|
|
13
14
|
const OWNER = 'call-hierarchy';
|
|
@@ -24,6 +25,7 @@ export class CallHierarchyFeature {
|
|
|
24
25
|
nodes = new Map();
|
|
25
26
|
roots = [];
|
|
26
27
|
prepared = [];
|
|
28
|
+
position = null;
|
|
27
29
|
direction = 'incoming';
|
|
28
30
|
controller = new AbortController();
|
|
29
31
|
/* Raised whenever the tree starts over or closes, so an answer for the tree that was never lands in the one that is. */
|
|
@@ -37,11 +39,13 @@ export class CallHierarchyFeature {
|
|
|
37
39
|
editor
|
|
38
40
|
} = language;
|
|
39
41
|
const offs = [language.onKey(event => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
const calls = isShortcut(this.language.shortcuts.callHierarchy, event);
|
|
43
|
+
if (calls || isShortcut(this.language.shortcuts.typeHierarchy, event)) {
|
|
44
|
+
const [first, second] = calls ? ['incoming', 'outgoing'] : ['supertypes', 'subtypes'];
|
|
45
|
+
if (this.isOpen && isTypeDirection(this.direction) !== calls) {
|
|
46
|
+
this.setDirection(this.direction === first ? second : first);
|
|
43
47
|
} else {
|
|
44
|
-
void this.open();
|
|
48
|
+
void this.open(undefined, first);
|
|
45
49
|
}
|
|
46
50
|
return true;
|
|
47
51
|
}
|
|
@@ -60,35 +64,45 @@ export class CallHierarchyFeature {
|
|
|
60
64
|
/* Whether a server of this document answers the three requests the tree is made of. */
|
|
61
65
|
get supported() {
|
|
62
66
|
const {
|
|
63
|
-
|
|
67
|
+
service,
|
|
64
68
|
uri
|
|
65
69
|
} = this.language;
|
|
66
|
-
const {
|
|
67
|
-
service
|
|
68
|
-
} = project;
|
|
69
70
|
return service.prepareCallHierarchy !== undefined && service.incomingCalls !== undefined && service.outgoingCalls !== undefined && service.supports(PREPARE, uri);
|
|
70
71
|
}
|
|
71
|
-
/*
|
|
72
|
+
/* Whether a server of this document answers the three requests of the type hierarchy. */
|
|
73
|
+
get typesSupported() {
|
|
74
|
+
const {
|
|
75
|
+
service,
|
|
76
|
+
uri
|
|
77
|
+
} = this.language;
|
|
78
|
+
return service.prepareTypeHierarchy !== undefined && service.supertypes !== undefined && service.subtypes !== undefined && service.supports(PREPARE_TYPES, uri);
|
|
79
|
+
}
|
|
80
|
+
/*
|
|
81
|
+
* Opens the tree for the symbol at the position, on its callers unless told otherwise; `supertypes` or `subtypes`
|
|
82
|
+
* open the type hierarchy of the type at the position.
|
|
83
|
+
*/
|
|
72
84
|
async open(position = this.language.editor.getCaret(), direction = 'incoming') {
|
|
73
85
|
const {
|
|
74
86
|
editor,
|
|
75
|
-
|
|
87
|
+
service,
|
|
76
88
|
uri
|
|
77
89
|
} = this.language;
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
const types = isTypeDirection(direction);
|
|
91
|
+
if (!(types ? this.typesSupported : this.supported)) {
|
|
92
|
+
this.tell(this.say(types ? 'typesUnavailable' : 'unavailable'));
|
|
80
93
|
return;
|
|
81
94
|
}
|
|
82
95
|
this.close();
|
|
83
96
|
const epoch = this.epoch;
|
|
84
97
|
let items;
|
|
85
98
|
try {
|
|
86
|
-
|
|
99
|
+
const options = {
|
|
87
100
|
signal: this.controller.signal
|
|
88
|
-
}
|
|
101
|
+
};
|
|
102
|
+
items = types ? await service.prepareTypeHierarchy(uri, position, options) : await service.prepareCallHierarchy(uri, position, options);
|
|
89
103
|
} catch (error) {
|
|
90
104
|
if (epoch === this.epoch && !(error instanceof StaleResultError)) {
|
|
91
|
-
this.tell(this.say('failed', {
|
|
105
|
+
this.tell(this.say(types ? 'typesFailed' : 'failed', {
|
|
92
106
|
message: messageOf(error)
|
|
93
107
|
}));
|
|
94
108
|
}
|
|
@@ -98,11 +112,12 @@ export class CallHierarchyFeature {
|
|
|
98
112
|
return;
|
|
99
113
|
}
|
|
100
114
|
if (items === null || items.length === 0) {
|
|
101
|
-
this.tell(this.say('none'));
|
|
115
|
+
this.tell(this.say(types ? 'typesNone' : 'none'));
|
|
102
116
|
return;
|
|
103
117
|
}
|
|
104
118
|
this.language.peek.close();
|
|
105
119
|
this.prepared = items;
|
|
120
|
+
this.position = position;
|
|
106
121
|
this.direction = direction;
|
|
107
122
|
this.seed();
|
|
108
123
|
const active = this.roots[0];
|
|
@@ -143,12 +158,16 @@ export class CallHierarchyFeature {
|
|
|
143
158
|
this.language.editor.setInputPopup(null);
|
|
144
159
|
this.language.editor.focus();
|
|
145
160
|
}
|
|
146
|
-
/* Starts the tree over from the same symbols for the other direction. */
|
|
161
|
+
/* Starts the tree over from the same symbols for the other direction; a switch between calls and types prepares the symbol again. */
|
|
147
162
|
setDirection(direction) {
|
|
148
163
|
const view = this.language.popups.getState().callHierarchy;
|
|
149
164
|
if (view === null || view.direction === direction) {
|
|
150
165
|
return;
|
|
151
166
|
}
|
|
167
|
+
if (isTypeDirection(direction) !== isTypeDirection(view.direction)) {
|
|
168
|
+
void this.open(this.position ?? undefined, direction);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
152
171
|
this.reset();
|
|
153
172
|
this.direction = direction;
|
|
154
173
|
this.seed();
|
|
@@ -309,11 +328,9 @@ export class CallHierarchyFeature {
|
|
|
309
328
|
return;
|
|
310
329
|
}
|
|
311
330
|
const {
|
|
312
|
-
service,
|
|
313
331
|
i18n
|
|
314
332
|
} = this.language.project;
|
|
315
333
|
const {
|
|
316
|
-
uri,
|
|
317
334
|
editor
|
|
318
335
|
} = this.language;
|
|
319
336
|
const {
|
|
@@ -329,11 +346,10 @@ export class CallHierarchyFeature {
|
|
|
329
346
|
error: null
|
|
330
347
|
});
|
|
331
348
|
try {
|
|
332
|
-
const
|
|
349
|
+
const children = await this.childrenOf(direction, node, options);
|
|
333
350
|
if (epoch !== this.epoch) {
|
|
334
351
|
return;
|
|
335
352
|
}
|
|
336
|
-
const children = childrenOf(direction, node, calls ?? []);
|
|
337
353
|
for (const child of children) {
|
|
338
354
|
this.nodes.set(child.id, child);
|
|
339
355
|
}
|
|
@@ -360,6 +376,22 @@ export class CallHierarchyFeature {
|
|
|
360
376
|
});
|
|
361
377
|
}
|
|
362
378
|
}
|
|
379
|
+
async childrenOf(direction, node, options) {
|
|
380
|
+
const {
|
|
381
|
+
service,
|
|
382
|
+
uri
|
|
383
|
+
} = this.language;
|
|
384
|
+
switch (direction) {
|
|
385
|
+
case 'incoming':
|
|
386
|
+
return childrenOf(direction, node, (await service.incomingCalls(uri, node.item, options)) ?? []);
|
|
387
|
+
case 'outgoing':
|
|
388
|
+
return childrenOf(direction, node, (await service.outgoingCalls(uri, node.item, options)) ?? []);
|
|
389
|
+
case 'supertypes':
|
|
390
|
+
return typeChildrenOf(node, (await service.supertypes(uri, node.item, options)) ?? []);
|
|
391
|
+
case 'subtypes':
|
|
392
|
+
return typeChildrenOf(node, (await service.subtypes(uri, node.item, options)) ?? []);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
363
395
|
async preview(node, site) {
|
|
364
396
|
const {
|
|
365
397
|
project
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ClipboardEntry {
|
|
2
|
+
readonly text: string;
|
|
3
|
+
readonly wholeLines: boolean;
|
|
4
|
+
readonly at: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ClipboardHistoryOptions {
|
|
7
|
+
readonly limit?: number;
|
|
8
|
+
readonly maxLength?: number;
|
|
9
|
+
readonly entries?: readonly ClipboardEntry[];
|
|
10
|
+
onChange?(entries: readonly ClipboardEntry[]): void;
|
|
11
|
+
readonly clock?: () => number;
|
|
12
|
+
}
|
|
13
|
+
export declare class ClipboardHistory {
|
|
14
|
+
private readonly limit;
|
|
15
|
+
private readonly maxLength;
|
|
16
|
+
private readonly onChange;
|
|
17
|
+
private readonly clock;
|
|
18
|
+
private readonly listeners;
|
|
19
|
+
private list;
|
|
20
|
+
constructor(options?: ClipboardHistoryOptions);
|
|
21
|
+
get entries(): readonly ClipboardEntry[];
|
|
22
|
+
add(text: string, options?: {
|
|
23
|
+
readonly wholeLines?: boolean;
|
|
24
|
+
}): void;
|
|
25
|
+
remove(entry: ClipboardEntry): void;
|
|
26
|
+
promote(entry: ClipboardEntry): void;
|
|
27
|
+
clear(): void;
|
|
28
|
+
subscribe(listener: () => void): () => void;
|
|
29
|
+
private change;
|
|
30
|
+
private trimmed;
|
|
31
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* The texts copied or cut in the editors of a project, newest first, for Paste from History. */
|
|
2
|
+
export class ClipboardHistory {
|
|
3
|
+
limit;
|
|
4
|
+
maxLength;
|
|
5
|
+
onChange;
|
|
6
|
+
clock;
|
|
7
|
+
listeners = new Set();
|
|
8
|
+
list;
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.limit = options.limit ?? 100;
|
|
11
|
+
this.maxLength = options.maxLength ?? 10_000_000;
|
|
12
|
+
this.onChange = options.onChange;
|
|
13
|
+
this.clock = options.clock ?? Date.now;
|
|
14
|
+
this.list = this.trimmed(options.entries ?? []);
|
|
15
|
+
}
|
|
16
|
+
/* Newest first. */
|
|
17
|
+
get entries() {
|
|
18
|
+
return this.list;
|
|
19
|
+
}
|
|
20
|
+
/* Puts a copy on top. The same text again moves up instead of being kept twice, and nothing is kept for an empty text. */
|
|
21
|
+
add(text, options = {}) {
|
|
22
|
+
if (text === '') {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const entry = {
|
|
26
|
+
text,
|
|
27
|
+
wholeLines: options.wholeLines === true,
|
|
28
|
+
at: this.clock()
|
|
29
|
+
};
|
|
30
|
+
this.change([entry, ...this.list.filter(other => other.text !== text)]);
|
|
31
|
+
}
|
|
32
|
+
remove(entry) {
|
|
33
|
+
if (this.list.includes(entry)) {
|
|
34
|
+
this.change(this.list.filter(other => other !== entry));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/* Moves an entry to the top, as choosing it does. */
|
|
38
|
+
promote(entry) {
|
|
39
|
+
if (this.list.includes(entry) && this.list[0] !== entry) {
|
|
40
|
+
this.change([entry, ...this.list.filter(other => other !== entry)]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
clear() {
|
|
44
|
+
if (this.list.length > 0) {
|
|
45
|
+
this.change([]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
subscribe(listener) {
|
|
49
|
+
this.listeners.add(listener);
|
|
50
|
+
return () => this.listeners.delete(listener);
|
|
51
|
+
}
|
|
52
|
+
change(entries) {
|
|
53
|
+
this.list = this.trimmed(entries);
|
|
54
|
+
this.onChange?.(this.list);
|
|
55
|
+
this.listeners.forEach(listener => listener());
|
|
56
|
+
}
|
|
57
|
+
/* Keeps the newest entries that fit the limit and the total length. */
|
|
58
|
+
trimmed(entries) {
|
|
59
|
+
const kept = [];
|
|
60
|
+
let length = 0;
|
|
61
|
+
for (const entry of entries.slice(0, this.limit)) {
|
|
62
|
+
length += entry.text.length;
|
|
63
|
+
if (kept.length > 0 && length > this.maxLength) {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
kept.push(entry);
|
|
67
|
+
}
|
|
68
|
+
return kept;
|
|
69
|
+
}
|
|
70
|
+
}
|
package/dist/code-actions.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ActionEntry } from './code-actions-model.ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type Problem } from './diagnostics-model.ts';
|
|
3
3
|
import type { EditorLanguage } from './editor-language.ts';
|
|
4
4
|
import { type Timers } from './timers.ts';
|
|
5
5
|
export declare class CodeActionsFeature {
|
|
@@ -14,6 +14,8 @@ export declare class CodeActionsFeature {
|
|
|
14
14
|
quickFixFor(problem: Problem): Promise<void>;
|
|
15
15
|
organizeImports(): Promise<void>;
|
|
16
16
|
formatDocument(): Promise<void>;
|
|
17
|
+
get formatsSelection(): boolean;
|
|
18
|
+
formatSelection(): Promise<void>;
|
|
17
19
|
list(only: readonly string[]): Promise<ActionEntry[] | null>;
|
|
18
20
|
private ask;
|
|
19
21
|
private request;
|
package/dist/code-actions.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ErrorCodes, LspError, StaleResultError } from '@adecore/lsp';
|
|
2
2
|
import { KEY_PRIORITY } from './key-priority.js';
|
|
3
3
|
import { ACTION_GROUPS, REFACTOR_GROUPS, actionsOf, diagnosticsAt, fixableOnLine, isHint, mergeEntries, previewOf } from './code-actions-model.js';
|
|
4
|
+
import { comparePositions } from './diagnostics-model.js';
|
|
4
5
|
import { Refresher } from './refresher.js';
|
|
5
6
|
import { isShortcut } from './shortcut-keys.js';
|
|
6
7
|
import { realTimers } from './timers.js';
|
|
@@ -64,7 +65,7 @@ export class CodeActionsFeature {
|
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
get supported() {
|
|
67
|
-
return this.language.
|
|
68
|
+
return this.language.service.supports(METHOD, this.language.uri);
|
|
68
69
|
}
|
|
69
70
|
/* The list under the caret, or under the selection's start. */
|
|
70
71
|
open() {
|
|
@@ -121,15 +122,14 @@ export class CodeActionsFeature {
|
|
|
121
122
|
async formatDocument() {
|
|
122
123
|
const {
|
|
123
124
|
editor,
|
|
124
|
-
project,
|
|
125
125
|
uri
|
|
126
126
|
} = this.language;
|
|
127
|
-
if (!
|
|
127
|
+
if (!this.language.service.supports('textDocument/formatting', uri)) {
|
|
128
128
|
this.tell('error', this.say('noFormatter'));
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
131
|
try {
|
|
132
|
-
const edits = await
|
|
132
|
+
const edits = await this.language.service.formatting(uri, {
|
|
133
133
|
...editor.getIndentation()
|
|
134
134
|
});
|
|
135
135
|
if (edits !== null && edits.length > 0 && !editor.applyEdits(edits.map(edit => ({
|
|
@@ -142,6 +142,48 @@ export class CodeActionsFeature {
|
|
|
142
142
|
this.fail(error);
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
+
/* Whether a server formats a part of this document, so `formatSelection` has something to ask. */
|
|
146
|
+
get formatsSelection() {
|
|
147
|
+
return this.language.service.supports('textDocument/rangeFormatting', this.language.uri);
|
|
148
|
+
}
|
|
149
|
+
/*
|
|
150
|
+
* Formats what is selected, every selection in one request when the server formats several ranges at once and
|
|
151
|
+
* one by one otherwise; the whole document when nothing is selected.
|
|
152
|
+
*/
|
|
153
|
+
async formatSelection() {
|
|
154
|
+
const {
|
|
155
|
+
editor,
|
|
156
|
+
uri
|
|
157
|
+
} = this.language;
|
|
158
|
+
const ranges = editor.getSelections().filter(range => comparePositions(range.start, range.end) !== 0);
|
|
159
|
+
if (ranges.length === 0) {
|
|
160
|
+
await this.formatDocument();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (!this.formatsSelection) {
|
|
164
|
+
this.tell('error', this.say('noFormatter'));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const {
|
|
168
|
+
service
|
|
169
|
+
} = this.language;
|
|
170
|
+
const formatting = {
|
|
171
|
+
...editor.getIndentation()
|
|
172
|
+
};
|
|
173
|
+
try {
|
|
174
|
+
const edits = service.rangesFormatting !== undefined && service.supports('textDocument/rangesFormatting', uri) ? await service.rangesFormatting(uri, ranges, formatting) : (await Promise.all(ranges.map(range => service.rangeFormatting(uri, range, formatting, {
|
|
175
|
+
parallel: true
|
|
176
|
+
})))).flatMap(list => list ?? []);
|
|
177
|
+
if (edits !== null && edits.length > 0 && !editor.applyEdits(edits.map(edit => ({
|
|
178
|
+
range: edit.range,
|
|
179
|
+
text: edit.newText
|
|
180
|
+
})))) {
|
|
181
|
+
this.tell('error', this.say('readOnly'));
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
this.fail(error);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
145
187
|
/* The actions of one kind for the selection, as entries a menu can list and `apply` runs. */
|
|
146
188
|
list(only) {
|
|
147
189
|
if (!this.supported) {
|
|
@@ -206,7 +248,6 @@ export class CodeActionsFeature {
|
|
|
206
248
|
/* Asks the servers; null when they could not answer, with the reason said aloud for a request a person made. */
|
|
207
249
|
async request(range, triggerKind, options = {}) {
|
|
208
250
|
const {
|
|
209
|
-
project,
|
|
210
251
|
uri,
|
|
211
252
|
diagnostics
|
|
212
253
|
} = this.language;
|
|
@@ -224,7 +265,7 @@ export class CodeActionsFeature {
|
|
|
224
265
|
} : {}),
|
|
225
266
|
triggerKind: triggerKind
|
|
226
267
|
};
|
|
227
|
-
const entries = actionsOf(await
|
|
268
|
+
const entries = actionsOf(await this.language.service.codeActions(uri, range, context, {
|
|
228
269
|
signal
|
|
229
270
|
}), order);
|
|
230
271
|
// A server may answer with more than the kinds asked for.
|
|
@@ -283,16 +324,15 @@ export class CodeActionsFeature {
|
|
|
283
324
|
return known;
|
|
284
325
|
}
|
|
285
326
|
const {
|
|
286
|
-
project,
|
|
287
327
|
uri
|
|
288
328
|
} = this.language;
|
|
289
329
|
const {
|
|
290
330
|
action
|
|
291
331
|
} = entry;
|
|
292
332
|
let result = action;
|
|
293
|
-
if (action.edit === undefined &&
|
|
333
|
+
if (action.edit === undefined && this.language.service.providerOptions(METHOD, uri)?.resolveProvider === true) {
|
|
294
334
|
try {
|
|
295
|
-
result = await
|
|
335
|
+
result = await this.language.service.resolveCodeAction(uri, action, {
|
|
296
336
|
signal
|
|
297
337
|
});
|
|
298
338
|
} catch (error) {
|
|
@@ -383,7 +423,7 @@ export class CodeActionsFeature {
|
|
|
383
423
|
if (action.command?.command === INLINE_RENAME_COMMAND) {
|
|
384
424
|
await this.startRename(action.command);
|
|
385
425
|
} else if (action.command !== undefined) {
|
|
386
|
-
await
|
|
426
|
+
await this.language.service.executeCommand(uri, action.command);
|
|
387
427
|
}
|
|
388
428
|
} catch (error) {
|
|
389
429
|
this.fail(error);
|
package/dist/code-vision.js
CHANGED
|
@@ -111,7 +111,7 @@ export class CodeVisionFeature {
|
|
|
111
111
|
this.plan();
|
|
112
112
|
}
|
|
113
113
|
get canCount() {
|
|
114
|
-
return this.settings.usages && this.language.
|
|
114
|
+
return this.settings.usages && this.language.service.supports(REFERENCES, this.language.uri);
|
|
115
115
|
}
|
|
116
116
|
/* Queues the declarations in view whose count is not from the current text, nearest the top of the view first. */
|
|
117
117
|
plan() {
|
|
@@ -128,14 +128,13 @@ export class CodeVisionFeature {
|
|
|
128
128
|
}
|
|
129
129
|
async count(declaration) {
|
|
130
130
|
const {
|
|
131
|
-
project,
|
|
132
131
|
uri
|
|
133
132
|
} = this.language;
|
|
134
133
|
const controller = new AbortController();
|
|
135
134
|
this.running.set(declaration.id, controller);
|
|
136
135
|
const epoch = this.epoch;
|
|
137
136
|
try {
|
|
138
|
-
const locations = await
|
|
137
|
+
const locations = await this.language.service.references(uri, declaration.position, false, {
|
|
139
138
|
signal: controller.signal,
|
|
140
139
|
parallel: true
|
|
141
140
|
});
|
package/dist/completion.js
CHANGED
|
@@ -198,7 +198,7 @@ export class CompletionFeature {
|
|
|
198
198
|
};
|
|
199
199
|
recentChoicesOf(this.language.languageId).record(entry.item);
|
|
200
200
|
let item = this.resolved.get(entry.item) ?? entry.item;
|
|
201
|
-
const needsResolve = !this.resolved.has(entry.item) &&
|
|
201
|
+
const needsResolve = !this.resolved.has(entry.item) && this.language.service.providerOptions('completionItem/resolve', uri) !== undefined;
|
|
202
202
|
this.close();
|
|
203
203
|
if (needsResolve) {
|
|
204
204
|
// Resolving can add the import an item needs; an item that cannot be resolved is still inserted as it is.
|
|
@@ -482,7 +482,6 @@ export class CompletionFeature {
|
|
|
482
482
|
afterInsert(item, commit, lineBefore) {
|
|
483
483
|
const {
|
|
484
484
|
editor,
|
|
485
|
-
project,
|
|
486
485
|
uri,
|
|
487
486
|
signature
|
|
488
487
|
} = this.language;
|
|
@@ -508,7 +507,7 @@ export class CompletionFeature {
|
|
|
508
507
|
if (command.command === PARAMETER_HINTS_COMMAND) {
|
|
509
508
|
signature.trigger();
|
|
510
509
|
} else {
|
|
511
|
-
|
|
510
|
+
this.language.service.executeCommand(uri, command).catch(() => undefined);
|
|
512
511
|
}
|
|
513
512
|
}
|
|
514
513
|
/*
|
|
@@ -519,13 +518,12 @@ export class CompletionFeature {
|
|
|
519
518
|
async resolveNow(item, signal) {
|
|
520
519
|
const {
|
|
521
520
|
editor,
|
|
522
|
-
project,
|
|
523
521
|
uri
|
|
524
522
|
} = this.language;
|
|
525
523
|
try {
|
|
526
524
|
return {
|
|
527
525
|
...item,
|
|
528
|
-
...(await
|
|
526
|
+
...(await this.language.service.resolveCompletion(uri, item, {
|
|
529
527
|
signal
|
|
530
528
|
}))
|
|
531
529
|
};
|
|
@@ -535,14 +533,14 @@ export class CompletionFeature {
|
|
|
535
533
|
}
|
|
536
534
|
}
|
|
537
535
|
try {
|
|
538
|
-
const fresh = itemsOf(await
|
|
536
|
+
const fresh = itemsOf(await this.language.service.completion(uri, editor.getCaret(), {
|
|
539
537
|
triggerKind: 1
|
|
540
538
|
}, {
|
|
541
539
|
signal
|
|
542
540
|
})).items.find(candidate => candidate.label === item.label && candidate.kind === item.kind);
|
|
543
541
|
return fresh === undefined ? item : {
|
|
544
542
|
...fresh,
|
|
545
|
-
...(await
|
|
543
|
+
...(await this.language.service.resolveCompletion(uri, fresh, {
|
|
546
544
|
signal
|
|
547
545
|
}).catch(() => fresh))
|
|
548
546
|
};
|
|
@@ -672,17 +670,15 @@ export class CompletionFeature {
|
|
|
672
670
|
}
|
|
673
671
|
triggerCharacters() {
|
|
674
672
|
const {
|
|
675
|
-
project,
|
|
676
673
|
uri
|
|
677
674
|
} = this.language;
|
|
678
|
-
return
|
|
675
|
+
return this.language.service.providerOptions(METHOD, uri)?.triggerCharacters ?? [];
|
|
679
676
|
}
|
|
680
677
|
beginRequest(context, delay) {
|
|
681
678
|
const {
|
|
682
|
-
project,
|
|
683
679
|
uri
|
|
684
680
|
} = this.language;
|
|
685
|
-
if (!
|
|
681
|
+
if (!this.language.service.supports(METHOD, uri)) {
|
|
686
682
|
return;
|
|
687
683
|
}
|
|
688
684
|
this.timers.clear(this.requestTimer);
|
|
@@ -701,7 +697,7 @@ export class CompletionFeature {
|
|
|
701
697
|
this.controller = controller;
|
|
702
698
|
let normalized;
|
|
703
699
|
try {
|
|
704
|
-
const result = await
|
|
700
|
+
const result = await this.language.service.completion(uri, position, context, {
|
|
705
701
|
signal: controller.signal
|
|
706
702
|
});
|
|
707
703
|
if (request !== this.request || this.controller !== controller || controller.signal.aborted) {
|
|
@@ -805,20 +801,19 @@ export class CompletionFeature {
|
|
|
805
801
|
}
|
|
806
802
|
scheduleResolve() {
|
|
807
803
|
const {
|
|
808
|
-
project,
|
|
809
804
|
uri
|
|
810
805
|
} = this.language;
|
|
811
806
|
this.timers.clear(this.resolveTimer);
|
|
812
807
|
this.resolving?.abort();
|
|
813
808
|
const entry = this.ranked[this.active];
|
|
814
|
-
if (entry === undefined || this.resolved.has(entry.item) ||
|
|
809
|
+
if (entry === undefined || this.resolved.has(entry.item) || this.language.service.providerOptions('completionItem/resolve', uri) === undefined) {
|
|
815
810
|
return;
|
|
816
811
|
}
|
|
817
812
|
const request = this.request;
|
|
818
813
|
this.resolveTimer = this.timers.set(() => {
|
|
819
814
|
const controller = new AbortController();
|
|
820
815
|
this.resolving = controller;
|
|
821
|
-
void
|
|
816
|
+
void this.language.service.resolveCompletion(uri, entry.item, {
|
|
822
817
|
signal: controller.signal
|
|
823
818
|
}).then(item => {
|
|
824
819
|
this.resolved.set(entry.item, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { KeymapId } from '@adecore/editor/keymap';
|
|
2
2
|
import type { NavigationKind } from './navigation.ts';
|
|
3
|
-
export type MenuRowId = NavigationKind | 'peekReferences' | 'callHierarchy' | 'renameSymbol' | 'codeActions';
|
|
3
|
+
export type MenuRowId = NavigationKind | 'peekReferences' | 'callHierarchy' | 'typeHierarchy' | 'renameSymbol' | 'codeActions';
|
|
4
4
|
export interface MenuRowSpec {
|
|
5
5
|
readonly id: MenuRowId;
|
|
6
6
|
readonly method: string;
|
|
@@ -24,6 +24,10 @@ const REFERENCES = [{
|
|
|
24
24
|
id: 'callHierarchy',
|
|
25
25
|
method: 'textDocument/prepareCallHierarchy',
|
|
26
26
|
shortcut: 'callHierarchy'
|
|
27
|
+
}, {
|
|
28
|
+
id: 'typeHierarchy',
|
|
29
|
+
method: 'textDocument/prepareTypeHierarchy',
|
|
30
|
+
shortcut: 'typeHierarchy'
|
|
27
31
|
}];
|
|
28
32
|
const CHANGES = [{
|
|
29
33
|
id: 'renameSymbol',
|
package/dist/definition-link.js
CHANGED
|
@@ -25,8 +25,8 @@ export function followModKey(apple, onHeld) {
|
|
|
25
25
|
}
|
|
26
26
|
/*
|
|
27
27
|
* The name under the pointer drawn as a link while Cmd (Ctrl elsewhere) is held and a server knows where it
|
|
28
|
-
* is defined, which is what a Mod+click on it follows.
|
|
29
|
-
* key comes from the window.
|
|
28
|
+
* is defined, which is what a Mod+click on it follows. A document link under the pointer goes first. The
|
|
29
|
+
* editor only says where the pointer is, so the key comes from the window.
|
|
30
30
|
*/
|
|
31
31
|
export class DefinitionLinkFeature {
|
|
32
32
|
language;
|
|
@@ -71,13 +71,23 @@ export class DefinitionLinkFeature {
|
|
|
71
71
|
const {
|
|
72
72
|
pointer
|
|
73
73
|
} = this;
|
|
74
|
-
|
|
74
|
+
const link = pointer === null ? null : this.language.links.rangeAt(pointer);
|
|
75
|
+
if (this.held && link !== null) {
|
|
76
|
+
const key = `link:${link.start.line}:${link.start.character}`;
|
|
77
|
+
if (key !== this.shownKey) {
|
|
78
|
+
this.clear();
|
|
79
|
+
this.shownKey = key;
|
|
80
|
+
this.drawn = true;
|
|
81
|
+
this.language.editor.setLink(link);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (!this.held || pointer === null || !this.language.service.supports('textDocument/definition', this.language.uri)) {
|
|
75
86
|
this.clear();
|
|
76
87
|
return;
|
|
77
88
|
}
|
|
78
89
|
const {
|
|
79
90
|
editor,
|
|
80
|
-
project,
|
|
81
91
|
uri
|
|
82
92
|
} = this.language;
|
|
83
93
|
const line = lineTextOf(editor, pointer.line);
|
|
@@ -95,7 +105,7 @@ export class DefinitionLinkFeature {
|
|
|
95
105
|
const request = ++this.request;
|
|
96
106
|
const controller = new AbortController();
|
|
97
107
|
this.lookup = controller;
|
|
98
|
-
|
|
108
|
+
this.language.service.definition(uri, pointer, {
|
|
99
109
|
signal: controller.signal
|
|
100
110
|
}).then(result => {
|
|
101
111
|
if (request === this.request && locationsOf(result).length > 0) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Color, ColorInformation, ColorPresentation, TextEdit } from '@adecore/lsp';
|
|
2
|
+
import type { EditorLanguage } from './editor-language.ts';
|
|
3
|
+
import { type Timers } from './timers.ts';
|
|
4
|
+
export declare function cssColorOf(color: Color): string;
|
|
5
|
+
export declare function colorOfHex(value: string): Color | null;
|
|
6
|
+
export declare function presentationEdits(presentation: ColorPresentation, information: ColorInformation): TextEdit[];
|
|
7
|
+
export declare class DocumentColorsFeature {
|
|
8
|
+
private readonly language;
|
|
9
|
+
private colors;
|
|
10
|
+
private readonly query;
|
|
11
|
+
private enabled;
|
|
12
|
+
constructor(language: EditorLanguage, timers?: Timers);
|
|
13
|
+
get supported(): boolean;
|
|
14
|
+
all(): readonly ColorInformation[];
|
|
15
|
+
configure(settings: {
|
|
16
|
+
readonly enabled?: boolean;
|
|
17
|
+
}): void;
|
|
18
|
+
presentations(information: ColorInformation, color?: Color): Promise<ColorPresentation[]>;
|
|
19
|
+
apply(presentation: ColorPresentation, information: ColorInformation): boolean;
|
|
20
|
+
private show;
|
|
21
|
+
private pressed;
|
|
22
|
+
private open;
|
|
23
|
+
private choose;
|
|
24
|
+
}
|