Skip to content

Commit 2c3c4dd

Browse files
authored
Merge pull request microsoft#16135 from katemihalikova/diff3
Add support for diff3-style merge
2 parents 4b40f45 + 2d60b2d commit 2c3c4dd

12 files changed

+258
-10
lines changed

src/compiler/scanner.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ namespace ts {
429429
case CharacterCodes.slash:
430430
// starts of normal trivia
431431
case CharacterCodes.lessThan:
432+
case CharacterCodes.bar:
432433
case CharacterCodes.equals:
433434
case CharacterCodes.greaterThan:
434435
// Starts of conflict marker trivia
@@ -496,6 +497,7 @@ namespace ts {
496497
break;
497498

498499
case CharacterCodes.lessThan:
500+
case CharacterCodes.bar:
499501
case CharacterCodes.equals:
500502
case CharacterCodes.greaterThan:
501503
if (isConflictMarkerTrivia(text, pos)) {
@@ -562,12 +564,12 @@ namespace ts {
562564
}
563565
}
564566
else {
565-
Debug.assert(ch === CharacterCodes.equals);
566-
// Consume everything from the start of the mid-conflict marker to the start of the next
567-
// end-conflict marker.
567+
Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
568+
// Consume everything from the start of a ||||||| or ======= marker to the start
569+
// of the next ======= or >>>>>>> marker.
568570
while (pos < len) {
569-
const ch = text.charCodeAt(pos);
570-
if (ch === CharacterCodes.greaterThan && isConflictMarkerTrivia(text, pos)) {
571+
const currentChar = text.charCodeAt(pos);
572+
if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) {
571573
break;
572574
}
573575

@@ -1562,6 +1564,16 @@ namespace ts {
15621564
pos++;
15631565
return token = SyntaxKind.OpenBraceToken;
15641566
case CharacterCodes.bar:
1567+
if (isConflictMarkerTrivia(text, pos)) {
1568+
pos = scanConflictMarkerTrivia(text, pos, error);
1569+
if (skipTrivia) {
1570+
continue;
1571+
}
1572+
else {
1573+
return token = SyntaxKind.ConflictMarkerTrivia;
1574+
}
1575+
}
1576+
15651577
if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
15661578
return pos += 2, token = SyntaxKind.BarBarToken;
15671579
}

src/harness/unittests/services/colorization.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,50 @@ class D { }\r\n\
424424
comment("=======\r\nclass D { }\r\n"),
425425
comment(">>>>>>> Branch - a"),
426426
finalEndOfLineState(ts.EndOfLineState.None));
427+
428+
testLexicalClassification(
429+
"class C {\r\n\
430+
<<<<<<< HEAD\r\n\
431+
v = 1;\r\n\
432+
||||||| merged common ancestors\r\n\
433+
v = 3;\r\n\
434+
=======\r\n\
435+
v = 2;\r\n\
436+
>>>>>>> Branch - a\r\n\
437+
}",
438+
ts.EndOfLineState.None,
439+
keyword("class"),
440+
identifier("C"),
441+
punctuation("{"),
442+
comment("<<<<<<< HEAD"),
443+
identifier("v"),
444+
operator("="),
445+
numberLiteral("1"),
446+
punctuation(";"),
447+
comment("||||||| merged common ancestors\r\n v = 3;\r\n"),
448+
comment("=======\r\n v = 2;\r\n"),
449+
comment(">>>>>>> Branch - a"),
450+
punctuation("}"),
451+
finalEndOfLineState(ts.EndOfLineState.None));
452+
453+
testLexicalClassification(
454+
"<<<<<<< HEAD\r\n\
455+
class C { }\r\n\
456+
||||||| merged common ancestors\r\n\
457+
class E { }\r\n\
458+
=======\r\n\
459+
class D { }\r\n\
460+
>>>>>>> Branch - a\r\n",
461+
ts.EndOfLineState.None,
462+
comment("<<<<<<< HEAD"),
463+
keyword("class"),
464+
identifier("C"),
465+
punctuation("{"),
466+
punctuation("}"),
467+
comment("||||||| merged common ancestors\r\nclass E { }\r\n"),
468+
comment("=======\r\nclass D { }\r\n"),
469+
comment(">>>>>>> Branch - a"),
470+
finalEndOfLineState(ts.EndOfLineState.None));
427471
});
428472

429473
it("'of' keyword", function () {

src/services/classifier.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,9 @@ namespace ts {
685685
continue;
686686
}
687687

688-
// for the ======== add a comment for the first line, and then lex all
689-
// subsequent lines up until the end of the conflict marker.
690-
Debug.assert(ch === CharacterCodes.equals);
688+
// for the ||||||| and ======== markers, add a comment for the first line,
689+
// and then lex all subsequent lines up until the end of the conflict marker.
690+
Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
691691
classifyDisabledMergeCode(text, start, end);
692692
}
693693
}
@@ -782,8 +782,8 @@ namespace ts {
782782
}
783783

784784
function classifyDisabledMergeCode(text: string, start: number, end: number) {
785-
// Classify the line that the ======= marker is on as a comment. Then just lex
786-
// all further tokens and add them to the result.
785+
// Classify the line that the ||||||| or ======= marker is on as a comment.
786+
// Then just lex all further tokens and add them to the result.
787787
let i: number;
788788
for (i = start; i < end; i++) {
789789
if (isLineBreak(text.charCodeAt(i))) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(2,1): error TS1185: Merge conflict marker encountered.
2+
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(4,1): error TS1185: Merge conflict marker encountered.
3+
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(6,1): error TS1185: Merge conflict marker encountered.
4+
tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(8,1): error TS1185: Merge conflict marker encountered.
5+
6+
7+
==== tests/cases/compiler/conflictMarkerDiff3Trivia1.ts (4 errors) ====
8+
class C {
9+
<<<<<<< HEAD
10+
~~~~~~~
11+
!!! error TS1185: Merge conflict marker encountered.
12+
v = 1;
13+
||||||| merged common ancestors
14+
~~~~~~~
15+
!!! error TS1185: Merge conflict marker encountered.
16+
v = 3;
17+
=======
18+
~~~~~~~
19+
!!! error TS1185: Merge conflict marker encountered.
20+
v = 2;
21+
>>>>>>> Branch-a
22+
~~~~~~~
23+
!!! error TS1185: Merge conflict marker encountered.
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [conflictMarkerDiff3Trivia1.ts]
2+
class C {
3+
<<<<<<< HEAD
4+
v = 1;
5+
||||||| merged common ancestors
6+
v = 3;
7+
=======
8+
v = 2;
9+
>>>>>>> Branch-a
10+
}
11+
12+
//// [conflictMarkerDiff3Trivia1.js]
13+
var C = (function () {
14+
function C() {
15+
this.v = 1;
16+
}
17+
return C;
18+
}());
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(3,1): error TS1185: Merge conflict marker encountered.
2+
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(4,6): error TS2304: Cannot find name 'a'.
3+
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(6,1): error TS1185: Merge conflict marker encountered.
4+
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(9,1): error TS1185: Merge conflict marker encountered.
5+
tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(12,1): error TS1185: Merge conflict marker encountered.
6+
7+
8+
==== tests/cases/compiler/conflictMarkerDiff3Trivia2.ts (5 errors) ====
9+
class C {
10+
foo() {
11+
<<<<<<< B
12+
~~~~~~~
13+
!!! error TS1185: Merge conflict marker encountered.
14+
a();
15+
~
16+
!!! error TS2304: Cannot find name 'a'.
17+
}
18+
||||||| merged common ancestors
19+
~~~~~~~
20+
!!! error TS1185: Merge conflict marker encountered.
21+
c();
22+
}
23+
=======
24+
~~~~~~~
25+
!!! error TS1185: Merge conflict marker encountered.
26+
b();
27+
}
28+
>>>>>>> A
29+
~~~~~~~
30+
!!! error TS1185: Merge conflict marker encountered.
31+
32+
public bar() { }
33+
}
34+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [conflictMarkerDiff3Trivia2.ts]
2+
class C {
3+
foo() {
4+
<<<<<<< B
5+
a();
6+
}
7+
||||||| merged common ancestors
8+
c();
9+
}
10+
=======
11+
b();
12+
}
13+
>>>>>>> A
14+
15+
public bar() { }
16+
}
17+
18+
19+
//// [conflictMarkerDiff3Trivia2.js]
20+
var C = (function () {
21+
function C() {
22+
}
23+
C.prototype.foo = function () {
24+
a();
25+
};
26+
C.prototype.bar = function () { };
27+
return C;
28+
}());
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class C {
2+
<<<<<<< HEAD
3+
v = 1;
4+
||||||| merged common ancestors
5+
v = 3;
6+
=======
7+
v = 2;
8+
>>>>>>> Branch-a
9+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class C {
2+
foo() {
3+
<<<<<<< B
4+
a();
5+
}
6+
||||||| merged common ancestors
7+
c();
8+
}
9+
=======
10+
b();
11+
}
12+
>>>>>>> A
13+
14+
public bar() { }
15+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
////<<<<<<< HEAD
5+
////v = 1;
6+
////||||||| merged common ancestors
7+
////v = 3;
8+
////=======
9+
////v = 2;
10+
////>>>>>>> Branch - a
11+
////}
12+
13+
format.document();
14+
verify.currentFileContentIs("class C {\r\n\
15+
<<<<<<< HEAD\r\n\
16+
v = 1;\r\n\
17+
||||||| merged common ancestors\r\n\
18+
v = 3;\r\n\
19+
=======\r\n\
20+
v = 2;\r\n\
21+
>>>>>>> Branch - a\r\n\
22+
}");
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
////class C {
4+
////<<<<<<< HEAD
5+
//// v = 1;
6+
////||||||| merged common ancestors
7+
//// v = 3;
8+
////=======
9+
//// v = 2;
10+
////>>>>>>> Branch - a
11+
////}
12+
13+
const c = classification;
14+
verify.syntacticClassificationsAre(
15+
c.keyword("class"), c.className("C"), c.punctuation("{"),
16+
c.comment("<<<<<<< HEAD"),
17+
c.identifier("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"),
18+
c.comment("||||||| merged common ancestors"),
19+
c.identifier("v"), c.punctuation("="), c.numericLiteral("3"), c.punctuation(";"),
20+
c.comment("======="),
21+
c.identifier("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"),
22+
c.comment(">>>>>>> Branch - a"),
23+
c.punctuation("}"));
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
////<<<<<<< HEAD
4+
////class C { }
5+
////||||||| merged common ancestors
6+
////class E { }
7+
////=======
8+
////class D { }
9+
////>>>>>>> Branch - a
10+
11+
const c = classification;
12+
verify.syntacticClassificationsAre(
13+
c.comment("<<<<<<< HEAD"),
14+
c.keyword("class"), c.className("C"), c.punctuation("{"), c.punctuation("}"),
15+
c.comment("||||||| merged common ancestors"),
16+
c.keyword("class"), c.identifier("E"), c.punctuation("{"), c.punctuation("}"),
17+
c.comment("======="),
18+
c.keyword("class"), c.identifier("D"), c.punctuation("{"), c.punctuation("}"),
19+
c.comment(">>>>>>> Branch - a"));

0 commit comments

Comments
 (0)