Skip to content

Commit b87fa64

Browse files
authored
Merge pull request #656 from allevato/broken-multiline-strings
Fix multi-line string wrapping in `@available` attributes.
2 parents b2d25c6 + 9626e00 commit b87fa64

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift

+27-2
Original file line numberDiff line numberDiff line change
@@ -1801,8 +1801,23 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
18011801

18021802
override func visit(_ node: AvailabilityLabeledArgumentSyntax) -> SyntaxVisitorContinueKind {
18031803
before(node.label, tokens: .open)
1804-
after(node.colon, tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true)))
1805-
after(node.value.lastToken(viewMode: .sourceAccurate), tokens: .close)
1804+
1805+
let tokensAfterColon: [Token]
1806+
let endTokens: [Token]
1807+
1808+
if case .string(let string) = node.value,
1809+
string.openingQuote.tokenKind == .multilineStringQuote
1810+
{
1811+
tokensAfterColon =
1812+
[.break(.open(kind: .block), newlines: .elective(ignoresDiscretionary: true))]
1813+
endTokens = [.break(.close(mustBreak: false), size: 0), .close]
1814+
} else {
1815+
tokensAfterColon = [.break(.continue, newlines: .elective(ignoresDiscretionary: true))]
1816+
endTokens = [.close]
1817+
}
1818+
1819+
after(node.colon, tokens: tokensAfterColon)
1820+
after(node.value.lastToken(viewMode: .sourceAccurate), tokens: endTokens)
18061821
return .visitChildren
18071822
}
18081823

@@ -2382,6 +2397,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
23822397
return .visitChildren
23832398
}
23842399

2400+
override func visit(_ node: SimpleStringLiteralExprSyntax) -> SyntaxVisitorContinueKind {
2401+
if node.openingQuote.tokenKind == .multilineStringQuote {
2402+
after(node.openingQuote, tokens: .break(.same, size: 0, newlines: .hard(count: 1)))
2403+
if !node.segments.isEmpty {
2404+
before(node.closingQuote, tokens: .break(.same, newlines: .hard(count: 1)))
2405+
}
2406+
}
2407+
return .visitChildren
2408+
}
2409+
23852410
override func visit(_ node: StringSegmentSyntax) -> SyntaxVisitorContinueKind {
23862411
// Looks up the correct break kind based on prior context.
23872412
func breakKind() -> BreakKind {

Tests/SwiftFormatTests/PrettyPrint/AttributeTests.swift

+54
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,58 @@ final class AttributeTests: PrettyPrintTestCase {
356356

357357
assertPrettyPrintEqual(input: input, expected: expected, linelength: 32)
358358
}
359+
360+
func testMultilineStringLiteralInCustomAttribute() {
361+
let input =
362+
#"""
363+
@CustomAttribute(message: """
364+
This is a
365+
multiline
366+
string
367+
""")
368+
public func f() {}
369+
"""#
370+
371+
let expected =
372+
#"""
373+
@CustomAttribute(
374+
message: """
375+
This is a
376+
multiline
377+
string
378+
""")
379+
public func f() {}
380+
381+
"""#
382+
383+
assertPrettyPrintEqual(input: input, expected: expected, linelength: 100)
384+
}
385+
386+
func testMultilineStringLiteralInAvailableAttribute() {
387+
let input =
388+
#"""
389+
@available(*, deprecated, message: """
390+
This is a
391+
multiline
392+
string
393+
""")
394+
public func f() {}
395+
"""#
396+
397+
let expected =
398+
#"""
399+
@available(
400+
*, deprecated,
401+
message: """
402+
This is a
403+
multiline
404+
string
405+
"""
406+
)
407+
public func f() {}
408+
409+
"""#
410+
411+
assertPrettyPrintEqual(input: input, expected: expected, linelength: 100)
412+
}
359413
}

0 commit comments

Comments
 (0)