Skip to content

Commit 50e742c

Browse files
committed
Always prompt when splitting a workspace stack element
1 parent 58aa111 commit 50e742c

1 file changed

Lines changed: 63 additions & 13 deletions

File tree

src/vs/platform/undoRedo/common/undoRedoService.ts

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,55 @@ class ResourceStackElement {
3333
this.strResources = [this.strResource];
3434
}
3535
}
36+
37+
const enum RemovedResourceReason {
38+
ExternalRemoval = 0,
39+
NoParallelUniverses = 1
40+
}
41+
42+
class RemovedResources {
43+
public readonly set: Set<string> = new Set<string>();
44+
public readonly reason: [URI[], URI[]] = [[], []];
45+
46+
public createMessage(): string {
47+
let messages: string[] = [];
48+
if (this.reason[RemovedResourceReason.ExternalRemoval].length > 0) {
49+
const paths = this.reason[RemovedResourceReason.ExternalRemoval].map(uri => uri.scheme === Schemas.file ? uri.fsPath : uri.path);
50+
messages.push(nls.localize('externalRemoval', "The following files have been closed: {0}.", paths.join(', ')));
51+
}
52+
if (this.reason[RemovedResourceReason.NoParallelUniverses].length > 0) {
53+
const paths = this.reason[RemovedResourceReason.NoParallelUniverses].map(uri => uri.scheme === Schemas.file ? uri.fsPath : uri.path);
54+
messages.push(nls.localize('noParallelUniverses', "The following files have been modified in an incompatible way: {0}.", paths.join(', ')));
55+
}
56+
return messages.join('\n');
57+
}
58+
}
59+
3660
class WorkspaceStackElement {
3761
public readonly type = UndoRedoElementType.Workspace;
3862
public readonly actual: IWorkspaceUndoRedoElement;
3963
public readonly label: string;
4064

4165
public readonly resources: URI[];
4266
public readonly strResources: string[];
67+
public removedResources: RemovedResources | null;
4368

4469
constructor(actual: IWorkspaceUndoRedoElement) {
4570
this.actual = actual;
4671
this.label = actual.label;
4772
this.resources = actual.resources.slice(0);
4873
this.strResources = this.resources.map(resource => uriGetComparisonKey(resource));
74+
this.removedResources = null;
75+
}
76+
77+
public removeResource(resource: URI, strResource: string, reason: RemovedResourceReason): void {
78+
if (!this.removedResources) {
79+
this.removedResources = new RemovedResources();
80+
}
81+
if (!this.removedResources.set.has(strResource)) {
82+
this.removedResources.set.add(strResource);
83+
this.removedResources.reason[reason].push(resource);
84+
}
4985
}
5086
}
5187
type StackElement = ResourceStackElement | WorkspaceStackElement;
@@ -91,7 +127,7 @@ export class UndoRedoService implements IUndoRedoService {
91127
// remove the future
92128
for (const futureElement of editStack.future) {
93129
if (futureElement.type === UndoRedoElementType.Workspace) {
94-
this._splitFutureWorkspaceElement(futureElement, strResource);
130+
futureElement.removeResource(resource, strResource, RemovedResourceReason.NoParallelUniverses);
95131
}
96132
}
97133
editStack.future = [];
@@ -114,7 +150,7 @@ export class UndoRedoService implements IUndoRedoService {
114150
return null;
115151
}
116152

117-
private _splitPastWorkspaceElement(toRemove: WorkspaceStackElement, ignoreStrResource: string | null): void {
153+
private _splitPastWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: Set<string> | null): void {
118154
const individualArr = toRemove.actual.split();
119155
const individualMap = new Map<string, ResourceStackElement>();
120156
for (const _element of individualArr) {
@@ -123,7 +159,7 @@ export class UndoRedoService implements IUndoRedoService {
123159
}
124160

125161
for (const strResource of toRemove.strResources) {
126-
if (strResource === ignoreStrResource) {
162+
if (ignoreResources && ignoreResources.has(strResource)) {
127163
continue;
128164
}
129165
const editStack = this._editStacks.get(strResource)!;
@@ -142,7 +178,7 @@ export class UndoRedoService implements IUndoRedoService {
142178
}
143179
}
144180

145-
private _splitFutureWorkspaceElement(toRemove: WorkspaceStackElement, ignoreStrResource: string | null): void {
181+
private _splitFutureWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: Set<string> | null): void {
146182
const individualArr = toRemove.actual.split();
147183
const individualMap = new Map<string, ResourceStackElement>();
148184
for (const _element of individualArr) {
@@ -151,7 +187,7 @@ export class UndoRedoService implements IUndoRedoService {
151187
}
152188

153189
for (const strResource of toRemove.strResources) {
154-
if (strResource === ignoreStrResource) {
190+
if (ignoreResources && ignoreResources.has(strResource)) {
155191
continue;
156192
}
157193
const editStack = this._editStacks.get(strResource)!;
@@ -174,14 +210,14 @@ export class UndoRedoService implements IUndoRedoService {
174210
const strResource = uriGetComparisonKey(resource);
175211
if (this._editStacks.has(strResource)) {
176212
const editStack = this._editStacks.get(strResource)!;
177-
for (const pastElement of editStack.past) {
178-
if (pastElement.type === UndoRedoElementType.Workspace) {
179-
this._splitPastWorkspaceElement(pastElement, strResource);
213+
for (const element of editStack.past) {
214+
if (element.type === UndoRedoElementType.Workspace) {
215+
element.removeResource(resource, strResource, RemovedResourceReason.ExternalRemoval);
180216
}
181217
}
182-
for (const futureElement of editStack.future) {
183-
if (futureElement.type === UndoRedoElementType.Workspace) {
184-
this._splitFutureWorkspaceElement(futureElement, strResource);
218+
for (const element of editStack.future) {
219+
if (element.type === UndoRedoElementType.Workspace) {
220+
element.removeResource(resource, strResource, RemovedResourceReason.ExternalRemoval);
185221
}
186222
}
187223
this._editStacks.delete(strResource);
@@ -220,6 +256,13 @@ export class UndoRedoService implements IUndoRedoService {
220256
}
221257

222258
private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
259+
if (element.removedResources) {
260+
this._splitPastWorkspaceElement(element, element.removedResources.set);
261+
const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
262+
this._notificationService.info(message);
263+
return;
264+
}
265+
223266
// this must be the last past element in all the impacted resources!
224267
let affectedEditStacks: ResourceEditStack[] = [];
225268
for (const strResource of element.strResources) {
@@ -236,7 +279,7 @@ export class UndoRedoService implements IUndoRedoService {
236279
if (cannotUndoDueToResources.length > 0) {
237280
this._splitPastWorkspaceElement(element, null);
238281
const paths = cannotUndoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
239-
const message = nls.localize('undoFurtherChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
282+
const message = nls.localize('cannotWorkspaceUndoDueToChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
240283
this._notificationService.info(message);
241284
return;
242285
}
@@ -297,6 +340,13 @@ export class UndoRedoService implements IUndoRedoService {
297340
}
298341

299342
private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
343+
if (element.removedResources) {
344+
this._splitFutureWorkspaceElement(element, element.removedResources.set);
345+
const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
346+
this._notificationService.info(message);
347+
return;
348+
}
349+
300350
// this must be the last future element in all the impacted resources!
301351
let affectedEditStacks: ResourceEditStack[] = [];
302352
for (const strResource of element.strResources) {
@@ -313,7 +363,7 @@ export class UndoRedoService implements IUndoRedoService {
313363
if (cannotRedoDueToResources.length > 0) {
314364
this._splitFutureWorkspaceElement(element, null);
315365
const paths = cannotRedoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
316-
const message = nls.localize('redoFurtherChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
366+
const message = nls.localize('cannotWorkspaceRedoDueToChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
317367
this._notificationService.info(message);
318368
return;
319369
}

0 commit comments

Comments
 (0)