@theia/plugin-ext 1.34.1 → 1.35.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 (110) hide show
  1. package/lib/common/plugin-api-rpc-model.d.ts +18 -1
  2. package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
  3. package/lib/common/plugin-api-rpc-model.js.map +1 -1
  4. package/lib/common/plugin-api-rpc.d.ts +10 -5
  5. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  6. package/lib/common/plugin-api-rpc.js.map +1 -1
  7. package/lib/common/plugin-protocol.d.ts +30 -0
  8. package/lib/common/plugin-protocol.d.ts.map +1 -1
  9. package/lib/common/plugin-protocol.js.map +1 -1
  10. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  11. package/lib/hosted/browser/hosted-plugin.js +10 -17
  12. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  13. package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
  14. package/lib/hosted/node/plugin-activation-events.d.ts +7 -0
  15. package/lib/hosted/node/plugin-activation-events.d.ts.map +1 -0
  16. package/lib/hosted/node/plugin-activation-events.js +96 -0
  17. package/lib/hosted/node/plugin-activation-events.js.map +1 -0
  18. package/lib/hosted/node/plugin-manifest-loader.d.ts +2 -1
  19. package/lib/hosted/node/plugin-manifest-loader.d.ts.map +1 -1
  20. package/lib/hosted/node/plugin-manifest-loader.js +2 -1
  21. package/lib/hosted/node/plugin-manifest-loader.js.map +1 -1
  22. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  23. package/lib/hosted/node/scanners/scanner-theia.js +27 -36
  24. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  25. package/lib/main/browser/data-transfer/data-transfer-type-converters.d.ts +9 -0
  26. package/lib/main/browser/data-transfer/data-transfer-type-converters.d.ts.map +1 -0
  27. package/lib/main/browser/data-transfer/data-transfer-type-converters.js +65 -0
  28. package/lib/main/browser/data-transfer/data-transfer-type-converters.js.map +1 -0
  29. package/lib/main/browser/dialogs/modal-notification.d.ts.map +1 -1
  30. package/lib/main/browser/dialogs/modal-notification.js +4 -2
  31. package/lib/main/browser/dialogs/modal-notification.js.map +1 -1
  32. package/lib/main/browser/languages-main.d.ts +8 -1
  33. package/lib/main/browser/languages-main.d.ts.map +1 -1
  34. package/lib/main/browser/languages-main.js +26 -2
  35. package/lib/main/browser/languages-main.js.map +1 -1
  36. package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
  37. package/lib/main/browser/plugin-ext-frontend-module.js +3 -0
  38. package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
  39. package/lib/main/browser/text-editors-main.d.ts +2 -2
  40. package/lib/main/browser/text-editors-main.d.ts.map +1 -1
  41. package/lib/main/browser/text-editors-main.js +2 -2
  42. package/lib/main/browser/text-editors-main.js.map +1 -1
  43. package/lib/main/browser/webview/webview-context-keys.d.ts +13 -0
  44. package/lib/main/browser/webview/webview-context-keys.d.ts.map +1 -0
  45. package/lib/main/browser/webview/webview-context-keys.js +64 -0
  46. package/lib/main/browser/webview/webview-context-keys.js.map +1 -0
  47. package/lib/plugin/dialogs.js +2 -2
  48. package/lib/plugin/dialogs.js.map +1 -1
  49. package/lib/plugin/file-system-ext-impl.d.ts +11 -5
  50. package/lib/plugin/file-system-ext-impl.d.ts.map +1 -1
  51. package/lib/plugin/file-system-ext-impl.js +8 -16
  52. package/lib/plugin/file-system-ext-impl.js.map +1 -1
  53. package/lib/plugin/known-commands.d.ts.map +1 -1
  54. package/lib/plugin/known-commands.js +13 -0
  55. package/lib/plugin/known-commands.js.map +1 -1
  56. package/lib/plugin/languages/document-drop-edit.d.ts +16 -0
  57. package/lib/plugin/languages/document-drop-edit.d.ts.map +1 -0
  58. package/lib/plugin/languages/document-drop-edit.js +23 -0
  59. package/lib/plugin/languages/document-drop-edit.js.map +1 -0
  60. package/lib/plugin/languages.d.ts +9 -2
  61. package/lib/plugin/languages.d.ts.map +1 -1
  62. package/lib/plugin/languages.js +27 -1
  63. package/lib/plugin/languages.js.map +1 -1
  64. package/lib/plugin/plugin-context.d.ts.map +1 -1
  65. package/lib/plugin/plugin-context.js +8 -4
  66. package/lib/plugin/plugin-context.js.map +1 -1
  67. package/lib/plugin/preference-registry.d.ts +5 -3
  68. package/lib/plugin/preference-registry.d.ts.map +1 -1
  69. package/lib/plugin/preference-registry.js +31 -42
  70. package/lib/plugin/preference-registry.js.map +1 -1
  71. package/lib/plugin/preference-registry.spec.js +29 -41
  72. package/lib/plugin/preference-registry.spec.js.map +1 -1
  73. package/lib/plugin/text-editors.d.ts +1 -1
  74. package/lib/plugin/text-editors.d.ts.map +1 -1
  75. package/lib/plugin/text-editors.js +2 -2
  76. package/lib/plugin/text-editors.js.map +1 -1
  77. package/lib/plugin/type-converters.d.ts +6 -0
  78. package/lib/plugin/type-converters.d.ts.map +1 -1
  79. package/lib/plugin/type-converters.js +37 -1
  80. package/lib/plugin/type-converters.js.map +1 -1
  81. package/lib/plugin/types-impl.d.ts +5 -0
  82. package/lib/plugin/types-impl.d.ts.map +1 -1
  83. package/lib/plugin/types-impl.js +13 -3
  84. package/lib/plugin/types-impl.js.map +1 -1
  85. package/package.json +27 -27
  86. package/src/common/plugin-api-rpc-model.ts +22 -1
  87. package/src/common/plugin-api-rpc.ts +18 -5
  88. package/src/common/plugin-protocol.ts +32 -4
  89. package/src/hosted/browser/hosted-plugin.ts +9 -16
  90. package/src/hosted/node/hosted-plugin-process.ts +2 -2
  91. package/src/hosted/node/plugin-activation-events.ts +111 -0
  92. package/src/hosted/node/plugin-manifest-loader.ts +4 -3
  93. package/src/hosted/node/scanners/scanner-theia.ts +59 -75
  94. package/src/main/browser/data-transfer/data-transfer-type-converters.ts +70 -0
  95. package/src/main/browser/dialogs/modal-notification.ts +4 -2
  96. package/src/main/browser/languages-main.ts +34 -4
  97. package/src/main/browser/plugin-ext-frontend-module.ts +3 -0
  98. package/src/main/browser/text-editors-main.ts +3 -2
  99. package/src/main/browser/webview/webview-context-keys.ts +49 -0
  100. package/src/plugin/dialogs.ts +2 -2
  101. package/src/plugin/file-system-ext-impl.ts +8 -18
  102. package/src/plugin/known-commands.ts +16 -1
  103. package/src/plugin/languages/document-drop-edit.ts +44 -0
  104. package/src/plugin/languages.ts +41 -3
  105. package/src/plugin/plugin-context.ts +9 -4
  106. package/src/plugin/preference-registry.spec.ts +29 -45
  107. package/src/plugin/preference-registry.ts +33 -45
  108. package/src/plugin/text-editors.ts +2 -2
  109. package/src/plugin/type-converters.ts +37 -0
  110. package/src/plugin/types-impl.ts +11 -0
@@ -126,7 +126,7 @@ export class HostedPluginProcess implements ServerPluginRunner {
126
126
  await waitForTerminated.promise;
127
127
  }
128
128
 
129
- this.killProcessTree(cp.pid);
129
+ this.killProcessTree(cp.pid!);
130
130
  }
131
131
 
132
132
  killProcessTree(parentPid: number): void {
@@ -206,7 +206,7 @@ export class HostedPluginProcess implements ServerPluginRunner {
206
206
  childProcess.stderr!.on('data', data => this.logger.error(`[${options.serverName}: ${childProcess.pid}] ${data.toString().trim()}`));
207
207
 
208
208
  this.logger.debug(`[${options.serverName}: ${childProcess.pid}] IPC started`);
209
- childProcess.once('exit', (code: number, signal: string) => this.onChildProcessExit(options.serverName, childProcess.pid, code, signal));
209
+ childProcess.once('exit', (code: number, signal: string) => this.onChildProcessExit(options.serverName, childProcess.pid!, code, signal));
210
210
  childProcess.on('error', err => this.onChildProcessError(err));
211
211
  return childProcess;
212
212
  }
@@ -0,0 +1,111 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 TypeFox 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 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { flatten } from '../../common/arrays';
18
+ import { isStringArray, isObject } from '@theia/core/lib/common/types';
19
+ import {
20
+ PluginPackage,
21
+ PluginPackageAuthenticationProvider,
22
+ PluginPackageCommand,
23
+ PluginPackageCustomEditor,
24
+ PluginPackageLanguageContribution,
25
+ PluginPackageNotebook,
26
+ PluginPackageView
27
+ } from '../../common/plugin-protocol';
28
+
29
+ /**
30
+ * Most activation events can be automatically deduced from the package manifest.
31
+ * This function will update the manifest based on the plugin contributions.
32
+ */
33
+ export function updateActivationEvents(manifest: PluginPackage): void {
34
+ if (!isObject(manifest) || !isObject(manifest.contributes) || !manifest.contributes) {
35
+ return;
36
+ }
37
+
38
+ const activationEvents = new Set(isStringArray(manifest.activationEvents) ? manifest.activationEvents : []);
39
+
40
+ if (manifest.contributes.commands) {
41
+ const value = manifest.contributes.commands;
42
+ const commands = Array.isArray(value) ? value : [value];
43
+ updateCommandsContributions(commands, activationEvents);
44
+ }
45
+ if (Array.isArray(manifest.contributes.views)) {
46
+ const views = flatten(Object.values(manifest.contributes.views)) as PluginPackageView[];
47
+ updateViewsContribution(views, activationEvents);
48
+ }
49
+ if (Array.isArray(manifest.contributes.customEditors)) {
50
+ updateCustomEditorsContribution(manifest.contributes.customEditors, activationEvents);
51
+ }
52
+ if (Array.isArray(manifest.contributes.authentication)) {
53
+ updateAuthenticationProviderContributions(manifest.contributes.authentication, activationEvents);
54
+ }
55
+ if (Array.isArray(manifest.contributes.languages)) {
56
+ updateLanguageContributions(manifest.contributes.languages, activationEvents);
57
+ }
58
+ if (Array.isArray(manifest.contributes.notebooks)) {
59
+ updateNotebookContributions(manifest.contributes.notebooks, activationEvents);
60
+ }
61
+
62
+ manifest.activationEvents = Array.from(activationEvents);
63
+ }
64
+
65
+ function updateViewsContribution(views: PluginPackageView[], activationEvents: Set<string>): void {
66
+ for (const view of views) {
67
+ if (isObject(view) && typeof view.id === 'string') {
68
+ activationEvents.add(`onView:${view.id}`);
69
+ }
70
+ }
71
+ }
72
+
73
+ function updateCustomEditorsContribution(customEditors: PluginPackageCustomEditor[], activationEvents: Set<string>): void {
74
+ for (const customEditor of customEditors) {
75
+ if (isObject(customEditor) && typeof customEditor.viewType === 'string') {
76
+ activationEvents.add(`onCustomEditor:${customEditor.viewType}`);
77
+ }
78
+ }
79
+ }
80
+
81
+ function updateCommandsContributions(commands: PluginPackageCommand[], activationEvents: Set<string>): void {
82
+ for (const command of commands) {
83
+ if (isObject(command) && typeof command.command === 'string') {
84
+ activationEvents.add(`onCommand:${command.command}`);
85
+ }
86
+ }
87
+ }
88
+
89
+ function updateAuthenticationProviderContributions(authProviders: PluginPackageAuthenticationProvider[], activationEvents: Set<string>): void {
90
+ for (const authProvider of authProviders) {
91
+ if (isObject(authProvider) && typeof authProvider.id === 'string') {
92
+ activationEvents.add(`onAuthenticationRequest:${authProvider.id}`);
93
+ }
94
+ }
95
+ }
96
+
97
+ function updateLanguageContributions(languages: PluginPackageLanguageContribution[], activationEvents: Set<string>): void {
98
+ for (const language of languages) {
99
+ if (isObject(language) && typeof language.id === 'string') {
100
+ activationEvents.add(`onLanguage:${language.id}`);
101
+ }
102
+ }
103
+ }
104
+
105
+ function updateNotebookContributions(notebooks: PluginPackageNotebook[], activationEvents: Set<string>): void {
106
+ for (const notebook of notebooks) {
107
+ if (isObject(notebook) && typeof notebook.type === 'string') {
108
+ activationEvents.add(`onNotebookSerializer:${notebook.type}`);
109
+ }
110
+ }
111
+ }
@@ -16,10 +16,10 @@
16
16
 
17
17
  import * as path from 'path';
18
18
  import * as fs from '@theia/core/shared/fs-extra';
19
- import { PluginIdentifiers } from '../../common';
19
+ import { PluginIdentifiers, PluginPackage } from '../../common';
20
+ import { updateActivationEvents } from './plugin-activation-events';
20
21
 
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- export async function loadManifest(pluginPath: string): Promise<any> {
22
+ export async function loadManifest(pluginPath: string): Promise<PluginPackage> {
23
23
  const manifest = await fs.readJson(path.join(pluginPath, 'package.json'));
24
24
  // translate vscode builtins, as they are published with a prefix. See https://github.com/theia-ide/vscode-builtin-extensions/blob/master/src/republish.js#L50
25
25
  const built_prefix = '@theia/vscode-builtin-';
@@ -27,5 +27,6 @@ export async function loadManifest(pluginPath: string): Promise<any> {
27
27
  manifest.name = manifest.name.substr(built_prefix.length);
28
28
  }
29
29
  manifest.publisher ??= PluginIdentifiers.UNPUBLISHED;
30
+ updateActivationEvents(manifest);
30
31
  return manifest;
31
32
  }
@@ -64,21 +64,15 @@ import {
64
64
  } from '../../../common/plugin-protocol';
65
65
  import * as fs from 'fs';
66
66
  import * as path from 'path';
67
- import { isObject } from 'util';
67
+ import { isObject, isStringArray, RecursivePartial } from '@theia/core/lib/common/types';
68
68
  import { GrammarsReader } from './grammars-reader';
69
69
  import { CharacterPair } from '../../../common/plugin-api-rpc';
70
70
  import * as jsoncparser from 'jsonc-parser';
71
71
  import { IJSONSchema } from '@theia/core/lib/common/json-schema';
72
72
  import { deepClone } from '@theia/core/lib/common/objects';
73
73
  import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema';
74
- import { RecursivePartial } from '@theia/core/lib/common/types';
75
- import {
76
- ProblemMatcherContribution,
77
- ProblemPatternContribution,
78
- TaskDefinition
79
- } from '@theia/task/lib/common/task-protocol';
74
+ import { TaskDefinition } from '@theia/task/lib/common/task-protocol';
80
75
  import { ColorDefinition } from '@theia/core/lib/common/color';
81
- import { ResourceLabelFormatter } from '@theia/core/lib/common/label-protocol';
82
76
  import { PluginUriFactory } from './plugin-uri-factory';
83
77
 
84
78
  namespace nls {
@@ -181,42 +175,42 @@ export class TheiaPluginScanner implements PluginScanner {
181
175
  contributions.configurationDefaults = PreferenceSchemaProperties.is(configurationDefaults) ? configurationDefaults : undefined;
182
176
 
183
177
  try {
184
- if (rawPlugin.contributes!.languages) {
185
- const languages = this.readLanguages(rawPlugin.contributes.languages!, rawPlugin.packagePath);
178
+ if (rawPlugin.contributes.languages) {
179
+ const languages = this.readLanguages(rawPlugin.contributes.languages, rawPlugin.packagePath);
186
180
  contributions.languages = languages;
187
181
  }
188
182
  } catch (err) {
189
- console.error(`Could not read '${rawPlugin.name}' contribution 'languages'.`, rawPlugin.contributes!.languages, err);
183
+ console.error(`Could not read '${rawPlugin.name}' contribution 'languages'.`, rawPlugin.contributes.languages, err);
190
184
  }
191
185
 
192
186
  try {
193
- if (rawPlugin.contributes!.submenus) {
194
- contributions.submenus = this.readSubmenus(rawPlugin.contributes.submenus!, rawPlugin);
187
+ if (rawPlugin.contributes.submenus) {
188
+ contributions.submenus = this.readSubmenus(rawPlugin.contributes.submenus, rawPlugin);
195
189
  }
196
190
  } catch (err) {
197
- console.error(`Could not read '${rawPlugin.name}' contribution 'submenus'.`, rawPlugin.contributes!.submenus, err);
191
+ console.error(`Could not read '${rawPlugin.name}' contribution 'submenus'.`, rawPlugin.contributes.submenus, err);
198
192
  }
199
193
 
200
194
  try {
201
- if (rawPlugin.contributes!.grammars) {
202
- const grammars = this.grammarsReader.readGrammars(rawPlugin.contributes.grammars!, rawPlugin.packagePath);
195
+ if (rawPlugin.contributes.grammars) {
196
+ const grammars = this.grammarsReader.readGrammars(rawPlugin.contributes.grammars, rawPlugin.packagePath);
203
197
  contributions.grammars = grammars;
204
198
  }
205
199
  } catch (err) {
206
- console.error(`Could not read '${rawPlugin.name}' contribution 'grammars'.`, rawPlugin.contributes!.grammars, err);
200
+ console.error(`Could not read '${rawPlugin.name}' contribution 'grammars'.`, rawPlugin.contributes.grammars, err);
207
201
  }
208
202
 
209
203
  try {
210
- if (rawPlugin.contributes?.customEditors) {
211
- const customEditors = this.readCustomEditors(rawPlugin.contributes.customEditors!);
204
+ if (rawPlugin.contributes.customEditors) {
205
+ const customEditors = this.readCustomEditors(rawPlugin.contributes.customEditors);
212
206
  contributions.customEditors = customEditors;
213
207
  }
214
208
  } catch (err) {
215
- console.error(`Could not read '${rawPlugin.name}' contribution 'customEditors'.`, rawPlugin.contributes!.customEditors, err);
209
+ console.error(`Could not read '${rawPlugin.name}' contribution 'customEditors'.`, rawPlugin.contributes.customEditors, err);
216
210
  }
217
211
 
218
212
  try {
219
- if (rawPlugin.contributes && rawPlugin.contributes.viewsContainers) {
213
+ if (rawPlugin.contributes.viewsContainers) {
220
214
  const viewsContainers = rawPlugin.contributes.viewsContainers;
221
215
  contributions.viewsContainers = {};
222
216
 
@@ -231,28 +225,28 @@ export class TheiaPluginScanner implements PluginScanner {
231
225
  }
232
226
  }
233
227
  } catch (err) {
234
- console.error(`Could not read '${rawPlugin.name}' contribution 'viewsContainers'.`, rawPlugin.contributes!.viewsContainers, err);
228
+ console.error(`Could not read '${rawPlugin.name}' contribution 'viewsContainers'.`, rawPlugin.contributes.viewsContainers, err);
235
229
  }
236
230
 
237
231
  try {
238
- if (rawPlugin.contributes!.views) {
232
+ if (rawPlugin.contributes.views) {
239
233
  contributions.views = {};
240
234
 
241
- Object.keys(rawPlugin.contributes.views!).forEach(location => {
242
- const views = this.readViews(rawPlugin.contributes!.views![location]);
243
- contributions.views![location] = views;
244
- });
235
+ for (const location of Object.keys(rawPlugin.contributes.views)) {
236
+ const views = this.readViews(rawPlugin.contributes.views[location]);
237
+ contributions.views[location] = views;
238
+ }
245
239
  }
246
240
  } catch (err) {
247
- console.error(`Could not read '${rawPlugin.name}' contribution 'views'.`, rawPlugin.contributes!.views, err);
241
+ console.error(`Could not read '${rawPlugin.name}' contribution 'views'.`, rawPlugin.contributes.views, err);
248
242
  }
249
243
 
250
244
  try {
251
- if (rawPlugin.contributes!.viewsWelcome) {
252
- contributions.viewsWelcome = this.readViewsWelcome(rawPlugin.contributes!.viewsWelcome, rawPlugin.contributes!.views);
245
+ if (rawPlugin.contributes.viewsWelcome) {
246
+ contributions.viewsWelcome = this.readViewsWelcome(rawPlugin.contributes!.viewsWelcome, rawPlugin.contributes.views);
253
247
  }
254
248
  } catch (err) {
255
- console.error(`Could not read '${rawPlugin.name}' contribution 'viewsWelcome'.`, rawPlugin.contributes!.viewsWelcome, err);
249
+ console.error(`Could not read '${rawPlugin.name}' contribution 'viewsWelcome'.`, rawPlugin.contributes.viewsWelcome, err);
256
250
  }
257
251
 
258
252
  try {
@@ -266,67 +260,73 @@ export class TheiaPluginScanner implements PluginScanner {
266
260
  }
267
261
 
268
262
  try {
269
- if (rawPlugin.contributes!.menus) {
263
+ if (rawPlugin.contributes.menus) {
270
264
  contributions.menus = {};
271
265
 
272
- Object.keys(rawPlugin.contributes.menus!).forEach(location => {
273
- const menus = this.readMenus(rawPlugin.contributes!.menus![location]);
274
- contributions.menus![location] = menus;
275
- });
266
+ for (const location of Object.keys(rawPlugin.contributes.menus)) {
267
+ const menus = this.readMenus(rawPlugin.contributes.menus[location]);
268
+ contributions.menus[location] = menus;
269
+ }
276
270
  }
277
271
  } catch (err) {
278
- console.error(`Could not read '${rawPlugin.name}' contribution 'menus'.`, rawPlugin.contributes!.menus, err);
272
+ console.error(`Could not read '${rawPlugin.name}' contribution 'menus'.`, rawPlugin.contributes.menus, err);
279
273
  }
280
274
 
281
275
  try {
282
- if (rawPlugin.contributes! && rawPlugin.contributes.keybindings) {
276
+ if (rawPlugin.contributes.keybindings) {
283
277
  const rawKeybindings = Array.isArray(rawPlugin.contributes.keybindings) ? rawPlugin.contributes.keybindings : [rawPlugin.contributes.keybindings];
284
278
  contributions.keybindings = rawKeybindings.map(rawKeybinding => this.readKeybinding(rawKeybinding));
285
279
  }
286
280
  } catch (err) {
287
- console.error(`Could not read '${rawPlugin.name}' contribution 'keybindings'.`, rawPlugin.contributes!.keybindings, err);
281
+ console.error(`Could not read '${rawPlugin.name}' contribution 'keybindings'.`, rawPlugin.contributes.keybindings, err);
288
282
  }
289
283
 
290
284
  try {
291
- if (rawPlugin.contributes!.debuggers) {
292
- const debuggers = this.readDebuggers(rawPlugin.contributes.debuggers!);
285
+ if (rawPlugin.contributes.debuggers) {
286
+ const debuggers = this.readDebuggers(rawPlugin.contributes.debuggers);
293
287
  contributions.debuggers = debuggers;
294
288
  }
295
289
  } catch (err) {
296
- console.error(`Could not read '${rawPlugin.name}' contribution 'debuggers'.`, rawPlugin.contributes!.debuggers, err);
290
+ console.error(`Could not read '${rawPlugin.name}' contribution 'debuggers'.`, rawPlugin.contributes.debuggers, err);
297
291
  }
298
292
 
299
293
  try {
300
- if (rawPlugin.contributes!.taskDefinitions) {
301
- const definitions = rawPlugin.contributes!.taskDefinitions!;
294
+ if (rawPlugin.contributes.taskDefinitions) {
295
+ const definitions = rawPlugin.contributes.taskDefinitions!;
302
296
  contributions.taskDefinitions = definitions.map(definitionContribution => this.readTaskDefinition(rawPlugin.name, definitionContribution));
303
297
  }
304
298
  } catch (err) {
305
- console.error(`Could not read '${rawPlugin.name}' contribution 'taskDefinitions'.`, rawPlugin.contributes!.taskDefinitions, err);
299
+ console.error(`Could not read '${rawPlugin.name}' contribution 'taskDefinitions'.`, rawPlugin.contributes.taskDefinitions, err);
306
300
  }
307
301
 
308
302
  try {
309
- if (rawPlugin.contributes!.problemMatchers) {
310
- contributions.problemMatchers = rawPlugin.contributes!.problemMatchers as ProblemMatcherContribution[];
311
- }
303
+ contributions.problemMatchers = rawPlugin.contributes.problemMatchers;
312
304
  } catch (err) {
313
- console.error(`Could not read '${rawPlugin.name}' contribution 'problemMatchers'.`, rawPlugin.contributes!.problemMatchers, err);
305
+ console.error(`Could not read '${rawPlugin.name}' contribution 'problemMatchers'.`, rawPlugin.contributes.problemMatchers, err);
314
306
  }
315
307
 
316
308
  try {
317
- if (rawPlugin.contributes!.problemPatterns) {
318
- contributions.problemPatterns = rawPlugin.contributes!.problemPatterns as ProblemPatternContribution[];
319
- }
309
+ contributions.problemPatterns = rawPlugin.contributes.problemPatterns;
320
310
  } catch (err) {
321
- console.error(`Could not read '${rawPlugin.name}' contribution 'problemPatterns'.`, rawPlugin.contributes!.problemPatterns, err);
311
+ console.error(`Could not read '${rawPlugin.name}' contribution 'problemPatterns'.`, rawPlugin.contributes.problemPatterns, err);
322
312
  }
323
313
 
324
314
  try {
325
- if (rawPlugin.contributes!.resourceLabelFormatters) {
326
- contributions.resourceLabelFormatters = rawPlugin.contributes!.resourceLabelFormatters as ResourceLabelFormatter[];
327
- }
315
+ contributions.resourceLabelFormatters = rawPlugin.contributes.resourceLabelFormatters;
316
+ } catch (err) {
317
+ console.error(`Could not read '${rawPlugin.name}' contribution 'resourceLabelFormatters'.`, rawPlugin.contributes.resourceLabelFormatters, err);
318
+ }
319
+
320
+ try {
321
+ contributions.authentication = rawPlugin.contributes.authentication;
322
+ } catch (err) {
323
+ console.error(`Could not read '${rawPlugin.name}' contribution 'authentication'.`, rawPlugin.contributes.authentication, err);
324
+ }
325
+
326
+ try {
327
+ contributions.notebooks = rawPlugin.contributes.notebooks;
328
328
  } catch (err) {
329
- console.error(`Could not read '${rawPlugin.name}' contribution 'resourceLabelFormatters'.`, rawPlugin.contributes!.resourceLabelFormatters, err);
329
+ console.error(`Could not read '${rawPlugin.name}' contribution 'notebooks'.`, rawPlugin.contributes.authentication, err);
330
330
  }
331
331
 
332
332
  try {
@@ -837,7 +837,6 @@ export class TheiaPluginScanner implements PluginScanner {
837
837
  }
838
838
 
839
839
  let result: AutoClosingPairConditional[] | undefined = undefined;
840
- // tslint:disable-next-line:one-variable-per-declaration
841
840
  for (let i = 0, len = source.length; i < len; i++) {
842
841
  const pair = source[i];
843
842
  if (Array.isArray(pair)) {
@@ -861,7 +860,7 @@ export class TheiaPluginScanner implements PluginScanner {
861
860
  continue;
862
861
  }
863
862
  if (typeof pair.notIn !== 'undefined') {
864
- if (!isStringArr(pair.notIn)) {
863
+ if (!isStringArray(pair.notIn)) {
865
864
  console.warn(`[${langId}]: language configuration: expected \`autoClosingPairs[${i}].notIn\` to be a string array.`);
866
865
  continue;
867
866
  }
@@ -884,7 +883,6 @@ export class TheiaPluginScanner implements PluginScanner {
884
883
  }
885
884
 
886
885
  let result: AutoClosingPair[] | undefined = undefined;
887
- // tslint:disable-next-line:one-variable-per-declaration
888
886
  for (let i = 0, len = source.length; i < len; i++) {
889
887
  const pair = source[i];
890
888
  if (Array.isArray(pair)) {
@@ -918,21 +916,7 @@ export class TheiaPluginScanner implements PluginScanner {
918
916
 
919
917
  function isCharacterPair(something: CharacterPair): boolean {
920
918
  return (
921
- isStringArr(something)
919
+ isStringArray(something)
922
920
  && something.length === 2
923
921
  );
924
922
  }
925
-
926
- function isStringArr(something: string[]): boolean {
927
- if (!Array.isArray(something)) {
928
- return false;
929
- }
930
- // tslint:disable-next-line:one-variable-per-declaration
931
- for (let i = 0, len = something.length; i < len; i++) {
932
- if (typeof something[i] !== 'string') {
933
- return false;
934
- }
935
- }
936
- return true;
937
-
938
- }
@@ -0,0 +1,70 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 Red Hat, Inc. 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 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { IDataTransferItem, VSDataTransfer } from '@theia/monaco-editor-core/esm/vs/base/common/dataTransfer';
18
+ import { DataTransferDTO, DataTransferItemDTO } from '../../../common/plugin-api-rpc-model';
19
+ import { URI } from '../../../plugin/types-impl';
20
+
21
+ export namespace DataTransferItem {
22
+ export async function from(mime: string, item: IDataTransferItem): Promise<DataTransferItemDTO> {
23
+ const stringValue = await item.asString();
24
+
25
+ if (mime === 'text/uri-list') {
26
+ return {
27
+ id: item.id,
28
+ asString: '',
29
+ fileData: undefined,
30
+ uriListData: serializeUriList(stringValue),
31
+ };
32
+ }
33
+
34
+ const fileValue = item.asFile();
35
+ return {
36
+ id: item.id,
37
+ asString: stringValue,
38
+ fileData: fileValue ? { name: fileValue.name, uri: fileValue.uri } : undefined,
39
+ };
40
+ }
41
+
42
+ function serializeUriList(stringValue: string): ReadonlyArray<string | URI> {
43
+ return stringValue.split('\r\n').map(part => {
44
+ if (part.startsWith('#')) {
45
+ return part;
46
+ }
47
+
48
+ try {
49
+ return URI.parse(part);
50
+ } catch {
51
+ // noop
52
+ }
53
+
54
+ return part;
55
+ });
56
+ }
57
+ }
58
+
59
+ export namespace DataTransfer {
60
+ export async function toDataTransferDTO(value: VSDataTransfer): Promise<DataTransferDTO> {
61
+ return {
62
+ items: await Promise.all(
63
+ Array.from(value.entries())
64
+ .map(
65
+ async ([mime, item]) => [mime, await DataTransferItem.from(mime, item)]
66
+ )
67
+ )
68
+ };
69
+ }
70
+ }
@@ -77,8 +77,10 @@ export class ModalNotification extends AbstractDialog<string | undefined> {
77
77
  detailElement.textContent = options.detail;
78
78
  }
79
79
 
80
- actions.forEach((action: MainMessageItem) => {
81
- const button = this.createButton(action.title);
80
+ actions.forEach((action: MainMessageItem, index: number) => {
81
+ const button = index === 0
82
+ ? this.appendAcceptButton(action.title)
83
+ : this.createButton(action.title);
82
84
  button.classList.add('main');
83
85
  this.controlPanel.appendChild(button);
84
86
  this.addKeyListener(button,
@@ -44,7 +44,7 @@ import {
44
44
  } from '../../common/plugin-api-rpc-model';
45
45
  import { RPCProtocol } from '../../common/rpc-protocol';
46
46
  import { MonacoLanguages, WorkspaceSymbolProvider } from '@theia/monaco/lib/browser/monaco-languages';
47
- import CoreURI from '@theia/core/lib/common/uri';
47
+ import { URI } from '@theia/core/lib/common/uri';
48
48
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
49
49
  import { Emitter, Event } from '@theia/core/lib/common/event';
50
50
  import { ProblemManager } from '@theia/markers/lib/browser';
@@ -71,6 +71,8 @@ import { EditorLanguageStatusService, LanguageStatus as EditorLanguageStatus } f
71
71
  import { LanguageSelector, RelativePattern } from '@theia/editor/lib/common/language-selector';
72
72
  import { ILanguageFeaturesService } from '@theia/monaco-editor-core/esm/vs/editor/common/services/languageFeatures';
73
73
  import {
74
+ DocumentOnDropEdit,
75
+ DocumentOnDropEditProvider,
74
76
  EvaluatableExpression,
75
77
  EvaluatableExpressionProvider,
76
78
  InlineValue,
@@ -78,7 +80,10 @@ import {
78
80
  InlineValuesProvider
79
81
  } from '@theia/monaco-editor-core/esm/vs/editor/common/languages';
80
82
  import { ITextModel } from '@theia/monaco-editor-core/esm/vs/editor/common/model';
81
- import { CodeActionTriggerKind } from '../../plugin/types-impl';
83
+ import { CodeActionTriggerKind, SnippetString } from '../../plugin/types-impl';
84
+ import { DataTransfer } from './data-transfer/data-transfer-type-converters';
85
+ import { VSDataTransfer } from '@theia/monaco-editor-core/esm/vs/base/common/dataTransfer';
86
+ import { FileUploadService } from '@theia/filesystem/lib/browser/file-upload-service';
82
87
 
83
88
  /**
84
89
  * @monaco-uplift The public API declares these functions as (languageId: string, service).
@@ -107,6 +112,9 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
107
112
  @inject(EditorLanguageStatusService)
108
113
  protected readonly languageStatusService: EditorLanguageStatusService;
109
114
 
115
+ @inject(FileUploadService)
116
+ protected readonly fileUploadService: FileUploadService;
117
+
110
118
  private readonly proxy: LanguagesExt;
111
119
  private readonly services = new Map<number, Disposable>();
112
120
  private readonly toDispose = new DisposableCollection();
@@ -252,13 +260,13 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
252
260
 
253
261
  $clearDiagnostics(id: string): void {
254
262
  for (const uri of this.problemManager.getUris()) {
255
- this.problemManager.setMarkers(new CoreURI(uri), id, []);
263
+ this.problemManager.setMarkers(new URI(uri), id, []);
256
264
  }
257
265
  }
258
266
 
259
267
  $changeDiagnostics(id: string, delta: [string, MarkerData[]][]): void {
260
268
  for (const [uriString, markers] of delta) {
261
- const uri = new CoreURI(uriString);
269
+ const uri = new URI(uriString);
262
270
  this.problemManager.setMarkers(uri, id, markers.map(reviveMarker));
263
271
  }
264
272
  }
@@ -718,6 +726,28 @@ export class LanguagesMainImpl implements LanguagesMain, Disposable {
718
726
  return this.proxy.$provideOnTypeFormattingEdits(handle, model.uri, position, ch, options, token);
719
727
  }
720
728
 
729
+ $registerDocumentDropEditProvider(handle: number, selector: SerializedDocumentFilter[]): void {
730
+ this.register(handle, (StandaloneServices.get(ILanguageFeaturesService).documentOnDropEditProvider.register(selector, this.createDocumentDropEditProvider(handle))));
731
+ }
732
+
733
+ createDocumentDropEditProvider(handle: number): DocumentOnDropEditProvider {
734
+ return {
735
+ provideDocumentOnDropEdits: async (model, position, dataTransfer, token) => this.provideDocumentDropEdits(handle, model, position, dataTransfer, token)
736
+ };
737
+ }
738
+
739
+ protected async provideDocumentDropEdits(handle: number, model: ITextModel, position: monaco.IPosition,
740
+ dataTransfer: VSDataTransfer, token: CancellationToken): Promise<DocumentOnDropEdit | undefined> {
741
+ await this.fileUploadService.upload(new URI(), { source: dataTransfer, leaveInTemp: true });
742
+ const edit = await this.proxy.$provideDocumentDropEdits(handle, model.uri, position, await DataTransfer.toDataTransferDTO(dataTransfer), token);
743
+ if (edit) {
744
+ return {
745
+ insertText: edit.insertText instanceof SnippetString ? { snippet: edit.insertText.value } : edit.insertText,
746
+ additionalEdit: toMonacoWorkspaceEdit(edit?.additionalEdit)
747
+ };
748
+ }
749
+ }
750
+
721
751
  $registerFoldingRangeProvider(handle: number, pluginInfo: PluginInfo, selector: SerializedDocumentFilter[], eventHandle: number | undefined): void {
722
752
  const languageSelector = this.toLanguageSelector(selector);
723
753
  const provider = this.createFoldingRangeProvider(handle);
@@ -82,6 +82,7 @@ import { PluginMenuCommandAdapter } from './menus/plugin-menu-command-adapter';
82
82
  import './theme-icon-override';
83
83
  import { PluginTerminalRegistry } from './plugin-terminal-registry';
84
84
  import { DnDFileContentStore } from './view/dnd-file-content-store';
85
+ import { WebviewContextKeys } from './webview/webview-context-keys';
85
86
 
86
87
  export default new ContainerModule((bind, unbind, isBound, rebind) => {
87
88
 
@@ -177,6 +178,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
177
178
  bind(WebviewWidget).toSelf();
178
179
  bind(WebviewWidgetFactory).toDynamicValue(ctx => new WebviewWidgetFactory(ctx.container)).inSingletonScope();
179
180
  bind(WidgetFactory).toService(WebviewWidgetFactory);
181
+ bind(WebviewContextKeys).toSelf().inSingletonScope();
182
+ bind(FrontendApplicationContribution).toService(WebviewContextKeys);
180
183
 
181
184
  bind(CustomEditorContribution).toSelf().inSingletonScope();
182
185
  bind(CommandContribution).toService(CustomEditorContribution);
@@ -30,6 +30,7 @@ import {
30
30
  DecorationOptions,
31
31
  WorkspaceEditDto,
32
32
  DocumentsMain,
33
+ WorkspaceEditMetadataDto,
33
34
  } from '../../common/plugin-api-rpc';
34
35
  import { Range, TextDocumentShowOptions } from '../../common/plugin-api-rpc-model';
35
36
  import { EditorsAndDocumentsMain } from './editors-and-documents-main';
@@ -126,11 +127,11 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
126
127
  return Promise.resolve(this.editorsAndDocuments.getEditor(id)!.applyEdits(modelVersionId, edits, opts));
127
128
  }
128
129
 
129
- async $tryApplyWorkspaceEdit(dto: WorkspaceEditDto): Promise<boolean> {
130
+ async $tryApplyWorkspaceEdit(dto: WorkspaceEditDto, metadata?: WorkspaceEditMetadataDto): Promise<boolean> {
130
131
  const workspaceEdit = toMonacoWorkspaceEdit(dto);
131
132
  try {
132
133
  const edits = ResourceEdit.convert(workspaceEdit);
133
- const { success } = await this.bulkEditService.apply(edits);
134
+ const { success } = await this.bulkEditService.apply(edits, { respectAutoSaveConfig: metadata?.isRefactoring });
134
135
  return success;
135
136
  } catch {
136
137
  return false;