Skip to content

Commit

Permalink
tweak workspace edit dto and handling #105283
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Aug 26, 2020
1 parent 35ba71b commit 600d8a5
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 54 deletions.
25 changes: 21 additions & 4 deletions src/vs/workbench/api/browser/mainThreadEditors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { disposed } from 'vs/base/common/errors';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { equals as objectEquals } from 'vs/base/common/objects';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IBulkEditService, ResourceEdit } from 'vs/editor/browser/services/bulkEditService';
import { IBulkEditService, ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { IRange } from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
Expand All @@ -20,7 +20,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/browser/mainThreadDocumentsAndEditors';
import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor';
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, reviveWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
import { EditorViewColumn, editorGroupToViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
Expand All @@ -29,6 +29,23 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { revive } from 'vs/base/common/marshalling';

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));
}
}
return result;
}

export class MainThreadTextEditors implements MainThreadTextEditorsShape {

Expand Down Expand Up @@ -222,8 +239,8 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
}

$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise<boolean> {
const { edits } = reviveWorkspaceEditDto(dto)!;
return this._bulkEditService.apply(ResourceEdit.convert({ edits })).then(() => true, _err => false);
const edits = reviveWorkspaceEditDto2(dto);
return this._bulkEditService.apply(edits).then(() => true, _err => false);
}

$tryInsertSnippet(id: string, template: string, ranges: readonly IRange[], opts: IUndoStopOptions): Promise<boolean> {
Expand Down
7 changes: 7 additions & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1232,14 +1232,21 @@ export interface IWorkspaceEditEntryMetadataDto {
iconPath?: { id: string } | UriComponents | { light: UriComponents, dark: UriComponents };
}

export const enum WorkspaceEditType {
File = 1,
Text = 2,
}

export interface IWorkspaceFileEditDto {
_type: WorkspaceEditType.File;
oldUri?: UriComponents;
newUri?: UriComponents;
options?: modes.WorkspaceFileEditOptions
metadata?: IWorkspaceEditEntryMetadataDto;
}

export interface IWorkspaceTextEditDto {
_type: WorkspaceEditType.Text;
resource: UriComponents;
edit: modes.TextEdit;
modelVersionId?: number;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {

try {
const result = await this._proxy.$executeCommand<T>(id, toArgs, retry);
return revive(result);
return revive<any>(result);
} catch (e) {
// Rerun the command when it wasn't known, had arguments, and when retry
// is enabled. We do this because the command might be registered inside
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IWorkspaceEditDto, WorkspaceEditType } 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';
Expand Down Expand Up @@ -146,6 +146,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
if (Array.isArray(value) && (<vscode.TextEdit[]>value).every(e => e instanceof TextEdit)) {
for (const { newText, newEol, range } of value) {
dto.edits.push({
_type: WorkspaceEditType.Text,
resource: document.uri,
edit: {
range: range && Range.from(range),
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,10 @@ export namespace WorkspaceEdit {
if (value instanceof types.WorkspaceEdit) {
for (let entry of value.allEntries()) {

if (entry._type === 1) {
if (entry._type === types.FileEditType.File) {
// file operation
result.edits.push(<extHostProtocol.IWorkspaceFileEditDto>{
_type: extHostProtocol.WorkspaceEditType.File,
oldUri: entry.from,
newUri: entry.to,
options: entry.options,
Expand All @@ -526,6 +527,7 @@ export namespace WorkspaceEdit {
// text edits
const doc = documents?.getDocument(entry.uri);
result.edits.push(<extHostProtocol.IWorkspaceTextEditDto>{
_type: extHostProtocol.WorkspaceEditType.Text,
resource: entry.uri,
edit: TextEdit.from(entry.edit),
modelVersionId: doc?.version,
Expand Down
67 changes: 34 additions & 33 deletions src/vs/workbench/api/common/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { coalesce, equals } from 'vs/base/common/arrays';
import { coalesceInPlace, equals } from 'vs/base/common/arrays';
import { escapeCodicons } from 'vs/base/common/codicons';
import { illegalArgument } from 'vs/base/common/errors';
import { IRelativePattern } from 'vs/base/common/glob';
import { isMarkdownString } from 'vs/base/common/htmlContent';
import { ResourceMap } from 'vs/base/common/map';
import { startsWith } from 'vs/base/common/strings';
import { isStringArray } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
Expand Down Expand Up @@ -575,16 +576,21 @@ export interface IFileOperationOptions {
recursive?: boolean;
}

export const enum FileEditType {
File = 1,
Text = 2
}

export interface IFileOperation {
_type: 1;
_type: FileEditType.File;
from?: URI;
to?: URI;
options?: IFileOperationOptions;
metadata?: vscode.WorkspaceEditEntryMetadata;
}

export interface IFileTextEdit {
_type: 2;
_type: FileEditType.Text;
uri: URI;
edit: TextEdit;
metadata?: vscode.WorkspaceEditEntryMetadata;
Expand All @@ -593,22 +599,31 @@ export interface IFileTextEdit {
@es5ClassCompat
export class WorkspaceEdit implements vscode.WorkspaceEdit {

private _edits = new Array<IFileOperation | IFileTextEdit>();
private readonly _edits = new Array<IFileOperation | IFileTextEdit>();


allEntries(): ReadonlyArray<IFileTextEdit | IFileOperation> {
return this._edits;
}

// --- file

renameFile(from: vscode.Uri, to: vscode.Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean; }, metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: 1, from, to, options, metadata });
this._edits.push({ _type: FileEditType.File, from, to, options, metadata });
}

createFile(uri: vscode.Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean; }, metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: 1, from: undefined, to: uri, options, metadata });
this._edits.push({ _type: FileEditType.File, from: undefined, to: uri, options, metadata });
}

deleteFile(uri: vscode.Uri, options?: { recursive?: boolean, ignoreIfNotExists?: boolean; }, metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: 1, from: uri, to: undefined, options, metadata });
this._edits.push({ _type: FileEditType.File, from: uri, to: undefined, options, metadata });
}

// --- text

replace(uri: URI, range: Range, newText: string, metadata?: vscode.WorkspaceEditEntryMetadata): void {
this._edits.push({ _type: 2, uri, edit: new TextEdit(range, newText), metadata });
this._edits.push({ _type: FileEditType.Text, uri, edit: new TextEdit(range, newText), metadata });
}

insert(resource: URI, position: Position, newText: string, metadata?: vscode.WorkspaceEditEntryMetadata): void {
Expand All @@ -619,25 +634,27 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
this.replace(resource, range, '', metadata);
}

// --- text (Maplike)

has(uri: URI): boolean {
return this._edits.some(edit => edit._type === 2 && edit.uri.toString() === uri.toString());
return this._edits.some(edit => edit._type === FileEditType.Text && edit.uri.toString() === uri.toString());
}

set(uri: URI, edits: TextEdit[]): void {
if (!edits) {
// remove all text edits for `uri`
for (let i = 0; i < this._edits.length; i++) {
const element = this._edits[i];
if (element._type === 2 && element.uri.toString() === uri.toString()) {
if (element._type === FileEditType.Text && element.uri.toString() === uri.toString()) {
this._edits[i] = undefined!; // will be coalesced down below
}
}
this._edits = coalesce(this._edits);
coalesceInPlace(this._edits);
} else {
// append edit to the end
for (const edit of edits) {
if (edit) {
this._edits.push({ _type: 2, uri, edit });
this._edits.push({ _type: FileEditType.Text, uri, edit });
}
}
}
Expand All @@ -646,44 +663,28 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
get(uri: URI): TextEdit[] {
const res: TextEdit[] = [];
for (let candidate of this._edits) {
if (candidate._type === 2 && candidate.uri.toString() === uri.toString()) {
if (candidate._type === FileEditType.Text && candidate.uri.toString() === uri.toString()) {
res.push(candidate.edit);
}
}
return res;
}

entries(): [URI, TextEdit[]][] {
const textEdits = new Map<string, [URI, TextEdit[]]>();
const textEdits = new ResourceMap<[URI, TextEdit[]]>();
for (let candidate of this._edits) {
if (candidate._type === 2) {
let textEdit = textEdits.get(candidate.uri.toString());
if (candidate._type === FileEditType.Text) {
let textEdit = textEdits.get(candidate.uri);
if (!textEdit) {
textEdit = [candidate.uri, []];
textEdits.set(candidate.uri.toString(), textEdit);
textEdits.set(candidate.uri, textEdit);
}
textEdit[1].push(candidate.edit);
}
}
return [...textEdits.values()];
}

allEntries(): ReadonlyArray<IFileTextEdit | IFileOperation> {
return this._edits;
}

// _allEntries(): ([URI, TextEdit] | [URI?, URI?, IFileOperationOptions?])[] {
// const res: ([URI, TextEdit] | [URI?, URI?, IFileOperationOptions?])[] = [];
// for (let edit of this._edits) {
// if (edit._type === 1) {
// res.push([edit.from, edit.to, edit.options]);
// } else {
// res.push([edit.uri, edit.edit]);
// }
// }
// return res;
// }

get size(): number {
return this.entries().length;
}
Expand Down
12 changes: 8 additions & 4 deletions src/vs/workbench/test/browser/api/extHostTextEditors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { MainContext, MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { MainContext, MainThreadTextEditorsShape, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { SingleProxyRPCProtocol, TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors';
import { WorkspaceTextEdit } from 'vs/editor/common/modes';
import { NullLogService } from 'vs/platform/log/common/log';
import { assertType } from 'vs/base/common/types';

suite('ExtHostTextEditors.applyWorkspaceEdit', () => {

Expand Down Expand Up @@ -48,15 +48,19 @@ suite('ExtHostTextEditors.applyWorkspaceEdit', () => {
edit.replace(resource, new extHostTypes.Range(0, 0, 0, 0), 'hello');
await editors.applyWorkspaceEdit(edit);
assert.equal(workspaceResourceEdits.edits.length, 1);
assert.equal((<WorkspaceTextEdit>workspaceResourceEdits.edits[0]).modelVersionId, 1337);
const [first] = workspaceResourceEdits.edits;
assertType(first._type === WorkspaceEditType.Text);
assert.equal(first.modelVersionId, 1337);
});

test('does not use version id if document is not available', async () => {
let edit = new extHostTypes.WorkspaceEdit();
edit.replace(URI.parse('foo:bar2'), new extHostTypes.Range(0, 0, 0, 0), 'hello');
await editors.applyWorkspaceEdit(edit);
assert.equal(workspaceResourceEdits.edits.length, 1);
assert.ok(typeof (<WorkspaceTextEdit>workspaceResourceEdits.edits[0]).modelVersionId === 'undefined');
const [first] = workspaceResourceEdits.edits;
assertType(first._type === WorkspaceEditType.Text);
assert.ok(typeof first.modelVersionId === 'undefined');
});

});
12 changes: 6 additions & 6 deletions src/vs/workbench/test/browser/api/extHostTypes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,17 +388,17 @@ suite('ExtHostTypes', function () {
assert.equal(all.length, 4);

const [first, second, third, fourth] = all;
assertType(first._type === 2);
assertType(first._type === types.FileEditType.Text);
assert.equal(first.uri.toString(), 'foo:a');

assertType(second._type === 1);
assertType(second._type === types.FileEditType.File);
assert.equal(second.from!.toString(), 'foo:a');
assert.equal(second.to!.toString(), 'foo:b');

assertType(third._type === 2);
assertType(third._type === types.FileEditType.Text);
assert.equal(third.uri.toString(), 'foo:a');

assertType(fourth._type === 2);
assertType(fourth._type === types.FileEditType.Text);
assert.equal(fourth.uri.toString(), 'foo:b');
});

Expand All @@ -411,8 +411,8 @@ suite('ExtHostTypes', function () {
assert.equal(edit.allEntries().length, 2);
let [first, second] = edit.allEntries();

assertType(first._type === 2);
assertType(second._type === 2);
assertType(first._type === types.FileEditType.Text);
assertType(second._type === types.FileEditType.Text);
assert.equal(first.edit.newText, 'Hello');
assert.equal(second.edit.newText, 'Foo');
});
Expand Down
11 changes: 7 additions & 4 deletions src/vs/workbench/test/browser/api/mainThreadEditors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape, IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape, IWorkspaceTextEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
import { mock } from 'vs/base/test/common/mock';
import { Event } from 'vs/base/common/event';
import { MainThreadTextEditors } from 'vs/workbench/api/browser/mainThreadEditors';
Expand Down Expand Up @@ -170,6 +170,7 @@ suite('MainThreadEditors', () => {
let model = modelService.createModel('something', null, resource);

let workspaceResourceEdit: IWorkspaceTextEditDto = {
_type: WorkspaceEditType.Text,
resource: resource,
modelVersionId: model.getVersionId(),
edit: {
Expand All @@ -191,6 +192,7 @@ suite('MainThreadEditors', () => {
let model = modelService.createModel('something', null, resource);

let workspaceResourceEdit1: IWorkspaceTextEditDto = {
_type: WorkspaceEditType.Text,
resource: resource,
modelVersionId: model.getVersionId(),
edit: {
Expand All @@ -199,6 +201,7 @@ suite('MainThreadEditors', () => {
}
};
let workspaceResourceEdit2: IWorkspaceTextEditDto = {
_type: WorkspaceEditType.Text,
resource: resource,
modelVersionId: model.getVersionId(),
edit: {
Expand All @@ -221,9 +224,9 @@ suite('MainThreadEditors', () => {
test(`applyWorkspaceEdit with only resource edit`, () => {
return editors.$tryApplyWorkspaceEdit({
edits: [
{ oldUri: resource, newUri: resource, options: undefined },
{ oldUri: undefined, newUri: resource, options: undefined },
{ oldUri: resource, newUri: undefined, options: undefined }
{ _type: WorkspaceEditType.File, oldUri: resource, newUri: resource, options: undefined },
{ _type: WorkspaceEditType.File, oldUri: undefined, newUri: resource, options: undefined },
{ _type: WorkspaceEditType.File, oldUri: resource, newUri: undefined, options: undefined }
]
}).then((result) => {
assert.equal(result, true);
Expand Down

0 comments on commit 600d8a5

Please sign in to comment.