@adecore/editor-react 0.42.0 → 0.44.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/LanguagePopups.js +7 -0
- package/dist/PickPopup.js +245 -104
- 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.d.ts +28 -0
- package/dist/completion.js +83 -27
- 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 +23 -1
- package/dist/editor-language.js +83 -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 +10 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +10 -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 +9 -5
- package/dist/key-priority.js +11 -6
- package/dist/linked-editing.d.ts +26 -0
- package/dist/linked-editing.js +215 -0
- package/dist/live-templates.d.ts +16 -0
- package/dist/live-templates.js +289 -0
- package/dist/locales/en.json +61 -2
- package/dist/locales/nl.json +61 -2
- package/dist/markup-context.d.ts +55 -0
- package/dist/markup-context.js +408 -0
- package/dist/markup.d.ts +39 -0
- package/dist/markup.js +465 -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 +21 -2
- package/dist/pick.js +152 -19
- package/dist/popups.d.ts +10 -0
- package/dist/popups.js +2 -1
- package/dist/postfix.d.ts +21 -0
- package/dist/postfix.js +212 -0
- package/dist/project-language.d.ts +20 -1
- package/dist/project-language.js +132 -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 +24 -0
- package/dist/signature.js +3 -6
- package/dist/snippet-insert.d.ts +10 -0
- package/dist/snippet-insert.js +217 -0
- package/dist/snippet-session.d.ts +2 -2
- package/dist/snippet-session.js +3 -3
- package/dist/snippet.d.ts +7 -1
- package/dist/snippet.js +65 -8
- package/dist/surround-constructs.d.ts +10 -0
- package/dist/surround-constructs.js +100 -0
- package/dist/surround.d.ts +18 -0
- package/dist/surround.js +399 -0
- package/dist/symbol-picker.js +4 -6
- package/dist/symbols.js +22 -3
- package/dist/template-builtins.d.ts +3 -0
- package/dist/template-builtins.js +46 -0
- package/dist/template-context.d.ts +12 -0
- package/dist/template-context.js +56 -0
- package/dist/templates.d.ts +59 -0
- package/dist/templates.js +103 -0
- 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/LanguagePopups.tsx +4 -0
- package/src/PickPopup.tsx +47 -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 +123 -25
- 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 +86 -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 +17 -0
- package/src/index.ts +28 -3
- package/src/inlay-hints.ts +2 -2
- package/src/inline-completion.ts +221 -0
- package/src/key-priority.ts +11 -6
- package/src/linked-editing.ts +199 -0
- package/src/live-templates.ts +315 -0
- package/src/locales/en.json +61 -2
- package/src/locales/nl.json +61 -2
- package/src/markup-context.ts +387 -0
- package/src/markup.ts +377 -0
- package/src/navigation.ts +6 -6
- package/src/paste-history.ts +111 -0
- package/src/peek.ts +4 -4
- package/src/pick.ts +218 -20
- package/src/popups.ts +21 -1
- package/src/postfix.ts +224 -0
- package/src/project-language.ts +139 -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-insert.ts +258 -0
- package/src/snippet-session.ts +9 -4
- package/src/snippet.ts +82 -7
- package/src/surround-constructs.ts +85 -0
- package/src/surround.ts +430 -0
- package/src/symbol-picker.ts +6 -6
- package/src/symbols.ts +30 -4
- package/src/template-builtins.ts +94 -0
- package/src/template-context.ts +65 -0
- package/src/templates.ts +197 -0
- package/src/testing.ts +126 -1
package/src/call-hierarchy.ts
CHANGED
|
@@ -5,12 +5,14 @@ import type { EditorLanguage } from './editor-language.ts';
|
|
|
5
5
|
import {
|
|
6
6
|
CALL_LEVEL_LIMIT,
|
|
7
7
|
childrenOf,
|
|
8
|
+
isTypeDirection,
|
|
8
9
|
moreIdOf,
|
|
9
10
|
rootsOf,
|
|
10
11
|
rowsOf,
|
|
11
12
|
statusIdOf,
|
|
12
13
|
stepsOf,
|
|
13
14
|
targetOf,
|
|
15
|
+
typeChildrenOf,
|
|
14
16
|
type CallDirection,
|
|
15
17
|
type CallNode,
|
|
16
18
|
type CallRow
|
|
@@ -23,6 +25,7 @@ import { realTimers, revealRow, type Timers } from './timers.ts';
|
|
|
23
25
|
|
|
24
26
|
const TOAST_ID = 'language-call-hierarchy';
|
|
25
27
|
const PREPARE = 'textDocument/prepareCallHierarchy';
|
|
28
|
+
const PREPARE_TYPES = 'textDocument/prepareTypeHierarchy';
|
|
26
29
|
|
|
27
30
|
/* 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. */
|
|
28
31
|
export const CALL_HIERARCHY_HEIGHT = PEEK_HEIGHT + 2;
|
|
@@ -42,6 +45,7 @@ export class CallHierarchyFeature {
|
|
|
42
45
|
private nodes = new Map<string, CallNode>();
|
|
43
46
|
private roots: string[] = [];
|
|
44
47
|
private prepared: CallHierarchyItem[] = [];
|
|
48
|
+
private position: EditorPosition | null = null;
|
|
45
49
|
private direction: CallDirection = 'incoming';
|
|
46
50
|
private controller = new AbortController();
|
|
47
51
|
|
|
@@ -58,11 +62,13 @@ export class CallHierarchyFeature {
|
|
|
58
62
|
|
|
59
63
|
const offs = [
|
|
60
64
|
language.onKey((event) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
const calls = isShortcut(this.language.shortcuts.callHierarchy, event);
|
|
66
|
+
if (calls || isShortcut(this.language.shortcuts.typeHierarchy, event)) {
|
|
67
|
+
const [first, second]: CallDirection[] = calls ? ['incoming', 'outgoing'] : ['supertypes', 'subtypes'];
|
|
68
|
+
if (this.isOpen && isTypeDirection(this.direction) !== calls) {
|
|
69
|
+
this.setDirection(this.direction === first ? second : first);
|
|
64
70
|
} else {
|
|
65
|
-
void this.open();
|
|
71
|
+
void this.open(undefined, first);
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
return true;
|
|
@@ -88,8 +94,7 @@ export class CallHierarchyFeature {
|
|
|
88
94
|
|
|
89
95
|
/* Whether a server of this document answers the three requests the tree is made of. */
|
|
90
96
|
get supported(): boolean {
|
|
91
|
-
const {
|
|
92
|
-
const { service } = project;
|
|
97
|
+
const { service, uri } = this.language;
|
|
93
98
|
|
|
94
99
|
return (
|
|
95
100
|
service.prepareCallHierarchy !== undefined &&
|
|
@@ -99,12 +104,28 @@ export class CallHierarchyFeature {
|
|
|
99
104
|
);
|
|
100
105
|
}
|
|
101
106
|
|
|
102
|
-
/*
|
|
107
|
+
/* Whether a server of this document answers the three requests of the type hierarchy. */
|
|
108
|
+
get typesSupported(): boolean {
|
|
109
|
+
const { service, uri } = this.language;
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
service.prepareTypeHierarchy !== undefined &&
|
|
113
|
+
service.supertypes !== undefined &&
|
|
114
|
+
service.subtypes !== undefined &&
|
|
115
|
+
service.supports(PREPARE_TYPES, uri)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/*
|
|
120
|
+
* Opens the tree for the symbol at the position, on its callers unless told otherwise; `supertypes` or `subtypes`
|
|
121
|
+
* open the type hierarchy of the type at the position.
|
|
122
|
+
*/
|
|
103
123
|
async open(position: EditorPosition = this.language.editor.getCaret(), direction: CallDirection = 'incoming'): Promise<void> {
|
|
104
|
-
const { editor,
|
|
124
|
+
const { editor, service, uri } = this.language;
|
|
125
|
+
const types = isTypeDirection(direction);
|
|
105
126
|
|
|
106
|
-
if (!this.supported) {
|
|
107
|
-
this.tell(this.say('unavailable'));
|
|
127
|
+
if (!(types ? this.typesSupported : this.supported)) {
|
|
128
|
+
this.tell(this.say(types ? 'typesUnavailable' : 'unavailable'));
|
|
108
129
|
|
|
109
130
|
return;
|
|
110
131
|
}
|
|
@@ -114,10 +135,12 @@ export class CallHierarchyFeature {
|
|
|
114
135
|
let items: CallHierarchyItem[] | null;
|
|
115
136
|
|
|
116
137
|
try {
|
|
117
|
-
|
|
138
|
+
const options = { signal: this.controller.signal };
|
|
139
|
+
|
|
140
|
+
items = types ? await service.prepareTypeHierarchy!(uri, position, options) : await service.prepareCallHierarchy!(uri, position, options);
|
|
118
141
|
} catch (error) {
|
|
119
142
|
if (epoch === this.epoch && !(error instanceof StaleResultError)) {
|
|
120
|
-
this.tell(this.say('failed', { message: messageOf(error) }));
|
|
143
|
+
this.tell(this.say(types ? 'typesFailed' : 'failed', { message: messageOf(error) }));
|
|
121
144
|
}
|
|
122
145
|
|
|
123
146
|
return;
|
|
@@ -128,13 +151,14 @@ export class CallHierarchyFeature {
|
|
|
128
151
|
}
|
|
129
152
|
|
|
130
153
|
if (items === null || items.length === 0) {
|
|
131
|
-
this.tell(this.say('none'));
|
|
154
|
+
this.tell(this.say(types ? 'typesNone' : 'none'));
|
|
132
155
|
|
|
133
156
|
return;
|
|
134
157
|
}
|
|
135
158
|
|
|
136
159
|
this.language.peek.close();
|
|
137
160
|
this.prepared = items;
|
|
161
|
+
this.position = position;
|
|
138
162
|
this.direction = direction;
|
|
139
163
|
this.seed();
|
|
140
164
|
const active = this.roots[0]!;
|
|
@@ -171,7 +195,7 @@ export class CallHierarchyFeature {
|
|
|
171
195
|
this.language.editor.focus();
|
|
172
196
|
}
|
|
173
197
|
|
|
174
|
-
/* Starts the tree over from the same symbols for the other direction. */
|
|
198
|
+
/* Starts the tree over from the same symbols for the other direction; a switch between calls and types prepares the symbol again. */
|
|
175
199
|
setDirection(direction: CallDirection): void {
|
|
176
200
|
const view = this.language.popups.getState().callHierarchy;
|
|
177
201
|
|
|
@@ -179,6 +203,12 @@ export class CallHierarchyFeature {
|
|
|
179
203
|
return;
|
|
180
204
|
}
|
|
181
205
|
|
|
206
|
+
if (isTypeDirection(direction) !== isTypeDirection(view.direction)) {
|
|
207
|
+
void this.open(this.position ?? undefined, direction);
|
|
208
|
+
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
182
212
|
this.reset();
|
|
183
213
|
this.direction = direction;
|
|
184
214
|
this.seed();
|
|
@@ -331,22 +361,19 @@ export class CallHierarchyFeature {
|
|
|
331
361
|
return;
|
|
332
362
|
}
|
|
333
363
|
|
|
334
|
-
const {
|
|
335
|
-
const {
|
|
364
|
+
const { i18n } = this.language.project;
|
|
365
|
+
const { editor } = this.language;
|
|
336
366
|
const { direction, epoch } = this;
|
|
337
367
|
const options = { signal: this.controller.signal, parallel: true };
|
|
338
368
|
this.patch(id, { load: 'loading', error: null });
|
|
339
369
|
|
|
340
370
|
try {
|
|
341
|
-
const
|
|
342
|
-
direction === 'incoming' ? await service.incomingCalls!(uri, node.item, options) : await service.outgoingCalls!(uri, node.item, options);
|
|
371
|
+
const children = await this.childrenOf(direction, node, options);
|
|
343
372
|
|
|
344
373
|
if (epoch !== this.epoch) {
|
|
345
374
|
return;
|
|
346
375
|
}
|
|
347
376
|
|
|
348
|
-
const children = childrenOf(direction, node, calls ?? []);
|
|
349
|
-
|
|
350
377
|
for (const child of children) {
|
|
351
378
|
this.nodes.set(child.id, child);
|
|
352
379
|
}
|
|
@@ -368,6 +395,21 @@ export class CallHierarchyFeature {
|
|
|
368
395
|
}
|
|
369
396
|
}
|
|
370
397
|
|
|
398
|
+
private async childrenOf(direction: CallDirection, node: CallNode, options: { signal: AbortSignal; parallel: boolean }): Promise<CallNode[]> {
|
|
399
|
+
const { service, uri } = this.language;
|
|
400
|
+
|
|
401
|
+
switch (direction) {
|
|
402
|
+
case 'incoming':
|
|
403
|
+
return childrenOf(direction, node, (await service.incomingCalls!(uri, node.item, options)) ?? []);
|
|
404
|
+
case 'outgoing':
|
|
405
|
+
return childrenOf(direction, node, (await service.outgoingCalls!(uri, node.item, options)) ?? []);
|
|
406
|
+
case 'supertypes':
|
|
407
|
+
return typeChildrenOf(node, (await service.supertypes!(uri, node.item, options)) ?? []);
|
|
408
|
+
case 'subtypes':
|
|
409
|
+
return typeChildrenOf(node, (await service.subtypes!(uri, node.item, options)) ?? []);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
371
413
|
private async preview(node: CallNode, site: number): Promise<void> {
|
|
372
414
|
const { project } = this.language;
|
|
373
415
|
const epoch = ++this.previewEpoch;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* One copy or cut, as the editors of a project made it. */
|
|
2
|
+
export interface ClipboardEntry {
|
|
3
|
+
readonly text: string;
|
|
4
|
+
/* The copy took the lines of bare carets, which paste back above the lines of bare carets. */
|
|
5
|
+
readonly wholeLines: boolean;
|
|
6
|
+
readonly at: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ClipboardHistoryOptions {
|
|
10
|
+
/* How many entries the history keeps; 100. */
|
|
11
|
+
readonly limit?: number;
|
|
12
|
+
/* The UTF-16 length all entries may take together; 10,000,000. The oldest go first, and the newest stays even when it alone is longer. */
|
|
13
|
+
readonly maxLength?: number;
|
|
14
|
+
/* What a host kept, newest first. */
|
|
15
|
+
readonly entries?: readonly ClipboardEntry[];
|
|
16
|
+
/* Told after every change, for a host that keeps the entries. */
|
|
17
|
+
onChange?(entries: readonly ClipboardEntry[]): void;
|
|
18
|
+
readonly clock?: () => number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* The texts copied or cut in the editors of a project, newest first, for Paste from History. */
|
|
22
|
+
export class ClipboardHistory {
|
|
23
|
+
private readonly limit: number;
|
|
24
|
+
private readonly maxLength: number;
|
|
25
|
+
private readonly onChange: ((entries: readonly ClipboardEntry[]) => void) | undefined;
|
|
26
|
+
private readonly clock: () => number;
|
|
27
|
+
private readonly listeners = new Set<() => void>();
|
|
28
|
+
private list: readonly ClipboardEntry[];
|
|
29
|
+
|
|
30
|
+
constructor(options: ClipboardHistoryOptions = {}) {
|
|
31
|
+
this.limit = options.limit ?? 100;
|
|
32
|
+
this.maxLength = options.maxLength ?? 10_000_000;
|
|
33
|
+
this.onChange = options.onChange;
|
|
34
|
+
this.clock = options.clock ?? Date.now;
|
|
35
|
+
this.list = this.trimmed(options.entries ?? []);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Newest first. */
|
|
39
|
+
get entries(): readonly ClipboardEntry[] {
|
|
40
|
+
return this.list;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Puts a copy on top. The same text again moves up instead of being kept twice, and nothing is kept for an empty text. */
|
|
44
|
+
add(text: string, options: { readonly wholeLines?: boolean } = {}): void {
|
|
45
|
+
if (text === '') {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const entry = { text, wholeLines: options.wholeLines === true, at: this.clock() };
|
|
50
|
+
|
|
51
|
+
this.change([entry, ...this.list.filter((other) => other.text !== text)]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
remove(entry: ClipboardEntry): void {
|
|
55
|
+
if (this.list.includes(entry)) {
|
|
56
|
+
this.change(this.list.filter((other) => other !== entry));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Moves an entry to the top, as choosing it does. */
|
|
61
|
+
promote(entry: ClipboardEntry): void {
|
|
62
|
+
if (this.list.includes(entry) && this.list[0] !== entry) {
|
|
63
|
+
this.change([entry, ...this.list.filter((other) => other !== entry)]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
clear(): void {
|
|
68
|
+
if (this.list.length > 0) {
|
|
69
|
+
this.change([]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
subscribe(listener: () => void): () => void {
|
|
74
|
+
this.listeners.add(listener);
|
|
75
|
+
|
|
76
|
+
return () => this.listeners.delete(listener);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private change(entries: readonly ClipboardEntry[]): void {
|
|
80
|
+
this.list = this.trimmed(entries);
|
|
81
|
+
this.onChange?.(this.list);
|
|
82
|
+
this.listeners.forEach((listener) => listener());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Keeps the newest entries that fit the limit and the total length. */
|
|
86
|
+
private trimmed(entries: readonly ClipboardEntry[]): readonly ClipboardEntry[] {
|
|
87
|
+
const kept: ClipboardEntry[] = [];
|
|
88
|
+
let length = 0;
|
|
89
|
+
|
|
90
|
+
for (const entry of entries.slice(0, this.limit)) {
|
|
91
|
+
length += entry.text.length;
|
|
92
|
+
|
|
93
|
+
if (kept.length > 0 && length > this.maxLength) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
kept.push(entry);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return kept;
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/code-actions.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
type ActionEntry,
|
|
14
14
|
type ActionGroup
|
|
15
15
|
} from './code-actions-model.ts';
|
|
16
|
-
import type
|
|
16
|
+
import { comparePositions, type Problem } from './diagnostics-model.ts';
|
|
17
17
|
import type { EditorLanguage } from './editor-language.ts';
|
|
18
18
|
import type { PickGroup, PickPreview } from './popups.ts';
|
|
19
19
|
import { Refresher } from './refresher.ts';
|
|
@@ -122,7 +122,7 @@ export class CodeActionsFeature {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
get supported(): boolean {
|
|
125
|
-
return this.language.
|
|
125
|
+
return this.language.service.supports(METHOD, this.language.uri);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/* The list under the caret, or under the selection's start. */
|
|
@@ -162,16 +162,16 @@ export class CodeActionsFeature {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
async formatDocument(): Promise<void> {
|
|
165
|
-
const { editor,
|
|
165
|
+
const { editor, uri } = this.language;
|
|
166
166
|
|
|
167
|
-
if (!
|
|
167
|
+
if (!this.language.service.supports('textDocument/formatting', uri)) {
|
|
168
168
|
this.tell('error', this.say('noFormatter'));
|
|
169
169
|
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
try {
|
|
174
|
-
const edits = await
|
|
174
|
+
const edits = await this.language.service.formatting(uri, { ...editor.getIndentation() });
|
|
175
175
|
|
|
176
176
|
if (edits !== null && edits.length > 0 && !editor.applyEdits(edits.map((edit) => ({ range: edit.range, text: edit.newText })))) {
|
|
177
177
|
this.tell('error', this.say('readOnly'));
|
|
@@ -181,6 +181,43 @@ export class CodeActionsFeature {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/* Whether a server formats a part of this document, so `formatSelection` has something to ask. */
|
|
185
|
+
get formatsSelection(): boolean {
|
|
186
|
+
return this.language.service.supports('textDocument/rangeFormatting', this.language.uri);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/*
|
|
190
|
+
* Formats what is selected, every selection in one request when the server formats several ranges at once and
|
|
191
|
+
* one by one otherwise; the whole document when nothing is selected.
|
|
192
|
+
*/
|
|
193
|
+
async formatSelection(): Promise<void> {
|
|
194
|
+
const { editor, uri } = this.language;
|
|
195
|
+
const ranges = editor.getSelections().filter((range) => comparePositions(range.start, range.end) !== 0);
|
|
196
|
+
if (ranges.length === 0) {
|
|
197
|
+
await this.formatDocument();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (!this.formatsSelection) {
|
|
201
|
+
this.tell('error', this.say('noFormatter'));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const { service } = this.language;
|
|
205
|
+
const formatting = { ...editor.getIndentation() };
|
|
206
|
+
try {
|
|
207
|
+
const edits =
|
|
208
|
+
service.rangesFormatting !== undefined && service.supports('textDocument/rangesFormatting', uri)
|
|
209
|
+
? await service.rangesFormatting(uri, ranges, formatting)
|
|
210
|
+
: (await Promise.all(ranges.map((range) => service.rangeFormatting(uri, range, formatting, { parallel: true })))).flatMap(
|
|
211
|
+
(list) => list ?? []
|
|
212
|
+
);
|
|
213
|
+
if (edits !== null && edits.length > 0 && !editor.applyEdits(edits.map((edit) => ({ range: edit.range, text: edit.newText })))) {
|
|
214
|
+
this.tell('error', this.say('readOnly'));
|
|
215
|
+
}
|
|
216
|
+
} catch (error) {
|
|
217
|
+
this.fail(error);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
184
221
|
/* The actions of one kind for the selection, as entries a menu can list and `apply` runs. */
|
|
185
222
|
list(only: readonly string[]): Promise<ActionEntry[] | null> {
|
|
186
223
|
if (!this.supported) {
|
|
@@ -247,7 +284,7 @@ export class CodeActionsFeature {
|
|
|
247
284
|
|
|
248
285
|
/* Asks the servers; null when they could not answer, with the reason said aloud for a request a person made. */
|
|
249
286
|
private async request(range: EditorRange, triggerKind: number, options: RequestOptions = {}): Promise<ActionEntry[] | null> {
|
|
250
|
-
const {
|
|
287
|
+
const { uri, diagnostics } = this.language;
|
|
251
288
|
const { only, signal, order } = options;
|
|
252
289
|
|
|
253
290
|
try {
|
|
@@ -264,7 +301,7 @@ export class CodeActionsFeature {
|
|
|
264
301
|
triggerKind: triggerKind as 1 | 2
|
|
265
302
|
};
|
|
266
303
|
|
|
267
|
-
const entries = actionsOf(await
|
|
304
|
+
const entries = actionsOf(await this.language.service.codeActions(uri, range, context, { signal }), order);
|
|
268
305
|
|
|
269
306
|
// A server may answer with more than the kinds asked for.
|
|
270
307
|
return only ? entries.filter((entry) => only.some((kind) => entry.action.kind === kind || entry.action.kind?.startsWith(`${kind}.`))) : entries;
|
|
@@ -329,13 +366,13 @@ export class CodeActionsFeature {
|
|
|
329
366
|
return known;
|
|
330
367
|
}
|
|
331
368
|
|
|
332
|
-
const {
|
|
369
|
+
const { uri } = this.language;
|
|
333
370
|
const { action } = entry;
|
|
334
371
|
let result = action;
|
|
335
372
|
|
|
336
|
-
if (action.edit === undefined &&
|
|
373
|
+
if (action.edit === undefined && this.language.service.providerOptions(METHOD, uri)?.resolveProvider === true) {
|
|
337
374
|
try {
|
|
338
|
-
result = await
|
|
375
|
+
result = await this.language.service.resolveCodeAction(uri, action, { signal });
|
|
339
376
|
} catch (error) {
|
|
340
377
|
if (isRefusal(error)) {
|
|
341
378
|
throw new ActionRefused((error as Error).message);
|
|
@@ -427,7 +464,7 @@ export class CodeActionsFeature {
|
|
|
427
464
|
if (action.command?.command === INLINE_RENAME_COMMAND) {
|
|
428
465
|
await this.startRename(action.command);
|
|
429
466
|
} else if (action.command !== undefined) {
|
|
430
|
-
await
|
|
467
|
+
await this.language.service.executeCommand(uri, action.command);
|
|
431
468
|
}
|
|
432
469
|
} catch (error) {
|
|
433
470
|
this.fail(error);
|
package/src/code-vision.ts
CHANGED
|
@@ -149,7 +149,7 @@ export class CodeVisionFeature {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
private get canCount(): boolean {
|
|
152
|
-
return this.settings.usages && this.language.
|
|
152
|
+
return this.settings.usages && this.language.service.supports(REFERENCES, this.language.uri);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
/* Queues the declarations in view whose count is not from the current text, nearest the top of the view first. */
|
|
@@ -180,13 +180,13 @@ export class CodeVisionFeature {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
private async count(declaration: CodeVisionDeclaration): Promise<void> {
|
|
183
|
-
const {
|
|
183
|
+
const { uri } = this.language;
|
|
184
184
|
const controller = new AbortController();
|
|
185
185
|
this.running.set(declaration.id, controller);
|
|
186
186
|
const epoch = this.epoch;
|
|
187
187
|
|
|
188
188
|
try {
|
|
189
|
-
const locations = await
|
|
189
|
+
const locations = await this.language.service.references(uri, declaration.position, false, { signal: controller.signal, parallel: true });
|
|
190
190
|
|
|
191
191
|
if (!this.disposed && epoch === this.epoch) {
|
|
192
192
|
this.counts.set(declaration.id, { count: distinctPlaces(locations ?? []), epoch });
|