Skip to content

Commit

Permalink
Only disable wrapping in import decls when it is safe to do so.
Browse files Browse the repository at this point in the history
The ImportDeclSyntax attributes might include IfConfigDecls, which
absolutely require line breaks in certain positions. The disable
breaking logic of ImportDecl was preventing these from being emitted.
  • Loading branch information
shawnhyam committed Oct 22, 2024
1 parent d7976ce commit a1fd498
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 10 deletions.
16 changes: 12 additions & 4 deletions Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1458,7 +1458,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {

override func visit(_ node: IfConfigDeclSyntax) -> SyntaxVisitorContinueKind {
// there has to be a break after an #endif
after(node.poundEndif, tokens: .break(.same, size: 0))
after(node.poundEndif, tokens: .break(.same, size: 0, newlines: .soft))
return .visitChildren
}

Expand Down Expand Up @@ -1893,14 +1893,22 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
}

override func visit(_ node: ImportDeclSyntax) -> SyntaxVisitorContinueKind {
// Import declarations should never be wrapped.
before(node.firstToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .disableBreaking(allowDiscretionary: false)))
// Import declarations ignore wrapping when it is safe to do so (no #if constructs)
let isSafeToIgnoreBreaking = !node.attributes.contains(where: { element in
return element.is(IfConfigDeclSyntax.self)
})

if isSafeToIgnoreBreaking {
before(node.firstToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .disableBreaking(allowDiscretionary: false)))
}

arrangeAttributeList(node.attributes)
after(node.importKeyword, tokens: .space)
after(node.importKindSpecifier, tokens: .space)

after(node.lastToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .enableBreaking))
if isSafeToIgnoreBreaking {
after(node.lastToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .enableBreaking))
}
return .visitChildren
}

Expand Down
17 changes: 11 additions & 6 deletions Tests/SwiftFormatTests/PrettyPrint/IfConfigTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -383,10 +383,10 @@ final class IfConfigTests: PrettyPrintTestCase {
.toggleStyle(
SwitchToggleStyle(tint: Color.blue))
#endif
.accessibilityValue(
binding.wrappedValue == true
? "On" : "Off"
)
.accessibilityValue(
binding.wrappedValue == true
? "On" : "Off"
)
}
"""
Expand Down Expand Up @@ -482,7 +482,7 @@ final class IfConfigTests: PrettyPrintTestCase {
#if os(iOS)
.iOSSpecificModifier()
#endif
.commonModifier()
.commonModifier()
"""

Expand Down Expand Up @@ -510,7 +510,7 @@ final class IfConfigTests: PrettyPrintTestCase {
#if os(iOS)
.iOSSpecificModifier()
#endif
.commonModifier()
.commonModifier()
"""

Expand Down Expand Up @@ -563,11 +563,16 @@ final class IfConfigTests: PrettyPrintTestCase {
"""
#if os(Foo)
@_spiOnly
#elseif os(Bar)
@_spiOnly
#else
@_spiOnly
#endif
@_spi(Foo) import Foundation
"""
var configuration = Configuration.forTesting
configuration.respectsExistingLineBreaks = false
configuration.indentConditionalCompilationBlocks = false
assertPrettyPrintEqual(input: input, expected: input, linelength: 80, configuration: configuration)

Expand Down

0 comments on commit a1fd498

Please sign in to comment.