diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts
index d27bbf879f..0a072a3b8a 100644
--- a/src/compiler/scanner.ts
+++ b/src/compiler/scanner.ts
@@ -429,6 +429,7 @@ namespace ts {
case CharacterCodes.slash:
// starts of normal trivia
case CharacterCodes.lessThan:
+ case CharacterCodes.bar:
case CharacterCodes.equals:
case CharacterCodes.greaterThan:
// Starts of conflict marker trivia
@@ -496,6 +497,7 @@ namespace ts {
break;
case CharacterCodes.lessThan:
+ case CharacterCodes.bar:
case CharacterCodes.equals:
case CharacterCodes.greaterThan:
if (isConflictMarkerTrivia(text, pos)) {
@@ -562,12 +564,12 @@ namespace ts {
}
}
else {
- Debug.assert(ch === CharacterCodes.equals);
- // Consume everything from the start of the mid-conflict marker to the start of the next
- // end-conflict marker.
+ Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
+ // Consume everything from the start of a ||||||| or ======= marker to the start
+ // of the next ======= or >>>>>>> marker.
while (pos < len) {
- const ch = text.charCodeAt(pos);
- if (ch === CharacterCodes.greaterThan && isConflictMarkerTrivia(text, pos)) {
+ const currentChar = text.charCodeAt(pos);
+ if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) {
break;
}
@@ -1562,6 +1564,16 @@ namespace ts {
pos++;
return token = SyntaxKind.OpenBraceToken;
case CharacterCodes.bar:
+ if (isConflictMarkerTrivia(text, pos)) {
+ pos = scanConflictMarkerTrivia(text, pos, error);
+ if (skipTrivia) {
+ continue;
+ }
+ else {
+ return token = SyntaxKind.ConflictMarkerTrivia;
+ }
+ }
+
if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
return pos += 2, token = SyntaxKind.BarBarToken;
}
diff --git a/src/harness/unittests/services/colorization.ts b/src/harness/unittests/services/colorization.ts
index fd7d932885..3fed9ec616 100644
--- a/src/harness/unittests/services/colorization.ts
+++ b/src/harness/unittests/services/colorization.ts
@@ -424,6 +424,50 @@ class D { }\r\n\
comment("=======\r\nclass D { }\r\n"),
comment(">>>>>>> Branch - a"),
finalEndOfLineState(ts.EndOfLineState.None));
+
+ testLexicalClassification(
+"class C {\r\n\
+<<<<<<< HEAD\r\n\
+ v = 1;\r\n\
+||||||| merged common ancestors\r\n\
+ v = 3;\r\n\
+=======\r\n\
+ v = 2;\r\n\
+>>>>>>> Branch - a\r\n\
+}",
+ ts.EndOfLineState.None,
+ keyword("class"),
+ identifier("C"),
+ punctuation("{"),
+ comment("<<<<<<< HEAD"),
+ identifier("v"),
+ operator("="),
+ numberLiteral("1"),
+ punctuation(";"),
+ comment("||||||| merged common ancestors\r\n v = 3;\r\n"),
+ comment("=======\r\n v = 2;\r\n"),
+ comment(">>>>>>> Branch - a"),
+ punctuation("}"),
+ finalEndOfLineState(ts.EndOfLineState.None));
+
+ testLexicalClassification(
+"<<<<<<< HEAD\r\n\
+class C { }\r\n\
+||||||| merged common ancestors\r\n\
+class E { }\r\n\
+=======\r\n\
+class D { }\r\n\
+>>>>>>> Branch - a\r\n",
+ ts.EndOfLineState.None,
+ comment("<<<<<<< HEAD"),
+ keyword("class"),
+ identifier("C"),
+ punctuation("{"),
+ punctuation("}"),
+ comment("||||||| merged common ancestors\r\nclass E { }\r\n"),
+ comment("=======\r\nclass D { }\r\n"),
+ comment(">>>>>>> Branch - a"),
+ finalEndOfLineState(ts.EndOfLineState.None));
});
it("'of' keyword", function () {
diff --git a/src/services/classifier.ts b/src/services/classifier.ts
index acee8fe4b0..beeddda434 100644
--- a/src/services/classifier.ts
+++ b/src/services/classifier.ts
@@ -685,9 +685,9 @@ namespace ts {
continue;
}
- // for the ======== add a comment for the first line, and then lex all
- // subsequent lines up until the end of the conflict marker.
- Debug.assert(ch === CharacterCodes.equals);
+ // for the ||||||| and ======== markers, add a comment for the first line,
+ // and then lex all subsequent lines up until the end of the conflict marker.
+ Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
}
}
@@ -782,8 +782,8 @@ namespace ts {
}
function classifyDisabledMergeCode(text: string, start: number, end: number) {
- // Classify the line that the ======= marker is on as a comment. Then just lex
- // all further tokens and add them to the result.
+ // Classify the line that the ||||||| or ======= marker is on as a comment.
+ // Then just lex all further tokens and add them to the result.
let i: number;
for (i = start; i < end; i++) {
if (isLineBreak(text.charCodeAt(i))) {
diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt b/tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt
new file mode 100644
index 0000000000..b38e4e189e
--- /dev/null
+++ b/tests/baselines/reference/conflictMarkerDiff3Trivia1.errors.txt
@@ -0,0 +1,24 @@
+tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(2,1): error TS1185: Merge conflict marker encountered.
+tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(4,1): error TS1185: Merge conflict marker encountered.
+tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(6,1): error TS1185: Merge conflict marker encountered.
+tests/cases/compiler/conflictMarkerDiff3Trivia1.ts(8,1): error TS1185: Merge conflict marker encountered.
+
+
+==== tests/cases/compiler/conflictMarkerDiff3Trivia1.ts (4 errors) ====
+ class C {
+ <<<<<<< HEAD
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ v = 1;
+ ||||||| merged common ancestors
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ v = 3;
+ =======
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ v = 2;
+ >>>>>>> Branch-a
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia1.js b/tests/baselines/reference/conflictMarkerDiff3Trivia1.js
new file mode 100644
index 0000000000..86cccd44e1
--- /dev/null
+++ b/tests/baselines/reference/conflictMarkerDiff3Trivia1.js
@@ -0,0 +1,18 @@
+//// [conflictMarkerDiff3Trivia1.ts]
+class C {
+<<<<<<< HEAD
+ v = 1;
+||||||| merged common ancestors
+ v = 3;
+=======
+ v = 2;
+>>>>>>> Branch-a
+}
+
+//// [conflictMarkerDiff3Trivia1.js]
+var C = (function () {
+ function C() {
+ this.v = 1;
+ }
+ return C;
+}());
diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt b/tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt
new file mode 100644
index 0000000000..2e29826c43
--- /dev/null
+++ b/tests/baselines/reference/conflictMarkerDiff3Trivia2.errors.txt
@@ -0,0 +1,34 @@
+tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(3,1): error TS1185: Merge conflict marker encountered.
+tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(4,6): error TS2304: Cannot find name 'a'.
+tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(6,1): error TS1185: Merge conflict marker encountered.
+tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(9,1): error TS1185: Merge conflict marker encountered.
+tests/cases/compiler/conflictMarkerDiff3Trivia2.ts(12,1): error TS1185: Merge conflict marker encountered.
+
+
+==== tests/cases/compiler/conflictMarkerDiff3Trivia2.ts (5 errors) ====
+ class C {
+ foo() {
+ <<<<<<< B
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ a();
+ ~
+!!! error TS2304: Cannot find name 'a'.
+ }
+ ||||||| merged common ancestors
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ c();
+ }
+ =======
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+ b();
+ }
+ >>>>>>> A
+ ~~~~~~~
+!!! error TS1185: Merge conflict marker encountered.
+
+ public bar() { }
+ }
+
\ No newline at end of file
diff --git a/tests/baselines/reference/conflictMarkerDiff3Trivia2.js b/tests/baselines/reference/conflictMarkerDiff3Trivia2.js
new file mode 100644
index 0000000000..61a2273019
--- /dev/null
+++ b/tests/baselines/reference/conflictMarkerDiff3Trivia2.js
@@ -0,0 +1,28 @@
+//// [conflictMarkerDiff3Trivia2.ts]
+class C {
+ foo() {
+<<<<<<< B
+ a();
+ }
+||||||| merged common ancestors
+ c();
+ }
+=======
+ b();
+ }
+>>>>>>> A
+
+ public bar() { }
+}
+
+
+//// [conflictMarkerDiff3Trivia2.js]
+var C = (function () {
+ function C() {
+ }
+ C.prototype.foo = function () {
+ a();
+ };
+ C.prototype.bar = function () { };
+ return C;
+}());
diff --git a/tests/cases/compiler/conflictMarkerDiff3Trivia1.ts b/tests/cases/compiler/conflictMarkerDiff3Trivia1.ts
new file mode 100644
index 0000000000..072cc4b968
--- /dev/null
+++ b/tests/cases/compiler/conflictMarkerDiff3Trivia1.ts
@@ -0,0 +1,9 @@
+class C {
+<<<<<<< HEAD
+ v = 1;
+||||||| merged common ancestors
+ v = 3;
+=======
+ v = 2;
+>>>>>>> Branch-a
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/conflictMarkerDiff3Trivia2.ts b/tests/cases/compiler/conflictMarkerDiff3Trivia2.ts
new file mode 100644
index 0000000000..023d425cd4
--- /dev/null
+++ b/tests/cases/compiler/conflictMarkerDiff3Trivia2.ts
@@ -0,0 +1,15 @@
+class C {
+ foo() {
+<<<<<<< B
+ a();
+ }
+||||||| merged common ancestors
+ c();
+ }
+=======
+ b();
+ }
+>>>>>>> A
+
+ public bar() { }
+}
diff --git a/tests/cases/fourslash/formatConflictDiff3Marker1.ts b/tests/cases/fourslash/formatConflictDiff3Marker1.ts
new file mode 100644
index 0000000000..f6492a6f60
--- /dev/null
+++ b/tests/cases/fourslash/formatConflictDiff3Marker1.ts
@@ -0,0 +1,22 @@
+///
+
+////class C {
+////<<<<<<< HEAD
+////v = 1;
+////||||||| merged common ancestors
+////v = 3;
+////=======
+////v = 2;
+////>>>>>>> Branch - a
+////}
+
+format.document();
+verify.currentFileContentIs("class C {\r\n\
+<<<<<<< HEAD\r\n\
+ v = 1;\r\n\
+||||||| merged common ancestors\r\n\
+v = 3;\r\n\
+=======\r\n\
+v = 2;\r\n\
+>>>>>>> Branch - a\r\n\
+}");
\ No newline at end of file
diff --git a/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts
new file mode 100644
index 0000000000..669705307a
--- /dev/null
+++ b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers1.ts
@@ -0,0 +1,23 @@
+///
+
+////class C {
+////<<<<<<< HEAD
+//// v = 1;
+////||||||| merged common ancestors
+//// v = 3;
+////=======
+//// v = 2;
+////>>>>>>> Branch - a
+////}
+
+const c = classification;
+verify.syntacticClassificationsAre(
+ c.keyword("class"), c.className("C"), c.punctuation("{"),
+ c.comment("<<<<<<< HEAD"),
+ c.identifier("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"),
+ c.comment("||||||| merged common ancestors"),
+ c.identifier("v"), c.punctuation("="), c.numericLiteral("3"), c.punctuation(";"),
+ c.comment("======="),
+ c.identifier("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"),
+ c.comment(">>>>>>> Branch - a"),
+ c.punctuation("}"));
\ No newline at end of file
diff --git a/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts
new file mode 100644
index 0000000000..1714439718
--- /dev/null
+++ b/tests/cases/fourslash/syntacticClassificationsConflictDiff3Markers2.ts
@@ -0,0 +1,19 @@
+///
+
+////<<<<<<< HEAD
+////class C { }
+////||||||| merged common ancestors
+////class E { }
+////=======
+////class D { }
+////>>>>>>> Branch - a
+
+const c = classification;
+verify.syntacticClassificationsAre(
+ c.comment("<<<<<<< HEAD"),
+ c.keyword("class"), c.className("C"), c.punctuation("{"), c.punctuation("}"),
+ c.comment("||||||| merged common ancestors"),
+ c.keyword("class"), c.identifier("E"), c.punctuation("{"), c.punctuation("}"),
+ c.comment("======="),
+ c.keyword("class"), c.identifier("D"), c.punctuation("{"), c.punctuation("}"),
+ c.comment(">>>>>>> Branch - a"));
\ No newline at end of file