Skip to content

Commit 146115b

Browse files
authored
Merge pull request microsoft#74231 from microsoft/rebornix/bettermerge
Show context for diff view of merge conflict and introduce compareAll.
2 parents 2197cd0 + c3fe962 commit 146115b

4 files changed

Lines changed: 70 additions & 7 deletions

File tree

extensions/merge-conflict/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@
114114
"type": "boolean",
115115
"description": "%config.autoNavigateNextConflictEnabled%",
116116
"default": false
117+
},
118+
"merge-conflict.diffViewPosition": {
119+
"type": "string",
120+
"enum": [
121+
"Current",
122+
"Beside",
123+
"Below"
124+
],
125+
"description": "%config.diffViewPosition%",
126+
"default": "Current"
117127
}
118128
}
119129
}

extensions/merge-conflict/package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"config.title": "Merge Conflict",
1616
"config.autoNavigateNextConflictEnabled": "Whether to automatically navigate to the next merge conflict after resolving a merge conflict.",
1717
"config.codeLensEnabled": "Create a Code Lens for merge conflict blocks within editor.",
18-
"config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor."
18+
"config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor.",
19+
"config.diffViewPosition": "Controls where the diff view should be opened when comparing changes in merge conflicts."
1920
}

extensions/merge-conflict/src/commandHandler.ts

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,54 @@ export default class CommandHandler implements vscode.Disposable {
8888
}
8989
}
9090

91+
const conflicts = await this.tracker.getConflicts(editor.document);
92+
93+
// Still failed to find conflict, warn the user and exit
94+
if (!conflicts) {
95+
vscode.window.showWarningMessage(localize('cursorNotInConflict', 'Editor cursor is not within a merge conflict'));
96+
return;
97+
}
98+
9199
const scheme = editor.document.uri.scheme;
92100
let range = conflict.current.content;
101+
let leftRanges = conflicts.map(conflict => [conflict.current.content, conflict.range]);
102+
let rightRanges = conflicts.map(conflict => [conflict.incoming.content, conflict.range]);
103+
93104
const leftUri = editor.document.uri.with({
94105
scheme: ContentProvider.scheme,
95-
query: JSON.stringify({ scheme, range })
106+
query: JSON.stringify({ scheme, range: range, ranges: leftRanges })
96107
});
97108

109+
98110
range = conflict.incoming.content;
99-
const rightUri = leftUri.with({ query: JSON.stringify({ scheme, range }) });
111+
const rightUri = leftUri.with({ query: JSON.stringify({ scheme, ranges: rightRanges }) });
112+
113+
let mergeConflictLineOffsets = 0;
114+
for (let nextconflict of conflicts) {
115+
if (nextconflict.range.isEqual(conflict.range)) {
116+
break;
117+
} else {
118+
mergeConflictLineOffsets += (nextconflict.range.end.line - nextconflict.range.start.line) - (nextconflict.incoming.content.end.line - nextconflict.incoming.content.start.line);
119+
}
120+
}
121+
const selection = new vscode.Range(
122+
conflict.range.start.line - mergeConflictLineOffsets, conflict.range.start.character,
123+
conflict.range.start.line - mergeConflictLineOffsets, conflict.range.start.character
124+
);
100125

101126
const title = localize('compareChangesTitle', '{0}: Current Changes ⟷ Incoming Changes', fileName);
102-
vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);
127+
const mergeConflictConfig = vscode.workspace.getConfiguration('merge-conflict');
128+
const openToTheSide = mergeConflictConfig.get<string>('diffViewPosition');
129+
const opts: vscode.TextDocumentShowOptions = {
130+
viewColumn: openToTheSide === 'Beside' ? vscode.ViewColumn.Beside : vscode.ViewColumn.Active,
131+
selection
132+
};
133+
134+
if (openToTheSide === 'Below') {
135+
await vscode.commands.executeCommand('workbench.action.newGroupBelow');
136+
}
137+
138+
await vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title, opts);
103139
}
104140

105141
navigateNext(editor: vscode.TextEditor): Promise<void> {

extensions/merge-conflict/src/contentProvider.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,27 @@ export default class MergeConflictContentProvider implements vscode.TextDocument
2323

2424
async provideTextDocumentContent(uri: vscode.Uri): Promise<string | null> {
2525
try {
26-
const { scheme, range } = JSON.parse(uri.query) as { scheme: string; range: { line: number, character: number }[] };
27-
const [start, end] = range;
26+
const { scheme, ranges } = JSON.parse(uri.query) as { scheme: string, ranges: [{ line: number, character: number }[], { line: number, character: number }[]][] };
2827

28+
// complete diff
2929
const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' }));
30-
const text = document.getText(new vscode.Range(start.line, start.character, end.line, end.character));
30+
31+
let text = '';
32+
let lastPosition = new vscode.Position(0, 0);
33+
34+
ranges.forEach(rangeObj => {
35+
let [conflictRange, fullRange] = rangeObj;
36+
const [start, end] = conflictRange;
37+
const [fullStart, fullEnd] = fullRange;
38+
39+
text += document.getText(new vscode.Range(lastPosition.line, lastPosition.character, fullStart.line, fullStart.character));
40+
text += document.getText(new vscode.Range(start.line, start.character, end.line, end.character));
41+
lastPosition = new vscode.Position(fullEnd.line, fullEnd.character);
42+
});
43+
44+
let documentEnd = document.lineAt(document.lineCount - 1).range.end;
45+
text += document.getText(new vscode.Range(lastPosition.line, lastPosition.character, documentEnd.line, documentEnd.character));
46+
3147
return text;
3248
}
3349
catch (ex) {

0 commit comments

Comments
 (0)