Skip to content

Commit

Permalink
Add AllowWhitespaceOnlyLines configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
TTOzzi committed Sep 5, 2024
1 parent 4a3def9 commit 44f83b4
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Documentation/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ top-level keys and values:

* `multiElementCollectionTrailingCommas` _(boolean)_: Determines whether multi-element collection literals should have trailing commas.
Defaults to `true`.

* `allowWhitespaceOnlyLines` _(boolean)_: Determines whether lines containing only whitespace should be preserved. When this setting is true, lines that consist solely of whitespace will not have the whitespace removed.
Defaults to `false`

> TODO: Add support for enabling/disabling specific syntax transformations in
> the pipeline.
Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftFormat/API/Configuration+Default.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ extension Configuration {
self.noAssignmentInExpressions = NoAssignmentInExpressionsConfiguration()
self.multiElementCollectionTrailingCommas = true
self.reflowMultilineStringLiterals = .never
self.allowWhitespaceOnlyLines = false
}
}
12 changes: 11 additions & 1 deletion Sources/SwiftFormat/API/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public struct Configuration: Codable, Equatable {
case noAssignmentInExpressions
case multiElementCollectionTrailingCommas
case reflowMultilineStringLiterals
case allowWhitespaceOnlyLines
}

/// A dictionary containing the default enabled/disabled states of rules, keyed by the rules'
Expand Down Expand Up @@ -259,6 +260,12 @@ public struct Configuration: Codable, Equatable {
}

public var reflowMultilineStringLiterals: MultilineStringReflowBehavior

/// Determines whether lines containing only whitespace should be preserved or removed.
///
/// If true, lines that consist solely of whitespace will be preserved as-is without removing
/// the whitespace. If false (the default), the whitespace on such lines will be completely removed.
public var allowWhitespaceOnlyLines: Bool

/// Creates a new `Configuration` by loading it from a configuration file.
public init(contentsOf url: URL) throws {
Expand Down Expand Up @@ -352,10 +359,13 @@ public struct Configuration: Codable, Equatable {
try container.decodeIfPresent(
Bool.self, forKey: .multiElementCollectionTrailingCommas)
?? defaults.multiElementCollectionTrailingCommas

self.reflowMultilineStringLiterals =
try container.decodeIfPresent(MultilineStringReflowBehavior.self, forKey: .reflowMultilineStringLiterals)
?? defaults.reflowMultilineStringLiterals
self.allowWhitespaceOnlyLines =
try container.decodeIfPresent(
Bool.self, forKey: .allowWhitespaceOnlyLines)
?? defaults.allowWhitespaceOnlyLines

// If the `rules` key is not present at all, default it to the built-in set
// so that the behavior is the same as if the configuration had been
Expand Down
7 changes: 6 additions & 1 deletion Sources/SwiftFormat/PrettyPrint/PrettyPrint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,12 @@ public class PrettyPrinter {

// Print out the number of spaces according to the size, and adjust spaceRemaining.
case .space(let size, _):
outputBuffer.enqueueSpaces(size)
if configuration.allowWhitespaceOnlyLines, outputBuffer.isAtStartOfLine {
let currentIndentationSpaceSize = outputBuffer.currentIndentation.indentation().count
outputBuffer.write(String(repeating: " ", count: size - currentIndentationSpaceSize))
} else {
outputBuffer.enqueueSpaces(size)
}

// Print any indentation required, followed by the text content of the syntax token.
case .syntax(let text):
Expand Down
7 changes: 6 additions & 1 deletion Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3465,7 +3465,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {

case .spaces(let n):
guard leadingIndent == .spaces(0) else { break }
leadingIndent = .spaces(n)
if config.allowWhitespaceOnlyLines, trivia.count > index + 1, trivia[index + 1].isNewline {
appendToken(.space(size: n))
requiresNextNewline = true
} else {
leadingIndent = .spaces(n)
}
case .tabs(let n):
guard leadingIndent == .spaces(0) else { break }
leadingIndent = .tabs(n)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extension Configuration {
config.spacesAroundRangeFormationOperators = false
config.noAssignmentInExpressions = NoAssignmentInExpressionsConfiguration()
config.multiElementCollectionTrailingCommas = true
config.allowWhitespaceOnlyLines = false
return config
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import SwiftFormat

final class AllowWhitespaceOnlyLinesTests: PrettyPrintTestCase {
func testAllowWhitespaceOnlyLinesEnabled() {
let input =
"""
class A {
func foo() -> Int {
return 1
}
func bar() -> Int {
return 2
}
}
"""

let expected =
"""
class A {
func foo() -> Int {
return 1
}
func bar() -> Int {
return 2
}
}
"""
var config = Configuration.forTesting
config.allowWhitespaceOnlyLines = true
assertPrettyPrintEqual(input: input, expected: expected, linelength: 80, configuration: config)
}

func testAllowWhitespaceOnlyLinesDisabled() {
let input =
"""
class A {
func foo() -> Int {
return 1
}
func bar() -> Int {
return 2
}
}
"""

let expected =
"""
class A {
func foo() -> Int {
return 1
}
func bar() -> Int {
return 2
}
}
"""
var config = Configuration.forTesting
config.allowWhitespaceOnlyLines = false
assertPrettyPrintEqual(input: input, expected: expected, linelength: 80, configuration: config)
}

func testExpressionsWithUnnecessaryWhitespaces() {
let input =
"""
class A {
func foo() -> Int {
return 1
}
func bar() -> Int {
return 2
}
}
"""

let expected =
"""
class A {
func foo() -> Int {
return 1
}
func bar() -> Int {
return 2
}
}
"""
var config = Configuration.forTesting
config.allowWhitespaceOnlyLines = true
assertPrettyPrintEqual(input: input, expected: expected, linelength: 80, configuration: config)
}
}

0 comments on commit 44f83b4

Please sign in to comment.