@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.
Files changed (150) hide show
  1. package/dist/CallHierarchyPanel.js +177 -181
  2. package/dist/EditorContextMenu.js +118 -105
  3. package/dist/LanguagePopups.js +7 -0
  4. package/dist/PickPopup.js +245 -104
  5. package/dist/WrapCard.d.ts +8 -0
  6. package/dist/WrapCard.js +172 -0
  7. package/dist/call-hierarchy-model.d.ts +4 -2
  8. package/dist/call-hierarchy-model.js +20 -0
  9. package/dist/call-hierarchy.d.ts +3 -0
  10. package/dist/call-hierarchy.js +54 -22
  11. package/dist/clipboard-history.d.ts +31 -0
  12. package/dist/clipboard-history.js +70 -0
  13. package/dist/code-actions.d.ts +3 -1
  14. package/dist/code-actions.js +50 -10
  15. package/dist/code-vision.js +2 -3
  16. package/dist/completion.d.ts +28 -0
  17. package/dist/completion.js +83 -27
  18. package/dist/context-menu-rows.d.ts +1 -1
  19. package/dist/context-menu-rows.js +4 -0
  20. package/dist/definition-link.js +15 -5
  21. package/dist/document-colors.d.ts +24 -0
  22. package/dist/document-colors.js +194 -0
  23. package/dist/document-links.d.ts +22 -0
  24. package/dist/document-links.js +133 -0
  25. package/dist/document-query.d.ts +15 -0
  26. package/dist/document-query.js +54 -0
  27. package/dist/edit-locations.d.ts +20 -0
  28. package/dist/edit-locations.js +136 -0
  29. package/dist/editor-language.d.ts +23 -1
  30. package/dist/editor-language.js +83 -2
  31. package/dist/emmet.d.ts +13 -0
  32. package/dist/emmet.js +62 -0
  33. package/dist/folding.js +2 -3
  34. package/dist/format-on-type.js +3 -5
  35. package/dist/highlights.js +2 -3
  36. package/dist/history.d.ts +7 -0
  37. package/dist/history.js +79 -1
  38. package/dist/host-types.d.ts +10 -0
  39. package/dist/index.d.ts +13 -2
  40. package/dist/index.js +10 -0
  41. package/dist/inlay-hints.js +2 -2
  42. package/dist/inline-completion.d.ts +39 -0
  43. package/dist/inline-completion.js +221 -0
  44. package/dist/key-priority.d.ts +9 -5
  45. package/dist/key-priority.js +11 -6
  46. package/dist/linked-editing.d.ts +26 -0
  47. package/dist/linked-editing.js +215 -0
  48. package/dist/live-templates.d.ts +16 -0
  49. package/dist/live-templates.js +289 -0
  50. package/dist/locales/en.json +61 -2
  51. package/dist/locales/nl.json +61 -2
  52. package/dist/markup-context.d.ts +55 -0
  53. package/dist/markup-context.js +408 -0
  54. package/dist/markup.d.ts +39 -0
  55. package/dist/markup.js +465 -0
  56. package/dist/navigation.js +4 -6
  57. package/dist/paste-history.d.ts +7 -0
  58. package/dist/paste-history.js +104 -0
  59. package/dist/peek.js +3 -4
  60. package/dist/pick.d.ts +21 -2
  61. package/dist/pick.js +152 -19
  62. package/dist/popups.d.ts +10 -0
  63. package/dist/popups.js +2 -1
  64. package/dist/postfix.d.ts +21 -0
  65. package/dist/postfix.js +212 -0
  66. package/dist/project-language.d.ts +20 -1
  67. package/dist/project-language.js +132 -18
  68. package/dist/rename.js +8 -11
  69. package/dist/rendered-docs.js +1 -2
  70. package/dist/selection-ranges.js +2 -3
  71. package/dist/shortcut-keys.d.ts +24 -0
  72. package/dist/signature.js +3 -6
  73. package/dist/snippet-insert.d.ts +10 -0
  74. package/dist/snippet-insert.js +217 -0
  75. package/dist/snippet-session.d.ts +2 -2
  76. package/dist/snippet-session.js +3 -3
  77. package/dist/snippet.d.ts +7 -1
  78. package/dist/snippet.js +65 -8
  79. package/dist/surround-constructs.d.ts +10 -0
  80. package/dist/surround-constructs.js +100 -0
  81. package/dist/surround.d.ts +18 -0
  82. package/dist/surround.js +399 -0
  83. package/dist/symbol-picker.js +4 -6
  84. package/dist/symbols.js +22 -3
  85. package/dist/template-builtins.d.ts +3 -0
  86. package/dist/template-builtins.js +46 -0
  87. package/dist/template-context.d.ts +12 -0
  88. package/dist/template-context.js +56 -0
  89. package/dist/templates.d.ts +59 -0
  90. package/dist/templates.js +103 -0
  91. package/dist/testing.d.ts +23 -1
  92. package/dist/testing.js +114 -0
  93. package/package.json +7 -6
  94. package/src/CallHierarchyPanel.tsx +26 -11
  95. package/src/EditorContextMenu.tsx +7 -0
  96. package/src/LanguagePopups.tsx +4 -0
  97. package/src/PickPopup.tsx +47 -5
  98. package/src/WrapCard.tsx +64 -0
  99. package/src/call-hierarchy-model.ts +25 -3
  100. package/src/call-hierarchy.ts +62 -20
  101. package/src/clipboard-history.ts +102 -0
  102. package/src/code-actions.ts +48 -11
  103. package/src/code-vision.ts +3 -3
  104. package/src/completion.ts +123 -25
  105. package/src/context-menu-rows.ts +3 -2
  106. package/src/definition-link.ts +17 -5
  107. package/src/document-colors.ts +189 -0
  108. package/src/document-links.ts +129 -0
  109. package/src/document-query.ts +71 -0
  110. package/src/edit-locations.ts +162 -0
  111. package/src/editor-language.ts +86 -3
  112. package/src/emmet-module.d.ts +44 -0
  113. package/src/emmet.ts +73 -0
  114. package/src/folding.ts +3 -3
  115. package/src/format-on-type.ts +5 -5
  116. package/src/highlights.ts +3 -3
  117. package/src/history.ts +81 -1
  118. package/src/host-types.ts +17 -0
  119. package/src/index.ts +28 -3
  120. package/src/inlay-hints.ts +2 -2
  121. package/src/inline-completion.ts +221 -0
  122. package/src/key-priority.ts +11 -6
  123. package/src/linked-editing.ts +199 -0
  124. package/src/live-templates.ts +315 -0
  125. package/src/locales/en.json +61 -2
  126. package/src/locales/nl.json +61 -2
  127. package/src/markup-context.ts +387 -0
  128. package/src/markup.ts +377 -0
  129. package/src/navigation.ts +6 -6
  130. package/src/paste-history.ts +111 -0
  131. package/src/peek.ts +4 -4
  132. package/src/pick.ts +218 -20
  133. package/src/popups.ts +21 -1
  134. package/src/postfix.ts +224 -0
  135. package/src/project-language.ts +139 -19
  136. package/src/rename.ts +11 -11
  137. package/src/rendered-docs.ts +2 -2
  138. package/src/selection-ranges.ts +3 -3
  139. package/src/signature.ts +6 -6
  140. package/src/snippet-insert.ts +258 -0
  141. package/src/snippet-session.ts +9 -4
  142. package/src/snippet.ts +82 -7
  143. package/src/surround-constructs.ts +85 -0
  144. package/src/surround.ts +430 -0
  145. package/src/symbol-picker.ts +6 -6
  146. package/src/symbols.ts +30 -4
  147. package/src/template-builtins.ts +94 -0
  148. package/src/template-context.ts +65 -0
  149. package/src/templates.ts +197 -0
  150. package/src/testing.ts +126 -1
@@ -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
- if (isShortcut(this.language.shortcuts.callHierarchy, event)) {
62
- if (this.isOpen) {
63
- this.setDirection(this.direction === 'incoming' ? 'outgoing' : 'incoming');
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 { project, uri } = this.language;
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
- /* Opens the tree for the symbol at the position, on its callers unless told otherwise. */
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, project, uri } = this.language;
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
- items = await project.service.prepareCallHierarchy!(uri, position, { signal: this.controller.signal });
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 { service, i18n } = this.language.project;
335
- const { uri, editor } = this.language;
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 calls =
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
+ }
@@ -13,7 +13,7 @@ import {
13
13
  type ActionEntry,
14
14
  type ActionGroup
15
15
  } from './code-actions-model.ts';
16
- import type { Problem } from './diagnostics-model.ts';
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.project.service.supports(METHOD, this.language.uri);
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, project, uri } = this.language;
165
+ const { editor, uri } = this.language;
166
166
 
167
- if (!project.service.supports('textDocument/formatting', uri)) {
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 project.service.formatting(uri, { ...editor.getIndentation() });
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 { project, uri, diagnostics } = this.language;
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 project.service.codeActions(uri, range, context, { signal }), order);
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 { project, uri } = this.language;
369
+ const { uri } = this.language;
333
370
  const { action } = entry;
334
371
  let result = action;
335
372
 
336
- if (action.edit === undefined && project.service.providerOptions(METHOD, uri)?.resolveProvider === true) {
373
+ if (action.edit === undefined && this.language.service.providerOptions(METHOD, uri)?.resolveProvider === true) {
337
374
  try {
338
- result = await project.service.resolveCodeAction(uri, action, { signal });
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 project.service.executeCommand(uri, action.command);
467
+ await this.language.service.executeCommand(uri, action.command);
431
468
  }
432
469
  } catch (error) {
433
470
  this.fail(error);
@@ -149,7 +149,7 @@ export class CodeVisionFeature {
149
149
  }
150
150
 
151
151
  private get canCount(): boolean {
152
- return this.settings.usages && this.language.project.service.supports(REFERENCES, this.language.uri);
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 { project, uri } = this.language;
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 project.service.references(uri, declaration.position, false, { signal: controller.signal, parallel: true });
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 });