Skip to content

Commit 28524a4

Browse files
committed
Fix an assertion failure if a string literal inside string interpolation is unterminated
1 parent df7458b commit 28524a4

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

Sources/SwiftParser/Lexer/Cursor.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ extension Lexer.Cursor {
133133
case .afterStringLiteral: return false
134134
case .afterClosingStringQuote: return false
135135
case .inStringInterpolationStart: return false
136-
case .inStringInterpolation(stringLiteralKind: let stringLiteralKind, parenCount: _): return stringLiteralKind != .multiLine
136+
case .inStringInterpolation: return false
137137
case .afterStringInterpolation: return false
138138
}
139139
}
@@ -993,6 +993,14 @@ extension Lexer.Cursor {
993993
} else {
994994
return Lexer.Result(.rightParen, stateTransition: .replace(newState: .inStringInterpolation(stringLiteralKind: stringLiteralKind, parenCount: parenCount - 1)))
995995
}
996+
case UInt8(ascii: "\r"), UInt8(ascii: "\n"):
997+
// We don't eat newlines as leading trivia in string interpolation of
998+
// single line strings but `lexNormal` expects newlines to already be
999+
// eaten. If we reach a newline inside string interpolation of a
1000+
// single-line string, emit an empty string segment to indicate to the
1001+
// parser that the string has ended and pop out of string interpolation.
1002+
assert(stringLiteralKind != .multiLine)
1003+
return Lexer.Result(.stringSegment, stateTransition: .pop)
9961004
default:
9971005
// If we haven't reached the end of the string interpolation, lex as if we were in a normal expression.
9981006
return self.lexNormal(sourceBufferStart: sourceBufferStart)

Tests/SwiftParserTest/translated/UnclosedStringInterpolationTests.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,17 @@ final class UnclosedStringInterpolationTests: XCTestCase {
119119
]
120120
)
121121
}
122+
123+
func testUnterminatedStringLiteralInInterpolation() {
124+
AssertParse(
125+
#"""
126+
"\("1️⃣
127+
"""#,
128+
diagnostics: [
129+
DiagnosticSpec(message: #"expected '"' to end string literal"#),
130+
DiagnosticSpec(message: #"expected ')' in string literal"#),
131+
DiagnosticSpec(message: #"expected '"' to end string literal"#),
132+
]
133+
)
134+
}
122135
}

0 commit comments

Comments
 (0)