@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.
- package/lib/common/plugin-api-rpc-model.d.ts +18 -1
- package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc-model.js.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +10 -5
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +30 -0
- package/lib/common/plugin-protocol.d.ts.map +1 -1
- package/lib/common/plugin-protocol.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +10 -17
- package/lib/hosted/browser/hosted-plugin.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
- package/lib/hosted/node/plugin-activation-events.d.ts +7 -0
- package/lib/hosted/node/plugin-activation-events.d.ts.map +1 -0
- package/lib/hosted/node/plugin-activation-events.js +96 -0
- package/lib/hosted/node/plugin-activation-events.js.map +1 -0
- package/lib/hosted/node/plugin-manifest-loader.d.ts +2 -1
- package/lib/hosted/node/plugin-manifest-loader.d.ts.map +1 -1
- package/lib/hosted/node/plugin-manifest-loader.js +2 -1
- package/lib/hosted/node/plugin-manifest-loader.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +27 -36
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/main/browser/data-transfer/data-transfer-type-converters.d.ts +9 -0
- package/lib/main/browser/data-transfer/data-transfer-type-converters.d.ts.map +1 -0
- package/lib/main/browser/data-transfer/data-transfer-type-converters.js +65 -0
- package/lib/main/browser/data-transfer/data-transfer-type-converters.js.map +1 -0
- package/lib/main/browser/dialogs/modal-notification.d.ts.map +1 -1
- package/lib/main/browser/dialogs/modal-notification.js +4 -2
- package/lib/main/browser/dialogs/modal-notification.js.map +1 -1
- package/lib/main/browser/languages-main.d.ts +8 -1
- package/lib/main/browser/languages-main.d.ts.map +1 -1
- package/lib/main/browser/languages-main.js +26 -2
- package/lib/main/browser/languages-main.js.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.js +3 -0
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/text-editors-main.d.ts +2 -2
- package/lib/main/browser/text-editors-main.d.ts.map +1 -1
- package/lib/main/browser/text-editors-main.js +2 -2
- package/lib/main/browser/text-editors-main.js.map +1 -1
- package/lib/main/browser/webview/webview-context-keys.d.ts +13 -0
- package/lib/main/browser/webview/webview-context-keys.d.ts.map +1 -0
- package/lib/main/browser/webview/webview-context-keys.js +64 -0
- package/lib/main/browser/webview/webview-context-keys.js.map +1 -0
- package/lib/plugin/dialogs.js +2 -2
- package/lib/plugin/dialogs.js.map +1 -1
- package/lib/plugin/file-system-ext-impl.d.ts +11 -5
- package/lib/plugin/file-system-ext-impl.d.ts.map +1 -1
- package/lib/plugin/file-system-ext-impl.js +8 -16
- package/lib/plugin/file-system-ext-impl.js.map +1 -1
- package/lib/plugin/known-commands.d.ts.map +1 -1
- package/lib/plugin/known-commands.js +13 -0
- package/lib/plugin/known-commands.js.map +1 -1
- package/lib/plugin/languages/document-drop-edit.d.ts +16 -0
- package/lib/plugin/languages/document-drop-edit.d.ts.map +1 -0
- package/lib/plugin/languages/document-drop-edit.js +23 -0
- package/lib/plugin/languages/document-drop-edit.js.map +1 -0
- package/lib/plugin/languages.d.ts +9 -2
- package/lib/plugin/languages.d.ts.map +1 -1
- package/lib/plugin/languages.js +27 -1
- package/lib/plugin/languages.js.map +1 -1
- package/lib/plugin/plugin-context.d.ts.map +1 -1
- package/lib/plugin/plugin-context.js +8 -4
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/preference-registry.d.ts +5 -3
- package/lib/plugin/preference-registry.d.ts.map +1 -1
- package/lib/plugin/preference-registry.js +31 -42
- package/lib/plugin/preference-registry.js.map +1 -1
- package/lib/plugin/preference-registry.spec.js +29 -41
- package/lib/plugin/preference-registry.spec.js.map +1 -1
- package/lib/plugin/text-editors.d.ts +1 -1
- package/lib/plugin/text-editors.d.ts.map +1 -1
- package/lib/plugin/text-editors.js +2 -2
- package/lib/plugin/text-editors.js.map +1 -1
- package/lib/plugin/type-converters.d.ts +6 -0
- package/lib/plugin/type-converters.d.ts.map +1 -1
- package/lib/plugin/type-converters.js +37 -1
- package/lib/plugin/type-converters.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +5 -0
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js +13 -3
- package/lib/plugin/types-impl.js.map +1 -1
- package/package.json +27 -27
- package/src/common/plugin-api-rpc-model.ts +22 -1
- package/src/common/plugin-api-rpc.ts +18 -5
- package/src/common/plugin-protocol.ts +32 -4
- package/src/hosted/browser/hosted-plugin.ts +9 -16
- package/src/hosted/node/hosted-plugin-process.ts +2 -2
- package/src/hosted/node/plugin-activation-events.ts +111 -0
- package/src/hosted/node/plugin-manifest-loader.ts +4 -3
- package/src/hosted/node/scanners/scanner-theia.ts +59 -75
- package/src/main/browser/data-transfer/data-transfer-type-converters.ts +70 -0
- package/src/main/browser/dialogs/modal-notification.ts +4 -2
- package/src/main/browser/languages-main.ts +34 -4
- package/src/main/browser/plugin-ext-frontend-module.ts +3 -0
- package/src/main/browser/text-editors-main.ts +3 -2
- package/src/main/browser/webview/webview-context-keys.ts +49 -0
- package/src/plugin/dialogs.ts +2 -2
- package/src/plugin/file-system-ext-impl.ts +8 -18
- package/src/plugin/known-commands.ts +16 -1
- package/src/plugin/languages/document-drop-edit.ts +44 -0
- package/src/plugin/languages.ts +41 -3
- package/src/plugin/plugin-context.ts +9 -4
- package/src/plugin/preference-registry.spec.ts +29 -45
- package/src/plugin/preference-registry.ts +33 -45
- package/src/plugin/text-editors.ts +2 -2
- package/src/plugin/type-converters.ts +37 -0
- package/src/plugin/types-impl.ts +11 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 Ericsson 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 { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
18
|
+
import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
19
|
+
import { ApplicationShell, FocusTracker, Widget } from '@theia/core/lib/browser';
|
|
20
|
+
import { WebviewWidget } from './webview';
|
|
21
|
+
|
|
22
|
+
@injectable()
|
|
23
|
+
export class WebviewContextKeys {
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Context key representing the `viewType` of the active `WebviewWidget`, if any.
|
|
27
|
+
*/
|
|
28
|
+
activeWebviewPanelId: ContextKey<string>;
|
|
29
|
+
|
|
30
|
+
@inject(ApplicationShell)
|
|
31
|
+
protected applicationShell: ApplicationShell;
|
|
32
|
+
|
|
33
|
+
@inject(ContextKeyService)
|
|
34
|
+
protected contextKeyService: ContextKeyService;
|
|
35
|
+
|
|
36
|
+
@postConstruct()
|
|
37
|
+
protected postConstruct(): void {
|
|
38
|
+
this.activeWebviewPanelId = this.contextKeyService.createKey('activeWebviewPanelId', '');
|
|
39
|
+
this.applicationShell.onDidChangeCurrentWidget(this.handleDidChangeCurrentWidget, this);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected handleDidChangeCurrentWidget(change: FocusTracker.IChangedArgs<Widget>): void {
|
|
43
|
+
if (change.newValue instanceof WebviewWidget) {
|
|
44
|
+
this.activeWebviewPanelId.set(change.newValue.viewType);
|
|
45
|
+
} else {
|
|
46
|
+
this.activeWebviewPanelId.set('');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/plugin/dialogs.ts
CHANGED
|
@@ -30,8 +30,8 @@ export class DialogsExtImpl {
|
|
|
30
30
|
title: options.title,
|
|
31
31
|
openLabel: options.openLabel,
|
|
32
32
|
defaultUri: options.defaultUri ? options.defaultUri.path : undefined,
|
|
33
|
-
canSelectFiles: options.canSelectFiles ? options.canSelectFiles : true,
|
|
34
|
-
canSelectFolders: options.canSelectFolders ? options.canSelectFolders : false,
|
|
33
|
+
canSelectFiles: typeof options.canSelectFiles === 'boolean' ? options.canSelectFiles : true,
|
|
34
|
+
canSelectFolders: typeof options.canSelectFolders === 'boolean' ? options.canSelectFolders : false,
|
|
35
35
|
canSelectMany: options.canSelectMany,
|
|
36
36
|
filters: options.filters
|
|
37
37
|
} as OpenDialogOptionsMain;
|
|
@@ -35,16 +35,16 @@ import { PLUGIN_RPC_CONTEXT, FileSystemExt, FileSystemMain, IFileChangeDto } fro
|
|
|
35
35
|
import * as vscode from '@theia/plugin';
|
|
36
36
|
import * as files from '@theia/filesystem/lib/common/files';
|
|
37
37
|
import * as typeConverter from './type-converters';
|
|
38
|
-
import { LanguagesExtImpl } from './languages';
|
|
39
38
|
import { Schemes as Schemas } from '../common/uri-components';
|
|
40
39
|
import { State, StateMachine, LinkComputer, Edge } from '../common/link-computer';
|
|
41
40
|
import { commonPrefixLength } from '@theia/core/lib/common/strings';
|
|
42
41
|
import { CharCode } from '@theia/core/lib/common/char-code';
|
|
43
42
|
import { BinaryBuffer } from '@theia/core/lib/common/buffer';
|
|
43
|
+
import { Emitter } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
44
44
|
|
|
45
45
|
type IDisposable = vscode.Disposable;
|
|
46
46
|
|
|
47
|
-
class FsLinkProvider {
|
|
47
|
+
export class FsLinkProvider {
|
|
48
48
|
|
|
49
49
|
private _schemes: string[] = [];
|
|
50
50
|
private _stateMachine?: StateMachine;
|
|
@@ -204,12 +204,14 @@ export class FileSystemExtImpl implements FileSystemExt {
|
|
|
204
204
|
private readonly _usedSchemes = new Set<string>();
|
|
205
205
|
private readonly _watches = new Map<number, IDisposable>();
|
|
206
206
|
|
|
207
|
-
private
|
|
207
|
+
private readonly onWillRegisterFileSystemProviderEmitter = new Emitter<FsLinkProvider>();
|
|
208
|
+
readonly onWillRegisterFileSystemProvider = this.onWillRegisterFileSystemProviderEmitter.event;
|
|
209
|
+
|
|
208
210
|
private _handlePool: number = 0;
|
|
209
211
|
|
|
210
212
|
readonly fileSystem: vscode.FileSystem;
|
|
211
213
|
|
|
212
|
-
constructor(rpc: RPCProtocol
|
|
214
|
+
constructor(rpc: RPCProtocol) {
|
|
213
215
|
this._proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.FILE_SYSTEM_MAIN);
|
|
214
216
|
this.fileSystem = new ConsumerFileSystem(this._proxy, this._capabilities);
|
|
215
217
|
|
|
@@ -218,18 +220,7 @@ export class FileSystemExtImpl implements FileSystemExt {
|
|
|
218
220
|
}
|
|
219
221
|
|
|
220
222
|
dispose(): void {
|
|
221
|
-
|
|
222
|
-
this._linkProviderRegistration.dispose();
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
private _registerLinkProviderIfNotYetRegistered(): void {
|
|
227
|
-
if (!this._linkProviderRegistration) {
|
|
228
|
-
this._linkProviderRegistration = this._extHostLanguageFeatures.registerDocumentLinkProvider('*', this._linkProvider, {
|
|
229
|
-
id: 'theia.fs-ext-impl',
|
|
230
|
-
name: 'fs-ext-impl'
|
|
231
|
-
});
|
|
232
|
-
}
|
|
223
|
+
this.onWillRegisterFileSystemProviderEmitter.dispose();
|
|
233
224
|
}
|
|
234
225
|
|
|
235
226
|
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean, isReadonly?: boolean } = {}) {
|
|
@@ -238,8 +229,7 @@ export class FileSystemExtImpl implements FileSystemExt {
|
|
|
238
229
|
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
|
|
239
230
|
}
|
|
240
231
|
|
|
241
|
-
|
|
242
|
-
this._registerLinkProviderIfNotYetRegistered();
|
|
232
|
+
this.onWillRegisterFileSystemProviderEmitter.fire(this._linkProvider);
|
|
243
233
|
|
|
244
234
|
const handle = this._handlePool++;
|
|
245
235
|
this._linkProvider.add(scheme);
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { Range as R, Position as P, Location as L } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
18
17
|
import * as theia from '@theia/plugin';
|
|
18
|
+
import { Range as R, Position as P, Location as L } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
19
|
+
import { URI as TheiaURI } from '@theia/core/lib/common/uri';
|
|
19
20
|
import { cloneAndChange } from '../common/objects';
|
|
20
21
|
import { Position, Range, Location, CallHierarchyItem, TypeHierarchyItem, URI, TextDocumentShowOptions } from './types-impl';
|
|
21
22
|
import {
|
|
@@ -63,6 +64,9 @@ export namespace KnownCommands {
|
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
const identity = (args: any[]) => args;
|
|
69
|
+
|
|
66
70
|
mappings['editor.action.select.all'] = ['editor.action.select.all', CONVERT_VSCODE_TO_MONACO];
|
|
67
71
|
mappings['editor.action.toggleHighContrast'] = ['editor.action.toggleHighContrast', CONVERT_VSCODE_TO_MONACO];
|
|
68
72
|
mappings['editor.action.moveCarretLeftAction'] = ['editor.action.moveCarretLeftAction', CONVERT_VSCODE_TO_MONACO];
|
|
@@ -302,6 +306,17 @@ export namespace KnownCommands {
|
|
|
302
306
|
mappings['vscode.open'] = ['vscode.open', CONVERT_VSCODE_TO_MONACO];
|
|
303
307
|
mappings['vscode.diff'] = ['vscode.diff', CONVERT_VSCODE_TO_MONACO];
|
|
304
308
|
|
|
309
|
+
// terminal commands
|
|
310
|
+
mappings['workbench.action.terminal.new'] = ['terminal:new', identity];
|
|
311
|
+
mappings['workbench.action.terminal.newWithProfile'] = ['terminal:new:profile', identity];
|
|
312
|
+
mappings['workbench.action.terminal.selectDefaultShell'] = ['terminal:profile:default', identity];
|
|
313
|
+
mappings['workbench.action.terminal.newInActiveWorkspace'] = ['terminal:new:active:workspace', identity];
|
|
314
|
+
mappings['workbench.action.terminal.clear'] = ['terminal:clear', identity];
|
|
315
|
+
mappings['openInTerminal'] = ['terminal:context', createConversionFunction((uri: URI) => new TheiaURI(uri))];
|
|
316
|
+
mappings['workbench.action.terminal.split'] = ['terminal:split', identity];
|
|
317
|
+
mappings['workbench.action.terminal.focusFind'] = ['terminal:find', identity];
|
|
318
|
+
mappings['workbench.action.terminal.hideFind'] = ['terminal:find:cancel', identity];
|
|
319
|
+
|
|
305
320
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
306
321
|
export function map<T>(id: string, args: any[] | undefined, toDo: (mappedId: string, mappedArgs: any[] | undefined, mappedResult: ConversionFunction | undefined) => T): T {
|
|
307
322
|
if (mappings[id]) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2018 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
|
+
import * as theia from '@theia/plugin';
|
|
17
|
+
import { DataTransferDTO, DocumentDropEdit } from '../../common/plugin-api-rpc-model';
|
|
18
|
+
import { CancellationToken } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
19
|
+
import { Position } from '../../common/plugin-api-rpc';
|
|
20
|
+
import * as Converter from '../type-converters';
|
|
21
|
+
import { DocumentsExtImpl } from '../documents';
|
|
22
|
+
import { URI } from '@theia/core/shared/vscode-uri';
|
|
23
|
+
import { FileSystemExtImpl } from '../file-system-ext-impl';
|
|
24
|
+
import * as os from 'os';
|
|
25
|
+
import * as path from 'path';
|
|
26
|
+
|
|
27
|
+
export class DocumentDropEditAdapter {
|
|
28
|
+
constructor(private readonly provider: theia.DocumentDropEditProvider,
|
|
29
|
+
private readonly documents: DocumentsExtImpl,
|
|
30
|
+
private readonly fileSystem: FileSystemExtImpl) { }
|
|
31
|
+
|
|
32
|
+
async provideDocumentDropEdits(resource: URI, position: Position, dataTransfer: DataTransferDTO, token: CancellationToken): Promise<DocumentDropEdit | undefined> {
|
|
33
|
+
return this.provider.provideDocumentDropEdits(
|
|
34
|
+
this.documents.getDocument(resource),
|
|
35
|
+
Converter.toPosition(position),
|
|
36
|
+
Converter.DataTransfer.toDataTransfer(dataTransfer, itemId => this.resolveFileData(itemId)),
|
|
37
|
+
token) as DocumentDropEdit | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private async resolveFileData(itemId: string): Promise<Uint8Array> {
|
|
41
|
+
const filePath = URI.file(path.resolve(os.tmpdir(), 'theia_upload', itemId));
|
|
42
|
+
return this.fileSystem.fileSystem.readFile(filePath);
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/plugin/languages.ts
CHANGED
|
@@ -69,7 +69,9 @@ import {
|
|
|
69
69
|
InlineValue,
|
|
70
70
|
InlineValueContext,
|
|
71
71
|
TypeHierarchyItem,
|
|
72
|
-
InlineCompletionContext
|
|
72
|
+
InlineCompletionContext,
|
|
73
|
+
DocumentDropEdit,
|
|
74
|
+
DataTransferDTO
|
|
73
75
|
} from '../common/plugin-api-rpc-model';
|
|
74
76
|
import { CompletionAdapter } from './languages/completion';
|
|
75
77
|
import { Diagnostics } from './languages/diagnostics';
|
|
@@ -109,6 +111,9 @@ import { LinkedEditingRangeAdapter } from './languages/linked-editing-range';
|
|
|
109
111
|
import { serializeEnterRules, serializeIndentation, serializeRegExp } from './languages-utils';
|
|
110
112
|
import { InlayHintsAdapter } from './languages/inlay-hints';
|
|
111
113
|
import { InlineCompletionAdapter, InlineCompletionAdapterBase } from './languages/inline-completion';
|
|
114
|
+
import { DocumentDropEditAdapter } from './languages/document-drop-edit';
|
|
115
|
+
import { IDisposable } from '@theia/monaco-editor-core';
|
|
116
|
+
import { FileSystemExtImpl, FsLinkProvider } from './file-system-ext-impl';
|
|
112
117
|
|
|
113
118
|
type Adapter = CompletionAdapter |
|
|
114
119
|
SignatureHelpAdapter |
|
|
@@ -139,7 +144,8 @@ type Adapter = CompletionAdapter |
|
|
|
139
144
|
DocumentSemanticTokensAdapter |
|
|
140
145
|
LinkedEditingRangeAdapter |
|
|
141
146
|
TypeHierarchyAdapter |
|
|
142
|
-
InlineCompletionAdapter
|
|
147
|
+
InlineCompletionAdapter |
|
|
148
|
+
DocumentDropEditAdapter;
|
|
143
149
|
|
|
144
150
|
export class LanguagesExtImpl implements LanguagesExt {
|
|
145
151
|
|
|
@@ -147,15 +153,25 @@ export class LanguagesExtImpl implements LanguagesExt {
|
|
|
147
153
|
|
|
148
154
|
private readonly diagnostics: Diagnostics;
|
|
149
155
|
|
|
156
|
+
private linkProviderRegistration?: IDisposable;
|
|
157
|
+
|
|
150
158
|
private callId = 0;
|
|
151
159
|
private adaptersMap = new Map<number, Adapter>();
|
|
152
160
|
|
|
153
161
|
constructor(
|
|
154
162
|
rpc: RPCProtocol,
|
|
155
163
|
private readonly documents: DocumentsExtImpl,
|
|
156
|
-
private readonly commands: CommandRegistryImpl
|
|
164
|
+
private readonly commands: CommandRegistryImpl,
|
|
165
|
+
private readonly filesSystem: FileSystemExtImpl) {
|
|
157
166
|
this.proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.LANGUAGES_MAIN);
|
|
158
167
|
this.diagnostics = new Diagnostics(rpc);
|
|
168
|
+
filesSystem.onWillRegisterFileSystemProvider(linkProvider => this.registerLinkProviderIfNotYetRegistered(linkProvider));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
dispose(): void {
|
|
172
|
+
if (this.linkProviderRegistration) {
|
|
173
|
+
this.linkProviderRegistration.dispose();
|
|
174
|
+
}
|
|
159
175
|
}
|
|
160
176
|
|
|
161
177
|
get onDidChangeDiagnostics(): Event<theia.DiagnosticChangeEvent> {
|
|
@@ -258,6 +274,15 @@ export class LanguagesExtImpl implements LanguagesExt {
|
|
|
258
274
|
return undefined;
|
|
259
275
|
}
|
|
260
276
|
|
|
277
|
+
private registerLinkProviderIfNotYetRegistered(linkProvider: FsLinkProvider): void {
|
|
278
|
+
if (!this.linkProviderRegistration) {
|
|
279
|
+
this.linkProviderRegistration = this.registerDocumentLinkProvider('*', linkProvider, {
|
|
280
|
+
id: 'theia.fs-ext-impl',
|
|
281
|
+
name: 'fs-ext-impl'
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
261
286
|
// ### Completion begin
|
|
262
287
|
$provideCompletionItems(handle: number, resource: UriComponents, position: Position,
|
|
263
288
|
context: CompletionContext, token: theia.CancellationToken): Promise<CompletionResultDto | undefined> {
|
|
@@ -463,6 +488,19 @@ export class LanguagesExtImpl implements LanguagesExt {
|
|
|
463
488
|
}
|
|
464
489
|
// ### Document Formatting Edit end
|
|
465
490
|
|
|
491
|
+
// ### Drop Edit Provider start
|
|
492
|
+
$provideDocumentDropEdits(handle: number, resource: UriComponents, position: Position,
|
|
493
|
+
dataTransfer: DataTransferDTO, token: theia.CancellationToken): Promise<DocumentDropEdit | undefined> {
|
|
494
|
+
return this.withAdapter(handle, DocumentDropEditAdapter, adapter => adapter.provideDocumentDropEdits(URI.revive(resource), position, dataTransfer, token), undefined);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
registerDocumentDropEditProvider(selector: theia.DocumentSelector, provider: theia.DocumentDropEditProvider): theia.Disposable {
|
|
498
|
+
const callId = this.addNewAdapter(new DocumentDropEditAdapter(provider, this.documents, this.filesSystem));
|
|
499
|
+
this.proxy.$registerDocumentDropEditProvider(callId, this.transformDocumentSelector(selector));
|
|
500
|
+
return this.createDisposable(callId);
|
|
501
|
+
}
|
|
502
|
+
// ### Drop Edit Provider end
|
|
503
|
+
|
|
466
504
|
// ### Document Range Formatting Edit begin
|
|
467
505
|
registerDocumentRangeFormattingEditProvider(selector: theia.DocumentSelector, provider: theia.DocumentRangeFormattingEditProvider,
|
|
468
506
|
pluginInfo: PluginInfo): theia.Disposable {
|
|
@@ -87,6 +87,7 @@ import {
|
|
|
87
87
|
DocumentHighlightKind,
|
|
88
88
|
DocumentHighlight,
|
|
89
89
|
DocumentLink,
|
|
90
|
+
DocumentDropEdit,
|
|
90
91
|
CodeLens,
|
|
91
92
|
CodeActionKind,
|
|
92
93
|
CodeActionTrigger,
|
|
@@ -257,11 +258,11 @@ export function createAPIFactory(
|
|
|
257
258
|
const statusBarMessageRegistryExt = new StatusBarMessageRegistryExt(rpc);
|
|
258
259
|
const terminalExt = rpc.set(MAIN_RPC_CONTEXT.TERMINAL_EXT, new TerminalServiceExtImpl(rpc));
|
|
259
260
|
const outputChannelRegistryExt = rpc.set(MAIN_RPC_CONTEXT.OUTPUT_CHANNEL_REGISTRY_EXT, new OutputChannelRegistryExtImpl(rpc));
|
|
260
|
-
const languagesExt = rpc.set(MAIN_RPC_CONTEXT.LANGUAGES_EXT, new LanguagesExtImpl(rpc, documents, commandRegistry));
|
|
261
261
|
const treeViewsExt = rpc.set(MAIN_RPC_CONTEXT.TREE_VIEWS_EXT, new TreeViewsExtImpl(rpc, commandRegistry));
|
|
262
262
|
const tasksExt = rpc.set(MAIN_RPC_CONTEXT.TASKS_EXT, new TasksExtImpl(rpc, terminalExt));
|
|
263
263
|
const connectionExt = rpc.set(MAIN_RPC_CONTEXT.CONNECTION_EXT, new ConnectionImpl(rpc.getProxy(PLUGIN_RPC_CONTEXT.CONNECTION_MAIN)));
|
|
264
|
-
const fileSystemExt = rpc.set(MAIN_RPC_CONTEXT.FILE_SYSTEM_EXT, new FileSystemExtImpl(rpc
|
|
264
|
+
const fileSystemExt = rpc.set(MAIN_RPC_CONTEXT.FILE_SYSTEM_EXT, new FileSystemExtImpl(rpc));
|
|
265
|
+
const languagesExt = rpc.set(MAIN_RPC_CONTEXT.LANGUAGES_EXT, new LanguagesExtImpl(rpc, documents, commandRegistry, fileSystemExt));
|
|
265
266
|
const extHostFileSystemEvent = rpc.set(MAIN_RPC_CONTEXT.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpc, editorsAndDocumentsExt));
|
|
266
267
|
const scmExt = rpc.set(MAIN_RPC_CONTEXT.SCM_EXT, new ScmExtImpl(rpc, commandRegistry));
|
|
267
268
|
const decorationsExt = rpc.set(MAIN_RPC_CONTEXT.DECORATIONS_EXT, new DecorationsExtImpl(rpc));
|
|
@@ -669,8 +670,8 @@ export function createAPIFactory(
|
|
|
669
670
|
saveAll(includeUntitled?: boolean): PromiseLike<boolean> {
|
|
670
671
|
return editors.saveAll(includeUntitled);
|
|
671
672
|
},
|
|
672
|
-
applyEdit(edit: theia.WorkspaceEdit): PromiseLike<boolean> {
|
|
673
|
-
return editors.applyWorkspaceEdit(edit);
|
|
673
|
+
applyEdit(edit: theia.WorkspaceEdit, metadata?: theia.WorkspaceEditMetadata): PromiseLike<boolean> {
|
|
674
|
+
return editors.applyWorkspaceEdit(edit, metadata);
|
|
674
675
|
},
|
|
675
676
|
registerTextDocumentContentProvider(scheme: string, provider: theia.TextDocumentContentProvider): theia.Disposable {
|
|
676
677
|
return workspaceExt.registerTextDocumentContentProvider(scheme, provider);
|
|
@@ -853,6 +854,9 @@ export function createAPIFactory(
|
|
|
853
854
|
): theia.Disposable {
|
|
854
855
|
return languagesExt.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters), pluginToPluginInfo(plugin));
|
|
855
856
|
},
|
|
857
|
+
registerDocumentDropEditProvider(selector: theia.DocumentSelector, provider: theia.DocumentDropEditProvider) {
|
|
858
|
+
return languagesExt.registerDocumentDropEditProvider(selector, provider);
|
|
859
|
+
},
|
|
856
860
|
registerDocumentLinkProvider(selector: theia.DocumentSelector, provider: theia.DocumentLinkProvider): theia.Disposable {
|
|
857
861
|
return languagesExt.registerDocumentLinkProvider(selector, provider, pluginToPluginInfo(plugin));
|
|
858
862
|
},
|
|
@@ -1195,6 +1199,7 @@ export function createAPIFactory(
|
|
|
1195
1199
|
DocumentHighlightKind,
|
|
1196
1200
|
DocumentHighlight,
|
|
1197
1201
|
DocumentLink,
|
|
1202
|
+
DocumentDropEdit,
|
|
1198
1203
|
CodeLens,
|
|
1199
1204
|
CodeActionKind,
|
|
1200
1205
|
CodeActionTrigger,
|
|
@@ -41,36 +41,6 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
41
41
|
preferenceRegistryExtImpl = new PreferenceRegistryExtImpl(mockRPC, mockWorkspace);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
it('should parse configuration data without overrides', () => {
|
|
45
|
-
const value: Record<string, any> = {
|
|
46
|
-
'my.key1.foo': 'value1',
|
|
47
|
-
'my.key1.bar': 'value2',
|
|
48
|
-
};
|
|
49
|
-
const result = preferenceRegistryExtImpl['parseConfigurationData'](value);
|
|
50
|
-
expect(result.contents.my).to.be.an('object');
|
|
51
|
-
expect(result.contents.my.key1).to.be.an('object');
|
|
52
|
-
|
|
53
|
-
expect(result.contents.my.key1.foo).to.be.an('string');
|
|
54
|
-
expect(result.contents.my.key1.foo).to.equal('value1');
|
|
55
|
-
|
|
56
|
-
expect(result.contents.my.key1.bar).to.be.an('string');
|
|
57
|
-
expect(result.contents.my.key1.bar).to.equal('value2');
|
|
58
|
-
expect(result.keys).deep.equal(['my.key1.foo', 'my.key1.bar']);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should parse configuration with overrides', () => {
|
|
62
|
-
const value: Record<string, any> = {
|
|
63
|
-
'editor.tabSize': 2,
|
|
64
|
-
'[typescript].editor.tabSize': 4,
|
|
65
|
-
};
|
|
66
|
-
const result = preferenceRegistryExtImpl['parseConfigurationData'](value);
|
|
67
|
-
expect(result.contents.editor.tabSize).to.equal(2);
|
|
68
|
-
const tsOverride = result.overrides[0];
|
|
69
|
-
expect(tsOverride.contents.editor.tabSize).to.equal(4);
|
|
70
|
-
expect(tsOverride.identifiers).deep.equal(['typescript']);
|
|
71
|
-
expect(tsOverride.keys).deep.equal(['editor.tabSize']);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
44
|
describe('Prototype pollution', () => {
|
|
75
45
|
it('Ignores key `__proto__`', () => {
|
|
76
46
|
const value: Record<string, any> = {
|
|
@@ -80,16 +50,18 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
80
50
|
'__proto__': {},
|
|
81
51
|
'[typescript].someKey.foo': 'value',
|
|
82
52
|
'[typescript].__proto__.injectedParsedPrototype': true,
|
|
53
|
+
'b': { '__proto__.injectedParsedPrototype': true },
|
|
54
|
+
'c': { '__proto__': { 'injectedParsedPrototype': true } }
|
|
83
55
|
};
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
expect(result.
|
|
87
|
-
expect(result.
|
|
88
|
-
expect(result.
|
|
56
|
+
const configuration = preferenceRegistryExtImpl['getConfigurationModel']('test', value);
|
|
57
|
+
const result = configuration['_contents'];
|
|
58
|
+
expect(result.my, 'Safe keys are preserved.').to.be.an('object');
|
|
59
|
+
expect(result.__proto__, 'Keys containing __proto__ are ignored').to.be.an('undefined');
|
|
60
|
+
expect(result.my.key1.foo, 'Safe keys are dendrified.').to.equal('value1');
|
|
89
61
|
const prototypeObject = Object.prototype as any;
|
|
90
|
-
expect(prototypeObject.injectedParsedPrototype).to.be.an('undefined');
|
|
62
|
+
expect(prototypeObject.injectedParsedPrototype, 'Object.prototype is unaffected').to.be.an('undefined');
|
|
91
63
|
const rawObject = {} as any;
|
|
92
|
-
expect(rawObject.injectedParsedPrototype).to.be.an('undefined');
|
|
64
|
+
expect(rawObject.injectedParsedPrototype, 'Instantiated objects are unaffected.').to.be.an('undefined');
|
|
93
65
|
});
|
|
94
66
|
|
|
95
67
|
it('Ignores key `constructor.prototype`', () => {
|
|
@@ -98,17 +70,19 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
98
70
|
'a.constructor.prototype.injectedParsedConstructorPrototype': true,
|
|
99
71
|
'constructor.prototype.injectedParsedConstructorPrototype': true,
|
|
100
72
|
'[python].some.key.foo': 'value',
|
|
101
|
-
'[python].a.constructor.prototype.injectedParsedConstructorPrototype': true
|
|
73
|
+
'[python].a.constructor.prototype.injectedParsedConstructorPrototype': true,
|
|
74
|
+
'constructor': { 'prototype.injectedParsedConstructorPrototype': true },
|
|
75
|
+
'b': { 'constructor': { 'prototype': { 'injectedParsedConstructorPrototype': true } } }
|
|
102
76
|
};
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
expect(result.
|
|
106
|
-
expect(result.
|
|
77
|
+
const configuration = preferenceRegistryExtImpl['getConfigurationModel']('test', value);
|
|
78
|
+
const result = configuration['_contents'];
|
|
79
|
+
expect(result.my, 'Safe keys are preserved').to.be.an('object');
|
|
80
|
+
expect(result.__proto__, 'Keys containing __proto__ are ignored').to.be.an('undefined');
|
|
81
|
+
expect(result.my.key1.foo, 'Safe keys are dendrified.').to.equal('value1');
|
|
107
82
|
const prototypeObject = Object.prototype as any;
|
|
108
|
-
expect(prototypeObject.injectedParsedConstructorPrototype).to.be.an('undefined');
|
|
109
|
-
expect(result.overrides[0].contents.__proto__).to.be.an('undefined');
|
|
83
|
+
expect(prototypeObject.injectedParsedConstructorPrototype, 'Object.prototype is unaffected').to.be.an('undefined');
|
|
110
84
|
const rawObject = {} as any;
|
|
111
|
-
expect(rawObject.injectedParsedConstructorPrototype).to.be.an('undefined');
|
|
85
|
+
expect(rawObject.injectedParsedConstructorPrototype, 'Instantiated objects are unaffected.').to.be.an('undefined');
|
|
112
86
|
});
|
|
113
87
|
});
|
|
114
88
|
|
|
@@ -250,6 +224,16 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
250
224
|
const valuesRetrieved = preferenceRegistryExtImpl.getConfiguration(undefined, { uri: workspaceRoot, languageId: 'python' }).get('editor') as Record<string, unknown>;
|
|
251
225
|
expect(valuesRetrieved.tabSize).equal(4);
|
|
252
226
|
});
|
|
227
|
+
it('Allows access to language overrides in bracket form', () => {
|
|
228
|
+
const pythonOverrides = preferenceRegistryExtImpl.getConfiguration().get<Record<string, any>>('[python]');
|
|
229
|
+
expect(pythonOverrides).not.to.be.undefined;
|
|
230
|
+
expect(pythonOverrides?.['editor.renderWhitespace']).equal('all');
|
|
231
|
+
});
|
|
232
|
+
// https://github.com/eclipse-theia/theia/issues/12043
|
|
233
|
+
it('Allows access to preferences without specifying the section', () => {
|
|
234
|
+
const inspection = preferenceRegistryExtImpl.getConfiguration().inspect('editor.fontSize');
|
|
235
|
+
expect(inspection?.defaultValue).equal(14);
|
|
236
|
+
});
|
|
253
237
|
});
|
|
254
238
|
|
|
255
239
|
describe('Proxy Behavior', () => {
|
|
@@ -20,8 +20,8 @@ import { Emitter, Event } from '@theia/core/lib/common/event';
|
|
|
20
20
|
import { isOSX, isWindows } from '@theia/core/lib/common/os';
|
|
21
21
|
import { URI } from '@theia/core/shared/vscode-uri';
|
|
22
22
|
import { ResourceMap } from '@theia/monaco-editor-core/esm/vs/base/common/map';
|
|
23
|
-
import { IConfigurationOverrides
|
|
24
|
-
import { Configuration, ConfigurationModel } from '@theia/monaco-editor-core/esm/vs/platform/configuration/common/configurationModels';
|
|
23
|
+
import { IConfigurationOverrides } from '@theia/monaco-editor-core/esm/vs/platform/configuration/common/configuration';
|
|
24
|
+
import { Configuration, ConfigurationModel, ConfigurationModelParser } from '@theia/monaco-editor-core/esm/vs/platform/configuration/common/configurationModels';
|
|
25
25
|
import { Workspace, WorkspaceFolder } from '@theia/monaco-editor-core/esm/vs/platform/workspace/common/workspace';
|
|
26
26
|
import * as theia from '@theia/plugin';
|
|
27
27
|
import { v4 } from 'uuid';
|
|
@@ -234,12 +234,12 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
private parse(data: PreferenceData): Configuration {
|
|
237
|
-
const defaultConfiguration = this.getConfigurationModel(data[PreferenceScope.Default]);
|
|
238
|
-
const userConfiguration = this.getConfigurationModel(data[PreferenceScope.User]);
|
|
239
|
-
const workspaceConfiguration = this.getConfigurationModel(data[PreferenceScope.Workspace]);
|
|
237
|
+
const defaultConfiguration = this.getConfigurationModel('Default', data[PreferenceScope.Default]);
|
|
238
|
+
const userConfiguration = this.getConfigurationModel('User', data[PreferenceScope.User]);
|
|
239
|
+
const workspaceConfiguration = this.getConfigurationModel('Workspace', data[PreferenceScope.Workspace]);
|
|
240
240
|
const folderConfigurations = new ResourceMap<ConfigurationModel>();
|
|
241
241
|
Object.keys(data[PreferenceScope.Folder]).forEach(resource => {
|
|
242
|
-
folderConfigurations.set(URI.parse(resource), this.getConfigurationModel(data[PreferenceScope.Folder][resource]));
|
|
242
|
+
folderConfigurations.set(URI.parse(resource), this.getConfigurationModel(`Folder: ${resource}`, data[PreferenceScope.Folder][resource]));
|
|
243
243
|
});
|
|
244
244
|
return new Configuration(
|
|
245
245
|
defaultConfiguration,
|
|
@@ -252,53 +252,41 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
|
|
|
252
252
|
);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
private getConfigurationModel(data: { [key: string]: any }): ConfigurationModel {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return new ConfigurationModel(configData.contents, configData.keys, configData.overrides);
|
|
255
|
+
private getConfigurationModel(label: string, data: { [key: string]: any }): ConfigurationModel {
|
|
256
|
+
const parser = new ConfigurationModelParser(label);
|
|
257
|
+
const sanitized = this.sanitize(data);
|
|
258
|
+
parser.parseRaw(sanitized);
|
|
259
|
+
return parser.configurationModel;
|
|
261
260
|
}
|
|
262
261
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
private
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
for (let i = 0; i < parts.length; i++) {
|
|
281
|
-
if (i === 0 && isOverride) {
|
|
282
|
-
const identifier = this.OVERRIDE_PROPERTY_PATTERN.exec(parts[i])![1];
|
|
283
|
-
if (!overrides[identifier]) {
|
|
284
|
-
overrides[identifier] = { keys: [], identifiers: [identifier], contents: Object.create(null) };
|
|
262
|
+
/**
|
|
263
|
+
* Creates a new object and assigns those keys of raw to it that are not likely to cause prototype polution.
|
|
264
|
+
* Also preprocesses override identifiers so that they take the form [identifier]: {...contents}.
|
|
265
|
+
*/
|
|
266
|
+
private sanitize<T = unknown>(raw: T): T {
|
|
267
|
+
if (!isObject(raw)) { return raw; }
|
|
268
|
+
const asObject = raw as Record<string, unknown>;
|
|
269
|
+
const sanitized = Object.create(null);
|
|
270
|
+
for (const key of Object.keys(asObject)) {
|
|
271
|
+
if (!injectionRe.test(key)) {
|
|
272
|
+
const override = this.OVERRIDE_KEY_TEST.exec(key);
|
|
273
|
+
if (override) {
|
|
274
|
+
const overrideKey = `[${override[1]}]`;
|
|
275
|
+
const remainder = key.slice(override[0].length);
|
|
276
|
+
if (!isObject(sanitized[overrideKey])) {
|
|
277
|
+
sanitized[overrideKey] = Object.create(null);
|
|
285
278
|
}
|
|
286
|
-
|
|
287
|
-
overrides[identifier].keys.push(key.slice(parts[i].length + 1));
|
|
288
|
-
} else if (i === parts.length - 1) {
|
|
289
|
-
branch[parts[i]] = data[key];
|
|
279
|
+
sanitized[overrideKey][remainder] = this.sanitize(asObject[key]);
|
|
290
280
|
} else {
|
|
291
|
-
|
|
292
|
-
branch[parts[i]] = Object.create(null);
|
|
293
|
-
}
|
|
294
|
-
branch = branch[parts[i]];
|
|
281
|
+
sanitized[key] = this.sanitize(asObject[key]);
|
|
295
282
|
}
|
|
296
283
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return { contents, keys, overrides: Object.values(overrides) };
|
|
284
|
+
}
|
|
285
|
+
return sanitized;
|
|
300
286
|
}
|
|
301
287
|
|
|
288
|
+
private readonly OVERRIDE_KEY_TEST = /^\[([^\]]+)\]\./;
|
|
289
|
+
|
|
302
290
|
private toConfigurationChangeEvent(eventData: PreferenceChangeExt[]): theia.ConfigurationChangeEvent {
|
|
303
291
|
return Object.freeze({
|
|
304
292
|
affectsConfiguration: (section: string, scope?: theia.ConfigurationScope): boolean => {
|
|
@@ -119,9 +119,9 @@ export class TextEditorsExtImpl implements TextEditorsExt {
|
|
|
119
119
|
return new TextEditorDecorationType(this.proxy, options);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
applyWorkspaceEdit(edit: theia.WorkspaceEdit): Promise<boolean> {
|
|
122
|
+
applyWorkspaceEdit(edit: theia.WorkspaceEdit, metadata?: theia.WorkspaceEditMetadata): Promise<boolean> {
|
|
123
123
|
const dto = Converters.fromWorkspaceEdit(edit, this.editorsAndDocuments);
|
|
124
|
-
return this.proxy.$tryApplyWorkspaceEdit(dto);
|
|
124
|
+
return this.proxy.$tryApplyWorkspaceEdit(dto, metadata);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
saveAll(includeUntitled?: boolean): PromiseLike<boolean> {
|
|
@@ -1348,3 +1348,40 @@ export namespace InlayHintKind {
|
|
|
1348
1348
|
return kind;
|
|
1349
1349
|
}
|
|
1350
1350
|
}
|
|
1351
|
+
|
|
1352
|
+
export namespace DataTransferItem {
|
|
1353
|
+
export function to(mime: string, item: model.DataTransferItemDTO, resolveFileData: (itemId: string) => Promise<Uint8Array>): theia.DataTransferItem {
|
|
1354
|
+
const file = item.fileData;
|
|
1355
|
+
if (file) {
|
|
1356
|
+
return new class extends types.DataTransferItem {
|
|
1357
|
+
override asFile(): theia.DataTransferFile {
|
|
1358
|
+
return {
|
|
1359
|
+
name: file.name,
|
|
1360
|
+
uri: URI.revive(file.uri),
|
|
1361
|
+
data: () => resolveFileData(item.id),
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
}('');
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
if (mime === 'text/uri-list' && item.uriListData) {
|
|
1368
|
+
return new types.DataTransferItem(reviveUriList(item.uriListData));
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
return new types.DataTransferItem(item.asString);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
function reviveUriList(parts: ReadonlyArray<string | UriComponents>): string {
|
|
1375
|
+
return parts.map(part => typeof part === 'string' ? part : URI.revive(part).toString()).join('\r\n');
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
export namespace DataTransfer {
|
|
1380
|
+
export function toDataTransfer(value: model.DataTransferDTO, resolveFileData: (itemId: string) => Promise<Uint8Array>): theia.DataTransfer {
|
|
1381
|
+
const dataTransfer = new types.DataTransfer();
|
|
1382
|
+
for (const [mimeType, item] of value.items) {
|
|
1383
|
+
dataTransfer.set(mimeType, DataTransferItem.to(mimeType, item, resolveFileData));
|
|
1384
|
+
}
|
|
1385
|
+
return dataTransfer;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
package/src/plugin/types-impl.ts
CHANGED
|
@@ -1530,6 +1530,17 @@ export class DocumentLink {
|
|
|
1530
1530
|
}
|
|
1531
1531
|
}
|
|
1532
1532
|
|
|
1533
|
+
@es5ClassCompat
|
|
1534
|
+
export class DocumentDropEdit {
|
|
1535
|
+
insertText: string | SnippetString;
|
|
1536
|
+
|
|
1537
|
+
additionalEdit?: WorkspaceEdit;
|
|
1538
|
+
|
|
1539
|
+
constructor(insertText: string | SnippetString) {
|
|
1540
|
+
this.insertText = insertText;
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1533
1544
|
@es5ClassCompat
|
|
1534
1545
|
export class CodeLens {
|
|
1535
1546
|
|