Skip to content

Commit 600d8a5

Browse files
committed
tweak workspace edit dto and handling #105283
1 parent 35ba71b commit 600d8a5

9 files changed

+89
-54
lines changed

src/vs/workbench/api/browser/mainThreadEditors.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { disposed } from 'vs/base/common/errors';
88
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
99
import { equals as objectEquals } from 'vs/base/common/objects';
1010
import { URI, UriComponents } from 'vs/base/common/uri';
11-
import { IBulkEditService, ResourceEdit } from 'vs/editor/browser/services/bulkEditService';
11+
import { IBulkEditService, ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService';
1212
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
1313
import { IRange } from 'vs/editor/common/core/range';
1414
import { ISelection } from 'vs/editor/common/core/selection';
@@ -20,7 +20,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
2020
import { IOpenerService } from 'vs/platform/opener/common/opener';
2121
import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/browser/mainThreadDocumentsAndEditors';
2222
import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor';
23-
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, reviveWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
23+
import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, IExtHostContext, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
2424
import { EditorViewColumn, editorGroupToViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
2525
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
2626
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -29,6 +29,23 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
2929
import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith';
3030
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
3131
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
32+
import { revive } from 'vs/base/common/marshalling';
33+
34+
function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] {
35+
if (!data?.edits) {
36+
return [];
37+
}
38+
39+
const result: ResourceEdit[] = [];
40+
for (let edit of revive<IWorkspaceEditDto>(data).edits) {
41+
if (edit._type === WorkspaceEditType.File) {
42+
result.push(new ResourceFileEdit(edit.oldUri, edit.newUri, edit.options, edit.metadata));
43+
} else if (edit._type === WorkspaceEditType.Text) {
44+
result.push(new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata));
45+
}
46+
}
47+
return result;
48+
}
3249

3350
export class MainThreadTextEditors implements MainThreadTextEditorsShape {
3451

@@ -222,8 +239,8 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
222239
}
223240

224241
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise<boolean> {
225-
const { edits } = reviveWorkspaceEditDto(dto)!;
226-
return this._bulkEditService.apply(ResourceEdit.convert({ edits })).then(() => true, _err => false);
242+
const edits = reviveWorkspaceEditDto2(dto);
243+
return this._bulkEditService.apply(edits).then(() => true, _err => false);
227244
}
228245

229246
$tryInsertSnippet(id: string, template: string, ranges: readonly IRange[], opts: IUndoStopOptions): Promise<boolean> {

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,14 +1232,21 @@ export interface IWorkspaceEditEntryMetadataDto {
12321232
iconPath?: { id: string } | UriComponents | { light: UriComponents, dark: UriComponents };
12331233
}
12341234

1235+
export const enum WorkspaceEditType {
1236+
File = 1,
1237+
Text = 2,
1238+
}
1239+
12351240
export interface IWorkspaceFileEditDto {
1241+
_type: WorkspaceEditType.File;
12361242
oldUri?: UriComponents;
12371243
newUri?: UriComponents;
12381244
options?: modes.WorkspaceFileEditOptions
12391245
metadata?: IWorkspaceEditEntryMetadataDto;
12401246
}
12411247

12421248
export interface IWorkspaceTextEditDto {
1249+
_type: WorkspaceEditType.Text;
12431250
resource: UriComponents;
12441251
edit: modes.TextEdit;
12451252
modelVersionId?: number;

src/vs/workbench/api/common/extHostCommands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
141141

142142
try {
143143
const result = await this._proxy.$executeCommand<T>(id, toArgs, retry);
144-
return revive(result);
144+
return revive<any>(result);
145145
} catch (e) {
146146
// Rerun the command when it wasn't known, had arguments, and when retry
147147
// is enabled. We do this because the command might be registered inside

src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { Event } from 'vs/base/common/event';
77
import { URI, UriComponents } from 'vs/base/common/uri';
88
import { illegalState } from 'vs/base/common/errors';
9-
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
9+
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
1010
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
1111
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
1212
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
@@ -146,6 +146,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
146146
if (Array.isArray(value) && (<vscode.TextEdit[]>value).every(e => e instanceof TextEdit)) {
147147
for (const { newText, newEol, range } of value) {
148148
dto.edits.push({
149+
_type: WorkspaceEditType.Text,
149150
resource: document.uri,
150151
edit: {
151152
range: range && Range.from(range),

src/vs/workbench/api/common/extHostTypeConverters.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,9 +513,10 @@ export namespace WorkspaceEdit {
513513
if (value instanceof types.WorkspaceEdit) {
514514
for (let entry of value.allEntries()) {
515515

516-
if (entry._type === 1) {
516+
if (entry._type === types.FileEditType.File) {
517517
// file operation
518518
result.edits.push(<extHostProtocol.IWorkspaceFileEditDto>{
519+
_type: extHostProtocol.WorkspaceEditType.File,
519520
oldUri: entry.from,
520521
newUri: entry.to,
521522
options: entry.options,
@@ -526,6 +527,7 @@ export namespace WorkspaceEdit {
526527
// text edits
527528
const doc = documents?.getDocument(entry.uri);
528529
result.edits.push(<extHostProtocol.IWorkspaceTextEditDto>{
530+
_type: extHostProtocol.WorkspaceEditType.Text,
529531
resource: entry.uri,
530532
edit: TextEdit.from(entry.edit),
531533
modelVersionId: doc?.version,

src/vs/workbench/api/common/extHostTypes.ts

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { coalesce, equals } from 'vs/base/common/arrays';
6+
import { coalesceInPlace, equals } from 'vs/base/common/arrays';
77
import { escapeCodicons } from 'vs/base/common/codicons';
88
import { illegalArgument } from 'vs/base/common/errors';
99
import { IRelativePattern } from 'vs/base/common/glob';
1010
import { isMarkdownString } from 'vs/base/common/htmlContent';
11+
import { ResourceMap } from 'vs/base/common/map';
1112
import { startsWith } from 'vs/base/common/strings';
1213
import { isStringArray } from 'vs/base/common/types';
1314
import { URI } from 'vs/base/common/uri';
@@ -575,16 +576,21 @@ export interface IFileOperationOptions {
575576
recursive?: boolean;
576577
}
577578

579+
export const enum FileEditType {
580+
File = 1,
581+
Text = 2
582+
}
583+
578584
export interface IFileOperation {
579-
_type: 1;
585+
_type: FileEditType.File;
580586
from?: URI;
581587
to?: URI;
582588
options?: IFileOperationOptions;
583589
metadata?: vscode.WorkspaceEditEntryMetadata;
584590
}
585591

586592
export interface IFileTextEdit {
587-
_type: 2;
593+
_type: FileEditType.Text;
588594
uri: URI;
589595
edit: TextEdit;
590596
metadata?: vscode.WorkspaceEditEntryMetadata;
@@ -593,22 +599,31 @@ export interface IFileTextEdit {
593599
@es5ClassCompat
594600
export class WorkspaceEdit implements vscode.WorkspaceEdit {
595601

596-
private _edits = new Array<IFileOperation | IFileTextEdit>();
602+
private readonly _edits = new Array<IFileOperation | IFileTextEdit>();
603+
604+
605+
allEntries(): ReadonlyArray<IFileTextEdit | IFileOperation> {
606+
return this._edits;
607+
}
608+
609+
// --- file
597610

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

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

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

623+
// --- text
624+
610625
replace(uri: URI, range: Range, newText: string, metadata?: vscode.WorkspaceEditEntryMetadata): void {
611-
this._edits.push({ _type: 2, uri, edit: new TextEdit(range, newText), metadata });
626+
this._edits.push({ _type: FileEditType.Text, uri, edit: new TextEdit(range, newText), metadata });
612627
}
613628

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

637+
// --- text (Maplike)
638+
622639
has(uri: URI): boolean {
623-
return this._edits.some(edit => edit._type === 2 && edit.uri.toString() === uri.toString());
640+
return this._edits.some(edit => edit._type === FileEditType.Text && edit.uri.toString() === uri.toString());
624641
}
625642

626643
set(uri: URI, edits: TextEdit[]): void {
627644
if (!edits) {
628645
// remove all text edits for `uri`
629646
for (let i = 0; i < this._edits.length; i++) {
630647
const element = this._edits[i];
631-
if (element._type === 2 && element.uri.toString() === uri.toString()) {
648+
if (element._type === FileEditType.Text && element.uri.toString() === uri.toString()) {
632649
this._edits[i] = undefined!; // will be coalesced down below
633650
}
634651
}
635-
this._edits = coalesce(this._edits);
652+
coalesceInPlace(this._edits);
636653
} else {
637654
// append edit to the end
638655
for (const edit of edits) {
639656
if (edit) {
640-
this._edits.push({ _type: 2, uri, edit });
657+
this._edits.push({ _type: FileEditType.Text, uri, edit });
641658
}
642659
}
643660
}
@@ -646,44 +663,28 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
646663
get(uri: URI): TextEdit[] {
647664
const res: TextEdit[] = [];
648665
for (let candidate of this._edits) {
649-
if (candidate._type === 2 && candidate.uri.toString() === uri.toString()) {
666+
if (candidate._type === FileEditType.Text && candidate.uri.toString() === uri.toString()) {
650667
res.push(candidate.edit);
651668
}
652669
}
653670
return res;
654671
}
655672

656673
entries(): [URI, TextEdit[]][] {
657-
const textEdits = new Map<string, [URI, TextEdit[]]>();
674+
const textEdits = new ResourceMap<[URI, TextEdit[]]>();
658675
for (let candidate of this._edits) {
659-
if (candidate._type === 2) {
660-
let textEdit = textEdits.get(candidate.uri.toString());
676+
if (candidate._type === FileEditType.Text) {
677+
let textEdit = textEdits.get(candidate.uri);
661678
if (!textEdit) {
662679
textEdit = [candidate.uri, []];
663-
textEdits.set(candidate.uri.toString(), textEdit);
680+
textEdits.set(candidate.uri, textEdit);
664681
}
665682
textEdit[1].push(candidate.edit);
666683
}
667684
}
668685
return [...textEdits.values()];
669686
}
670687

671-
allEntries(): ReadonlyArray<IFileTextEdit | IFileOperation> {
672-
return this._edits;
673-
}
674-
675-
// _allEntries(): ([URI, TextEdit] | [URI?, URI?, IFileOperationOptions?])[] {
676-
// const res: ([URI, TextEdit] | [URI?, URI?, IFileOperationOptions?])[] = [];
677-
// for (let edit of this._edits) {
678-
// if (edit._type === 1) {
679-
// res.push([edit.from, edit.to, edit.options]);
680-
// } else {
681-
// res.push([edit.uri, edit.edit]);
682-
// }
683-
// }
684-
// return res;
685-
// }
686-
687688
get size(): number {
688689
return this.entries().length;
689690
}

src/vs/workbench/test/browser/api/extHostTextEditors.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
*--------------------------------------------------------------------------------------------*/
55
import * as assert from 'assert';
66
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
7-
import { MainContext, MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
7+
import { MainContext, MainThreadTextEditorsShape, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
88
import { URI } from 'vs/base/common/uri';
99
import { mock } from 'vs/base/test/common/mock';
1010
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
1111
import { SingleProxyRPCProtocol, TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
1212
import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors';
13-
import { WorkspaceTextEdit } from 'vs/editor/common/modes';
1413
import { NullLogService } from 'vs/platform/log/common/log';
14+
import { assertType } from 'vs/base/common/types';
1515

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

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

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

6266
});

src/vs/workbench/test/browser/api/extHostTypes.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,17 +388,17 @@ suite('ExtHostTypes', function () {
388388
assert.equal(all.length, 4);
389389

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

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

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

401-
assertType(fourth._type === 2);
401+
assertType(fourth._type === types.FileEditType.Text);
402402
assert.equal(fourth.uri.toString(), 'foo:b');
403403
});
404404

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

414-
assertType(first._type === 2);
415-
assertType(second._type === 2);
414+
assertType(first._type === types.FileEditType.Text);
415+
assertType(second._type === types.FileEditType.Text);
416416
assert.equal(first.edit.newText, 'Hello');
417417
assert.equal(second.edit.newText, 'Foo');
418418
});

src/vs/workbench/test/browser/api/mainThreadEditors.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
1010
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
1111
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
1212
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
13-
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape, IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
13+
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape, IWorkspaceTextEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol';
1414
import { mock } from 'vs/base/test/common/mock';
1515
import { Event } from 'vs/base/common/event';
1616
import { MainThreadTextEditors } from 'vs/workbench/api/browser/mainThreadEditors';
@@ -170,6 +170,7 @@ suite('MainThreadEditors', () => {
170170
let model = modelService.createModel('something', null, resource);
171171

172172
let workspaceResourceEdit: IWorkspaceTextEditDto = {
173+
_type: WorkspaceEditType.Text,
173174
resource: resource,
174175
modelVersionId: model.getVersionId(),
175176
edit: {
@@ -191,6 +192,7 @@ suite('MainThreadEditors', () => {
191192
let model = modelService.createModel('something', null, resource);
192193

193194
let workspaceResourceEdit1: IWorkspaceTextEditDto = {
195+
_type: WorkspaceEditType.Text,
194196
resource: resource,
195197
modelVersionId: model.getVersionId(),
196198
edit: {
@@ -199,6 +201,7 @@ suite('MainThreadEditors', () => {
199201
}
200202
};
201203
let workspaceResourceEdit2: IWorkspaceTextEditDto = {
204+
_type: WorkspaceEditType.Text,
202205
resource: resource,
203206
modelVersionId: model.getVersionId(),
204207
edit: {
@@ -221,9 +224,9 @@ suite('MainThreadEditors', () => {
221224
test(`applyWorkspaceEdit with only resource edit`, () => {
222225
return editors.$tryApplyWorkspaceEdit({
223226
edits: [
224-
{ oldUri: resource, newUri: resource, options: undefined },
225-
{ oldUri: undefined, newUri: resource, options: undefined },
226-
{ oldUri: resource, newUri: undefined, options: undefined }
227+
{ _type: WorkspaceEditType.File, oldUri: resource, newUri: resource, options: undefined },
228+
{ _type: WorkspaceEditType.File, oldUri: undefined, newUri: resource, options: undefined },
229+
{ _type: WorkspaceEditType.File, oldUri: resource, newUri: undefined, options: undefined }
227230
]
228231
}).then((result) => {
229232
assert.equal(result, true);

0 commit comments

Comments
 (0)