From 40df36b6e59ddea38e02bf4a3fc5841fc99881a4 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 18 Jun 2018 17:43:30 +0200 Subject: [PATCH] add proposed api for workspace edit #10659 --- .../src/singlefolder-tests/workspace.test.ts | 76 +++++++++++-------- .../workbench/api/node/extHostTextEditors.ts | 20 +---- .../api/node/extHostTypeConverters.ts | 6 +- .../electron-browser/bulkEditService.ts | 11 ++- 4 files changed, 56 insertions(+), 57 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index a26fc00bfab..efaa8e518e2 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -10,6 +10,7 @@ import * as vscode from 'vscode'; import { createRandomFile, deleteFile, closeAllEditors, pathEquals } from '../utils'; import { join, basename } from 'path'; import * as fs from 'fs'; +import { networkInterfaces } from 'os'; suite('workspace-namespace', () => { @@ -520,42 +521,51 @@ suite('workspace-namespace', () => { }); - // test('applyEdit should fail when editing deleted resource', async () => { - // const resource = await createRandomFile(); + test('applyEdit should fail when editing deleted resource', async () => { + const resource = await createRandomFile(); + const edit = new vscode.WorkspaceEdit(); + edit.deleteFile(resource); + edit.insert(resource, new vscode.Position(0, 0), ''); + + let success = await vscode.workspace.applyEdit(edit); + assert.equal(success, false); + }); + + test('applyEdit should fail when renaming deleted resource', async () => { + const resource = await createRandomFile(); + + const edit = new vscode.WorkspaceEdit(); + edit.deleteFile(resource); + edit.renameFile(resource, resource); + + let success = await vscode.workspace.applyEdit(edit); + assert.equal(success, false); + }); + + test('applyEdit should fail when editing renamed from resource', async () => { + const resource = await createRandomFile(); + const newResource = vscode.Uri.parse(resource.fsPath + '.1'); + const edit = new vscode.WorkspaceEdit(); + edit.renameFile(resource, newResource); + edit.insert(resource, new vscode.Position(0, 0), ''); + + let success = await vscode.workspace.applyEdit(edit); + assert.equal(success, false); + }); + + // test('applyEdit "edit A -> rename A to B -> edit B"', async () => { + // const oldUri = await createRandomFile(); + // const newUri = oldUri.with({ path: oldUri.path + 'NEW' }); // const edit = new vscode.WorkspaceEdit(); - // edit.deleteResource(resource); - // try { - // edit.insert(resource, new vscode.Position(0, 0), ''); - // assert.fail(false, 'Should disallow edit of deleted resource'); - // } catch { - // // noop - // } - // }); + // edit.insert(oldUri, new vscode.Position(0, 0), 'BEFORE'); + // edit.renameFile(oldUri, newUri); + // edit.insert(newUri, new vscode.Position(0, 0), 'AFTER'); - // test('applyEdit should fail when renaming deleted resource', async () => { - // const resource = await createRandomFile(); + // let success = await vscode.workspace.applyEdit(edit); + // assert.equal(success, true); - // const edit = new vscode.WorkspaceEdit(); - // edit.deleteResource(resource); - // try { - // edit.renameResource(resource, resource); - // assert.fail(false, 'Should disallow rename of deleted resource'); - // } catch { - // // noop - // } - // }); - - // test('applyEdit should fail when editing renamed from resource', async () => { - // const resource = await createRandomFile(); - // const newResource = vscode.Uri.parse(resource.fsPath + '.1'); - // const edit = new vscode.WorkspaceEdit(); - // edit.renameResource(resource, newResource); - // try { - // edit.insert(resource, new vscode.Position(0, 0), ''); - // assert.fail(false, 'Should disallow editing renamed file'); - // } catch { - // // noop - // } + // let doc = await vscode.workspace.openTextDocument(newUri); + // assert.equal(doc.getText(), 'AFTERBEFORE'); // }); }); diff --git a/src/vs/workbench/api/node/extHostTextEditors.ts b/src/vs/workbench/api/node/extHostTextEditors.ts index 4bbe0c52412..fb33f6247fa 100644 --- a/src/vs/workbench/api/node/extHostTextEditors.ts +++ b/src/vs/workbench/api/node/extHostTextEditors.ts @@ -11,7 +11,7 @@ import { TextEditorSelectionChangeKind } from './extHostTypes'; import * as TypeConverters from './extHostTypeConverters'; import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor'; import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors'; -import { MainContext, MainThreadTextEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IMainContext, WorkspaceEditDto, IEditorPropertiesChangeData } from './extHost.protocol'; +import { MainContext, MainThreadTextEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IMainContext, IEditorPropertiesChangeData } from './extHost.protocol'; import * as vscode from 'vscode'; export class ExtHostEditors implements ExtHostEditorsShape { @@ -91,23 +91,7 @@ export class ExtHostEditors implements ExtHostEditorsShape { } applyWorkspaceEdit(edit: vscode.WorkspaceEdit): TPromise { - - const dto: WorkspaceEditDto = { edits: [] }; - - for (let entry of edit.entries()) { - let [uri, uriOrEdits] = entry; - if (Array.isArray(uriOrEdits)) { - let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString()); - dto.edits.push({ - resource: uri, - modelVersionId: doc && doc.version, - edits: uriOrEdits.map(TypeConverters.TextEdit.from) - }); - // } else { - // dto.edits.push({ oldUri: uri, newUri: uriOrEdits }); - } - } - + const dto = TypeConverters.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors); return this._proxy.$tryApplyWorkspaceEdit(dto); } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index 485a3fee2f9..f5988c930c8 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -24,6 +24,7 @@ import * as languageSelector from 'vs/editor/common/modes/languageSelector'; import { WorkspaceEditDto, ResourceTextEditDto, ResourceFileEditDto } from 'vs/workbench/api/node/extHost.protocol'; import { MarkerSeverity, IRelatedInformation, IMarkerData, MarkerTag } from 'vs/platform/markers/common/markers'; import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; +import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; export interface PositionLike { line: number; @@ -269,7 +270,7 @@ export const TextEdit = { }; export namespace WorkspaceEdit { - export function from(value: vscode.WorkspaceEdit): modes.WorkspaceEdit { + export function from(value: vscode.WorkspaceEdit, documents?: ExtHostDocumentsAndEditors): WorkspaceEditDto { const result: modes.WorkspaceEdit = { edits: [] }; @@ -277,7 +278,8 @@ export namespace WorkspaceEdit { const [uri, uriOrEdits] = entry; if (Array.isArray(uriOrEdits)) { // text edits - result.edits.push({ resource: uri, edits: uriOrEdits.map(TextEdit.from) }); + let doc = documents ? documents.getDocument(uri.toString()) : undefined; + result.edits.push({ resource: uri, modelVersionId: doc && doc.version, edits: uriOrEdits.map(TextEdit.from) }); } else { // resource edits result.edits.push({ oldUri: uri, newUri: uriOrEdits }); diff --git a/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts index cfa25c08037..3e6906377e7 100644 --- a/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/electron-browser/bulkEditService.ts @@ -26,6 +26,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; +import { ILogService } from 'vs/platform/log/common/log'; abstract class Recording { @@ -385,6 +386,7 @@ export class BulkEditService implements IBulkEditService { _serviceBrand: any; constructor( + @ILogService private readonly _logService: ILogService, @IModelService private readonly _modelService: IModelService, @IEditorService private readonly _editorService: IEditorService, @ITextModelService private readonly _textModelService: ITextModelService, @@ -424,11 +426,12 @@ export class BulkEditService implements IBulkEditService { const bulkEdit = new BulkEdit(options.editor, options.progress, this._textModelService, this._fileService, this._textFileService, this._environmentService, this._contextService); bulkEdit.add(edits); + return bulkEdit.perform().then(selection => { - return { - selection, - ariaSummary: bulkEdit.ariaMessage() - }; + return { selection, ariaSummary: bulkEdit.ariaMessage() }; + }, err => { + this._logService.error(err); + return TPromise.wrapError(err); }); } }