Skip to content

Commit fa69b4e

Browse files
committed
Show context for diff view of merge conflict and introduce compareAll.
1 parent 7b078e1 commit fa69b4e

5 files changed

Lines changed: 83 additions & 10 deletions

File tree

extensions/merge-conflict/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@
8181
"title": "%command.compare%",
8282
"original": "Compare Current Conflict",
8383
"command": "merge-conflict.compare"
84+
},
85+
{
86+
"category": "%command.category%",
87+
"title": "%command.compareAll%",
88+
"original": "Compare All Conflict in Current Editor",
89+
"command": "merge-conflict.compareAll"
8490
}
8591
],
8692
"menus": {
@@ -114,6 +120,11 @@
114120
"type": "boolean",
115121
"description": "%config.autoNavigateNextConflictEnabled%",
116122
"default": false
123+
},
124+
"merge-conflict.diffViewContext": {
125+
"type": "number",
126+
"description": "%config.diffViewContext%",
127+
"default": 0
117128
}
118129
}
119130
}

extensions/merge-conflict/package.nls.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
"command.next": "Next Conflict",
1313
"command.previous": "Previous Conflict",
1414
"command.compare": "Compare Current Conflict",
15+
"command.compareAll": "Compare All Conflict in Current Editor",
1516
"config.title": "Merge Conflict",
1617
"config.autoNavigateNextConflictEnabled": "Whether to automatically navigate to the next merge conflict after resolving a merge conflict.",
1718
"config.codeLensEnabled": "Create a Code Lens for merge conflict blocks within editor.",
18-
"config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor."
19+
"config.decoratorsEnabled": "Create decorators for merge conflict blocks within editor.",
20+
"config.diffViewContext": "Controls how many unchanged lines around the merge conflict should be displayed in the diff view."
1921
}

extensions/merge-conflict/src/codelensProvider.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,17 @@ export default class MergeConflictCodeLensProvider implements vscode.CodeLensPro
8585
arguments: [conflict]
8686
};
8787

88+
let diffAllCommand: vscode.Command = {
89+
command: 'merge-conflict.compareAll',
90+
title: localize('compareAllChanges', 'Compare All Changes')
91+
};
92+
8893
items.push(
8994
new vscode.CodeLens(conflict.range, acceptCurrentCommand),
9095
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 1 })), acceptIncomingCommand),
9196
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 2 })), acceptBothCommand),
92-
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 3 })), diffCommand)
97+
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 3 })), diffCommand),
98+
new vscode.CodeLens(conflict.range.with(conflict.range.start.with({ character: conflict.range.start.character + 4 })), diffAllCommand)
9399
);
94100
});
95101

extensions/merge-conflict/src/commandHandler.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ export default class CommandHandler implements vscode.Disposable {
3939
this.registerTextEditorCommand('merge-conflict.accept.all-both', this.acceptAllBoth),
4040
this.registerTextEditorCommand('merge-conflict.next', this.navigateNext),
4141
this.registerTextEditorCommand('merge-conflict.previous', this.navigatePrevious),
42-
this.registerTextEditorCommand('merge-conflict.compare', this.compare)
42+
this.registerTextEditorCommand('merge-conflict.compare', this.compare),
43+
this.registerTextEditorCommand('merge-conflict.compareAll', this.compareAll)
4344
);
4445
}
4546

@@ -92,11 +93,36 @@ export default class CommandHandler implements vscode.Disposable {
9293
let range = conflict.current.content;
9394
const leftUri = editor.document.uri.with({
9495
scheme: ContentProvider.scheme,
95-
query: JSON.stringify({ scheme, range })
96+
query: JSON.stringify({ scheme, range, fullRange: conflict.range })
9697
});
9798

9899
range = conflict.incoming.content;
99-
const rightUri = leftUri.with({ query: JSON.stringify({ scheme, range }) });
100+
const rightUri = leftUri.with({ query: JSON.stringify({ scheme, range, fullRange: conflict.range }) });
101+
102+
const title = localize('compareChangesTitle', '{0}: Current Changes ⟷ Incoming Changes', fileName);
103+
vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);
104+
}
105+
106+
async compareAll(editor: vscode.TextEditor) {
107+
const fileName = path.basename(editor.document.uri.fsPath);
108+
const conflicts = await this.tracker.getConflicts(editor.document);
109+
110+
// Still failed to find conflict, warn the user and exit
111+
if (!conflicts) {
112+
vscode.window.showWarningMessage(localize('cursorNotInConflict', 'Editor cursor is not within a merge conflict'));
113+
return;
114+
}
115+
116+
const scheme = editor.document.uri.scheme;
117+
let leftRanges = conflicts.map(conflict => [conflict.current.content, conflict.range]);
118+
let rightRanges = conflicts.map(conflict => [conflict.incoming.content, conflict.range]);
119+
120+
const leftUri = editor.document.uri.with({
121+
scheme: ContentProvider.scheme,
122+
query: JSON.stringify({ type: 'full', scheme, ranges: leftRanges })
123+
});
124+
125+
const rightUri = leftUri.with({ query: JSON.stringify({ type: 'full', scheme, ranges: rightRanges }) });
100126

101127
const title = localize('compareChangesTitle', '{0}: Current Changes ⟷ Incoming Changes', fileName);
102128
vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);

extensions/merge-conflict/src/contentProvider.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,40 @@ 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 { 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 }[]][] };
2827

29-
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));
31-
return text;
28+
if (type === 'full') {
29+
// complete diff
30+
const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' }));
31+
32+
let text = '';
33+
let lastPosition = new vscode.Position(0, 0);
34+
ranges.forEach(rangeObj => {
35+
let [range, fullRange] = rangeObj;
36+
const [start, end] = range;
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+
47+
return text;
48+
} else {
49+
const [start, end] = range;
50+
const [fullStart, fullEnd] = fullRange;
51+
const mergeConflictConfig = vscode.workspace.getConfiguration('merge-conflict');
52+
const context = Math.max(0, mergeConflictConfig.get<number>('diffViewContext') || 0);
53+
const document = await vscode.workspace.openTextDocument(uri.with({ scheme, query: '' }));
54+
const text =
55+
document.getText(new vscode.Range(Math.max(0, fullStart.line - context), 0, fullStart.line, fullStart.character))
56+
+ document.getText(new vscode.Range(start.line, start.character, end.line, end.character))
57+
+ document.getText(new vscode.Range(fullEnd.line, fullEnd.character, Math.min(document.lineCount, fullEnd.line + context + 1), 0));
58+
return text;
59+
}
3260
}
3361
catch (ex) {
3462
await vscode.window.showErrorMessage('Unable to show comparison');

0 commit comments

Comments
 (0)