Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/merge-conflict/src/documentMergeConflict.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import * as interfaces from './interfaces';
6
import * as vscode from 'vscode';
7
import type TelemetryReporter from '@vscode/extension-telemetry';
8
9
export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict {
10
11
public range: vscode.Range;
12
public current: interfaces.IMergeRegion;
13
public incoming: interfaces.IMergeRegion;
14
public commonAncestors: interfaces.IMergeRegion[];
15
public splitter: vscode.Range;
16
private applied = false;
17
18
constructor(descriptor: interfaces.IDocumentMergeConflictDescriptor, private readonly telemetryReporter: TelemetryReporter) {
19
this.range = descriptor.range;
20
this.current = descriptor.current;
21
this.incoming = descriptor.incoming;
22
this.commonAncestors = descriptor.commonAncestors;
23
this.splitter = descriptor.splitter;
24
}
25
26
public commitEdit(type: interfaces.CommitType, editor: vscode.TextEditor, edit?: vscode.TextEditorEdit): Thenable<boolean> {
27
function commitTypeToString(type: interfaces.CommitType): string {
28
switch (type) {
29
case interfaces.CommitType.Current:
30
return 'current';
31
case interfaces.CommitType.Incoming:
32
return 'incoming';
33
case interfaces.CommitType.Both:
34
return 'both';
35
}
36
}
37
38
/* __GDPR__
39
"mergeMarkers.accept" : {
40
"owner": "hediet",
41
"comment": "Used to understand how the inline merge editor experience is used.",
42
"resolution": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Indicates how the merge conflict was resolved by the user" }
43
}
44
*/
45
this.telemetryReporter.sendTelemetryEvent('mergeMarkers.accept', { resolution: commitTypeToString(type) });
46
47
if (edit) {
48
49
this.applyEdit(type, editor.document, edit);
50
return Promise.resolve(true);
51
}
52
53
return editor.edit((edit) => this.applyEdit(type, editor.document, edit));
54
}
55
56
public applyEdit(type: interfaces.CommitType, document: vscode.TextDocument, edit: { replace(range: vscode.Range, newText: string): void }): void {
57
if (this.applied) {
58
return;
59
}
60
this.applied = true;
61
62
// Each conflict is a set of ranges as follows, note placements or newlines
63
// which may not in spans
64
// [ Conflict Range -- (Entire content below)
65
// [ Current Header ]\n -- >>>>> Header
66
// [ Current Content ] -- (content)
67
// [ Splitter ]\n -- =====
68
// [ Incoming Content ] -- (content)
69
// [ Incoming Header ]\n -- <<<<< Incoming
70
// ]
71
if (type === interfaces.CommitType.Current) {
72
// Replace [ Conflict Range ] with [ Current Content ]
73
const content = document.getText(this.current.content);
74
this.replaceRangeWithContent(content, edit);
75
}
76
else if (type === interfaces.CommitType.Incoming) {
77
const content = document.getText(this.incoming.content);
78
this.replaceRangeWithContent(content, edit);
79
}
80
else if (type === interfaces.CommitType.Both) {
81
// Replace [ Conflict Range ] with [ Current Content ] + \n + [ Incoming Content ]
82
83
const currentContent = document.getText(this.current.content);
84
const incomingContent = document.getText(this.incoming.content);
85
86
edit.replace(this.range, currentContent.concat(incomingContent));
87
}
88
}
89
90
private replaceRangeWithContent(content: string, edit: { replace(range: vscode.Range, newText: string): void }) {
91
if (this.isNewlineOnly(content)) {
92
edit.replace(this.range, '');
93
return;
94
}
95
96
// Replace [ Conflict Range ] with [ Current Content ]
97
edit.replace(this.range, content);
98
}
99
100
private isNewlineOnly(text: string) {
101
return text === '\n' || text === '\r\n';
102
}
103
}
104
105