@adecore/editor-react 0.39.0 → 0.40.1

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 (154) hide show
  1. package/dist/CallHierarchyPanel.js +30 -55
  2. package/dist/CodeAuthorsCard.js +0 -1
  3. package/dist/CompletionPopup.js +150 -181
  4. package/dist/DiffView.d.ts +1 -1
  5. package/dist/DiffView.js +2 -29
  6. package/dist/PickPopup.js +54 -80
  7. package/dist/SplitDiffView.js +27 -57
  8. package/dist/SymbolPicker.js +2 -8
  9. package/dist/code-actions-model.js +2 -9
  10. package/dist/code-actions.js +10 -11
  11. package/dist/code-vision.js +2 -1
  12. package/dist/completion-model.js +2 -2
  13. package/dist/completion.js +13 -34
  14. package/dist/definition-link.d.ts +1 -0
  15. package/dist/definition-link.js +22 -18
  16. package/dist/diagnostics-model.d.ts +1 -0
  17. package/dist/diagnostics-model.js +3 -1
  18. package/dist/diagnostics.js +1 -2
  19. package/dist/diff-syntax.d.ts +1 -0
  20. package/dist/diff-syntax.js +31 -0
  21. package/dist/doc-comment-model.d.ts +1 -0
  22. package/dist/doc-comment-model.js +1 -1
  23. package/dist/folding.js +2 -3
  24. package/dist/format-on-type.js +6 -10
  25. package/dist/hover-content.d.ts +0 -2
  26. package/dist/hover-content.js +1 -9
  27. package/dist/inlay-hints.d.ts +0 -1
  28. package/dist/inlay-hints.js +11 -41
  29. package/dist/navigation.js +4 -14
  30. package/dist/peek.js +2 -12
  31. package/dist/popup-focus.d.ts +3 -1
  32. package/dist/popup-focus.js +33 -0
  33. package/dist/recent-choices.d.ts +0 -1
  34. package/dist/recent-choices.js +0 -4
  35. package/dist/rendered-docs.d.ts +1 -0
  36. package/dist/rendered-docs.js +15 -28
  37. package/dist/snippet-field-transforms.d.ts +5 -0
  38. package/dist/snippet-field-transforms.js +27 -16
  39. package/dist/snippet-session.js +8 -20
  40. package/dist/symbol-links.js +3 -10
  41. package/dist/symbol-picker-model.d.ts +1 -0
  42. package/dist/symbol-picker-model.js +7 -0
  43. package/dist/unique.d.ts +10 -0
  44. package/dist/unique.js +15 -0
  45. package/package.json +9 -9
  46. package/src/AnchoredPopup.tsx +2 -0
  47. package/src/BaselineStatus.tsx +1 -0
  48. package/src/CallHierarchyPanel.tsx +16 -6
  49. package/src/ChangeReview.tsx +7 -0
  50. package/src/CodeAuthorsCard.tsx +2 -5
  51. package/src/CompletionPopup.tsx +21 -15
  52. package/src/DiffView.tsx +53 -30
  53. package/src/EditorContextMenu.tsx +7 -0
  54. package/src/EditorView.tsx +28 -0
  55. package/src/FindReplace.tsx +8 -0
  56. package/src/HoverCard.tsx +8 -0
  57. package/src/HoverSections.tsx +11 -0
  58. package/src/LanguagePopups.tsx +1 -0
  59. package/src/PanelResizeHandle.tsx +8 -0
  60. package/src/PathText.tsx +1 -0
  61. package/src/PeekPanel.tsx +13 -0
  62. package/src/PickPopup.tsx +7 -6
  63. package/src/RenameCard.tsx +13 -0
  64. package/src/RenderedDocs.tsx +11 -0
  65. package/src/SplitDiffView.tsx +91 -56
  66. package/src/SymbolPicker.tsx +10 -18
  67. package/src/call-hierarchy-model.ts +10 -0
  68. package/src/call-hierarchy.ts +82 -0
  69. package/src/code-actions-model.ts +21 -9
  70. package/src/code-actions.ts +83 -7
  71. package/src/code-authors.ts +20 -0
  72. package/src/code-vision-model.ts +37 -0
  73. package/src/code-vision.ts +47 -3
  74. package/src/completion-call.ts +19 -0
  75. package/src/completion-model.ts +58 -2
  76. package/src/completion.ts +156 -30
  77. package/src/conflict-model.ts +4 -0
  78. package/src/context-menu-rows.ts +1 -0
  79. package/src/context-menu.ts +7 -0
  80. package/src/definition-link.ts +42 -18
  81. package/src/diagnostics-model.ts +19 -1
  82. package/src/diagnostics.ts +31 -2
  83. package/src/diff-expansion.ts +9 -0
  84. package/src/diff-overlays.tsx +8 -0
  85. package/src/diff-syntax.ts +54 -0
  86. package/src/diff-wordmarks.ts +8 -0
  87. package/src/doc-comment-model.ts +51 -1
  88. package/src/editor-language.ts +11 -0
  89. package/src/find-query.ts +7 -0
  90. package/src/folding.ts +10 -3
  91. package/src/format-on-type.ts +23 -10
  92. package/src/highlight-layers.ts +3 -0
  93. package/src/highlights.ts +18 -0
  94. package/src/history.ts +11 -0
  95. package/src/holder.ts +3 -0
  96. package/src/hover-content.ts +34 -17
  97. package/src/hover.ts +57 -0
  98. package/src/index.ts +4 -0
  99. package/src/inlay-hints.ts +86 -47
  100. package/src/key-priority.ts +2 -0
  101. package/src/line-edits.ts +8 -0
  102. package/src/models.ts +6 -0
  103. package/src/navigation-history.ts +5 -0
  104. package/src/navigation.ts +28 -13
  105. package/src/panel-size.ts +7 -0
  106. package/src/patch-decorations.ts +39 -0
  107. package/src/patch-layout.ts +47 -0
  108. package/src/peek-model.ts +21 -0
  109. package/src/peek.ts +49 -13
  110. package/src/pick.ts +35 -0
  111. package/src/popup-focus.ts +11 -1
  112. package/src/popup-placement.ts +5 -0
  113. package/src/popups.ts +2 -6
  114. package/src/project-language.ts +33 -0
  115. package/src/project-problems.ts +11 -0
  116. package/src/proposal-model.ts +40 -0
  117. package/src/recent-choices.ts +3 -5
  118. package/src/refresher.ts +3 -0
  119. package/src/rename-model.ts +28 -0
  120. package/src/rename.ts +56 -0
  121. package/src/rendered-docs.ts +89 -19
  122. package/src/review-group.ts +4 -0
  123. package/src/row-host.ts +12 -0
  124. package/src/selection-ranges.ts +6 -0
  125. package/src/semantic-delta.ts +7 -0
  126. package/src/semantic-model.ts +11 -0
  127. package/src/semantic-tokens.ts +37 -0
  128. package/src/shortcut-keys.ts +3 -0
  129. package/src/signature-model.ts +7 -0
  130. package/src/signature.ts +27 -0
  131. package/src/snippet-field-transforms.ts +48 -13
  132. package/src/snippet-indent.ts +10 -0
  133. package/src/snippet-range-order.ts +5 -0
  134. package/src/snippet-session.ts +173 -31
  135. package/src/snippet-transform-client.ts +14 -0
  136. package/src/snippet-transform-format.ts +98 -0
  137. package/src/snippet-transform-protocol.ts +5 -0
  138. package/src/snippet-transform-queue.ts +53 -0
  139. package/src/snippet-transform-worker.ts +14 -0
  140. package/src/snippet-variables.ts +9 -0
  141. package/src/snippet.ts +107 -0
  142. package/src/split-alignment.ts +10 -0
  143. package/src/split-scroll.ts +8 -0
  144. package/src/symbol-links.ts +9 -12
  145. package/src/symbol-picker-model.ts +25 -0
  146. package/src/symbol-picker.ts +9 -0
  147. package/src/symbols.ts +21 -0
  148. package/src/testing.ts +7 -0
  149. package/src/timers.ts +5 -0
  150. package/src/unique.ts +23 -0
  151. package/src/use-problem-counts.ts +4 -0
  152. package/src/view-state.ts +9 -0
  153. package/src/word-diff.ts +5 -0
  154. package/src/workspace-edit.ts +84 -0
@@ -9,10 +9,12 @@ interface RequestOptions {
9
9
  readonly kind?: 'accept' | 'exit';
10
10
  readonly current?: () => boolean;
11
11
  }
12
+
12
13
  export interface SnippetTransformLease {
13
14
  request(jobs: readonly SnippetTransformJob[], options?: RequestOptions): Promise<readonly string[]>;
14
15
  dispose(): void;
15
16
  }
17
+
16
18
  interface Job {
17
19
  readonly owner: symbol;
18
20
  readonly kind: 'accept' | 'exit';
@@ -21,6 +23,7 @@ interface Job {
21
23
  readonly resolve: (values: readonly string[]) => void;
22
24
  readonly reject: (error: unknown) => void;
23
25
  }
26
+
24
27
  export class SnippetTransformQueueError extends Error {}
25
28
 
26
29
  const IDLE_RELEASE_MS = 1000;
@@ -34,91 +37,121 @@ export class SnippetTransforms {
34
37
  private active: Job | null = null;
35
38
  private idle: unknown;
36
39
  private disposed = false;
40
+
37
41
  constructor(factory: () => WorkerRequestPort, timers: Timers = realTimers) {
38
42
  this.timers = timers;
43
+
39
44
  this.client = createSnippetTransformClient({
40
45
  workerFactory: factory,
41
46
  schedule: (callback, delay) => {
42
47
  const timer = timers.set(callback, delay);
48
+
43
49
  return () => timers.clear(timer);
44
50
  }
45
51
  });
46
52
  }
53
+
47
54
  acquire(): SnippetTransformLease {
48
55
  const owner = Symbol('snippet');
49
56
  this.owners.add(owner);
57
+
50
58
  return {
51
59
  request: (jobs, options = {}) => this.request(owner, jobs, options),
52
60
  dispose: () => this.releaseOwner(owner)
53
61
  };
54
62
  }
63
+
55
64
  private request(owner: symbol, jobs: readonly SnippetTransformJob[], options: RequestOptions): Promise<readonly string[]> {
56
65
  if (this.disposed || !this.owners.has(owner)) {
57
66
  return Promise.reject(new SnippetTransformError('disposed', 'The snippet owner was disposed.'));
58
67
  }
68
+
59
69
  let copied: SnippetTransformJob[];
70
+
60
71
  try {
61
72
  validateSnippetTransformJobs(jobs);
73
+
62
74
  if (jobs.reduce((sum, job) => sum + job.value.length, 0) > MAX_TRANSFORM_WORK) {
63
75
  throw new RangeError('The snippet transform inputs exceed the work budget.');
64
76
  }
77
+
65
78
  copied = jobs.map((job) => ({ ...job, format: job.format.map((node) => ({ ...node })) }));
66
79
  } catch (error) {
67
80
  return Promise.reject(
68
81
  new SnippetTransformError(error instanceof RangeError ? 'range' : 'syntax', error instanceof Error ? error.message : String(error))
69
82
  );
70
83
  }
84
+
71
85
  if (copied.length === 0) {
72
86
  return Promise.resolve([]);
73
87
  }
88
+
74
89
  this.pending = this.pending.filter((job) => {
75
90
  if (job.current()) {
76
91
  return true;
77
92
  }
93
+
78
94
  job.reject(new SnippetTransformError('superseded', 'The queued snippet changed.'));
95
+
79
96
  return false;
80
97
  });
98
+
81
99
  const kind = options.kind ?? 'accept';
100
+
82
101
  if (kind === 'accept') {
83
102
  this.pending = this.pending.filter((job) => {
84
103
  if (job.owner !== owner || job.kind !== 'accept') {
85
104
  return true;
86
105
  }
106
+
87
107
  job.reject(new SnippetTransformError('superseded', 'A newer snippet accept replaced the queued one.'));
108
+
88
109
  return false;
89
110
  });
90
111
  }
112
+
91
113
  if (this.pending.length >= MAX_PENDING) {
92
114
  return Promise.reject(new SnippetTransformQueueError('Too many queued snippet transforms.'));
93
115
  }
116
+
94
117
  this.timers.clear(this.idle);
118
+
95
119
  return new Promise((resolve, reject) => {
96
120
  this.pending.push({ owner, kind, jobs: copied, current: () => this.owners.has(owner) && (options.current?.() ?? true), resolve, reject });
97
121
  queueMicrotask(() => this.pump());
98
122
  });
99
123
  }
124
+
100
125
  private pump(): void {
101
126
  if (this.disposed || this.active !== null) {
102
127
  return;
103
128
  }
129
+
104
130
  const job = this.pending.shift();
131
+
105
132
  if (job === undefined) {
106
133
  this.timers.clear(this.idle);
107
134
  this.idle = this.timers.set(() => this.client.release(), IDLE_RELEASE_MS);
135
+
108
136
  return;
109
137
  }
138
+
110
139
  if (!job.current()) {
111
140
  job.reject(new SnippetTransformError('superseded', 'The queued snippet changed.'));
112
141
  this.pump();
142
+
113
143
  return;
114
144
  }
145
+
115
146
  this.active = job;
147
+
116
148
  void this.client
117
149
  .transform(job.jobs)
118
150
  .then((values) => {
119
151
  if (!job.current()) {
120
152
  throw new SnippetTransformError('superseded', 'The snippet changed while transforming.');
121
153
  }
154
+
122
155
  job.resolve(values);
123
156
  })
124
157
  .catch((error) => job.reject(error))
@@ -127,29 +160,37 @@ export class SnippetTransforms {
127
160
  this.pump();
128
161
  });
129
162
  }
163
+
130
164
  private releaseOwner(owner: symbol): void {
131
165
  if (!this.owners.delete(owner)) {
132
166
  return;
133
167
  }
168
+
134
169
  this.pending = this.pending.filter((job) => {
135
170
  if (job.owner !== owner) {
136
171
  return true;
137
172
  }
173
+
138
174
  job.reject(new SnippetTransformError('disposed', 'The snippet owner was disposed.'));
175
+
139
176
  return false;
140
177
  });
178
+
141
179
  if (this.active?.owner === owner) {
142
180
  this.active.reject(new SnippetTransformError('disposed', 'The snippet owner was disposed.'));
143
181
  this.client.cancel();
144
182
  }
183
+
145
184
  if (this.owners.size === 0) {
146
185
  this.dispose();
147
186
  }
148
187
  }
188
+
149
189
  dispose(): void {
150
190
  if (this.disposed) {
151
191
  return;
152
192
  }
193
+
153
194
  this.disposed = true;
154
195
  this.timers.clear(this.idle);
155
196
  this.owners.clear();
@@ -160,39 +201,51 @@ export class SnippetTransforms {
160
201
  this.client.dispose();
161
202
  }
162
203
  }
204
+
163
205
  interface Entry {
164
206
  readonly queue: SnippetTransforms;
165
207
  references: number;
166
208
  }
209
+
167
210
  const projects = new WeakMap<ProjectLanguage, Entry>();
211
+
168
212
  export function acquireSnippetTransforms(project: ProjectLanguage, timers: Timers): SnippetTransformLease | null {
169
213
  const factory = project.host.snippetTransformWorker;
214
+
170
215
  if (factory === undefined) {
171
216
  return null;
172
217
  }
218
+
173
219
  let entry = projects.get(project);
220
+
174
221
  if (entry === undefined) {
175
222
  entry = { queue: new SnippetTransforms(factory, timers), references: 0 };
176
223
  projects.set(project, entry);
177
224
  }
225
+
178
226
  const held = entry,
179
227
  lease = held.queue.acquire();
228
+
180
229
  held.references++;
181
230
  let disposed = false;
231
+
182
232
  return {
183
233
  request: (jobs, options) => lease.request(jobs, options),
184
234
  dispose: () => {
185
235
  if (disposed) {
186
236
  return;
187
237
  }
238
+
188
239
  disposed = true;
189
240
  lease.dispose();
241
+
190
242
  if (--held.references === 0 && projects.get(project) === held) {
191
243
  projects.delete(project);
192
244
  }
193
245
  }
194
246
  };
195
247
  }
248
+
196
249
  export function disposeSnippetTransforms(project: ProjectLanguage): void {
197
250
  projects.get(project)?.queue.dispose();
198
251
  projects.delete(project);
@@ -1,5 +1,6 @@
1
1
  import { applySnippetTransform, createSnippetTransformBudget, validateSnippetTransformJobs } from './snippet-transform-format.ts';
2
2
  import { MAX_TRANSFORM_CHARACTERS, type SnippetTransformInput, type SnippetTransformOutput } from './snippet-transform-protocol.ts';
3
+
3
4
  export {
4
5
  createSnippetTransformClient,
5
6
  SnippetTransformError,
@@ -7,7 +8,9 @@ export {
7
8
  type SnippetTransformClientOptions,
8
9
  type SnippetTransformErrorKind
9
10
  } from './snippet-transform-client.ts';
11
+
10
12
  export { compileSnippetTransformFormat } from './snippet-transform-format.ts';
13
+
11
14
  export type {
12
15
  SnippetTransformJob,
13
16
  SnippetTransformInput,
@@ -15,33 +18,42 @@ export type {
15
18
  SnippetTransformCase,
16
19
  SnippetTransformFormatNode
17
20
  } from './snippet-transform-protocol.ts';
21
+
18
22
  export interface SnippetTransformWorkerEndpoint {
19
23
  addEventListener(type: 'message', listener: (event: MessageEvent<SnippetTransformInput>) => void): void;
20
24
  removeEventListener(type: 'message', listener: (event: MessageEvent<SnippetTransformInput>) => void): void;
21
25
  postMessage(message: SnippetTransformOutput): void;
22
26
  }
27
+
23
28
  export function serveSnippetTransforms(endpoint: SnippetTransformWorkerEndpoint): () => void {
24
29
  const receive = ({ data: request }: MessageEvent<SnippetTransformInput>): void => {
25
30
  const id = request !== null && typeof request === 'object' && Number.isSafeInteger(request.id) && request.id > 0 ? request.id : 0;
31
+
26
32
  try {
27
33
  if (id === 0 || request.type !== 'transform') {
28
34
  throw new RangeError('Invalid snippet transform request.');
29
35
  }
36
+
30
37
  validateSnippetTransformJobs(request.jobs);
31
38
  let remaining = MAX_TRANSFORM_CHARACTERS;
32
39
  const budget = createSnippetTransformBudget();
33
40
  const patterns = new Map<string, RegExp>();
41
+
34
42
  const values = request.jobs.map((job) => {
35
43
  const key = job.flags + '\0' + job.pattern;
36
44
  let expression = patterns.get(key);
45
+
37
46
  if (expression === undefined) {
38
47
  expression = new RegExp(job.pattern, job.flags);
39
48
  patterns.set(key, expression);
40
49
  }
50
+
41
51
  const value = applySnippetTransform(job, remaining, expression, budget);
42
52
  remaining -= value.length;
53
+
43
54
  return value;
44
55
  });
56
+
45
57
  endpoint.postMessage({ type: 'transformed', id: request.id, values });
46
58
  } catch (error) {
47
59
  endpoint.postMessage({
@@ -52,7 +64,9 @@ export function serveSnippetTransforms(endpoint: SnippetTransformWorkerEndpoint)
52
64
  });
53
65
  }
54
66
  };
67
+
55
68
  endpoint.addEventListener('message', receive);
56
69
  endpoint.postMessage({ type: 'ready' });
70
+
57
71
  return () => endpoint.removeEventListener('message', receive);
58
72
  }
@@ -15,8 +15,11 @@ export function createSnippetResolver(
15
15
  const filename = path?.replace(/\\/g, '/').split('/').at(-1);
16
16
  const folder = context.folder?.replace(/\\/g, '/').replace(/\/$/, '');
17
17
  const normalized = path?.replace(/\\/g, '/');
18
+
18
19
  const pad = (value: number): string => String(value).padStart(2, '0');
20
+
19
21
  const timezone = -now.getTimezoneOffset();
22
+
20
23
  const values: Record<string, string | undefined> = {
21
24
  TM_SELECTED_TEXT: context.selectedText,
22
25
  TM_CURRENT_LINE: context.currentLine,
@@ -46,16 +49,20 @@ export function createSnippetResolver(
46
49
  CURRENT_SECONDS_UNIX: String(Math.floor(now.getTime() / 1000)),
47
50
  CURRENT_TIMEZONE_OFFSET: (timezone < 0 ? '-' : '+') + pad(Math.floor(Math.abs(timezone) / 60)) + pad(Math.abs(timezone) % 60)
48
51
  };
52
+
49
53
  const builtins = new Map(Object.entries(values));
50
54
  const cache = new Map<string, string | undefined>();
55
+
51
56
  return (name) => {
52
57
  if (!cache.has(name)) {
53
58
  let supplied: string | undefined;
59
+
54
60
  try {
55
61
  supplied = custom?.(name, context);
56
62
  } catch {
57
63
  // A failed host override leaves the built-in or editable variable available.
58
64
  }
65
+
59
66
  const value =
60
67
  supplied ??
61
68
  (name === 'RANDOM'
@@ -67,8 +74,10 @@ export function createSnippetResolver(
67
74
  : name === 'UUID'
68
75
  ? (sources.uuid?.() ?? globalThis.crypto?.randomUUID())
69
76
  : builtins.get(name));
77
+
70
78
  cache.set(name, value);
71
79
  }
80
+
72
81
  return cache.get(name);
73
82
  };
74
83
  }