@theia/core 1.64.0-next.28 → 1.64.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 (95) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +59 -9
  3. package/i18n/nls.de.json +59 -9
  4. package/i18n/nls.es.json +59 -9
  5. package/i18n/nls.fr.json +59 -9
  6. package/i18n/nls.hu.json +59 -9
  7. package/i18n/nls.it.json +59 -9
  8. package/i18n/nls.ja.json +59 -9
  9. package/i18n/nls.json +63 -13
  10. package/i18n/nls.ko.json +59 -9
  11. package/i18n/nls.pl.json +59 -9
  12. package/i18n/nls.pt-br.json +59 -9
  13. package/i18n/nls.ru.json +59 -9
  14. package/i18n/nls.tr.json +59 -9
  15. package/i18n/nls.zh-cn.json +59 -9
  16. package/i18n/nls.zh-tw.json +59 -9
  17. package/lib/browser/catalog.json +149 -15
  18. package/lib/browser/context-key-service.d.ts +4 -0
  19. package/lib/browser/context-key-service.d.ts.map +1 -1
  20. package/lib/browser/context-key-service.js.map +1 -1
  21. package/lib/browser/frontend-application-module.js +1 -1
  22. package/lib/browser/frontend-application-module.js.map +1 -1
  23. package/lib/browser/menu/browser-menu-plugin.d.ts +1 -1
  24. package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
  25. package/lib/browser/menu/browser-menu-plugin.js +2 -2
  26. package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
  27. package/lib/browser/preload/i18n-preload-contribution.js +1 -1
  28. package/lib/browser/preload/i18n-preload-contribution.js.map +1 -1
  29. package/lib/browser/shell/application-shell.d.ts +1 -1
  30. package/lib/browser/shell/application-shell.d.ts.map +1 -1
  31. package/lib/browser/shell/application-shell.js.map +1 -1
  32. package/lib/common/array-utils.d.ts +4 -0
  33. package/lib/common/array-utils.d.ts.map +1 -1
  34. package/lib/common/array-utils.js +47 -0
  35. package/lib/common/array-utils.js.map +1 -1
  36. package/lib/common/diff.d.ts +33 -0
  37. package/lib/common/diff.d.ts.map +1 -0
  38. package/lib/common/diff.js +20 -0
  39. package/lib/common/diff.js.map +1 -0
  40. package/lib/common/message-rpc/msg-pack-extension-manager.js +2 -2
  41. package/lib/common/message-rpc/msg-pack-extension-manager.js.map +1 -1
  42. package/lib/common/observable/autorun.d.ts +81 -0
  43. package/lib/common/observable/autorun.d.ts.map +1 -0
  44. package/lib/common/observable/autorun.js +194 -0
  45. package/lib/common/observable/autorun.js.map +1 -0
  46. package/lib/common/observable/derived-observable.d.ts +71 -0
  47. package/lib/common/observable/derived-observable.d.ts.map +1 -0
  48. package/lib/common/observable/derived-observable.js +258 -0
  49. package/lib/common/observable/derived-observable.js.map +1 -0
  50. package/lib/common/observable/index.d.ts +8 -0
  51. package/lib/common/observable/index.d.ts.map +1 -0
  52. package/lib/common/observable/index.js +26 -0
  53. package/lib/common/observable/index.js.map +1 -0
  54. package/lib/common/observable/observable-base.d.ts +181 -0
  55. package/lib/common/observable/observable-base.d.ts.map +1 -0
  56. package/lib/common/observable/observable-base.js +183 -0
  57. package/lib/common/observable/observable-base.js.map +1 -0
  58. package/lib/common/observable/observable-from-event.d.ts +41 -0
  59. package/lib/common/observable/observable-from-event.d.ts.map +1 -0
  60. package/lib/common/observable/observable-from-event.js +115 -0
  61. package/lib/common/observable/observable-from-event.js.map +1 -0
  62. package/lib/common/observable/observable-signal.d.ts +9 -0
  63. package/lib/common/observable/observable-signal.d.ts.map +1 -0
  64. package/lib/common/observable/observable-signal.js +45 -0
  65. package/lib/common/observable/observable-signal.js.map +1 -0
  66. package/lib/common/observable/observable-utils.d.ts +26 -0
  67. package/lib/common/observable/observable-utils.d.ts.map +1 -0
  68. package/lib/common/observable/observable-utils.js +98 -0
  69. package/lib/common/observable/observable-utils.js.map +1 -0
  70. package/lib/common/observable/observable.spec.d.ts +2 -0
  71. package/lib/common/observable/observable.spec.d.ts.map +1 -0
  72. package/lib/common/observable/observable.spec.js +301 -0
  73. package/lib/common/observable/observable.spec.js.map +1 -0
  74. package/lib/common/observable/settable-observable.d.ts +16 -0
  75. package/lib/common/observable/settable-observable.d.ts.map +1 -0
  76. package/lib/common/observable/settable-observable.js +58 -0
  77. package/lib/common/observable/settable-observable.js.map +1 -0
  78. package/package.json +7 -8
  79. package/src/browser/context-key-service.ts +5 -0
  80. package/src/browser/frontend-application-module.ts +1 -1
  81. package/src/browser/menu/browser-menu-plugin.ts +3 -3
  82. package/src/browser/preload/i18n-preload-contribution.ts +1 -1
  83. package/src/browser/shell/application-shell.ts +1 -1
  84. package/src/common/array-utils.ts +53 -0
  85. package/src/common/diff.ts +56 -0
  86. package/src/common/message-rpc/msg-pack-extension-manager.ts +2 -2
  87. package/src/common/observable/autorun.ts +246 -0
  88. package/src/common/observable/derived-observable.ts +321 -0
  89. package/src/common/observable/index.ts +23 -0
  90. package/src/common/observable/observable-base.ts +324 -0
  91. package/src/common/observable/observable-from-event.ts +148 -0
  92. package/src/common/observable/observable-signal.ts +48 -0
  93. package/src/common/observable/observable-utils.ts +119 -0
  94. package/src/common/observable/observable.spec.ts +342 -0
  95. package/src/common/observable/settable-observable.ts +73 -0
@@ -212,7 +212,7 @@ export class MenuServices {
212
212
  }
213
213
 
214
214
  export interface MenuWidgetFactory {
215
- createMenuWidget(effectiveMenuPath: MenuPath, menu: Submenu, contextMatcher: ContextMatcher, options: BrowserMenuOptions): MenuWidget;
215
+ createMenuWidget(effectiveMenuPath: MenuPath, menu: Submenu, contextMatcher: ContextMatcher, options: BrowserMenuOptions, args?: unknown[]): MenuWidget;
216
216
  }
217
217
 
218
218
  /**
@@ -252,7 +252,7 @@ export class DynamicMenuWidget extends MenuWidget {
252
252
 
253
253
  protected override onBeforeDetach(msg: Message): void {
254
254
  this.node.ownerDocument.removeEventListener('pointerdown', this, true);
255
- super.onAfterDetach(msg);
255
+ super.onBeforeDetach(msg);
256
256
  }
257
257
 
258
258
  override handleEvent(event: Event): void {
@@ -325,7 +325,7 @@ export class DynamicMenuWidget extends MenuWidget {
325
325
  if (node.isVisible(nodePath, contextMatcher, context, ...(this.args || []))) {
326
326
  if (CompoundMenuNode.is(node)) {
327
327
  if (RenderedMenuNode.is(node)) {
328
- const submenu = this.services.menuWidgetFactory.createMenuWidget(nodePath, node, this.contextMatcher, this.options);
328
+ const submenu = this.services.menuWidgetFactory.createMenuWidget(nodePath, node, this.contextMatcher, this.options, this.args);
329
329
  if (submenu.items.length > 0) {
330
330
  result.push({ type: 'submenu', submenu });
331
331
  }
@@ -43,7 +43,7 @@ export class I18nPreloadContribution implements PreloadContribution {
43
43
  const localization = await this.localizationServer.loadLocalization(locale);
44
44
  if (localization.languagePack) {
45
45
  nls.localization = localization;
46
- } else {
46
+ } else if (locale !== nls.defaultLocale) {
47
47
  // In case the localization that we've loaded doesn't localize Theia completely (languagePack is false)
48
48
  // We simply reset the locale to the default again
49
49
  Object.assign(nls, {
@@ -656,7 +656,7 @@ export class ApplicationShell extends Widget {
656
656
  this.additionalDraggedUris = undefined;
657
657
  }
658
658
 
659
- protected static getDraggedEditorUris(dataTransfer: DataTransfer): URI[] {
659
+ static getDraggedEditorUris(dataTransfer: DataTransfer): URI[] {
660
660
  const data = dataTransfer.getData('theia-editor-dnd');
661
661
  return data ? data.split('\n').map(entry => new URI(entry)) : [];
662
662
  }
@@ -151,4 +151,57 @@ export namespace ArrayUtils {
151
151
  }
152
152
  return true;
153
153
  }
154
+
155
+ export function equals<T>(one: ReadonlyArray<T> | undefined, other: ReadonlyArray<T> | undefined, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
156
+ if (one === other) {
157
+ return true;
158
+ }
159
+
160
+ if (!one || !other) {
161
+ return false;
162
+ }
163
+
164
+ if (one.length !== other.length) {
165
+ return false;
166
+ }
167
+
168
+ for (let i = 0, len = one.length; i < len; i++) {
169
+ if (!itemEquals(one[i], other[i])) {
170
+ return false;
171
+ }
172
+ }
173
+
174
+ return true;
175
+ }
176
+
177
+ export function findLast<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
178
+ const idx = findLastIdx(array, predicate);
179
+ if (idx === -1) {
180
+ return undefined;
181
+ }
182
+ return array[idx];
183
+ }
184
+
185
+ export function findLastIdx<T>(array: readonly T[], predicate: (item: T) => boolean, fromIndex = array.length - 1): number {
186
+ for (let i = fromIndex; i >= 0; i--) {
187
+ const element = array[i];
188
+
189
+ if (predicate(element)) {
190
+ return i;
191
+ }
192
+ }
193
+
194
+ return -1;
195
+ }
196
+
197
+ export function checkAdjacentItems<T>(items: readonly T[], predicate: (item1: T, item2: T) => boolean): boolean {
198
+ for (let i = 0; i < items.length - 1; i++) {
199
+ const a = items[i];
200
+ const b = items[i + 1];
201
+ if (!predicate(a, b)) {
202
+ return false;
203
+ }
204
+ }
205
+ return true;
206
+ }
154
207
  }
@@ -0,0 +1,56 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 1C-Soft LLC and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { Range } from 'vscode-languageserver-protocol';
18
+ import { CancellationToken } from './cancellation';
19
+ import URI from './uri';
20
+
21
+ /** Represents a textual diff. */
22
+ export interface Diff {
23
+ readonly changes: readonly DetailedLineRangeMapping[];
24
+ }
25
+
26
+ export interface DetailedLineRangeMapping extends LineRangeMapping {
27
+ readonly innerChanges?: readonly RangeMapping[];
28
+ }
29
+
30
+ export interface LineRangeMapping {
31
+ readonly left: LineRange;
32
+ readonly right: LineRange;
33
+ }
34
+
35
+ /** Represents a range of whole lines of text. */
36
+ export interface LineRange {
37
+ /** A zero-based number of the start line. */
38
+ readonly start: number;
39
+ /** A zero-based number of the end line, exclusive. */
40
+ readonly end: number;
41
+ }
42
+
43
+ export interface RangeMapping {
44
+ readonly left: Range;
45
+ readonly right: Range;
46
+ }
47
+
48
+ export const DiffComputer = Symbol('DiffComputer');
49
+
50
+ export interface DiffComputer {
51
+ computeDiff(left: URI, right: URI, options?: DiffComputerOptions): Promise<Diff | undefined>;
52
+ }
53
+
54
+ export interface DiffComputerOptions {
55
+ readonly cancellationToken?: CancellationToken;
56
+ }
@@ -47,8 +47,8 @@ export class MsgPackExtensionManager {
47
47
  addExtension({
48
48
  Class: extension.class,
49
49
  type: extension.tag,
50
- write: extension.serialize,
51
- read: extension.deserialize
50
+ write: instance => extension.serialize(instance),
51
+ read: serialized => extension.deserialize(serialized)
52
52
  });
53
53
  });
54
54
  }
@@ -0,0 +1,246 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 1C-Soft LLC and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ /*---------------------------------------------------------------------------------------------
17
+ * Copyright (c) Microsoft Corporation. All rights reserved.
18
+ * Licensed under the MIT License. See License.txt in the project root for license information.
19
+ *--------------------------------------------------------------------------------------------*/
20
+ // copied and modified from https://github.com/microsoft/vscode/blob/1.96.3/src/vs/base/common/observableInternal/autorun.ts
21
+
22
+ import { Disposable } from '../disposable';
23
+ import { Observable } from './observable-base';
24
+
25
+ export class Autorun<TChangeSummary = unknown> implements Disposable {
26
+
27
+ protected state = Autorun.State.Stale;
28
+ protected updateCount = 0;
29
+ protected disposed = false;
30
+ protected isRunning = false;
31
+ protected dependencies = new Set<Observable<unknown>>();
32
+ protected dependenciesToBeRemoved?: Set<Observable<unknown>>;
33
+ protected readonly dependencyObserver = this.createDependencyObserver();
34
+ protected readonly createChangeSummary?: () => TChangeSummary;
35
+ protected readonly willHandleChange?: <T, TChange>(context: Observable.ChangeContext<T, TChange>, changeSummary: TChangeSummary | undefined) => boolean;
36
+ protected changeSummary?: TChangeSummary;
37
+
38
+ constructor(
39
+ protected readonly doRun: (args: Autorun.Args<TChangeSummary>) => void,
40
+ options?: Autorun.Options<TChangeSummary>
41
+ ) {
42
+ this.createChangeSummary = options?.createChangeSummary;
43
+ this.willHandleChange = options?.willHandleChange;
44
+ this.changeSummary = this.createChangeSummary?.();
45
+ try {
46
+ this.run(true);
47
+ } catch (e) {
48
+ this.dispose();
49
+ throw e;
50
+ }
51
+ }
52
+
53
+ dispose(): void {
54
+ if (this.disposed) {
55
+ return;
56
+ }
57
+ this.disposed = true;
58
+ for (const dependency of this.dependencies) {
59
+ dependency.removeObserver(this.dependencyObserver);
60
+ }
61
+ this.dependencies.clear();
62
+ }
63
+
64
+ protected run(isFirstRun = false): void {
65
+ if (this.disposed) {
66
+ return;
67
+ }
68
+
69
+ this.dependenciesToBeRemoved = this.dependencies;
70
+ this.dependencies = new Set<Observable<unknown>>();
71
+
72
+ this.state = Autorun.State.UpToDate;
73
+
74
+ try {
75
+ const { changeSummary } = this;
76
+ this.changeSummary = this.createChangeSummary?.();
77
+ this.isRunning = true;
78
+ Observable.Accessor.runWithAccessor(() => this.doRun({ autorun: this, isFirstRun, changeSummary }), dependency => this.watchDependency(dependency));
79
+ } finally {
80
+ this.isRunning = false;
81
+ // We don't want our watched dependencies to think that they are no longer observed, even temporarily.
82
+ // Thus, we only unsubscribe from dependencies that are definitely not watched anymore.
83
+ for (const dependency of this.dependenciesToBeRemoved) {
84
+ dependency.removeObserver(this.dependencyObserver);
85
+ }
86
+ this.dependenciesToBeRemoved = undefined;
87
+ }
88
+ }
89
+
90
+ protected watchDependency<T>(dependency: Observable<T>): T {
91
+ if (!this.isRunning) {
92
+ throw new Error('The accessor may only be called while the autorun is running');
93
+ }
94
+
95
+ // In case the run action disposed the autorun.
96
+ if (this.disposed) {
97
+ return dependency.getUntracked();
98
+ }
99
+
100
+ // Subscribe before getting the value to enable caching.
101
+ dependency.addObserver(this.dependencyObserver);
102
+ // This might call handleChange indirectly, which could invalidate us.
103
+ const value = dependency.getUntracked();
104
+ // Which is why we only add the observable to the dependencies now.
105
+ this.dependencies.add(dependency);
106
+ this.dependenciesToBeRemoved?.delete(dependency);
107
+ return value;
108
+ }
109
+
110
+ protected createDependencyObserver(): Observable.Observer {
111
+ return {
112
+ beginUpdate: () => {
113
+ if (this.state === Autorun.State.UpToDate) {
114
+ this.state = Autorun.State.DependenciesMightHaveChanged;
115
+ }
116
+ this.updateCount++;
117
+ },
118
+
119
+ endUpdate: () => {
120
+ this.updateCount--;
121
+ if (this.updateCount === 0) {
122
+ do {
123
+ if (this.state === Autorun.State.DependenciesMightHaveChanged) {
124
+ this.state = Autorun.State.UpToDate;
125
+ for (const dependency of this.dependencies) {
126
+ dependency.update(); // might call handleChange indirectly, which could make us stale
127
+ if (this.state as Autorun.State === Autorun.State.Stale) {
128
+ // The other dependencies will refresh on demand
129
+ break;
130
+ }
131
+ }
132
+ }
133
+
134
+ if (this.state !== Autorun.State.UpToDate) {
135
+ try {
136
+ this.run();
137
+ } catch (e) {
138
+ console.error(e);
139
+ }
140
+ }
141
+ // In case the run action changed one of our dependencies, we need to run again.
142
+ } while (this.state !== Autorun.State.UpToDate);
143
+ }
144
+ if (this.updateCount < 0) {
145
+ throw new Error('Unexpected update count: ' + this.updateCount);
146
+ }
147
+ },
148
+
149
+ handlePossibleChange: <T>(observable: Observable<T>) => {
150
+ if (this.state === Autorun.State.UpToDate && this.dependencies.has(observable) && !this.dependenciesToBeRemoved?.has(observable)) {
151
+ this.state = Autorun.State.DependenciesMightHaveChanged;
152
+ }
153
+ },
154
+
155
+ handleChange: <T, TChange>(observable: Observable<T, TChange>, change: TChange) => {
156
+ if (this.dependencies.has(observable) && !this.dependenciesToBeRemoved?.has(observable)) {
157
+ let shouldReact = true;
158
+ if (this.willHandleChange) {
159
+ try {
160
+ shouldReact = this.willHandleChange({
161
+ observable,
162
+ change,
163
+ isChangeOf: <U, UChange>(o: Observable<U, UChange>): this is { change: UChange } => o as unknown === observable
164
+ }, this.changeSummary);
165
+ } catch (e) {
166
+ console.error(e);
167
+ }
168
+ }
169
+ if (shouldReact) {
170
+ this.state = Autorun.State.Stale;
171
+ }
172
+ }
173
+ }
174
+ };
175
+ }
176
+ }
177
+
178
+ export namespace Autorun {
179
+
180
+ /**
181
+ * Runs the given {@link run} function immediately, and whenever an update scope ends
182
+ * and an observable tracked as a dependency of the autorun has changed.
183
+ *
184
+ * Note that the run function of the autorun is called within an invocation context where
185
+ * the {@link Observable.Accessor.getCurrent current accessor} is set to track the autorun
186
+ * dependencies, so that any observables accessed with `get()` will automatically be tracked.
187
+ * Occasionally, it might be useful to disable such automatic tracking and track the dependencies
188
+ * manually with `get(accessor)`. This can be done using the {@link Observable.noAutoTracking} function,
189
+ * e.g.
190
+ * ```ts
191
+ * this.toDispose.push(Autorun.create(() => Observable.noAutoTracking(accessor => {
192
+ * const value1 = this.observable1.get(accessor); // the autorun will depend on this observable...
193
+ * const value2 = this.observable2.get(); // ...but not on this observable
194
+ * })));
195
+ * ```
196
+ * In particular, this pattern might be useful when copying existing autorun code from VS Code,
197
+ * where observables can only be tracked manually with `read(reader)`, which corresponds to
198
+ * `get(accessor)` in Theia; calls to `get()` never cause an observable to be tracked. This directly
199
+ * corresponds to disabling automatic tracking in Theia with {@link Observable.noAutoTracking}.
200
+ */
201
+ export function create<TChangeSummary = void>(run: (args: Args<TChangeSummary>) => void, options?: Options<TChangeSummary>): Disposable {
202
+ return new Autorun(run, options);
203
+ }
204
+
205
+ export interface Args<TChangeSummary> {
206
+ readonly autorun: Disposable;
207
+ readonly isFirstRun: boolean;
208
+ /**
209
+ * The change summary with the changes collected from the start of the previous run of the autorun until the start of this run.
210
+ *
211
+ * The change summary is created by {@link Options.createChangeSummary} and
212
+ * the changes are collected by {@link Options.willHandleChange}.
213
+ */
214
+ readonly changeSummary: TChangeSummary | undefined;
215
+ };
216
+
217
+ export interface Options<TChangeSummary> {
218
+ /**
219
+ * Creates a change summary that can collect the changes reported by the observed dependencies to {@link willHandleChange}.
220
+ */
221
+ createChangeSummary?: () => TChangeSummary;
222
+
223
+ /**
224
+ * Handles a change reported by an observed dependency, e.g. by adding it to the {@link changeSummary}.
225
+ * Returns `true` if the reported change should be reacted to, and `false` if it should be ignored.
226
+ */
227
+ willHandleChange?: <T, TChange>(context: Observable.ChangeContext<T, TChange>, changeSummary: TChangeSummary | undefined) => boolean;
228
+ }
229
+
230
+ export const enum State {
231
+ /**
232
+ * Dependencies might have changed. Need to check if at least one dependency has actually changed.
233
+ */
234
+ DependenciesMightHaveChanged,
235
+
236
+ /**
237
+ * A dependency has changed. Need to (re-)run.
238
+ */
239
+ Stale,
240
+
241
+ /**
242
+ * All is up to date.
243
+ */
244
+ UpToDate
245
+ }
246
+ }