Skip to content

Commit

Permalink
Add indentBlankLines configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
TTOzzi authored and macshome committed Dec 2, 2024
1 parent 2e4e0a6 commit 90931a6
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 4 deletions.
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("")
}
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

0 comments on commit 90931a6

Please sign in to comment.