Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a configuration to preserve whitespace on lines containing only whitespace #804

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Documentation/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ top-level keys and values:

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

* `indentBlankLines` _(boolean)_: Determines whether blank lines should be modified
to match the current indentation. When this setting is true, blank lines will be modified
to match the indentation level, adding indentation whether or not there is existing whitespace.
When false (the default), all whitespace in blank lines will be completely removed.

> 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.indentBlankLines = false
}
}
14 changes: 14 additions & 0 deletions 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 indentBlankLines
}

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

public var reflowMultilineStringLiterals: MultilineStringReflowBehavior

/// Determines whether to add indentation whitespace to blank lines or remove it entirely.
///
/// If true, blank lines will be modified to match the current indentation level:
/// if they contain whitespace, the existing whitespace will be adjusted, and if they are empty, spaces will be added to match the indentation.
/// If false (the default), the whitespace in blank lines will be removed entirely.
public var indentBlankLines: Bool

/// Creates a new `Configuration` by loading it from a configuration file.
public init(contentsOf url: URL) throws {
let data = try Data(contentsOf: url)
Expand Down Expand Up @@ -368,6 +376,12 @@ public struct Configuration: Codable, Equatable {
self.reflowMultilineStringLiterals =
try container.decodeIfPresent(MultilineStringReflowBehavior.self, forKey: .reflowMultilineStringLiterals)
?? defaults.reflowMultilineStringLiterals
self.indentBlankLines =
try container.decodeIfPresent(
Bool.self,
forKey: .indentBlankLines
)
?? defaults.indentBlankLines

// 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
6 changes: 5 additions & 1 deletion Sources/SwiftFormat/PrettyPrint/PrettyPrint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ public class PrettyPrinter {
outputBuffer.enqueueSpaces(size)
outputBuffer.write("\\")
}
outputBuffer.writeNewlines(newline)
outputBuffer.writeNewlines(newline, shouldIndentBlankLines: configuration.indentBlankLines)
lastBreak = true
} else {
if outputBuffer.isAtStartOfLine {
Expand All @@ -458,6 +458,10 @@ public class PrettyPrinter {

// Print out the number of spaces according to the size, and adjust spaceRemaining.
case .space(let size, _):
if configuration.indentBlankLines, outputBuffer.isAtStartOfLine {
// An empty string write is needed to add line-leading indentation that matches the current indentation on a line that contains only whitespaces.
outputBuffer.write("")
ahoppen marked this conversation as resolved.
Show resolved Hide resolved
}
outputBuffer.enqueueSpaces(size)

// Print any indentation required, followed by the text content of the syntax token.
Expand Down
15 changes: 12 additions & 3 deletions Sources/SwiftFormat/PrettyPrint/PrettyPrintBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ struct PrettyPrintBuffer {
/// subtract the previously written newlines during the second call so that we end up with the
/// correct number overall.
///
/// - Parameter newlines: The number and type of newlines to write.
mutating func writeNewlines(_ newlines: NewlineBehavior) {
/// - Parameters:
/// - newlines: The number and type of newlines to write.
/// - shouldIndentBlankLines: A Boolean value indicating whether to insert spaces
/// for blank lines based on the current indentation level.
mutating func writeNewlines(_ newlines: NewlineBehavior, shouldIndentBlankLines: Bool) {
let numberToPrint: Int
switch newlines {
case .elective:
Expand All @@ -86,7 +89,13 @@ struct PrettyPrintBuffer {
}

guard numberToPrint > 0 else { return }
writeRaw(String(repeating: "\n", count: numberToPrint))
for number in 0..<numberToPrint {
if shouldIndentBlankLines, number >= 1 {
writeRaw(currentIndentation.indentation())
}
writeRaw("\n")
}

lineNumber += numberToPrint
isAtStartOfLine = true
consecutiveNewlineCount += numberToPrint
Expand Down
7 changes: 7 additions & 0 deletions Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3521,6 +3521,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
leadingIndent = nil

case .newlines(let count), .carriageReturns(let count), .carriageReturnLineFeeds(let count):
if config.indentBlankLines,
let leadingIndent, leadingIndent.count > 0
{
requiresNextNewline = true
}

leadingIndent = .spaces(0)
guard !isStartOfFile else { break }

Expand Down Expand Up @@ -3557,6 +3563,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
case .spaces(let n):
guard leadingIndent == .spaces(0) else { break }
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.indentBlankLines = false
return config
}
}
Loading