Fix: Accept All Current/Incoming for multiple files (fixes #63621)

This commit is contained in:
Christof Marti 2019-07-01 16:15:37 +02:00
parent d722d9a1a2
commit 039a49a5ea
3 changed files with 45 additions and 13 deletions

View file

@ -34,8 +34,8 @@ export default class CommandHandler implements vscode.Disposable {
this.registerTextEditorCommand('merge-conflict.accept.incoming', this.acceptIncoming),
this.registerTextEditorCommand('merge-conflict.accept.selection', this.acceptSelection),
this.registerTextEditorCommand('merge-conflict.accept.both', this.acceptBoth),
this.registerTextEditorCommand('merge-conflict.accept.all-current', this.acceptAllCurrent),
this.registerTextEditorCommand('merge-conflict.accept.all-incoming', this.acceptAllIncoming),
this.registerTextEditorCommand('merge-conflict.accept.all-current', this.acceptAllCurrent, this.acceptAllCurrentResources),
this.registerTextEditorCommand('merge-conflict.accept.all-incoming', this.acceptAllIncoming, this.acceptAllIncomingResources),
this.registerTextEditorCommand('merge-conflict.accept.all-both', this.acceptAllBoth),
this.registerTextEditorCommand('merge-conflict.next', this.navigateNext),
this.registerTextEditorCommand('merge-conflict.previous', this.navigatePrevious),
@ -43,8 +43,11 @@ export default class CommandHandler implements vscode.Disposable {
);
}
private registerTextEditorCommand(command: string, cb: (editor: vscode.TextEditor, ...args: any[]) => Promise<void>) {
private registerTextEditorCommand(command: string, cb: (editor: vscode.TextEditor, ...args: any[]) => Promise<void>, resourceCB?: (uris: vscode.Uri[]) => Promise<void>) {
return vscode.commands.registerCommand(command, (...args) => {
if (resourceCB && args.length && args.every(arg => arg && arg.resourceUri)) {
return resourceCB.call(this, args.map(arg => arg.resourceUri));
}
const editor = vscode.window.activeTextEditor;
return editor && cb.call(this, editor, ...args);
});
@ -70,6 +73,14 @@ export default class CommandHandler implements vscode.Disposable {
return this.acceptAll(interfaces.CommitType.Incoming, editor);
}
acceptAllCurrentResources(resources: vscode.Uri[]): Promise<void> {
return this.acceptAllResources(interfaces.CommitType.Current, resources);
}
acceptAllIncomingResources(resources: vscode.Uri[]): Promise<void> {
return this.acceptAllResources(interfaces.CommitType.Incoming, resources);
}
acceptAllBoth(editor: vscode.TextEditor): Promise<void> {
return this.acceptAll(interfaces.CommitType.Both, editor);
}
@ -259,10 +270,31 @@ export default class CommandHandler implements vscode.Disposable {
// Apply all changes as one edit
await editor.edit((edit) => conflicts.forEach(conflict => {
conflict.applyEdit(type, editor, edit);
conflict.applyEdit(type, editor.document, edit);
}));
}
private async acceptAllResources(type: interfaces.CommitType, resources: vscode.Uri[]): Promise<void> {
const documents = await Promise.all(resources.map(resource => vscode.workspace.openTextDocument(resource)));
const edit = new vscode.WorkspaceEdit();
for (const document of documents) {
const conflicts = await this.tracker.getConflicts(document);
if (!conflicts || conflicts.length === 0) {
continue;
}
// For get the current state of the document, as we know we are doing to do a large edit
this.tracker.forget(document);
// Apply all changes as one edit
conflicts.forEach(conflict => {
conflict.applyEdit(type, document, { replace: (range, newText) => edit.replace(document.uri, range, newText) });
});
}
vscode.workspace.applyEdit(edit);
}
private async findConflictContainingSelection(editor: vscode.TextEditor, conflicts?: interfaces.IDocumentMergeConflict[]): Promise<interfaces.IDocumentMergeConflict | null> {
if (!conflicts) {

View file

@ -25,14 +25,14 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict
if (edit) {
this.applyEdit(type, editor, edit);
this.applyEdit(type, editor.document, edit);
return Promise.resolve(true);
}
return editor.edit((edit) => this.applyEdit(type, editor, edit));
return editor.edit((edit) => this.applyEdit(type, editor.document, edit));
}
public applyEdit(type: interfaces.CommitType, editor: vscode.TextEditor, edit: vscode.TextEditorEdit): void {
public applyEdit(type: interfaces.CommitType, document: vscode.TextDocument, edit: { replace(range: vscode.Range, newText: string): void; }): void {
// Each conflict is a set of ranges as follows, note placements or newlines
// which may not in in spans
@ -45,24 +45,24 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict
// ]
if (type === interfaces.CommitType.Current) {
// Replace [ Conflict Range ] with [ Current Content ]
let content = editor.document.getText(this.current.content);
let content = document.getText(this.current.content);
this.replaceRangeWithContent(content, edit);
}
else if (type === interfaces.CommitType.Incoming) {
let content = editor.document.getText(this.incoming.content);
let content = document.getText(this.incoming.content);
this.replaceRangeWithContent(content, edit);
}
else if (type === interfaces.CommitType.Both) {
// Replace [ Conflict Range ] with [ Current Content ] + \n + [ Incoming Content ]
const currentContent = editor.document.getText(this.current.content);
const incomingContent = editor.document.getText(this.incoming.content);
const currentContent = document.getText(this.current.content);
const incomingContent = document.getText(this.incoming.content);
edit.replace(this.range, currentContent.concat(incomingContent));
}
}
private replaceRangeWithContent(content: string, edit: vscode.TextEditorEdit) {
private replaceRangeWithContent(content: string, edit: { replace(range: vscode.Range, newText: string): void; }) {
if (this.isNewlineOnly(content)) {
edit.replace(this.range, '');
return;

View file

@ -25,7 +25,7 @@ export interface IExtensionConfiguration {
export interface IDocumentMergeConflict extends IDocumentMergeConflictDescriptor {
commitEdit(type: CommitType, editor: vscode.TextEditor, edit?: vscode.TextEditorEdit): Thenable<boolean>;
applyEdit(type: CommitType, editor: vscode.TextEditor, edit: vscode.TextEditorEdit): void;
applyEdit(type: CommitType, document: vscode.TextDocument, edit: { replace(range: vscode.Range, newText: string): void; }): void;
}
export interface IDocumentMergeConflictDescriptor {