mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 09:35:39 -05:00
Merge from vscode fcf3346a8e9f5ee1e00674461d9e2c2292a14ee3 (#12295)
* Merge from vscode fcf3346a8e9f5ee1e00674461d9e2c2292a14ee3 * Fix test build break * Update distro * Fix build errors * Update distro * Update REH build file * Update build task names for REL * Fix product build yaml * Fix product REH task name * Fix type in task name * Update linux build step * Update windows build tasks * Turn off server publish * Disable REH * Fix typo * Bump distro * Update vscode tests * Bump distro * Fix type in disto * Bump distro * Turn off docker build * Remove docker step from release Co-authored-by: ADS Merger <andresse@microsoft.com> Co-authored-by: Karl Burtram <karlb@microsoft.com>
This commit is contained in:
@@ -15,6 +15,7 @@ import { TokenClassificationExtensionPoints } from 'vs/workbench/services/themes
|
||||
import { LanguageConfigurationFileHandler } from 'vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint';
|
||||
|
||||
// --- mainThread participants
|
||||
import './mainThreadBulkEdits';
|
||||
import './mainThreadCodeInsets';
|
||||
import './mainThreadClipboard';
|
||||
import './mainThreadCommands';
|
||||
|
||||
44
src/vs/workbench/api/browser/mainThreadBulkEdits.ts
Normal file
44
src/vs/workbench/api/browser/mainThreadBulkEdits.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IBulkEditService, ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { IExtHostContext, IWorkspaceEditDto, WorkspaceEditType, MainThreadBulkEditsShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
|
||||
function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] {
|
||||
if (!data?.edits) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: ResourceEdit[] = [];
|
||||
for (let edit of revive<IWorkspaceEditDto>(data).edits) {
|
||||
if (edit._type === WorkspaceEditType.File) {
|
||||
result.push(new ResourceFileEdit(edit.oldUri, edit.newUri, edit.options, edit.metadata));
|
||||
} else if (edit._type === WorkspaceEditType.Text) {
|
||||
result.push(new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata));
|
||||
} else if (edit._type === WorkspaceEditType.Cell) {
|
||||
result.push(new ResourceNotebookCellEdit(edit.resource, edit.edit, edit.notebookVersionId, edit.metadata));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadBulkEdits)
|
||||
export class MainThreadBulkEdits implements MainThreadBulkEditsShape {
|
||||
|
||||
constructor(
|
||||
_extHostContext: IExtHostContext,
|
||||
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||
) { }
|
||||
|
||||
dispose(): void { }
|
||||
|
||||
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise<boolean> {
|
||||
const edits = reviveWorkspaceEditDto2(dto);
|
||||
return this._bulkEditService.apply(edits).then(() => true, _err => false);
|
||||
}
|
||||
}
|
||||
@@ -29,12 +29,13 @@ import { CustomDocumentBackupData } from 'vs/workbench/contrib/customEditor/brow
|
||||
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
import { CustomTextEditorModel } from 'vs/workbench/contrib/customEditor/common/customTextEditorModel';
|
||||
import { WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
|
||||
import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
|
||||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
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 { IWorkingCopy, IWorkingCopyBackup, IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
|
||||
@@ -153,7 +154,7 @@ export class MainThreadCustomEditors extends Disposable implements extHostProtoc
|
||||
return;
|
||||
}
|
||||
|
||||
webviewInput.webview.onDispose(() => {
|
||||
webviewInput.webview.onDidDispose(() => {
|
||||
// If the model is still dirty, make sure we have time to save it
|
||||
if (modelRef.object.isDirty()) {
|
||||
const sub = modelRef.object.onDidChangeDirty(() => {
|
||||
@@ -314,6 +315,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
@IUndoRedoService private readonly _undoService: IUndoRedoService,
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@IWorkingCopyService workingCopyService: IWorkingCopyService,
|
||||
@IPathService private readonly _pathService: IPathService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -535,7 +537,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
|
||||
}
|
||||
|
||||
const remoteAuthority = this._environmentService.configuration.remoteAuthority;
|
||||
const localResource = toLocalResource(this._editorResource, remoteAuthority);
|
||||
const localResource = toLocalResource(this._editorResource, remoteAuthority, this._pathService.defaultUriScheme);
|
||||
|
||||
return this._fileDialogService.pickFileToSave(localResource, options?.availableFileSystems);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { toLocalResource, extUri, IExtUri } from 'vs/base/common/resources';
|
||||
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
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';
|
||||
|
||||
export class BoundModelReferenceCollection {
|
||||
|
||||
@@ -126,7 +127,8 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
@ITextModelService textModelResolverService: ITextModelService,
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService,
|
||||
@IPathService private readonly _pathService: IPathService
|
||||
) {
|
||||
super();
|
||||
this._modelService = modelService;
|
||||
@@ -271,7 +273,7 @@ export class MainThreadDocuments extends Disposable implements MainThreadDocumen
|
||||
}
|
||||
|
||||
private _handleUntitledScheme(uri: URI): Promise<URI> {
|
||||
const asLocalUri = toLocalResource(uri, this._environmentService.configuration.remoteAuthority);
|
||||
const asLocalUri = toLocalResource(uri, this._environmentService.configuration.remoteAuthority, this._pathService.defaultUriScheme);
|
||||
return this._fileService.resolve(asLocalUri).then(stats => {
|
||||
// don't create a new file ontop of an existing file
|
||||
return Promise.reject(new Error('file already exists'));
|
||||
|
||||
@@ -30,6 +30,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
|
||||
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
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';
|
||||
|
||||
namespace delta {
|
||||
|
||||
@@ -334,10 +335,11 @@ export class MainThreadDocumentsAndEditors {
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
@IClipboardService private readonly _clipboardService: IClipboardService,
|
||||
@IPathService pathService: IPathService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentsAndEditors);
|
||||
|
||||
this._mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(this, extHostContext, this._modelService, this._textFileService, fileService, textModelResolverService, environmentService, uriIdentityService, workingCopyFileService));
|
||||
this._mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(this, extHostContext, this._modelService, this._textFileService, fileService, textModelResolverService, environmentService, uriIdentityService, workingCopyFileService, pathService));
|
||||
extHostContext.set(MainContext.MainThreadDocuments, this._mainThreadDocuments);
|
||||
|
||||
const mainThreadTextEditors = this._toDispose.add(new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._editorService, this._editorGroupService));
|
||||
|
||||
@@ -44,7 +44,7 @@ function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceE
|
||||
} else if (edit._type === WorkspaceEditType.Text) {
|
||||
result.push(new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata));
|
||||
} else if (edit._type === WorkspaceEditType.Cell) {
|
||||
result.push(new ResourceNotebookCellEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata));
|
||||
result.push(new ResourceNotebookCellEdit(edit.resource, edit.edit, edit.notebookVersionId, edit.metadata));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
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 { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
@@ -16,15 +16,22 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
|
||||
private readonly _proxy: ExtHostFileSystemShape;
|
||||
private readonly _fileProvider = new Map<number, RemoteFileSystemProvider>();
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystem);
|
||||
|
||||
const infoProxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemInfo);
|
||||
|
||||
this._disposables.add(_fileService.onDidChangeFileSystemProviderRegistrations(e => infoProxy.$acceptProviderInfos(e.scheme, e.provider?.capabilities ?? null)));
|
||||
this._disposables.add(_fileService.onDidChangeFileSystemProviderCapabilities(e => infoProxy.$acceptProviderInfos(e.scheme, e.provider.capabilities)));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.dispose();
|
||||
dispose(this._fileProvider.values());
|
||||
this._fileProvider.clear();
|
||||
}
|
||||
@@ -34,7 +41,7 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
|
||||
}
|
||||
|
||||
$unregisterProvider(handle: number): void {
|
||||
dispose(this._fileProvider.get(handle));
|
||||
this._fileProvider.get(handle)?.dispose();
|
||||
this._fileProvider.delete(handle);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
|
||||
}
|
||||
}
|
||||
|
||||
private _showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[], extension: IExtensionDescription | undefined): Promise<number> {
|
||||
private _showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[], extension: IExtensionDescription | undefined): Promise<number | undefined> {
|
||||
|
||||
return new Promise<number>(resolve => {
|
||||
return new Promise<number | undefined>(resolve => {
|
||||
|
||||
const primaryActions: MessageItemAction[] = [];
|
||||
|
||||
|
||||
@@ -7,18 +7,22 @@ import * as DOM from 'vs/base/browser/dom';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { combinedDisposable, Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, INotebookDocumentFilter, NotebookCellMetadata, NotebookCellOutputsSplice, NotebookDocumentMetadata, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, IMainCellDto, INotebookDocumentFilter, NotebookCellOutputsSplice, NotebookCellsChangeType, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol';
|
||||
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, INotebookModelAddedData, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol';
|
||||
|
||||
class DocumentAndEditorState {
|
||||
static ofSets<T>(before: Set<T>, after: Set<T>): { removed: T[], added: T[] } {
|
||||
@@ -58,7 +62,7 @@ class DocumentAndEditorState {
|
||||
const apiEditors = [];
|
||||
for (let id in after.textEditors) {
|
||||
const editor = after.textEditors.get(id)!;
|
||||
apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.textModel!.selections, visibleRanges: editor.visibleRanges });
|
||||
apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.getSelectionHandles(), visibleRanges: editor.visibleRanges });
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -72,7 +76,7 @@ class DocumentAndEditorState {
|
||||
const addedAPIEditors = editorDelta.added.map(add => ({
|
||||
id: add.getId(),
|
||||
documentUri: add.uri!,
|
||||
selections: add.textModel!.selections || [],
|
||||
selections: add.getSelectionHandles(),
|
||||
visibleRanges: add.visibleRanges
|
||||
}));
|
||||
|
||||
@@ -84,10 +88,9 @@ class DocumentAndEditorState {
|
||||
const visibleEditorDelta = DocumentAndEditorState.ofMaps(before.visibleEditors, after.visibleEditors);
|
||||
|
||||
return {
|
||||
addedDocuments: documentDelta.added.map(e => {
|
||||
addedDocuments: documentDelta.added.map((e: NotebookTextModel): INotebookModelAddedData => {
|
||||
return {
|
||||
viewType: e.viewType,
|
||||
handle: e.handle,
|
||||
uri: e.uri,
|
||||
metadata: e.metadata,
|
||||
versionId: e.versionId,
|
||||
@@ -129,13 +132,13 @@ class DocumentAndEditorState {
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadNotebook)
|
||||
export class MainThreadNotebooks extends Disposable implements MainThreadNotebookShape {
|
||||
private readonly _notebookProviders = new Map<string, IMainNotebookController>();
|
||||
private readonly _notebookProviders = new Map<string, { controller: IMainNotebookController, disposable: IDisposable }>();
|
||||
private readonly _notebookKernelProviders = new Map<number, { extension: NotebookExtensionDescription, emitter: Emitter<URI | undefined>, provider: IDisposable }>();
|
||||
private readonly _proxy: ExtHostNotebookShape;
|
||||
private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
|
||||
private _currentState?: DocumentAndEditorState;
|
||||
private _editorEventListenersMapping: Map<string, DisposableStore> = new Map();
|
||||
private _documentEventListenersMapping: Map<string, DisposableStore> = new Map();
|
||||
private _documentEventListenersMapping: ResourceMap<DisposableStore> = new ResourceMap();
|
||||
private readonly _cellStatusBarEntries: Map<number, IDisposable> = new Map();
|
||||
|
||||
constructor(
|
||||
@@ -145,29 +148,21 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@INotebookCellStatusBarService private readonly cellStatusBarService: INotebookCellStatusBarService
|
||||
@INotebookCellStatusBarService private readonly cellStatusBarService: INotebookCellStatusBarService,
|
||||
@IWorkingCopyService private readonly _workingCopyService: IWorkingCopyService,
|
||||
) {
|
||||
super();
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook);
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
async $tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[]): Promise<boolean> {
|
||||
async $tryApplyEdits(_viewType: string, resource: UriComponents, modelVersionId: number, cellEdits: ICellEditOperation[]): Promise<boolean> {
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
if (textModel) {
|
||||
this._notebookService.transformEditsOutputs(textModel, edits);
|
||||
return textModel.applyEdit(modelVersionId, edits, true);
|
||||
if (!textModel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async removeNotebookTextModel(uri: URI): Promise<void> {
|
||||
// TODO@rebornix, remove cell should use emitDelta as well to ensure document/editor events are sent together
|
||||
this._proxy.$acceptDocumentAndEditorsDelta({ removedDocuments: [uri] });
|
||||
let textModelDisposableStore = this._documentEventListenersMapping.get(uri.toString());
|
||||
textModelDisposableStore?.dispose();
|
||||
this._documentEventListenersMapping.delete(URI.from(uri).toString());
|
||||
this._notebookService.transformEditsOutputs(textModel, cellEdits);
|
||||
return textModel.applyEdits(modelVersionId, cellEdits, true, undefined, () => undefined);
|
||||
}
|
||||
|
||||
private _isDeltaEmpty(delta: INotebookDocumentsAndEditorsDelta) {
|
||||
@@ -231,7 +226,12 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
if (!this._editorEventListenersMapping.has(editor.getId())) {
|
||||
const disposableStore = new DisposableStore();
|
||||
disposableStore.add(editor.onDidChangeVisibleRanges(() => {
|
||||
this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: { ranges: editor.visibleRanges } });
|
||||
this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: { ranges: editor.visibleRanges }, selections: null });
|
||||
}));
|
||||
|
||||
disposableStore.add(editor.onDidChangeSelection(() => {
|
||||
const selectionHandles = editor.getSelectionHandles();
|
||||
this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: null, selections: { selections: selectionHandles } });
|
||||
}));
|
||||
|
||||
this._editorEventListenersMapping.set(editor.getId(), disposableStore);
|
||||
@@ -256,40 +256,79 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
notebookEditorAddedHandler(editor);
|
||||
});
|
||||
|
||||
const notebookDocumentAddedHandler = (doc: URI) => {
|
||||
if (!this._editorEventListenersMapping.has(doc.toString())) {
|
||||
const disposableStore = new DisposableStore();
|
||||
const textModel = this._notebookService.getNotebookTextModel(doc);
|
||||
disposableStore.add(textModel!.onDidModelChangeProxy(e => {
|
||||
this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty);
|
||||
this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: { selections: textModel!.selections }, metadata: null });
|
||||
}));
|
||||
disposableStore.add(textModel!.onDidSelectionChange(e => {
|
||||
const selectionsChange = e ? { selections: e } : null;
|
||||
this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: selectionsChange, metadata: null });
|
||||
}));
|
||||
const cellToDto = (cell: NotebookCellTextModel): IMainCellDto => {
|
||||
return {
|
||||
handle: cell.handle,
|
||||
uri: cell.uri,
|
||||
source: cell.textBuffer.getLinesContent(),
|
||||
eol: cell.textBuffer.getEOL(),
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
outputs: cell.outputs,
|
||||
metadata: cell.metadata
|
||||
};
|
||||
};
|
||||
|
||||
this._editorEventListenersMapping.set(textModel!.uri.toString(), disposableStore);
|
||||
|
||||
const notebookDocumentAddedHandler = (textModel: NotebookTextModel) => {
|
||||
if (!this._documentEventListenersMapping.has(textModel.uri)) {
|
||||
const disposableStore = new DisposableStore();
|
||||
disposableStore.add(textModel!.onDidChangeContent(event => {
|
||||
const dto = event.rawEvents.map(e => {
|
||||
const data =
|
||||
e.kind === NotebookCellsChangeType.ModelChange || e.kind === NotebookCellsChangeType.Initialize
|
||||
? {
|
||||
kind: e.kind,
|
||||
versionId: event.versionId,
|
||||
changes: e.changes.map(diff => [diff[0], diff[1], diff[2].map(cell => cellToDto(cell as NotebookCellTextModel))] as [number, number, IMainCellDto[]])
|
||||
}
|
||||
: (
|
||||
e.kind === NotebookCellsChangeType.Move
|
||||
? {
|
||||
kind: e.kind,
|
||||
index: e.index,
|
||||
length: e.length,
|
||||
newIdx: e.newIdx,
|
||||
versionId: event.versionId,
|
||||
cells: e.cells.map(cell => cellToDto(cell as NotebookCellTextModel))
|
||||
}
|
||||
: e
|
||||
);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
/**
|
||||
* TODO@rebornix, @jrieken
|
||||
* When a document is modified, it will trigger onDidChangeContent events.
|
||||
* The first event listener is this one, which doesn't know if the text model is dirty or not. It can ask `workingCopyService` but get the wrong result
|
||||
* The second event listener is `NotebookEditorModel`, which will then set `isDirty` to `true`.
|
||||
* Since `e.transient` decides if the model should be dirty or not, we will use the same logic here.
|
||||
*/
|
||||
const hasNonTransientEvent = event.rawEvents.find(e => !e.transient);
|
||||
this._proxy.$acceptModelChanged(textModel.uri, {
|
||||
rawEvents: dto,
|
||||
versionId: event.versionId
|
||||
}, !!hasNonTransientEvent);
|
||||
|
||||
const hasDocumentMetadataChangeEvent = event.rawEvents.find(e => e.kind === NotebookCellsChangeType.ChangeDocumentMetadata);
|
||||
if (!!hasDocumentMetadataChangeEvent) {
|
||||
this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { metadata: textModel.metadata });
|
||||
}
|
||||
}));
|
||||
this._documentEventListenersMapping.set(textModel!.uri, disposableStore);
|
||||
}
|
||||
};
|
||||
|
||||
this._register(this._notebookService.onNotebookDocumentAdd((documents) => {
|
||||
documents.forEach(doc => {
|
||||
notebookDocumentAddedHandler(doc);
|
||||
});
|
||||
this._notebookService.listNotebookDocuments().forEach(notebookDocumentAddedHandler);
|
||||
this._register(this._notebookService.onDidAddNotebookDocument(document => {
|
||||
notebookDocumentAddedHandler(document);
|
||||
this._updateState();
|
||||
}));
|
||||
|
||||
this._notebookService.listNotebookDocuments().forEach((doc) => {
|
||||
notebookDocumentAddedHandler(doc.uri);
|
||||
});
|
||||
|
||||
this._register(this._notebookService.onNotebookDocumentRemove((documents) => {
|
||||
documents.forEach(doc => {
|
||||
this._documentEventListenersMapping.get(doc.toString())?.dispose();
|
||||
this._documentEventListenersMapping.delete(doc.toString());
|
||||
});
|
||||
|
||||
this._register(this._notebookService.onDidRemoveNotebookDocument(uri => {
|
||||
this._documentEventListenersMapping.get(uri)?.dispose();
|
||||
this._documentEventListenersMapping.delete(uri);
|
||||
this._updateState();
|
||||
}));
|
||||
|
||||
@@ -404,16 +443,12 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
// }
|
||||
}
|
||||
|
||||
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void> {
|
||||
async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void> {
|
||||
const controller: IMainNotebookController = {
|
||||
supportBackup: _supportBackup,
|
||||
options: options,
|
||||
supportBackup,
|
||||
options,
|
||||
reloadNotebook: async (mainthreadTextModel: NotebookTextModel) => {
|
||||
const data = await this._proxy.$resolveNotebookData(_viewType, mainthreadTextModel.uri);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await this._proxy.$resolveNotebookData(viewType, mainthreadTextModel.uri);
|
||||
mainthreadTextModel.updateLanguages(data.languages);
|
||||
mainthreadTextModel.metadata = data.metadata;
|
||||
mainthreadTextModel.transientOptions = options;
|
||||
@@ -425,31 +460,17 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
this._notebookService.transformEditsOutputs(mainthreadTextModel, edits);
|
||||
await new Promise(resolve => {
|
||||
DOM.scheduleAtNextAnimationFrame(() => {
|
||||
const ret = mainthreadTextModel!.applyEdit(mainthreadTextModel!.versionId, edits, true);
|
||||
const ret = mainthreadTextModel!.applyEdits(mainthreadTextModel!.versionId, edits, true, undefined, () => undefined);
|
||||
resolve(ret);
|
||||
});
|
||||
});
|
||||
},
|
||||
createNotebook: async (textModel: NotebookTextModel, backupId?: string) => {
|
||||
// open notebook document
|
||||
const data = await this._proxy.$resolveNotebookData(textModel.viewType, textModel.uri, backupId);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
textModel.updateLanguages(data.languages);
|
||||
textModel.metadata = data.metadata;
|
||||
textModel.transientOptions = options;
|
||||
|
||||
if (data.cells.length) {
|
||||
textModel.initialize(data!.cells);
|
||||
} else {
|
||||
const mainCell = textModel.createCellTextModel('', textModel.resolvedLanguages.length ? textModel.resolvedLanguages[0] : '', CellKind.Code, [], undefined);
|
||||
textModel.insertTemplateCell(mainCell);
|
||||
}
|
||||
|
||||
this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { selections: null, metadata: textModel.metadata });
|
||||
return;
|
||||
resolveNotebookDocument: async (viewType: string, uri: URI, backupId?: string) => {
|
||||
const data = await this._proxy.$resolveNotebookData(viewType, uri, backupId);
|
||||
return {
|
||||
data,
|
||||
transientOptions: options
|
||||
};
|
||||
},
|
||||
resolveNotebookEditor: async (viewType: string, uri: URI, editorId: string) => {
|
||||
await this._proxy.$resolveNotebookEditor(viewType, uri, editorId);
|
||||
@@ -457,34 +478,28 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
onDidReceiveMessage: (editorId: string, rendererType: string | undefined, message: unknown) => {
|
||||
this._proxy.$onDidReceiveMessage(editorId, rendererType, message);
|
||||
},
|
||||
removeNotebookDocument: async (uri: URI) => {
|
||||
return this.removeNotebookTextModel(uri);
|
||||
},
|
||||
save: async (uri: URI, token: CancellationToken) => {
|
||||
return this._proxy.$saveNotebook(_viewType, uri, token);
|
||||
return this._proxy.$saveNotebook(viewType, uri, token);
|
||||
},
|
||||
saveAs: async (uri: URI, target: URI, token: CancellationToken) => {
|
||||
return this._proxy.$saveNotebookAs(_viewType, uri, target, token);
|
||||
return this._proxy.$saveNotebookAs(viewType, uri, target, token);
|
||||
},
|
||||
backup: async (uri: URI, token: CancellationToken) => {
|
||||
return this._proxy.$backup(_viewType, uri, token);
|
||||
return this._proxy.$backup(viewType, uri, token);
|
||||
}
|
||||
};
|
||||
|
||||
this._notebookProviders.set(_viewType, controller);
|
||||
this._notebookService.registerNotebookController(_viewType, _extension, controller);
|
||||
const disposable = this._notebookService.registerNotebookController(viewType, extension, controller);
|
||||
this._notebookProviders.set(viewType, { controller, disposable });
|
||||
return;
|
||||
}
|
||||
|
||||
async $onNotebookChange(viewType: string, uri: UriComponents): Promise<void> {
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(uri));
|
||||
textModel?.handleUnknownChange();
|
||||
}
|
||||
|
||||
async $unregisterNotebookProvider(viewType: string): Promise<void> {
|
||||
this._notebookProviders.delete(viewType);
|
||||
this._notebookService.unregisterNotebookProvider(viewType);
|
||||
return;
|
||||
const entry = this._notebookProviders.get(viewType);
|
||||
if (entry) {
|
||||
entry.disposable.dispose();
|
||||
this._notebookProviders.delete(viewType);
|
||||
}
|
||||
}
|
||||
|
||||
async $registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise<void> {
|
||||
@@ -547,26 +562,28 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
textModel?.updateLanguages(languages);
|
||||
}
|
||||
|
||||
async $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void> {
|
||||
this.logService.debug('MainThreadNotebooks#updateNotebookMetadata', resource.path, metadata);
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
textModel?.updateNotebookMetadata(metadata);
|
||||
}
|
||||
|
||||
async $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise<void> {
|
||||
this.logService.debug('MainThreadNotebooks#updateNotebookCellMetadata', resource.path, handle, metadata);
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
textModel?.changeCellMetadata(handle, metadata, true);
|
||||
}
|
||||
|
||||
async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise<void> {
|
||||
this.logService.debug('MainThreadNotebooks#spliceNotebookCellOutputs', resource.path, cellHandle);
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
|
||||
if (textModel) {
|
||||
this._notebookService.transformSpliceOutputs(textModel, splices);
|
||||
textModel.spliceNotebookCellOutputs(cellHandle, splices);
|
||||
if (!textModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._notebookService.transformSpliceOutputs(textModel, splices);
|
||||
const cell = textModel.cells.find(cell => cell.handle === cellHandle);
|
||||
|
||||
if (!cell) {
|
||||
return;
|
||||
}
|
||||
|
||||
textModel.applyEdits(textModel.versionId, [
|
||||
{
|
||||
editType: CellEditType.OutputsSplice,
|
||||
index: textModel.cells.indexOf(cell),
|
||||
splices
|
||||
}
|
||||
], true, undefined, () => undefined);
|
||||
}
|
||||
|
||||
async $postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean> {
|
||||
@@ -579,21 +596,30 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
return false;
|
||||
}
|
||||
|
||||
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void {
|
||||
$onUndoableContentChange(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void {
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
|
||||
if (textModel) {
|
||||
textModel.handleEdit(label, () => {
|
||||
return this._proxy.$undoNotebook(textModel.viewType, textModel.uri, editId, textModel.isDirty);
|
||||
textModel.handleUnknownUndoableEdit(label, () => {
|
||||
const isDirty = this._workingCopyService.isDirty(textModel.uri.with({ scheme: Schemas.vscodeNotebook }));
|
||||
return this._proxy.$undoNotebook(textModel.viewType, textModel.uri, editId, isDirty);
|
||||
}, () => {
|
||||
return this._proxy.$redoNotebook(textModel.viewType, textModel.uri, editId, textModel.isDirty);
|
||||
const isDirty = this._workingCopyService.isDirty(textModel.uri.with({ scheme: Schemas.vscodeNotebook }));
|
||||
return this._proxy.$redoNotebook(textModel.viewType, textModel.uri, editId, isDirty);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$onContentChange(resource: UriComponents, viewType: string): void {
|
||||
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
|
||||
textModel?.handleUnknownChange();
|
||||
|
||||
if (textModel) {
|
||||
textModel.applyEdits(textModel.versionId, [
|
||||
{
|
||||
editType: CellEditType.Unknown
|
||||
}
|
||||
], true, undefined, () => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
async $tryRevealRange(id: string, range: ICellRange, revealType: NotebookEditorRevealType) {
|
||||
@@ -640,4 +666,3 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ export class MainThreadProgress implements MainThreadProgressShape {
|
||||
|
||||
private _createTask(handle: number) {
|
||||
return (progress: IProgress<IProgressStep>) => {
|
||||
return new Promise<any>(resolve => {
|
||||
return new Promise<void>(resolve => {
|
||||
this._progress.set(handle, { resolve, progress });
|
||||
});
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { IDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { ExtHostContext, MainThreadSCMShape, ExtHostSCMShape, SCMProviderFeatures, SCMRawResourceSplices, SCMGroupFeatures, MainContext, IExtHostContext } from '../common/extHost.protocol';
|
||||
@@ -49,7 +48,7 @@ class MainThreadSCMResourceGroup implements ISCMResourceGroup {
|
||||
}
|
||||
|
||||
$updateGroup(features: SCMGroupFeatures): void {
|
||||
this.features = assign(this.features, features);
|
||||
this.features = { ...this.features, ...features };
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
|
||||
@@ -139,7 +138,7 @@ class MainThreadSCMProvider implements ISCMProvider {
|
||||
) { }
|
||||
|
||||
$updateSourceControl(features: SCMProviderFeatures): void {
|
||||
this.features = assign(this.features, features);
|
||||
this.features = { ...this.features, ...features };
|
||||
this._onDidChange.fire();
|
||||
|
||||
if (typeof features.commitTemplate !== 'undefined') {
|
||||
|
||||
@@ -13,8 +13,8 @@ import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } fr
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { WebviewIcons } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
|
||||
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -140,7 +140,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
|
||||
this._webviewInputs.add(handle, input);
|
||||
this._mainThreadWebviews.addWebview(handle, input.webview);
|
||||
|
||||
input.webview.onDispose(() => {
|
||||
input.webview.onDidDispose(() => {
|
||||
this._proxy.$onDidDisposeWebviewPanel(handle).finally(() => {
|
||||
this._webviewInputs.delete(handle);
|
||||
});
|
||||
|
||||
@@ -29,13 +29,20 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc
|
||||
}
|
||||
|
||||
public $setWebviewViewTitle(handle: extHostProtocol.WebviewHandle, value: string | undefined): void {
|
||||
const webviewView = this._webviewViews.get(handle);
|
||||
if (!webviewView) {
|
||||
throw new Error('unknown webview view');
|
||||
}
|
||||
const webviewView = this.getWebviewView(handle);
|
||||
webviewView.title = value;
|
||||
}
|
||||
|
||||
public $setWebviewViewDescription(handle: extHostProtocol.WebviewHandle, value: string | undefined): void {
|
||||
const webviewView = this.getWebviewView(handle);
|
||||
webviewView.description = value;
|
||||
}
|
||||
|
||||
public $show(handle: extHostProtocol.WebviewHandle, preserveFocus: boolean): void {
|
||||
const webviewView = this.getWebviewView(handle);
|
||||
webviewView.show(preserveFocus);
|
||||
}
|
||||
|
||||
public $registerWebviewViewProvider(viewType: string, options?: { retainContextWhenHidden?: boolean }): void {
|
||||
if (this._webviewViewProviders.has(viewType)) {
|
||||
throw new Error(`View provider for ${viewType} already registered`);
|
||||
@@ -71,7 +78,7 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc
|
||||
});
|
||||
|
||||
try {
|
||||
await this._proxy.$resolveWebviewView(handle, viewType, state, cancellation);
|
||||
await this._proxy.$resolveWebviewView(handle, viewType, webviewView.title, state, cancellation);
|
||||
} catch (error) {
|
||||
onUnexpectedError(error);
|
||||
webviewView.webview.html = this.mainThreadWebviews.getWebviewResolvedFailedContent(viewType);
|
||||
@@ -89,5 +96,13 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc
|
||||
provider.dispose();
|
||||
this._webviewViewProviders.delete(viewType);
|
||||
}
|
||||
|
||||
private getWebviewView(handle: string): WebviewView {
|
||||
const webviewView = this._webviewViews.get(handle);
|
||||
if (!webviewView) {
|
||||
throw new Error('unknown webview view');
|
||||
}
|
||||
return webviewView;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ 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 { Webview, WebviewExtensionDescription, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||
import { WebviewInputOptions } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
|
||||
|
||||
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {
|
||||
|
||||
@@ -69,7 +69,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
disposables.add(webview.onMessage((message: any) => { this._proxy.$onMessage(handle, message); }));
|
||||
disposables.add(webview.onMissingCsp((extension: ExtensionIdentifier) => this._proxy.$onMissingCsp(handle, extension.value)));
|
||||
|
||||
disposables.add(webview.onDispose(() => {
|
||||
disposables.add(webview.onDidDispose(() => {
|
||||
disposables.dispose();
|
||||
this._webviews.delete(handle);
|
||||
}));
|
||||
|
||||
@@ -108,9 +108,23 @@ enum InitialVisibility {
|
||||
|
||||
const viewDescriptor: IJSONSchema = {
|
||||
type: 'object',
|
||||
required: ['id', 'name'],
|
||||
defaultSnippets: [{ body: { id: '${1:id}', name: '${2:name}' } }],
|
||||
properties: {
|
||||
type: {
|
||||
markdownDescription: localize('vscode.extension.contributes.view.type', "Type of the the view. This can either be `tree` for a tree view based view or `webview` for a webview based view. The default is `tree`."),
|
||||
type: 'string',
|
||||
enum: [
|
||||
'tree',
|
||||
'webview',
|
||||
],
|
||||
markdownEnumDescriptions: [
|
||||
localize('vscode.extension.contributes.view.tree', "The view is backed by a `TreeView` created by `createTreeView`."),
|
||||
localize('vscode.extension.contributes.view.webview', "The view is backed by a `WebviewView` registered by `registerWebviewViewProvider`."),
|
||||
]
|
||||
},
|
||||
id: {
|
||||
description: localize('vscode.extension.contributes.view.id', 'Identifier of the view. This should be unique across all views. It is recommended to include your extension id as part of the view id. Use this to register a data provider through `vscode.window.registerTreeDataProviderForView` API. Also to trigger activating your extension by registering `onView:${id}` event to `activationEvents`.'),
|
||||
markdownDescription: localize('vscode.extension.contributes.view.id', 'Identifier of the view. This should be unique across all views. It is recommended to include your extension id as part of the view id. Use this to register a data provider through `vscode.window.registerTreeDataProviderForView` API. Also to trigger activating your extension by registering `onView:${id}` event to `activationEvents`.'),
|
||||
type: 'string'
|
||||
},
|
||||
name: {
|
||||
|
||||
@@ -67,7 +67,6 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostTheming } from 'vs/workbench/api/common/extHostTheming';
|
||||
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
@@ -80,6 +79,8 @@ import { IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileS
|
||||
import { ExtHostWebviewViews } from 'vs/workbench/api/common/extHostWebviewView';
|
||||
import { ExtHostCustomEditors } from 'vs/workbench/api/common/extHostCustomEditors';
|
||||
import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPanels';
|
||||
import { ExtHostBulkEdits } from 'vs/workbench/api/common/extHostBulkEdits';
|
||||
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -92,6 +93,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
|
||||
// services
|
||||
const initData = accessor.get(IExtHostInitDataService);
|
||||
const extHostFileSystemInfo = accessor.get(IExtHostFileSystemInfo);
|
||||
const extHostConsumerFileSystem = accessor.get(IExtHostConsumerFileSystem);
|
||||
const extensionService = accessor.get(IExtHostExtensionService);
|
||||
const extHostWorkspace = accessor.get(IExtHostWorkspace);
|
||||
@@ -106,6 +108,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostWindow = accessor.get(IExtHostWindow);
|
||||
|
||||
// register addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostFileSystemInfo, extHostFileSystemInfo);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
|
||||
@@ -128,14 +131,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
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.MainThreadTextEditors)));
|
||||
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, initData.environment, extHostLogService, extensionStoragePaths));
|
||||
const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors, 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 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));
|
||||
const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures, extHostFileSystemInfo));
|
||||
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostLogService, extHostDocumentsAndEditors));
|
||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
@@ -153,10 +156,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
// Check that no named customers are missing
|
||||
// {{SQL CARBON EDIT}} filter out the services we don't expose
|
||||
const filtered: ProxyIdentifier<any>[] = [ExtHostContext.ExtHostDebugService, ExtHostContext.ExtHostTask];
|
||||
const expected: ProxyIdentifier<any>[] = values(ExtHostContext).filter(v => !find(filtered, x => x === v));
|
||||
const expected: ProxyIdentifier<any>[] = values(ExtHostContext).filter(v => !filtered.find(x => x === v));
|
||||
rpcProtocol.assertRegistered(expected);
|
||||
|
||||
// Other instances
|
||||
const extHostBulkEdits = new ExtHostBulkEdits(rpcProtocol, extHostDocumentsAndEditors, extHostNotebook);
|
||||
const extHostClipboard = new ExtHostClipboard(rpcProtocol);
|
||||
const extHostMessageService = new ExtHostMessageService(rpcProtocol, extHostLogService);
|
||||
const extHostDialogs = new ExtHostDialogs(rpcProtocol);
|
||||
@@ -694,7 +698,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostWorkspace.saveAll(includeUntitled);
|
||||
},
|
||||
applyEdit(edit: vscode.WorkspaceEdit): Thenable<boolean> {
|
||||
return extHostEditors.applyWorkspaceEdit(edit);
|
||||
return extHostBulkEdits.applyWorkspaceEdit(edit);
|
||||
},
|
||||
createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => {
|
||||
return extHostFileSystemEvent.createFileSystemWatcher(typeConverters.GlobPattern.from(pattern), ignoreCreate, ignoreChange, ignoreDelete);
|
||||
@@ -991,6 +995,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeActiveNotebookEditor(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeNotebookDocumentMetadata(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookDocumentMetadata(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeNotebookCells(listener, thisArgs?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidChangeNotebookCells(listener, thisArgs, disposables);
|
||||
|
||||
@@ -19,7 +19,8 @@ import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHost
|
||||
import { IExtHostTunnelService, ExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { IExtHostApiDeprecationService, ExtHostApiDeprecationService, } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { IExtHostWindow, ExtHostWindow } from 'vs/workbench/api/common/extHostWindow';
|
||||
import { ExtHostConsumerFileSystem, IExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
|
||||
import { IExtHostConsumerFileSystem, ExtHostConsumerFileSystem } from 'vs/workbench/api/common/extHostFileSystemConsumer';
|
||||
import { IExtHostFileSystemInfo, ExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
|
||||
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths);
|
||||
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService);
|
||||
@@ -29,6 +30,7 @@ registerSingleton(IExtHostConsumerFileSystem, ExtHostConsumerFileSystem);
|
||||
// registerSingleton(IExtHostDebugService, WorkerExtHostDebugService);
|
||||
registerSingleton(IExtHostDecorations, ExtHostDecorations);
|
||||
registerSingleton(IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors);
|
||||
registerSingleton(IExtHostFileSystemInfo, ExtHostFileSystemInfo);
|
||||
registerSingleton(IExtHostOutputService, ExtHostOutputService);
|
||||
registerSingleton(IExtHostSearch, ExtHostSearch);
|
||||
registerSingleton(IExtHostStorage, ExtHostStorage);
|
||||
|
||||
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelOptions } 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 { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { Dto } from 'vs/base/common/types';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
@@ -267,6 +267,10 @@ export interface ITextDocumentShowOptions {
|
||||
selection?: IRange;
|
||||
}
|
||||
|
||||
export interface MainThreadBulkEditsShape extends IDisposable {
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise<string | undefined>;
|
||||
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
|
||||
@@ -279,7 +283,6 @@ export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): Promise<void>;
|
||||
$trySetSelections(id: string, selections: ISelection[]): Promise<void>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Promise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto): Promise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: readonly IRange[], opts: IUndoStopOptions): Promise<boolean>;
|
||||
$getDiffInformation(id: string): Promise<editorCommon.ILineChange[]>;
|
||||
}
|
||||
@@ -644,6 +647,9 @@ export interface MainThreadWebviewViewsShape extends IDisposable {
|
||||
$unregisterWebviewViewProvider(viewType: string): void;
|
||||
|
||||
$setWebviewViewTitle(handle: WebviewHandle, value: string | undefined): void;
|
||||
$setWebviewViewDescription(handle: WebviewHandle, value: string | undefined): void;
|
||||
|
||||
$show(handle: WebviewHandle, preserveFocus: boolean): void;
|
||||
}
|
||||
|
||||
export interface WebviewPanelViewStateData {
|
||||
@@ -684,7 +690,7 @@ export interface ExtHostCustomEditorsShape {
|
||||
}
|
||||
|
||||
export interface ExtHostWebviewViewsShape {
|
||||
$resolveWebviewView(webviewHandle: WebviewHandle, viewType: string, state: any, cancellation: CancellationToken): Promise<void>;
|
||||
$resolveWebviewView(webviewHandle: WebviewHandle, viewType: string, title: string | undefined, state: any, cancellation: CancellationToken): Promise<void>;
|
||||
|
||||
$onDidChangeWebviewViewVisibility(webviewHandle: WebviewHandle, visible: boolean): void;
|
||||
|
||||
@@ -734,20 +740,17 @@ export type INotebookCellStatusBarEntryDto = Dto<INotebookCellStatusBarEntry>;
|
||||
|
||||
export interface MainThreadNotebookShape extends IDisposable {
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void>;
|
||||
$onNotebookChange(viewType: string, resource: UriComponents): Promise<void>;
|
||||
$unregisterNotebookProvider(viewType: string): Promise<void>;
|
||||
$registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise<void>;
|
||||
$unregisterNotebookKernelProvider(handle: number): Promise<void>;
|
||||
$onNotebookKernelChange(handle: number, uri: UriComponents | undefined): void;
|
||||
$tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[]): Promise<boolean>;
|
||||
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
|
||||
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void>;
|
||||
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise<void>;
|
||||
$spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise<void>;
|
||||
$postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean>;
|
||||
$setStatusBarEntry(id: number, statusBarEntry: INotebookCellStatusBarEntryDto): Promise<void>;
|
||||
$tryRevealRange(id: string, range: ICellRange, revealType: NotebookEditorRevealType): Promise<void>;
|
||||
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
|
||||
$onUndoableContentChange(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
|
||||
$onContentChange(resource: UriComponents, viewType: string): void;
|
||||
}
|
||||
|
||||
@@ -1037,6 +1040,10 @@ export interface ExtHostWorkspaceShape {
|
||||
$handleTextSearchResult(result: search.IRawFileMatch2, requestId: number): void;
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemInfoShape {
|
||||
$acceptProviderInfos(scheme: string, capabilities: number | null): void;
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemShape {
|
||||
$stat(handle: number, resource: UriComponents): Promise<files.IStat>;
|
||||
$readdir(handle: number, resource: UriComponents): Promise<[string, files.FileType][]>;
|
||||
@@ -1277,7 +1284,7 @@ export interface IWorkspaceCellEditDto {
|
||||
_type: WorkspaceEditType.Cell;
|
||||
resource: UriComponents;
|
||||
edit: ICellEditOperation;
|
||||
modelVersionId?: number;
|
||||
notebookVersionId?: number;
|
||||
metadata?: IWorkspaceEditEntryMetadataDto;
|
||||
}
|
||||
|
||||
@@ -1643,16 +1650,15 @@ export interface INotebookVisibleRangesEvent {
|
||||
|
||||
export interface INotebookEditorPropertiesChangeData {
|
||||
visibleRanges: INotebookVisibleRangesEvent | null;
|
||||
selections: INotebookSelectionChangeEvent | null;
|
||||
}
|
||||
|
||||
export interface INotebookDocumentPropertiesChangeData {
|
||||
metadata: NotebookDocumentMetadata | null;
|
||||
selections: INotebookSelectionChangeEvent | null;
|
||||
}
|
||||
|
||||
export interface INotebookModelAddedData {
|
||||
uri: UriComponents;
|
||||
handle: number;
|
||||
versionId: number;
|
||||
cells: IMainCellDto[],
|
||||
viewType: string;
|
||||
@@ -1677,7 +1683,7 @@ export interface INotebookDocumentsAndEditorsDelta {
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookShape {
|
||||
$resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise<NotebookDataDto | undefined>;
|
||||
$resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise<NotebookDataDto>;
|
||||
$resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise<void>;
|
||||
$provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise<INotebookKernelInfoDto2[]>;
|
||||
$resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void>;
|
||||
@@ -1690,7 +1696,7 @@ export interface ExtHostNotebookShape {
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
|
||||
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelId: string | undefined }): void;
|
||||
$onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent, isDirty: boolean): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void;
|
||||
$acceptModelSaved(uriComponents: UriComponents): void;
|
||||
$acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void;
|
||||
$acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void;
|
||||
@@ -1727,6 +1733,7 @@ export interface ExtHostTimelineShape {
|
||||
|
||||
export const MainContext = {
|
||||
MainThreadAuthentication: createMainId<MainThreadAuthenticationShape>('MainThreadAuthentication'),
|
||||
MainThreadBulkEdits: createMainId<MainThreadBulkEditsShape>('MainThreadBulkEdits'),
|
||||
MainThreadClipboard: createMainId<MainThreadClipboardShape>('MainThreadClipboard'),
|
||||
MainThreadCommands: createMainId<MainThreadCommandsShape>('MainThreadCommands'),
|
||||
MainThreadComments: createMainId<MainThreadCommentsShape>('MainThreadComments'),
|
||||
@@ -1787,6 +1794,7 @@ export const ExtHostContext = {
|
||||
ExtHostEditors: createExtId<ExtHostEditorsShape>('ExtHostEditors'),
|
||||
ExtHostTreeViews: createExtId<ExtHostTreeViewsShape>('ExtHostTreeViews'),
|
||||
ExtHostFileSystem: createExtId<ExtHostFileSystemShape>('ExtHostFileSystem'),
|
||||
ExtHostFileSystemInfo: createExtId<ExtHostFileSystemInfoShape>('ExtHostFileSystemInfo'),
|
||||
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventServiceShape>('ExtHostFileSystemEventService'),
|
||||
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
||||
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
|
||||
|
||||
@@ -228,10 +228,15 @@ const newCommands: ApiCommand[] = [
|
||||
}
|
||||
return typeConverters.WorkspaceEdit.to(value);
|
||||
})
|
||||
),
|
||||
// --- links
|
||||
new ApiCommand(
|
||||
'vscode.executeLinkProvider', '_executeLinkProvider', 'Execute document link provider.',
|
||||
[ApiCommandArgument.Uri, new ApiCommandArgument('linkResolveCount', '(optional) Number of links that should be resolved, only when links are unresolved.', v => typeof v === 'number' || typeof v === 'undefined', v => v)],
|
||||
new ApiCommandResult<modes.ILink[], vscode.DocumentLink[]>('A promise that resolves to an array of DocumentLink-instances.', value => value.map(typeConverters.DocumentLink.to))
|
||||
)
|
||||
];
|
||||
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
@@ -289,13 +294,6 @@ export class ExtHostApiCommands {
|
||||
returns: 'A promise that resolves to an array of CodeLens-instances.'
|
||||
});
|
||||
|
||||
this._register('vscode.executeLinkProvider', this._executeDocumentLinkProvider, {
|
||||
description: 'Execute document link provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of DocumentLink-instances.'
|
||||
});
|
||||
this._register('vscode.executeDocumentColorProvider', this._executeDocumentColorProvider, {
|
||||
description: 'Execute document color provider.',
|
||||
args: [
|
||||
@@ -478,12 +476,6 @@ export class ExtHostApiCommands {
|
||||
typeConverters.Range.to(item.range),
|
||||
item.command ? this._commands.converter.fromInternal(item.command) : undefined);
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
private _executeDocumentLinkProvider(resource: URI): Promise<vscode.DocumentLink[] | undefined> {
|
||||
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource)
|
||||
.then(tryMapWith(typeConverters.DocumentLink.to));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
29
src/vs/workbench/api/common/extHostBulkEdits.ts
Normal file
29
src/vs/workbench/api/common/extHostBulkEdits.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 { MainContext, MainThreadBulkEditsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { WorkspaceEdit } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostBulkEdits {
|
||||
|
||||
private readonly _proxy: MainThreadBulkEditsShape;
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
private readonly _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _extHostNotebooks: ExtHostNotebookController,
|
||||
) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadBulkEdits);
|
||||
}
|
||||
|
||||
applyWorkspaceEdit(edit: vscode.WorkspaceEdit): Promise<boolean> {
|
||||
const dto = WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors, this._extHostNotebooks);
|
||||
return this._proxy.$tryApplyWorkspaceEdit(dto);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { illegalState } from 'vs/base/common/errors';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentSaveParticipantShape, IWorkspaceEditDto, WorkspaceEditType, MainThreadBulkEditsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
@@ -26,7 +26,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
constructor(
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _mainThreadEditors: MainThreadTextEditorsShape,
|
||||
private readonly _mainThreadBulkEdits: MainThreadBulkEditsShape,
|
||||
private readonly _thresholds: { timeout: number; errors: number; } = { timeout: 1500, errors: 3 }
|
||||
) {
|
||||
//
|
||||
@@ -165,7 +165,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
}
|
||||
|
||||
if (version === document.version) {
|
||||
return this._mainThreadEditors.$tryApplyWorkspaceEdit(dto);
|
||||
return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto);
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('concurrent_edits'));
|
||||
|
||||
@@ -747,7 +747,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
protected abstract _beforeAlmostReadyToRunExtensions(): Promise<void>;
|
||||
protected abstract _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined;
|
||||
protected abstract _loadCommonJSModule<T>(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T>;
|
||||
public abstract async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
|
||||
public abstract $setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,15 +7,15 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape, IFileChangeDto } from './extHost.protocol';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { FileChangeType } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as typeConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { State, StateMachine, LinkComputer, Edge } from 'vs/editor/common/modes/linkComputer';
|
||||
import { commonPrefixLength } from 'vs/base/common/strings';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
|
||||
class FsLinkProvider {
|
||||
|
||||
@@ -113,21 +113,18 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
private readonly _linkProvider = new FsLinkProvider();
|
||||
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>();
|
||||
private readonly _usedSchemes = new Set<string>();
|
||||
private readonly _registeredSchemes = new Set<string>();
|
||||
private readonly _watches = new Map<number, IDisposable>();
|
||||
|
||||
private _linkProviderRegistration?: IDisposable;
|
||||
private _handlePool: number = 0;
|
||||
|
||||
constructor(mainContext: IMainContext, private _extHostLanguageFeatures: ExtHostLanguageFeatures) {
|
||||
constructor(mainContext: IMainContext, private _extHostLanguageFeatures: ExtHostLanguageFeatures, private _extHostFileSystemInfo: IExtHostFileSystemInfo) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadFileSystem);
|
||||
|
||||
// register used schemes
|
||||
Object.keys(Schemas).forEach(scheme => this._usedSchemes.add(scheme));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this._linkProviderRegistration);
|
||||
this._linkProviderRegistration?.dispose();
|
||||
}
|
||||
|
||||
private _registerLinkProviderIfNotYetRegistered(): void {
|
||||
@@ -138,7 +135,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
|
||||
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean, isReadonly?: boolean } = {}) {
|
||||
|
||||
if (this._usedSchemes.has(scheme)) {
|
||||
if (this._registeredSchemes.has(scheme) || !this._extHostFileSystemInfo.isFreeScheme(scheme)) {
|
||||
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
|
||||
}
|
||||
|
||||
@@ -147,7 +144,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
|
||||
const handle = this._handlePool++;
|
||||
this._linkProvider.add(scheme);
|
||||
this._usedSchemes.add(scheme);
|
||||
this._registeredSchemes.add(scheme);
|
||||
this._fsProvider.set(handle, provider);
|
||||
|
||||
let capabilities = files.FileSystemProviderCapabilities.FileReadWrite;
|
||||
@@ -198,7 +195,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
return toDisposable(() => {
|
||||
subscription.dispose();
|
||||
this._linkProvider.delete(scheme);
|
||||
this._usedSchemes.delete(scheme);
|
||||
this._registeredSchemes.delete(scheme);
|
||||
this._fsProvider.delete(handle);
|
||||
this._proxy.$unregisterProvider(handle);
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { FileSystemError } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
|
||||
export class ExtHostConsumerFileSystem implements vscode.FileSystem {
|
||||
|
||||
@@ -17,7 +18,10 @@ export class ExtHostConsumerFileSystem implements vscode.FileSystem {
|
||||
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
|
||||
constructor(@IExtHostRpcService extHostRpc: IExtHostRpcService) {
|
||||
constructor(
|
||||
@IExtHostRpcService extHostRpc: IExtHostRpcService,
|
||||
@IExtHostFileSystemInfo private readonly _fileSystemInfo: IExtHostFileSystemInfo,
|
||||
) {
|
||||
this._proxy = extHostRpc.getProxy(MainContext.MainThreadFileSystem);
|
||||
}
|
||||
|
||||
@@ -45,6 +49,14 @@ export class ExtHostConsumerFileSystem implements vscode.FileSystem {
|
||||
copy(source: vscode.Uri, destination: vscode.Uri, options?: { overwrite?: boolean; }): Promise<void> {
|
||||
return this._proxy.$copy(source, destination, { ...{ overwrite: false }, ...options }).catch(ExtHostConsumerFileSystem._handleError);
|
||||
}
|
||||
isWritableFileSystem(scheme: string): boolean | undefined {
|
||||
const capabilities = this._fileSystemInfo.getCapabilities(scheme);
|
||||
if (typeof capabilities === 'number') {
|
||||
return !(capabilities & files.FileSystemProviderCapabilities.Readonly);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private static _handleError(err: any): never {
|
||||
// generic error
|
||||
if (!(err instanceof Error)) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IRelativePattern, parse } from 'vs/base/common/glob';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, MainThreadTextEditorsShape, SourceTargetPair, IWorkspaceEditDto } from './extHost.protocol';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, MainContext, SourceTargetPair, IWorkspaceEditDto, MainThreadBulkEditsShape } from './extHost.protocol';
|
||||
import * as typeConverter from './extHostTypeConverters';
|
||||
import { Disposable, WorkspaceEdit } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -123,7 +123,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
mainContext: IMainContext,
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _mainThreadTextEditors: MainThreadTextEditorsShape = mainContext.getProxy(MainContext.MainThreadTextEditors)
|
||||
private readonly _mainThreadBulkEdits: MainThreadBulkEditsShape = mainContext.getProxy(MainContext.MainThreadBulkEdits)
|
||||
) {
|
||||
//
|
||||
}
|
||||
@@ -222,7 +222,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
|
||||
dto.edits = dto.edits.concat(edits);
|
||||
}
|
||||
return this._mainThreadTextEditors.$tryApplyWorkspaceEdit(dto);
|
||||
return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
src/vs/workbench/api/common/extHostFileSystemInfo.ts
Normal file
35
src/vs/workbench/api/common/extHostFileSystemInfo.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ExtHostFileSystemInfoShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
export class ExtHostFileSystemInfo implements ExtHostFileSystemInfoShape {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _systemSchemes = new Set(Object.keys(Schemas));
|
||||
private readonly _providerInfo = new Map<string, number>();
|
||||
|
||||
$acceptProviderInfos(scheme: string, capabilities: number | null): void {
|
||||
if (capabilities === null) {
|
||||
this._providerInfo.delete(scheme);
|
||||
} else {
|
||||
this._providerInfo.set(scheme, capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
isFreeScheme(scheme: string): boolean {
|
||||
return !this._providerInfo.has(scheme) && !this._systemSchemes.has(scheme);
|
||||
}
|
||||
|
||||
getCapabilities(scheme: string): number | undefined {
|
||||
return this._providerInfo.get(scheme);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtHostFileSystemInfo extends ExtHostFileSystemInfo { }
|
||||
export const IExtHostFileSystemInfo = createDecorator<IExtHostFileSystemInfo>('IExtHostFileSystemInfo');
|
||||
@@ -25,7 +25,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { encodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokensDto';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
@@ -177,7 +177,7 @@ class CodeLensAdapter {
|
||||
}
|
||||
|
||||
releaseCodeLenses(cachedId: number): void {
|
||||
dispose(this._disposables.get(cachedId));
|
||||
this._disposables.get(cachedId)?.dispose();
|
||||
this._disposables.delete(cachedId);
|
||||
this._cache.delete(cachedId);
|
||||
}
|
||||
@@ -455,7 +455,7 @@ class CodeActionAdapter {
|
||||
}
|
||||
|
||||
public releaseCodeActions(cachedId: number): void {
|
||||
dispose(this._disposables.get(cachedId));
|
||||
this._disposables.get(cachedId)?.dispose();
|
||||
this._disposables.delete(cachedId);
|
||||
this._cache.delete(cachedId);
|
||||
}
|
||||
@@ -938,7 +938,7 @@ class SuggestAdapter {
|
||||
}
|
||||
|
||||
releaseCompletionItems(id: number): any {
|
||||
dispose(this._disposables.get(id));
|
||||
this._disposables.get(id)?.dispose();
|
||||
this._disposables.delete(id);
|
||||
this._cache.delete(id);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
527
src/vs/workbench/api/common/extHostNotebookDocument.ts
Normal file
527
src/vs/workbench/api/common/extHostNotebookDocument.ts
Normal file
@@ -0,0 +1,527 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { Disposable, DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { ISplice } from 'vs/base/common/sequence';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as UUID from 'vs/base/common/uuid';
|
||||
import { CellKind, INotebookDocumentPropertiesChangeData, IWorkspaceCellEditDto, MainThreadBulkEditsShape, MainThreadNotebookShape, NotebookCellOutputsSplice, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { CellEditType, CellOutputKind, diff, IMainCellDto, IProcessedOutput, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookCellsSplice2, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
import { Cache } from './cache';
|
||||
|
||||
|
||||
interface IObservable<T> {
|
||||
proxy: T;
|
||||
onDidChange: Event<void>;
|
||||
}
|
||||
|
||||
function getObservable<T extends Object>(obj: T): IObservable<T> {
|
||||
const onDidChange = new Emitter<void>();
|
||||
const proxy = new Proxy(obj, {
|
||||
set(target: T, p: PropertyKey, value: any, _receiver: any): boolean {
|
||||
target[p as keyof T] = value;
|
||||
onDidChange.fire();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
proxy,
|
||||
onDidChange: onDidChange.event
|
||||
};
|
||||
}
|
||||
|
||||
class RawContentChangeEvent {
|
||||
|
||||
constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: ExtHostCell[], readonly items: ExtHostCell[]) { }
|
||||
|
||||
static asApiEvent(event: RawContentChangeEvent): vscode.NotebookCellsChangeData {
|
||||
return Object.freeze({
|
||||
start: event.start,
|
||||
deletedCount: event.deletedCount,
|
||||
deletedItems: event.deletedItems.map(data => data.cell),
|
||||
items: event.items.map(data => data.cell)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostCell extends Disposable {
|
||||
|
||||
static asModelAddData(notebook: vscode.NotebookDocument, cell: IMainCellDto): IExtHostModelAddedData {
|
||||
return {
|
||||
EOL: cell.eol,
|
||||
lines: cell.source,
|
||||
modeId: cell.language,
|
||||
uri: cell.uri,
|
||||
isDirty: false,
|
||||
versionId: 1,
|
||||
notebook
|
||||
};
|
||||
}
|
||||
|
||||
private _onDidDispose = new Emitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
|
||||
private _onDidChangeOutputs = new Emitter<ISplice<IProcessedOutput>[]>();
|
||||
readonly onDidChangeOutputs: Event<ISplice<IProcessedOutput>[]> = this._onDidChangeOutputs.event;
|
||||
|
||||
private _outputs: any[];
|
||||
private _outputMapping = new WeakMap<vscode.CellOutput, string | undefined /* output ID */>();
|
||||
|
||||
private _metadata: vscode.NotebookCellMetadata;
|
||||
private _metadataChangeListener: IDisposable;
|
||||
|
||||
readonly handle: number;
|
||||
readonly uri: URI;
|
||||
readonly cellKind: CellKind;
|
||||
|
||||
private _cell: vscode.NotebookCell | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _mainThreadBulkEdits: MainThreadBulkEditsShape,
|
||||
private readonly _notebook: ExtHostNotebookDocument,
|
||||
private readonly _extHostDocument: ExtHostDocumentsAndEditors,
|
||||
private readonly _cellData: IMainCellDto,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.handle = _cellData.handle;
|
||||
this.uri = URI.revive(_cellData.uri);
|
||||
this.cellKind = _cellData.cellKind;
|
||||
|
||||
this._outputs = _cellData.outputs;
|
||||
for (const output of this._outputs) {
|
||||
this._outputMapping.set(output, output.outputId);
|
||||
delete output.outputId;
|
||||
}
|
||||
|
||||
const observableMetadata = getObservable(_cellData.metadata ?? {});
|
||||
this._metadata = observableMetadata.proxy;
|
||||
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
|
||||
this._updateMetadata();
|
||||
}));
|
||||
}
|
||||
|
||||
get cell(): vscode.NotebookCell {
|
||||
if (!this._cell) {
|
||||
const that = this;
|
||||
const document = this._extHostDocument.getDocument(this.uri)!.document;
|
||||
this._cell = Object.freeze({
|
||||
get index() { return that._notebook.getCellIndex(that); },
|
||||
notebook: that._notebook.notebookDocument,
|
||||
uri: that.uri,
|
||||
cellKind: this._cellData.cellKind,
|
||||
document,
|
||||
get language() { return document.languageId; },
|
||||
get outputs() { return that._outputs; },
|
||||
set outputs(value) { that._updateOutputs(value); },
|
||||
get metadata() { return that._metadata; },
|
||||
set metadata(value) {
|
||||
that.setMetadata(value);
|
||||
that._updateMetadata();
|
||||
},
|
||||
});
|
||||
}
|
||||
return this._cell;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
super.dispose();
|
||||
this._onDidDispose.fire();
|
||||
}
|
||||
|
||||
setOutputs(newOutputs: vscode.CellOutput[]): void {
|
||||
this._outputs = newOutputs;
|
||||
}
|
||||
|
||||
private _updateOutputs(newOutputs: vscode.CellOutput[]) {
|
||||
const rawDiffs = diff<vscode.CellOutput>(this._outputs || [], newOutputs || [], (a) => {
|
||||
return this._outputMapping.has(a);
|
||||
});
|
||||
|
||||
const transformedDiffs: ISplice<IProcessedOutput>[] = rawDiffs.map(diff => {
|
||||
for (let i = diff.start; i < diff.start + diff.deleteCount; i++) {
|
||||
this._outputMapping.delete(this._outputs[i]);
|
||||
}
|
||||
|
||||
return {
|
||||
deleteCount: diff.deleteCount,
|
||||
start: diff.start,
|
||||
toInsert: diff.toInsert.map((output): IProcessedOutput => {
|
||||
if (output.outputKind === CellOutputKind.Rich) {
|
||||
const uuid = UUID.generateUuid();
|
||||
this._outputMapping.set(output, uuid);
|
||||
return { ...output, outputId: uuid };
|
||||
}
|
||||
|
||||
this._outputMapping.set(output, undefined);
|
||||
return output;
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
this._outputs = newOutputs;
|
||||
this._onDidChangeOutputs.fire(transformedDiffs);
|
||||
}
|
||||
|
||||
setMetadata(newMetadata: vscode.NotebookCellMetadata): void {
|
||||
// Don't apply metadata defaults here, 'undefined' means 'inherit from document metadata'
|
||||
this._metadataChangeListener.dispose();
|
||||
const observableMetadata = getObservable(newMetadata);
|
||||
this._metadata = observableMetadata.proxy;
|
||||
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
|
||||
this._updateMetadata();
|
||||
}));
|
||||
}
|
||||
|
||||
private _updateMetadata(): Promise<boolean> {
|
||||
const index = this._notebook.notebookDocument.cells.indexOf(this.cell);
|
||||
const edit: IWorkspaceCellEditDto = {
|
||||
_type: WorkspaceEditType.Cell,
|
||||
metadata: undefined,
|
||||
resource: this._notebook.uri,
|
||||
notebookVersionId: this._notebook.notebookDocument.version,
|
||||
edit: { editType: CellEditType.Metadata, index, metadata: this._metadata }
|
||||
};
|
||||
|
||||
return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit({ edits: [edit] });
|
||||
}
|
||||
}
|
||||
|
||||
export interface INotebookEventEmitter {
|
||||
emitModelChange(events: vscode.NotebookCellsChangeEvent): void;
|
||||
emitDocumentMetadataChange(event: vscode.NotebookDocumentMetadataChangeEvent): void;
|
||||
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void;
|
||||
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void;
|
||||
emitCellMetadataChange(event: vscode.NotebookCellMetadataChangeEvent): void;
|
||||
}
|
||||
|
||||
function hashPath(resource: URI): string {
|
||||
const str = resource.scheme === Schemas.file || resource.scheme === Schemas.untitled ? resource.fsPath : resource.toString();
|
||||
return hash(str) + '';
|
||||
}
|
||||
|
||||
export class ExtHostNotebookDocument extends Disposable {
|
||||
|
||||
private static _handlePool: number = 0;
|
||||
readonly handle = ExtHostNotebookDocument._handlePool++;
|
||||
|
||||
private _cells: ExtHostCell[] = [];
|
||||
|
||||
private _cellDisposableMapping = new Map<number, DisposableStore>();
|
||||
|
||||
private _notebook: vscode.NotebookDocument | undefined;
|
||||
private _metadata: Required<vscode.NotebookDocumentMetadata>;
|
||||
private _metadataChangeListener: IDisposable;
|
||||
private _versionId = 0;
|
||||
private _isDirty: boolean = false;
|
||||
private _backupCounter = 1;
|
||||
private _backup?: vscode.NotebookDocumentBackup;
|
||||
private _disposed = false;
|
||||
private _languages: string[] = [];
|
||||
|
||||
private readonly _edits = new Cache<vscode.NotebookDocumentEditEvent>('notebook documents');
|
||||
|
||||
constructor(
|
||||
private readonly _proxy: MainThreadNotebookShape,
|
||||
private readonly _documentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _mainThreadBulkEdits: MainThreadBulkEditsShape,
|
||||
private readonly _emitter: INotebookEventEmitter,
|
||||
private readonly _viewType: string,
|
||||
metadata: Required<vscode.NotebookDocumentMetadata>,
|
||||
public readonly uri: URI,
|
||||
private readonly _storagePath: URI | undefined
|
||||
) {
|
||||
super();
|
||||
|
||||
const observableMetadata = getObservable(metadata);
|
||||
this._metadata = observableMetadata.proxy;
|
||||
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
|
||||
this._tryUpdateMetadata();
|
||||
}));
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposed = true;
|
||||
super.dispose();
|
||||
dispose(this._cellDisposableMapping.values());
|
||||
}
|
||||
|
||||
private _updateMetadata(newMetadata: Required<vscode.NotebookDocumentMetadata>) {
|
||||
this._metadataChangeListener.dispose();
|
||||
newMetadata = {
|
||||
...notebookDocumentMetadataDefaults,
|
||||
...newMetadata
|
||||
};
|
||||
if (this._metadataChangeListener) {
|
||||
this._metadataChangeListener.dispose();
|
||||
}
|
||||
|
||||
const observableMetadata = getObservable(newMetadata);
|
||||
this._metadata = observableMetadata.proxy;
|
||||
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
|
||||
this._tryUpdateMetadata();
|
||||
}));
|
||||
|
||||
this._tryUpdateMetadata();
|
||||
}
|
||||
|
||||
private _tryUpdateMetadata() {
|
||||
const edit: IWorkspaceCellEditDto = {
|
||||
_type: WorkspaceEditType.Cell,
|
||||
metadata: undefined,
|
||||
edit: { editType: CellEditType.DocumentMetadata, metadata: this._metadata },
|
||||
resource: this.uri,
|
||||
notebookVersionId: this.notebookDocument.version,
|
||||
};
|
||||
|
||||
return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit({ edits: [edit] });
|
||||
}
|
||||
|
||||
get notebookDocument(): vscode.NotebookDocument {
|
||||
if (!this._notebook) {
|
||||
const that = this;
|
||||
this._notebook = Object.freeze({
|
||||
get uri() { return that.uri; },
|
||||
get version() { return that._versionId; },
|
||||
get fileName() { return that.uri.fsPath; },
|
||||
get viewType() { return that._viewType; },
|
||||
get isDirty() { return that._isDirty; },
|
||||
get isUntitled() { return that.uri.scheme === Schemas.untitled; },
|
||||
get cells(): ReadonlyArray<vscode.NotebookCell> { return that._cells.map(cell => cell.cell); },
|
||||
get languages() { return that._languages; },
|
||||
set languages(value: string[]) { that._trySetLanguages(value); },
|
||||
get metadata() { return that._metadata; },
|
||||
set metadata(value: Required<vscode.NotebookDocumentMetadata>) { that._updateMetadata(value); },
|
||||
});
|
||||
}
|
||||
return this._notebook;
|
||||
}
|
||||
|
||||
private _trySetLanguages(newLanguages: string[]) {
|
||||
this._languages = newLanguages;
|
||||
this._proxy.$updateNotebookLanguages(this._viewType, this.uri, this._languages);
|
||||
}
|
||||
|
||||
getNewBackupUri(): URI {
|
||||
if (!this._storagePath) {
|
||||
throw new Error('Backup requires a valid storage path');
|
||||
}
|
||||
const fileName = hashPath(this.uri) + (this._backupCounter++);
|
||||
return joinPath(this._storagePath, fileName);
|
||||
}
|
||||
|
||||
updateBackup(backup: vscode.NotebookDocumentBackup): void {
|
||||
this._backup?.delete();
|
||||
this._backup = backup;
|
||||
}
|
||||
|
||||
disposeBackup(): void {
|
||||
this._backup?.delete();
|
||||
this._backup = undefined;
|
||||
}
|
||||
|
||||
acceptDocumentPropertiesChanged(data: INotebookDocumentPropertiesChangeData) {
|
||||
const newMetadata = {
|
||||
...notebookDocumentMetadataDefaults,
|
||||
...data.metadata
|
||||
};
|
||||
|
||||
if (this._metadataChangeListener) {
|
||||
this._metadataChangeListener.dispose();
|
||||
}
|
||||
|
||||
const observableMetadata = getObservable(newMetadata);
|
||||
this._metadata = observableMetadata.proxy;
|
||||
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
|
||||
this._tryUpdateMetadata();
|
||||
}));
|
||||
|
||||
this._emitter.emitDocumentMetadataChange({ document: this.notebookDocument });
|
||||
}
|
||||
|
||||
acceptModelChanged(event: NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
this._versionId = event.versionId;
|
||||
this._isDirty = isDirty;
|
||||
event.rawEvents.forEach(e => {
|
||||
if (e.kind === NotebookCellsChangeType.Initialize) {
|
||||
this._spliceNotebookCells(e.changes, true);
|
||||
} if (e.kind === NotebookCellsChangeType.ModelChange) {
|
||||
this._spliceNotebookCells(e.changes, false);
|
||||
} else if (e.kind === NotebookCellsChangeType.Move) {
|
||||
this._moveCell(e.index, e.newIdx);
|
||||
} else if (e.kind === NotebookCellsChangeType.Output) {
|
||||
this._setCellOutputs(e.index, e.outputs);
|
||||
} else if (e.kind === NotebookCellsChangeType.ChangeLanguage) {
|
||||
this._changeCellLanguage(e.index, e.language);
|
||||
} else if (e.kind === NotebookCellsChangeType.ChangeCellMetadata) {
|
||||
this._changeCellMetadata(e.index, e.metadata);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _spliceNotebookCells(splices: NotebookCellsSplice2[], initialization: boolean): void {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const contentChangeEvents: RawContentChangeEvent[] = [];
|
||||
const addedCellDocuments: IExtHostModelAddedData[] = [];
|
||||
const removedCellDocuments: URI[] = [];
|
||||
|
||||
splices.reverse().forEach(splice => {
|
||||
const cellDtos = splice[2];
|
||||
const newCells = cellDtos.map(cell => {
|
||||
|
||||
const extCell = new ExtHostCell(this._mainThreadBulkEdits, this, this._documentsAndEditors, cell);
|
||||
|
||||
if (!initialization) {
|
||||
addedCellDocuments.push(ExtHostCell.asModelAddData(this.notebookDocument, cell));
|
||||
}
|
||||
|
||||
if (!this._cellDisposableMapping.has(extCell.handle)) {
|
||||
const store = new DisposableStore();
|
||||
store.add(extCell);
|
||||
this._cellDisposableMapping.set(extCell.handle, store);
|
||||
}
|
||||
|
||||
const store = this._cellDisposableMapping.get(extCell.handle)!;
|
||||
|
||||
store.add(extCell.onDidChangeOutputs((diffs) => {
|
||||
this.eventuallyUpdateCellOutputs(extCell, diffs);
|
||||
}));
|
||||
|
||||
return extCell;
|
||||
});
|
||||
|
||||
for (let j = splice[0]; j < splice[0] + splice[1]; j++) {
|
||||
this._cellDisposableMapping.get(this._cells[j].handle)?.dispose();
|
||||
this._cellDisposableMapping.delete(this._cells[j].handle);
|
||||
}
|
||||
|
||||
const deletedItems = this._cells.splice(splice[0], splice[1], ...newCells);
|
||||
for (let cell of deletedItems) {
|
||||
removedCellDocuments.push(cell.uri);
|
||||
}
|
||||
|
||||
contentChangeEvents.push(new RawContentChangeEvent(splice[0], splice[1], deletedItems, newCells));
|
||||
});
|
||||
|
||||
this._documentsAndEditors.acceptDocumentsAndEditorsDelta({
|
||||
addedDocuments: addedCellDocuments,
|
||||
removedDocuments: removedCellDocuments
|
||||
});
|
||||
|
||||
if (!initialization) {
|
||||
this._emitter.emitModelChange({
|
||||
document: this.notebookDocument,
|
||||
changes: contentChangeEvents.map(RawContentChangeEvent.asApiEvent)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _moveCell(index: number, newIdx: number): void {
|
||||
const cells = this._cells.splice(index, 1);
|
||||
this._cells.splice(newIdx, 0, ...cells);
|
||||
const changes: vscode.NotebookCellsChangeData[] = [{
|
||||
start: index,
|
||||
deletedCount: 1,
|
||||
deletedItems: cells.map(data => data.cell),
|
||||
items: []
|
||||
}, {
|
||||
start: newIdx,
|
||||
deletedCount: 0,
|
||||
deletedItems: [],
|
||||
items: cells.map(data => data.cell)
|
||||
}];
|
||||
this._emitter.emitModelChange({
|
||||
document: this.notebookDocument,
|
||||
changes
|
||||
});
|
||||
}
|
||||
|
||||
private _setCellOutputs(index: number, outputs: IProcessedOutput[]): void {
|
||||
const cell = this._cells[index];
|
||||
cell.setOutputs(outputs);
|
||||
this._emitter.emitCellOutputsChange({ document: this.notebookDocument, cells: [cell.cell] });
|
||||
}
|
||||
|
||||
private _changeCellLanguage(index: number, language: string): void {
|
||||
const cell = this._cells[index];
|
||||
const event: vscode.NotebookCellLanguageChangeEvent = { document: this.notebookDocument, cell: cell.cell, language };
|
||||
this._emitter.emitCellLanguageChange(event);
|
||||
}
|
||||
|
||||
private _changeCellMetadata(index: number, newMetadata: NotebookCellMetadata | undefined): void {
|
||||
const cell = this._cells[index];
|
||||
cell.setMetadata(newMetadata || {});
|
||||
const event: vscode.NotebookCellMetadataChangeEvent = { document: this.notebookDocument, cell: cell.cell };
|
||||
this._emitter.emitCellMetadataChange(event);
|
||||
}
|
||||
|
||||
async eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice<IProcessedOutput>[]) {
|
||||
const outputDtos: NotebookCellOutputsSplice[] = diffs.map(diff => {
|
||||
const outputs = diff.toInsert;
|
||||
return [diff.start, diff.deleteCount, outputs];
|
||||
});
|
||||
|
||||
if (!outputDtos.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._proxy.$spliceNotebookCellOutputs(this._viewType, this.uri, cell.handle, outputDtos);
|
||||
this._emitter.emitCellOutputsChange({
|
||||
document: this.notebookDocument,
|
||||
cells: [cell.cell]
|
||||
});
|
||||
}
|
||||
|
||||
getCell(cellHandle: number): ExtHostCell | undefined {
|
||||
return this._cells.find(cell => cell.handle === cellHandle);
|
||||
}
|
||||
|
||||
getCellIndex(cell: ExtHostCell): number {
|
||||
return this._cells.indexOf(cell);
|
||||
}
|
||||
|
||||
addEdit(item: vscode.NotebookDocumentEditEvent): number {
|
||||
return this._edits.add([item]);
|
||||
}
|
||||
|
||||
async undo(editId: number, isDirty: boolean): Promise<void> {
|
||||
await this.getEdit(editId).undo();
|
||||
// if (!isDirty) {
|
||||
// this.disposeBackup();
|
||||
// }
|
||||
}
|
||||
|
||||
async redo(editId: number, isDirty: boolean): Promise<void> {
|
||||
await this.getEdit(editId).redo();
|
||||
// if (!isDirty) {
|
||||
// this.disposeBackup();
|
||||
// }
|
||||
}
|
||||
|
||||
private getEdit(editId: number): vscode.NotebookDocumentEditEvent {
|
||||
const edit = this._edits.get(editId, 0);
|
||||
if (!edit) {
|
||||
throw new Error('No edit found');
|
||||
}
|
||||
|
||||
return edit;
|
||||
}
|
||||
|
||||
disposeEdits(editIds: number[]): void {
|
||||
for (const id of editIds) {
|
||||
this._edits.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
230
src/vs/workbench/api/common/extHostNotebookEditor.ts
Normal file
230
src/vs/workbench/api/common/extHostNotebookEditor.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { readonly } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import { addIdToOutput, CellEditType, ICellEditOperation, ICellReplaceEdit, INotebookEditData, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostNotebookDocument } from './extHostNotebookDocument';
|
||||
|
||||
class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit {
|
||||
|
||||
private readonly _documentVersionId: number;
|
||||
|
||||
private _finalized: boolean = false;
|
||||
private _collectedEdits: ICellEditOperation[] = [];
|
||||
|
||||
constructor(documentVersionId: number) {
|
||||
this._documentVersionId = documentVersionId;
|
||||
}
|
||||
|
||||
finalize(): INotebookEditData {
|
||||
this._finalized = true;
|
||||
return {
|
||||
documentVersionId: this._documentVersionId,
|
||||
cellEdits: this._collectedEdits
|
||||
};
|
||||
}
|
||||
|
||||
private _throwIfFinalized() {
|
||||
if (this._finalized) {
|
||||
throw new Error('Edit is only valid while callback runs');
|
||||
}
|
||||
}
|
||||
|
||||
replaceMetadata(value: vscode.NotebookDocumentMetadata): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.DocumentMetadata,
|
||||
metadata: { ...notebookDocumentMetadataDefaults, ...value }
|
||||
});
|
||||
}
|
||||
|
||||
replaceCellMetadata(index: number, metadata: vscode.NotebookCellMetadata): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.Metadata,
|
||||
index,
|
||||
metadata
|
||||
});
|
||||
}
|
||||
|
||||
replaceCellOutput(index: number, outputs: vscode.CellOutput[]): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.Output,
|
||||
index,
|
||||
outputs: outputs.map(output => addIdToOutput(output))
|
||||
});
|
||||
}
|
||||
|
||||
replaceCells(from: number, to: number, cells: vscode.NotebookCellData[]): void {
|
||||
this._throwIfFinalized();
|
||||
this._collectedEdits.push({
|
||||
editType: CellEditType.Replace,
|
||||
index: from,
|
||||
count: to - from,
|
||||
cells: cells.map(data => {
|
||||
return {
|
||||
...data,
|
||||
outputs: data.outputs.map(output => addIdToOutput(output)),
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor {
|
||||
|
||||
//TODO@rebornix noop setter?
|
||||
selection?: vscode.NotebookCell;
|
||||
|
||||
private _visibleRanges: vscode.NotebookCellRange[] = [];
|
||||
private _viewColumn?: vscode.ViewColumn;
|
||||
private _active: boolean = false;
|
||||
private _visible: boolean = false;
|
||||
private _kernel?: vscode.NotebookKernel;
|
||||
|
||||
private _onDidDispose = new Emitter<void>();
|
||||
private _onDidReceiveMessage = new Emitter<any>();
|
||||
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
readonly onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
|
||||
|
||||
constructor(
|
||||
readonly id: string,
|
||||
private readonly _viewType: string,
|
||||
private readonly _proxy: MainThreadNotebookShape,
|
||||
private readonly _webComm: vscode.NotebookCommunication,
|
||||
readonly notebookData: ExtHostNotebookDocument,
|
||||
) {
|
||||
super();
|
||||
this._register(this._webComm.onDidReceiveMessage(e => {
|
||||
this._onDidReceiveMessage.fire(e);
|
||||
}));
|
||||
}
|
||||
|
||||
get viewColumn(): vscode.ViewColumn | undefined {
|
||||
return this._viewColumn;
|
||||
}
|
||||
|
||||
set viewColumn(_value) {
|
||||
throw readonly('viewColumn');
|
||||
}
|
||||
|
||||
get kernel() {
|
||||
return this._kernel;
|
||||
}
|
||||
|
||||
set kernel(_kernel: vscode.NotebookKernel | undefined) {
|
||||
throw readonly('kernel');
|
||||
}
|
||||
|
||||
_acceptKernel(kernel?: vscode.NotebookKernel) {
|
||||
this._kernel = kernel;
|
||||
}
|
||||
|
||||
get visible(): boolean {
|
||||
return this._visible;
|
||||
}
|
||||
|
||||
set visible(_state: boolean) {
|
||||
throw readonly('visible');
|
||||
}
|
||||
|
||||
_acceptVisibility(value: boolean) {
|
||||
this._visible = value;
|
||||
}
|
||||
|
||||
get visibleRanges() {
|
||||
return this._visibleRanges;
|
||||
}
|
||||
|
||||
set visibleRanges(_range: vscode.NotebookCellRange[]) {
|
||||
throw readonly('visibleRanges');
|
||||
}
|
||||
|
||||
_acceptVisibleRanges(value: vscode.NotebookCellRange[]): void {
|
||||
this._visibleRanges = value;
|
||||
}
|
||||
|
||||
get active(): boolean {
|
||||
return this._active;
|
||||
}
|
||||
|
||||
set active(_state: boolean) {
|
||||
throw readonly('active');
|
||||
}
|
||||
|
||||
_acceptActive(value: boolean) {
|
||||
this._active = value;
|
||||
}
|
||||
|
||||
get document(): vscode.NotebookDocument {
|
||||
return this.notebookData.notebookDocument;
|
||||
}
|
||||
|
||||
edit(callback: (editBuilder: NotebookEditorCellEditBuilder) => void): Thenable<boolean> {
|
||||
const edit = new NotebookEditorCellEditBuilder(this.document.version);
|
||||
callback(edit);
|
||||
return this._applyEdit(edit.finalize());
|
||||
}
|
||||
|
||||
private _applyEdit(editData: INotebookEditData): Promise<boolean> {
|
||||
|
||||
// return when there is nothing to do
|
||||
if (editData.cellEdits.length === 0) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
const compressedEdits: ICellEditOperation[] = [];
|
||||
let compressedEditsIndex = -1;
|
||||
|
||||
for (let i = 0; i < editData.cellEdits.length; i++) {
|
||||
if (compressedEditsIndex < 0) {
|
||||
compressedEdits.push(editData.cellEdits[i]);
|
||||
compressedEditsIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const prevIndex = compressedEditsIndex;
|
||||
const prev = compressedEdits[prevIndex];
|
||||
|
||||
if (prev.editType === CellEditType.Replace && editData.cellEdits[i].editType === CellEditType.Replace) {
|
||||
const edit = editData.cellEdits[i];
|
||||
if ((edit.editType !== CellEditType.DocumentMetadata && edit.editType !== CellEditType.Unknown) && prev.index === edit.index) {
|
||||
prev.cells.push(...(editData.cellEdits[i] as ICellReplaceEdit).cells);
|
||||
prev.count += (editData.cellEdits[i] as ICellReplaceEdit).count;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
compressedEdits.push(editData.cellEdits[i]);
|
||||
compressedEditsIndex++;
|
||||
}
|
||||
|
||||
return this._proxy.$tryApplyEdits(this._viewType, this.document.uri, editData.documentVersionId, compressedEdits);
|
||||
}
|
||||
|
||||
revealRange(range: vscode.NotebookCellRange, revealType?: extHostTypes.NotebookEditorRevealType) {
|
||||
this._proxy.$tryRevealRange(this.id, range, revealType || extHostTypes.NotebookEditorRevealType.Default);
|
||||
}
|
||||
|
||||
async postMessage(message: any): Promise<boolean> {
|
||||
return this._webComm.postMessage(message);
|
||||
}
|
||||
|
||||
asWebviewUri(localResource: vscode.Uri): vscode.Uri {
|
||||
return this._webComm.asWebviewUri(localResource);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._onDidDispose.fire();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -456,7 +456,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape, IExtHostTask
|
||||
});
|
||||
}
|
||||
|
||||
public abstract async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution>;
|
||||
public abstract executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution>;
|
||||
|
||||
public get taskExecutions(): vscode.TaskExecution[] {
|
||||
const result: vscode.TaskExecution[] = [];
|
||||
@@ -561,7 +561,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape, IExtHostTask
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract async resolveTaskInternal(resolvedTaskDTO: tasks.TaskDTO): Promise<tasks.TaskDTO | undefined>;
|
||||
protected abstract resolveTaskInternal(resolvedTaskDTO: tasks.TaskDTO): Promise<tasks.TaskDTO | undefined>;
|
||||
|
||||
public async $resolveTask(handle: number, taskDTO: tasks.TaskDTO): Promise<tasks.TaskDTO | undefined> {
|
||||
const handler = this._handlers.get(handle);
|
||||
@@ -601,7 +601,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape, IExtHostTask
|
||||
return await this.resolveTaskInternal(resolvedTaskDTO);
|
||||
}
|
||||
|
||||
public abstract async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }>;
|
||||
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 }>;
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
|
||||
) {
|
||||
super(proxy, id);
|
||||
this._creationOptions = Object.freeze(this._creationOptions);
|
||||
this._pidPromise = new Promise<number>(c => this._pidPromiseComplete = c);
|
||||
this._pidPromise = new Promise<number | undefined>(c => this._pidPromiseComplete = c);
|
||||
}
|
||||
|
||||
public async create(
|
||||
@@ -316,7 +316,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
protected _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
|
||||
protected _terminalProcessDisposables: { [id: number]: IDisposable } = {};
|
||||
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
|
||||
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
|
||||
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal | undefined> } = {};
|
||||
protected _environmentVariableCollections: Map<string, EnvironmentVariableCollection> = new Map();
|
||||
|
||||
private readonly _bufferer: TerminalDataBufferer;
|
||||
@@ -670,7 +670,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
|
||||
return this._getTerminalPromises[id];
|
||||
}
|
||||
|
||||
private _createGetTerminalPromise(id: number, retries: number = 5): Promise<ExtHostTerminal> {
|
||||
private _createGetTerminalPromise(id: number, retries: number = 5): Promise<ExtHostTerminal | undefined> {
|
||||
return new Promise(c => {
|
||||
if (retries === 0) {
|
||||
c(undefined);
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { ExtHostEditorsShape, IEditorPropertiesChangeData, IMainContext, ITextDocumentShowOptions, ITextEditorPositionData, MainContext, MainThreadTextEditorsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostTextEditor, TextEditorDecorationType } from 'vs/workbench/api/common/extHostTextEditor';
|
||||
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { TextEditorSelectionChangeKind } from 'vs/workbench/api/common/extHostTypes';
|
||||
@@ -34,7 +33,6 @@ export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
private readonly _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _extHostNotebooks: ExtHostNotebookController,
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTextEditors);
|
||||
|
||||
@@ -92,11 +90,6 @@ export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
return new TextEditorDecorationType(this._proxy, options);
|
||||
}
|
||||
|
||||
applyWorkspaceEdit(edit: vscode.WorkspaceEdit): Promise<boolean> {
|
||||
const dto = TypeConverters.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors, this._extHostNotebooks);
|
||||
return this._proxy.$tryApplyWorkspaceEdit(dto);
|
||||
}
|
||||
|
||||
// --- called from main thread
|
||||
|
||||
$acceptEditorPropertiesChanged(id: string, data: IEditorPropertiesChangeData): void {
|
||||
|
||||
@@ -537,10 +537,11 @@ export namespace WorkspaceEdit {
|
||||
} else if (entry._type === types.FileEditType.Cell) {
|
||||
result.edits.push(<extHostProtocol.IWorkspaceCellEditDto>{
|
||||
_type: extHostProtocol.WorkspaceEditType.Cell,
|
||||
metadata: entry.metadata,
|
||||
resource: entry.uri,
|
||||
edit: entry.edit,
|
||||
metadata: entry.metadata,
|
||||
modelVersionId: notebooks?.lookupNotebookDocument(entry.uri)?.notebookDocument.version
|
||||
notebookMetadata: entry.notebookMetadata,
|
||||
notebookVersionId: notebooks?.lookupNotebookDocument(entry.uri)?.notebookDocument.version
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { addIdToOutput, CellEditType, ICellEditOperation } from 'vs/workbench/co
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
function es5ClassCompat(target: Function): any {
|
||||
///@ts-expect-error
|
||||
// @ts-ignore - {{SQL CARBON EDIT}}
|
||||
function _() { return Reflect.construct(target, arguments, this.constructor); }
|
||||
Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')!);
|
||||
Object.setPrototypeOf(_, target);
|
||||
@@ -601,7 +601,8 @@ export interface IFileTextEdit {
|
||||
export interface IFileCellEdit {
|
||||
_type: FileEditType.Cell;
|
||||
uri: URI;
|
||||
edit: ICellEditOperation;
|
||||
edit?: ICellEditOperation;
|
||||
notebookMetadata?: vscode.NotebookDocumentMetadata;
|
||||
metadata?: vscode.WorkspaceEditEntryMetadata;
|
||||
}
|
||||
|
||||
@@ -629,17 +630,21 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
|
||||
this._edits.push({ _type: FileEditType.File, from: uri, to: undefined, options, metadata });
|
||||
}
|
||||
|
||||
// --- cell
|
||||
// --- notebook
|
||||
|
||||
replaceCells(uri: URI, start: number, end: number, cells: vscode.NotebookCellData[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
replaceNotebookMetadata(uri: URI, value: vscode.NotebookDocumentMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
this._edits.push({ _type: FileEditType.Cell, metadata, uri, notebookMetadata: value });
|
||||
}
|
||||
|
||||
replaceNotebookCells(uri: URI, start: number, end: number, cells: vscode.NotebookCellData[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Replace, index: start, count: end - start, cells: cells.map(cell => ({ ...cell, outputs: cell.outputs.map(output => addIdToOutput(output)) })) } });
|
||||
}
|
||||
|
||||
replaceCellOutput(uri: URI, index: number, outputs: vscode.CellOutput[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
replaceNotebookCellOutput(uri: URI, index: number, outputs: vscode.CellOutput[], metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Output, index, outputs: outputs.map(output => addIdToOutput(output)) } });
|
||||
}
|
||||
|
||||
replaceCellMetadata(uri: URI, index: number, cellMetadata: vscode.NotebookCellMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
replaceNotebookCellMetadata(uri: URI, index: number, cellMetadata: vscode.NotebookCellMetadata, metadata?: vscode.WorkspaceEditEntryMetadata): void {
|
||||
this._edits.push({ _type: FileEditType.Cell, metadata, uri, edit: { editType: CellEditType.Metadata, index, metadata: cellMetadata } });
|
||||
}
|
||||
|
||||
|
||||
@@ -23,17 +23,20 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView {
|
||||
#isDisposed = false;
|
||||
#isVisible: boolean;
|
||||
#title: string | undefined;
|
||||
#description: string | undefined;
|
||||
|
||||
constructor(
|
||||
handle: extHostProtocol.WebviewHandle,
|
||||
proxy: extHostProtocol.MainThreadWebviewViewsShape,
|
||||
viewType: string,
|
||||
title: string | undefined,
|
||||
webview: ExtHostWebview,
|
||||
isVisible: boolean,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.#viewType = viewType;
|
||||
this.#title = title;
|
||||
this.#handle = handle;
|
||||
this.#proxy = proxy;
|
||||
this.#webview = webview;
|
||||
@@ -70,6 +73,19 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView {
|
||||
}
|
||||
}
|
||||
|
||||
public get description(): string | undefined {
|
||||
this.assertNotDisposed();
|
||||
return this.#description;
|
||||
}
|
||||
|
||||
public set description(value: string | undefined) {
|
||||
this.assertNotDisposed();
|
||||
if (this.#description !== value) {
|
||||
this.#description = value;
|
||||
this.#proxy.$setWebviewViewDescription(this.#handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public get visible(): boolean { return this.#isVisible; }
|
||||
|
||||
public get webview(): vscode.Webview { return this.#webview; }
|
||||
@@ -85,6 +101,11 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView {
|
||||
this.#onDidChangeVisibility.fire();
|
||||
}
|
||||
|
||||
public show(preserveFocus?: boolean): void {
|
||||
this.assertNotDisposed();
|
||||
this.#proxy.$show(this.#handle, !!preserveFocus);
|
||||
}
|
||||
|
||||
private assertNotDisposed() {
|
||||
if (this.#isDisposed) {
|
||||
throw new Error('Webview is disposed');
|
||||
@@ -134,6 +155,7 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
|
||||
async $resolveWebviewView(
|
||||
webviewHandle: string,
|
||||
viewType: string,
|
||||
title: string | undefined,
|
||||
state: any,
|
||||
cancellation: CancellationToken,
|
||||
): Promise<void> {
|
||||
@@ -145,7 +167,7 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
|
||||
const { provider, extension } = entry;
|
||||
|
||||
const webview = this._extHostWebview.createNewWebview(webviewHandle, { /* todo */ }, extension);
|
||||
const revivedView = new ExtHostWebviewView(webviewHandle, this._proxy, viewType, webview, true);
|
||||
const revivedView = new ExtHostWebviewView(webviewHandle, this._proxy, viewType, title, webview, true);
|
||||
|
||||
this._webviewViews.set(webviewHandle, revivedView);
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ namespace schema {
|
||||
};
|
||||
|
||||
export const submenusContribution: IJSONSchema = {
|
||||
description: localize('vscode.extension.contributes.submenus', "(Proposed API) Contributes submenu items to the editor"),
|
||||
description: localize('vscode.extension.contributes.submenus', "Contributes submenu items to the editor"),
|
||||
type: 'array',
|
||||
items: submenu
|
||||
};
|
||||
@@ -622,11 +622,6 @@ submenusExtensionPoint.setHandler(extensions => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!extension.description.enableProposedApi) {
|
||||
collector.error(localize('submenu.proposedAPI.invalid', "Submenus are proposed API and are only available when running out of dev or with the following command line switch: --enable-proposed-api {0}", extension.description.identifier.value));
|
||||
return;
|
||||
}
|
||||
|
||||
let absoluteIcon: { dark: URI; light?: URI; } | ThemeIcon | undefined;
|
||||
if (entry.value.icon) {
|
||||
if (typeof entry.value.icon === 'string') {
|
||||
@@ -675,7 +670,6 @@ menusExtensionPoint.setHandler(extensions => {
|
||||
}
|
||||
|
||||
let menu = _apiMenusByKey.get(entry.key);
|
||||
let isSubmenu = false;
|
||||
|
||||
if (!menu) {
|
||||
const submenu = _submenus.get(entry.key);
|
||||
@@ -686,7 +680,6 @@ menusExtensionPoint.setHandler(extensions => {
|
||||
id: submenu.id,
|
||||
description: ''
|
||||
};
|
||||
isSubmenu = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,11 +693,6 @@ menusExtensionPoint.setHandler(extensions => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSubmenu && !extension.description.enableProposedApi) {
|
||||
collector.error(localize('proposedAPI.invalid.submenu', "{0} is a submenu identifier and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", entry.key, extension.description.identifier.value));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const menuItem of entry.value) {
|
||||
let item: IMenuItem | ISubmenuItem;
|
||||
|
||||
@@ -725,13 +713,8 @@ menusExtensionPoint.setHandler(extensions => {
|
||||
|
||||
item = { command, alt, group: undefined, order: undefined, when: undefined };
|
||||
} else {
|
||||
if (!extension.description.enableProposedApi) {
|
||||
collector.error(localize('proposedAPI.invalid.submenureference', "Menu item references a submenu which is only available when running out of dev or with the following command line switch: --enable-proposed-api {0}", extension.description.identifier.value));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (menu.supportsSubmenus === false) {
|
||||
collector.error(localize('proposedAPI.unsupported.submenureference', "Menu item references a submenu for a menu which doesn't have submenu support."));
|
||||
collector.error(localize('unsupported.submenureference', "Menu item references a submenu for a menu which doesn't have submenu support."));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user