Show context for diff view of merge conflict and introduce compareAll.

This commit is contained in:
Peng Lyu 2019-05-23 14:19:09 -07:00
parent 7b078e1165
commit fa69b4e7d6
5 changed files with 83 additions and 10 deletions

View file

@ -81,6 +81,12 @@
"title": "%command.compare%",
"original": "Compare Current Conflict",
"command": "merge-conflict.compare"
},
{
"category": "%command.category%",
"title": "%command.compareAll%",
"original": "Compare All Conflict in Current Editor",
"command": "merge-conflict.compareAll"
}
],
"menus": {
@ -114,6 +120,11 @@
"type": "boolean",
"description": "%config.autoNavigateNextConflictEnabled%",
"default": false
},
"merge-conflict.diffViewContext": {
"type": "number",
"description": "%config.diffViewContext%",
"default": 0
}
}
}

View file

@ -12,8 +12,10 @@
"command.next": "Next Conflict",
"command.previous": "Previous Conflict",
"command.compare": "Compare Current Conflict",
"command.compareAll": "Compare All Conflict in Current Editor",
"config.title": "Merge Conflict",
"config.autoNavigateNextConflictEnabled": "Whether to automatically navigate to the next merge conflict after resolving a merge conflict.",
"config.codeLensEnabled": "Create a Code Lens for merge conflict blocks within editor.",
"config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor."
"config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor.",
"config.diffViewContext": "Controls how many unchanged lines around the merge conflict should be displayed in the diff view."
}

View file

@ -85,11 +85,17 @@ export default class MergeConflictCodeLensProvider implements vscode.CodeLensPro
arguments: [conflict]
};
let diffAllCommand: vscode.Command = {
command: 'merge-conflict.compareAll',
title: localize('compareAllChanges', 'Compare All Changes')
};
items.push(
new vscode.CodeLens(conflict.range, acceptCurrentCommand),
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 1 })), acceptIncomingCommand),
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 2 })), acceptBothCommand),
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 3 })), diffCommand)
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 3 })), diffCommand),
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 4 })), diffAllCommand)
);
});

View file

@ -39,7 +39,8 @@ export default class CommandHandler implements vscode.Disposable {
this.registerTextEditorCommand('merge-conflict.accept.all-both', this.acceptAllBoth),
this.registerTextEditorCommand('merge-conflict.next', this.navigateNext),
this.registerTextEditorCommand('merge-conflict.previous', this.navigatePrevious),
this.registerTextEditorCommand('merge-conflict.compare', this.compare)
this.registerTextEditorCommand('merge-conflict.compare', this.compare),
this.registerTextEditorCommand('merge-conflict.compareAll', this.compareAll)
);
}
@ -92,11 +93,36 @@ export default class CommandHandler implements vscode.Disposable {
let range = conflict.current.content;
const leftUri = editor.document.uri.with({
scheme: ContentProvider.scheme,
query: JSON.stringify({ scheme, range })
query: JSON.stringify({ scheme, range, fullRange: conflict.range })
});
range = conflict.incoming.content;
const rightUri = leftUri.with({ query: JSON.stringify({ scheme, range }) });
const rightUri = leftUri.with({ query: JSON.stringify({ scheme, range, fullRange: conflict.range }) });
const title = localize('compareChangesTitle', '{0}: Current Changes ⟷ Incoming Changes', fileName);
vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);
}
async compareAll(editor: vscode.TextEditor) {
const fileName = path.basename(editor.document.uri.fsPath);
const conflicts = await this.tracker.getConflicts(editor.document);
// Still failed to find conflict, warn the user and exit
if (!conflicts) {
vscode.window.showWarningMessage(localize('cursorNotInConflict', 'Editor cursor is not within a merge conflict'));
return;
}
const scheme = editor.document.uri.scheme;
let leftRanges = conflicts.map(conflict => [conflict.current.content, conflict.range]);
let rightRanges = conflicts.map(conflict => [conflict.incoming.content, conflict.range]);
const leftUri = editor.document.uri.with({
scheme: ContentProvider.scheme,
query: JSON.stringify({ type: 'full', scheme, ranges: leftRanges })
});
const rightUri = leftUri.with({ query: JSON.stringify({ type: 'full', scheme, ranges: rightRanges }) });
const title = localize('compareChangesTitle', '{0}: Current Changes ⟷ Incoming Changes', fileName);
vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);

View file

@ -23,12 +23,40 @@ export default class MergeConflictContentProvider implements vscode.TextDocument
async provideTextDocumentContent(uri: vscode.Uri): Promise<string | null> {
try {
const { scheme, range } = JSON.parse(uri.query) as { scheme: string; range: { line: number, character: number }[] };
const [start, end] = range;
const { type, scheme, range, fullRange, ranges } = JSON.parse(uri.query) as { type: string, scheme: string; range: { line: number, character: number }[], fullRange: { line: number, character: number }[], ranges: [{ line: number, character: number }[], { line: number, character: number }[]][] };
const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' }));
const text = document.getText(new vscode.Range(start.line, start.character, end.line, end.character));
return text;
if (type === 'full') {
// complete diff
const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' }));
let text = '';
let lastPosition = new vscode.Position(0, 0);
ranges.forEach(rangeObj => {
let [range, fullRange] = rangeObj;
const [start, end] = range;
const [fullStart, fullEnd] = fullRange;
text += document.getText(new vscode.Range(lastPosition.line, lastPosition.character, fullStart.line, fullStart.character));
text += document.getText(new vscode.Range(start.line, start.character, end.line, end.character));
lastPosition = new vscode.Position(fullEnd.line, fullEnd.character);
});
let documentEnd = document.lineAt(document.lineCount - 1).range.end;
text += document.getText(new vscode.Range(lastPosition.line, lastPosition.character, documentEnd.line, documentEnd.character));
return text;
} else {
const [start, end] = range;
const [fullStart, fullEnd] = fullRange;
const mergeConflictConfig = vscode.workspace.getConfiguration('merge-conflict');
const context = Math.max(0, mergeConflictConfig.get<number>('diffViewContext') || 0);
const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' }));
const text =
document.getText(new vscode.Range(Math.max(0, fullStart.line - context), 0, fullStart.line, fullStart.character))
+ document.getText(new vscode.Range(start.line, start.character, end.line, end.character))
+ document.getText(new vscode.Range(fullEnd.line, fullEnd.character, Math.min(document.lineCount, fullEnd.line + context + 1), 0));
return text;
}
}
catch (ex) {
await vscode.window.showErrorMessage('Unable to show comparison');