mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-20 01:25:37 -05:00
Merge from vscode e3c4990c67c40213af168300d1cfeb71d680f877 (#16569)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
|
||||
@@ -65,6 +65,7 @@ import './mainThreadComments';
|
||||
import './mainThreadNotebook';
|
||||
import './mainThreadNotebookKernels';
|
||||
import './mainThreadNotebookDocumentsAndEditors';
|
||||
import './mainThreadNotebookRenderers';
|
||||
import './mainThreadTask';
|
||||
import './mainThreadLabelService';
|
||||
import './mainThreadTunnelService';
|
||||
|
||||
@@ -34,12 +34,14 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
const allowedExtensions = readAllowedExtensions(this.storageService, this.id, accountName);
|
||||
|
||||
if (!allowedExtensions.length) {
|
||||
this.dialogService.show(Severity.Info, nls.localize('noTrustedExtensions', "This account has not been used by any extensions."), []);
|
||||
this.dialogService.show(Severity.Info, nls.localize('noTrustedExtensions', "This account has not been used by any extensions."));
|
||||
return;
|
||||
}
|
||||
|
||||
const quickPick = this.quickInputService.createQuickPick<{ label: string, description: string, extension: AllowedExtension }>();
|
||||
quickPick.canSelectMany = true;
|
||||
quickPick.customButton = true;
|
||||
quickPick.customLabel = nls.localize('manageTrustedExtensions.cancel', 'Cancel');
|
||||
const usages = readAccountUsages(this.storageService, this.id, accountName);
|
||||
const items = allowedExtensions.map(extension => {
|
||||
const usage = usages.find(usage => extension.id === usage.extensionId);
|
||||
@@ -68,6 +70,10 @@ export class MainThreadAuthenticationProvider extends Disposable {
|
||||
quickPick.dispose();
|
||||
});
|
||||
|
||||
quickPick.onDidCustom(() => {
|
||||
quickPick.hide();
|
||||
});
|
||||
|
||||
quickPick.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ CommandsRegistry.registerCommand('_remoteCLI.manageExtensions', async function (
|
||||
const extensionManagementServerService = accessor.get(IExtensionManagementServerService);
|
||||
const remoteExtensionManagementService = extensionManagementServerService.remoteExtensionManagementServer?.extensionManagementService;
|
||||
if (!remoteExtensionManagementService) {
|
||||
return undefined;
|
||||
return undefined; // {{SQL CARBON EDIT}} Strict nulls
|
||||
}
|
||||
|
||||
const cliService = instantiationService.createChild(new ServiceCollection([IExtensionManagementService, remoteExtensionManagementService])).createInstance(RemoteExtensionCLIManagementService);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { multibyteAwareBtoa } from 'vs/base/browser/dom';
|
||||
import { CancelablePromise, createCancelablePromise, timeout } from 'vs/base/common/async';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
||||
@@ -16,7 +16,7 @@ import { isEqual, isEqualOrParent, toLocalResource } from 'vs/base/common/resour
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { FileChangesEvent, FileChangeType, FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileOperation, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
@@ -35,9 +35,10 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IPathService } from 'vs/workbench/services/path/common/pathService';
|
||||
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkingCopyFileService, WorkingCopyFileEvent } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { IWorkingCopy, IWorkingCopyBackup, NO_TYPE_ID, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopy';
|
||||
import { ResourceWorkingCopy } from 'vs/workbench/services/workingCopy/common/resourceWorkingCopy';
|
||||
|
||||
const enum CustomEditorModelType {
|
||||
Custom,
|
||||
@@ -50,6 +51,8 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
|
||||
private readonly _editorProviders = new Map<string, IDisposable>();
|
||||
|
||||
private readonly _editorRenameBackups = new Map<string, CustomDocumentBackupData>();
|
||||
|
||||
constructor(
|
||||
context: extHostProtocol.IExtHostContext,
|
||||
private readonly mainThreadWebview: MainThreadWebviews,
|
||||
@@ -60,7 +63,7 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
@ICustomEditorService private readonly _customEditorService: ICustomEditorService,
|
||||
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
|
||||
@IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -89,6 +92,9 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
},
|
||||
resolveWebview: () => { throw new Error('not implemented'); }
|
||||
}));
|
||||
|
||||
// Working copy operations
|
||||
this._register(workingCopyFileService.onWillRunWorkingCopyFileOperation(async e => this.onWillRunWorkingCopyFileOperation(e)));
|
||||
}
|
||||
|
||||
override dispose() {
|
||||
@@ -137,9 +143,18 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
webviewInput.webview.options = options;
|
||||
webviewInput.webview.extension = extension;
|
||||
|
||||
// If there's an old resource this was a move and we must resolve the backup at the same time as the webview
|
||||
// This is because the backup must be ready upon model creation, and the input resolve method comes after
|
||||
let backupId = webviewInput.backupId;
|
||||
if (webviewInput.oldResource && !webviewInput.backupId) {
|
||||
const backup = this._editorRenameBackups.get(webviewInput.oldResource.toString());
|
||||
backupId = backup?.backupId;
|
||||
this._editorRenameBackups.delete(webviewInput.oldResource.toString());
|
||||
}
|
||||
|
||||
let modelRef: IReference<ICustomEditorModel>;
|
||||
try {
|
||||
modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, { backupId: webviewInput.backupId }, cancellation);
|
||||
modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, { backupId }, cancellation);
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
webviewInput.webview.html = this.mainThreadWebview.getWebviewResolvedFailedContent(viewType);
|
||||
@@ -252,6 +267,31 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
//#region Working Copy
|
||||
private async onWillRunWorkingCopyFileOperation(e: WorkingCopyFileEvent) {
|
||||
if (e.operation !== FileOperation.MOVE) {
|
||||
return;
|
||||
}
|
||||
e.waitUntil((async () => {
|
||||
const models = [];
|
||||
for (const file of e.files) {
|
||||
if (file.source) {
|
||||
models.push(...(await this._customEditorService.models.getAllModels(file.source)));
|
||||
}
|
||||
}
|
||||
for (const model of models) {
|
||||
if (model instanceof MainThreadCustomEditorModel && model.isDirty()) {
|
||||
const workingCopy = await model.backup(CancellationToken.None);
|
||||
if (workingCopy.meta) {
|
||||
// This cast is safe because we do an instanceof check above and a custom document backup data is always returned
|
||||
this._editorRenameBackups.set(model.editorResource.toString(), workingCopy.meta as CustomDocumentBackupData);
|
||||
}
|
||||
}
|
||||
}
|
||||
})());
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
namespace HotExitState {
|
||||
@@ -276,9 +316,7 @@ namespace HotExitState {
|
||||
}
|
||||
|
||||
|
||||
class MainThreadCustomEditorModel extends Disposable implements ICustomEditorModel, IWorkingCopy {
|
||||
|
||||
#isDisposed = false;
|
||||
class MainThreadCustomEditorModel extends ResourceWorkingCopy implements ICustomEditorModel {
|
||||
|
||||
private _fromBackup: boolean = false;
|
||||
private _hotExitState: HotExitState.State = HotExitState.Allowed;
|
||||
@@ -288,13 +326,9 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
private _savePoint: number = -1;
|
||||
private readonly _edits: Array<number> = [];
|
||||
private _isDirtyFromContentChange = false;
|
||||
private _inOrphaned = false;
|
||||
|
||||
private _ongoingSave?: CancelablePromise<void>;
|
||||
|
||||
private readonly _onDidChangeOrphaned = this._register(new Emitter<void>());
|
||||
public readonly onDidChangeOrphaned = this._onDidChangeOrphaned.event;
|
||||
|
||||
// TODO@mjbvz consider to enable a `typeId` that is specific for custom
|
||||
// editors. Using a distinct `typeId` allows the working copy to have
|
||||
// any resource (including file based resources) even if other working
|
||||
@@ -322,7 +356,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
untitledDocumentData = editors[0].untitledDocumentData;
|
||||
}
|
||||
const { editable } = await proxy.$createCustomDocument(resource, viewType, options.backupId, untitledDocumentData, cancellation);
|
||||
return instantiationService.createInstance(MainThreadCustomEditorModel, proxy, viewType, resource, !!options.backupId, editable, getEditors);
|
||||
return instantiationService.createInstance(MainThreadCustomEditorModel, proxy, viewType, resource, !!options.backupId, editable, !!untitledDocumentData, getEditors);
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -331,16 +365,17 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
private readonly _editorResource: URI,
|
||||
fromBackup: boolean,
|
||||
private readonly _editable: boolean,
|
||||
startDirty: boolean,
|
||||
private readonly _getEditors: () => CustomEditorInput[],
|
||||
@IFileDialogService private readonly _fileDialogService: IFileDialogService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@IFileService fileService: IFileService,
|
||||
@ILabelService private readonly _labelService: ILabelService,
|
||||
@IUndoRedoService private readonly _undoService: IUndoRedoService,
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@IWorkingCopyService workingCopyService: IWorkingCopyService,
|
||||
@IPathService private readonly _pathService: IPathService
|
||||
@IPathService private readonly _pathService: IPathService,
|
||||
) {
|
||||
super();
|
||||
super(MainThreadCustomEditorModel.toWorkingCopyResource(_viewType, _editorResource), fileService);
|
||||
|
||||
this._fromBackup = fromBackup;
|
||||
|
||||
@@ -348,7 +383,10 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
this._register(workingCopyService.registerWorkingCopy(this));
|
||||
}
|
||||
|
||||
this._register(_fileService.onDidFilesChange(e => this.onDidFilesChange(e)));
|
||||
// Normally means we're re-opening an untitled file
|
||||
if (startDirty) {
|
||||
this._isDirtyFromContentChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
get editorResource() {
|
||||
@@ -356,8 +394,6 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
}
|
||||
|
||||
override dispose() {
|
||||
this.#isDisposed = true;
|
||||
|
||||
if (this._editable) {
|
||||
this._undoService.removeElements(this._editorResource);
|
||||
}
|
||||
@@ -369,11 +405,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
|
||||
//#region IWorkingCopy
|
||||
|
||||
public get resource() {
|
||||
// Make sure each custom editor has a unique resource for backup and edits
|
||||
return MainThreadCustomEditorModel.toWorkingCopyResource(this._viewType, this._editorResource);
|
||||
}
|
||||
|
||||
// Make sure each custom editor has a unique resource for backup and edits
|
||||
private static toWorkingCopyResource(viewType: string, resource: URI) {
|
||||
const authority = viewType.replace(/[^a-z0-9\-_]/gi, '-');
|
||||
const path = `/${multibyteAwareBtoa(resource.with({ query: null, fragment: null }).toString(true))}`;
|
||||
@@ -403,10 +435,6 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
return this._fromBackup;
|
||||
}
|
||||
|
||||
public isOrphaned(): boolean {
|
||||
return this._inOrphaned;
|
||||
}
|
||||
|
||||
private isUntitled() {
|
||||
return this._editorResource.scheme === Schemas.untitled;
|
||||
}
|
||||
@@ -417,66 +445,12 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
private readonly _onDidChangeContent: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeContent: Event<void> = this._onDidChangeContent.event;
|
||||
|
||||
readonly onDidChangeReadonly = Event.None;
|
||||
|
||||
//#endregion
|
||||
|
||||
private async onDidFilesChange(e: FileChangesEvent): Promise<void> {
|
||||
let fileEventImpactsModel = false;
|
||||
let newInOrphanModeGuess: boolean | undefined;
|
||||
|
||||
// If we are currently orphaned, we check if the model file was added back
|
||||
if (this._inOrphaned) {
|
||||
const modelFileAdded = e.contains(this.editorResource, FileChangeType.ADDED);
|
||||
if (modelFileAdded) {
|
||||
newInOrphanModeGuess = false;
|
||||
fileEventImpactsModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise we check if the model file was deleted
|
||||
else {
|
||||
const modelFileDeleted = e.contains(this.editorResource, FileChangeType.DELETED);
|
||||
if (modelFileDeleted) {
|
||||
newInOrphanModeGuess = true;
|
||||
fileEventImpactsModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileEventImpactsModel && this._inOrphaned !== newInOrphanModeGuess) {
|
||||
let newInOrphanModeValidated: boolean = false;
|
||||
if (newInOrphanModeGuess) {
|
||||
// We have received reports of users seeing delete events even though the file still
|
||||
// exists (network shares issue: https://github.com/microsoft/vscode/issues/13665).
|
||||
// Since we do not want to mark the model as orphaned, we have to check if the
|
||||
// file is really gone and not just a faulty file event.
|
||||
await timeout(100);
|
||||
|
||||
if (this.#isDisposed) {
|
||||
newInOrphanModeValidated = true;
|
||||
} else {
|
||||
const exists = await this._fileService.exists(this.editorResource);
|
||||
newInOrphanModeValidated = !exists;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._inOrphaned !== newInOrphanModeValidated && !this.#isDisposed) {
|
||||
this.setOrphaned(newInOrphanModeValidated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setOrphaned(orphaned: boolean): void {
|
||||
if (this._inOrphaned !== orphaned) {
|
||||
this._inOrphaned = orphaned;
|
||||
this._onDidChangeOrphaned.fire();
|
||||
}
|
||||
}
|
||||
|
||||
public isEditable(): boolean {
|
||||
return this._editable;
|
||||
}
|
||||
|
||||
public isOnReadonlyFileSystem(): boolean {
|
||||
return this._fileService.hasCapability(this.editorResource, FileSystemProviderCapabilities.Readonly);
|
||||
public isReadonly(): boolean {
|
||||
return !this._editable;
|
||||
}
|
||||
|
||||
public get viewType() {
|
||||
@@ -569,7 +543,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
}
|
||||
}
|
||||
|
||||
public async revert(_options?: IRevertOptions) {
|
||||
public async revert(options?: IRevertOptions) {
|
||||
if (!this._editable) {
|
||||
return;
|
||||
}
|
||||
@@ -578,7 +552,10 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
return;
|
||||
}
|
||||
|
||||
this._proxy.$revert(this._editorResource, this.viewType, CancellationToken.None);
|
||||
if (!options?.soft) {
|
||||
this._proxy.$revert(this._editorResource, this.viewType, CancellationToken.None);
|
||||
}
|
||||
|
||||
this.change(() => {
|
||||
this._isDirtyFromContentChange = false;
|
||||
this._fromBackup = false;
|
||||
@@ -650,7 +627,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
return true;
|
||||
} else {
|
||||
// Since the editor is readonly, just copy the file over
|
||||
await this._fileService.copy(resource, targetResource, false /* overwrite */);
|
||||
await this.fileService.copy(resource, targetResource, false /* overwrite */);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -698,6 +675,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
pendingState.operation.cancel();
|
||||
});
|
||||
|
||||
let errorMessage = '';
|
||||
try {
|
||||
const backupId = await pendingState.operation;
|
||||
// Make sure state has not changed in the meantime
|
||||
@@ -716,12 +694,15 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
if (this._hotExitState === pendingState) {
|
||||
this._hotExitState = HotExitState.NotAllowed;
|
||||
}
|
||||
if (e.message) {
|
||||
errorMessage = e.message;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._hotExitState === HotExitState.Allowed) {
|
||||
return backupData;
|
||||
}
|
||||
|
||||
throw new Error('Cannot back up in this state');
|
||||
throw new Error(`Cannot back up in this state: ${errorMessage}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +329,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
type: session.configuration.type,
|
||||
name: session.name,
|
||||
folderUri: session.root ? session.root.uri : undefined,
|
||||
configuration: session.configuration
|
||||
configuration: session.configuration,
|
||||
parent: session.parentSession?.getId(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/commo
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IPathService } from 'vs/workbench/services/path/common/pathService';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
|
||||
export class BoundModelReferenceCollection {
|
||||
|
||||
@@ -105,52 +106,39 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
private _onIsCaughtUpWithContentChanges = this._register(new Emitter<URI>());
|
||||
public readonly onIsCaughtUpWithContentChanges = this._onIsCaughtUpWithContentChanges.event;
|
||||
|
||||
private readonly _modelService: IModelService;
|
||||
private readonly _textModelResolverService: ITextModelService;
|
||||
private readonly _textFileService: ITextFileService;
|
||||
private readonly _fileService: IFileService;
|
||||
private readonly _environmentService: IWorkbenchEnvironmentService;
|
||||
private readonly _uriIdentityService: IUriIdentityService;
|
||||
|
||||
private _modelTrackers: { [modelUrl: string]: ModelTracker; };
|
||||
private readonly _proxy: ExtHostDocumentsShape;
|
||||
private readonly _modelIsSynced = new Set<string>();
|
||||
private readonly _modelTrackers = new ResourceMap<ModelTracker>();
|
||||
private readonly _modelIsSynced = new ResourceMap<void>();
|
||||
private readonly _modelReferenceCollection: BoundModelReferenceCollection;
|
||||
|
||||
constructor(
|
||||
documentsAndEditors: MainThreadDocumentsAndEditors,
|
||||
extHostContext: IExtHostContext,
|
||||
@IModelService modelService: IModelService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IFileService fileService: IFileService,
|
||||
@ITextModelService textModelResolverService: ITextModelService,
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
@ITextFileService private readonly _textFileService: ITextFileService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@ITextModelService private readonly _textModelResolverService: ITextModelService,
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@IUriIdentityService private readonly _uriIdentityService: IUriIdentityService,
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService,
|
||||
@IPathService private readonly _pathService: IPathService
|
||||
) {
|
||||
super();
|
||||
this._modelService = modelService;
|
||||
this._textModelResolverService = textModelResolverService;
|
||||
this._textFileService = textFileService;
|
||||
this._fileService = fileService;
|
||||
this._environmentService = environmentService;
|
||||
this._uriIdentityService = uriIdentityService;
|
||||
|
||||
this._modelReferenceCollection = this._register(new BoundModelReferenceCollection(uriIdentityService.extUri));
|
||||
this._modelReferenceCollection = this._register(new BoundModelReferenceCollection(_uriIdentityService.extUri));
|
||||
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocuments);
|
||||
|
||||
this._register(documentsAndEditors.onDocumentAdd(models => models.forEach(this._onModelAdded, this)));
|
||||
this._register(documentsAndEditors.onDocumentRemove(urls => urls.forEach(this._onModelRemoved, this)));
|
||||
this._register(modelService.onModelModeChanged(this._onModelModeChanged, this));
|
||||
this._register(_modelService.onModelModeChanged(this._onModelModeChanged, this));
|
||||
|
||||
this._register(textFileService.files.onDidSave(e => {
|
||||
this._register(_textFileService.files.onDidSave(e => {
|
||||
if (this._shouldHandleFileEvent(e.model.resource)) {
|
||||
this._proxy.$acceptModelSaved(e.model.resource);
|
||||
}
|
||||
}));
|
||||
this._register(textFileService.files.onDidChangeDirty(m => {
|
||||
this._register(_textFileService.files.onDidChangeDirty(m => {
|
||||
if (this._shouldHandleFileEvent(m.resource)) {
|
||||
this._proxy.$acceptDirtyStateChanged(m.resource, m.isDirty());
|
||||
}
|
||||
@@ -167,22 +155,18 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._modelTrackers = Object.create(null);
|
||||
}
|
||||
|
||||
public override dispose(): void {
|
||||
Object.keys(this._modelTrackers).forEach((modelUrl) => {
|
||||
this._modelTrackers[modelUrl].dispose();
|
||||
});
|
||||
this._modelTrackers = Object.create(null);
|
||||
dispose(this._modelTrackers.values());
|
||||
this._modelTrackers.clear();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public isCaughtUpWithContentChanges(resource: URI): boolean {
|
||||
const modelUrl = resource.toString();
|
||||
if (this._modelTrackers[modelUrl]) {
|
||||
return this._modelTrackers[modelUrl].isCaughtUpWithContentChanges();
|
||||
const tracker = this._modelTrackers.get(resource);
|
||||
if (tracker) {
|
||||
return tracker.isCaughtUpWithContentChanges();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -198,28 +182,25 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
// don't synchronize too large models
|
||||
return;
|
||||
}
|
||||
const modelUrl = model.uri;
|
||||
this._modelIsSynced.add(modelUrl.toString());
|
||||
this._modelTrackers[modelUrl.toString()] = new ModelTracker(model, this._onIsCaughtUpWithContentChanges, this._proxy, this._textFileService);
|
||||
this._modelIsSynced.set(model.uri, undefined);
|
||||
this._modelTrackers.set(model.uri, new ModelTracker(model, this._onIsCaughtUpWithContentChanges, this._proxy, this._textFileService));
|
||||
}
|
||||
|
||||
private _onModelModeChanged(event: { model: ITextModel; oldModeId: string; }): void {
|
||||
let { model } = event;
|
||||
const modelUrl = model.uri;
|
||||
if (!this._modelIsSynced.has(modelUrl.toString())) {
|
||||
if (!this._modelIsSynced.has(model.uri)) {
|
||||
return;
|
||||
}
|
||||
this._proxy.$acceptModelModeChanged(model.uri, model.getLanguageIdentifier().language);
|
||||
}
|
||||
|
||||
private _onModelRemoved(modelUrl: URI): void {
|
||||
const strModelUrl = modelUrl.toString();
|
||||
if (!this._modelIsSynced.has(strModelUrl)) {
|
||||
if (!this._modelIsSynced.has(modelUrl)) {
|
||||
return;
|
||||
}
|
||||
this._modelIsSynced.delete(strModelUrl);
|
||||
this._modelTrackers[strModelUrl].dispose();
|
||||
delete this._modelTrackers[strModelUrl];
|
||||
this._modelIsSynced.delete(modelUrl);
|
||||
this._modelTrackers.get(modelUrl)!.dispose();
|
||||
this._modelTrackers.delete(modelUrl);
|
||||
}
|
||||
|
||||
// --- from extension host process
|
||||
@@ -252,7 +233,7 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
return Promise.reject(new Error(`cannot open ${canonicalUri.toString()}`));
|
||||
} else if (!extUri.isEqual(documentUri, canonicalUri)) {
|
||||
return Promise.reject(new Error(`cannot open ${canonicalUri.toString()}. Detail: Actual document opened as ${documentUri.toString()}`));
|
||||
} else if (!this._modelIsSynced.has(canonicalUri.toString())) {
|
||||
} else if (!this._modelIsSynced.has(canonicalUri)) {
|
||||
return Promise.reject(new Error(`cannot open ${canonicalUri.toString()}. Detail: Files above 50MB cannot be synchronized with extensions.`));
|
||||
} else {
|
||||
return canonicalUri;
|
||||
@@ -291,7 +272,7 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
}).then(model => {
|
||||
const resource = model.resource;
|
||||
|
||||
if (!this._modelIsSynced.has(resource.toString())) {
|
||||
if (!this._modelIsSynced.has(resource)) {
|
||||
throw new Error(`expected URI ${resource.toString()} to have come to LIFE`);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor'
|
||||
import { MainThreadTextEditors } from 'vs/workbench/api/browser/mainThreadEditors';
|
||||
import { ExtHostContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IExtHostContext, IModelAddedData, ITextEditorAddData, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { editorGroupToViewColumn, EditorGroupColumn, IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
@@ -30,7 +30,6 @@ import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/commo
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IPathService } from 'vs/workbench/services/path/common/pathService';
|
||||
import { editorGroupToViewColumn, EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { diffSets, diffMaps } from 'vs/base/common/collections';
|
||||
|
||||
|
||||
@@ -410,7 +409,7 @@ export class MainThreadDocumentsAndEditors {
|
||||
};
|
||||
}
|
||||
|
||||
private _findEditorPosition(editor: MainThreadTextEditor): EditorViewColumn | undefined {
|
||||
private _findEditorPosition(editor: MainThreadTextEditor): EditorGroupColumn | undefined {
|
||||
for (const editorPane of this._editorService.visibleEditorPanes) {
|
||||
if (editor.matches(editorPane)) {
|
||||
return editorGroupToViewColumn(this._editorGroupService, editorPane.group);
|
||||
|
||||
@@ -23,4 +23,4 @@ export class MainThreadDownloadService extends Disposable implements MainThreadD
|
||||
return this.downloadService.download(URI.revive(uri), URI.revive(to));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +414,7 @@ export class MainThreadTextEditor {
|
||||
if (!this._codeEditor) {
|
||||
return;
|
||||
}
|
||||
this._codeEditor.setDecorations(key, ranges);
|
||||
this._codeEditor.setDecorations('exthost-api', key, ranges);
|
||||
}
|
||||
|
||||
public setDecorationsFast(key: string, _ranges: number[]): void {
|
||||
|
||||
@@ -7,8 +7,9 @@ import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle'
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostContext, IExtHostEditorTabsShape, IExtHostContext, MainContext, IEditorTabDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { Verbosity } from 'vs/workbench/common/editor';
|
||||
import { EditorResourceAccessor, Verbosity } from 'vs/workbench/common/editor';
|
||||
import { GroupChangeKind, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export interface ITabInfo {
|
||||
name: string;
|
||||
@@ -27,11 +28,12 @@ export class MainThreadEditorTabs {
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IEditorGroupsService private readonly _editorGroupsService: IEditorGroupsService,
|
||||
@IEditorService editorService: IEditorService
|
||||
) {
|
||||
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostEditorTabs);
|
||||
|
||||
this._editorGroupsService.groups.forEach(this._subscribeToGroup, this);
|
||||
this._editorGroupsService.whenReady.then(() => this._editorGroupsService.groups.forEach(this._subscribeToGroup, this));
|
||||
this._dispoables.add(_editorGroupsService.onDidAddGroup(this._subscribeToGroup, this));
|
||||
this._dispoables.add(_editorGroupsService.onDidRemoveGroup(e => {
|
||||
const subscription = this._groups.get(e);
|
||||
@@ -41,6 +43,7 @@ export class MainThreadEditorTabs {
|
||||
this._pushEditorTabs();
|
||||
}
|
||||
}));
|
||||
this._dispoables.add(editorService.onDidActiveEditorChange(this._pushEditorTabs, this));
|
||||
this._pushEditorTabs();
|
||||
}
|
||||
|
||||
@@ -69,7 +72,8 @@ export class MainThreadEditorTabs {
|
||||
tabs.push({
|
||||
group: group.id,
|
||||
name: editor.getTitle(Verbosity.SHORT) ?? '',
|
||||
resource: editor.resource
|
||||
resource: EditorResourceAccessor.getOriginalUri(editor) ?? editor.resource,
|
||||
isActive: (this._editorGroupsService.activeGroup === group) && group.isActive(editor)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] {
|
||||
if (!data?.edits) {
|
||||
@@ -249,10 +250,10 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
|
||||
return Promise.resolve(editor.insertSnippet(template, ranges, opts));
|
||||
}
|
||||
|
||||
$registerTextEditorDecorationType(key: string, options: IDecorationRenderOptions): void {
|
||||
$registerTextEditorDecorationType(extensionId: ExtensionIdentifier, key: string, options: IDecorationRenderOptions): void {
|
||||
key = `${this._instanceId}-${key}`;
|
||||
this._registeredDecorationTypes[key] = true;
|
||||
this._codeEditorService.registerDecorationType(key, options);
|
||||
this._codeEditorService.registerDecorationType(`exthost-api-${extensionId}`, key, options);
|
||||
}
|
||||
|
||||
$removeTextEditorDecorationType(key: string): void {
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensio
|
||||
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ITimerService } from 'vs/workbench/services/timer/browser/timerService';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadExtensionService)
|
||||
export class MainThreadExtensionService implements MainThreadExtensionServiceShape {
|
||||
@@ -35,6 +36,7 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
|
||||
@IHostService private readonly _hostService: IHostService,
|
||||
@IWorkbenchExtensionEnablementService private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService,
|
||||
@ITimerService private readonly _timerService: ITimerService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IWorkbenchEnvironmentService protected readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
) {
|
||||
this._extensionHostKind = extHostContext.extensionHostKind;
|
||||
@@ -105,15 +107,36 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
|
||||
});
|
||||
} else {
|
||||
const enablementState = this._extensionEnablementService.getEnablementState(missingInstalledDependency);
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: localize('disabledDep', "Cannot activate the '{0}' extension because it depends on the '{1}' extension, which is disabled. Would you like to enable the extension and reload the window?", extName, missingInstalledDependency.manifest.displayName || missingInstalledDependency.manifest.name),
|
||||
actions: {
|
||||
primary: [new Action('enable', localize('enable dep', "Enable and Reload"), '', true,
|
||||
() => this._extensionEnablementService.setEnablement([missingInstalledDependency], enablementState === EnablementState.DisabledGlobally ? EnablementState.EnabledGlobally : EnablementState.EnabledWorkspace)
|
||||
.then(() => this._hostService.reload(), e => this._notificationService.error(e)))]
|
||||
}
|
||||
});
|
||||
if (enablementState === EnablementState.DisabledByVirtualWorkspace) {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: localize('notSupportedInWorkspace', "Cannot activate the '{0}' extension because it depends on the '{1}' extension which is not supported in the current workspace", extName, missingInstalledDependency.manifest.displayName || missingInstalledDependency.manifest.name),
|
||||
});
|
||||
} else if (enablementState === EnablementState.DisabledByTrustRequirement) {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: localize('restrictedMode', "Cannot activate the '{0}' extension because it depends on the '{1}' extension which is not supported in Restricted Mode", extName, missingInstalledDependency.manifest.displayName || missingInstalledDependency.manifest.name),
|
||||
actions: {
|
||||
primary: [new Action('manageWorkspaceTrust', localize('manageWorkspaceTrust', "Manage Workspace Trust"), '', true,
|
||||
() => this._commandService.executeCommand('workbench.trust.manage'))]
|
||||
}
|
||||
});
|
||||
} else if (this._extensionEnablementService.canChangeEnablement(missingInstalledDependency)) {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: localize('disabledDep', "Cannot activate the '{0}' extension because it depends on the '{1}' extension which is disabled. Would you like to enable the extension and reload the window?", extName, missingInstalledDependency.manifest.displayName || missingInstalledDependency.manifest.name),
|
||||
actions: {
|
||||
primary: [new Action('enable', localize('enable dep', "Enable and Reload"), '', true,
|
||||
() => this._extensionEnablementService.setEnablement([missingInstalledDependency], enablementState === EnablementState.DisabledGlobally ? EnablementState.EnabledGlobally : EnablementState.EnabledWorkspace)
|
||||
.then(() => this._hostService.reload(), e => this._notificationService.error(e)))]
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: localize('disabledDepNoAction', "Cannot activate the '{0}' extension because it depends on the '{1}' extension which is disabled.", extName, missingInstalledDependency.manifest.displayName || missingInstalledDependency.manifest.name),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions, FileOpenOptions, IFileStat, FileOperationError, FileOperationResult, FileSystemProviderErrorCode, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithFileFolderCopyCapability } from 'vs/platform/files/common/files';
|
||||
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions, FileOpenOptions, IFileStat, FileOperationError, FileOperationResult, FileSystemProviderErrorCode, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithFileFolderCopyCapability, FilePermission } from 'vs/platform/files/common/files';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../common/extHost.protocol';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
@@ -65,6 +65,7 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
ctime: stat.ctime,
|
||||
mtime: stat.mtime,
|
||||
size: stat.size,
|
||||
permissions: MainThreadFileSystem._asFilePermission(stat),
|
||||
type: MainThreadFileSystem._asFileType(stat)
|
||||
};
|
||||
}).catch(MainThreadFileSystem._handleError);
|
||||
@@ -95,6 +96,13 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
return res;
|
||||
}
|
||||
|
||||
private static _asFilePermission(stat: IFileStat): FilePermission | undefined {
|
||||
if (stat.readonly) {
|
||||
return FilePermission.Readonly;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
$readFile(uri: UriComponents): Promise<VSBuffer> {
|
||||
return this._fileService.readFile(URI.revive(uri)).then(file => file.value).catch(MainThreadFileSystem._handleError);
|
||||
}
|
||||
|
||||
@@ -33,4 +33,4 @@ export class MainThreadLabelService implements MainThreadLabelServiceShape {
|
||||
dispose(): void {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Position as EditorPosition } from 'vs/editor/common/core/position';
|
||||
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto, IdentifiableInlineCompletions, IdentifiableInlineCompletion } from '../common/extHost.protocol';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
@@ -471,7 +471,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
provideCompletionItems: async (model: ITextModel, position: EditorPosition, context: modes.CompletionContext, token: CancellationToken): Promise<modes.CompletionList | undefined> => {
|
||||
const result = await this._proxy.$provideCompletionItems(handle, model.uri, position, context, token);
|
||||
if (!result) {
|
||||
return <any>result;
|
||||
return <any>result; // {{SQL CARBON EDIT}}
|
||||
}
|
||||
return {
|
||||
suggestions: result[ISuggestResultDtoField.completions].map(d => MainThreadLanguageFeatures._inflateSuggestDto(result[ISuggestResultDtoField.defaultRanges], d)),
|
||||
@@ -500,6 +500,21 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
this._registrations.set(handle, modes.CompletionProviderRegistry.register(selector, provider));
|
||||
}
|
||||
|
||||
$registerInlineCompletionsSupport(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
const provider: modes.InlineCompletionsProvider<IdentifiableInlineCompletions> = {
|
||||
provideInlineCompletions: async (model: ITextModel, position: EditorPosition, context: modes.InlineCompletionContext, token: CancellationToken): Promise<IdentifiableInlineCompletions | undefined> => {
|
||||
return this._proxy.$provideInlineCompletions(handle, model.uri, position, context, token);
|
||||
},
|
||||
handleItemDidShow: async (completions: IdentifiableInlineCompletions, item: IdentifiableInlineCompletion): Promise<void> => {
|
||||
return this._proxy.$handleInlineCompletionDidShow(handle, completions.pid, item.idx);
|
||||
},
|
||||
freeInlineCompletions: (completions: IdentifiableInlineCompletions): void => {
|
||||
this._proxy.$freeInlineCompletionsList(handle, completions.pid);
|
||||
}
|
||||
};
|
||||
this._registrations.set(handle, modes.InlineCompletionsProviderRegistry.register(selector, provider));
|
||||
}
|
||||
|
||||
// --- parameter hints
|
||||
|
||||
$registerSignatureHelpProvider(handle: number, selector: IDocumentFilterDto[], metadata: ISignatureHelpProviderMetadataDto): void {
|
||||
@@ -525,10 +540,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- inline hints
|
||||
|
||||
$registerInlineHintsProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void {
|
||||
const provider = <modes.InlineHintsProvider>{
|
||||
provideInlineHints: async (model: ITextModel, range: EditorRange, token: CancellationToken): Promise<modes.InlineHint[] | undefined> => {
|
||||
const result = await this._proxy.$provideInlineHints(handle, model.uri, range, token);
|
||||
$registerInlayHintsProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void {
|
||||
const provider = <modes.InlayHintsProvider>{
|
||||
provideInlayHints: async (model: ITextModel, range: EditorRange, token: CancellationToken): Promise<modes.InlayHint[] | undefined> => {
|
||||
const result = await this._proxy.$provideInlayHints(handle, model.uri, range, token);
|
||||
return result?.hints;
|
||||
}
|
||||
};
|
||||
@@ -536,13 +551,13 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
if (typeof eventHandle === 'number') {
|
||||
const emitter = new Emitter<void>();
|
||||
this._registrations.set(eventHandle, emitter);
|
||||
provider.onDidChangeInlineHints = emitter.event;
|
||||
provider.onDidChangeInlayHints = emitter.event;
|
||||
}
|
||||
|
||||
this._registrations.set(handle, modes.InlineHintsProviderRegistry.register(selector, provider));
|
||||
this._registrations.set(handle, modes.InlayHintsProviderRegistry.register(selector, provider));
|
||||
}
|
||||
|
||||
$emitInlineHintsEvent(eventHandle: number, event?: any): void {
|
||||
$emitInlayHintsEvent(eventHandle: number, event?: any): void {
|
||||
const obj = this._registrations.get(eventHandle);
|
||||
if (obj instanceof Emitter) {
|
||||
obj.fire(event);
|
||||
|
||||
@@ -6,13 +6,11 @@
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
|
||||
import { NotebookSelector } from 'vs/workbench/contrib/notebook/common/notebookSelector';
|
||||
import { INotebookCellStatusBarItemProvider, INotebookExclusiveDocumentFilter, NotebookDataDto, TransientCellMetadata, TransientDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookCellStatusBarItemProvider, INotebookContributionData, NotebookDataDto, TransientCellMetadata, TransientDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookContentProvider, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, MainContext, MainThreadNotebookShape, NotebookExtensionDescription } from '../common/extHost.protocol';
|
||||
|
||||
@@ -43,13 +41,8 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
dispose(this._notebookSerializer.values());
|
||||
}
|
||||
|
||||
async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, options: {
|
||||
transientOutputs: boolean;
|
||||
transientCellMetadata: TransientCellMetadata;
|
||||
transientDocumentMetadata: TransientDocumentMetadata;
|
||||
viewOptions?: { displayName: string; filenamePattern: (string | IRelativePattern | INotebookExclusiveDocumentFilter)[]; exclusive: boolean; };
|
||||
}): Promise<void> {
|
||||
let contentOptions = { transientOutputs: options.transientOutputs, transientCellMetadata: options.transientCellMetadata, transientDocumentMetadata: options.transientDocumentMetadata };
|
||||
async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, data: INotebookContributionData | undefined): Promise<void> {
|
||||
let contentOptions = { ...options };
|
||||
|
||||
const controller: INotebookContentProvider = {
|
||||
get options() {
|
||||
@@ -60,7 +53,6 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
contentOptions.transientDocumentMetadata = newOptions.transientDocumentMetadata;
|
||||
contentOptions.transientOutputs = newOptions.transientOutputs;
|
||||
},
|
||||
viewOptions: options.viewOptions,
|
||||
open: async (uri: URI, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken) => {
|
||||
const data = await this._proxy.$openNotebook(viewType, uri, backupId, untitledDocumentData, token);
|
||||
return {
|
||||
@@ -79,7 +71,11 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
}
|
||||
};
|
||||
|
||||
const disposable = this._notebookService.registerNotebookController(viewType, extension, controller);
|
||||
const disposable = new DisposableStore();
|
||||
disposable.add(this._notebookService.registerNotebookController(viewType, extension, controller));
|
||||
if (data) {
|
||||
disposable.add(this._notebookService.registerContributedNotebookType(viewType, data));
|
||||
}
|
||||
this._notebookProviders.set(viewType, { controller, disposable });
|
||||
}
|
||||
|
||||
@@ -104,7 +100,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
}
|
||||
}
|
||||
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions): void {
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, data: INotebookContributionData | undefined): void {
|
||||
const registration = this._notebookService.registerNotebookSerializer(viewType, extension, {
|
||||
options,
|
||||
dataToNotebook: (data: VSBuffer): Promise<NotebookDataDto> => {
|
||||
@@ -114,7 +110,12 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
return this._proxy.$notebookToData(handle, data, CancellationToken.None);
|
||||
}
|
||||
});
|
||||
this._notebookSerializer.set(handle, registration);
|
||||
const disposables = new DisposableStore();
|
||||
disposables.add(registration);
|
||||
if (data) {
|
||||
disposables.add(this._notebookService.registerContributedNotebookType(viewType, data));
|
||||
}
|
||||
this._notebookSerializer.set(handle, disposables);
|
||||
}
|
||||
|
||||
$unregisterNotebookSerializer(handle: number): void {
|
||||
@@ -129,7 +130,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
}
|
||||
}
|
||||
|
||||
async $registerNotebookCellStatusBarItemProvider(handle: number, eventHandle: number | undefined, selector: NotebookSelector): Promise<void> {
|
||||
async $registerNotebookCellStatusBarItemProvider(handle: number, eventHandle: number | undefined, viewType: string): Promise<void> {
|
||||
const that = this;
|
||||
const provider: INotebookCellStatusBarItemProvider = {
|
||||
async provideCellStatusBarItems(uri: URI, index: number, token: CancellationToken) {
|
||||
@@ -143,7 +144,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape {
|
||||
}
|
||||
};
|
||||
},
|
||||
selector: selector
|
||||
viewType
|
||||
};
|
||||
|
||||
if (typeof eventHandle === 'number') {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -9,19 +9,21 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { BoundModelReferenceCollection } from 'vs/workbench/api/browser/mainThreadDocuments';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { IImmediateCellEditOperation, IMainCellDto, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IImmediateCellEditOperation, IMainCellDto, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, MainThreadNotebookDocumentsShape } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostNotebookDocumentsShape, IExtHostContext, MainThreadNotebookDocumentsShape } from '../common/extHost.protocol';
|
||||
import { MainThreadNotebooksAndEditors } from 'vs/workbench/api/browser/mainThreadNotebookDocumentsAndEditors';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
|
||||
export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsShape {
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
private readonly _proxy: ExtHostNotebookShape;
|
||||
private readonly _proxy: ExtHostNotebookDocumentsShape;
|
||||
private readonly _documentEventListenersMapping = new ResourceMap<DisposableStore>();
|
||||
private readonly _modelReferenceCollection: BoundModelReferenceCollection;
|
||||
|
||||
@@ -32,7 +34,7 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
@INotebookEditorModelResolverService private readonly _notebookEditorModelResolverService: INotebookEditorModelResolverService,
|
||||
@IUriIdentityService private readonly _uriIdentityService: IUriIdentityService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook);
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebookDocuments);
|
||||
this._modelReferenceCollection = new BoundModelReferenceCollection(this._uriIdentityService.extUri);
|
||||
|
||||
notebooksAndEditors.onDidAddNotebooks(this._handleNotebooksAdded, this, this._disposables);
|
||||
@@ -47,7 +49,6 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
this._disposables.dispose();
|
||||
this._modelReferenceCollection.dispose();
|
||||
dispose(this._documentEventListenersMapping.values());
|
||||
|
||||
}
|
||||
|
||||
private _handleNotebooksAdded(notebooks: readonly NotebookTextModel[]): void {
|
||||
@@ -114,18 +115,59 @@ export class MainThreadNotebookDocuments implements MainThreadNotebookDocumentsS
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: cell.outputs,
|
||||
metadata: cell.metadata
|
||||
metadata: cell.metadata,
|
||||
internalMetadata: cell.internalMetadata,
|
||||
};
|
||||
}
|
||||
|
||||
async $tryOpenDocument(uriComponents: UriComponents): Promise<URI> {
|
||||
async $tryCreateNotebook(options: { viewType: string, content?: NotebookDataDto }): Promise<UriComponents> {
|
||||
|
||||
const info = this._notebookService.getContributedNotebookType(options.viewType);
|
||||
if (!info) {
|
||||
throw new Error('UNKNOWN view type: ' + options.viewType);
|
||||
}
|
||||
|
||||
// find a free URI for the untitled case
|
||||
const suffix = NotebookProviderInfo.possibleFileEnding(info.selectors) ?? '';
|
||||
let uri: URI;
|
||||
for (let counter = 1; ; counter++) {
|
||||
let candidate = URI.from({ scheme: Schemas.untitled, path: `Untitled-${counter}${suffix}`, query: options.viewType });
|
||||
if (!this._notebookService.getNotebookTextModel(candidate)) {
|
||||
uri = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const ref = await this._notebookEditorModelResolverService.resolve(uri, options.viewType);
|
||||
|
||||
// untitled notebooks are disposed when they get saved. we should not hold a reference
|
||||
// to such a disposed notebook and therefore dispose the reference as well
|
||||
ref.object.notebook.onWillDispose(() => {
|
||||
ref.dispose();
|
||||
});
|
||||
|
||||
// untitled notebooks are dirty by default
|
||||
this._proxy.$acceptDirtyStateChanged(uri, true);
|
||||
|
||||
// apply content changes... slightly HACKY -> this triggers a change event
|
||||
if (options.content) {
|
||||
ref.object.notebook.reset(
|
||||
options.content.cells,
|
||||
options.content.metadata,
|
||||
ref.object.notebook.transientOptions
|
||||
);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
async $tryOpenNotebook(uriComponents: UriComponents): Promise<URI> {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const ref = await this._notebookEditorModelResolverService.resolve(uri, undefined);
|
||||
this._modelReferenceCollection.add(uri, ref);
|
||||
return uri;
|
||||
}
|
||||
|
||||
async $trySaveDocument(uriComponents: UriComponents) {
|
||||
async $trySaveNotebook(uriComponents: UriComponents) {
|
||||
const uri = URI.revive(uriComponents);
|
||||
|
||||
const ref = await this._notebookEditorModelResolverService.resolve(uri);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { diffMaps, diffSets } from 'vs/base/common/collections';
|
||||
@@ -30,7 +30,7 @@ interface INotebookAndEditorDelta {
|
||||
}
|
||||
|
||||
class NotebookAndEditorState {
|
||||
static compute(before: NotebookAndEditorState | undefined, after: NotebookAndEditorState): INotebookAndEditorDelta {
|
||||
static delta(before: NotebookAndEditorState | undefined, after: NotebookAndEditorState): INotebookAndEditorDelta {
|
||||
if (!before) {
|
||||
return {
|
||||
addedDocuments: [...after.documents],
|
||||
@@ -107,7 +107,7 @@ export class MainThreadNotebooksAndEditors {
|
||||
extHostContext.set(MainContext.MainThreadNotebookDocuments, this._mainThreadNotebooks);
|
||||
extHostContext.set(MainContext.MainThreadNotebookEditors, this._mainThreadEditors);
|
||||
|
||||
this._notebookService.onDidCreateNotebookDocument(() => this._updateState(), this, this._disposables);
|
||||
this._notebookService.onWillAddNotebookDocument(() => this._updateState(), this, this._disposables);
|
||||
this._notebookService.onDidRemoveNotebookDocument(() => this._updateState(), this, this._disposables);
|
||||
this._editorService.onDidActiveEditorChange(() => this._updateState(), this, this._disposables);
|
||||
this._editorService.onDidVisibleEditorsChange(() => this._updateState(), this, this._disposables);
|
||||
@@ -170,7 +170,7 @@ export class MainThreadNotebooksAndEditors {
|
||||
}
|
||||
|
||||
const newState = new NotebookAndEditorState(new Set(this._notebookService.listNotebookDocuments()), editors, activeEditor, visibleEditorsMap);
|
||||
this._onDelta(NotebookAndEditorState.compute(this._currentState, newState));
|
||||
this._onDelta(NotebookAndEditorState.delta(this._currentState, newState));
|
||||
this._currentState = newState;
|
||||
}
|
||||
|
||||
@@ -234,7 +234,8 @@ export class MainThreadNotebooksAndEditors {
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: cell.outputs,
|
||||
metadata: cell.metadata
|
||||
metadata: cell.metadata,
|
||||
internalMetadata: cell.internalMetadata,
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { getNotebookEditorFromEditorPane, INotebookEditor, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { getNotebookEditorFromEditorPane, INotebookEditor, INotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookDocumentShowOptions, INotebookEditorViewColumnInfo, MainThreadNotebookEditorsShape, NotebookEditorRevealType } from '../common/extHost.protocol';
|
||||
import { ExtHostContext, ExtHostNotebookEditorsShape, IExtHostContext, INotebookDocumentShowOptions, INotebookEditorViewColumnInfo, MainThreadNotebookEditorsShape, NotebookEditorRevealType } from '../common/extHost.protocol';
|
||||
import { MainThreadNotebooksAndEditors } from 'vs/workbench/api/browser/mainThreadNotebookDocumentsAndEditors';
|
||||
import { ICellEditOperation, INotebookDecorationRenderOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
@@ -36,7 +36,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
private readonly _proxy: ExtHostNotebookShape;
|
||||
private readonly _proxy: ExtHostNotebookEditorsShape;
|
||||
private readonly _mainThreadEditors = new Map<string, MainThreadNotebook>();
|
||||
|
||||
private _currentViewColumnInfo?: INotebookEditorViewColumnInfo;
|
||||
@@ -50,7 +50,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
@INotebookEditorService private readonly _notebookEditorService: INotebookEditorService,
|
||||
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook);
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebookEditors);
|
||||
|
||||
notebooksAndEditors.onDidAddEditors(this._handleEditorsAdded, this, this._disposables);
|
||||
notebooksAndEditors.onDidRemoveEditors(this._handleEditorsRemoved, this, this._disposables);
|
||||
@@ -121,10 +121,8 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
return editor.textModel.applyEdits(cellEdits, true, undefined, () => undefined, undefined);
|
||||
}
|
||||
|
||||
|
||||
|
||||
async $tryShowNotebookDocument(resource: UriComponents, viewType: string, options: INotebookDocumentShowOptions): Promise<string> {
|
||||
const editorOptions = new NotebookEditorOptions({
|
||||
const editorOptions: INotebookEditorOptions = {
|
||||
cellSelections: options.selections,
|
||||
preserveFocus: options.preserveFocus,
|
||||
pinned: options.pinned,
|
||||
@@ -132,8 +130,8 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
// preserve pre 1.38 behaviour to not make group active when preserveFocus: true
|
||||
// but make sure to restore the editor to fix https://github.com/microsoft/vscode/issues/79633
|
||||
activation: options.preserveFocus ? EditorActivation.RESTORE : undefined,
|
||||
override: EditorOverride.DISABLED,
|
||||
});
|
||||
override: EditorOverride.DISABLED
|
||||
};
|
||||
|
||||
const input = NotebookEditorInput.create(this._instantiationService, URI.revive(resource), viewType);
|
||||
const editorPane = await this._editorService.openEditor(input, editorOptions, options.position);
|
||||
@@ -188,4 +186,12 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape
|
||||
notebookEditor.setEditorDecorations(key, range);
|
||||
}
|
||||
}
|
||||
|
||||
$trySetSelections(id: string, ranges: ICellRange[]): void {
|
||||
const editor = this._notebookEditorService.getNotebookEditor(id);
|
||||
if (editor) {
|
||||
// @rebornix how to set an editor selection?
|
||||
// editor.setSelections(ranges)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { flatten, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
@@ -44,7 +44,7 @@ abstract class MainThreadKernel implements INotebookKernel {
|
||||
|
||||
constructor(data: INotebookKernelDto2, private _modeService: IModeService) {
|
||||
this.id = data.id;
|
||||
this.viewType = data.viewType;
|
||||
this.viewType = data.notebookType;
|
||||
this.extension = data.extensionId;
|
||||
|
||||
this.implementsInterrupt = data.supportsInterrupt ?? false;
|
||||
@@ -52,7 +52,7 @@ abstract class MainThreadKernel implements INotebookKernel {
|
||||
this.description = data.description;
|
||||
this.detail = data.detail;
|
||||
this.supportedLanguages = isNonEmptyArray(data.supportedLanguages) ? data.supportedLanguages : _modeService.getRegisteredModes();
|
||||
this.implementsExecutionOrder = data.hasExecutionOrder ?? false;
|
||||
this.implementsExecutionOrder = data.supportsExecutionOrder ?? false;
|
||||
this.localResourceRoot = URI.revive(data.extensionLocation);
|
||||
this.preloads = data.preloads?.map(u => ({ uri: URI.revive(u.uri), provides: u.provides })) ?? [];
|
||||
}
|
||||
@@ -77,8 +77,8 @@ abstract class MainThreadKernel implements INotebookKernel {
|
||||
this.supportedLanguages = isNonEmptyArray(data.supportedLanguages) ? data.supportedLanguages : this._modeService.getRegisteredModes();
|
||||
event.supportedLanguages = true;
|
||||
}
|
||||
if (data.hasExecutionOrder !== undefined) {
|
||||
this.implementsExecutionOrder = data.hasExecutionOrder;
|
||||
if (data.supportsExecutionOrder !== undefined) {
|
||||
this.implementsExecutionOrder = data.supportsExecutionOrder;
|
||||
event.hasExecutionOrder = true;
|
||||
}
|
||||
this._onDidChange.fire(event);
|
||||
@@ -122,9 +122,6 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
private _onEditorAdd(editor: INotebookEditor) {
|
||||
|
||||
const ipcListener = editor.onDidReceiveMessage(e => {
|
||||
if (e.forRenderer) {
|
||||
return;
|
||||
}
|
||||
if (!editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
@@ -134,7 +131,7 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
}
|
||||
for (let [handle, candidate] of this._kernels) {
|
||||
if (candidate[0] === selected) {
|
||||
this._proxy.$acceptRendererMessage(handle, editor.getId(), e.message);
|
||||
this._proxy.$acceptKernelMessageFromRenderer(handle, editor.getId(), e.message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -164,11 +161,11 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
}
|
||||
if (editorId === undefined) {
|
||||
// all editors
|
||||
editor.postMessage(undefined, message);
|
||||
editor.postMessage(message);
|
||||
didSend = true;
|
||||
} else if (editor.getId() === editorId) {
|
||||
// selected editors
|
||||
editor.postMessage(undefined, message);
|
||||
editor.postMessage(message);
|
||||
didSend = true;
|
||||
break;
|
||||
}
|
||||
@@ -188,16 +185,16 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
|
||||
await that._proxy.$cancelCells(handle, uri, handles);
|
||||
}
|
||||
}(data, this._modeService);
|
||||
const registration = this._notebookKernelService.registerKernel(kernel);
|
||||
|
||||
const listener = this._notebookKernelService.onDidChangeNotebookKernelBinding(e => {
|
||||
if (e.oldKernel === kernel.id) {
|
||||
this._proxy.$acceptSelection(handle, e.notebook, false);
|
||||
this._proxy.$acceptNotebookAssociation(handle, e.notebook, false);
|
||||
} else if (e.newKernel === kernel.id) {
|
||||
this._proxy.$acceptSelection(handle, e.notebook, true);
|
||||
this._proxy.$acceptNotebookAssociation(handle, e.notebook, true);
|
||||
}
|
||||
});
|
||||
|
||||
const registration = this._notebookKernelService.registerKernel(kernel);
|
||||
this._kernels.set(handle, [kernel, combinedDisposable(listener, registration)]);
|
||||
}
|
||||
|
||||
|
||||
29
src/vs/workbench/api/browser/mainThreadNotebookRenderers.ts
Normal file
29
src/vs/workbench/api/browser/mainThreadNotebookRenderers.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, ExtHostNotebookRenderersShape, IExtHostContext, MainContext, MainThreadNotebookRenderersShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { INotebookRendererMessagingService } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadNotebookRenderers)
|
||||
export class MainThreadNotebookRenderers extends Disposable implements MainThreadNotebookRenderersShape {
|
||||
private readonly proxy: ExtHostNotebookRenderersShape;
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@INotebookRendererMessagingService private readonly messaging: INotebookRendererMessagingService,
|
||||
) {
|
||||
super();
|
||||
this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebookRenderers);
|
||||
this._register(messaging.onShouldPostMessage(e => {
|
||||
this.proxy.$postRendererMessage(e.editorId, e.rendererId, e.message);
|
||||
}));
|
||||
}
|
||||
|
||||
$postMessage(editorId: string, rendererId: string, message: unknown): void {
|
||||
this.messaging.fireDidReceiveMessage(editorId, rendererId, message);
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
this.entries.clear();
|
||||
}
|
||||
|
||||
$setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void {
|
||||
$setEntry(entryId: number, id: string, name: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void {
|
||||
// if there are icons in the text use the tooltip for the aria label
|
||||
let ariaLabel: string;
|
||||
let role: string | undefined = undefined;
|
||||
@@ -37,23 +37,23 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
|
||||
} else {
|
||||
ariaLabel = getCodiconAriaLabel(text);
|
||||
}
|
||||
const entry: IStatusbarEntry = { text, tooltip, command, color, backgroundColor, ariaLabel, role };
|
||||
const entry: IStatusbarEntry = { name, text, tooltip, command, color, backgroundColor, ariaLabel, role };
|
||||
|
||||
if (typeof priority === 'undefined') {
|
||||
priority = 0;
|
||||
}
|
||||
|
||||
// Reset existing entry if alignment or priority changed
|
||||
let existingEntry = this.entries.get(id);
|
||||
let existingEntry = this.entries.get(entryId);
|
||||
if (existingEntry && (existingEntry.alignment !== alignment || existingEntry.priority !== priority)) {
|
||||
dispose(existingEntry.accessor);
|
||||
this.entries.delete(id);
|
||||
this.entries.delete(entryId);
|
||||
existingEntry = undefined;
|
||||
}
|
||||
|
||||
// Create new entry if not existing
|
||||
if (!existingEntry) {
|
||||
this.entries.set(id, { accessor: this.statusbarService.addEntry(entry, statusId, statusName, alignment, priority), alignment, priority });
|
||||
this.entries.set(entryId, { accessor: this.statusbarService.addEntry(entry, id, alignment, priority), alignment, priority });
|
||||
}
|
||||
|
||||
// Otherwise update
|
||||
|
||||
@@ -702,9 +702,6 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
});
|
||||
});
|
||||
},
|
||||
getDefaultShellAndArgs: (): Promise<{ shell: string, args: string[] | string | undefined }> => {
|
||||
return Promise.resolve(this._proxy.$getDefaultShellAndArgs());
|
||||
},
|
||||
findExecutable: (command: string, cwd?: string, paths?: string[]): Promise<string | undefined> => {
|
||||
return this._proxy.$findExecutable(command, cwd, paths);
|
||||
}
|
||||
|
||||
@@ -3,22 +3,23 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, TerminalLaunchConfig, ITerminalDimensionsDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions } from 'vs/platform/terminal/common/terminal';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, TitleEventSource } from 'vs/platform/terminal/common/terminal';
|
||||
import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering';
|
||||
import { ExtHostContext, ExtHostTerminalServiceShape, IExtHostContext, ITerminalDimensionsDto, MainContext, MainThreadTerminalServiceShape, TerminalIdentifier, TerminalLaunchConfig } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ITerminalExternalLinkProvider, ITerminalInstance, ITerminalInstanceService, ITerminalLink, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy';
|
||||
import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { deserializeEnvironmentVariableCollection, serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
|
||||
import { IAvailableProfilesRequest as IAvailableProfilesRequest, IDefaultShellAndArgsRequest, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { OperatingSystem, OS } from 'vs/base/common/platform';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTerminalService)
|
||||
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
|
||||
@@ -30,11 +31,10 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
* This comes in play only when dealing with terminals created on the extension host side
|
||||
*/
|
||||
private _extHostTerminalIds = new Map<string, number>();
|
||||
private _remoteAuthority: string | null;
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
private readonly _terminalProcessProxies = new Map<number, ITerminalProcessExtHostProxy>();
|
||||
private readonly _profileProviders = new Map<string, IDisposable>();
|
||||
private _dataEventTracker: TerminalDataEventTracker | undefined;
|
||||
private _extHostKind: ExtensionHostKind;
|
||||
/**
|
||||
* A single shared terminal link provider for the exthost. When an ext registers a link
|
||||
* provider, this is registered with the terminal on the renderer side and all links are
|
||||
@@ -43,17 +43,19 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
*/
|
||||
private _linkProvider: IDisposable | undefined;
|
||||
|
||||
private _os: OperatingSystem = OS;
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
private readonly _extHostContext: IExtHostContext,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@ITerminalInstanceService readonly terminalInstanceService: ITerminalInstanceService,
|
||||
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
|
||||
this._remoteAuthority = extHostContext.remoteAuthority;
|
||||
this._proxy = _extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
|
||||
|
||||
// ITerminalService listeners
|
||||
this._toDispose.add(_terminalService.onInstanceCreated((instance) => {
|
||||
@@ -61,8 +63,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._onInstanceDimensionsChanged(instance);
|
||||
}));
|
||||
|
||||
this._extHostKind = extHostContext.extensionHostKind;
|
||||
|
||||
this._toDispose.add(_terminalService.onInstanceDisposed(instance => this._onTerminalDisposed(instance)));
|
||||
this._toDispose.add(_terminalService.onInstanceProcessIdReady(instance => this._onTerminalProcessIdReady(instance)));
|
||||
this._toDispose.add(_terminalService.onInstanceDimensionsChanged(instance => this._onInstanceDimensionsChanged(instance)));
|
||||
@@ -70,12 +70,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._toDispose.add(_terminalService.onInstanceRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e)));
|
||||
this._toDispose.add(_terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null)));
|
||||
this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => instance && this._onTitleChanged(instance.instanceId, instance.title)));
|
||||
this._toDispose.add(_terminalService.onRequestAvailableProfiles(e => this._onRequestAvailableProfiles(e)));
|
||||
|
||||
// ITerminalInstanceService listeners
|
||||
if (terminalInstanceService.onRequestDefaultShellAndArgs) {
|
||||
this._toDispose.add(terminalInstanceService.onRequestDefaultShellAndArgs(e => this._onRequestDefaultShellAndArgs(e)));
|
||||
}
|
||||
|
||||
// Set initial ext host state
|
||||
this._terminalService.terminalInstances.forEach(t => {
|
||||
@@ -94,7 +88,11 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._proxy.$initEnvironmentVariableCollections(serializedCollections);
|
||||
}
|
||||
|
||||
this._terminalService.extHostReady(extHostContext.remoteAuthority!); // TODO@Tyriar: remove null assertion
|
||||
remoteAgentService.getEnvironment().then(async env => {
|
||||
this._os = env?.os || OS;
|
||||
this._updateDefaultProfile();
|
||||
});
|
||||
this._terminalService.onDidChangeAvailableProfiles(() => this._updateDefaultProfile());
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -102,6 +100,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._linkProvider?.dispose();
|
||||
}
|
||||
|
||||
private async _updateDefaultProfile() {
|
||||
const remoteAuthority = withNullAsUndefined(this._extHostContext.remoteAuthority);
|
||||
const defaultProfile = this._terminalProfileResolverService.getDefaultProfile({ remoteAuthority, os: this._os });
|
||||
const defaultAutomationProfile = this._terminalProfileResolverService.getDefaultProfile({ remoteAuthority, os: this._os, allowAutomationShell: true });
|
||||
this._proxy.$acceptDefaultProfile(...await Promise.all([defaultProfile, defaultAutomationProfile]));
|
||||
}
|
||||
|
||||
private _getTerminalId(id: TerminalIdentifier): number | undefined {
|
||||
if (typeof id === 'number') {
|
||||
return id;
|
||||
@@ -135,9 +140,19 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
: undefined,
|
||||
extHostTerminalId: extHostTerminalId,
|
||||
isFeatureTerminal: launchConfig.isFeatureTerminal,
|
||||
isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal
|
||||
isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal,
|
||||
useShellEnvironment: launchConfig.useShellEnvironment
|
||||
};
|
||||
const terminal = this._terminalService.createTerminal(shellLaunchConfig);
|
||||
let terminal: ITerminalInstance | undefined;
|
||||
if (launchConfig.isSplitTerminal) {
|
||||
const activeInstance = this._terminalService.getActiveInstance();
|
||||
if (activeInstance) {
|
||||
terminal = withNullAsUndefined(this._terminalService.splitInstance(activeInstance, shellLaunchConfig));
|
||||
}
|
||||
}
|
||||
if (!terminal) {
|
||||
terminal = this._terminalService.createTerminal(shellLaunchConfig);
|
||||
}
|
||||
this._extHostTerminalIds.set(extHostTerminalId, terminal.instanceId);
|
||||
}
|
||||
|
||||
@@ -196,6 +211,18 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._terminalService.registerProcessSupport(isSupported);
|
||||
}
|
||||
|
||||
public $registerProfileProvider(id: string): void {
|
||||
// Proxy profile provider requests through the extension host
|
||||
this._profileProviders.set(id, this._terminalService.registerTerminalProfileProvider(id, {
|
||||
createContributedTerminalProfile: async (isSplitTerminal) => this._proxy.$createContributedProfileTerminal(id, isSplitTerminal)
|
||||
}));
|
||||
}
|
||||
|
||||
public $unregisterProfileProvider(id: string): void {
|
||||
this._profileProviders.get(id)?.dispose();
|
||||
this._profileProviders.delete(id);
|
||||
}
|
||||
|
||||
private _onActiveTerminalChanged(terminalId: number | null): void {
|
||||
this._proxy.$acceptActiveTerminalChanged(terminalId);
|
||||
}
|
||||
@@ -265,7 +292,15 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
}
|
||||
|
||||
public $sendProcessTitle(terminalId: number, title: string): void {
|
||||
this._terminalProcessProxies.get(terminalId)?.emitTitle(title);
|
||||
// Since title events can only come from vscode.Pseudoterminals right now, these are routed
|
||||
// directly to the instance as API source events such that they will replace the initial
|
||||
// `name` property provided for the Pseudoterminal. If we support showing both Api and
|
||||
// Process titles at the same time we may want to pass this through as a Process source
|
||||
// event.
|
||||
const instance = this._terminalService.getInstanceFromId(terminalId);
|
||||
if (instance) {
|
||||
instance.setTitle(title, TitleEventSource.Api);
|
||||
}
|
||||
}
|
||||
|
||||
public $sendProcessData(terminalId: number, data: string): void {
|
||||
@@ -308,28 +343,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
||||
this._getTerminalProcess(terminalId)?.emitLatency(sum / COUNT);
|
||||
}
|
||||
|
||||
private _isPrimaryExtHost(): boolean {
|
||||
// The "primary" ext host is the remote ext host if there is one, otherwise the local
|
||||
const conn = this._remoteAgentService.getConnection();
|
||||
if (conn) {
|
||||
return this._remoteAuthority === conn.remoteAuthority;
|
||||
}
|
||||
return this._extHostKind !== ExtensionHostKind.LocalWebWorker;
|
||||
}
|
||||
|
||||
private async _onRequestAvailableProfiles(req: IAvailableProfilesRequest): Promise<void> {
|
||||
if (this._isPrimaryExtHost()) {
|
||||
req.callback(await this._proxy.$getAvailableProfiles(req.configuredProfilesOnly));
|
||||
}
|
||||
}
|
||||
|
||||
private async _onRequestDefaultShellAndArgs(req: IDefaultShellAndArgsRequest): Promise<void> {
|
||||
if (this._isPrimaryExtHost()) {
|
||||
const res = await this._proxy.$getDefaultShellAndArgs(req.useAutomationShell);
|
||||
req.callback(res.shell, res.args);
|
||||
}
|
||||
}
|
||||
|
||||
private _getTerminalProcess(terminalId: number): ITerminalProcessExtHostProxy | undefined {
|
||||
const terminal = this._terminalProcessProxies.get(terminalId);
|
||||
if (!terminal) {
|
||||
|
||||
@@ -60,7 +60,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
});
|
||||
}
|
||||
|
||||
$reveal(treeViewId: string, itemInfo: { item: ITreeItem, parentChain: ITreeItem[]; } | undefined, options: IRevealOptions): Promise<void> {
|
||||
$reveal(treeViewId: string, itemInfo: { item: ITreeItem, parentChain: ITreeItem[] } | undefined, options: IRevealOptions): Promise<void> {
|
||||
this.logService.trace('MainThreadTreeViews#$reveal', treeViewId, itemInfo?.item, itemInfo?.parentChain, options);
|
||||
|
||||
return this.viewsService.openView(treeViewId, options.focus)
|
||||
@@ -73,7 +73,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
});
|
||||
}
|
||||
|
||||
$refresh(treeViewId: string, itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem; }): Promise<void> {
|
||||
$refresh(treeViewId: string, itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): Promise<void> {
|
||||
this.logService.trace('MainThreadTreeViews#$refresh', treeViewId, itemsToRefreshByHandle);
|
||||
|
||||
const viewer = this.getTreeView(treeViewId);
|
||||
|
||||
@@ -41,7 +41,8 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
|
||||
}
|
||||
|
||||
private processFindingEnabled(): boolean {
|
||||
return (!!this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING)) && (this.configurationService.getValue(PORT_AUTO_SOURCE_SETTING) === PORT_AUTO_SOURCE_SETTING_PROCESS);
|
||||
return (!!this.configurationService.getValue(PORT_AUTO_FORWARD_SETTING) || this.tunnelService.hasTunnelProvider)
|
||||
&& (this.configurationService.getValue(PORT_AUTO_SOURCE_SETTING) === PORT_AUTO_SOURCE_SETTING_PROCESS);
|
||||
}
|
||||
|
||||
async $setRemoteTunnelService(processId: number): Promise<void> {
|
||||
|
||||
@@ -14,8 +14,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { serializeMessage } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { deserializeWebviewMessage } from 'vs/workbench/api/common/extHostWebviewMessaging';
|
||||
import { serializeWebviewMessage, deserializeWebviewMessage } from 'vs/workbench/api/common/extHostWebviewMessaging';
|
||||
import { Webview, WebviewContentOptions, WebviewExtensionDescription, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
|
||||
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {
|
||||
@@ -74,7 +73,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
disposables.add(webview.onDidClickLink((uri) => this.onDidClickLink(handle, uri)));
|
||||
|
||||
disposables.add(webview.onMessage((message) => {
|
||||
const serialized = serializeMessage(message.message, options);
|
||||
const serialized = serializeWebviewMessage(message.message, options);
|
||||
this._proxy.$onMessage(handle, serialized.message, ...serialized.buffers);
|
||||
}));
|
||||
|
||||
|
||||
@@ -60,8 +60,7 @@ export class MainThreadWindow implements MainThreadWindowShape {
|
||||
}
|
||||
|
||||
async $asExternalUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise<UriComponents> {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const result = await this.openerService.resolveExternalUri(uri, options);
|
||||
const result = await this.openerService.resolveExternalUri(URI.revive(uriComponents), options);
|
||||
return result.resolved;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import { URI } from 'vs/base/common/uri';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { IWorkspacesService, IRecent } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IViewDescriptorService, IViewsService, ViewVisibilityState } from 'vs/workbench/common/views';
|
||||
@@ -30,100 +28,6 @@ function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) =>
|
||||
};
|
||||
}
|
||||
|
||||
interface INewWindowAPICommandOptions {
|
||||
reuseWindow?: boolean;
|
||||
/**
|
||||
* If set, defines the remoteAuthority of the new window. `null` will open a local window.
|
||||
* If not set, defaults to remoteAuthority of the current window.
|
||||
*/
|
||||
remoteAuthority?: string | null;
|
||||
}
|
||||
|
||||
export class NewWindowAPICommand {
|
||||
public static readonly ID = 'vscode.newWindow';
|
||||
public static execute(executor: ICommandsExecutor, options?: INewWindowAPICommandOptions): Promise<any> {
|
||||
const commandOptions: IOpenEmptyWindowOptions = {
|
||||
forceReuseWindow: options && options.reuseWindow,
|
||||
remoteAuthority: options && options.remoteAuthority
|
||||
};
|
||||
|
||||
return executor.executeCommand('_files.newWindow', commandOptions);
|
||||
}
|
||||
}
|
||||
CommandsRegistry.registerCommand({
|
||||
id: NewWindowAPICommand.ID,
|
||||
handler: adjustHandler(NewWindowAPICommand.execute),
|
||||
description: {
|
||||
description: 'Opens an new window',
|
||||
args: [
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, uri: URI) {
|
||||
const workspacesService = accessor.get(IWorkspacesService);
|
||||
return workspacesService.removeRecentlyOpened([uri]);
|
||||
});
|
||||
|
||||
export class RemoveFromRecentlyOpenedAPICommand {
|
||||
public static readonly ID = 'vscode.removeFromRecentlyOpened';
|
||||
public static execute(executor: ICommandsExecutor, path: string | URI): Promise<any> {
|
||||
if (typeof path === 'string') {
|
||||
path = path.match(/^[^:/?#]+:\/\//) ? URI.parse(path) : URI.file(path);
|
||||
} else {
|
||||
path = URI.revive(path); // called from extension host
|
||||
}
|
||||
return executor.executeCommand('_workbench.removeFromRecentlyOpened', path);
|
||||
}
|
||||
}
|
||||
CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute));
|
||||
|
||||
export interface OpenIssueReporterArgs {
|
||||
readonly extensionId: string;
|
||||
readonly issueTitle?: string;
|
||||
readonly issueBody?: string;
|
||||
}
|
||||
|
||||
export class OpenIssueReporter {
|
||||
public static readonly ID = 'vscode.openIssueReporter';
|
||||
|
||||
public static execute(executor: ICommandsExecutor, args: string | OpenIssueReporterArgs): Promise<void> {
|
||||
const commandArgs = typeof args === 'string'
|
||||
? { extensionId: args }
|
||||
: args;
|
||||
return executor.executeCommand('workbench.action.openIssueReporter', commandArgs);
|
||||
}
|
||||
}
|
||||
|
||||
interface RecentEntry {
|
||||
uri: URI;
|
||||
type: 'workspace' | 'folder' | 'file';
|
||||
label?: string;
|
||||
remoteAuthority?: string;
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async function (accessor: ServicesAccessor, recentEntry: RecentEntry) {
|
||||
const workspacesService = accessor.get(IWorkspacesService);
|
||||
let recent: IRecent | undefined = undefined;
|
||||
const uri = recentEntry.uri;
|
||||
const label = recentEntry.label;
|
||||
const remoteAuthority = recentEntry.remoteAuthority;
|
||||
if (recentEntry.type === 'workspace') {
|
||||
const workspace = await workspacesService.getWorkspaceIdentifier(uri);
|
||||
recent = { workspace, label, remoteAuthority };
|
||||
} else if (recentEntry.type === 'folder') {
|
||||
recent = { folderUri: uri, label, remoteAuthority };
|
||||
} else {
|
||||
recent = { fileUri: uri, label, remoteAuthority };
|
||||
}
|
||||
return workspacesService.addRecentlyOpened([recent]);
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand('_workbench.getRecentlyOpened', async function (accessor: ServicesAccessor) {
|
||||
const workspacesService = accessor.get(IWorkspacesService);
|
||||
return workspacesService.getRecentlyOpened();
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand('_extensionTests.setLogLevel', function (accessor: ServicesAccessor, level: number) {
|
||||
const logService = accessor.get(ILogService);
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -29,7 +28,7 @@ import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocu
|
||||
import { Extension, IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtHostFileSystem } from 'vs/workbench/api/common/extHostFileSystem';
|
||||
import { ExtHostFileSystemEventService } from 'vs/workbench/api/common/extHostFileSystemEventService';
|
||||
import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { ExtHostLanguageFeatures, InlineCompletionController } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { ExtHostLanguages } from 'vs/workbench/api/common/extHostLanguages';
|
||||
import { ExtHostMessageService } from 'vs/workbench/api/common/extHostMessageService';
|
||||
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
|
||||
@@ -59,7 +58,7 @@ import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
|
||||
import { IExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
// import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
// import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; {{SQL CARBON EDIT}}
|
||||
import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
@@ -82,11 +81,15 @@ import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSyste
|
||||
import { ExtHostTesting } from 'vs/workbench/api/common/extHostTesting';
|
||||
import { ExtHostUriOpeners } from 'vs/workbench/api/common/extHostUriOpener';
|
||||
import { IExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState';
|
||||
import { ExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
|
||||
import { ExtHostNotebookKernels } from 'vs/workbench/api/common/extHostNotebookKernels';
|
||||
import { RemoteTrustOption } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { TextSearchCompleteMessageType } from 'vs/workbench/services/search/common/searchExtTypes';
|
||||
import { ExtHostNotebookRenderers } from 'vs/workbench/api/common/extHostNotebookRenderers';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
import { ExtHostNotebookEditors } from 'vs/workbench/api/common/extHostNotebookEditors';
|
||||
import { ExtHostNotebookDocuments } from 'vs/workbench/api/common/extHostNotebookDocuments';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -114,6 +117,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostApiDeprecation = accessor.get(IExtHostApiDeprecationService);
|
||||
const extHostWindow = accessor.get(IExtHostWindow);
|
||||
const extHostSecretState = accessor.get(IExtHostSecretState);
|
||||
const extHostEditorTabs = accessor.get(IExtHostEditorTabs);
|
||||
|
||||
// register addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostFileSystemInfo, extHostFileSystemInfo);
|
||||
@@ -126,6 +130,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWindow, extHostWindow);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostSecretState, extHostSecretState);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostTelemetry, extHostTelemetry);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostEditorTabs, extHostEditorTabs);
|
||||
|
||||
// automatically create and register addressable instances
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
|
||||
@@ -138,16 +143,18 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, accessor.get(IExtHostOutputService));
|
||||
|
||||
// manually create and register addressable instances
|
||||
const extHostEditorTabs = rpcProtocol.set(ExtHostContext.ExtHostEditorTabs, new ExtHostEditorTabs());
|
||||
const extHostUrls = rpcProtocol.set(ExtHostContext.ExtHostUrls, new ExtHostUrls(rpcProtocol));
|
||||
const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
|
||||
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadBulkEdits)));
|
||||
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments, extHostLogService, extensionStoragePaths));
|
||||
const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook));
|
||||
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments, extensionStoragePaths));
|
||||
const extHostNotebookDocuments = rpcProtocol.set(ExtHostContext.ExtHostNotebookDocuments, new ExtHostNotebookDocuments(extHostLogService, extHostNotebook));
|
||||
const extHostNotebookEditors = rpcProtocol.set(ExtHostContext.ExtHostNotebookEditors, new ExtHostNotebookEditors(extHostLogService, rpcProtocol, extHostNotebook));
|
||||
const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook, extHostLogService));
|
||||
const extHostNotebookRenderers = rpcProtocol.set(ExtHostContext.ExtHostNotebookRenderers, new ExtHostNotebookRenderers(rpcProtocol, extHostNotebook));
|
||||
const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands, extHostLogService));
|
||||
const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, initData.environment));
|
||||
const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, initData));
|
||||
const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol, extHostLogService));
|
||||
const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, uriTransformer, extHostDocuments, extHostCommands, extHostDiagnostics, extHostLogService, extHostApiDeprecation));
|
||||
const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures));
|
||||
@@ -160,7 +167,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
|
||||
const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol));
|
||||
const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands));
|
||||
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment, extHostWorkspace, extHostLogService, extHostApiDeprecation));
|
||||
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, { remote: initData.remote }, extHostWorkspace, extHostLogService, extHostApiDeprecation));
|
||||
const extHostWebviewPanels = rpcProtocol.set(ExtHostContext.ExtHostWebviewPanels, new ExtHostWebviewPanels(rpcProtocol, extHostWebviews, extHostWorkspace));
|
||||
const extHostCustomEditors = rpcProtocol.set(ExtHostContext.ExtHostCustomEditors, new ExtHostCustomEditors(rpcProtocol, extHostDocuments, extensionStoragePaths, extHostWebviews, extHostWebviewPanels));
|
||||
const extHostWebviewViews = rpcProtocol.set(ExtHostContext.ExtHostWebviewViews, new ExtHostWebviewViews(rpcProtocol, extHostWebviews));
|
||||
@@ -219,7 +226,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
})();
|
||||
|
||||
const authentication: typeof vscode.authentication = {
|
||||
getSession(providerId: string, scopes: string[], options?: vscode.AuthenticationGetSessionOptions) {
|
||||
getSession(providerId: string, scopes: readonly string[], options?: vscode.AuthenticationGetSessionOptions) {
|
||||
return extHostAuthentication.getSession(extension, providerId, scopes, options as any);
|
||||
},
|
||||
get onDidChangeSessions(): Event<vscode.AuthenticationSessionsChangeEvent> {
|
||||
@@ -298,7 +305,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
get uriScheme() { return initData.environment.appUriScheme; },
|
||||
get clipboard(): vscode.Clipboard { return extHostClipboard.value; },
|
||||
get shell() {
|
||||
return extHostTerminalService.getDefaultShell(false, configProvider);
|
||||
return extHostTerminalService.getDefaultShell(false);
|
||||
},
|
||||
get isTelemetryEnabled() {
|
||||
return extHostTelemetry.getTelemetryEnabled();
|
||||
@@ -316,12 +323,26 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
allowContributedOpeners: options?.allowContributedOpeners,
|
||||
});
|
||||
},
|
||||
asExternalUri(uri: URI) {
|
||||
async asExternalUri(uri: URI) {
|
||||
if (uri.scheme === initData.environment.appUriScheme) {
|
||||
return extHostUrls.createAppUri(uri);
|
||||
}
|
||||
|
||||
return extHostWindow.asExternalUri(uri, { allowTunneling: !!initData.remote.authority });
|
||||
const isHttp = matchesScheme(uri, Schemas.http) || matchesScheme(uri, Schemas.https);
|
||||
|
||||
if (!isHttp) {
|
||||
checkProposedApiEnabled(extension); // https://github.com/microsoft/vscode/issues/124263
|
||||
}
|
||||
|
||||
try {
|
||||
return await extHostWindow.asExternalUri(uri, { allowTunneling: !!initData.remote.authority });
|
||||
} catch (err) {
|
||||
if (isHttp) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
get remoteName() {
|
||||
return getRemoteName(initData.remote.authority);
|
||||
@@ -482,6 +503,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable {
|
||||
return extHostLanguageFeatures.registerCompletionItemProvider(extension, checkSelector(selector), provider, triggerCharacters);
|
||||
},
|
||||
registerInlineCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProvider): vscode.Disposable {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguageFeatures.registerInlineCompletionsProvider(extension, checkSelector(selector), provider);
|
||||
},
|
||||
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
|
||||
return extHostLanguageFeatures.registerDocumentLinkProvider(extension, checkSelector(selector), provider);
|
||||
},
|
||||
@@ -504,9 +529,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguages.tokenAtPosition(doc, pos);
|
||||
},
|
||||
registerInlineHintsProvider(selector: vscode.DocumentSelector, provider: vscode.InlineHintsProvider): vscode.Disposable {
|
||||
registerInlayHintsProvider(selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguageFeatures.registerInlineHintsProvider(extension, selector, provider);
|
||||
return extHostLanguageFeatures.registerInlayHintsProvider(extension, selector, provider);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -532,7 +557,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus);
|
||||
},
|
||||
createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
|
||||
return extHostEditors.createTextEditorDecorationType(options);
|
||||
return extHostEditors.createTextEditorDecorationType(extension, options);
|
||||
},
|
||||
onDidChangeActiveTextEditor(listener, thisArg?, disposables?) {
|
||||
return extHostEditors.onDidChangeActiveTextEditor(listener, thisArg, disposables);
|
||||
@@ -599,26 +624,21 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
showSaveDialog(options) {
|
||||
return extHostDialogs.showSaveDialog(options);
|
||||
},
|
||||
createStatusBarItem(alignmentOrOptions?: vscode.StatusBarAlignment | vscode.StatusBarItemOptions, priority?: number): vscode.StatusBarItem {
|
||||
let id: string;
|
||||
let name: string;
|
||||
createStatusBarItem(alignmentOrId?: vscode.StatusBarAlignment | string, priorityOrAlignment?: number | vscode.StatusBarAlignment, priorityArg?: number): vscode.StatusBarItem {
|
||||
let id: string | undefined;
|
||||
let alignment: number | undefined;
|
||||
let accessibilityInformation: vscode.AccessibilityInformation | undefined = undefined;
|
||||
let priority: number | undefined;
|
||||
|
||||
if (alignmentOrOptions && typeof alignmentOrOptions !== 'number') {
|
||||
id = alignmentOrOptions.id;
|
||||
name = alignmentOrOptions.name;
|
||||
alignment = alignmentOrOptions.alignment;
|
||||
priority = alignmentOrOptions.priority;
|
||||
accessibilityInformation = alignmentOrOptions.accessibilityInformation;
|
||||
if (typeof alignmentOrId === 'string') {
|
||||
id = alignmentOrId;
|
||||
alignment = priorityOrAlignment;
|
||||
priority = priorityArg;
|
||||
} else {
|
||||
id = extension.identifier.value;
|
||||
name = nls.localize('extensionLabel', "{0} (Extension)", extension.displayName || extension.name);
|
||||
alignment = alignmentOrOptions as number; // {{SQL CARBON EDIT}} strict-null-check
|
||||
priority = priority;
|
||||
alignment = alignmentOrId as number; // {{SQL CARBON EDIT}} strict-null-check
|
||||
priority = priorityOrAlignment;
|
||||
}
|
||||
|
||||
return extHostStatusBar.createStatusBarEntry(id, name, alignment, priority, accessibilityInformation);
|
||||
return extHostStatusBar.createStatusBarEntry(extension, id, alignment, priority);
|
||||
},
|
||||
setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): vscode.Disposable {
|
||||
return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
|
||||
@@ -647,18 +667,18 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
if ('pty' in nameOrOptions) {
|
||||
return extHostTerminalService.createExtensionTerminal(nameOrOptions);
|
||||
}
|
||||
if (nameOrOptions.message) {
|
||||
checkProposedApiEnabled(extension);
|
||||
}
|
||||
if (nameOrOptions.icon) {
|
||||
if (nameOrOptions.iconPath) {
|
||||
checkProposedApiEnabled(extension);
|
||||
}
|
||||
return extHostTerminalService.createTerminalFromOptions(nameOrOptions);
|
||||
}
|
||||
return extHostTerminalService.createTerminal(nameOrOptions, shellPath, shellArgs);
|
||||
},
|
||||
registerTerminalLinkProvider(handler: vscode.TerminalLinkProvider): vscode.Disposable {
|
||||
return extHostTerminalService.registerLinkProvider(handler);
|
||||
registerTerminalLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable {
|
||||
return extHostTerminalService.registerLinkProvider(provider);
|
||||
},
|
||||
registerTerminalProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
|
||||
return extHostTerminalService.registerProfileProvider(id, provider);
|
||||
},
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension);
|
||||
@@ -715,11 +735,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
},
|
||||
onDidChangeNotebookEditorSelection(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookEditorSelection(listener, thisArgs, disposables);
|
||||
return extHostNotebookEditors.onDidChangeNotebookEditorSelection(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeNotebookEditorVisibleRanges(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookEditorVisibleRanges(listener, thisArgs, disposables);
|
||||
return extHostNotebookEditors.onDidChangeNotebookEditorVisibleRanges(listener, thisArgs, disposables);
|
||||
},
|
||||
showNotebookDocument(uriOrDocument, options?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
@@ -736,6 +756,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
get onDidChangeOpenEditors() {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostEditorTabs.onDidChangeTabs;
|
||||
},
|
||||
getInlineCompletionItemController<T extends vscode.InlineCompletionItem>(provider: vscode.InlineCompletionItemProvider<T>): vscode.InlineCompletionController<T> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return InlineCompletionController.get(provider);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -847,6 +871,34 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
onWillSaveTextDocument: (listener, thisArgs?, disposables?) => {
|
||||
return extHostDocumentSaveParticipant.getOnWillSaveTextDocumentEvent(extension)(listener, thisArgs, disposables);
|
||||
},
|
||||
get notebookDocuments(): vscode.NotebookDocument[] {
|
||||
return extHostNotebook.notebookDocuments.map(d => d.apiNotebook);
|
||||
},
|
||||
async openNotebookDocument(uriOrType?: URI | string, content?: vscode.NotebookData) {
|
||||
let uri: URI;
|
||||
if (URI.isUri(uriOrType)) {
|
||||
uri = uriOrType;
|
||||
await extHostNotebook.openNotebookDocument(uriOrType);
|
||||
} else if (typeof uriOrType === 'string') {
|
||||
uri = URI.revive(await extHostNotebook.createNotebookDocument({ viewType: uriOrType, content }));
|
||||
} else {
|
||||
throw new Error('Invalid arguments');
|
||||
}
|
||||
return extHostNotebook.getNotebookDocument(uri).apiNotebook;
|
||||
},
|
||||
get onDidOpenNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
return extHostNotebook.onDidOpenNotebookDocument;
|
||||
},
|
||||
get onDidCloseNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
return extHostNotebook.onDidCloseNotebookDocument;
|
||||
},
|
||||
registerNotebookSerializer(viewType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) {
|
||||
return extHostNotebook.registerNotebookSerializer(extension, viewType, serializer, options, extension.enableProposedApi ? registration : undefined);
|
||||
},
|
||||
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options, extension.enableProposedApi ? registration : undefined);
|
||||
},
|
||||
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
|
||||
return configProvider.onDidChangeConfiguration(listener, thisArgs, disposables);
|
||||
},
|
||||
@@ -864,7 +916,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostTask.registerTaskProvider(extension, type, provider);
|
||||
},
|
||||
registerFileSystemProvider(scheme, provider, options) {
|
||||
return extHostFileSystem.registerFileSystemProvider(extension.identifier, scheme, provider, options);
|
||||
return extHostFileSystem.registerFileSystemProvider(extension.identifier, scheme, provider, options, extension.enableProposedApi);
|
||||
},
|
||||
get fs() {
|
||||
return extHostConsumerFileSystem.value;
|
||||
@@ -1014,12 +1066,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
return undefined!;
|
||||
},
|
||||
addBreakpoints(breakpoints: vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
addBreakpoints(breakpoints: readonly vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio'); // {{SQL CARBON EDIT}}
|
||||
return undefined!;
|
||||
},
|
||||
removeBreakpoints(breakpoints: vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio');
|
||||
removeBreakpoints(breakpoints: readonly vscode.Breakpoint[]) {
|
||||
extHostLogService.warn('Debug API is disabled in Azure Data Studio'); // {{SQL CARBON EDIT}}
|
||||
return undefined!;
|
||||
},
|
||||
asDebugSourceUri(source: vscode.DebugProtocolSource, session?: vscode.DebugSession): vscode.Uri {
|
||||
@@ -1056,52 +1108,34 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
};
|
||||
|
||||
// namespace: notebook
|
||||
const notebook: typeof vscode.notebook = {
|
||||
openNotebookDocument: (uriComponents) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.openNotebookDocument(uriComponents);
|
||||
const notebooks: typeof vscode.notebooks = {
|
||||
createNotebookController(id: string, notebookType: string, label: string, handler?, rendererScripts?: vscode.NotebookRendererScript[]) {
|
||||
return extHostNotebookKernels.createNotebookController(extension, id, notebookType, label, handler, extension.enableProposedApi ? rendererScripts : undefined);
|
||||
},
|
||||
get onDidOpenNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidOpenNotebookDocument;
|
||||
},
|
||||
get onDidCloseNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidCloseNotebookDocument;
|
||||
registerNotebookCellStatusBarItemProvider: (notebookType: string, provider: vscode.NotebookCellStatusBarItemProvider) => {
|
||||
return extHostNotebook.registerNotebookCellStatusBarItemProvider(extension, notebookType, provider);
|
||||
},
|
||||
get onDidSaveNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidSaveNotebookDocument;
|
||||
},
|
||||
get notebookDocuments(): vscode.NotebookDocument[] {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.notebookDocuments.map(d => d.apiNotebook);
|
||||
},
|
||||
registerNotebookSerializer(viewType, serializer, options) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookSerializer(extension, viewType, serializer, options);
|
||||
},
|
||||
registerNotebookContentProvider: (viewType, provider, options) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options);
|
||||
},
|
||||
registerNotebookCellStatusBarItemProvider: (selector: vscode.NotebookSelector, provider: vscode.NotebookCellStatusBarItemProvider) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookCellStatusBarItemProvider(extension, selector, provider);
|
||||
return extHostNotebookDocuments.onDidSaveNotebookDocument;
|
||||
},
|
||||
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.createNotebookEditorDecorationType(options);
|
||||
return extHostNotebookEditors.createNotebookEditorDecorationType(options);
|
||||
},
|
||||
createRendererMessaging(rendererId) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebookRenderers.createRendererMessaging(rendererId);
|
||||
},
|
||||
onDidChangeNotebookDocumentMetadata(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookDocumentMetadata(listener, thisArgs, disposables);
|
||||
return extHostNotebookDocuments.onDidChangeNotebookDocumentMetadata(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeNotebookCells(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookCells(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeCellExecutionState(listener, thisArgs?, disposables?) {
|
||||
onDidChangeNotebookCellExecutionState(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookCellExecutionState(listener, thisArgs, disposables);
|
||||
},
|
||||
@@ -1117,14 +1151,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension);
|
||||
return new ExtHostNotebookConcatDocument(extHostNotebook, extHostDocuments, notebook, selector);
|
||||
},
|
||||
createNotebookCellExecutionTask(uri: vscode.Uri, index: number, kernelId: string): vscode.NotebookCellExecutionTask | undefined {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.createNotebookCellExecution(uri, index, kernelId);
|
||||
},
|
||||
createNotebookController(id, viewType, label, executeHandler, preloads) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebookKernels.createNotebookController(extension, id, viewType, label, executeHandler, preloads);
|
||||
}
|
||||
};
|
||||
|
||||
return <typeof vscode>{
|
||||
@@ -1138,7 +1164,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
env,
|
||||
extensions,
|
||||
languages,
|
||||
notebook,
|
||||
notebooks,
|
||||
scm,
|
||||
tasks,
|
||||
test,
|
||||
@@ -1191,6 +1217,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
InlineValueText: extHostTypes.InlineValueText,
|
||||
InlineValueVariableLookup: extHostTypes.InlineValueVariableLookup,
|
||||
InlineValueEvaluatableExpression: extHostTypes.InlineValueEvaluatableExpression,
|
||||
InlineCompletionTriggerKind: extHostTypes.InlineCompletionTriggerKind,
|
||||
EventEmitter: Emitter,
|
||||
ExtensionKind: extHostTypes.ExtensionKind,
|
||||
ExtensionMode: extHostTypes.ExtensionMode,
|
||||
@@ -1199,9 +1226,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
FileDecoration: extHostTypes.FileDecoration,
|
||||
FileSystemError: extHostTypes.FileSystemError,
|
||||
FileType: files.FileType,
|
||||
FilePermission: files.FilePermission,
|
||||
FoldingRange: extHostTypes.FoldingRange,
|
||||
FoldingRangeKind: extHostTypes.FoldingRangeKind,
|
||||
FunctionBreakpoint: extHostTypes.FunctionBreakpoint,
|
||||
InlineCompletionItem: extHostTypes.InlineSuggestion,
|
||||
InlineCompletionList: extHostTypes.InlineSuggestions,
|
||||
Hover: extHostTypes.Hover,
|
||||
IndentAction: languageConfiguration.IndentAction,
|
||||
Location: extHostTypes.Location,
|
||||
@@ -1254,10 +1284,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
ViewColumn: extHostTypes.ViewColumn,
|
||||
WorkspaceEdit: extHostTypes.WorkspaceEdit,
|
||||
// proposed api types
|
||||
InlineHint: extHostTypes.InlineHint,
|
||||
InlineHintKind: extHostTypes.InlineHintKind,
|
||||
InlayHint: extHostTypes.InlayHint,
|
||||
InlayHintKind: extHostTypes.InlayHintKind,
|
||||
RemoteAuthorityResolverError: extHostTypes.RemoteAuthorityResolverError,
|
||||
RemoteTrustOption: RemoteTrustOption,
|
||||
ResolvedAuthority: extHostTypes.ResolvedAuthority,
|
||||
SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType,
|
||||
ExtensionRuntime: extHostTypes.ExtensionRuntime,
|
||||
@@ -1265,16 +1294,16 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
NotebookRange: extHostTypes.NotebookRange,
|
||||
NotebookCellKind: extHostTypes.NotebookCellKind,
|
||||
NotebookCellExecutionState: extHostTypes.NotebookCellExecutionState,
|
||||
NotebookDocumentMetadata: extHostTypes.NotebookDocumentMetadata,
|
||||
NotebookCellMetadata: extHostTypes.NotebookCellMetadata,
|
||||
NotebookCellData: extHostTypes.NotebookCellData,
|
||||
NotebookData: extHostTypes.NotebookData,
|
||||
NotebookRendererScript: extHostTypes.NotebookRendererScript,
|
||||
NotebookCellStatusBarAlignment: extHostTypes.NotebookCellStatusBarAlignment,
|
||||
NotebookEditorRevealType: extHostTypes.NotebookEditorRevealType,
|
||||
NotebookCellOutput: extHostTypes.NotebookCellOutput,
|
||||
NotebookCellOutputItem: extHostTypes.NotebookCellOutputItem,
|
||||
NotebookCellStatusBarItem: extHostTypes.NotebookCellStatusBarItem,
|
||||
NotebookControllerAffinity: extHostTypes.NotebookControllerAffinity,
|
||||
PortAttributes: extHostTypes.PortAttributes,
|
||||
LinkedEditingRanges: extHostTypes.LinkedEditingRanges,
|
||||
TestItemStatus: extHostTypes.TestItemStatus,
|
||||
TestResultState: extHostTypes.TestResultState,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IExtHostCommands, ExtHostCommands } from 'vs/workbench/api/common/extHo
|
||||
import { IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostTerminalService, WorkerExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostTask, WorkerExtHostTask } from 'vs/workbench/api/common/extHostTask';
|
||||
// import { IExtHostDebugService, WorkerExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
// import { IExtHostDebugService, WorkerExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; {{SQL CARBON EDIT}}
|
||||
import { IExtHostSearch, ExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
import { IExtensionStoragePaths, ExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
|
||||
@@ -23,13 +23,14 @@ import { IExtHostConsumerFileSystem, ExtHostConsumerFileSystem } from 'vs/workbe
|
||||
import { IExtHostFileSystemInfo, ExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
import { IExtHostSecretState, ExtHostSecretState } from 'vs/workbench/api/common/exHostSecretState';
|
||||
import { ExtHostTelemetry, IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
|
||||
import { ExtHostEditorTabs, IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService);
|
||||
registerSingleton(IExtHostCommands, ExtHostCommands);
|
||||
registerSingleton(IExtHostConfiguration, ExtHostConfiguration);
|
||||
registerSingleton(IExtHostConsumerFileSystem, ExtHostConsumerFileSystem);
|
||||
// registerSingleton(IExtHostDebugService, WorkerExtHostDebugService);
|
||||
// registerSingleton(IExtHostDebugService, WorkerExtHostDebugService); {{SQL CARBON EDIT}}
|
||||
registerSingleton(IExtHostDecorations, ExtHostDecorations);
|
||||
registerSingleton(IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors);
|
||||
registerSingleton(IExtHostFileSystemInfo, ExtHostFileSystemInfo);
|
||||
@@ -43,3 +44,4 @@ registerSingleton(IExtHostWindow, ExtHostWindow);
|
||||
registerSingleton(IExtHostWorkspace, ExtHostWorkspace);
|
||||
registerSingleton(IExtHostSecretState, ExtHostSecretState);
|
||||
registerSingleton(IExtHostTelemetry, ExtHostTelemetry);
|
||||
registerSingleton(IExtHostEditorTabs, ExtHostEditorTabs);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
||||
@@ -11,7 +10,10 @@ import { SerializedError } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { Dto } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { RenderLineNumbersType, TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
@@ -22,8 +24,9 @@ import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model'
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationData, IConfigurationChange, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationTarget, IConfigurationChange, IConfigurationData, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
@@ -32,40 +35,35 @@ import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
import * as quickInput from 'vs/platform/quickinput/common/quickInput';
|
||||
import { RemoteAuthorityResolverErrorCode, ResolverResult, TunnelDescription, IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import * as statusbar from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { IRemoteConnectionData, RemoteAuthorityResolverErrorCode, ResolverResult, TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { ProvidedPortAttributes, TunnelCreationOptions, TunnelOptions, TunnelProviderFeatures } from 'vs/platform/remote/common/tunnel';
|
||||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { TreeDataTransferDTO } from 'vs/workbench/api/common/shared/treeDataTransfer';
|
||||
import * as tasks from 'vs/workbench/api/common/shared/tasks';
|
||||
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
|
||||
import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ActivationKind, MissingExtensionDependency, ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile } from 'vs/platform/terminal/common/terminal';
|
||||
import { ThemeColor, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IExtensionIdWithVersion } from 'vs/platform/userDataSync/common/extensionsStorageSync';
|
||||
import { WorkspaceTrustRequestOptions } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, ProvidedPortAttributes } from 'vs/platform/remote/common/tunnel';
|
||||
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, TransientCellMetadata, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter, IOutputDto, TransientOptions, IImmediateCellEditOperation, INotebookCellStatusBarItem, TransientDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { Dto } from 'vs/base/common/types';
|
||||
import { DebugConfigurationProviderTriggerKind, TestResultState } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IExtensionIdWithVersion } from 'vs/platform/userDataSync/common/extensionsStorageSync';
|
||||
import { InternalTestItem, RunTestForProviderRequest, RunTestsRequest, TestIdWithSrc, TestsDiff, ISerializedTestResults, ITestMessage, ITestItem, ITestRunTask, ExtensionRunTestsRequest } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { WorkspaceTrustRequestOptions } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions, ITerminalEnvironment, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal';
|
||||
import { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { NotebookSelector } from 'vs/workbench/contrib/notebook/common/notebookSelector';
|
||||
import * as tasks from 'vs/workbench/api/common/shared/tasks';
|
||||
import { EditorGroupColumn, SaveReason } from 'vs/workbench/common/editor';
|
||||
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CellKind, ICellEditOperation, IImmediateCellEditOperation, IMainCellDto, INotebookCellStatusBarItem, INotebookContributionData, INotebookDecorationRenderOptions, IOutputDto, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookDataDto, NotebookDocumentMetadata, TransientCellMetadata, TransientDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { ExtensionRunTestsRequest, InternalTestItem, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForProviderRequest, RunTestsRequest, TestIdWithSrc, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTimelineOptions, Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { ActivationKind, ExtensionHostKind, MissingExtensionDependency } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import * as statusbar from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
|
||||
@@ -80,8 +78,6 @@ export interface IEnvironment {
|
||||
extensionTestsLocationURI?: URI;
|
||||
globalStorageHome: URI;
|
||||
workspaceStorageHome: URI;
|
||||
webviewResourceRoot: string;
|
||||
webviewCspSource: string;
|
||||
useHostProxy?: boolean;
|
||||
}
|
||||
|
||||
@@ -176,7 +172,7 @@ export interface MainThreadAuthenticationShape extends IDisposable {
|
||||
$unregisterAuthenticationProvider(id: string): void;
|
||||
$ensureProvider(id: string): Promise<void>;
|
||||
$sendDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void;
|
||||
$getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, clearSessionPreference?: boolean }): Promise<modes.AuthenticationSession | undefined>;
|
||||
$getSession(providerId: string, scopes: readonly string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, clearSessionPreference?: boolean }): Promise<modes.AuthenticationSession | undefined>;
|
||||
$removeSession(providerId: string, sessionId: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -279,7 +275,7 @@ export interface MainThreadBulkEditsShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise<string | undefined>;
|
||||
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
|
||||
$registerTextEditorDecorationType(extensionId: ExtensionIdentifier, key: string, options: editorCommon.IDecorationRenderOptions): void;
|
||||
$removeTextEditorDecorationType(key: string): void;
|
||||
$tryShowEditor(id: string, position: EditorGroupColumn): Promise<void>;
|
||||
$tryHideEditor(id: string): Promise<void>;
|
||||
@@ -376,6 +372,14 @@ export interface ISignatureHelpProviderMetadataDto {
|
||||
readonly retriggerCharacters: readonly string[];
|
||||
}
|
||||
|
||||
export interface IdentifiableInlineCompletions extends modes.InlineCompletions<IdentifiableInlineCompletion> {
|
||||
pid: number;
|
||||
}
|
||||
|
||||
export interface IdentifiableInlineCompletion extends modes.InlineCompletion {
|
||||
idx: number;
|
||||
}
|
||||
|
||||
export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$unregister(handle: number): void;
|
||||
$registerDocumentSymbolProvider(handle: number, selector: IDocumentFilterDto[], label: string): void;
|
||||
@@ -402,9 +406,10 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$emitDocumentSemanticTokensEvent(eventHandle: number): void;
|
||||
$registerDocumentRangeSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void;
|
||||
$registerSuggestSupport(handle: number, selector: IDocumentFilterDto[], triggerCharacters: string[], supportsResolveDetails: boolean, displayName: string): void;
|
||||
$registerInlineCompletionsSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerSignatureHelpProvider(handle: number, selector: IDocumentFilterDto[], metadata: ISignatureHelpProviderMetadataDto): void;
|
||||
$registerInlineHintsProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void;
|
||||
$emitInlineHintsEvent(eventHandle: number, event?: any): void;
|
||||
$registerInlayHintsProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void;
|
||||
$emitInlayHintsEvent(eventHandle: number, event?: any): void;
|
||||
$registerDocumentLinkProvider(handle: number, selector: IDocumentFilterDto[], supportsResolve: boolean): void;
|
||||
$registerDocumentColorProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerFoldingRangeProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void;
|
||||
@@ -463,7 +468,7 @@ export interface TerminalLaunchConfig {
|
||||
shellArgs?: string[] | string;
|
||||
cwd?: string | UriComponents;
|
||||
env?: ITerminalEnvironment;
|
||||
icon?: string;
|
||||
icon?: URI | { light: URI; dark: URI } | ThemeIcon;
|
||||
initialText?: string;
|
||||
waitOnExit?: boolean;
|
||||
strictEnv?: boolean;
|
||||
@@ -471,6 +476,8 @@ export interface TerminalLaunchConfig {
|
||||
isExtensionCustomPtyTerminal?: boolean;
|
||||
isFeatureTerminal?: boolean;
|
||||
isExtensionOwnedTerminal?: boolean;
|
||||
useShellEnvironment?: boolean;
|
||||
isSplitTerminal?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
@@ -484,6 +491,8 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$startLinkProvider(): void;
|
||||
$stopLinkProvider(): void;
|
||||
$registerProcessSupport(isSupported: boolean): void;
|
||||
$registerProfileProvider(id: string): void;
|
||||
$unregisterProfileProvider(id: string): void;
|
||||
$setEnvironmentVariableCollection(extensionIdentifier: string, persistent: boolean, collection: ISerializableEnvironmentVariableCollection | undefined): void;
|
||||
|
||||
// Process
|
||||
@@ -628,7 +637,8 @@ export interface MainThreadEditorTabsShape extends IDisposable {
|
||||
export interface IEditorTabDto {
|
||||
group: number;
|
||||
name: string;
|
||||
resource: UriComponents
|
||||
resource: UriComponents;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export interface IExtHostEditorTabsShape {
|
||||
@@ -652,7 +662,6 @@ export interface WebviewExtensionDescription {
|
||||
export interface NotebookExtensionDescription {
|
||||
readonly id: ExtensionIdentifier;
|
||||
readonly location: UriComponents;
|
||||
readonly description?: string;
|
||||
}
|
||||
|
||||
export enum WebviewEditorCapabilities {
|
||||
@@ -713,7 +722,7 @@ export interface WebviewMessageArrayBufferReference {
|
||||
export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$setHtml(handle: WebviewHandle, value: string): void;
|
||||
$setOptions(handle: WebviewHandle, options: IWebviewOptions): void;
|
||||
$postMessage(handle: WebviewHandle, value: any, ...buffers: VSBuffer[]): Promise<boolean>
|
||||
$postMessage(handle: WebviewHandle, value: string, ...buffers: VSBuffer[]): Promise<boolean>
|
||||
}
|
||||
|
||||
export interface MainThreadWebviewPanelsShape extends IDisposable {
|
||||
@@ -823,11 +832,6 @@ export interface ExtHostWebviewViewsShape {
|
||||
$disposeWebviewView(webviewHandle: WebviewHandle): void;
|
||||
}
|
||||
|
||||
export enum CellKind {
|
||||
Markdown = 1,
|
||||
Code = 2
|
||||
}
|
||||
|
||||
export enum CellOutputKind {
|
||||
Text = 1,
|
||||
Error = 2,
|
||||
@@ -878,19 +882,14 @@ export interface INotebookCellStatusBarListDto {
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookShape extends IDisposable {
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, options: {
|
||||
transientOutputs: boolean;
|
||||
transientCellMetadata: TransientCellMetadata;
|
||||
transientDocumentMetadata: TransientDocumentMetadata;
|
||||
viewOptions?: { displayName: string; filenamePattern: (string | IRelativePattern | INotebookExclusiveDocumentFilter)[]; exclusive: boolean; };
|
||||
}): Promise<void>;
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, registration: INotebookContributionData | undefined): Promise<void>;
|
||||
$updateNotebookProviderOptions(viewType: string, options?: { transientOutputs: boolean; transientCellMetadata: TransientCellMetadata; transientDocumentMetadata: TransientDocumentMetadata; }): Promise<void>;
|
||||
$unregisterNotebookProvider(viewType: string): Promise<void>;
|
||||
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions): void;
|
||||
$registerNotebookSerializer(handle: number, extension: NotebookExtensionDescription, viewType: string, options: TransientOptions, registration: INotebookContributionData | undefined): void;
|
||||
$unregisterNotebookSerializer(handle: number): void;
|
||||
|
||||
$registerNotebookCellStatusBarItemProvider(handle: number, eventHandle: number | undefined, selector: NotebookSelector): Promise<void>;
|
||||
$registerNotebookCellStatusBarItemProvider(handle: number, eventHandle: number | undefined, viewType: string): Promise<void>;
|
||||
$unregisterNotebookCellStatusBarItemProvider(handle: number, eventHandle: number | undefined): Promise<void>;
|
||||
$emitCellStatusBarEvent(eventHandle: number): void;
|
||||
}
|
||||
@@ -900,19 +899,21 @@ export interface MainThreadNotebookEditorsShape extends IDisposable {
|
||||
$tryRevealRange(id: string, range: ICellRange, revealType: NotebookEditorRevealType): Promise<void>;
|
||||
$registerNotebookEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void;
|
||||
$removeNotebookEditorDecorationType(key: string): void;
|
||||
$trySetSelections(id: string, range: ICellRange[]): void;
|
||||
$trySetDecorations(id: string, range: ICellRange, decorationKey: string): void;
|
||||
$tryApplyEdits(editorId: string, modelVersionId: number, cellEdits: ICellEditOperation[]): Promise<boolean>
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookDocumentsShape extends IDisposable {
|
||||
$tryOpenDocument(uriComponents: UriComponents): Promise<UriComponents>;
|
||||
$trySaveDocument(uri: UriComponents): Promise<boolean>;
|
||||
$tryCreateNotebook(options: { viewType: string, content?: NotebookDataDto }): Promise<UriComponents>;
|
||||
$tryOpenNotebook(uriComponents: UriComponents): Promise<UriComponents>;
|
||||
$trySaveNotebook(uri: UriComponents): Promise<boolean>;
|
||||
$applyEdits(resource: UriComponents, edits: IImmediateCellEditOperation[], computeUndoRedo?: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export interface INotebookKernelDto2 {
|
||||
id: string;
|
||||
viewType: string;
|
||||
notebookType: string;
|
||||
extensionId: ExtensionIdentifier;
|
||||
extensionLocation: UriComponents;
|
||||
label: string;
|
||||
@@ -920,7 +921,7 @@ export interface INotebookKernelDto2 {
|
||||
description?: string;
|
||||
supportedLanguages?: string[];
|
||||
supportsInterrupt?: boolean;
|
||||
hasExecutionOrder?: boolean;
|
||||
supportsExecutionOrder?: boolean;
|
||||
preloads?: { uri: UriComponents; provides: string[] }[];
|
||||
}
|
||||
|
||||
@@ -932,6 +933,10 @@ export interface MainThreadNotebookKernelsShape extends IDisposable {
|
||||
$updateNotebookPriority(handle: number, uri: UriComponents, value: number | undefined): void;
|
||||
}
|
||||
|
||||
export interface MainThreadNotebookRenderersShape extends IDisposable {
|
||||
$postMessage(editorId: string, rendererId: string, message: unknown): void;
|
||||
}
|
||||
|
||||
export interface MainThreadUrlsShape extends IDisposable {
|
||||
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void>;
|
||||
$unregisterUriHandler(handle: number): Promise<void>;
|
||||
@@ -1312,6 +1317,7 @@ export type IResolveAuthorityResult = IResolveAuthorityErrorResult | IResolveAut
|
||||
|
||||
export interface ExtHostExtensionServiceShape {
|
||||
$resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult>;
|
||||
$getCanonicalURI(remoteAuthority: string, uri: UriComponents): Promise<UriComponents>;
|
||||
$startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
|
||||
$extensionTestsExecute(): Promise<number>;
|
||||
$extensionTestsExit(code: number): Promise<void>;
|
||||
@@ -1450,17 +1456,16 @@ export interface ISignatureHelpContextDto {
|
||||
readonly activeSignatureHelp?: ISignatureHelpDto;
|
||||
}
|
||||
|
||||
export interface IInlineHintDto {
|
||||
export interface IInlayHintDto {
|
||||
text: string;
|
||||
range: IRange;
|
||||
kind: modes.InlineHintKind;
|
||||
position: IPosition;
|
||||
kind: modes.InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
hoverMessage?: string;
|
||||
}
|
||||
|
||||
export interface IInlineHintsDto {
|
||||
hints: IInlineHintDto[]
|
||||
export interface IInlayHintsDto {
|
||||
hints: IInlayHintDto[]
|
||||
}
|
||||
|
||||
export interface ILocationDto {
|
||||
@@ -1653,9 +1658,12 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<ISuggestResultDto | undefined>;
|
||||
$resolveCompletionItem(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined>;
|
||||
$releaseCompletionItems(handle: number, id: number): void;
|
||||
$provideInlineCompletions(handle: number, resource: UriComponents, position: IPosition, context: modes.InlineCompletionContext, token: CancellationToken): Promise<IdentifiableInlineCompletions | undefined>;
|
||||
$handleInlineCompletionDidShow(handle: number, pid: number, idx: number): void;
|
||||
$freeInlineCompletionsList(handle: number, pid: number): void;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<ISignatureHelpDto | undefined>;
|
||||
$releaseSignatureHelp(handle: number, id: number): void;
|
||||
$provideInlineHints(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<IInlineHintsDto | undefined>
|
||||
$provideInlayHints(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<IInlayHintsDto | undefined>
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<ILinksListDto | undefined>;
|
||||
$resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<ILinkDto | undefined>;
|
||||
$releaseDocumentLinks(handle: number, id: number): void;
|
||||
@@ -1686,11 +1694,6 @@ export interface ExtHostTelemetryShape {
|
||||
$onDidChangeTelemetryEnabled(enabled: boolean): void;
|
||||
}
|
||||
|
||||
export interface IShellAndArgsDto {
|
||||
shell: string;
|
||||
args: string[] | string | undefined;
|
||||
}
|
||||
|
||||
export interface ITerminalLinkDto {
|
||||
/** The ID of the link to enable activation and disposal. */
|
||||
id: number;
|
||||
@@ -1724,11 +1727,11 @@ export interface ExtHostTerminalServiceShape {
|
||||
$acceptProcessRequestInitialCwd(id: number): void;
|
||||
$acceptProcessRequestCwd(id: number): void;
|
||||
$acceptProcessRequestLatency(id: number): number;
|
||||
$getAvailableProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]>;
|
||||
$getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
|
||||
$provideLinks(id: number, line: string): Promise<ITerminalLinkDto[]>;
|
||||
$activateLink(id: number, linkId: number): void;
|
||||
$initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void;
|
||||
$acceptDefaultProfile(profile: ITerminalProfile, automationProfile: ITerminalProfile): void;
|
||||
$createContributedProfileTerminal(id: string, isSplitTerminal: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostSCMShape {
|
||||
@@ -1747,7 +1750,6 @@ export interface ExtHostTaskShape {
|
||||
$onDidEndTaskProcess(value: tasks.TaskProcessEndedDTO): void;
|
||||
$OnDidEndTask(execution: tasks.TaskExecutionDTO): void;
|
||||
$resolveVariables(workspaceFolder: UriComponents, toResolve: { process?: { name: string; cwd?: string; }, variables: string[]; }): Promise<{ process?: string; variables: { [key: string]: string; }; }>;
|
||||
$getDefaultShellAndArgs(): Thenable<{ shell: string, args: string[] | string | undefined; }>;
|
||||
$jsonTasksSupported(): Thenable<boolean>;
|
||||
$findExecutable(command: string, cwd?: string, paths?: string[]): Promise<string | undefined>;
|
||||
}
|
||||
@@ -1806,6 +1808,7 @@ export interface IDebugSessionFullDto {
|
||||
id: DebugSessionUUID;
|
||||
type: string;
|
||||
name: string;
|
||||
parent: DebugSessionUUID | undefined;
|
||||
folderUri: UriComponents | undefined;
|
||||
configuration: IConfig;
|
||||
}
|
||||
@@ -1913,22 +1916,7 @@ export interface INotebookDocumentsAndEditorsDelta {
|
||||
visibleEditors?: string[];
|
||||
}
|
||||
|
||||
export interface INotebookKernelInfoDto2 {
|
||||
id?: string;
|
||||
friendlyId: string;
|
||||
label: string;
|
||||
extension: ExtensionIdentifier;
|
||||
extensionLocation: UriComponents;
|
||||
providerHandle?: number;
|
||||
description?: string;
|
||||
detail?: string;
|
||||
isPreferred?: boolean;
|
||||
preloads?: { uri: UriComponents; provides: string[] }[];
|
||||
supportedLanguages?: string[]
|
||||
implementsInterrupt?: boolean;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookShape extends ExtHostNotebookDocumentsAndEditorsShape, ExtHostNotebookDocumentsShape, ExtHostNotebookEditorsShape {
|
||||
export interface ExtHostNotebookShape extends ExtHostNotebookDocumentsAndEditorsShape {
|
||||
$provideNotebookCellStatusBarItems(handle: number, uri: UriComponents, index: number, token: CancellationToken): Promise<INotebookCellStatusBarListDto | undefined>;
|
||||
$releaseNotebookCellStatusBarItems(id: number): void;
|
||||
|
||||
@@ -1941,6 +1929,10 @@ export interface ExtHostNotebookShape extends ExtHostNotebookDocumentsAndEditors
|
||||
$notebookToData(handle: number, data: NotebookDataDto, token: CancellationToken): Promise<VSBuffer>;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookRenderersShape {
|
||||
$postRendererMessage(editorId: string, rendererId: string, message: unknown): void;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookDocumentsAndEditorsShape {
|
||||
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): void;
|
||||
}
|
||||
@@ -1960,10 +1952,10 @@ export interface ExtHostNotebookEditorsShape {
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookKernelsShape {
|
||||
$acceptSelection(handle: number, uri: UriComponents, value: boolean): void;
|
||||
$acceptNotebookAssociation(handle: number, uri: UriComponents, value: boolean): void;
|
||||
$executeCells(handle: number, uri: UriComponents, handles: number[]): Promise<void>;
|
||||
$cancelCells(handle: number, uri: UriComponents, handles: number[]): Promise<void>;
|
||||
$acceptRendererMessage(handle: number, editorId: string, message: any): void;
|
||||
$acceptKernelMessageFromRenderer(handle: number, editorId: string, message: any): void;
|
||||
}
|
||||
|
||||
export interface ExtHostStorageShape {
|
||||
@@ -2094,6 +2086,7 @@ export const MainContext = {
|
||||
MainThreadNotebookDocuments: createMainId<MainThreadNotebookDocumentsShape>('MainThreadNotebookDocumentsShape'),
|
||||
MainThreadNotebookEditors: createMainId<MainThreadNotebookEditorsShape>('MainThreadNotebookEditorsShape'),
|
||||
MainThreadNotebookKernels: createMainId<MainThreadNotebookKernelsShape>('MainThreadNotebookKernels'),
|
||||
MainThreadNotebookRenderers: createMainId<MainThreadNotebookRenderersShape>('MainThreadNotebookRenderers'),
|
||||
MainThreadTheming: createMainId<MainThreadThemingShape>('MainThreadTheming'),
|
||||
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService'),
|
||||
MainThreadTimeline: createMainId<MainThreadTimelineShape>('MainThreadTimeline'),
|
||||
@@ -2140,7 +2133,10 @@ export const ExtHostContext = {
|
||||
ExtHostOutputService: createMainId<ExtHostOutputServiceShape>('ExtHostOutputService'),
|
||||
ExtHosLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService'),
|
||||
ExtHostNotebook: createMainId<ExtHostNotebookShape>('ExtHostNotebook'),
|
||||
ExtHostNotebookDocuments: createMainId<ExtHostNotebookDocumentsShape>('ExtHostNotebookDocuments'),
|
||||
ExtHostNotebookEditors: createMainId<ExtHostNotebookEditorsShape>('ExtHostNotebookEditors'),
|
||||
ExtHostNotebookKernels: createMainId<ExtHostNotebookKernelsShape>('ExtHostNotebookKernels'),
|
||||
ExtHostNotebookRenderers: createMainId<ExtHostNotebookRenderersShape>('ExtHostNotebookRenderers'),
|
||||
ExtHostTheming: createMainId<ExtHostThemingShape>('ExtHostTheming'),
|
||||
ExtHostTunnelService: createMainId<ExtHostTunnelServiceShape>('ExtHostTunnelService'),
|
||||
ExtHostAuthentication: createMainId<ExtHostAuthenticationShape>('ExtHostAuthentication'),
|
||||
|
||||
@@ -4,17 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IRawColorInfo, IWorkspaceEditDto, ICallHierarchyItemDto, IIncomingCallDto, IOutgoingCallDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ApiCommand, ApiCommandArgument, ApiCommandResult, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { CustomCodeAction } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { ICommandsExecutor, RemoveFromRecentlyOpenedAPICommand, OpenIssueReporter, OpenIssueReporterArgs } from './apiCommands';
|
||||
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
@@ -326,10 +323,10 @@ const newCommands: ApiCommand[] = [
|
||||
),
|
||||
// --- inline hints
|
||||
new ApiCommand(
|
||||
'vscode.executeInlineHintProvider', '_executeInlineHintProvider', 'Execute inline hints provider',
|
||||
'vscode.executeInlayHintProvider', '_executeInlayHintProvider', 'Execute inlay hints provider',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Range],
|
||||
new ApiCommandResult<modes.InlineHint[], vscode.InlineHint[]>('A promise that resolves to an array of InlineHint objects', result => {
|
||||
return result.map(typeConverters.InlineHint.to);
|
||||
new ApiCommandResult<modes.InlayHint[], vscode.InlayHint[]>('A promise that resolves to an array of Inlay objects', result => {
|
||||
return result.map(typeConverters.InlayHint.to);
|
||||
})
|
||||
),
|
||||
// --- notebooks
|
||||
@@ -420,63 +417,8 @@ export class ExtHostApiCommands {
|
||||
|
||||
static register(commands: ExtHostCommands) {
|
||||
newCommands.forEach(commands.registerApiCommand, commands);
|
||||
return new ExtHostApiCommands(commands).registerCommands();
|
||||
}
|
||||
|
||||
private _commands: ExtHostCommands;
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
private constructor(commands: ExtHostCommands) {
|
||||
this._commands = commands;
|
||||
}
|
||||
|
||||
registerCommands() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following commands are registered on both sides separately.
|
||||
//
|
||||
// We are trying to maintain backwards compatibility for cases where
|
||||
// API commands are encoded as markdown links, for example.
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
type ICommandHandler = (...args: any[]) => any;
|
||||
const adjustHandler = (handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler => {
|
||||
return (...args: any[]) => {
|
||||
return handler(this._commands, ...args);
|
||||
};
|
||||
};
|
||||
|
||||
this._register(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute), {
|
||||
description: 'Removes an entry with the given path from the recently opened list.',
|
||||
args: [
|
||||
{ name: 'path', description: 'Path to remove from recently opened.', constraint: (value: any) => typeof value === 'string' }
|
||||
]
|
||||
});
|
||||
|
||||
this._register(OpenIssueReporter.ID, adjustHandler(OpenIssueReporter.execute), {
|
||||
description: 'Opens the issue reporter with the provided extension id as the selected source',
|
||||
args: [
|
||||
{ name: 'extensionId', description: 'extensionId to report an issue on', constraint: (value: unknown) => typeof value === 'string' || (typeof value === 'object' && typeof (value as OpenIssueReporterArgs).extensionId === 'string') }
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// --- command impl
|
||||
|
||||
/**
|
||||
* @deprecated use the ApiCommand instead
|
||||
*/
|
||||
private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void {
|
||||
const disposable = this._commands.registerCommand(false, id, handler, this, description);
|
||||
this._disposables.add(disposable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function tryMapWith<T, R>(f: (x: T) => R) {
|
||||
|
||||
@@ -48,11 +48,11 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
return Object.freeze(this._providers.slice());
|
||||
}
|
||||
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise<vscode.AuthenticationSession | undefined> {
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise<vscode.AuthenticationSession>;
|
||||
async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise<vscode.AuthenticationSession | undefined> {
|
||||
const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier);
|
||||
const inFlightRequests = this._inFlightRequests.get(extensionId) || [];
|
||||
const sortedScopes = scopes.sort().join(' ');
|
||||
const sortedScopes = [...scopes].sort().join(' ');
|
||||
let inFlightRequest: GetSessionsRequest | undefined = inFlightRequests.find(request => request.scopes === sortedScopes);
|
||||
|
||||
if (inFlightRequest) {
|
||||
@@ -81,7 +81,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
||||
}
|
||||
}
|
||||
|
||||
private async _getSession(requestingExtension: IExtensionDescription, extensionId: string, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise<vscode.AuthenticationSession | undefined> {
|
||||
private async _getSession(requestingExtension: IExtensionDescription, extensionId: string, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise<vscode.AuthenticationSession | undefined> {
|
||||
await this._proxy.$ensureProvider(providerId);
|
||||
const extensionName = requestingExtension.displayName || requestingExtension.name;
|
||||
return this._proxy.$getSession(providerId, scopes, extensionId, extensionName, options);
|
||||
|
||||
@@ -8,10 +8,9 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtHostTextEditor } from 'vs/workbench/api/common/extHostTextEditor';
|
||||
import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors';
|
||||
import { asWebviewUri, webviewGenericCspSource, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostEditorInsetsShape, MainThreadEditorInsetsShape } from './extHost.protocol';
|
||||
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
|
||||
export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {
|
||||
|
||||
@@ -61,16 +60,15 @@ export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {
|
||||
|
||||
const webview = new class implements vscode.Webview {
|
||||
|
||||
private readonly _uuid = generateUuid();
|
||||
private _html: string = '';
|
||||
private _options: vscode.WebviewOptions = Object.create(null);
|
||||
|
||||
asWebviewUri(resource: vscode.Uri): vscode.Uri {
|
||||
return asWebviewUri(that._initData, this._uuid, resource);
|
||||
return asWebviewUri(resource, that._initData.remote);
|
||||
}
|
||||
|
||||
get cspSource(): string {
|
||||
return that._initData.webviewCspSource;
|
||||
return webviewGenericCspSource;
|
||||
}
|
||||
|
||||
set options(value: vscode.WebviewOptions) {
|
||||
|
||||
@@ -170,12 +170,12 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
const toArgs = cloneAndChange(args, function (value) {
|
||||
if (value instanceof extHostTypes.Position) {
|
||||
return extHostTypeConverter.Position.from(value);
|
||||
}
|
||||
if (value instanceof extHostTypes.Range) {
|
||||
} else if (value instanceof extHostTypes.Range) {
|
||||
return extHostTypeConverter.Range.from(value);
|
||||
}
|
||||
if (value instanceof extHostTypes.Location) {
|
||||
} else if (value instanceof extHostTypes.Location) {
|
||||
return extHostTypeConverter.location.from(value);
|
||||
} else if (extHostTypes.NotebookRange.isNotebookRange(value)) {
|
||||
return extHostTypeConverter.NotebookRange.from(value);
|
||||
}
|
||||
if (!Array.isArray(value)) {
|
||||
return value;
|
||||
|
||||
@@ -31,6 +31,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import * as process from 'vs/base/common/process';
|
||||
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
|
||||
export const IExtHostDebugService = createDecorator<IExtHostDebugService>('IExtHostDebugService');
|
||||
|
||||
@@ -47,8 +48,8 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape {
|
||||
onDidChangeBreakpoints: Event<vscode.BreakpointsChangeEvent>;
|
||||
breakpoints: vscode.Breakpoint[];
|
||||
|
||||
addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
|
||||
addBreakpoints(breakpoints0: readonly vscode.Breakpoint[]): Promise<void>;
|
||||
removeBreakpoints(breakpoints0: readonly vscode.Breakpoint[]): Promise<void>;
|
||||
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise<boolean>;
|
||||
stopDebugging(session?: vscode.DebugSession): Promise<void>;
|
||||
registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider, trigger: vscode.DebugConfigurationProviderTriggerKind): vscode.Disposable;
|
||||
@@ -109,6 +110,7 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
|
||||
@IExtHostExtensionService private _extensionService: IExtHostExtensionService,
|
||||
@IExtHostDocumentsAndEditors private _editorsService: IExtHostDocumentsAndEditors,
|
||||
@IExtHostConfiguration protected _configurationService: IExtHostConfiguration,
|
||||
@IExtHostEditorTabs protected _editorTabs: IExtHostEditorTabs
|
||||
) {
|
||||
this._configProviderHandleCounter = 0;
|
||||
this._configProviders = [];
|
||||
@@ -843,7 +845,8 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
|
||||
let ds = this._debugSessions.get(dto.id);
|
||||
if (!ds) {
|
||||
const folder = await this.getFolder(dto.folderUri);
|
||||
ds = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, folder, dto.configuration);
|
||||
const parent = dto.parent ? this._debugSessions.get(dto.parent) : undefined;
|
||||
ds = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, folder, dto.configuration, parent);
|
||||
this._debugSessions.set(ds.id, ds);
|
||||
this._debugServiceProxy.$sessionCached(ds.id);
|
||||
}
|
||||
@@ -870,7 +873,8 @@ export class ExtHostDebugSession implements vscode.DebugSession {
|
||||
private _type: string,
|
||||
private _name: string,
|
||||
private _workspaceFolder: vscode.WorkspaceFolder | undefined,
|
||||
private _configuration: vscode.DebugConfiguration) {
|
||||
private _configuration: vscode.DebugConfiguration,
|
||||
private _parentSession: vscode.DebugSession | undefined) {
|
||||
}
|
||||
|
||||
public get id(): string {
|
||||
@@ -884,12 +888,15 @@ export class ExtHostDebugSession implements vscode.DebugSession {
|
||||
public get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public set name(name: string) {
|
||||
this._name = name;
|
||||
this._debugServiceProxy.$setDebugSessionName(this._id, name);
|
||||
}
|
||||
|
||||
public get parentSession(): vscode.DebugSession | undefined {
|
||||
return this._parentSession;
|
||||
}
|
||||
|
||||
_acceptNameChanged(name: string) {
|
||||
this._name = name;
|
||||
}
|
||||
@@ -930,7 +937,21 @@ export class ExtHostDebugConsole {
|
||||
|
||||
export class ExtHostVariableResolverService extends AbstractVariableResolverService {
|
||||
|
||||
constructor(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors | undefined, configurationService: ExtHostConfigProvider, workspaceService?: IExtHostWorkspace) {
|
||||
constructor(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors | undefined, configurationService: ExtHostConfigProvider, editorTabs: IExtHostEditorTabs, workspaceService?: IExtHostWorkspace) {
|
||||
function getActiveUri(): URI | undefined {
|
||||
if (editorService) {
|
||||
const activeEditor = editorService.activeEditor();
|
||||
if (activeEditor) {
|
||||
return activeEditor.document.uri;
|
||||
}
|
||||
const tabs = editorTabs.tabs.filter(tab => tab.isActive);
|
||||
if (tabs.length > 0) {
|
||||
return tabs[0].resource;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
super({
|
||||
getFolderUri: (folderName: string): URI | undefined => {
|
||||
const found = folders.filter(f => f.name === folderName);
|
||||
@@ -952,19 +973,17 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ
|
||||
return process.env['VSCODE_EXEC_PATH'];
|
||||
},
|
||||
getFilePath: (): string | undefined => {
|
||||
if (editorService) {
|
||||
const activeEditor = editorService.activeEditor();
|
||||
if (activeEditor) {
|
||||
return path.normalize(activeEditor.document.uri.fsPath);
|
||||
}
|
||||
const activeUri = getActiveUri();
|
||||
if (activeUri) {
|
||||
return path.normalize(activeUri.fsPath);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
getWorkspaceFolderPathForFile: (): string | undefined => {
|
||||
if (editorService && workspaceService) {
|
||||
const activeEditor = editorService.activeEditor();
|
||||
if (activeEditor) {
|
||||
const ws = workspaceService.getWorkspaceFolder(activeEditor.document.uri);
|
||||
if (workspaceService) {
|
||||
const activeUri = getActiveUri();
|
||||
if (activeUri) {
|
||||
const ws = workspaceService.getWorkspaceFolder(activeUri);
|
||||
if (ws) {
|
||||
return path.normalize(ws.uri.fsPath);
|
||||
}
|
||||
@@ -1076,12 +1095,13 @@ export class WorkerExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
@IExtHostWorkspace workspaceService: IExtHostWorkspace,
|
||||
@IExtHostExtensionService extensionService: IExtHostExtensionService,
|
||||
@IExtHostDocumentsAndEditors editorsService: IExtHostDocumentsAndEditors,
|
||||
@IExtHostConfiguration configurationService: IExtHostConfiguration
|
||||
@IExtHostConfiguration configurationService: IExtHostConfiguration,
|
||||
@IExtHostEditorTabs editorTabs: IExtHostEditorTabs
|
||||
) {
|
||||
super(extHostRpcService, workspaceService, extensionService, editorsService, configurationService);
|
||||
super(extHostRpcService, workspaceService, extensionService, editorsService, configurationService, editorTabs);
|
||||
}
|
||||
|
||||
protected createVariableResolver(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider): AbstractVariableResolverService {
|
||||
return new ExtHostVariableResolverService(folders, editorService, configurationService);
|
||||
return new ExtHostVariableResolverService(folders, editorService, configurationService, this._editorTabs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
private readonly _collections = new Map<string, DiagnosticCollection>();
|
||||
private readonly _onDidChangeDiagnostics = new Emitter<vscode.Uri[]>();
|
||||
|
||||
static _debouncer(last: (vscode.Uri | string)[] | undefined, current: (vscode.Uri | string)[]): (vscode.Uri | string)[] {
|
||||
static _debouncer(last: vscode.Uri[] | undefined, current: vscode.Uri[]): vscode.Uri[] {
|
||||
if (!last) {
|
||||
return current;
|
||||
} else {
|
||||
@@ -225,24 +225,12 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
}
|
||||
}
|
||||
|
||||
static _mapper(last: (vscode.Uri | string)[]): { uris: vscode.Uri[] } {
|
||||
const uris: vscode.Uri[] = [];
|
||||
const map = new Set<string>();
|
||||
static _mapper(last: vscode.Uri[]): { uris: readonly vscode.Uri[] } {
|
||||
const map = new ResourceMap<vscode.Uri>();
|
||||
for (const uri of last) {
|
||||
if (typeof uri === 'string') {
|
||||
if (!map.has(uri)) {
|
||||
map.add(uri);
|
||||
uris.push(URI.parse(uri));
|
||||
}
|
||||
} else {
|
||||
if (!map.has(uri.toString())) {
|
||||
map.add(uri.toString());
|
||||
uris.push(uri);
|
||||
}
|
||||
}
|
||||
map.set(uri, uri);
|
||||
}
|
||||
Object.freeze(uris);
|
||||
return { uris };
|
||||
return { uris: Object.freeze(Array.from(map.values())) };
|
||||
}
|
||||
|
||||
readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = Event.map(Event.debounce(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._debouncer, 50), ExtHostDiagnostics._mapper);
|
||||
|
||||
@@ -7,15 +7,25 @@ import type * as vscode from 'vscode';
|
||||
import { IEditorTabDto, IExtHostEditorTabsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IEditorTab {
|
||||
name: string;
|
||||
group: number;
|
||||
resource: vscode.Uri
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
export class ExtHostEditorTabs implements IExtHostEditorTabsShape {
|
||||
export interface IExtHostEditorTabs extends IExtHostEditorTabsShape {
|
||||
readonly _serviceBrand: undefined;
|
||||
tabs: readonly IEditorTab[];
|
||||
onDidChangeTabs: Event<void>;
|
||||
}
|
||||
|
||||
export const IExtHostEditorTabs = createDecorator<IExtHostEditorTabs>('IExtHostEditorTabs');
|
||||
|
||||
export class ExtHostEditorTabs implements IExtHostEditorTabs {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeTabs = new Emitter<void>();
|
||||
readonly onDidChangeTabs: Event<void> = this._onDidChangeTabs.event;
|
||||
@@ -31,7 +41,8 @@ export class ExtHostEditorTabs implements IExtHostEditorTabsShape {
|
||||
return {
|
||||
name: dto.name,
|
||||
group: dto.group,
|
||||
resource: URI.revive(dto.resource)
|
||||
resource: URI.revive(dto.resource),
|
||||
isActive: dto.isActive
|
||||
};
|
||||
});
|
||||
this._onDidChangeTabs.fire();
|
||||
|
||||
@@ -7,10 +7,10 @@ import * as nls from 'vs/nls';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import { originalFSPath, joinPath } from 'vs/base/common/resources';
|
||||
import { Barrier, timeout } from 'vs/base/common/async';
|
||||
import { asPromise, Barrier, timeout } from 'vs/base/common/async';
|
||||
import { dispose, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostExtensionServiceShape, IInitData, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IResolveAuthorityResult } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
@@ -292,19 +292,19 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
try {
|
||||
if (typeof extension.module.deactivate === 'function') {
|
||||
result = Promise.resolve(extension.module.deactivate()).then(undefined, (err) => {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
this._logService.error(err);
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
this._logService.error(err);
|
||||
}
|
||||
|
||||
// clean up subscriptions
|
||||
try {
|
||||
dispose(extension.subscriptions);
|
||||
} catch (err) {
|
||||
// TODO: Do something with err if this is not the shutdown case
|
||||
this._logService.error(err);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -631,7 +631,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
|
||||
// -- called by main thread
|
||||
|
||||
public async $resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult> {
|
||||
private async _activateAndGetResolver(remoteAuthority: string): Promise<{ authorityPrefix: string; resolver: vscode.RemoteAuthorityResolver | undefined; }> {
|
||||
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
||||
if (authorityPlusIndex === -1) {
|
||||
throw new Error(`Not an authority that can be resolved!`);
|
||||
@@ -641,7 +641,12 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
await this._almostReadyToRunExtensions.wait();
|
||||
await this._activateByEvent(`onResolveRemoteAuthority:${authorityPrefix}`, false);
|
||||
|
||||
const resolver = this._resolvers[authorityPrefix];
|
||||
return { authorityPrefix, resolver: this._resolvers[authorityPrefix] };
|
||||
}
|
||||
|
||||
public async $resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult> {
|
||||
|
||||
const { authorityPrefix, resolver } = await this._activateAndGetResolver(remoteAuthority);
|
||||
if (!resolver) {
|
||||
return {
|
||||
type: 'error',
|
||||
@@ -668,7 +673,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
};
|
||||
const options: ResolvedOptions = {
|
||||
extensionHostEnv: result.extensionHostEnv,
|
||||
trust: result.trust
|
||||
isTrusted: result.isTrusted
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -695,6 +700,28 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
}
|
||||
}
|
||||
|
||||
public async $getCanonicalURI(remoteAuthority: string, uriComponents: UriComponents): Promise<UriComponents> {
|
||||
|
||||
const { authorityPrefix, resolver } = await this._activateAndGetResolver(remoteAuthority);
|
||||
if (!resolver) {
|
||||
throw new Error(`Cannot get canonical URI because no remote extension is installed to resolve ${authorityPrefix}`);
|
||||
}
|
||||
|
||||
const uri = URI.revive(uriComponents);
|
||||
|
||||
if (typeof resolver.getCanonicalURI === 'undefined') {
|
||||
// resolver cannot compute canonical URI
|
||||
return uri;
|
||||
}
|
||||
|
||||
const result = await asPromise(() => resolver.getCanonicalURI!(uri));
|
||||
if (!result) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
this._registry.keepOnly(enabledExtensionIds);
|
||||
return this._startExtensionHost();
|
||||
|
||||
@@ -115,6 +115,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>();
|
||||
private readonly _registeredSchemes = new Set<string>();
|
||||
private readonly _watches = new Map<number, IDisposable>();
|
||||
private readonly _enableProposedApi = new Map<number, boolean>();
|
||||
|
||||
private _linkProviderRegistration?: IDisposable;
|
||||
private _handlePool: number = 0;
|
||||
@@ -133,7 +134,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
}
|
||||
}
|
||||
|
||||
registerFileSystemProvider(extension: ExtensionIdentifier, scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean, isReadonly?: boolean } = {}) {
|
||||
registerFileSystemProvider(extension: ExtensionIdentifier, scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean, isReadonly?: boolean } = {}, enableProposedApi?: boolean) {
|
||||
|
||||
if (this._registeredSchemes.has(scheme)) {
|
||||
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
|
||||
@@ -146,6 +147,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
this._linkProvider.add(scheme);
|
||||
this._registeredSchemes.add(scheme);
|
||||
this._fsProvider.set(handle, provider);
|
||||
this._enableProposedApi.set(handle, enableProposedApi ?? false);
|
||||
|
||||
let capabilities = files.FileSystemProviderCapabilities.FileReadWrite;
|
||||
if (options.isCaseSensitive) {
|
||||
@@ -200,17 +202,22 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
this._linkProvider.delete(scheme);
|
||||
this._registeredSchemes.delete(scheme);
|
||||
this._fsProvider.delete(handle);
|
||||
this._enableProposedApi.delete(handle);
|
||||
this._proxy.$unregisterProvider(handle);
|
||||
});
|
||||
}
|
||||
|
||||
private static _asIStat(stat: vscode.FileStat): files.IStat {
|
||||
const { type, ctime, mtime, size } = stat;
|
||||
return { type, ctime, mtime, size };
|
||||
private static _asIStat(stat: vscode.FileStat, enableProposedApi: boolean): files.IStat {
|
||||
const { type, ctime, mtime, size, permissions } = stat;
|
||||
if (enableProposedApi) {
|
||||
return { type, ctime, mtime, size, permissions };
|
||||
} else {
|
||||
return { type, ctime, mtime, size };
|
||||
}
|
||||
}
|
||||
|
||||
$stat(handle: number, resource: UriComponents): Promise<files.IStat> {
|
||||
return Promise.resolve(this._getFsProvider(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat);
|
||||
return Promise.resolve(this._getFsProvider(handle).stat(URI.revive(resource))).then(stat => ExtHostFileSystem._asIStat(stat, this._enableProposedApi.get(handle) ?? false));
|
||||
}
|
||||
|
||||
$readdir(handle: number, resource: UriComponents): Promise<[string, files.FileType][]> {
|
||||
|
||||
@@ -24,4 +24,4 @@ export class ExtHostLabelService implements ExtHostLabelServiceShape {
|
||||
this._proxy.$unregisterResourceLabelFormatter(handle);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range as EditorRange } from 'vs/editor/common/core/range';
|
||||
import { isFalsyOrEmpty, isNonEmptyArray, coalesce, asArray } from 'vs/base/common/arrays';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
import { isArray, isObject } from 'vs/base/common/types';
|
||||
import { ISelection, Selection } from 'vs/editor/common/core/selection';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -33,6 +33,7 @@ import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostAp
|
||||
import { Cache } from './cache';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { CancellationError } from 'vs/base/common/errors';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
// --- adapter
|
||||
|
||||
@@ -1038,6 +1039,99 @@ class SuggestAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
class InlineCompletionAdapter {
|
||||
private readonly _cache = new Cache<vscode.InlineCompletionItem>('InlineCompletionItem');
|
||||
private readonly _disposables = new Map<number, DisposableStore>();
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.InlineCompletionItemProvider,
|
||||
private readonly _commands: CommandsConverter,
|
||||
) { }
|
||||
|
||||
public async provideInlineCompletions(resource: URI, position: IPosition, context: vscode.InlineCompletionContext, token: CancellationToken): Promise<extHostProtocol.IdentifiableInlineCompletions | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
|
||||
const result = await asPromise(() => this._provider.provideInlineCompletionItems(doc, pos, context, token));
|
||||
|
||||
if (!result) {
|
||||
// undefined and null are valid results
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const normalizedResult: vscode.InlineCompletionList = isArray(result) ? { items: result } : result;
|
||||
|
||||
const pid = this._cache.add(normalizedResult.items);
|
||||
let disposableStore: DisposableStore | undefined = undefined;
|
||||
|
||||
return {
|
||||
pid,
|
||||
items: normalizedResult.items.map<extHostProtocol.IdentifiableInlineCompletion>((item, idx) => {
|
||||
let command: modes.Command | undefined = undefined;
|
||||
if (item.command) {
|
||||
if (!disposableStore) {
|
||||
disposableStore = new DisposableStore();
|
||||
this._disposables.set(pid, disposableStore);
|
||||
}
|
||||
command = this._commands.toInternal(item.command, disposableStore);
|
||||
}
|
||||
|
||||
return ({
|
||||
text: item.text,
|
||||
range: item.range ? typeConvert.Range.from(item.range) : undefined,
|
||||
command,
|
||||
idx: idx,
|
||||
});
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
public disposeCompletions(pid: number) {
|
||||
this._cache.delete(pid);
|
||||
const d = this._disposables.get(pid);
|
||||
if (d) {
|
||||
d.clear();
|
||||
}
|
||||
this._disposables.delete(pid);
|
||||
}
|
||||
|
||||
public handleDidShowCompletionItem(pid: number, idx: number): void {
|
||||
const completionItem = this._cache.get(pid, idx);
|
||||
if (completionItem) {
|
||||
InlineCompletionController.get(this._provider).fireOnDidShowCompletionItem({
|
||||
completionItem
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class InlineCompletionController<T extends vscode.InlineCompletionItem> implements vscode.InlineCompletionController<T> {
|
||||
private static readonly map = new WeakMap<vscode.InlineCompletionItemProvider<any>, InlineCompletionController<any>>();
|
||||
|
||||
public static get<T extends vscode.InlineCompletionItem>(provider: vscode.InlineCompletionItemProvider<T>): InlineCompletionController<T> {
|
||||
let existing = InlineCompletionController.map.get(provider);
|
||||
if (!existing) {
|
||||
existing = new InlineCompletionController();
|
||||
InlineCompletionController.map.set(provider, existing);
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
private readonly _onDidShowCompletionItemEmitter = new Emitter<vscode.InlineCompletionItemDidShowEvent<T>>();
|
||||
public readonly onDidShowCompletionItem: vscode.Event<vscode.InlineCompletionItemDidShowEvent<T>> = this._onDidShowCompletionItemEmitter.event;
|
||||
|
||||
public fireOnDidShowCompletionItem(event: vscode.InlineCompletionItemDidShowEvent<T>): void {
|
||||
this._onDidShowCompletionItemEmitter.fire(event);
|
||||
}
|
||||
}
|
||||
|
||||
class SignatureHelpAdapter {
|
||||
|
||||
private readonly _cache = new Cache<vscode.SignatureHelp>('SignatureHelp');
|
||||
@@ -1082,16 +1176,16 @@ class SignatureHelpAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
class InlineHintsAdapter {
|
||||
class InlayHintsAdapter {
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.InlineHintsProvider,
|
||||
private readonly _provider: vscode.InlayHintsProvider,
|
||||
) { }
|
||||
|
||||
provideInlineHints(resource: URI, range: IRange, token: CancellationToken): Promise<extHostProtocol.IInlineHintsDto | undefined> {
|
||||
provideInlayHints(resource: URI, range: IRange, token: CancellationToken): Promise<extHostProtocol.IInlayHintsDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
return asPromise(() => this._provider.provideInlineHints(doc, typeConvert.Range.to(range), token)).then(value => {
|
||||
return value ? { hints: value.map(typeConvert.InlineHint.from) } : undefined;
|
||||
return asPromise(() => this._provider.provideInlayHints(doc, typeConvert.Range.to(range), token)).then(value => {
|
||||
return value ? { hints: value.map(typeConvert.InlayHint.from) } : undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1105,50 +1199,62 @@ class LinkProviderAdapter {
|
||||
private readonly _provider: vscode.DocumentLinkProvider
|
||||
) { }
|
||||
|
||||
provideLinks(resource: URI, token: CancellationToken): Promise<extHostProtocol.ILinksListDto | undefined> {
|
||||
async provideLinks(resource: URI, token: CancellationToken): Promise<extHostProtocol.ILinksListDto | undefined> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
|
||||
return asPromise(() => this._provider.provideDocumentLinks(doc, token)).then(links => {
|
||||
if (!Array.isArray(links) || links.length === 0) {
|
||||
// bad result
|
||||
return undefined;
|
||||
}
|
||||
const links = await asPromise(() => this._provider.provideDocumentLinks(doc, token));
|
||||
if (!Array.isArray(links) || links.length === 0) {
|
||||
// bad result
|
||||
return undefined;
|
||||
}
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
if (typeof this._provider.resolveDocumentLink !== 'function') {
|
||||
// no resolve -> no caching
|
||||
return { links: links.filter(LinkProviderAdapter._validateLink).map(typeConvert.DocumentLink.from) };
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
// cancelled -> return without further ado, esp no caching
|
||||
// of results as they will leak
|
||||
return undefined;
|
||||
}
|
||||
} else {
|
||||
// cache links for future resolving
|
||||
const pid = this._cache.add(links);
|
||||
const result: extHostProtocol.ILinksListDto = { links: [], id: pid };
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
|
||||
if (typeof this._provider.resolveDocumentLink !== 'function') {
|
||||
// no resolve -> no caching
|
||||
return { links: links.map(typeConvert.DocumentLink.from) };
|
||||
|
||||
} else {
|
||||
// cache links for future resolving
|
||||
const pid = this._cache.add(links);
|
||||
const result: extHostProtocol.ILinksListDto = { links: [], id: pid };
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
const dto: extHostProtocol.ILinkDto = typeConvert.DocumentLink.from(links[i]);
|
||||
dto.cacheId = [pid, i];
|
||||
result.links.push(dto);
|
||||
if (!LinkProviderAdapter._validateLink(links[i])) {
|
||||
continue;
|
||||
}
|
||||
return result;
|
||||
|
||||
const dto: extHostProtocol.ILinkDto = typeConvert.DocumentLink.from(links[i]);
|
||||
dto.cacheId = [pid, i];
|
||||
result.links.push(dto);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
resolveLink(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ILinkDto | undefined> {
|
||||
private static _validateLink(link: vscode.DocumentLink): boolean {
|
||||
if (link.target && link.target.path.length > 50_000) {
|
||||
console.warn('DROPPING link because it is too long');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async resolveLink(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ILinkDto | undefined> {
|
||||
if (typeof this._provider.resolveDocumentLink !== 'function') {
|
||||
return Promise.resolve(undefined);
|
||||
return undefined;
|
||||
}
|
||||
const item = this._cache.get(...id);
|
||||
if (!item) {
|
||||
return Promise.resolve(undefined);
|
||||
return undefined;
|
||||
}
|
||||
return asPromise(() => this._provider.resolveDocumentLink!(item, token)).then(value => {
|
||||
return value && typeConvert.DocumentLink.from(value) || undefined;
|
||||
});
|
||||
const link = await asPromise(() => this._provider.resolveDocumentLink!(item, token));
|
||||
if (!link || !LinkProviderAdapter._validateLink(link)) {
|
||||
return undefined;
|
||||
}
|
||||
return typeConvert.DocumentLink.from(link);
|
||||
}
|
||||
|
||||
releaseLinks(id: number): any {
|
||||
@@ -1355,7 +1461,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov
|
||||
| TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter
|
||||
| SelectionRangeAdapter | CallHierarchyAdapter | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter
|
||||
| EvaluatableExpressionAdapter | InlineValuesAdapter
|
||||
| LinkedEditingRangeAdapter | InlineHintsAdapter;
|
||||
| LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter;
|
||||
|
||||
class AdapterData {
|
||||
constructor(
|
||||
@@ -1809,6 +1915,28 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id), undefined);
|
||||
}
|
||||
|
||||
// --- ghost test
|
||||
|
||||
registerInlineCompletionsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new InlineCompletionAdapter(this._documents, provider, this._commands.converter), extension);
|
||||
this._proxy.$registerInlineCompletionsSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideInlineCompletions(handle: number, resource: UriComponents, position: IPosition, context: modes.InlineCompletionContext, token: CancellationToken): Promise<extHostProtocol.IdentifiableInlineCompletions | undefined> {
|
||||
return this._withAdapter(handle, InlineCompletionAdapter, adapter => adapter.provideInlineCompletions(URI.revive(resource), position, context, token), undefined);
|
||||
}
|
||||
|
||||
$handleInlineCompletionDidShow(handle: number, pid: number, idx: number): void {
|
||||
this._withAdapter(handle, InlineCompletionAdapter, async adapter => {
|
||||
adapter.handleDidShowCompletionItem(pid, idx);
|
||||
}, undefined);
|
||||
}
|
||||
|
||||
$freeInlineCompletionsList(handle: number, pid: number): void {
|
||||
this._withAdapter(handle, InlineCompletionAdapter, async adapter => { adapter.disposeCompletions(pid); }, undefined);
|
||||
}
|
||||
|
||||
// --- parameter hints
|
||||
|
||||
registerSignatureHelpProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, metadataOrTriggerChars: string[] | vscode.SignatureHelpProviderMetadata): vscode.Disposable {
|
||||
@@ -1831,23 +1959,23 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
|
||||
// --- inline hints
|
||||
|
||||
registerInlineHintsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineHintsProvider): vscode.Disposable {
|
||||
registerInlayHintsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {
|
||||
|
||||
const eventHandle = typeof provider.onDidChangeInlineHints === 'function' ? this._nextHandle() : undefined;
|
||||
const handle = this._addNewAdapter(new InlineHintsAdapter(this._documents, provider), extension);
|
||||
const eventHandle = typeof provider.onDidChangeInlayHints === 'function' ? this._nextHandle() : undefined;
|
||||
const handle = this._addNewAdapter(new InlayHintsAdapter(this._documents, provider), extension);
|
||||
|
||||
this._proxy.$registerInlineHintsProvider(handle, this._transformDocumentSelector(selector), eventHandle);
|
||||
this._proxy.$registerInlayHintsProvider(handle, this._transformDocumentSelector(selector), eventHandle);
|
||||
let result = this._createDisposable(handle);
|
||||
|
||||
if (eventHandle !== undefined) {
|
||||
const subscription = provider.onDidChangeInlineHints!(_ => this._proxy.$emitInlineHintsEvent(eventHandle));
|
||||
const subscription = provider.onDidChangeInlayHints!(_ => this._proxy.$emitInlayHintsEvent(eventHandle));
|
||||
result = Disposable.from(result, subscription);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
$provideInlineHints(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<extHostProtocol.IInlineHintsDto | undefined> {
|
||||
return this._withAdapter(handle, InlineHintsAdapter, adapter => adapter.provideInlineHints(URI.revive(resource), range, token), undefined);
|
||||
$provideInlayHints(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<extHostProtocol.IInlayHintsDto | undefined> {
|
||||
return this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.provideInlayHints(URI.revive(resource), range, token), undefined);
|
||||
}
|
||||
|
||||
// --- links
|
||||
|
||||
@@ -56,6 +56,11 @@ export class ExtensionMemento implements vscode.Memento {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
get keys(): readonly string[] {
|
||||
// Filter out `undefined` values, as they can stick around in the `_value` until the `onDidChangeStorage` event runs
|
||||
return Object.entries(this._value ?? {}).filter(([, value]) => value !== undefined).map(([key]) => key);
|
||||
}
|
||||
|
||||
get whenReady(): Promise<ExtensionMemento> {
|
||||
return this._init;
|
||||
}
|
||||
|
||||
@@ -3,54 +3,31 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Cache } from 'vs/workbench/api/common/cache';
|
||||
import { ExtHostNotebookShape, IMainContext, IModelAddedData, INotebookCellStatusBarListDto, INotebookDocumentPropertiesChangeData, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookEditorAddData, INotebookEditorPropertiesChangeData, INotebookEditorViewColumnInfo, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookEditorsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookShape, IMainContext, IModelAddedData, INotebookCellStatusBarListDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookEditorAddData, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookEditorsShape, MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { CellEditType, IImmediateCellEditOperation, INotebookExclusiveDocumentFilter, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookDataDto, NullablePartialNotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookExclusiveDocumentFilter, INotebookContributionData, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from './extHostNotebookDocument';
|
||||
import { ExtHostNotebookEditor } from './extHostNotebookEditor';
|
||||
|
||||
|
||||
export class NotebookEditorDecorationType {
|
||||
|
||||
private static readonly _Keys = new IdGenerator('NotebookEditorDecorationType');
|
||||
|
||||
readonly value: vscode.NotebookEditorDecorationType;
|
||||
|
||||
constructor(proxy: MainThreadNotebookEditorsShape, options: vscode.NotebookDecorationRenderOptions) {
|
||||
const key = NotebookEditorDecorationType._Keys.nextId();
|
||||
proxy.$registerNotebookEditorDecorationType(key, typeConverters.NotebookDecorationRenderOptions.from(options));
|
||||
|
||||
this.value = {
|
||||
key,
|
||||
dispose() {
|
||||
proxy.$removeNotebookEditorDecorationType(key);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type NotebookContentProviderData = {
|
||||
readonly provider: vscode.NotebookContentProvider;
|
||||
readonly extension: IExtensionDescription;
|
||||
@@ -68,12 +45,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
private readonly _documents = new ResourceMap<ExtHostNotebookDocument>();
|
||||
private readonly _editors = new Map<string, ExtHostNotebookEditor>();
|
||||
private readonly _commandsConverter: CommandsConverter;
|
||||
private readonly _onDidChangeNotebookEditorSelection = new Emitter<vscode.NotebookEditorSelectionChangeEvent>();
|
||||
readonly onDidChangeNotebookEditorSelection = this._onDidChangeNotebookEditorSelection.event;
|
||||
private readonly _onDidChangeNotebookEditorVisibleRanges = new Emitter<vscode.NotebookEditorVisibleRangesChangeEvent>();
|
||||
readonly onDidChangeNotebookEditorVisibleRanges = this._onDidChangeNotebookEditorVisibleRanges.event;
|
||||
private readonly _onDidChangeNotebookDocumentMetadata = new Emitter<vscode.NotebookDocumentMetadataChangeEvent>();
|
||||
readonly onDidChangeNotebookDocumentMetadata = this._onDidChangeNotebookDocumentMetadata.event;
|
||||
|
||||
private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
|
||||
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
|
||||
private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
|
||||
@@ -98,13 +70,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
onDidOpenNotebookDocument: Event<vscode.NotebookDocument> = this._onDidOpenNotebookDocument.event;
|
||||
private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
|
||||
onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
|
||||
private _onDidSaveNotebookDocument = new Emitter<vscode.NotebookDocument>();
|
||||
onDidSaveNotebookDocument: Event<vscode.NotebookDocument> = this._onDidSaveNotebookDocument.event;
|
||||
|
||||
private _onDidChangeVisibleNotebookEditors = new Emitter<vscode.NotebookEditor[]>();
|
||||
onDidChangeVisibleNotebookEditors = this._onDidChangeVisibleNotebookEditors.event;
|
||||
|
||||
private _activeExecutions = new ResourceMap<NotebookCellExecutionTask>();
|
||||
|
||||
private _statusBarCache = new Cache<IDisposable>('NotebookCellStatusBarCache');
|
||||
|
||||
constructor(
|
||||
@@ -112,7 +81,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
commands: ExtHostCommands,
|
||||
private _textDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private _textDocuments: ExtHostDocuments,
|
||||
private readonly logService: ILogService,
|
||||
private readonly _extensionStoragePaths: IExtensionStoragePaths,
|
||||
) {
|
||||
this._notebookProxy = mainContext.getProxy(MainContext.MainThreadNotebook);
|
||||
@@ -138,8 +106,12 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
});
|
||||
}
|
||||
|
||||
getEditorById(editorId: string): ExtHostNotebookEditor | undefined {
|
||||
return this._editors.get(editorId);
|
||||
getEditorById(editorId: string): ExtHostNotebookEditor {
|
||||
const editor = this._editors.get(editorId);
|
||||
if (!editor) {
|
||||
throw new Error(`unknown text editor: ${editorId}. known editors: ${[...this._editors.keys()]} `);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
getIdByEditor(editor: vscode.NotebookEditor): string | undefined {
|
||||
@@ -155,13 +127,11 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
return [...this._documents.values()];
|
||||
}
|
||||
|
||||
lookupNotebookDocument(uri: URI): ExtHostNotebookDocument | undefined {
|
||||
return this._documents.get(uri);
|
||||
}
|
||||
|
||||
private _getNotebookDocument(uri: URI): ExtHostNotebookDocument {
|
||||
getNotebookDocument(uri: URI, relaxed: true): ExtHostNotebookDocument | undefined;
|
||||
getNotebookDocument(uri: URI): ExtHostNotebookDocument;
|
||||
getNotebookDocument(uri: URI, relaxed?: true): ExtHostNotebookDocument | undefined {
|
||||
const result = this._documents.get(uri);
|
||||
if (!result) {
|
||||
if (!result && !relaxed) {
|
||||
throw new Error(`NO notebook document for '${uri}'`);
|
||||
}
|
||||
return result;
|
||||
@@ -179,13 +149,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
extension: IExtensionDescription,
|
||||
viewType: string,
|
||||
provider: vscode.NotebookContentProvider,
|
||||
options?: vscode.NotebookDocumentContentOptions & {
|
||||
viewOptions?: {
|
||||
displayName: string;
|
||||
filenamePattern: (vscode.GlobPattern | { include: vscode.GlobPattern; exclude: vscode.GlobPattern })[];
|
||||
exclusive?: boolean;
|
||||
};
|
||||
}
|
||||
options?: vscode.NotebookDocumentContentOptions,
|
||||
registration?: vscode.NotebookRegistrationData
|
||||
): vscode.Disposable {
|
||||
if (isFalsyOrWhitespace(viewType)) {
|
||||
throw new Error(`viewType cannot be empty or just whitespace`);
|
||||
@@ -196,7 +161,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
|
||||
this._notebookContentProviders.set(viewType, { extension, provider });
|
||||
|
||||
|
||||
let listener: IDisposable | undefined;
|
||||
if (provider.onDidChangeNotebookContentOptions) {
|
||||
listener = provider.onDidChangeNotebookContentOptions(() => {
|
||||
@@ -205,21 +169,12 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
});
|
||||
}
|
||||
|
||||
const viewOptionsFilenamePattern = options?.viewOptions?.filenamePattern
|
||||
.map(pattern => typeConverters.NotebookExclusiveDocumentPattern.from(pattern))
|
||||
.filter(pattern => pattern !== undefined) as (string | IRelativePattern | INotebookExclusiveDocumentFilter)[];
|
||||
|
||||
if (options?.viewOptions?.filenamePattern && !viewOptionsFilenamePattern) {
|
||||
console.warn(`Notebook content provider view options file name pattern is invalid ${options?.viewOptions?.filenamePattern}`);
|
||||
}
|
||||
|
||||
const internalOptions = typeConverters.NotebookDocumentContentOptions.from(options);
|
||||
this._notebookProxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation, description: extension.description }, viewType, {
|
||||
transientOutputs: internalOptions.transientOutputs,
|
||||
transientCellMetadata: internalOptions.transientCellMetadata,
|
||||
transientDocumentMetadata: internalOptions.transientDocumentMetadata,
|
||||
viewOptions: options?.viewOptions && viewOptionsFilenamePattern ? { displayName: options.viewOptions.displayName, filenamePattern: viewOptionsFilenamePattern, exclusive: options.viewOptions.exclusive || false } : undefined
|
||||
});
|
||||
this._notebookProxy.$registerNotebookProvider(
|
||||
{ id: extension.identifier, location: extension.extensionLocation },
|
||||
viewType,
|
||||
typeConverters.NotebookDocumentContentOptions.from(options),
|
||||
ExtHostNotebookController._convertNotebookRegistrationData(extension, registration)
|
||||
);
|
||||
|
||||
return new extHostTypes.Disposable(() => {
|
||||
listener?.dispose();
|
||||
@@ -228,13 +183,33 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
});
|
||||
}
|
||||
|
||||
registerNotebookCellStatusBarItemProvider(extension: IExtensionDescription, selector: vscode.NotebookSelector, provider: vscode.NotebookCellStatusBarItemProvider) {
|
||||
private static _convertNotebookRegistrationData(extension: IExtensionDescription, registration: vscode.NotebookRegistrationData | undefined): INotebookContributionData | undefined {
|
||||
if (!registration) {
|
||||
return undefined; // {{SQL CARBON EDIT}} Strict nulls
|
||||
}
|
||||
const viewOptionsFilenamePattern = registration.filenamePattern
|
||||
.map(pattern => typeConverters.NotebookExclusiveDocumentPattern.from(pattern))
|
||||
.filter(pattern => pattern !== undefined) as (string | IRelativePattern | INotebookExclusiveDocumentFilter)[];
|
||||
if (registration.filenamePattern && !viewOptionsFilenamePattern) {
|
||||
console.warn(`Notebook content provider view options file name pattern is invalid ${registration.filenamePattern}`);
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
extension: extension.identifier,
|
||||
providerDisplayName: extension.displayName || extension.name,
|
||||
displayName: registration.displayName,
|
||||
filenamePattern: viewOptionsFilenamePattern,
|
||||
exclusive: registration.exclusive || false
|
||||
};
|
||||
}
|
||||
|
||||
registerNotebookCellStatusBarItemProvider(extension: IExtensionDescription, notebookType: string, provider: vscode.NotebookCellStatusBarItemProvider) {
|
||||
|
||||
const handle = ExtHostNotebookController._notebookStatusBarItemProviderHandlePool++;
|
||||
const eventHandle = typeof provider.onDidChangeCellStatusBarItems === 'function' ? ExtHostNotebookController._notebookStatusBarItemProviderHandlePool++ : undefined;
|
||||
|
||||
this._notebookStatusBarItemProviders.set(handle, provider);
|
||||
this._notebookProxy.$registerNotebookCellStatusBarItemProvider(handle, eventHandle, selector);
|
||||
this._notebookProxy.$registerNotebookCellStatusBarItemProvider(handle, eventHandle, notebookType);
|
||||
|
||||
let subscription: vscode.Disposable | undefined;
|
||||
if (eventHandle !== undefined) {
|
||||
@@ -250,8 +225,12 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
});
|
||||
}
|
||||
|
||||
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
|
||||
return new NotebookEditorDecorationType(this._notebookEditorsProxy, options).value;
|
||||
async createNotebookDocument(options: { viewType: string, content?: vscode.NotebookData }): Promise<URI> {
|
||||
const canonicalUri = await this._notebookDocumentsProxy.$tryCreateNotebook({
|
||||
viewType: options.viewType,
|
||||
content: options.content && typeConverters.NotebookData.from(options.content)
|
||||
});
|
||||
return URI.revive(canonicalUri);
|
||||
}
|
||||
|
||||
async openNotebookDocument(uri: URI): Promise<vscode.NotebookDocument> {
|
||||
@@ -259,7 +238,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
if (cached) {
|
||||
return cached.apiNotebook;
|
||||
}
|
||||
const canonicalUri = await this._notebookDocumentsProxy.$tryOpenDocument(uri);
|
||||
const canonicalUri = await this._notebookDocumentsProxy.$tryOpenNotebook(uri);
|
||||
const document = this._documents.get(URI.revive(canonicalUri));
|
||||
return assertIsDefined(document?.apiNotebook);
|
||||
}
|
||||
@@ -285,7 +264,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
};
|
||||
}
|
||||
|
||||
const editorId = await this._notebookEditorsProxy.$tryShowNotebookDocument(notebookOrUri.uri, notebookOrUri.viewType, resolvedOptions);
|
||||
const editorId = await this._notebookEditorsProxy.$tryShowNotebookDocument(notebookOrUri.uri, notebookOrUri.notebookType, resolvedOptions);
|
||||
const editor = editorId && this._editors.get(editorId)?.apiEditor;
|
||||
|
||||
if (editor) {
|
||||
@@ -293,9 +272,9 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
}
|
||||
|
||||
if (editorId) {
|
||||
throw new Error(`Could NOT open editor for "${notebookOrUri.toString()}" because another editor opened in the meantime.`);
|
||||
throw new Error(`Could NOT open editor for "${notebookOrUri.uri.toString()}" because another editor opened in the meantime.`);
|
||||
} else {
|
||||
throw new Error(`Could NOT open editor for "${notebookOrUri.toString()}".`);
|
||||
throw new Error(`Could NOT open editor for "${notebookOrUri.uri.toString()}".`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +298,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
const cacheId = this._statusBarCache.add([disposables]);
|
||||
const items = (result && result.map(item => typeConverters.NotebookStatusBarItem.from(item, this._commandsConverter, disposables))) ?? undefined;
|
||||
const resultArr = Array.isArray(result) ? result : [result];
|
||||
const items = resultArr.map(item => typeConverters.NotebookStatusBarItem.from(item, this._commandsConverter, disposables));
|
||||
return {
|
||||
cacheId,
|
||||
items
|
||||
@@ -335,18 +315,18 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
private _handlePool = 0;
|
||||
private readonly _notebookSerializer = new Map<number, vscode.NotebookSerializer>();
|
||||
|
||||
registerNotebookSerializer(extension: IExtensionDescription, viewType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions): vscode.Disposable {
|
||||
registerNotebookSerializer(extension: IExtensionDescription, viewType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData): vscode.Disposable {
|
||||
if (isFalsyOrWhitespace(viewType)) {
|
||||
throw new Error(`viewType cannot be empty or just whitespace`);
|
||||
}
|
||||
const handle = this._handlePool++;
|
||||
this._notebookSerializer.set(handle, serializer);
|
||||
const internalOptions = typeConverters.NotebookDocumentContentOptions.from(options);
|
||||
this._notebookProxy.$registerNotebookSerializer(
|
||||
handle,
|
||||
{ id: extension.identifier, location: extension.extensionLocation, description: extension.description },
|
||||
{ id: extension.identifier, location: extension.extensionLocation },
|
||||
viewType,
|
||||
internalOptions
|
||||
typeConverters.NotebookDocumentContentOptions.from(options),
|
||||
ExtHostNotebookController._convertNotebookRegistrationData(extension, registration)
|
||||
);
|
||||
return toDisposable(() => {
|
||||
this._notebookProxy.$unregisterNotebookSerializer(handle);
|
||||
@@ -359,10 +339,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
throw new Error('NO serializer found');
|
||||
}
|
||||
const data = await serializer.deserializeNotebook(bytes.buffer, token);
|
||||
return {
|
||||
metadata: typeConverters.NotebookDocumentMetadata.from(data.metadata),
|
||||
cells: data.cells.map(typeConverters.NotebookCellData.from),
|
||||
};
|
||||
return typeConverters.NotebookData.from(data);
|
||||
}
|
||||
|
||||
async $notebookToData(handle: number, data: NotebookDataDto, token: CancellationToken): Promise<VSBuffer> {
|
||||
@@ -370,38 +347,30 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
if (!serializer) {
|
||||
throw new Error('NO serializer found');
|
||||
}
|
||||
const bytes = await serializer.serializeNotebook({
|
||||
metadata: typeConverters.NotebookDocumentMetadata.to(data.metadata),
|
||||
cells: data.cells.map(typeConverters.NotebookCellData.to)
|
||||
}, token);
|
||||
const bytes = await serializer.serializeNotebook(typeConverters.NotebookData.to(data), token);
|
||||
return VSBuffer.wrap(bytes);
|
||||
}
|
||||
|
||||
cancelOneNotebookCellExecution(cell: ExtHostCell): void {
|
||||
const execution = this._activeExecutions.get(cell.uri);
|
||||
execution?.cancel();
|
||||
}
|
||||
|
||||
// --- open, save, saveAs, backup
|
||||
|
||||
async $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, untitledDocumentData: VSBuffer | undefined, token: CancellationToken): Promise<NotebookDataDto> {
|
||||
const { provider } = this._getProviderData(viewType);
|
||||
const data = await provider.openNotebook(URI.revive(uri), { backupId, untitledDocumentData: untitledDocumentData?.buffer }, token);
|
||||
return {
|
||||
metadata: typeConverters.NotebookDocumentMetadata.from(data.metadata),
|
||||
metadata: data.metadata ?? Object.create(null),
|
||||
cells: data.cells.map(typeConverters.NotebookCellData.from),
|
||||
};
|
||||
}
|
||||
|
||||
async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean> {
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
const document = this.getNotebookDocument(URI.revive(uri));
|
||||
const { provider } = this._getProviderData(viewType);
|
||||
await provider.saveNotebook(document.apiNotebook, token);
|
||||
return true;
|
||||
}
|
||||
|
||||
async $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean> {
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
const document = this.getNotebookDocument(URI.revive(uri));
|
||||
const { provider } = this._getProviderData(viewType);
|
||||
await provider.saveNotebookAs(URI.revive(target), document.apiNotebook, token);
|
||||
return true;
|
||||
@@ -410,7 +379,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
private _backupIdPool: number = 0;
|
||||
|
||||
async $backupNotebook(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise<string> {
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
const document = this.getNotebookDocument(URI.revive(uri));
|
||||
const provider = this._getProviderData(viewType);
|
||||
|
||||
const storagePath = this._extensionStoragePaths.workspaceValue(provider.extension) ?? this._extensionStoragePaths.globalValue(provider.extension);
|
||||
@@ -422,70 +391,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
return backup.id;
|
||||
}
|
||||
|
||||
$acceptModelChanged(uri: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged(event, isDirty);
|
||||
}
|
||||
|
||||
$acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void {
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged({ rawEvents: [], versionId: document.apiNotebook.version }, isDirty);
|
||||
}
|
||||
|
||||
$acceptModelSaved(uri: UriComponents): void {
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
this._onDidSaveNotebookDocument.fire(document.apiNotebook);
|
||||
}
|
||||
|
||||
$acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void {
|
||||
this.logService.debug('ExtHostNotebook#$acceptEditorPropertiesChanged', id, data);
|
||||
|
||||
const editor = this._editors.get(id);
|
||||
if (!editor) {
|
||||
throw new Error(`unknown text editor: ${id}. known editors: ${[...this._editors.keys()]} `);
|
||||
}
|
||||
|
||||
// ONE: make all state updates
|
||||
if (data.visibleRanges) {
|
||||
editor._acceptVisibleRanges(data.visibleRanges.ranges.map(typeConverters.NotebookRange.to));
|
||||
}
|
||||
if (data.selections) {
|
||||
editor._acceptSelections(data.selections.selections.map(typeConverters.NotebookRange.to));
|
||||
}
|
||||
|
||||
// TWO: send all events after states have been updated
|
||||
if (data.visibleRanges) {
|
||||
this._onDidChangeNotebookEditorVisibleRanges.fire({
|
||||
notebookEditor: editor.apiEditor,
|
||||
visibleRanges: editor.apiEditor.visibleRanges
|
||||
});
|
||||
}
|
||||
if (data.selections) {
|
||||
this._onDidChangeNotebookEditorSelection.fire(Object.freeze({
|
||||
notebookEditor: editor.apiEditor,
|
||||
selections: editor.apiEditor.selections
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
$acceptEditorViewColumns(data: INotebookEditorViewColumnInfo): void {
|
||||
for (const id in data) {
|
||||
const editor = this._editors.get(id);
|
||||
if (!editor) {
|
||||
throw new Error(`unknown text editor: ${id}. known editors: ${[...this._editors.keys()]} `);
|
||||
}
|
||||
editor._acceptViewColumn(typeConverters.ViewColumn.to(data[id]));
|
||||
}
|
||||
}
|
||||
|
||||
$acceptDocumentPropertiesChanged(uri: UriComponents, data: INotebookDocumentPropertiesChangeData): void {
|
||||
this.logService.debug('ExtHostNotebook#$acceptDocumentPropertiesChanged', uri.path, data);
|
||||
const document = this._getNotebookDocument(URI.revive(uri));
|
||||
document.acceptDocumentPropertiesChanged(data);
|
||||
if (data.metadata) {
|
||||
this._onDidChangeNotebookDocumentMetadata.fire({ document: document.apiNotebook });
|
||||
}
|
||||
}
|
||||
|
||||
private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, data: INotebookEditorAddData) {
|
||||
|
||||
@@ -559,7 +464,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
}
|
||||
},
|
||||
viewType,
|
||||
modelData.metadata ? typeConverters.NotebookDocumentMetadata.to(modelData.metadata) : new extHostTypes.NotebookDocumentMetadata(),
|
||||
modelData.metadata ?? Object.create({}),
|
||||
uri,
|
||||
);
|
||||
|
||||
@@ -639,213 +544,4 @@ export class ExtHostNotebookController implements ExtHostNotebookShape {
|
||||
this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor?.apiEditor);
|
||||
}
|
||||
}
|
||||
createNotebookCellExecution(docUri: vscode.Uri, index: number, kernelId: string): vscode.NotebookCellExecutionTask | undefined {
|
||||
const document = this.lookupNotebookDocument(docUri);
|
||||
if (!document) {
|
||||
throw new Error(`Invalid uri: ${docUri} `);
|
||||
}
|
||||
|
||||
const cell = document.getCellFromIndex(index);
|
||||
if (!cell) {
|
||||
throw new Error(`Invalid cell index: ${docUri}, ${index} `);
|
||||
}
|
||||
|
||||
// TODO@roblou also validate kernelId, once kernel has moved from editor to document
|
||||
if (this._activeExecutions.has(cell.uri)) {
|
||||
throw new Error(`duplicate execution for ${cell.uri}`);
|
||||
}
|
||||
|
||||
const execution = new NotebookCellExecutionTask(docUri, document, cell, this._notebookDocumentsProxy);
|
||||
this._activeExecutions.set(cell.uri, execution);
|
||||
const listener = execution.onDidChangeState(() => {
|
||||
if (execution.state === NotebookCellExecutionTaskState.Resolved) {
|
||||
execution.dispose();
|
||||
listener.dispose();
|
||||
this._activeExecutions.delete(cell.uri);
|
||||
}
|
||||
});
|
||||
|
||||
return execution.asApiObject();
|
||||
}
|
||||
}
|
||||
|
||||
enum NotebookCellExecutionTaskState {
|
||||
Init,
|
||||
Started,
|
||||
Resolved
|
||||
}
|
||||
|
||||
class NotebookCellExecutionTask extends Disposable {
|
||||
private _onDidChangeState = new Emitter<void>();
|
||||
readonly onDidChangeState = this._onDidChangeState.event;
|
||||
|
||||
private _state = NotebookCellExecutionTaskState.Init;
|
||||
get state(): NotebookCellExecutionTaskState { return this._state; }
|
||||
|
||||
private readonly _tokenSource = this._register(new CancellationTokenSource());
|
||||
|
||||
private readonly _collector: TimeoutBasedCollector<IImmediateCellEditOperation>;
|
||||
|
||||
private _executionOrder: number | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _uri: vscode.Uri,
|
||||
private readonly _document: ExtHostNotebookDocument,
|
||||
private readonly _cell: ExtHostCell,
|
||||
private readonly _proxy: MainThreadNotebookDocumentsShape) {
|
||||
super();
|
||||
|
||||
this._collector = new TimeoutBasedCollector(10, edits => this.applyEdits(edits));
|
||||
|
||||
this._executionOrder = _cell.internalMetadata.executionOrder;
|
||||
this.mixinMetadata({
|
||||
runState: extHostTypes.NotebookCellExecutionState.Pending,
|
||||
executionOrder: null
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this._tokenSource.cancel();
|
||||
}
|
||||
|
||||
private async applyEditSoon(edit: IImmediateCellEditOperation): Promise<void> {
|
||||
await this._collector.addItem(edit);
|
||||
}
|
||||
|
||||
private async applyEdits(edits: IImmediateCellEditOperation[]): Promise<void> {
|
||||
return this._proxy.$applyEdits(this._uri, edits, false);
|
||||
}
|
||||
|
||||
private verifyStateForOutput() {
|
||||
if (this._state === NotebookCellExecutionTaskState.Init) {
|
||||
throw new Error('Must call start before modifying cell output');
|
||||
}
|
||||
|
||||
if (this._state === NotebookCellExecutionTaskState.Resolved) {
|
||||
throw new Error('Cannot modify cell output after calling resolve');
|
||||
}
|
||||
}
|
||||
|
||||
private mixinMetadata(mixinMetadata: NullablePartialNotebookCellMetadata) {
|
||||
const edit: IImmediateCellEditOperation = { editType: CellEditType.PartialMetadata, handle: this._cell.handle, metadata: mixinMetadata };
|
||||
this.applyEdits([edit]);
|
||||
}
|
||||
|
||||
private cellIndexToHandle(cellIndex: number | undefined): number | undefined {
|
||||
const cell = typeof cellIndex === 'number' ? this._document.getCellFromIndex(cellIndex) : this._cell;
|
||||
if (!cell) {
|
||||
return undefined; // {{SQL CARBON EDIT}} Strict null
|
||||
}
|
||||
|
||||
return cell.handle;
|
||||
}
|
||||
|
||||
asApiObject(): vscode.NotebookCellExecutionTask {
|
||||
const that = this;
|
||||
return Object.freeze(<vscode.NotebookCellExecutionTask>{
|
||||
get document() { return that._document.apiNotebook; },
|
||||
get cell() { return that._cell.apiCell; },
|
||||
|
||||
get executionOrder() { return that._executionOrder; },
|
||||
set executionOrder(v: number | undefined) {
|
||||
that._executionOrder = v;
|
||||
that.mixinMetadata({
|
||||
executionOrder: v
|
||||
});
|
||||
},
|
||||
|
||||
start(context?: vscode.NotebookCellExecuteStartContext): void {
|
||||
if (that._state === NotebookCellExecutionTaskState.Resolved || that._state === NotebookCellExecutionTaskState.Started) {
|
||||
throw new Error('Cannot call start again');
|
||||
}
|
||||
|
||||
that._state = NotebookCellExecutionTaskState.Started;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: extHostTypes.NotebookCellExecutionState.Executing,
|
||||
runStartTime: context?.startTime ?? null
|
||||
});
|
||||
},
|
||||
|
||||
end(result?: vscode.NotebookCellExecuteEndContext): void {
|
||||
if (that._state === NotebookCellExecutionTaskState.Resolved) {
|
||||
throw new Error('Cannot call resolve twice');
|
||||
}
|
||||
|
||||
that._state = NotebookCellExecutionTaskState.Resolved;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: extHostTypes.NotebookCellExecutionState.Idle,
|
||||
lastRunSuccess: result?.success ?? null,
|
||||
runEndTime: result?.endTime ?? null,
|
||||
});
|
||||
},
|
||||
|
||||
clearOutput(cellIndex?: number): Thenable<void> {
|
||||
that.verifyStateForOutput();
|
||||
return this.replaceOutput([], cellIndex);
|
||||
},
|
||||
|
||||
async appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cellIndex?: number): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
const handle = that.cellIndexToHandle(cellIndex);
|
||||
if (typeof handle !== 'number') {
|
||||
return;
|
||||
}
|
||||
|
||||
outputs = Array.isArray(outputs) ? outputs : [outputs];
|
||||
return that.applyEditSoon({ editType: CellEditType.Output, handle, append: true, outputs: outputs.map(typeConverters.NotebookCellOutput.from) });
|
||||
},
|
||||
|
||||
async replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cellIndex?: number): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
const handle = that.cellIndexToHandle(cellIndex);
|
||||
if (typeof handle !== 'number') {
|
||||
return;
|
||||
}
|
||||
|
||||
outputs = Array.isArray(outputs) ? outputs : [outputs];
|
||||
return that.applyEditSoon({ editType: CellEditType.Output, handle, outputs: outputs.map(typeConverters.NotebookCellOutput.from) });
|
||||
},
|
||||
|
||||
async appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputId: string): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
items = Array.isArray(items) ? items : [items];
|
||||
return that.applyEditSoon({ editType: CellEditType.OutputItems, append: true, items: items.map(typeConverters.NotebookCellOutputItem.from), outputId });
|
||||
},
|
||||
|
||||
async replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputId: string): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
items = Array.isArray(items) ? items : [items];
|
||||
return that.applyEditSoon({ editType: CellEditType.OutputItems, items: items.map(typeConverters.NotebookCellOutputItem.from), outputId });
|
||||
},
|
||||
|
||||
token: that._tokenSource.token
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class TimeoutBasedCollector<T> {
|
||||
private batch: T[] = [];
|
||||
private waitPromise: Promise<void> | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly delay: number,
|
||||
private readonly callback: (items: T[]) => Promise<void>) { }
|
||||
|
||||
addItem(item: T): Promise<void> {
|
||||
this.batch.push(item);
|
||||
if (!this.waitPromise) {
|
||||
this.waitPromise = timeout(this.delay).then(() => {
|
||||
this.waitPromise = undefined;
|
||||
const batch = this.batch;
|
||||
this.batch = [];
|
||||
return this.callback(batch);
|
||||
});
|
||||
}
|
||||
|
||||
return this.waitPromise;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { deepFreeze, equals } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CellKind, INotebookDocumentPropertiesChangeData, MainThreadNotebookDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { INotebookDocumentPropertiesChangeData, MainThreadNotebookDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { IMainCellDto, IOutputDto, IOutputItemDto, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookCellsSplice2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, IMainCellDto, IOutputDto, IOutputItemDto, NotebookCellInternalMetadata, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookCellsSplice2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
class RawContentChangeEvent {
|
||||
@@ -44,19 +44,19 @@ export class ExtHostCell {
|
||||
};
|
||||
}
|
||||
|
||||
private _outputs: extHostTypes.NotebookCellOutput[];
|
||||
private _metadata: extHostTypes.NotebookCellMetadata;
|
||||
private _outputs: vscode.NotebookCellOutput[];
|
||||
private _metadata: NotebookCellMetadata;
|
||||
private _previousResult: vscode.NotebookCellExecutionSummary | undefined;
|
||||
|
||||
private _internalMetadata: NotebookCellMetadata;
|
||||
private _internalMetadata: NotebookCellInternalMetadata;
|
||||
readonly handle: number;
|
||||
readonly uri: URI;
|
||||
readonly cellKind: CellKind;
|
||||
|
||||
private _cell: vscode.NotebookCell | undefined;
|
||||
private _apiCell: vscode.NotebookCell | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _notebook: ExtHostNotebookDocument,
|
||||
readonly notebook: ExtHostNotebookDocument,
|
||||
private readonly _extHostDocument: ExtHostDocumentsAndEditors,
|
||||
private readonly _cellData: IMainCellDto,
|
||||
) {
|
||||
@@ -64,33 +64,33 @@ export class ExtHostCell {
|
||||
this.uri = URI.revive(_cellData.uri);
|
||||
this.cellKind = _cellData.cellKind;
|
||||
this._outputs = _cellData.outputs.map(extHostTypeConverters.NotebookCellOutput.to);
|
||||
this._internalMetadata = _cellData.metadata ?? {};
|
||||
this._metadata = extHostTypeConverters.NotebookCellMetadata.to(this._internalMetadata);
|
||||
this._previousResult = extHostTypeConverters.NotebookCellPreviousExecutionResult.to(this._internalMetadata);
|
||||
this._internalMetadata = _cellData.internalMetadata ?? {};
|
||||
this._metadata = _cellData.metadata ?? {};
|
||||
this._previousResult = extHostTypeConverters.NotebookCellExecutionSummary.to(_cellData.internalMetadata ?? {});
|
||||
}
|
||||
|
||||
get internalMetadata(): NotebookCellMetadata {
|
||||
get internalMetadata(): NotebookCellInternalMetadata {
|
||||
return this._internalMetadata;
|
||||
}
|
||||
|
||||
get apiCell(): vscode.NotebookCell {
|
||||
if (!this._cell) {
|
||||
if (!this._apiCell) {
|
||||
const that = this;
|
||||
const data = this._extHostDocument.getDocument(this.uri);
|
||||
if (!data) {
|
||||
throw new Error(`MISSING extHostDocument for notebook cell: ${this.uri}`);
|
||||
}
|
||||
this._cell = Object.freeze<vscode.NotebookCell>({
|
||||
get index() { return that._notebook.getCellIndex(that); },
|
||||
notebook: that._notebook.apiNotebook,
|
||||
this._apiCell = Object.freeze<vscode.NotebookCell>({
|
||||
get index() { return that.notebook.getCellIndex(that); },
|
||||
notebook: that.notebook.apiNotebook,
|
||||
kind: extHostTypeConverters.NotebookCellKind.to(this._cellData.cellKind),
|
||||
document: data.document,
|
||||
get outputs() { return that._outputs.slice(0); },
|
||||
get metadata() { return that._metadata; },
|
||||
get latestExecutionSummary() { return that._previousResult; }
|
||||
get executionSummary() { return that._previousResult; }
|
||||
});
|
||||
}
|
||||
return this._cell;
|
||||
return this._apiCell;
|
||||
}
|
||||
|
||||
setOutputs(newOutputs: IOutputDto[]): void {
|
||||
@@ -102,16 +102,19 @@ export class ExtHostCell {
|
||||
const output = this._outputs.find(op => op.id === outputId);
|
||||
if (output) {
|
||||
if (!append) {
|
||||
output.outputs.length = 0;
|
||||
output.items.length = 0;
|
||||
}
|
||||
output.outputs.push(...newItems);
|
||||
output.items.push(...newItems);
|
||||
}
|
||||
}
|
||||
|
||||
setMetadata(newMetadata: NotebookCellMetadata): void {
|
||||
this._internalMetadata = newMetadata;
|
||||
this._metadata = extHostTypeConverters.NotebookCellMetadata.to(newMetadata);
|
||||
this._previousResult = extHostTypeConverters.NotebookCellPreviousExecutionResult.to(newMetadata);
|
||||
this._metadata = newMetadata;
|
||||
}
|
||||
|
||||
setInternalMetadata(newInternalMetadata: NotebookCellInternalMetadata): void {
|
||||
this._internalMetadata = newInternalMetadata;
|
||||
this._previousResult = extHostTypeConverters.NotebookCellExecutionSummary.to(newInternalMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +144,8 @@ export class ExtHostNotebookDocument {
|
||||
private readonly _textDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _textDocuments: ExtHostDocuments,
|
||||
private readonly _emitter: INotebookEventEmitter,
|
||||
private readonly _viewType: string,
|
||||
private _metadata: extHostTypes.NotebookDocumentMetadata,
|
||||
private readonly _notebookType: string,
|
||||
private _metadata: Record<string, any>,
|
||||
readonly uri: URI,
|
||||
) { }
|
||||
|
||||
@@ -156,7 +159,7 @@ export class ExtHostNotebookDocument {
|
||||
this._notebook = {
|
||||
get uri() { return that.uri; },
|
||||
get version() { return that._versionId; },
|
||||
get viewType() { return that._viewType; },
|
||||
get notebookType() { return that._notebookType; },
|
||||
get isDirty() { return that._isDirty; },
|
||||
get isUntitled() { return that.uri.scheme === Schemas.untitled; },
|
||||
get isClosed() { return that._disposed; },
|
||||
@@ -190,7 +193,7 @@ export class ExtHostNotebookDocument {
|
||||
|
||||
acceptDocumentPropertiesChanged(data: INotebookDocumentPropertiesChangeData) {
|
||||
if (data.metadata) {
|
||||
this._metadata = this._metadata.with(data.metadata);
|
||||
this._metadata = { ...this._metadata, ...data.metadata };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +216,14 @@ export class ExtHostNotebookDocument {
|
||||
this._changeCellLanguage(rawEvent.index, rawEvent.language);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.ChangeCellMetadata) {
|
||||
this._changeCellMetadata(rawEvent.index, rawEvent.metadata);
|
||||
} else if (rawEvent.kind === NotebookCellsChangeType.ChangeCellInternalMetadata) {
|
||||
this._changeCellInternalMetadata(rawEvent.index, rawEvent.internalMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _validateIndex(index: number): number {
|
||||
index = index | 0;
|
||||
if (index < 0) {
|
||||
return 0;
|
||||
} else if (index >= this._cells.length) {
|
||||
@@ -228,13 +234,15 @@ export class ExtHostNotebookDocument {
|
||||
}
|
||||
|
||||
private _validateRange(range: vscode.NotebookRange): vscode.NotebookRange {
|
||||
if (range.start < 0) {
|
||||
range = range.with({ start: 0 });
|
||||
let start = range.start | 0;
|
||||
let end = range.end | 0;
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
if (range.end > this._cells.length) {
|
||||
range = range.with({ end: this._cells.length });
|
||||
if (end > this._cells.length) {
|
||||
end = this._cells.length;
|
||||
}
|
||||
return range;
|
||||
return range.with({ start, end });
|
||||
}
|
||||
|
||||
private _getCells(range: vscode.NotebookRange): ExtHostCell[] {
|
||||
@@ -250,7 +258,7 @@ export class ExtHostNotebookDocument {
|
||||
if (this._disposed) {
|
||||
return Promise.reject(new Error('Notebook has been closed'));
|
||||
}
|
||||
return this._proxy.$trySaveDocument(this.uri);
|
||||
return this._proxy.$trySaveNotebook(this.uri);
|
||||
}
|
||||
|
||||
private _spliceNotebookCells(splices: NotebookCellsSplice2[], initialization: boolean): void {
|
||||
@@ -275,7 +283,7 @@ export class ExtHostNotebookDocument {
|
||||
|
||||
const changeEvent = new RawContentChangeEvent(splice[0], splice[1], [], newCells);
|
||||
const deletedItems = this._cells.splice(splice[0], splice[1], ...newCells);
|
||||
for (let cell of deletedItems) {
|
||||
for (const cell of deletedItems) {
|
||||
removedCellDocuments.push(cell.uri);
|
||||
changeEvent.deletedItems.push(cell.apiCell);
|
||||
}
|
||||
@@ -331,7 +339,6 @@ export class ExtHostNotebookDocument {
|
||||
private _changeCellMetadata(index: number, newMetadata: NotebookCellMetadata): void {
|
||||
const cell = this._cells[index];
|
||||
|
||||
const originalInternalMetadata = cell.internalMetadata;
|
||||
const originalExtMetadata = cell.apiCell.metadata;
|
||||
cell.setMetadata(newMetadata);
|
||||
const newExtMetadata = cell.apiCell.metadata;
|
||||
@@ -339,13 +346,24 @@ export class ExtHostNotebookDocument {
|
||||
if (!equals(originalExtMetadata, newExtMetadata)) {
|
||||
this._emitter.emitCellMetadataChange(deepFreeze({ document: this.apiNotebook, cell: cell.apiCell }));
|
||||
}
|
||||
}
|
||||
|
||||
if (originalInternalMetadata.runState !== newMetadata.runState) {
|
||||
const executionState = newMetadata.runState ?? extHostTypes.NotebookCellExecutionState.Idle;
|
||||
this._emitter.emitCellExecutionStateChange(deepFreeze({ document: this.apiNotebook, cell: cell.apiCell, executionState }));
|
||||
private _changeCellInternalMetadata(index: number, newInternalMetadata: NotebookCellInternalMetadata): void {
|
||||
const cell = this._cells[index];
|
||||
|
||||
const originalInternalMetadata = cell.internalMetadata;
|
||||
cell.setInternalMetadata(newInternalMetadata);
|
||||
|
||||
if (originalInternalMetadata.runState !== newInternalMetadata.runState) {
|
||||
const executionState = newInternalMetadata.runState ?? extHostTypes.NotebookCellExecutionState.Idle;
|
||||
this._emitter.emitCellExecutionStateChange(deepFreeze({ document: this.apiNotebook, cell: cell.apiCell, state: executionState }));
|
||||
}
|
||||
}
|
||||
|
||||
getCellFromApiCell(apiCell: vscode.NotebookCell): ExtHostCell | undefined {
|
||||
return this._cells.find(cell => cell.apiCell === apiCell);
|
||||
}
|
||||
|
||||
getCellFromIndex(index: number): ExtHostCell | undefined {
|
||||
return this._cells[index];
|
||||
}
|
||||
|
||||
50
src/vs/workbench/api/common/extHostNotebookDocuments.ts
Normal file
50
src/vs/workbench/api/common/extHostNotebookDocuments.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostNotebookDocumentsShape, INotebookDocumentPropertiesChangeData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { NotebookCellsChangedEventDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostNotebookDocuments implements ExtHostNotebookDocumentsShape {
|
||||
|
||||
private readonly _onDidChangeNotebookDocumentMetadata = new Emitter<vscode.NotebookDocumentMetadataChangeEvent>();
|
||||
readonly onDidChangeNotebookDocumentMetadata = this._onDidChangeNotebookDocumentMetadata.event;
|
||||
|
||||
private _onDidSaveNotebookDocument = new Emitter<vscode.NotebookDocument>();
|
||||
readonly onDidSaveNotebookDocument = this._onDidSaveNotebookDocument.event;
|
||||
|
||||
constructor(
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
private readonly _notebooksAndEditors: ExtHostNotebookController,
|
||||
) { }
|
||||
|
||||
$acceptModelChanged(uri: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged(event, isDirty);
|
||||
}
|
||||
|
||||
$acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void {
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged({ rawEvents: [], versionId: document.apiNotebook.version }, isDirty);
|
||||
}
|
||||
|
||||
$acceptModelSaved(uri: UriComponents): void {
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
this._onDidSaveNotebookDocument.fire(document.apiNotebook);
|
||||
}
|
||||
|
||||
$acceptDocumentPropertiesChanged(uri: UriComponents, data: INotebookDocumentPropertiesChangeData): void {
|
||||
this._logService.debug('ExtHostNotebook#$acceptDocumentPropertiesChanged', uri.path, data);
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptDocumentPropertiesChanged(data);
|
||||
if (data.metadata) {
|
||||
this._onDidChangeNotebookDocumentMetadata.fire({ document: document.apiNotebook });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import * as extHostConverter from 'vs/workbench/api/common/extHostTypeConverters
|
||||
import { CellEditType, ICellEditOperation, ICellReplaceEdit } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostNotebookDocument } from './extHostNotebookDocument';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
|
||||
interface INotebookEditData {
|
||||
documentVersionId: number;
|
||||
@@ -40,7 +41,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
}
|
||||
}
|
||||
|
||||
replaceMetadata(value: vscode.NotebookDocumentMetadata): void {
|
||||
replaceMetadata(value: { [key: string]: any }): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.DocumentMetadata,
|
||||
@@ -48,7 +49,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
});
|
||||
}
|
||||
|
||||
replaceCellMetadata(index: number, metadata: vscode.NotebookCellMetadata): void {
|
||||
replaceCellMetadata(index: number, metadata: Record<string, any>): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.Metadata,
|
||||
@@ -73,6 +74,8 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
|
||||
export class ExtHostNotebookEditor {
|
||||
|
||||
public static readonly apiEditorsToExtHost = new WeakMap<vscode.NotebookEditor, ExtHostNotebookEditor>();
|
||||
|
||||
private _selections: vscode.NotebookRange[] = [];
|
||||
private _visibleRanges: vscode.NotebookRange[] = [];
|
||||
private _viewColumn?: vscode.ViewColumn;
|
||||
@@ -105,6 +108,13 @@ export class ExtHostNotebookEditor {
|
||||
get selections() {
|
||||
return that._selections;
|
||||
},
|
||||
set selections(value: vscode.NotebookRange[]) {
|
||||
if (!Array.isArray(value) || !value.every(extHostTypes.NotebookRange.isNotebookRange)) {
|
||||
throw illegalArgument('selections');
|
||||
}
|
||||
that._selections = value;
|
||||
that._trySetSelections(value);
|
||||
},
|
||||
get visibleRanges() {
|
||||
return that._visibleRanges;
|
||||
},
|
||||
@@ -127,6 +137,8 @@ export class ExtHostNotebookEditor {
|
||||
return that.setDecorations(decorationType, range);
|
||||
}
|
||||
};
|
||||
|
||||
ExtHostNotebookEditor.apiEditorsToExtHost.set(this._editor, this);
|
||||
}
|
||||
return this._editor;
|
||||
}
|
||||
@@ -147,6 +159,10 @@ export class ExtHostNotebookEditor {
|
||||
this._selections = selections;
|
||||
}
|
||||
|
||||
private _trySetSelections(value: vscode.NotebookRange[]): void {
|
||||
this._proxy.$trySetSelections(this.id, value.map(extHostConverter.NotebookRange.from));
|
||||
}
|
||||
|
||||
_acceptViewColumn(value: vscode.ViewColumn | undefined) {
|
||||
this._viewColumn = value;
|
||||
}
|
||||
|
||||
88
src/vs/workbench/api/common/extHostNotebookEditors.ts
Normal file
88
src/vs/workbench/api/common/extHostNotebookEditors.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ExtHostNotebookEditorsShape, INotebookEditorPropertiesChangeData, INotebookEditorViewColumnInfo, MainContext, MainThreadNotebookEditorsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
class NotebookEditorDecorationType {
|
||||
|
||||
private static readonly _Keys = new IdGenerator('NotebookEditorDecorationType');
|
||||
|
||||
readonly value: vscode.NotebookEditorDecorationType;
|
||||
|
||||
constructor(proxy: MainThreadNotebookEditorsShape, options: vscode.NotebookDecorationRenderOptions) {
|
||||
const key = NotebookEditorDecorationType._Keys.nextId();
|
||||
proxy.$registerNotebookEditorDecorationType(key, typeConverters.NotebookDecorationRenderOptions.from(options));
|
||||
|
||||
this.value = {
|
||||
key,
|
||||
dispose() {
|
||||
proxy.$removeNotebookEditorDecorationType(key);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ExtHostNotebookEditors implements ExtHostNotebookEditorsShape {
|
||||
|
||||
private readonly _onDidChangeNotebookEditorSelection = new Emitter<vscode.NotebookEditorSelectionChangeEvent>();
|
||||
private readonly _onDidChangeNotebookEditorVisibleRanges = new Emitter<vscode.NotebookEditorVisibleRangesChangeEvent>();
|
||||
|
||||
readonly onDidChangeNotebookEditorSelection = this._onDidChangeNotebookEditorSelection.event;
|
||||
readonly onDidChangeNotebookEditorVisibleRanges = this._onDidChangeNotebookEditorVisibleRanges.event;
|
||||
|
||||
constructor(
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IExtHostRpcService private readonly _extHostRpc: IExtHostRpcService,
|
||||
private readonly _notebooksAndEditors: ExtHostNotebookController,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
|
||||
return new NotebookEditorDecorationType(this._extHostRpc.getProxy(MainContext.MainThreadNotebookEditors), options).value;
|
||||
}
|
||||
|
||||
$acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void {
|
||||
this._logService.debug('ExtHostNotebook#$acceptEditorPropertiesChanged', id, data);
|
||||
const editor = this._notebooksAndEditors.getEditorById(id);
|
||||
// ONE: make all state updates
|
||||
if (data.visibleRanges) {
|
||||
editor._acceptVisibleRanges(data.visibleRanges.ranges.map(typeConverters.NotebookRange.to));
|
||||
}
|
||||
if (data.selections) {
|
||||
editor._acceptSelections(data.selections.selections.map(typeConverters.NotebookRange.to));
|
||||
}
|
||||
|
||||
// TWO: send all events after states have been updated
|
||||
if (data.visibleRanges) {
|
||||
this._onDidChangeNotebookEditorVisibleRanges.fire({
|
||||
notebookEditor: editor.apiEditor,
|
||||
visibleRanges: editor.apiEditor.visibleRanges
|
||||
});
|
||||
}
|
||||
if (data.selections) {
|
||||
this._onDidChangeNotebookEditorSelection.fire(Object.freeze({
|
||||
notebookEditor: editor.apiEditor,
|
||||
selections: editor.apiEditor.selections
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
$acceptEditorViewColumns(data: INotebookEditorViewColumnInfo): void {
|
||||
for (const id in data) {
|
||||
const editor = this._notebooksAndEditors.getEditorById(id);
|
||||
editor._acceptViewColumn(typeConverters.ViewColumn.to(data[id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostNotebookKernelsShape, IMainContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostNotebookKernelsShape, IMainContext, INotebookKernelDto2, MainContext, MainThreadNotebookDocumentsShape, MainThreadNotebookKernelsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -13,30 +13,42 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { asWebviewUri } from 'vs/workbench/api/common/shared/webview';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ExtHostCell, ExtHostNotebookDocument } from 'vs/workbench/api/common/extHostNotebookDocument';
|
||||
import { CellEditType, IImmediateCellEditOperation, IOutputDto, NotebookCellExecutionState, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { NotebookCellOutput } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
interface IKernelData {
|
||||
extensionId: ExtensionIdentifier,
|
||||
controller: vscode.NotebookController;
|
||||
onDidChangeSelection: Emitter<{ selected: boolean; notebook: vscode.NotebookDocument; }>;
|
||||
onDidReceiveMessage: Emitter<{ editor: vscode.NotebookEditor, message: any }>;
|
||||
onDidReceiveMessage: Emitter<{ editor: vscode.NotebookEditor, message: any; }>;
|
||||
associatedNotebooks: ResourceMap<boolean>;
|
||||
}
|
||||
|
||||
export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
|
||||
private readonly _proxy: MainThreadNotebookKernelsShape;
|
||||
private readonly _activeExecutions = new ResourceMap<NotebookCellExecutionTask>();
|
||||
|
||||
private readonly _kernelData = new Map<number, IKernelData>();
|
||||
private _handlePool: number = 0;
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
private readonly _mainContext: IMainContext,
|
||||
private readonly _initData: IExtHostInitDataService,
|
||||
private readonly _extHostNotebook: ExtHostNotebookController
|
||||
private readonly _extHostNotebook: ExtHostNotebookController,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebookKernels);
|
||||
this._proxy = _mainContext.getProxy(MainContext.MainThreadNotebookKernels);
|
||||
}
|
||||
|
||||
createNotebookController(extension: IExtensionDescription, id: string, viewType: string, label: string, handler?: vscode.NotebookExecuteHandler, preloads?: vscode.NotebookKernelPreload[]): vscode.NotebookController {
|
||||
createNotebookController(extension: IExtensionDescription, id: string, viewType: string, label: string, handler?: (cells: vscode.NotebookCell[], notebook: vscode.NotebookDocument, controller: vscode.NotebookController) => void | Thenable<void>, preloads?: vscode.NotebookRendererScript[]): vscode.NotebookController {
|
||||
|
||||
for (let data of this._kernelData.values()) {
|
||||
if (data.controller.id === id && ExtensionIdentifier.equals(extension.identifier, data.extensionId)) {
|
||||
@@ -44,31 +56,33 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handle = this._handlePool++;
|
||||
const that = this;
|
||||
|
||||
this._logService.trace(`NotebookController[${handle}], CREATED by ${extension.identifier.value}, ${id}`);
|
||||
|
||||
const _defaultExecutHandler = () => console.warn(`NO execute handler from notebook controller '${data.id}' of extension: '${extension.identifier}'`);
|
||||
|
||||
let isDisposed = false;
|
||||
const commandDisposables = new DisposableStore();
|
||||
|
||||
const onDidChangeSelection = new Emitter<{ selected: boolean, notebook: vscode.NotebookDocument }>();
|
||||
const onDidReceiveMessage = new Emitter<{ editor: vscode.NotebookEditor, message: any }>();
|
||||
const onDidChangeSelection = new Emitter<{ selected: boolean, notebook: vscode.NotebookDocument; }>();
|
||||
const onDidReceiveMessage = new Emitter<{ editor: vscode.NotebookEditor, message: any; }>();
|
||||
|
||||
const data: INotebookKernelDto2 = {
|
||||
id: `${extension.identifier.value}/${id}`,
|
||||
viewType,
|
||||
notebookType: viewType,
|
||||
extensionId: extension.identifier,
|
||||
extensionLocation: extension.extensionLocation,
|
||||
label: label || extension.identifier.value,
|
||||
preloads: preloads ? preloads.map(extHostTypeConverters.NotebookKernelPreload.from) : []
|
||||
preloads: preloads ? preloads.map(extHostTypeConverters.NotebookRendererScript.from) : []
|
||||
};
|
||||
|
||||
//
|
||||
let _executeHandler: vscode.NotebookExecuteHandler = handler ?? _defaultExecutHandler;
|
||||
let _interruptHandler: vscode.NotebookInterruptHandler | undefined;
|
||||
let _executeHandler = handler ?? _defaultExecutHandler;
|
||||
let _interruptHandler: ((this: vscode.NotebookController, notebook: vscode.NotebookDocument) => void | Thenable<void>) | undefined;
|
||||
|
||||
// todo@jrieken the selector needs to be massaged
|
||||
this._proxy.$addKernel(handle, data).catch(err => {
|
||||
// this can happen when a kernel with that ID is already registered
|
||||
console.log(err);
|
||||
@@ -91,10 +105,13 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
});
|
||||
};
|
||||
|
||||
// notebook documents that are associated to this controller
|
||||
const associatedNotebooks = new ResourceMap<boolean>();
|
||||
|
||||
const controller: vscode.NotebookController = {
|
||||
get id() { return id; },
|
||||
get viewType() { return data.viewType; },
|
||||
onDidChangeNotebookAssociation: onDidChangeSelection.event,
|
||||
get notebookType() { return data.notebookType; },
|
||||
onDidChangeSelectedNotebooks: onDidChangeSelection.event,
|
||||
get label() {
|
||||
return data.label;
|
||||
},
|
||||
@@ -123,15 +140,15 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
data.supportedLanguages = value;
|
||||
_update();
|
||||
},
|
||||
get hasExecutionOrder() {
|
||||
return data.hasExecutionOrder ?? false;
|
||||
get supportsExecutionOrder() {
|
||||
return data.supportsExecutionOrder ?? false;
|
||||
},
|
||||
set hasExecutionOrder(value) {
|
||||
data.hasExecutionOrder = value;
|
||||
set supportsExecutionOrder(value) {
|
||||
data.supportsExecutionOrder = value;
|
||||
_update();
|
||||
},
|
||||
get preloads() {
|
||||
return data.preloads ? data.preloads.map(extHostTypeConverters.NotebookKernelPreload.to) : [];
|
||||
get rendererScripts() {
|
||||
return data.preloads ? data.preloads.map(extHostTypeConverters.NotebookRendererScript.to) : [];
|
||||
},
|
||||
get executeHandler() {
|
||||
return _executeHandler;
|
||||
@@ -147,15 +164,19 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
data.supportsInterrupt = Boolean(value);
|
||||
_update();
|
||||
},
|
||||
createNotebookCellExecutionTask(cell) {
|
||||
createNotebookCellExecution(cell) {
|
||||
if (isDisposed) {
|
||||
throw new Error('notebook controller is DISPOSED');
|
||||
}
|
||||
//todo@jrieken
|
||||
return that._extHostNotebook.createNotebookCellExecution(cell.notebook.uri, cell.index, data.id)!;
|
||||
if (!associatedNotebooks.has(cell.notebook.uri)) {
|
||||
that._logService.trace(`NotebookController[${handle}] NOT associated to notebook, associated to THESE notebooks:`, Array.from(associatedNotebooks.keys()).map(u => u.toString()));
|
||||
throw new Error(`notebook controller is NOT associated to notebook: ${cell.notebook.uri.toString()}`);
|
||||
}
|
||||
return that._createNotebookCellExecution(cell);
|
||||
},
|
||||
dispose: () => {
|
||||
if (!isDisposed) {
|
||||
this._logService.trace(`NotebookController[${handle}], DISPOSED`);
|
||||
isDisposed = true;
|
||||
this._kernelData.delete(handle);
|
||||
commandDisposables.dispose();
|
||||
@@ -164,30 +185,47 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
this._proxy.$removeKernel(handle);
|
||||
}
|
||||
},
|
||||
// --- ipc
|
||||
onDidReceiveMessage: onDidReceiveMessage.event,
|
||||
postMessage(message, editor) {
|
||||
return that._proxy.$postMessage(handle, editor && that._extHostNotebook.getIdByEditor(editor), message);
|
||||
},
|
||||
asWebviewUri(uri: URI) {
|
||||
return asWebviewUri(that._initData.environment, String(handle), uri);
|
||||
},
|
||||
// --- priority
|
||||
updateNotebookAffinity(notebook, priority) {
|
||||
that._proxy.$updateNotebookPriority(handle, notebook.uri, priority);
|
||||
}
|
||||
},
|
||||
// --- ipc
|
||||
onDidReceiveMessage: onDidReceiveMessage.event,
|
||||
postMessage(message, editor) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return that._proxy.$postMessage(handle, editor && that._extHostNotebook.getIdByEditor(editor), message);
|
||||
},
|
||||
asWebviewUri(uri: URI) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return asWebviewUri(uri, that._initData.remote);
|
||||
},
|
||||
};
|
||||
|
||||
this._kernelData.set(handle, { extensionId: extension.identifier, controller, onDidChangeSelection, onDidReceiveMessage });
|
||||
this._kernelData.set(handle, {
|
||||
extensionId: extension.identifier,
|
||||
controller,
|
||||
onDidReceiveMessage,
|
||||
onDidChangeSelection,
|
||||
associatedNotebooks
|
||||
});
|
||||
return controller;
|
||||
}
|
||||
|
||||
$acceptSelection(handle: number, uri: UriComponents, value: boolean): void {
|
||||
$acceptNotebookAssociation(handle: number, uri: UriComponents, value: boolean): void {
|
||||
const obj = this._kernelData.get(handle);
|
||||
if (obj) {
|
||||
// update data structure
|
||||
const notebook = this._extHostNotebook.getNotebookDocument(URI.revive(uri))!;
|
||||
if (value) {
|
||||
obj.associatedNotebooks.set(notebook.uri, true);
|
||||
} else {
|
||||
obj.associatedNotebooks.delete(notebook.uri);
|
||||
}
|
||||
this._logService.trace(`NotebookController[${handle}] ASSOCIATE notebook`, notebook.uri.toString(), value);
|
||||
// send event
|
||||
obj.onDidChangeSelection.fire({
|
||||
selected: value,
|
||||
notebook: this._extHostNotebook.lookupNotebookDocument(URI.revive(uri))!.apiNotebook
|
||||
notebook: notebook.apiNotebook
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -198,11 +236,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
// extension can dispose kernels in the meantime
|
||||
return;
|
||||
}
|
||||
const document = this._extHostNotebook.lookupNotebookDocument(URI.revive(uri));
|
||||
if (!document) {
|
||||
throw new Error('MISSING notebook');
|
||||
}
|
||||
|
||||
const document = this._extHostNotebook.getNotebookDocument(URI.revive(uri));
|
||||
const cells: vscode.NotebookCell[] = [];
|
||||
for (let cellHandle of handles) {
|
||||
const cell = document.getCell(cellHandle);
|
||||
@@ -212,9 +246,11 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
}
|
||||
|
||||
try {
|
||||
this._logService.trace(`NotebookController[${handle}] EXECUTE cells`, document.uri.toString(), cells.length);
|
||||
await obj.controller.executeHandler.call(obj.controller, cells, document.apiNotebook, obj.controller);
|
||||
} catch (err) {
|
||||
//
|
||||
this._logService.error(`NotebookController[${handle}] execute cells FAILED`, err);
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
@@ -225,24 +261,24 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
// extension can dispose kernels in the meantime
|
||||
return;
|
||||
}
|
||||
const document = this._extHostNotebook.lookupNotebookDocument(URI.revive(uri));
|
||||
if (!document) {
|
||||
throw new Error('MISSING notebook');
|
||||
}
|
||||
|
||||
// cancel or interrupt depends on the controller. When an interrupt handler is used we
|
||||
// don't trigger the cancelation token of executions.
|
||||
const document = this._extHostNotebook.getNotebookDocument(URI.revive(uri));
|
||||
if (obj.controller.interruptHandler) {
|
||||
await obj.controller.interruptHandler.call(obj.controller, document.apiNotebook);
|
||||
}
|
||||
|
||||
// we do both? interrupt and cancellation or should we be selective?
|
||||
for (let cellHandle of handles) {
|
||||
const cell = document.getCell(cellHandle);
|
||||
if (cell) {
|
||||
this._extHostNotebook.cancelOneNotebookCellExecution(cell);
|
||||
} else {
|
||||
for (let cellHandle of handles) {
|
||||
const cell = document.getCell(cellHandle);
|
||||
if (cell) {
|
||||
this._activeExecutions.get(cell.uri)?.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$acceptRendererMessage(handle: number, editorId: string, message: any): void {
|
||||
$acceptKernelMessageFromRenderer(handle: number, editorId: string, message: any): void {
|
||||
const obj = this._kernelData.get(handle);
|
||||
if (!obj) {
|
||||
// extension can dispose kernels in the meantime
|
||||
@@ -250,10 +286,231 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
}
|
||||
|
||||
const editor = this._extHostNotebook.getEditorById(editorId);
|
||||
if (!editor) {
|
||||
throw new Error(`send message for UNKNOWN editor: ${editorId}`);
|
||||
}
|
||||
|
||||
obj.onDidReceiveMessage.fire(Object.freeze({ editor: editor.apiEditor, message }));
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
_createNotebookCellExecution(cell: vscode.NotebookCell): vscode.NotebookCellExecution {
|
||||
if (cell.index < 0) {
|
||||
throw new Error('CANNOT execute cell that has been REMOVED from notebook');
|
||||
}
|
||||
const notebook = this._extHostNotebook.getNotebookDocument(cell.notebook.uri);
|
||||
const cellObj = notebook.getCellFromApiCell(cell);
|
||||
if (!cellObj) {
|
||||
throw new Error('invalid cell');
|
||||
}
|
||||
if (this._activeExecutions.has(cellObj.uri)) {
|
||||
throw new Error(`duplicate execution for ${cellObj.uri}`);
|
||||
}
|
||||
const execution = new NotebookCellExecutionTask(cellObj.notebook, cellObj, this._mainContext.getProxy(MainContext.MainThreadNotebookDocuments));
|
||||
this._activeExecutions.set(cellObj.uri, execution);
|
||||
const listener = execution.onDidChangeState(() => {
|
||||
if (execution.state === NotebookCellExecutionTaskState.Resolved) {
|
||||
execution.dispose();
|
||||
listener.dispose();
|
||||
this._activeExecutions.delete(cellObj.uri);
|
||||
}
|
||||
});
|
||||
return execution.asApiObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum NotebookCellExecutionTaskState {
|
||||
Init,
|
||||
Started,
|
||||
Resolved
|
||||
}
|
||||
|
||||
class NotebookCellExecutionTask extends Disposable {
|
||||
private _onDidChangeState = new Emitter<void>();
|
||||
readonly onDidChangeState = this._onDidChangeState.event;
|
||||
|
||||
private _state = NotebookCellExecutionTaskState.Init;
|
||||
get state(): NotebookCellExecutionTaskState { return this._state; }
|
||||
|
||||
private readonly _tokenSource = this._register(new CancellationTokenSource());
|
||||
|
||||
private readonly _collector: TimeoutBasedCollector<IImmediateCellEditOperation>;
|
||||
|
||||
private _executionOrder: number | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _document: ExtHostNotebookDocument,
|
||||
private readonly _cell: ExtHostCell,
|
||||
private readonly _proxy: MainThreadNotebookDocumentsShape
|
||||
) {
|
||||
super();
|
||||
|
||||
this._collector = new TimeoutBasedCollector(10, edits => this.applyEdits(edits));
|
||||
|
||||
this._executionOrder = _cell.internalMetadata.executionOrder;
|
||||
this.mixinMetadata({
|
||||
runState: NotebookCellExecutionState.Pending,
|
||||
executionOrder: null
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
this._tokenSource.cancel();
|
||||
}
|
||||
|
||||
private async applyEditSoon(edit: IImmediateCellEditOperation): Promise<void> {
|
||||
await this._collector.addItem(edit);
|
||||
}
|
||||
|
||||
private async applyEdits(edits: IImmediateCellEditOperation[]): Promise<void> {
|
||||
return this._proxy.$applyEdits(this._document.uri, edits, false);
|
||||
}
|
||||
|
||||
private verifyStateForOutput() {
|
||||
if (this._state === NotebookCellExecutionTaskState.Init) {
|
||||
throw new Error('Must call start before modifying cell output');
|
||||
}
|
||||
|
||||
if (this._state === NotebookCellExecutionTaskState.Resolved) {
|
||||
throw new Error('Cannot modify cell output after calling resolve');
|
||||
}
|
||||
}
|
||||
|
||||
private mixinMetadata(mixinMetadata: NullablePartialNotebookCellInternalMetadata) {
|
||||
const edit: IImmediateCellEditOperation = { editType: CellEditType.PartialInternalMetadata, handle: this._cell.handle, internalMetadata: mixinMetadata };
|
||||
this.applyEdits([edit]);
|
||||
}
|
||||
|
||||
private cellIndexToHandle(cellOrCellIndex: vscode.NotebookCell | number | undefined): number {
|
||||
let cell: ExtHostCell | undefined = this._cell;
|
||||
if (typeof cellOrCellIndex === 'number') {
|
||||
// todo@jrieken remove support for number shortly
|
||||
cell = this._document.getCellFromIndex(cellOrCellIndex);
|
||||
} else if (cellOrCellIndex) {
|
||||
cell = this._document.getCellFromApiCell(cellOrCellIndex);
|
||||
}
|
||||
if (!cell) {
|
||||
throw new Error('INVALID cell');
|
||||
}
|
||||
return cell.handle;
|
||||
}
|
||||
|
||||
private validateAndConvertOutputs(items: vscode.NotebookCellOutput[]): IOutputDto[] {
|
||||
return items.map(output => {
|
||||
const newOutput = NotebookCellOutput.ensureUniqueMimeTypes(output.items, true);
|
||||
if (newOutput === output.items) {
|
||||
return extHostTypeConverters.NotebookCellOutput.from(output);
|
||||
}
|
||||
return extHostTypeConverters.NotebookCellOutput.from({
|
||||
items: newOutput,
|
||||
id: output.id,
|
||||
metadata: output.metadata
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async updateOutputs(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell: vscode.NotebookCell | number | undefined, append: boolean): Promise<void> {
|
||||
const handle = this.cellIndexToHandle(cell);
|
||||
const outputDtos = this.validateAndConvertOutputs(asArray(outputs));
|
||||
return this.applyEditSoon({ editType: CellEditType.Output, handle, append, outputs: outputDtos });
|
||||
}
|
||||
|
||||
private async updateOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], outputOrOutputId: vscode.NotebookCellOutput | string, append: boolean): Promise<void> {
|
||||
if (NotebookCellOutput.isNotebookCellOutput(outputOrOutputId)) {
|
||||
outputOrOutputId = outputOrOutputId.id;
|
||||
}
|
||||
items = NotebookCellOutput.ensureUniqueMimeTypes(asArray(items), true);
|
||||
return this.applyEditSoon({ editType: CellEditType.OutputItems, items: items.map(extHostTypeConverters.NotebookCellOutputItem.from), outputId: outputOrOutputId, append });
|
||||
}
|
||||
|
||||
asApiObject(): vscode.NotebookCellExecution {
|
||||
const that = this;
|
||||
const result: vscode.NotebookCellExecution = {
|
||||
get token() { return that._tokenSource.token; },
|
||||
get cell() { return that._cell.apiCell; },
|
||||
get executionOrder() { return that._executionOrder; },
|
||||
set executionOrder(v: number | undefined) {
|
||||
that._executionOrder = v;
|
||||
that.mixinMetadata({
|
||||
executionOrder: v
|
||||
});
|
||||
},
|
||||
|
||||
start(startTime?: number): void {
|
||||
if (that._state === NotebookCellExecutionTaskState.Resolved || that._state === NotebookCellExecutionTaskState.Started) {
|
||||
throw new Error('Cannot call start again');
|
||||
}
|
||||
|
||||
that._state = NotebookCellExecutionTaskState.Started;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: NotebookCellExecutionState.Executing,
|
||||
runStartTime: startTime ?? null
|
||||
});
|
||||
},
|
||||
|
||||
end(success: boolean | undefined, endTime?: number): void {
|
||||
if (that._state === NotebookCellExecutionTaskState.Resolved) {
|
||||
throw new Error('Cannot call resolve twice');
|
||||
}
|
||||
|
||||
that._state = NotebookCellExecutionTaskState.Resolved;
|
||||
that._onDidChangeState.fire();
|
||||
|
||||
that.mixinMetadata({
|
||||
runState: null,
|
||||
lastRunSuccess: success ?? null,
|
||||
runEndTime: endTime ?? null,
|
||||
});
|
||||
},
|
||||
|
||||
clearOutput(cell?: vscode.NotebookCell | number): Thenable<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputs([], cell, false);
|
||||
},
|
||||
|
||||
appendOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputs(outputs, cell, true);
|
||||
},
|
||||
|
||||
replaceOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell | number): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputs(outputs, cell, false);
|
||||
},
|
||||
|
||||
appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputItems(items, output, true);
|
||||
},
|
||||
|
||||
replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput | string): Promise<void> {
|
||||
that.verifyStateForOutput();
|
||||
return that.updateOutputItems(items, output, false);
|
||||
}
|
||||
};
|
||||
return Object.freeze(result);
|
||||
}
|
||||
}
|
||||
|
||||
class TimeoutBasedCollector<T> {
|
||||
private batch: T[] = [];
|
||||
private waitPromise: Promise<void> | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly delay: number,
|
||||
private readonly callback: (items: T[]) => Promise<void>) { }
|
||||
|
||||
addItem(item: T): Promise<void> {
|
||||
this.batch.push(item);
|
||||
if (!this.waitPromise) {
|
||||
this.waitPromise = timeout(this.delay).then(() => {
|
||||
this.waitPromise = undefined;
|
||||
const batch = this.batch;
|
||||
this.batch = [];
|
||||
return this.callback(batch);
|
||||
});
|
||||
}
|
||||
|
||||
return this.waitPromise;
|
||||
}
|
||||
}
|
||||
|
||||
59
src/vs/workbench/api/common/extHostNotebookRenderers.ts
Normal file
59
src/vs/workbench/api/common/extHostNotebookRenderers.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostNotebookRenderersShape, IMainContext, MainContext, MainThreadNotebookRenderersShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostNotebookEditor } from 'vs/workbench/api/common/extHostNotebookEditor';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostNotebookRenderers implements ExtHostNotebookRenderersShape {
|
||||
private readonly _rendererMessageEmitters = new Map<string /* rendererId */, Emitter<vscode.NotebookRendererMessage<any>>>();
|
||||
private readonly proxy: MainThreadNotebookRenderersShape;
|
||||
|
||||
constructor(mainContext: IMainContext, private readonly _extHostNotebook: ExtHostNotebookController) {
|
||||
this.proxy = mainContext.getProxy(MainContext.MainThreadNotebookRenderers);
|
||||
}
|
||||
|
||||
public $postRendererMessage(editorId: string, rendererId: string, message: unknown): void {
|
||||
const editor = this._extHostNotebook.getEditorById(editorId);
|
||||
this._rendererMessageEmitters.get(rendererId)?.fire({ editor: editor.apiEditor, message });
|
||||
}
|
||||
|
||||
public createRendererMessaging<TSend, TRecv>(rendererId: string): vscode.NotebookRendererMessaging<TSend, TRecv> {
|
||||
const messaging: vscode.NotebookRendererMessaging<TSend, TRecv> = {
|
||||
onDidReceiveMessage: (...args) =>
|
||||
this.getOrCreateEmitterFor(rendererId).event(...args),
|
||||
postMessage: (editor, message) => {
|
||||
const extHostEditor = ExtHostNotebookEditor.apiEditorsToExtHost.get(editor);
|
||||
if (!extHostEditor) {
|
||||
throw new Error(`The first argument to postMessage() must be a NotebookEditor`);
|
||||
}
|
||||
|
||||
this.proxy.$postMessage(extHostEditor.id, rendererId, message);
|
||||
},
|
||||
};
|
||||
|
||||
return messaging;
|
||||
}
|
||||
|
||||
private getOrCreateEmitterFor(rendererId: string) {
|
||||
let emitter = this._rendererMessageEmitters.get(rendererId);
|
||||
if (emitter) {
|
||||
return emitter;
|
||||
}
|
||||
|
||||
emitter = new Emitter({
|
||||
onLastListenerRemove: () => {
|
||||
emitter?.dispose();
|
||||
this._rendererMessageEmitters.delete(rendererId);
|
||||
}
|
||||
});
|
||||
|
||||
this._rendererMessageEmitters.set(rendererId, emitter);
|
||||
|
||||
return emitter;
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,10 @@ import { MainContext, MainThreadStatusBarShape, IMainContext, ICommandDto } from
|
||||
import { localize } from 'vs/nls';
|
||||
import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
|
||||
private static ID_GEN = 0;
|
||||
|
||||
private static ALLOWED_BACKGROUND_COLORS = new Map<string, ThemeColor>(
|
||||
@@ -21,17 +23,20 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
#proxy: MainThreadStatusBarShape;
|
||||
#commands: CommandsConverter;
|
||||
|
||||
private _id: number;
|
||||
private _entryId: number;
|
||||
|
||||
private _extension?: IExtensionDescription;
|
||||
|
||||
private _id?: string;
|
||||
private _alignment: number;
|
||||
private _priority?: number;
|
||||
|
||||
private _disposed: boolean = false;
|
||||
private _visible: boolean = false;
|
||||
|
||||
private _statusId: string;
|
||||
private _statusName: string;
|
||||
|
||||
private _text: string = '';
|
||||
private _tooltip?: string;
|
||||
private _name?: string;
|
||||
private _color?: string | ThemeColor;
|
||||
private _backgroundColor?: ThemeColor;
|
||||
private readonly _internalCommandRegistration = new DisposableStore();
|
||||
@@ -43,20 +48,23 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
private _timeoutHandle: any;
|
||||
private _accessibilityInformation?: vscode.AccessibilityInformation;
|
||||
|
||||
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation) {
|
||||
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, extension: IExtensionDescription, id?: string, alignment?: ExtHostStatusBarAlignment, priority?: number);
|
||||
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, extension: IExtensionDescription | undefined, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number);
|
||||
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, extension?: IExtensionDescription, id?: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
|
||||
this.#proxy = proxy;
|
||||
this.#commands = commands;
|
||||
|
||||
this._id = ExtHostStatusBarEntry.ID_GEN++;
|
||||
this._statusId = id;
|
||||
this._statusName = name;
|
||||
this._entryId = ExtHostStatusBarEntry.ID_GEN++;
|
||||
|
||||
this._extension = extension;
|
||||
|
||||
this._id = id;
|
||||
this._alignment = alignment;
|
||||
this._priority = priority;
|
||||
this._accessibilityInformation = accessibilityInformation;
|
||||
}
|
||||
|
||||
public get id(): number {
|
||||
return this._id;
|
||||
public get id(): string {
|
||||
return this._id ?? this._extension!.identifier.value;
|
||||
}
|
||||
|
||||
public get alignment(): vscode.StatusBarAlignment {
|
||||
@@ -71,6 +79,10 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
return this._text;
|
||||
}
|
||||
|
||||
public get name(): string | undefined {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get tooltip(): string | undefined {
|
||||
return this._tooltip;
|
||||
}
|
||||
@@ -96,6 +108,11 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
this.update();
|
||||
}
|
||||
|
||||
public set name(name: string | undefined) {
|
||||
this._name = name;
|
||||
this.update();
|
||||
}
|
||||
|
||||
public set tooltip(tooltip: string | undefined) {
|
||||
this._tooltip = tooltip;
|
||||
this.update();
|
||||
@@ -150,7 +167,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
public hide(): void {
|
||||
clearTimeout(this._timeoutHandle);
|
||||
this._visible = false;
|
||||
this.#proxy.$dispose(this.id);
|
||||
this.#proxy.$dispose(this._entryId);
|
||||
}
|
||||
|
||||
private update(): void {
|
||||
@@ -164,6 +181,28 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
this._timeoutHandle = setTimeout(() => {
|
||||
this._timeoutHandle = undefined;
|
||||
|
||||
// If the id is not set, derive it from the extension identifier,
|
||||
// otherwise make sure to prefix it with the extension identifier
|
||||
// to get a more unique value across extensions.
|
||||
let id: string;
|
||||
if (this._extension) {
|
||||
if (this._id) {
|
||||
id = `${this._extension.identifier.value}.${this._id}`;
|
||||
} else {
|
||||
id = this._extension.identifier.value;
|
||||
}
|
||||
} else {
|
||||
id = this._id!;
|
||||
}
|
||||
|
||||
// If the name is not set, derive it from the extension descriptor
|
||||
let name: string;
|
||||
if (this._name) {
|
||||
name = this._name;
|
||||
} else {
|
||||
name = localize('extensionLabel', "{0} (Extension)", this._extension!.displayName || this._extension!.name);
|
||||
}
|
||||
|
||||
// If a background color is set, the foreground is determined
|
||||
let color = this._color;
|
||||
if (this._backgroundColor) {
|
||||
@@ -171,7 +210,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
|
||||
}
|
||||
|
||||
// Set to status bar
|
||||
this.#proxy.$setEntry(this.id, this._statusId, this._statusName, this._text, this._tooltip, this._command?.internal, color,
|
||||
this.#proxy.$setEntry(this._entryId, id, name, this._text, this._tooltip, this._command?.internal, color,
|
||||
this._backgroundColor, this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT,
|
||||
this._priority, this._accessibilityInformation);
|
||||
}, 0);
|
||||
@@ -189,7 +228,8 @@ class StatusBarMessage {
|
||||
private _messages: { message: string }[] = [];
|
||||
|
||||
constructor(statusBar: ExtHostStatusBar) {
|
||||
this._item = statusBar.createStatusBarEntry('status.extensionMessage', localize('status.extensionMessage', "Extension Status"), ExtHostStatusBarAlignment.Left, Number.MIN_VALUE);
|
||||
this._item = statusBar.createStatusBarEntry(undefined, 'status.extensionMessage', ExtHostStatusBarAlignment.Left, Number.MIN_VALUE);
|
||||
this._item.name = localize('status.extensionMessage', "Extension Status");
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@@ -233,12 +273,13 @@ export class ExtHostStatusBar {
|
||||
this._statusMessage = new StatusBarMessage(this);
|
||||
}
|
||||
|
||||
createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number, accessibilityInformation?: vscode.AccessibilityInformation): vscode.StatusBarItem {
|
||||
return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority, accessibilityInformation);
|
||||
createStatusBarEntry(extension: IExtensionDescription | undefined, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem;
|
||||
createStatusBarEntry(extension: IExtensionDescription, id?: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem;
|
||||
createStatusBarEntry(extension: IExtensionDescription, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem {
|
||||
return new ExtHostStatusBarEntry(this._proxy, this._commands, extension, id, alignment, priority);
|
||||
}
|
||||
|
||||
setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): Disposable {
|
||||
|
||||
const d = this._statusMessage.setMessage(text);
|
||||
let handle: any;
|
||||
|
||||
|
||||
@@ -605,8 +605,6 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape, IExtHostTask
|
||||
|
||||
public abstract $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }>;
|
||||
|
||||
public abstract $getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }>;
|
||||
|
||||
private nextHandle(): number {
|
||||
return this._handleCounter++;
|
||||
}
|
||||
@@ -775,10 +773,6 @@ export class WorkerExtHostTask extends ExtHostTaskBase {
|
||||
return result;
|
||||
}
|
||||
|
||||
public $getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
public async $jsonTasksSupported(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellAndArgsDto, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType } from './extHostTypes';
|
||||
import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType, ThemeColor } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { NotSupportedError } from 'vs/base/common/errors';
|
||||
@@ -19,9 +18,10 @@ import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/ter
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { IProcessReadyEvent, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, TerminalIcon, TerminalShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering';
|
||||
import { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable {
|
||||
|
||||
@@ -37,15 +37,22 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID
|
||||
onDidWriteTerminalData: Event<vscode.TerminalDataWriteEvent>;
|
||||
|
||||
createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal;
|
||||
createTerminalFromOptions(options: vscode.TerminalOptions, isFeatureTerminal?: boolean): vscode.Terminal;
|
||||
createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal;
|
||||
createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal;
|
||||
attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): void;
|
||||
getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string;
|
||||
getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string;
|
||||
getDefaultShell(useAutomationShell: boolean): string;
|
||||
getDefaultShellArgs(useAutomationShell: boolean): string[] | string;
|
||||
registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable;
|
||||
registerProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable;
|
||||
getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection;
|
||||
}
|
||||
|
||||
export interface ITerminalInternalOptions {
|
||||
isFeatureTerminal?: boolean;
|
||||
useShellEnvironment?: boolean;
|
||||
isSplitTerminal?: boolean;
|
||||
}
|
||||
|
||||
export const IExtHostTerminalService = createDecorator<IExtHostTerminalService>('IExtHostTerminalService');
|
||||
|
||||
export class ExtHostTerminal {
|
||||
@@ -114,29 +121,39 @@ export class ExtHostTerminal {
|
||||
}
|
||||
|
||||
public async create(
|
||||
shellPath?: string,
|
||||
shellArgs?: string[] | string,
|
||||
cwd?: string | URI,
|
||||
env?: ITerminalEnvironment,
|
||||
icon?: string,
|
||||
initialText?: string,
|
||||
waitOnExit?: boolean,
|
||||
strictEnv?: boolean,
|
||||
hideFromUser?: boolean,
|
||||
isFeatureTerminal?: boolean,
|
||||
isExtensionOwnedTerminal?: boolean
|
||||
options: vscode.TerminalOptions,
|
||||
internalOptions?: ITerminalInternalOptions,
|
||||
): Promise<void> {
|
||||
if (typeof this._id !== 'string') {
|
||||
throw new Error('Terminal has already been created');
|
||||
}
|
||||
await this._proxy.$createTerminal(this._id, { name: this._name, shellPath, shellArgs, cwd, env, icon, initialText, waitOnExit, strictEnv, hideFromUser, isFeatureTerminal, isExtensionOwnedTerminal });
|
||||
await this._proxy.$createTerminal(this._id, {
|
||||
name: options.name,
|
||||
shellPath: withNullAsUndefined(options.shellPath),
|
||||
shellArgs: withNullAsUndefined(options.shellArgs),
|
||||
cwd: withNullAsUndefined(options.cwd),
|
||||
env: withNullAsUndefined(options.env),
|
||||
icon: withNullAsUndefined(asTerminalIcon(options.iconPath)),
|
||||
initialText: withNullAsUndefined(options.message),
|
||||
strictEnv: withNullAsUndefined(options.strictEnv),
|
||||
hideFromUser: withNullAsUndefined(options.hideFromUser),
|
||||
isFeatureTerminal: withNullAsUndefined(internalOptions?.isFeatureTerminal),
|
||||
isExtensionOwnedTerminal: true,
|
||||
useShellEnvironment: withNullAsUndefined(internalOptions?.useShellEnvironment),
|
||||
isSplitTerminal: withNullAsUndefined(internalOptions?.isSplitTerminal)
|
||||
});
|
||||
}
|
||||
|
||||
public async createExtensionTerminal(): Promise<number> {
|
||||
public async createExtensionTerminal(isSplitTerminal?: boolean, iconPath?: URI | { light: URI; dark: URI } | ThemeIcon): Promise<number> {
|
||||
if (typeof this._id !== 'string') {
|
||||
throw new Error('Terminal has already been created');
|
||||
}
|
||||
await this._proxy.$createTerminal(this._id, { name: this._name, isExtensionCustomPtyTerminal: true });
|
||||
await this._proxy.$createTerminal(this._id, {
|
||||
name: this._name,
|
||||
isExtensionCustomPtyTerminal: true,
|
||||
icon: iconPath,
|
||||
isSplitTerminal
|
||||
});
|
||||
// At this point, the id has been set via `$acceptTerminalOpened`
|
||||
if (typeof this._id === 'string') {
|
||||
throw new Error('Terminal creation failed');
|
||||
@@ -195,8 +212,8 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
public readonly onProcessData: Event<string> = this._onProcessData.event;
|
||||
private readonly _onProcessExit = new Emitter<number | undefined>();
|
||||
public readonly onProcessExit: Event<number | undefined> = this._onProcessExit.event;
|
||||
private readonly _onProcessReady = new Emitter<{ pid: number, cwd: string }>();
|
||||
public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; }
|
||||
private readonly _onProcessReady = new Emitter<IProcessReadyEvent>();
|
||||
public get onProcessReady(): Event<IProcessReadyEvent> { return this._onProcessReady.event; }
|
||||
private readonly _onProcessTitleChanged = new Emitter<string>();
|
||||
public readonly onProcessTitleChanged: Event<string> = this._onProcessTitleChanged.event;
|
||||
private readonly _onProcessOverrideDimensions = new Emitter<ITerminalDimensionsOverride | undefined>();
|
||||
@@ -259,6 +276,9 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
|
||||
if (this._pty.onDidOverrideDimensions) {
|
||||
this._pty.onDidOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e ? { cols: e.columns, rows: e.rows } : undefined)); // {{SQL CARBON EDIT}} strict-null-checks
|
||||
}
|
||||
if (this._pty.onDidChangeName) {
|
||||
this._pty.onDidChangeName(title => this._onProcessTitleChanged.fire(title));
|
||||
}
|
||||
|
||||
this._pty.open(initialDimensions ? initialDimensions : undefined);
|
||||
|
||||
@@ -289,9 +309,12 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
|
||||
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal | undefined> } = {};
|
||||
protected _environmentVariableCollections: Map<string, EnvironmentVariableCollection> = new Map();
|
||||
private _defaultProfile: ITerminalProfile | undefined;
|
||||
private _defaultAutomationProfile: ITerminalProfile | undefined;
|
||||
|
||||
private readonly _bufferer: TerminalDataBufferer;
|
||||
private readonly _linkProviders: Set<vscode.TerminalLinkProvider> = new Set();
|
||||
private readonly _profileProviders: Map<string, vscode.TerminalProfileProvider> = new Map();
|
||||
private readonly _terminalLinkCache: Map<number, Map<number, ICachedLinkEntry>> = new Map();
|
||||
private readonly _terminalLinkCancellationSource: Map<number, CancellationTokenSource> = new Map();
|
||||
|
||||
@@ -331,16 +354,22 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
}
|
||||
|
||||
public abstract createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal;
|
||||
public abstract createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal;
|
||||
public abstract getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string;
|
||||
public abstract getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string;
|
||||
public abstract $getAvailableProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]>;
|
||||
public abstract $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>;
|
||||
public abstract createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal;
|
||||
|
||||
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
|
||||
public getDefaultShell(useAutomationShell: boolean): string {
|
||||
const profile = useAutomationShell ? this._defaultAutomationProfile : this._defaultProfile;
|
||||
return profile?.path || '';
|
||||
}
|
||||
|
||||
public getDefaultShellArgs(useAutomationShell: boolean): string[] | string {
|
||||
const profile = useAutomationShell ? this._defaultAutomationProfile : this._defaultProfile;
|
||||
return profile?.args || [];
|
||||
}
|
||||
|
||||
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name);
|
||||
const p = new ExtHostPseudoterminal(options.pty);
|
||||
terminal.createExtensionTerminal().then(id => {
|
||||
terminal.createExtensionTerminal(internalOptions?.isSplitTerminal, asTerminalIcon(options.iconPath)).then(id => {
|
||||
const disposable = this._setupExtHostProcessListeners(id, p);
|
||||
this._terminalProcessDisposables[id] = disposable;
|
||||
});
|
||||
@@ -363,7 +392,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
if (id === null) {
|
||||
this._activeTerminal = undefined;
|
||||
if (original !== this._activeTerminal) {
|
||||
this._onDidChangeActiveTerminal.fire(this._activeTerminal.value);
|
||||
this._onDidChangeActiveTerminal.fire(this._activeTerminal?.value); // {{SQL CARBON EDIT}}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -555,6 +584,34 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
});
|
||||
}
|
||||
|
||||
public registerProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable {
|
||||
if (this._profileProviders.has(id)) {
|
||||
throw new Error(`Terminal profile provider "${id}" already registered`);
|
||||
}
|
||||
this._profileProviders.set(id, provider);
|
||||
this._proxy.$registerProfileProvider(id);
|
||||
return new VSCodeDisposable(() => {
|
||||
this._profileProviders.delete(id);
|
||||
this._proxy.$unregisterProfileProvider(id);
|
||||
});
|
||||
}
|
||||
|
||||
public async $createContributedProfileTerminal(id: string, isSplitTerminal: boolean): Promise<void> {
|
||||
const token = new CancellationTokenSource().token;
|
||||
const options = await this._profileProviders.get(id)?.provideProfileOptions(token);
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
if (!options) {
|
||||
throw new Error(`No terminal profile options provided for id "${id}"`);
|
||||
}
|
||||
if ('pty' in options) {
|
||||
this.createExtensionTerminal(options, { isSplitTerminal });
|
||||
return;
|
||||
}
|
||||
this.createTerminalFromOptions(options, { isSplitTerminal });
|
||||
}
|
||||
|
||||
public async $provideLinks(terminalId: number, line: string): Promise<ITerminalLinkDto[]> {
|
||||
const terminal = this._getTerminalById(terminalId);
|
||||
if (!terminal) {
|
||||
@@ -686,6 +743,11 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
|
||||
});
|
||||
}
|
||||
|
||||
public $acceptDefaultProfile(profile: ITerminalProfile, automationProfile: ITerminalProfile): void {
|
||||
this._defaultProfile = profile;
|
||||
this._defaultAutomationProfile = automationProfile;
|
||||
}
|
||||
|
||||
private _setEnvironmentVariableCollection(extensionIdentifier: string, collection: EnvironmentVariableCollection): void {
|
||||
this._environmentVariableCollections.set(extensionIdentifier, collection);
|
||||
collection.onDidChangeCollection(() => {
|
||||
@@ -771,23 +833,20 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService {
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string {
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string {
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public $getAvailableProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]> {
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
|
||||
public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
|
||||
throw new NotSupportedError();
|
||||
}
|
||||
}
|
||||
|
||||
function asTerminalIcon(iconPath?: vscode.Uri | { light: vscode.Uri; dark: vscode.Uri } | vscode.ThemeIcon): TerminalIcon | undefined {
|
||||
if (!iconPath) {
|
||||
return undefined;
|
||||
}
|
||||
if (!('id' in iconPath)) {
|
||||
return iconPath;
|
||||
}
|
||||
return {
|
||||
id: iconPath.id,
|
||||
color: iconPath.color as ThemeColor
|
||||
};
|
||||
}
|
||||
|
||||
@@ -666,7 +666,7 @@ export class TestItemFilteredWrapper extends TestItemImpl {
|
||||
}
|
||||
}
|
||||
|
||||
const nowMatches = this.children.size > 0 || this.actual.uri.toString() === this.filterDocument.uri.toString();
|
||||
const nowMatches = this.children.size > 0 || this.actual.uri?.toString() === this.filterDocument.uri.toString();
|
||||
this._cachedMatchesFilter = nowMatches;
|
||||
|
||||
if (nowMatches !== didMatch) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
@@ -15,6 +15,7 @@ import { EndOfLine, Position, Range, Selection, SnippetString, TextEditorLineNum
|
||||
import type * as vscode from 'vscode';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Lazy } from 'vs/base/common/lazy';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class TextEditorDecorationType {
|
||||
|
||||
@@ -22,9 +23,9 @@ export class TextEditorDecorationType {
|
||||
|
||||
readonly value: vscode.TextEditorDecorationType;
|
||||
|
||||
constructor(proxy: MainThreadTextEditorsShape, options: vscode.DecorationRenderOptions) {
|
||||
constructor(proxy: MainThreadTextEditorsShape, extension: IExtensionDescription, options: vscode.DecorationRenderOptions) {
|
||||
const key = TextEditorDecorationType._Keys.nextId();
|
||||
proxy.$registerTextEditorDecorationType(key, TypeConverters.DecorationRenderOptions.from(options));
|
||||
proxy.$registerTextEditorDecorationType(extension.identifier, key, TypeConverters.DecorationRenderOptions.from(options));
|
||||
this.value = Object.freeze({
|
||||
key,
|
||||
dispose() {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ExtHostTextEditor, TextEditorDecorationType } from 'vs/workbench/api/co
|
||||
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { TextEditorSelectionChangeKind } from 'vs/workbench/api/common/extHostTypes';
|
||||
import type * as vscode from 'vscode';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
|
||||
@@ -91,8 +92,8 @@ export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
}
|
||||
}
|
||||
|
||||
createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
|
||||
return new TextEditorDecorationType(this._proxy, options).value;
|
||||
createTextEditorDecorationType(extension: IExtensionDescription, options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
|
||||
return new TextEditorDecorationType(this._proxy, extension, options).value;
|
||||
}
|
||||
|
||||
// --- called from main thread
|
||||
|
||||
@@ -9,7 +9,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import * as marked from 'vs/base/common/marked/marked';
|
||||
import { parse } from 'vs/base/common/marshalling';
|
||||
import { cloneAndChange } from 'vs/base/common/objects';
|
||||
import { isDefined, isNumber, isString } from 'vs/base/common/types';
|
||||
import { isDefined, isEmptyObject, isNumber, isString } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
@@ -545,7 +545,7 @@ export namespace WorkspaceEdit {
|
||||
resource: entry.uri,
|
||||
edit: entry.edit,
|
||||
notebookMetadata: entry.notebookMetadata,
|
||||
notebookVersionId: extHostNotebooks?.lookupNotebookDocument(entry.uri)?.apiNotebook.version
|
||||
notebookVersionId: extHostNotebooks?.getNotebookDocument(entry.uri, true)?.apiNotebook.version
|
||||
});
|
||||
|
||||
} else if (entry._type === types.FileEditType.CellOutput) {
|
||||
@@ -580,7 +580,7 @@ export namespace WorkspaceEdit {
|
||||
_type: extHostProtocol.WorkspaceEditType.Cell,
|
||||
metadata: entry.metadata,
|
||||
resource: entry.uri,
|
||||
notebookVersionId: extHostNotebooks?.lookupNotebookDocument(entry.uri)?.apiNotebook.version,
|
||||
notebookVersionId: extHostNotebooks?.getNotebookDocument(entry.uri, true)?.apiNotebook.version,
|
||||
edit: {
|
||||
editType: notebooks.CellEditType.Replace,
|
||||
index: entry.index,
|
||||
@@ -1130,37 +1130,35 @@ export namespace SignatureHelp {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace InlineHint {
|
||||
export namespace InlayHint {
|
||||
|
||||
export function from(hint: vscode.InlineHint): modes.InlineHint {
|
||||
export function from(hint: vscode.InlayHint): modes.InlayHint {
|
||||
return {
|
||||
text: hint.text,
|
||||
range: Range.from(hint.range),
|
||||
kind: InlineHintKind.from(hint.kind ?? types.InlineHintKind.Other),
|
||||
description: hint.description && MarkdownString.fromStrict(hint.description),
|
||||
position: Position.from(hint.position),
|
||||
kind: InlayHintKind.from(hint.kind ?? types.InlayHintKind.Other),
|
||||
whitespaceBefore: hint.whitespaceBefore,
|
||||
whitespaceAfter: hint.whitespaceAfter
|
||||
};
|
||||
}
|
||||
|
||||
export function to(hint: modes.InlineHint): vscode.InlineHint {
|
||||
const res = new types.InlineHint(
|
||||
export function to(hint: modes.InlayHint): vscode.InlayHint {
|
||||
const res = new types.InlayHint(
|
||||
hint.text,
|
||||
Range.to(hint.range),
|
||||
InlineHintKind.to(hint.kind)
|
||||
Position.to(hint.position),
|
||||
InlayHintKind.to(hint.kind)
|
||||
);
|
||||
res.whitespaceAfter = hint.whitespaceAfter;
|
||||
res.whitespaceBefore = hint.whitespaceBefore;
|
||||
res.description = htmlContent.isMarkdownString(hint.description) ? MarkdownString.to(hint.description) : hint.description;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace InlineHintKind {
|
||||
export function from(kind: vscode.InlineHintKind): modes.InlineHintKind {
|
||||
export namespace InlayHintKind {
|
||||
export function from(kind: vscode.InlayHintKind): modes.InlayHintKind {
|
||||
return kind;
|
||||
}
|
||||
export function to(kind: modes.InlineHintKind): vscode.InlineHintKind {
|
||||
export function to(kind: modes.InlayHintKind): vscode.InlayHintKind {
|
||||
return kind;
|
||||
}
|
||||
}
|
||||
@@ -1417,49 +1415,20 @@ export namespace NotebookRange {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookCellMetadata {
|
||||
|
||||
export function to(data: notebooks.NotebookCellMetadata): types.NotebookCellMetadata {
|
||||
return new types.NotebookCellMetadata().with({
|
||||
...data,
|
||||
...{
|
||||
executionOrder: null,
|
||||
lastRunSuccess: null,
|
||||
runState: null,
|
||||
runStartTime: null,
|
||||
runStartTimeAdjustment: null,
|
||||
runEndTime: null
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookDocumentMetadata {
|
||||
|
||||
export function from(data: types.NotebookDocumentMetadata): notebooks.NotebookDocumentMetadata {
|
||||
return data;
|
||||
}
|
||||
|
||||
export function to(data: notebooks.NotebookDocumentMetadata): types.NotebookDocumentMetadata {
|
||||
return new types.NotebookDocumentMetadata().with(data);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookCellPreviousExecutionResult {
|
||||
export function to(data: notebooks.NotebookCellMetadata): vscode.NotebookCellExecutionSummary {
|
||||
export namespace NotebookCellExecutionSummary {
|
||||
export function to(data: notebooks.NotebookCellInternalMetadata): vscode.NotebookCellExecutionSummary {
|
||||
return {
|
||||
startTime: data.runStartTime,
|
||||
endTime: data.runEndTime,
|
||||
timing: typeof data.runStartTime === 'number' && typeof data.runEndTime === 'number' ? { startTime: data.runStartTime, endTime: data.runEndTime } : undefined,
|
||||
executionOrder: data.executionOrder,
|
||||
success: data.lastRunSuccess
|
||||
};
|
||||
}
|
||||
|
||||
export function from(data: vscode.NotebookCellExecutionSummary): Partial<notebooks.NotebookCellMetadata> {
|
||||
export function from(data: vscode.NotebookCellExecutionSummary): Partial<notebooks.NotebookCellInternalMetadata> {
|
||||
return {
|
||||
lastRunSuccess: data.success,
|
||||
runStartTime: data.startTime,
|
||||
runEndTime: data.endTime,
|
||||
runStartTime: data.timing?.startTime,
|
||||
runEndTime: data.timing?.endTime,
|
||||
executionOrder: data.executionOrder
|
||||
};
|
||||
}
|
||||
@@ -1468,8 +1437,8 @@ export namespace NotebookCellPreviousExecutionResult {
|
||||
export namespace NotebookCellKind {
|
||||
export function from(data: vscode.NotebookCellKind): notebooks.CellKind {
|
||||
switch (data) {
|
||||
case types.NotebookCellKind.Markdown:
|
||||
return notebooks.CellKind.Markdown;
|
||||
case types.NotebookCellKind.Markup:
|
||||
return notebooks.CellKind.Markup;
|
||||
case types.NotebookCellKind.Code:
|
||||
default:
|
||||
return notebooks.CellKind.Code;
|
||||
@@ -1478,8 +1447,8 @@ export namespace NotebookCellKind {
|
||||
|
||||
export function to(data: notebooks.CellKind): vscode.NotebookCellKind {
|
||||
switch (data) {
|
||||
case notebooks.CellKind.Markdown:
|
||||
return types.NotebookCellKind.Markdown;
|
||||
case notebooks.CellKind.Markup:
|
||||
return types.NotebookCellKind.Markup;
|
||||
case notebooks.CellKind.Code:
|
||||
default:
|
||||
return types.NotebookCellKind.Code;
|
||||
@@ -1487,17 +1456,40 @@ export namespace NotebookCellKind {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookData {
|
||||
|
||||
export function from(data: vscode.NotebookData): notebooks.NotebookDataDto {
|
||||
const res: notebooks.NotebookDataDto = {
|
||||
metadata: data.metadata ?? Object.create(null),
|
||||
cells: [],
|
||||
};
|
||||
for (let cell of data.cells) {
|
||||
types.NotebookCellData.validate(cell);
|
||||
res.cells.push(NotebookCellData.from(cell));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export function to(data: notebooks.NotebookDataDto): vscode.NotebookData {
|
||||
const res = new types.NotebookData(
|
||||
data.cells.map(NotebookCellData.to),
|
||||
);
|
||||
if (!isEmptyObject(data.metadata)) {
|
||||
res.metadata = data.metadata;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookCellData {
|
||||
|
||||
export function from(data: vscode.NotebookCellData): notebooks.ICellDto2 {
|
||||
return {
|
||||
cellKind: NotebookCellKind.from(data.kind),
|
||||
language: data.language,
|
||||
source: data.source,
|
||||
metadata: {
|
||||
...data.metadata,
|
||||
...NotebookCellPreviousExecutionResult.from(data.latestExecutionSummary ?? {})
|
||||
},
|
||||
language: data.languageId,
|
||||
source: data.value,
|
||||
metadata: data.metadata,
|
||||
internalMetadata: NotebookCellExecutionSummary.from(data.executionSummary ?? {}),
|
||||
outputs: data.outputs ? data.outputs.map(NotebookCellOutput.from) : []
|
||||
};
|
||||
}
|
||||
@@ -1508,7 +1500,8 @@ export namespace NotebookCellData {
|
||||
data.source,
|
||||
data.language,
|
||||
data.outputs ? data.outputs.map(NotebookCellOutput.to) : undefined,
|
||||
data.metadata ? NotebookCellMetadata.to(data.metadata) : undefined,
|
||||
data.metadata,
|
||||
data.internalMetadata ? NotebookCellExecutionSummary.to(data.internalMetadata) : undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1517,21 +1510,20 @@ export namespace NotebookCellOutputItem {
|
||||
export function from(item: types.NotebookCellOutputItem): notebooks.IOutputItemDto {
|
||||
return {
|
||||
mime: item.mime,
|
||||
value: item.value,
|
||||
metadata: item.metadata
|
||||
valueBytes: Array.from(item.data), //todo@jrieken this HACKY and SLOW... hoist VSBuffer instead
|
||||
};
|
||||
}
|
||||
|
||||
export function to(item: notebooks.IOutputItemDto): types.NotebookCellOutputItem {
|
||||
return new types.NotebookCellOutputItem(item.mime, item.value, item.metadata);
|
||||
return new types.NotebookCellOutputItem(new Uint8Array(item.valueBytes), item.mime);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookCellOutput {
|
||||
export function from(output: types.NotebookCellOutput): notebooks.IOutputDto {
|
||||
export function from(output: vscode.NotebookCellOutput): notebooks.IOutputDto {
|
||||
return {
|
||||
outputId: output.id,
|
||||
outputs: output.outputs.map(NotebookCellOutputItem.from),
|
||||
outputs: output.items.map(NotebookCellOutputItem.from),
|
||||
metadata: output.metadata
|
||||
};
|
||||
}
|
||||
@@ -1644,35 +1636,22 @@ export namespace NotebookDocumentContentOptions {
|
||||
export function from(options: vscode.NotebookDocumentContentOptions | undefined): notebooks.TransientOptions {
|
||||
return {
|
||||
transientOutputs: options?.transientOutputs ?? false,
|
||||
transientCellMetadata: {
|
||||
...options?.transientCellMetadata,
|
||||
executionOrder: true,
|
||||
runState: true,
|
||||
runStartTime: true,
|
||||
runStartTimeAdjustment: true,
|
||||
runEndTime: true,
|
||||
lastRunSuccess: true
|
||||
},
|
||||
transientCellMetadata: options?.transientCellMetadata ?? {},
|
||||
transientDocumentMetadata: options?.transientDocumentMetadata ?? {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NotebookKernelPreload {
|
||||
export function from(preload: vscode.NotebookKernelPreload): { uri: UriComponents; provides: string[] } {
|
||||
export namespace NotebookRendererScript {
|
||||
export function from(preload: vscode.NotebookRendererScript): { uri: UriComponents; provides: string[] } {
|
||||
return {
|
||||
uri: preload.uri,
|
||||
provides: typeof preload.provides === 'string'
|
||||
? [preload.provides]
|
||||
: preload.provides ?? []
|
||||
};
|
||||
}
|
||||
export function to(preload: { uri: UriComponents; provides: string[] }): vscode.NotebookKernelPreload {
|
||||
return {
|
||||
uri: URI.revive(preload.uri),
|
||||
provides: preload.provides
|
||||
};
|
||||
}
|
||||
export function to(preload: { uri: UriComponents; provides: string[] }): vscode.NotebookRendererScript {
|
||||
return new types.NotebookRendererScript(URI.revive(preload.uri), preload.provides);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TestMessage {
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { coalesceInPlace, equals } from 'vs/base/common/arrays';
|
||||
import { asArray, coalesceInPlace, equals } from 'vs/base/common/arrays';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { isMarkdownString, MarkdownString as BaseMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ReadonlyMapView, ResourceMap } from 'vs/base/common/map';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { isStringArray } from 'vs/base/common/types';
|
||||
import { normalizeMimeType } from 'vs/base/common/mime';
|
||||
import { isArray, isStringArray } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
|
||||
@@ -612,7 +612,7 @@ export interface IFileCellEdit {
|
||||
_type: FileEditType.Cell;
|
||||
uri: URI;
|
||||
edit?: ICellEditOperation;
|
||||
notebookMetadata?: vscode.NotebookDocumentMetadata;
|
||||
notebookMetadata?: Record<string, any>;
|
||||
metadata?: vscode.WorkspaceEditEntryMetadata;
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ export interface ICellOutputEdit {
|
||||
index: number;
|
||||
append: boolean;
|
||||
newOutputs?: NotebookCellOutput[];
|
||||
newMetadata?: vscode.NotebookCellMetadata;
|
||||
newMetadata?: Record<string, any>;
|
||||
metadata?: vscode.WorkspaceEditEntryMetadata;
|
||||
}
|
||||
|
||||
@@ -674,7 +674,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
|
||||
|
||||
// --- notebook
|
||||
|
||||
replaceNotebookMetadata(uri: URI, value: vscode.NotebookDocumentMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
replaceNotebookMetadata(uri: URI, value: Record<string, any>, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.DocumentMetadata, metadata: value }, notebookMetadata: value });
|
||||
}
|
||||
|
||||
@@ -707,7 +707,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
|
||||
}
|
||||
}
|
||||
|
||||
replaceNotebookCellMetadata(uri: URI, index: number, cellMetadata: vscode.NotebookCellMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
replaceNotebookCellMetadata(uri: URI, index: number, cellMetadata: Record<string, any>, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.PartialMetadata, index, metadata: cellMetadata } });
|
||||
}
|
||||
|
||||
@@ -1420,24 +1420,23 @@ export enum SignatureHelpTriggerKind {
|
||||
}
|
||||
|
||||
|
||||
export enum InlineHintKind {
|
||||
export enum InlayHintKind {
|
||||
Other = 0,
|
||||
Type = 1,
|
||||
Parameter = 2,
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class InlineHint {
|
||||
export class InlayHint {
|
||||
text: string;
|
||||
range: Range;
|
||||
kind?: vscode.InlineHintKind;
|
||||
description?: string | vscode.MarkdownString;
|
||||
position: Position;
|
||||
kind?: vscode.InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
|
||||
constructor(text: string, range: Range, kind?: vscode.InlineHintKind) {
|
||||
constructor(text: string, position: Position, kind?: vscode.InlayHintKind) {
|
||||
this.text = text;
|
||||
this.range = range;
|
||||
this.position = position;
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
@@ -1548,6 +1547,29 @@ export class CompletionList {
|
||||
}
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class InlineSuggestion implements vscode.InlineCompletionItem {
|
||||
|
||||
text: string;
|
||||
range?: Range;
|
||||
command?: vscode.Command;
|
||||
|
||||
constructor(text: string, range?: Range, command?: vscode.Command) {
|
||||
this.text = text;
|
||||
this.range = range;
|
||||
this.command = command;
|
||||
}
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class InlineSuggestions implements vscode.InlineCompletionList {
|
||||
items: vscode.InlineCompletionItem[];
|
||||
|
||||
constructor(items: vscode.InlineCompletionItem[]) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
||||
|
||||
export enum ViewColumn {
|
||||
Active = -1,
|
||||
Beside = -2,
|
||||
@@ -2439,6 +2461,11 @@ export class EvaluatableExpression implements vscode.EvaluatableExpression {
|
||||
}
|
||||
}
|
||||
|
||||
export enum InlineCompletionTriggerKind {
|
||||
Automatic = 0,
|
||||
Explicit = 1,
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class InlineValueText implements vscode.InlineValueText {
|
||||
readonly range: Range;
|
||||
@@ -2956,103 +2983,20 @@ export class NotebookRange {
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookCellMetadata {
|
||||
readonly inputCollapsed?: boolean;
|
||||
readonly outputCollapsed?: boolean;
|
||||
readonly [key: string]: any;
|
||||
|
||||
constructor(inputCollapsed?: boolean, outputCollapsed?: boolean);
|
||||
constructor(data: Record<string, any>);
|
||||
constructor(inputCollapsedOrData: (boolean | undefined) | Record<string, any>, outputCollapsed?: boolean) {
|
||||
if (typeof inputCollapsedOrData === 'object') {
|
||||
Object.assign(this, inputCollapsedOrData);
|
||||
} else {
|
||||
this.inputCollapsed = inputCollapsedOrData;
|
||||
this.outputCollapsed = outputCollapsed;
|
||||
}
|
||||
}
|
||||
|
||||
with(change: {
|
||||
inputCollapsed?: boolean | null,
|
||||
outputCollapsed?: boolean | null,
|
||||
[key: string]: any
|
||||
}): NotebookCellMetadata {
|
||||
|
||||
let { inputCollapsed, outputCollapsed, ...remaining } = change;
|
||||
|
||||
if (inputCollapsed === undefined) {
|
||||
inputCollapsed = this.inputCollapsed;
|
||||
} else if (inputCollapsed === null) {
|
||||
inputCollapsed = undefined;
|
||||
}
|
||||
if (outputCollapsed === undefined) {
|
||||
outputCollapsed = this.outputCollapsed;
|
||||
} else if (outputCollapsed === null) {
|
||||
outputCollapsed = undefined;
|
||||
}
|
||||
|
||||
if (inputCollapsed === this.inputCollapsed &&
|
||||
outputCollapsed === this.outputCollapsed &&
|
||||
Object.keys(remaining).length === 0
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new NotebookCellMetadata(
|
||||
{
|
||||
inputCollapsed,
|
||||
outputCollapsed,
|
||||
...remaining
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookDocumentMetadata {
|
||||
readonly trusted: boolean;
|
||||
readonly [key: string]: any;
|
||||
|
||||
constructor(trusted?: boolean);
|
||||
constructor(data: Record<string, any>);
|
||||
constructor(trustedOrData: boolean | Record<string, any> = true) {
|
||||
if (typeof trustedOrData === 'object') {
|
||||
Object.assign(this, trustedOrData);
|
||||
this.trusted = trustedOrData.trusted ?? true;
|
||||
} else {
|
||||
this.trusted = trustedOrData;
|
||||
}
|
||||
}
|
||||
|
||||
with(change: {
|
||||
trusted?: boolean | null,
|
||||
[key: string]: any
|
||||
}): NotebookDocumentMetadata {
|
||||
|
||||
let { trusted, ...remaining } = change;
|
||||
|
||||
if (trusted === undefined) {
|
||||
trusted = this.trusted;
|
||||
} else if (trusted === null) {
|
||||
trusted = undefined;
|
||||
}
|
||||
|
||||
if (trusted === this.trusted &&
|
||||
Object.keys(remaining).length === 0
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new NotebookDocumentMetadata(
|
||||
{
|
||||
trusted,
|
||||
...remaining
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookCellData {
|
||||
|
||||
static validate(data: NotebookCellData): void {
|
||||
if (typeof data.kind !== 'number') {
|
||||
throw new Error('NotebookCellData MUST have \'kind\' property');
|
||||
}
|
||||
if (typeof data.value !== 'string') {
|
||||
throw new Error('NotebookCellData MUST have \'value\' property');
|
||||
}
|
||||
if (typeof data.languageId !== 'string') {
|
||||
throw new Error('NotebookCellData MUST have \'languageId\' property');
|
||||
}
|
||||
}
|
||||
|
||||
static isNotebookCellDataArray(value: unknown): value is vscode.NotebookCellData[] {
|
||||
return Array.isArray(value) && (<unknown[]>value).every(elem => NotebookCellData.isNotebookCellData(elem));
|
||||
}
|
||||
@@ -3063,30 +3007,31 @@ export class NotebookCellData {
|
||||
}
|
||||
|
||||
kind: NotebookCellKind;
|
||||
source: string;
|
||||
language: string;
|
||||
outputs?: NotebookCellOutput[];
|
||||
metadata?: NotebookCellMetadata;
|
||||
latestExecutionSummary?: vscode.NotebookCellExecutionSummary;
|
||||
value: string;
|
||||
languageId: string;
|
||||
outputs?: vscode.NotebookCellOutput[];
|
||||
metadata?: Record<string, any>;
|
||||
executionSummary?: vscode.NotebookCellExecutionSummary;
|
||||
|
||||
constructor(kind: NotebookCellKind, source: string, language: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, latestExecutionSummary?: vscode.NotebookCellExecutionSummary) {
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: vscode.NotebookCellOutput[], metadata?: Record<string, any>, executionSummary?: vscode.NotebookCellExecutionSummary) {
|
||||
this.kind = kind;
|
||||
this.source = source;
|
||||
this.language = language;
|
||||
this.value = value;
|
||||
this.languageId = languageId;
|
||||
this.outputs = outputs ?? [];
|
||||
this.metadata = metadata;
|
||||
this.latestExecutionSummary = latestExecutionSummary;
|
||||
this.executionSummary = executionSummary;
|
||||
|
||||
NotebookCellData.validate(this);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookData {
|
||||
|
||||
cells: NotebookCellData[];
|
||||
metadata: NotebookDocumentMetadata;
|
||||
metadata?: { [key: string]: any };
|
||||
|
||||
constructor(cells: NotebookCellData[], metadata?: NotebookDocumentMetadata) {
|
||||
constructor(cells: NotebookCellData[]) {
|
||||
this.cells = cells;
|
||||
this.metadata = metadata ?? new NotebookDocumentMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3094,32 +3039,105 @@ export class NotebookData {
|
||||
export class NotebookCellOutputItem {
|
||||
|
||||
static isNotebookCellOutputItem(obj: unknown): obj is vscode.NotebookCellOutputItem {
|
||||
return obj instanceof NotebookCellOutputItem;
|
||||
if (obj instanceof NotebookCellOutputItem) {
|
||||
return true;
|
||||
}
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return typeof (<vscode.NotebookCellOutputItem>obj).mime === 'string'
|
||||
&& (<vscode.NotebookCellOutputItem>obj).data instanceof Uint8Array;
|
||||
}
|
||||
|
||||
static error(err: Error | { name: string, message?: string, stack?: string }): NotebookCellOutputItem {
|
||||
const obj = {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
};
|
||||
return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error');
|
||||
}
|
||||
|
||||
static stdout(value: string): NotebookCellOutputItem {
|
||||
return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout');
|
||||
}
|
||||
|
||||
static stderr(value: string): NotebookCellOutputItem {
|
||||
return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr');
|
||||
}
|
||||
|
||||
static bytes(value: Uint8Array, mime: string = 'application/octet-stream'): NotebookCellOutputItem {
|
||||
return new NotebookCellOutputItem(value, mime);
|
||||
}
|
||||
|
||||
static #encoder = new TextEncoder();
|
||||
|
||||
static text(value: string, mime: string = 'text/plain'): NotebookCellOutputItem {
|
||||
const bytes = NotebookCellOutputItem.#encoder.encode(String(value));
|
||||
return new NotebookCellOutputItem(bytes, mime);
|
||||
}
|
||||
|
||||
static json(value: any, mime: string = 'application/json'): NotebookCellOutputItem {
|
||||
const rawStr = JSON.stringify(value, undefined, '\t');
|
||||
return NotebookCellOutputItem.text(rawStr, mime);
|
||||
}
|
||||
|
||||
constructor(
|
||||
public data: Uint8Array,
|
||||
public mime: string,
|
||||
public value: unknown, // JSON'able
|
||||
public metadata?: Record<string, any>
|
||||
) {
|
||||
if (isFalsyOrWhitespace(this.mime)) {
|
||||
throw new Error('INVALID mime type, must not be empty or falsy');
|
||||
const mimeNormalized = normalizeMimeType(mime, true);
|
||||
if (!mimeNormalized) {
|
||||
throw new Error('INVALID mime type, must not be empty or falsy: ' + mime);
|
||||
}
|
||||
this.mime = mimeNormalized;
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookCellOutput {
|
||||
|
||||
static isNotebookCellOutput(candidate: any): candidate is vscode.NotebookCellOutput {
|
||||
if (candidate instanceof NotebookCellOutput) {
|
||||
return true;
|
||||
}
|
||||
if (!candidate || typeof candidate !== 'object') {
|
||||
return false;
|
||||
}
|
||||
return typeof (<NotebookCellOutput>candidate).id === 'string' && isArray((<NotebookCellOutput>candidate).items);
|
||||
}
|
||||
|
||||
static ensureUniqueMimeTypes(items: NotebookCellOutputItem[], warn: boolean = false): NotebookCellOutputItem[] {
|
||||
const seen = new Set<string>();
|
||||
const removeIdx = new Set<number>();
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
const normalMime = normalizeMimeType(item.mime);
|
||||
if (!seen.has(normalMime)) {
|
||||
seen.add(normalMime);
|
||||
continue;
|
||||
}
|
||||
// duplicated mime types... first has won
|
||||
removeIdx.add(i);
|
||||
if (warn) {
|
||||
console.warn(`DUPLICATED mime type '${item.mime}' will be dropped`);
|
||||
}
|
||||
}
|
||||
if (removeIdx.size === 0) {
|
||||
return items;
|
||||
}
|
||||
return items.filter((_item, index) => !removeIdx.has(index));
|
||||
}
|
||||
|
||||
id: string;
|
||||
outputs: NotebookCellOutputItem[];
|
||||
items: NotebookCellOutputItem[];
|
||||
metadata?: Record<string, any>;
|
||||
|
||||
constructor(
|
||||
outputs: NotebookCellOutputItem[],
|
||||
items: NotebookCellOutputItem[],
|
||||
idOrMetadata?: string | Record<string, any>,
|
||||
metadata?: Record<string, any>
|
||||
) {
|
||||
this.outputs = outputs;
|
||||
this.items = NotebookCellOutput.ensureUniqueMimeTypes(items, true);
|
||||
if (typeof idOrMetadata === 'string') {
|
||||
this.id = idOrMetadata;
|
||||
this.metadata = metadata;
|
||||
@@ -3131,7 +3149,7 @@ export class NotebookCellOutput {
|
||||
}
|
||||
|
||||
export enum NotebookCellKind {
|
||||
Markdown = 1,
|
||||
Markup = 1,
|
||||
Code = 2
|
||||
}
|
||||
|
||||
@@ -3156,11 +3174,7 @@ export enum NotebookEditorRevealType {
|
||||
export class NotebookCellStatusBarItem {
|
||||
constructor(
|
||||
public text: string,
|
||||
public alignment: NotebookCellStatusBarAlignment,
|
||||
public command?: string | vscode.Command,
|
||||
public tooltip?: string,
|
||||
public priority?: number,
|
||||
public accessibilityInformation?: vscode.AccessibilityInformation) { }
|
||||
public alignment: NotebookCellStatusBarAlignment) { }
|
||||
}
|
||||
|
||||
|
||||
@@ -3169,6 +3183,18 @@ export enum NotebookControllerAffinity {
|
||||
Preferred = 2
|
||||
}
|
||||
|
||||
export class NotebookRendererScript {
|
||||
|
||||
public provides: string[];
|
||||
|
||||
constructor(
|
||||
public uri: vscode.Uri,
|
||||
provides: string | string[] = []
|
||||
) {
|
||||
this.provides = asArray(provides);
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Timeline
|
||||
@@ -3228,6 +3254,25 @@ export class LinkedEditingRanges {
|
||||
}
|
||||
}
|
||||
|
||||
//#region ports
|
||||
export class PortAttributes {
|
||||
private _port: number;
|
||||
private _autoForwardAction: PortAutoForwardAction;
|
||||
constructor(port: number, autoForwardAction: PortAutoForwardAction) {
|
||||
this._port = port;
|
||||
this._autoForwardAction = autoForwardAction;
|
||||
}
|
||||
|
||||
get port(): number {
|
||||
return this._port;
|
||||
}
|
||||
|
||||
get autoForwardAction(): PortAutoForwardAction {
|
||||
return this._autoForwardAction;
|
||||
}
|
||||
}
|
||||
//#endregion ports
|
||||
|
||||
//#region Testing
|
||||
export enum TestResultState {
|
||||
Unset = 0,
|
||||
@@ -3282,7 +3327,7 @@ const rangeComparator = (a: vscode.Range | undefined, b: vscode.Range | undefine
|
||||
|
||||
export class TestItemImpl implements vscode.TestItem<unknown> {
|
||||
public readonly id!: string;
|
||||
public readonly uri!: vscode.Uri;
|
||||
public readonly uri!: vscode.Uri | undefined;
|
||||
public readonly children!: ReadonlyMap<string, TestItemImpl>;
|
||||
public readonly parent!: TestItemImpl | undefined;
|
||||
|
||||
@@ -3296,7 +3341,7 @@ export class TestItemImpl implements vscode.TestItem<unknown> {
|
||||
/** Extension-owned resolve handler */
|
||||
public resolveHandler?: (token: vscode.CancellationToken) => void;
|
||||
|
||||
constructor(id: string, public label: string, uri: vscode.Uri, public data: unknown) {
|
||||
constructor(id: string, public label: string, uri: vscode.Uri | undefined, public data: unknown) {
|
||||
const api = getPrivateApiFor(this);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
@@ -3322,7 +3367,7 @@ export class TestItemImpl implements vscode.TestItem<unknown> {
|
||||
range: testItemPropAccessor(api, 'range', undefined, rangeComparator),
|
||||
description: testItemPropAccessor(api, 'description', undefined, strictEqualComparator),
|
||||
runnable: testItemPropAccessor(api, 'runnable', true, strictEqualComparator),
|
||||
debuggable: testItemPropAccessor(api, 'debuggable', true, strictEqualComparator),
|
||||
debuggable: testItemPropAccessor(api, 'debuggable', false, strictEqualComparator),
|
||||
status: testItemPropAccessor(api, 'status', TestItemStatus.Resolved, strictEqualComparator),
|
||||
error: testItemPropAccessor(api, 'error', undefined, strictEqualComparator),
|
||||
});
|
||||
|
||||
@@ -10,9 +10,9 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
|
||||
import { normalizeVersion, parseVersion } from 'vs/platform/extensions/common/extensionValidator';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { deserializeWebviewMessage } from 'vs/workbench/api/common/extHostWebviewMessaging';
|
||||
import { serializeWebviewMessage, deserializeWebviewMessage } from 'vs/workbench/api/common/extHostWebviewMessaging';
|
||||
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import { asWebviewUri, webviewGenericCspSource, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as extHostProtocol from './extHost.protocol';
|
||||
|
||||
@@ -69,12 +69,11 @@ export class ExtHostWebview implements vscode.Webview {
|
||||
|
||||
public asWebviewUri(resource: vscode.Uri): vscode.Uri {
|
||||
this.#hasCalledAsWebviewUri = true;
|
||||
return asWebviewUri(this.#initData, this.#handle, resource);
|
||||
return asWebviewUri(resource, this.#initData.remote);
|
||||
}
|
||||
|
||||
public get cspSource(): string {
|
||||
return this.#initData.webviewCspSource
|
||||
.replace('{{uuid}}', this.#handle);
|
||||
return webviewGenericCspSource;
|
||||
}
|
||||
|
||||
public get html(): string {
|
||||
@@ -110,7 +109,7 @@ export class ExtHostWebview implements vscode.Webview {
|
||||
if (this.#isDisposed) {
|
||||
return false;
|
||||
}
|
||||
const serialized = serializeMessage(message, { serializeBuffersForPostMessage: this.#serializeBuffersForPostMessage });
|
||||
const serialized = serializeWebviewMessage(message, { serializeBuffersForPostMessage: this.#serializeBuffersForPostMessage });
|
||||
return this.#proxy.$postMessage(this.#handle, serialized.message, ...serialized.buffers);
|
||||
}
|
||||
|
||||
@@ -122,48 +121,14 @@ export class ExtHostWebview implements vscode.Webview {
|
||||
}
|
||||
|
||||
export function shouldSerializeBuffersForPostMessage(extension: IExtensionDescription): boolean {
|
||||
if (!extension.enableProposedApi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const version = normalizeVersion(parseVersion(extension.engines.vscode));
|
||||
return !!version && version.majorBase >= 1 && version.minorBase >= 56;
|
||||
return !!version && version.majorBase >= 1 && version.minorBase >= 57;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function serializeMessage(message: any, options: { serializeBuffersForPostMessage?: boolean }): { message: string, buffers: VSBuffer[] } {
|
||||
if (options.serializeBuffersForPostMessage) {
|
||||
// Extract all ArrayBuffers from the message and replace them with references.
|
||||
const vsBuffers: Array<{ original: ArrayBuffer, vsBuffer: VSBuffer }> = [];
|
||||
|
||||
const replacer = (_key: string, value: any) => {
|
||||
if (value && value instanceof ArrayBuffer) {
|
||||
let index = vsBuffers.findIndex(x => x.original === value);
|
||||
if (index === -1) {
|
||||
const bytes = new Uint8Array(value);
|
||||
const vsBuffer = VSBuffer.wrap(bytes);
|
||||
index = vsBuffers.length;
|
||||
vsBuffers.push({ original: value, vsBuffer });
|
||||
}
|
||||
|
||||
return <extHostProtocol.WebviewMessageArrayBufferReference>{
|
||||
$$vscode_array_buffer_reference$$: true,
|
||||
index,
|
||||
};
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
const serializedMessage = JSON.stringify(message, replacer);
|
||||
return { message: serializedMessage, buffers: vsBuffers.map(x => x.vsBuffer) };
|
||||
} else {
|
||||
return { message: JSON.stringify(message), buffers: [] };
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
|
||||
|
||||
private readonly _webviewProxy: extHostProtocol.MainThreadWebviewsShape;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
@@ -21,9 +21,9 @@ class ArrayBufferSet {
|
||||
|
||||
export function serializeWebviewMessage(
|
||||
message: any,
|
||||
transfer?: readonly ArrayBuffer[]
|
||||
options: { serializeBuffersForPostMessage?: boolean }
|
||||
): { message: string, buffers: VSBuffer[] } {
|
||||
if (transfer) {
|
||||
if (options.serializeBuffersForPostMessage) {
|
||||
// Extract all ArrayBuffers from the message and replace them with references.
|
||||
const arrayBuffers = new ArrayBufferSet();
|
||||
|
||||
|
||||
@@ -61,8 +61,6 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
async asExternalUri(uri: URI, options: IOpenUriOptions): Promise<URI> {
|
||||
if (isFalsyOrWhitespace(uri.scheme)) {
|
||||
return Promise.reject('Invalid scheme - cannot be empty');
|
||||
} else if (!new Set([Schemas.http, Schemas.https]).has(uri.scheme)) {
|
||||
return Promise.reject(`Invalid scheme '${uri.scheme}'`);
|
||||
}
|
||||
|
||||
const result = await this._proxy.$asExternalUri(uri, options);
|
||||
|
||||
@@ -563,8 +563,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
|
||||
}
|
||||
|
||||
requestWorkspaceTrust(options?: vscode.WorkspaceTrustRequestOptions): Promise<boolean | undefined> {
|
||||
const promise = this._proxy.$requestWorkspaceTrust(options);
|
||||
return options?.modal ? promise : Promise.resolve(this._trusted);
|
||||
return this._proxy.$requestWorkspaceTrust(options);
|
||||
}
|
||||
|
||||
$onDidGrantWorkspaceTrust(): void {
|
||||
|
||||
@@ -24,6 +24,7 @@ interface IAPIMenu {
|
||||
readonly description: string;
|
||||
readonly proposed?: boolean; // defaults to false
|
||||
readonly supportsSubmenus?: boolean; // defaults to true
|
||||
readonly deprecationMessage?: string;
|
||||
}
|
||||
|
||||
const apiMenus: IAPIMenu[] = [
|
||||
@@ -137,7 +138,8 @@ const apiMenus: IAPIMenu[] = [
|
||||
id: MenuId.StatusBarWindowIndicatorMenu,
|
||||
description: localize('menus.statusBarWindowIndicator', "The window indicator menu in the status bar"),
|
||||
proposed: true,
|
||||
supportsSubmenus: false
|
||||
supportsSubmenus: false,
|
||||
deprecationMessage: localize('menus.statusBarWindowIndicator.deprecated', "Use menu 'statusBar/remoteIndicator' instead."),
|
||||
},
|
||||
{
|
||||
key: 'statusBar/remoteIndicator',
|
||||
@@ -185,6 +187,12 @@ const apiMenus: IAPIMenu[] = [
|
||||
proposed: true
|
||||
},
|
||||
*/
|
||||
{
|
||||
key: 'notebook/toolbar/right',
|
||||
id: MenuId.NotebookRightToolbar,
|
||||
description: localize('notebook.toolbar.right', "The contributed notebook right toolbar menu"),
|
||||
proposed: true
|
||||
},
|
||||
{
|
||||
key: 'notebook/cell/title',
|
||||
id: MenuId.NotebookCellTitle,
|
||||
@@ -272,8 +280,15 @@ const apiMenus: IAPIMenu[] = [
|
||||
key: 'dataGrid/item/context',
|
||||
id: MenuId.DataGridItemContext,
|
||||
description: locConstants.menusExtensionPointDataGridContext
|
||||
}
|
||||
},
|
||||
// {{SQL CARBON EDIT}} end menu entries
|
||||
{
|
||||
key: 'editor/inlineCompletions/actions',
|
||||
id: MenuId.InlineCompletionsActions,
|
||||
description: localize('inlineCompletions.actions', "The actions shown when hovering on an inline completion"),
|
||||
supportsSubmenus: false,
|
||||
proposed: true
|
||||
},
|
||||
];
|
||||
|
||||
namespace schema {
|
||||
@@ -461,6 +476,7 @@ namespace schema {
|
||||
type: 'object',
|
||||
properties: index(apiMenus, menu => menu.key, menu => ({
|
||||
description: menu.proposed ? `(${localize('proposed', "Proposed API")}) ${menu.description}` : menu.description,
|
||||
deprecationMessage: menu.deprecationMessage,
|
||||
type: 'array',
|
||||
items: menu.supportsSubmenus === false ? menuItem : { oneOf: [menuItem, submenuItem] }
|
||||
})),
|
||||
@@ -482,6 +498,7 @@ namespace schema {
|
||||
export interface IUserFriendlyCommand {
|
||||
command: string;
|
||||
title: string | ILocalizedString;
|
||||
shortTitle?: string | ILocalizedString;
|
||||
enablement?: string;
|
||||
category?: string | ILocalizedString;
|
||||
icon?: IUserFriendlyIcon;
|
||||
@@ -501,6 +518,9 @@ namespace schema {
|
||||
if (!isValidLocalizedString(command.title, collector, 'title')) {
|
||||
return false;
|
||||
}
|
||||
if (command.shortTitle && !isValidLocalizedString(command.shortTitle, collector, 'shortTitle')) {
|
||||
return false;
|
||||
}
|
||||
if (command.enablement && typeof command.enablement !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'precondition'));
|
||||
return false;
|
||||
@@ -554,6 +574,10 @@ namespace schema {
|
||||
description: localize('vscode.extension.contributes.commandType.title', 'Title by which the command is represented in the UI'),
|
||||
type: 'string'
|
||||
},
|
||||
shortTitle: {
|
||||
description: localize('vscode.extension.contributes.commandType.shortTitle', 'Short title by which the command is represented in the UI'),
|
||||
type: 'string'
|
||||
},
|
||||
category: {
|
||||
description: localize('vscode.extension.contributes.commandType.category', '(Optional) Category string by the command is grouped in the UI'),
|
||||
type: 'string'
|
||||
@@ -611,7 +635,7 @@ commandsExtensionPoint.setHandler(extensions => {
|
||||
return;
|
||||
}
|
||||
|
||||
const { icon, enablement, category, title, command } = userFriendlyCommand;
|
||||
const { icon, enablement, category, title, shortTitle, command } = userFriendlyCommand;
|
||||
|
||||
let absoluteIcon: { dark: URI; light?: URI; } | ThemeIcon | undefined;
|
||||
if (icon) {
|
||||
@@ -632,6 +656,7 @@ commandsExtensionPoint.setHandler(extensions => {
|
||||
bucket.push({
|
||||
id: command,
|
||||
title,
|
||||
shortTitle: extension.description.enableProposedApi ? shortTitle : undefined,
|
||||
category,
|
||||
precondition: ContextKeyExpr.deserialize(enablement),
|
||||
icon: absoluteIcon
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface TaskPresentationOptionsDTO {
|
||||
showReuseMessage?: boolean;
|
||||
clear?: boolean;
|
||||
group?: string;
|
||||
close?: boolean;
|
||||
}
|
||||
|
||||
export interface RunOptionsDTO {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITreeDataTransfer, ITreeDataTransferItem } from 'vs/workbench/common/views';
|
||||
|
||||
@@ -3,28 +3,63 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export interface WebviewInitData {
|
||||
readonly isExtensionDevelopmentDebug: boolean;
|
||||
readonly webviewResourceRoot: string;
|
||||
readonly webviewCspSource: string;
|
||||
readonly remote: {
|
||||
readonly isRemote: boolean;
|
||||
readonly authority: string | undefined
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Root from which resources in webviews are loaded.
|
||||
*
|
||||
* This is hardcoded because we never expect to actually hit it. Instead these requests
|
||||
* should always go to a service worker.
|
||||
*/
|
||||
export const webviewResourceBaseHost = 'vscode-webview.net';
|
||||
|
||||
export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
|
||||
|
||||
export const webviewGenericCspSource = `https://*.${webviewResourceBaseHost}`;
|
||||
|
||||
/**
|
||||
* Construct a uri that can load resources inside a webview
|
||||
*
|
||||
* We encode the resource component of the uri so that on the main thread
|
||||
* we know where to load the resource from (remote or truly local):
|
||||
*
|
||||
* ```txt
|
||||
* ${scheme}+${resource-authority}.vscode-resource.vscode-webview.net/${path}
|
||||
* ```
|
||||
*
|
||||
* @param resource Uri of the resource to load.
|
||||
* @param remoteInfo Optional information about the remote that specifies where `resource` should be resolved from.
|
||||
*/
|
||||
export function asWebviewUri(
|
||||
initData: WebviewInitData,
|
||||
uuid: string,
|
||||
resource: vscode.Uri,
|
||||
remoteInfo?: { authority: string | undefined, isRemote: boolean }
|
||||
): vscode.Uri {
|
||||
const uri = initData.webviewResourceRoot
|
||||
// Make sure we preserve the scheme of the resource but convert it into a normal path segment
|
||||
// The scheme is important as we need to know if we are requesting a local or a remote resource.
|
||||
.replace('{{resource}}', resource.scheme + withoutScheme(resource))
|
||||
.replace('{{uuid}}', uuid);
|
||||
return URI.parse(uri);
|
||||
}
|
||||
if (resource.scheme === Schemas.http || resource.scheme === Schemas.https) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
function withoutScheme(resource: vscode.Uri): string {
|
||||
return resource.toString().replace(/^\S+?:/, '');
|
||||
if (remoteInfo && remoteInfo.authority && remoteInfo.isRemote && resource.scheme === Schemas.file) {
|
||||
resource = URI.from({
|
||||
scheme: Schemas.vscodeRemote,
|
||||
authority: remoteInfo.authority,
|
||||
path: resource.path,
|
||||
});
|
||||
}
|
||||
|
||||
return URI.from({
|
||||
scheme: Schemas.https,
|
||||
authority: `${resource.scheme}+${resource.authority}.${webviewRootResourceAuthority}`,
|
||||
path: resource.path,
|
||||
fragment: resource.fragment,
|
||||
query: resource.query,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ExtHostOutputService2 } from 'vs/workbench/api/node/extHostOutputService';
|
||||
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
|
||||
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
|
||||
// import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
|
||||
// import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService'; {{SQL CARBON EDIT}}
|
||||
import { NativeExtHostSearch } from 'vs/workbench/api/node/extHostSearch';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
||||
import { ExtHostTunnelService } from 'vs/workbench/api/node/extHostTunnelService';
|
||||
// import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
// import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; {{SQL CARBON EDIT}}
|
||||
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch';
|
||||
@@ -30,7 +30,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
registerSingleton(IExtHostExtensionService, ExtHostExtensionService);
|
||||
registerSingleton(ILogService, ExtHostLogService);
|
||||
|
||||
// registerSingleton(IExtHostDebugService, ExtHostDebugService);
|
||||
// registerSingleton(IExtHostDebugService, ExtHostDebugService); {{SQL CARBON EDIT}}
|
||||
registerSingleton(IExtHostOutputService, ExtHostOutputService2);
|
||||
registerSingleton(IExtHostSearch, NativeExtHostSearch);
|
||||
registerSingleton(IExtHostTask, ExtHostTask);
|
||||
|
||||
@@ -20,10 +20,11 @@ import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ExtHostDebugServiceBase, ExtHostDebugSession, ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
import { SignService } from 'vs/platform/sign/node/signService';
|
||||
import { hasChildProcesses, prepareCommand, runInExternalTerminal } from 'vs/workbench/contrib/debug/node/terminals';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver';
|
||||
import { createCancelablePromise, firstParallel } from 'vs/base/common/async';
|
||||
import { hasChildProcesses, prepareCommand, runInExternalTerminal } from 'vs/workbench/contrib/debug/node/terminals';
|
||||
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
|
||||
export class ExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
|
||||
@@ -38,9 +39,10 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
@IExtHostExtensionService extensionService: IExtHostExtensionService,
|
||||
@IExtHostDocumentsAndEditors editorsService: IExtHostDocumentsAndEditors,
|
||||
@IExtHostConfiguration configurationService: IExtHostConfiguration,
|
||||
@IExtHostTerminalService private _terminalService: IExtHostTerminalService
|
||||
@IExtHostTerminalService private _terminalService: IExtHostTerminalService,
|
||||
@IExtHostEditorTabs editorTabs: IExtHostEditorTabs
|
||||
) {
|
||||
super(extHostRpcService, workspaceService, extensionService, editorsService, configurationService);
|
||||
super(extHostRpcService, workspaceService, extensionService, editorsService, configurationService, editorTabs);
|
||||
}
|
||||
|
||||
protected override createDebugAdapter(adapter: IAdapterDescriptor, session: ExtHostDebugSession): AbstractDebugAdapter | undefined {
|
||||
@@ -79,11 +81,13 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
}
|
||||
|
||||
const configProvider = await this._configurationService.getConfigProvider();
|
||||
const shell = this._terminalService.getDefaultShell(true, configProvider);
|
||||
const shellArgs = this._terminalService.getDefaultShellArgs(true, configProvider);
|
||||
const shell = this._terminalService.getDefaultShell(true);
|
||||
const shellArgs = this._terminalService.getDefaultShellArgs(true);
|
||||
|
||||
const terminalName = args.title || nls.localize('debug.terminal.title', "Debug Process");
|
||||
|
||||
const shellConfig = JSON.stringify({ shell, shellArgs });
|
||||
let terminal = await this._integratedTerminalInstances.checkout(shellConfig);
|
||||
let terminal = await this._integratedTerminalInstances.checkout(shellConfig, terminalName);
|
||||
|
||||
let cwdForPrepareCommand: string | undefined;
|
||||
let giveShellTimeToInitialize = false;
|
||||
@@ -93,10 +97,13 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
shellPath: shell,
|
||||
shellArgs: shellArgs,
|
||||
cwd: args.cwd,
|
||||
name: args.title || nls.localize('debug.terminal.title', "debuggee"),
|
||||
name: terminalName,
|
||||
};
|
||||
giveShellTimeToInitialize = true;
|
||||
terminal = this._terminalService.createTerminalFromOptions(options, true);
|
||||
terminal = this._terminalService.createTerminalFromOptions(options, {
|
||||
isFeatureTerminal: true,
|
||||
useShellEnvironment: true
|
||||
});
|
||||
this._integratedTerminalInstances.insert(terminal, shellConfig);
|
||||
|
||||
} else {
|
||||
@@ -139,14 +146,13 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase {
|
||||
return shellProcessId;
|
||||
|
||||
} else if (args.kind === 'external') {
|
||||
|
||||
return runInExternalTerminal(args, await this._configurationService.getConfigProvider());
|
||||
}
|
||||
return super.$runInTerminal(args, sessionId);
|
||||
}
|
||||
|
||||
protected createVariableResolver(folders: vscode.WorkspaceFolder[], editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider): AbstractVariableResolverService {
|
||||
return new ExtHostVariableResolverService(folders, editorService, configurationService, this._workspaceService);
|
||||
return new ExtHostVariableResolverService(folders, editorService, configurationService, this._editorTabs, this._workspaceService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,9 +164,15 @@ class DebugTerminalCollection {
|
||||
|
||||
private _terminalInstances = new Map<vscode.Terminal, { lastUsedAt: number, config: string }>();
|
||||
|
||||
public async checkout(config: string) {
|
||||
public async checkout(config: string, name: string) {
|
||||
const entries = [...this._terminalInstances.entries()];
|
||||
const promises = entries.map(([terminal, termInfo]) => createCancelablePromise(async ct => {
|
||||
|
||||
// Only allow terminals that match the title. See #123189
|
||||
if (terminal.name !== name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (termInfo.lastUsedAt !== -1 && await hasChildProcesses(await terminal.processId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,26 +8,27 @@ import type * as vscode from 'vscode';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { SymlinkSupport } from 'vs/base/node/pfs';
|
||||
import { promises } from 'fs';
|
||||
import { Promises, SymlinkSupport } from 'vs/base/node/pfs';
|
||||
import { AbstractExtHostOutputChannel, ExtHostPushOutputChannel, ExtHostOutputService, LazyOutputChannel } from 'vs/workbench/api/common/extHostOutput';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { createRotatingLogger } from 'vs/platform/log/node/spdlogLog';
|
||||
import { RotatingLogger } from 'spdlog';
|
||||
import { Logger } from 'spdlog';
|
||||
import { ByteSize } from 'vs/platform/files/common/files';
|
||||
|
||||
class OutputAppender {
|
||||
|
||||
private appender: RotatingLogger;
|
||||
static async create(name: string, file: string): Promise<OutputAppender> {
|
||||
const appender = await createRotatingLogger(name, file, 30 * ByteSize.MB, 1);
|
||||
appender.clearFormatters();
|
||||
|
||||
constructor(name: string, readonly file: string) {
|
||||
this.appender = createRotatingLogger(name, file, 30 * ByteSize.MB, 1);
|
||||
this.appender.clearFormatters();
|
||||
return new OutputAppender(name, file, appender);
|
||||
}
|
||||
|
||||
private constructor(readonly name: string, readonly file: string, private readonly appender: Logger) { }
|
||||
|
||||
append(content: string): void {
|
||||
this.appender.critical(content);
|
||||
}
|
||||
@@ -38,7 +39,7 @@ class OutputAppender {
|
||||
}
|
||||
|
||||
|
||||
export class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {
|
||||
class ExtHostOutputChannelBackedByFile extends AbstractExtHostOutputChannel {
|
||||
|
||||
private _appender: OutputAppender;
|
||||
|
||||
@@ -109,11 +110,11 @@ export class ExtHostOutputService2 extends ExtHostOutputService {
|
||||
const outputDirPath = join(this._logsLocation.fsPath, `output_logging_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`);
|
||||
const exists = await SymlinkSupport.existsDirectory(outputDirPath);
|
||||
if (!exists) {
|
||||
await promises.mkdir(outputDirPath, { recursive: true });
|
||||
await Promises.mkdir(outputDirPath, { recursive: true });
|
||||
}
|
||||
const fileName = `${this._namePool++}-${name.replace(/[\\/:\*\?"<>\|]/g, '')}`;
|
||||
const file = URI.file(join(outputDirPath, `${fileName}.log`));
|
||||
const appender = new OutputAppender(fileName, file.fsPath);
|
||||
const appender = await OutputAppender.create(fileName, file.fsPath);
|
||||
return new ExtHostOutputChannelBackedByFile(name, appender, this._proxy);
|
||||
} catch (error) {
|
||||
// Do not crash if logger cannot be created
|
||||
|
||||
@@ -14,6 +14,7 @@ import * as tasks from '../common/shared/tasks';
|
||||
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
@@ -22,7 +23,7 @@ import { ExtHostTaskBase, TaskHandleDTO, TaskDTO, CustomExecutionDTO, HandlerDat
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
|
||||
export class ExtHostTask extends ExtHostTaskBase {
|
||||
private _variableResolver: ExtHostVariableResolverService | undefined;
|
||||
@@ -35,7 +36,8 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
@IExtHostConfiguration configurationService: IExtHostConfiguration,
|
||||
@IExtHostTerminalService extHostTerminalService: IExtHostTerminalService,
|
||||
@ILogService logService: ILogService,
|
||||
@IExtHostApiDeprecationService deprecationService: IExtHostApiDeprecationService
|
||||
@IExtHostApiDeprecationService deprecationService: IExtHostApiDeprecationService,
|
||||
@IExtHostEditorTabs private readonly editorTabs: IExtHostEditorTabs
|
||||
) {
|
||||
super(extHostRpc, initData, workspaceService, editorService, configurationService, extHostTerminalService, logService, deprecationService);
|
||||
if (initData.remote.isRemote && initData.remote.authority) {
|
||||
@@ -124,11 +126,10 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
return resolvedTaskDTO;
|
||||
}
|
||||
|
||||
|
||||
private async getVariableResolver(workspaceFolders: vscode.WorkspaceFolder[]): Promise<ExtHostVariableResolverService> {
|
||||
if (this._variableResolver === undefined) {
|
||||
const configProvider = await this._configurationService.getConfigProvider();
|
||||
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider, this.workspaceService);
|
||||
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders, this._editorService, configProvider, this.editorTabs, this.workspaceService);
|
||||
}
|
||||
return this._variableResolver;
|
||||
}
|
||||
@@ -173,10 +174,6 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
return result;
|
||||
}
|
||||
|
||||
public $getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }> {
|
||||
return this._terminalService.$getDefaultShellAndArgs(true);
|
||||
}
|
||||
|
||||
public async $jsonTasksSupported(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,143 +3,27 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { getSystemShell, getSystemShellSync } from 'vs/base/node/shell';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { SafeConfigProvider } from 'vs/platform/terminal/common/terminal';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfigProvider, ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { BaseExtHostTerminalService, ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ITerminalProfile } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
import { detectAvailableProfiles } from 'vs/workbench/contrib/terminal/node/terminalProfiles';
|
||||
import { BaseExtHostTerminalService, ExtHostTerminal, ITerminalInternalOptions } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
||||
|
||||
private _variableResolver: ExtHostVariableResolverService | undefined;
|
||||
private _variableResolverPromise: Promise<ExtHostVariableResolverService>;
|
||||
private _lastActiveWorkspace: IWorkspaceFolder | undefined;
|
||||
|
||||
private _defaultShell: string | undefined;
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostConfiguration private _extHostConfiguration: ExtHostConfiguration,
|
||||
@IExtHostWorkspace private _extHostWorkspace: ExtHostWorkspace,
|
||||
@IExtHostDocumentsAndEditors private _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
@ILogService private _logService: ILogService
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService
|
||||
) {
|
||||
super(true, extHostRpc);
|
||||
|
||||
// Getting the SystemShell is an async operation, however, the ExtHost terminal service is mostly synchronous
|
||||
// and the API `vscode.env.shell` is also synchronous. The default shell _should_ be set when extensions are
|
||||
// starting up but if not, we run getSystemShellSync below which gets a sane default.
|
||||
getSystemShell(platform.OS, process.env as platform.IProcessEnvironment).then(s => this._defaultShell = s);
|
||||
|
||||
this._updateLastActiveWorkspace();
|
||||
this._variableResolverPromise = this._updateVariableResolver();
|
||||
this._registerListeners();
|
||||
}
|
||||
|
||||
public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), { name, shellPath, shellArgs }, name);
|
||||
this._terminals.push(terminal);
|
||||
terminal.create(shellPath, shellArgs);
|
||||
return terminal.value;
|
||||
return this.createTerminalFromOptions({ name, shellPath, shellArgs });
|
||||
}
|
||||
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions, isFeatureTerminal?: boolean): vscode.Terminal {
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
|
||||
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name);
|
||||
this._terminals.push(terminal);
|
||||
terminal.create(
|
||||
withNullAsUndefined(options.shellPath),
|
||||
withNullAsUndefined(options.shellArgs),
|
||||
withNullAsUndefined(options.cwd),
|
||||
withNullAsUndefined(options.env),
|
||||
withNullAsUndefined(options.icon),
|
||||
withNullAsUndefined(options.message),
|
||||
/*options.waitOnExit*/ undefined,
|
||||
withNullAsUndefined(options.strictEnv),
|
||||
withNullAsUndefined(options.hideFromUser),
|
||||
withNullAsUndefined(isFeatureTerminal),
|
||||
true
|
||||
);
|
||||
terminal.create(options, internalOptions);
|
||||
return terminal.value;
|
||||
}
|
||||
|
||||
public getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string {
|
||||
return terminalEnvironment.getDefaultShell(
|
||||
this._buildSafeConfigProvider(configProvider),
|
||||
this._defaultShell ?? getSystemShellSync(platform.OS, process.env as platform.IProcessEnvironment),
|
||||
process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'),
|
||||
process.env.windir,
|
||||
terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, process.env, this._variableResolver),
|
||||
this._logService,
|
||||
useAutomationShell
|
||||
);
|
||||
}
|
||||
|
||||
public getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string {
|
||||
return terminalEnvironment.getDefaultShellArgs(
|
||||
this._buildSafeConfigProvider(configProvider),
|
||||
useAutomationShell,
|
||||
terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, process.env, this._variableResolver),
|
||||
this._logService
|
||||
);
|
||||
}
|
||||
|
||||
private _registerListeners(): void {
|
||||
this._extHostDocumentsAndEditors.onDidChangeActiveTextEditor(() => this._updateLastActiveWorkspace());
|
||||
this._extHostWorkspace.onDidChangeWorkspace(() => {
|
||||
this._variableResolverPromise = this._updateVariableResolver();
|
||||
});
|
||||
}
|
||||
|
||||
private _updateLastActiveWorkspace(): void {
|
||||
const activeEditor = this._extHostDocumentsAndEditors.activeEditor();
|
||||
if (activeEditor) {
|
||||
this._lastActiveWorkspace = this._extHostWorkspace.getWorkspaceFolder(activeEditor.document.uri) as IWorkspaceFolder;
|
||||
}
|
||||
}
|
||||
|
||||
private async _updateVariableResolver(): Promise<ExtHostVariableResolverService> {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
const workspaceFolders = await this._extHostWorkspace.getWorkspaceFolders2();
|
||||
this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider);
|
||||
return this._variableResolver;
|
||||
}
|
||||
|
||||
public async $getAvailableProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]> {
|
||||
const safeConfigProvider = this._buildSafeConfigProvider(await this._extHostConfiguration.getConfigProvider());
|
||||
return detectAvailableProfiles(configuredProfilesOnly, safeConfigProvider, undefined, this._logService, await this._variableResolverPromise, this._lastActiveWorkspace);
|
||||
}
|
||||
|
||||
public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto> {
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
return {
|
||||
shell: this.getDefaultShell(useAutomationShell, configProvider),
|
||||
args: this.getDefaultShellArgs(useAutomationShell, configProvider)
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Remove when workspace trust is enabled
|
||||
private _buildSafeConfigProvider(configProvider: ExtHostConfigProvider): SafeConfigProvider {
|
||||
const config = configProvider.getConfiguration();
|
||||
return (key: string) => {
|
||||
const isWorkspaceConfigAllowed = config.get('terminal.integrated.allowWorkspaceConfiguration');
|
||||
if (isWorkspaceConfigAllowed) {
|
||||
return config.get(key) as any;
|
||||
}
|
||||
const inspected = config.inspect(key);
|
||||
return inspected?.globalValue || inspected?.defaultValue;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitData
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { exec } from 'child_process';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as fs from 'fs';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
@@ -365,8 +364,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
let tcp: string = '';
|
||||
let tcp6: string = '';
|
||||
try {
|
||||
tcp = await fs.promises.readFile('/proc/net/tcp', 'utf8');
|
||||
tcp6 = await fs.promises.readFile('/proc/net/tcp6', 'utf8');
|
||||
tcp = await pfs.Promises.readFile('/proc/net/tcp', 'utf8');
|
||||
tcp6 = await pfs.Promises.readFile('/proc/net/tcp6', 'utf8');
|
||||
} catch (e) {
|
||||
// File reading error. No additional handling needed.
|
||||
}
|
||||
@@ -379,7 +378,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
}));
|
||||
const socketMap = getSockets(procSockets);
|
||||
|
||||
const procChildren = await pfs.readdir('/proc');
|
||||
const procChildren = await pfs.Promises.readdir('/proc');
|
||||
const processes: {
|
||||
pid: number, cwd: string, cmd: string
|
||||
}[] = [];
|
||||
@@ -387,10 +386,10 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
try {
|
||||
const pid: number = Number(childName);
|
||||
const childUri = resources.joinPath(URI.file('/proc'), childName);
|
||||
const childStat = await fs.promises.stat(childUri.fsPath);
|
||||
const childStat = await pfs.Promises.stat(childUri.fsPath);
|
||||
if (childStat.isDirectory() && !isNaN(pid)) {
|
||||
const cwd = await fs.promises.readlink(resources.joinPath(childUri, 'cwd').fsPath);
|
||||
const cmd = await fs.promises.readFile(resources.joinPath(childUri, 'cmdline').fsPath, 'utf8');
|
||||
const cwd = await pfs.Promises.readlink(resources.joinPath(childUri, 'cwd').fsPath);
|
||||
const cmd = await pfs.Promises.readFile(resources.joinPath(childUri, 'cmdline').fsPath, 'utf8');
|
||||
processes.push({ pid, cwd, cmd });
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user