Skip to content

Commit

Permalink
Add option to add a newline between 2 adjacent attributes
Browse files Browse the repository at this point in the history
Add an option that inserts hard line breaks between adjacent attributes.

Closes #773
  • Loading branch information
dduan committed Jul 29, 2024
1 parent b268009 commit 33ebf17
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 2 deletions.
1 change: 1 addition & 0 deletions Sources/SwiftFormat/API/Configuration+Default.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extension Configuration {
self.lineBreakBeforeControlFlowKeywords = false
self.lineBreakBeforeEachArgument = false
self.lineBreakBeforeEachGenericRequirement = false
self.lineBreakBetweenAttributes = false
self.prioritizeKeepingFunctionOutputTogether = false
self.indentConditionalCompilationBlocks = true
self.lineBreakAroundMultilineExpressionChainComponents = false
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftFormat/API/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public struct Configuration: Codable, Equatable {
case lineBreakBeforeControlFlowKeywords
case lineBreakBeforeEachArgument
case lineBreakBeforeEachGenericRequirement
case lineBreakBetweenAttributes
case prioritizeKeepingFunctionOutputTogether
case indentConditionalCompilationBlocks
case lineBreakAroundMultilineExpressionChainComponents
Expand Down Expand Up @@ -111,6 +112,9 @@ public struct Configuration: Codable, Equatable {
/// horizontally first, with line breaks only being fired when the line length would be exceeded.
public var lineBreakBeforeEachGenericRequirement: Bool

/// If true, a line break will be added between adjacent attributes.
public var lineBreakBetweenAttributes: Bool

/// Determines if function-like declaration outputs should be prioritized to be together with the
/// function signature right (closing) parenthesis.
///
Expand Down Expand Up @@ -243,6 +247,9 @@ public struct Configuration: Codable, Equatable {
self.lineBreakBeforeEachGenericRequirement =
try container.decodeIfPresent(Bool.self, forKey: .lineBreakBeforeEachGenericRequirement)
?? defaults.lineBreakBeforeEachGenericRequirement
self.lineBreakBetweenAttributes =
try container.decodeIfPresent(Bool.self, forKey: .lineBreakBetweenAttributes)
?? defaults.lineBreakBetweenAttributes
self.prioritizeKeepingFunctionOutputTogether =
try container.decodeIfPresent(Bool.self, forKey: .prioritizeKeepingFunctionOutputTogether)
?? defaults.prioritizeKeepingFunctionOutputTogether
Expand Down Expand Up @@ -296,6 +303,7 @@ public struct Configuration: Codable, Equatable {
try container.encode(lineBreakBeforeEachGenericRequirement, forKey: .lineBreakBeforeEachGenericRequirement)
try container.encode(prioritizeKeepingFunctionOutputTogether, forKey: .prioritizeKeepingFunctionOutputTogether)
try container.encode(indentConditionalCompilationBlocks, forKey: .indentConditionalCompilationBlocks)
try container.encode(lineBreakBetweenAttributes, forKey: .lineBreakBetweenAttributes)
try container.encode(
lineBreakAroundMultilineExpressionChainComponents,
forKey: .lineBreakAroundMultilineExpressionChainComponents)
Expand Down
5 changes: 3 additions & 2 deletions Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2893,11 +2893,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
suppressFinalBreak: Bool = false
) {
if let attributes = attributes {
let behavior: NewlineBehavior = config.lineBreakBetweenAttributes ? .hard : .elective
before(attributes.firstToken(viewMode: .sourceAccurate), tokens: .open)
insertTokens(.break(.same), betweenElementsOf: attributes)
insertTokens(.break(.same, newlines: behavior), betweenElementsOf: attributes)
var afterAttributeTokens = [Token.close]
if !suppressFinalBreak {
afterAttributeTokens.append(.break(.same))
afterAttributeTokens.append(.break(.same, newlines: behavior))
}
after(attributes.lastToken(viewMode: .sourceAccurate), tokens: afterAttributeTokens)
}
Expand Down
33 changes: 33 additions & 0 deletions Tests/SwiftFormatTests/PrettyPrint/AttributeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -468,4 +468,37 @@ final class AttributeTests: PrettyPrintTestCase {

assertPrettyPrintEqual(input: input, expected: expected, linelength: 100)
}

func testLineBreakBetweenAttributes() {
let input =
"""
@available(iOS 16.0, *) @available(macOS 14.0, *)
@available(tvOS 16.0, *) @frozen
struct X {
@available(iOS 17.0, *) @available(macOS 15.0, *)
@MainActor @discardableResult
func f() -> Int { 0 }
}
"""

let expected =
"""
@available(iOS 16.0, *)
@available(macOS 14.0, *)
@available(tvOS 16.0, *)
@frozen
struct X {
@available(iOS 17.0, *)
@available(macOS 15.0, *)
@MainActor
@discardableResult
func f() -> Int { 0 }
}
"""
var configuration = Configuration.forTesting
configuration.respectsExistingLineBreaks = false
configuration.lineBreakBetweenAttributes = true
assertPrettyPrintEqual(input: input, expected: expected, linelength: 80, configuration: configuration)
}
}

0 comments on commit 33ebf17

Please sign in to comment.