Skip to content

Commit 6bb4225

Browse files
committed
Allow empty lines without indenation in multi-line string literals
1 parent 8c06097 commit 6bb4225

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

Sources/SwiftParser/StringLiterals.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ extension Parser {
210210
segment.unexpectedAfterContent,
211211
arena: self.arena
212212
)
213+
} else if segment.content.tokenText == "" || segment.content.tokenText.triviaPieceIfNewline != nil {
214+
// Empty lines don't need to be indented and there's no indentation we need to strip away.
213215
} else {
214216
let actualIndentation = segment.content.tokenText.prefix(while: { $0 == UInt8(ascii: " ") || $0 == UInt8(ascii: "\t") })
215217
let actualIndentationTrivia = TriviaParser.parseTrivia(SyntaxText(rebasing: actualIndentation), position: .leading)

Tests/SwiftParserTest/ExpressionTests.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,76 @@ final class ExpressionTests: XCTestCase {
986986
"""#
987987
)
988988
}
989+
990+
func testEmptyLineInMultilineStringLiteral() {
991+
AssertParse(
992+
#"""
993+
"""
994+
line 1
995+
996+
line 2
997+
"""
998+
"""#,
999+
substructure: Syntax(
1000+
StringLiteralExprSyntax(
1001+
openDelimiter: nil,
1002+
openQuote: .multilineStringQuoteToken(leadingTrivia: [.spaces(2)], trailingTrivia: .newline),
1003+
segments: StringLiteralSegmentsSyntax([
1004+
.stringSegment(StringSegmentSyntax(content: .stringSegment("line 1\n", leadingTrivia: [.spaces(2)]))),
1005+
.stringSegment(StringSegmentSyntax(content: .stringSegment("\n"))),
1006+
.stringSegment(StringSegmentSyntax(content: .stringSegment("line 2", leadingTrivia: [.spaces(2)], trailingTrivia: .newline))),
1007+
]),
1008+
closeQuote: .multilineStringQuoteToken(leadingTrivia: [.spaces(2)]),
1009+
closeDelimiter: nil
1010+
)
1011+
),
1012+
options: [.substructureCheckTrivia]
1013+
)
1014+
1015+
AssertParse(
1016+
#"""
1017+
"""
1018+
line 1
1019+
1020+
"""
1021+
"""#,
1022+
substructure: Syntax(
1023+
StringLiteralExprSyntax(
1024+
openDelimiter: nil,
1025+
openQuote: .multilineStringQuoteToken(leadingTrivia: [.spaces(2)], trailingTrivia: .newline),
1026+
segments: StringLiteralSegmentsSyntax([
1027+
.stringSegment(StringSegmentSyntax(content: .stringSegment("line 1\n", leadingTrivia: [.spaces(2)]))),
1028+
.stringSegment(StringSegmentSyntax(content: .stringSegment("", trailingTrivia: .newline))),
1029+
]),
1030+
closeQuote: .multilineStringQuoteToken(leadingTrivia: [.spaces(2)]),
1031+
closeDelimiter: nil
1032+
)
1033+
),
1034+
options: [.substructureCheckTrivia]
1035+
)
1036+
}
1037+
1038+
func testUnderIndentedWhitespaceonlyLineInMultilineStringLiteral() {
1039+
AssertParse(
1040+
#"""
1041+
"""
1042+
line 1
1043+
1️⃣
1044+
line 2
1045+
"""
1046+
"""#,
1047+
diagnostics: [
1048+
DiagnosticSpec(message: "insufficient indentation of line in multi-line string literal")
1049+
],
1050+
fixedSource: #"""
1051+
"""
1052+
line 1
1053+
\#(" ")
1054+
line 2
1055+
"""
1056+
"""#
1057+
)
1058+
}
9891059
}
9901060

9911061
final class MemberExprTests: XCTestCase {

0 commit comments

Comments
 (0)