Skip to content

Commit d76d848

Browse files
committed
Diagnose source conflict markers
1 parent 25d74e2 commit d76d848

File tree

5 files changed

+24
-32
lines changed

5 files changed

+24
-32
lines changed

Sources/SwiftParser/Lexer/Cursor.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ extension Lexer.Cursor {
10271027
let start = self
10281028

10291029
switch self.advance() {
1030-
// 'continue' - the character is a part of the trivia9.
1030+
// 'continue' - the character is a part of the trivia.
10311031
// 'break' - the character should a part of token text.
10321032
case nil:
10331033
break
@@ -1070,10 +1070,10 @@ extension Lexer.Cursor {
10701070
self.advanceToEndOfLine()
10711071
continue
10721072
case UInt8(ascii: "<"), UInt8(ascii: ">"):
1073-
guard self.tryLexConflictMarker(start: start) else {
1074-
break
1073+
if self.tryLexConflictMarker(start: start) {
1074+
error = (.sourceConflictMarker, start)
1075+
continue
10751076
}
1076-
continue
10771077
// Start character of tokens.
10781078
// case (char)-1: case (char)-2:
10791079
case // Punctuation.
@@ -2195,7 +2195,7 @@ extension Lexer.Cursor {
21952195
}
21962196
mutating func tryLexConflictMarker(start: Lexer.Cursor) -> Bool {
21972197
// Only a conflict marker if it starts at the beginning of a line.
2198-
guard start.previous == UInt8(ascii: "\n") || start.previous == UInt8(ascii: "\r") else {
2198+
guard start.previous == UInt8(ascii: "\n") || start.previous == UInt8(ascii: "\r") || start.previous == 0 else {
21992199
return false
22002200
}
22012201

@@ -2211,7 +2211,6 @@ extension Lexer.Cursor {
22112211
}
22122212

22132213
// Diagnose at the conflict marker, then jump ahead to the end.
2214-
// diagnose(CurPtr, diag::lex_conflict_marker_in_file);
22152214
self = end
22162215

22172216
// Skip ahead to the end of the marker.

Sources/SwiftParserDiagnostics/LexerDiagnosticMessages.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public enum StaticLexerError: String, DiagnosticMessage {
5151
case lexerErrorOffsetOverflow = "the lexer dicovered an error in this token but was not able to represent its offset due to overflow; please split the token"
5252
case nonBreakingSpace = "non-breaking space (U+00A0) used instead of regular space"
5353
case nulCharacter = "nul character embedded in middle of file"
54+
case sourceConflictMarker = "source control conflict marker in source file"
5455
case unexpectedBlockCommentEnd = "unexpected end of block comment"
5556
case unicodeCurlyQuote = #"unicode curly quote found; use '"' instead"#
5657

@@ -142,6 +143,7 @@ public extension SwiftSyntax.LexerError {
142143
case .lexerErrorOffsetOverflow: return StaticLexerError.lexerErrorOffsetOverflow
143144
case .nonBreakingSpace: return StaticLexerError.nonBreakingSpace
144145
case .nulCharacter: return StaticLexerError.nulCharacter
146+
case .sourceConflictMarker: return StaticLexerError.sourceConflictMarker
145147
case .unexpectedBlockCommentEnd: return StaticLexerError.unexpectedBlockCommentEnd
146148
case .unicodeCurlyQuote: return StaticLexerError.unicodeCurlyQuote
147149
}

Sources/SwiftSyntax/LexerError.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public struct LexerError: Hashable {
3838
case lexerErrorOffsetOverflow
3939
case nonBreakingSpace
4040
case nulCharacter
41+
case sourceConflictMarker
4142
case unexpectedBlockCommentEnd
4243
case unicodeCurlyQuote
4344
}

Tests/SwiftParserTest/LexerTests.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ public class LexerTests: XCTestCase {
453453
"""
454454
// diff3-style conflict markers
455455
456-
<<<<<<< HEAD:conflict_markers.swift // expected-error {{source control conflict marker in source file}}
456+
1️⃣<<<<<<< HEAD:conflict_markers.swift // expected-error {{source control conflict marker in source file}}
457457
var a : String = "A"
458458
var b : String = "b"
459459
=======
@@ -477,6 +477,7 @@ public class LexerTests: XCTestCase {
477477
>>>>>>> 18844bc65229786b96b89a9fc7739c0fc897905e:conflict_markers.swift
478478
""",
479479
text: "",
480+
error: "source control conflict marker in source file",
480481
flags: [.isAtStartOfLine]
481482
)
482483
]
@@ -486,7 +487,7 @@ public class LexerTests: XCTestCase {
486487
"""
487488
// Perforce-style conflict markers
488489
489-
>>>> ORIGINAL
490+
1️⃣>>>> ORIGINAL
490491
var a : String = "A"
491492
var b : String = "B"
492493
==== THEIRS
@@ -518,6 +519,7 @@ public class LexerTests: XCTestCase {
518519
519520
""",
520521
text: "",
522+
error: "source control conflict marker in source file",
521523
flags: [.isAtStartOfLine]
522524
)
523525
]

Tests/SwiftParserTest/translated/ConflictMarkersTests.swift

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,14 @@ final class ConflictMarkersTests: XCTestCase {
7373
1️⃣<<<<<<< HEAD:conflict_markers.swift
7474
var a : String = "A"
7575
var b : String = "b"
76-
=======2️⃣
76+
=======
7777
var a : String = "a"
7878
var b : String = "B"
79-
>>>>>>> 188443️⃣bc65229786b96b89a9fc7739c0fc897905e4️⃣:conflict_markers.swift
79+
>>>>>>> 18844bc65229786b96b89a9fc7739c0fc897905e:conflict_markers.swift
8080
print(a + b)
8181
"""#,
8282
diagnostics: [
83-
// TODO: Old parser expected error on line 1: source control conflict marker in source file
84-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '<<<<<<< HEAD:conflict_markers.swift' before variable"),
85-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected expression after operator"),
86-
DiagnosticSpec(locationMarker: "3️⃣", message: "'b' is not a valid digit in integer literal"),
87-
DiagnosticSpec(locationMarker: "4️⃣", message: "extraneous code at top level"),
83+
DiagnosticSpec(message: "source control conflict marker in source file")
8884
]
8985
)
9086
}
@@ -95,14 +91,11 @@ final class ConflictMarkersTests: XCTestCase {
9591
1️⃣<<<<<<< HEAD:conflict_markers.swift
9692
=======
9793
var d : String = "D"
98-
>>>>>>> 188442️⃣bc65229786b96b89a9fc7739c0fc897905e3️⃣:conflict_markers.swift
94+
>>>>>>> 18844bc65229786b96b89a9fc7739c0fc897905e:conflict_markers.swift
9995
print(d)
10096
"""#,
10197
diagnostics: [
102-
// TODO: Old parser expected error on line 1: source control conflict marker in source file
103-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code before variable"),
104-
DiagnosticSpec(locationMarker: "2️⃣", message: "'b' is not a valid digit in integer literal"),
105-
DiagnosticSpec(locationMarker: "3️⃣", message: "extraneous code at top level"),
98+
DiagnosticSpec(message: "source control conflict marker in source file")
10699
]
107100
)
108101
}
@@ -119,22 +112,19 @@ final class ConflictMarkersTests: XCTestCase {
119112
func testConflictMarkers10() {
120113
AssertParse(
121114
#"""
122-
1️⃣<<<<<<< HEAD:conflict_markers.swift
115+
1️⃣<<<<<<< HEAD:conflict_markers.swift
123116
<<<<<<<"HEAD:fake_conflict_markers.swift"
124117
var fake_b : String = "a"
125118
>>>>>>>"18844bc65229786b96b89a9fc7739c0fc897905e:fake_conflict_markers.swift"
126119
=======
127120
<<<<<<<"HEAD:fake_conflict_markers.swift"
128121
var fake_c : String = "a"
129122
>>>>>>>"18844bc65229786b96b89a9fc7739c0fc897905e:fake_conflict_markers.swift"
130-
>>>>>>> 188442️⃣bc65229786b96b89a9fc7739c0fc897905e3️⃣:conflict_markers.swift
123+
>>>>>>> 18844bc65229786b96b89a9fc7739c0fc897905e:conflict_markers.swift
131124
print(fake_b + fake_c)
132125
"""#,
133126
diagnostics: [
134-
// TODO: Old parser expected error on line 1: source control conflict marker in source file
135-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code before variable"),
136-
DiagnosticSpec(locationMarker: "2️⃣", message: "'b' is not a valid digit in integer literal"),
137-
DiagnosticSpec(locationMarker: "3️⃣", message: "extraneous code at top level"),
127+
DiagnosticSpec(message: "source control conflict marker in source file")
138128
]
139129
)
140130
}
@@ -154,7 +144,7 @@ final class ConflictMarkersTests: XCTestCase {
154144
// Conflict marker.
155145
let a = "a", b = "b"
156146
a
157-
<<<<<<< b
147+
1️⃣<<<<<<< b
158148
a
159149
>>>>>>> b
160150
// Not a conflict marker.
@@ -165,7 +155,7 @@ final class ConflictMarkersTests: XCTestCase {
165155
}()
166156
"""#,
167157
diagnostics: [
168-
// TODO: Old parser expected error on line 5: source control conflict marker in source file
158+
DiagnosticSpec(message: "source control conflict marker in source file")
169159
]
170160
)
171161
}
@@ -194,8 +184,7 @@ final class ConflictMarkersTests: XCTestCase {
194184
print(a + b)
195185
"""#,
196186
diagnostics: [
197-
// TODO: Old parser expected error on line 1: source control conflict marker in source file
198-
DiagnosticSpec(message: "unexpected code '>>>> ORIGINAL' before variable")
187+
DiagnosticSpec(message: "source control conflict marker in source file")
199188
]
200189
)
201190
}
@@ -211,8 +200,7 @@ final class ConflictMarkersTests: XCTestCase {
211200
print(d)
212201
"""#,
213202
diagnostics: [
214-
// TODO: Old parser expected error on line 1: source control conflict marker in source file
215-
DiagnosticSpec(message: "unexpected code before variable")
203+
DiagnosticSpec(message: "source control conflict marker in source file")
216204
]
217205
)
218206
}

0 commit comments

Comments
 (0)