Skip to content

.swift-format: Specify an exhaustive configuration #1057

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

Merged
merged 2 commits into from
Aug 11, 2025
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
68 changes: 62 additions & 6 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -1,20 +1,76 @@
{
"version": 1,
"lineLength": 120,
"fileScopedDeclarationPrivacy": {
"accessLevel": "private"
},
"indentConditionalCompilationBlocks": false,
"indentSwitchCaseLabels": false,
"indentation": {
"spaces": 2
},
"lineBreakAroundMultilineExpressionChainComponents": false,
"lineBreakBeforeControlFlowKeywords": false,
"lineBreakBeforeEachArgument": true,
"indentConditionalCompilationBlocks": false,
"lineBreakBeforeEachGenericRequirement": false,
"lineBreakBetweenDeclarationAttributes": false,
"lineLength": 120,
"maximumBlankLines": 1,
"multiElementCollectionTrailingCommas": true,
"noAssignmentInExpressions": {
"allowedFunctions": [
"XCTAssertNoThrow"
]
},
"prioritizeKeepingFunctionOutputTogether": true,
"reflowMultilineStringLiterals": {
"never": {

}
},
"respectsExistingLineBreaks": true,
"rules": {
"AllPublicDeclarationsHaveDocumentation": false,
"AlwaysUseLiteralForEmptyCollectionInit": false,
"AlwaysUseLowerCamelCase": false,
"AmbiguousTrailingClosureOverload": false,
"BeginDocumentationCommentWithOneLineSummary": false,
"DoNotUseSemicolons": false,
"DontRepeatTypeInStaticProperties": false,
"FileScopedDeclarationPrivacy": true,
"FullyIndirectEnum": true,
"GroupNumericLiterals": true,
"IdentifiersMustBeASCII": true,
"NeverForceUnwrap": false,
"NeverUseForceTry": false,
"NeverUseImplicitlyUnwrappedOptionals": false,
"NoAccessLevelOnExtensionDeclaration": false,
"NoAssignmentInExpressions": true,
"NoBlockComments": false,
"NoCasesWithOnlyFallthrough": true,
"NoEmptyTrailingClosureParentheses": true,
"NoLabelsInCasePatterns": true,
"NoLeadingUnderscores": false,
"NoParensAroundConditions": true,
"NoPlaygroundLiterals": true,
"NoVoidReturnOnFunctionSignature": true,
"OmitExplicitReturns": false,
"OneCasePerLine": true,
"OneVariableDeclarationPerLine": true,
"OnlyOneTrailingClosureArgument": true,
"OrderedImports": true,
"ReplaceForEachWithForLoop": true,
"ReturnVoidInsteadOfEmptyTuple": true,
"TypeNamesShouldBeCapitalized": true,
"UseEarlyExits": false,
"UseExplicitNilCheckInConditions": true,
"UseLetInEveryBoundCaseVariable": false,
"UseShorthandTypeNames": true,
"UseSingleLinePropertyGetter": true,
"UseSynthesizedInitializer": false,
"ReturnVoidInsteadOfEmptyTuple": true,
"NoVoidReturnOnFunctionSignature": true,
}
"UseTripleSlashForDocumentationComments": true,
"UseWhereClausesInForLoops": false,
"ValidateDocumentationComments": false
},
"spacesAroundRangeFormationOperators": false,
"spacesBeforeEndOfLineComments": 2,
"version": 1,
}
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/Core/DocumentationCommentText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private func asciiArtLength(of string: Substring, leadingSpaces: Int) -> Int {
/// Returns the start index of the earliest comment in the Trivia if we work backwards and
/// skip through comments, newlines, and whitespace. Then we advance a bit forward to be sure
/// the returned index is actually a comment and not whitespace.
private func findCommentStartIndex(_ triviaArray: Array<TriviaPiece>) -> Array<TriviaPiece>.Index {
private func findCommentStartIndex(_ triviaArray: [TriviaPiece]) -> Array<TriviaPiece>.Index {
func firstCommentIndex(_ slice: ArraySlice<TriviaPiece>) -> Array<TriviaPiece>.Index {
return slice.firstIndex(where: {
switch $0 {
Expand Down
6 changes: 4 additions & 2 deletions Sources/SwiftFormat/Core/RuleMask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ enum IgnoreDirective: CustomStringConvertible {
/// The rule status comment directives implementation intentionally supports exactly the same nodes
/// as `TokenStreamCreator` to disable pretty printing. This ensures ignore comments for pretty
/// printing and for rules are as consistent as possible.
fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
private class RuleStatusCollectionVisitor: SyntaxVisitor {
/// Describes the possible matches for ignore directives, in comments.
enum RuleStatusDirectiveMatch {
/// There is a directive that applies to all rules.
Expand Down Expand Up @@ -219,7 +219,9 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
// node's children are irrelevant because all rules are suppressed by this node.
return .skipChildren
case .subset(let ruleNames):
ruleNames.forEach { ruleMap[$0, default: []].append(sourceRange) }
for ruleName in ruleNames {
ruleMap[ruleName, default: []].append(sourceRange)
}
break
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/PrettyPrint/PrettyPrint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public class PrettyPrinter {
// the group.
case .open(let breaktype):
// Determine if the break tokens in this group need to be forced.
if (!canFit(length) || lastBreak), case .consistent = breaktype {
if !canFit(length) || lastBreak, case .consistent = breaktype {
forceBreakStack.append(true)
} else {
forceBreakStack.append(false)
Expand Down
10 changes: 5 additions & 5 deletions Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fileprivate extension AccessorBlockSyntax {

/// Visits the nodes of a syntax tree and constructs a linear stream of formatting tokens that
/// tell the pretty printer how the source text should be laid out.
fileprivate final class TokenStreamCreator: SyntaxVisitor {
private final class TokenStreamCreator: SyntaxVisitor {
private var tokens = [Token]()
private var beforeMap = [TokenSyntax: [Token]]()
private var afterMap = [TokenSyntax: [[Token]]]()
Expand Down Expand Up @@ -3023,7 +3023,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
}

for after in afterGroups.reversed() {
after.forEach { afterToken in
for afterToken in after {
var shouldExtractTrailingComment = false
if wasLineComment && !hasAppendedTrailingComment {
switch afterToken {
Expand Down Expand Up @@ -4447,7 +4447,7 @@ extension TriviaPiece {
/// - trivia: Leading trivia for a node that the formatter supports ignoring.
/// - isWholeFile: Whether to search for a whole-file ignore directive or per node ignore.
/// - Returns: Whether the trivia contains the specified type of ignore directive.
fileprivate func isFormatterIgnorePresent(inTrivia trivia: Trivia, isWholeFile: Bool) -> Bool {
private func isFormatterIgnorePresent(inTrivia trivia: Trivia, isWholeFile: Bool) -> Bool {
func isFormatterIgnore(in commentText: String, prefix: String, suffix: String) -> Bool {
let trimmed =
commentText.dropFirst(prefix.count)
Expand Down Expand Up @@ -4480,7 +4480,7 @@ fileprivate func isFormatterIgnorePresent(inTrivia trivia: Trivia, isWholeFile:
/// be safely ignored.
///
/// - Parameter node: A node that can be safely ignored.
fileprivate func shouldFormatterIgnore(node: Syntax) -> Bool {
private func shouldFormatterIgnore(node: Syntax) -> Bool {
// Regardless of the level of nesting, if the ignore directive is present on the first token
// contained within the node then the entire node is eligible for ignoring.
return isFormatterIgnorePresent(inTrivia: node.allPrecedingTrivia, isWholeFile: false)
Expand All @@ -4491,7 +4491,7 @@ fileprivate func shouldFormatterIgnore(node: Syntax) -> Bool {
/// in the original source).
///
/// - Parameter file: The root syntax node for a source file.
fileprivate func shouldFormatterIgnore(file: SourceFileSyntax) -> Bool {
private func shouldFormatterIgnore(file: SourceFileSyntax) -> Bool {
return isFormatterIgnorePresent(inTrivia: file.allPrecedingTrivia, isWholeFile: true)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/PrettyPrint/Verbatim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ struct Verbatim {
}

/// Returns the leading number of spaces in the given string.
fileprivate func numberOfLeadingSpaces(in text: Substring) -> Int {
private func numberOfLeadingSpaces(in text: Substring) -> Int {
var count = 0
for char in text {
if char == " " { count += 1 } else { break }
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/Rules/AlwaysUseLowerCamelCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
///
/// - Parameter node: A node whose identifier may be used in diagnostics.
/// - Returns: A human readable description of the node and its identifier.
fileprivate func identifierDescription<NodeType: SyntaxProtocol>(for node: NodeType) -> String {
private func identifierDescription<NodeType: SyntaxProtocol>(for node: NodeType) -> String {
switch Syntax(node).as(SyntaxEnum.self) {
case .closureSignature: return "closure parameter"
case .enumCaseElement: return "enum case"
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftFormat/Rules/NoCasesWithOnlyFallthrough.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {

/// Flushes any un-collapsed violations to the new cases list.
func flushViolations() {
fallthroughOnlyCases.forEach {
newChildren.append(.switchCase(visit($0)))
for node in fallthroughOnlyCases {
newChildren.append(.switchCase(visit(node)))
}
fallthroughOnlyCases.removeAll()
}
Expand Down
10 changes: 5 additions & 5 deletions Sources/SwiftFormat/Rules/OrderedImports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,14 @@ public final class OrderedImports: SyntaxFormatRule {
}

/// Remove any leading blank lines from the main code.
fileprivate func formatCodeblocks(_ codeblocks: inout [Line]) {
private func formatCodeblocks(_ codeblocks: inout [Line]) {
if let contentIndex = codeblocks.firstIndex(where: { !$0.isBlankLine }) {
codeblocks.removeSubrange(0..<contentIndex)
}
}

/// Join the lists of Line objects into a single list of Lines with a blank line separating them.
fileprivate func joinLines(_ inputLineLists: [Line]...) -> [Line] {
private func joinLines(_ inputLineLists: [Line]...) -> [Line] {
var lineLists = inputLineLists
lineLists.removeAll { $0.isEmpty }
guard lineLists.count > 0 else { return [] }
Expand All @@ -320,7 +320,7 @@ fileprivate func joinLines(_ inputLineLists: [Line]...) -> [Line] {
/// This function transforms the statements in a CodeBlockItemListSyntax object into a list of Line
/// objects. Blank lines and standalone comments are represented by their own Line object. Code with
/// a trailing comment are represented together in the same Line.
fileprivate func generateLines(
private func generateLines(
codeBlockItemList: CodeBlockItemListSyntax,
context: Context
) -> [Line] {
Expand Down Expand Up @@ -380,7 +380,7 @@ fileprivate func generateLines(

/// This function transforms a list of Line objects into a list of CodeBlockItemSyntax objects,
/// replacing the trivia appropriately to ensure comments appear in the right location.
fileprivate func convertToCodeBlockItems(lines: [Line]) -> [CodeBlockItemSyntax] {
private func convertToCodeBlockItems(lines: [Line]) -> [CodeBlockItemSyntax] {
var output: [CodeBlockItemSyntax] = []
var pendingLeadingTrivia: [TriviaPiece] = []

Expand Down Expand Up @@ -450,7 +450,7 @@ public enum LineType: CustomStringConvertible {
/// represent a single printed line. Other types of code (e.g. structs and classes) will span
/// multiple literal lines, but can still be represented by a single Line object. This is desireable
/// since we aren't interested in rearranging those types of structures in this rule.
fileprivate class Line {
private class Line {
/// Storage for the different types of AST nodes that can be held by a `Line`.
enum SyntaxNode {
/// A collection of code block items that aren't imports. These types of code blocks aren't
Expand Down
8 changes: 5 additions & 3 deletions Sources/SwiftFormat/Rules/UseSynthesizedInitializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ public final class UseSynthesizedInitializer: SyntaxLintRule {
// initializer, then all of the initializers must remain.
let initializersCount = node.memberBlock.members.filter { $0.decl.is(InitializerDeclSyntax.self) }.count
if extraneousInitializers.count == initializersCount {
extraneousInitializers.forEach { diagnose(.removeRedundantInitializer, on: $0) }
for initializer in extraneousInitializers {
diagnose(.removeRedundantInitializer, on: initializer)
}
}

return .visitChildren
Expand Down Expand Up @@ -197,7 +199,7 @@ extension Finding.Message {
}

/// Defines the access levels which may be assigned to a synthesized memberwise initializer.
fileprivate enum AccessLevel {
private enum AccessLevel {
case `internal`
case `fileprivate`
case `private`
Expand All @@ -212,7 +214,7 @@ fileprivate enum AccessLevel {
///
/// - Parameter properties: The properties contained within the struct.
/// - Returns: The synthesized memberwise initializer's access level.
fileprivate func synthesizedInitAccessLevel(using properties: [VariableDeclSyntax]) -> AccessLevel {
private func synthesizedInitAccessLevel(using properties: [VariableDeclSyntax]) -> AccessLevel {
var hasFileprivate = false
for property in properties {
// Private takes precedence, so finding 1 private property defines the access level.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public final class UseWhereClausesInForLoops: SyntaxFormatRule {
}
}

fileprivate func updateWithWhereCondition(
private func updateWithWhereCondition(
node: ForStmtSyntax,
condition: ExprSyntax,
statements: CodeBlockItemListSyntax
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public final class ValidateDocumentationComments: SyntaxLintRule {

/// Iterates through every parameter of paramList and returns a list of the
/// parameters identifiers.
fileprivate func funcParametersIdentifiers(in paramList: FunctionParameterListSyntax) -> [String] {
private func funcParametersIdentifiers(in paramList: FunctionParameterListSyntax) -> [String] {
var funcParameters = [String]()
for parameter in paramList {
// If there is a label and an identifier, then the identifier (`secondName`) is the name that
Expand All @@ -164,7 +164,7 @@ fileprivate func funcParametersIdentifiers(in paramList: FunctionParameterListSy

/// Indicates if the parameters name from the documentation and the parameters
/// from the declaration are the same.
fileprivate func parametersAreEqual(
private func parametersAreEqual(
params: [DocumentationComment.Parameter],
funcParam: [String]
) -> Bool {
Expand Down
2 changes: 1 addition & 1 deletion Sources/swift-format/Subcommands/Format.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension SwiftFormatCommand {
}

func run() throws {
try performanceMeasurementOptions.printingInstructionCountIfRequested() {
try performanceMeasurementOptions.printingInstructionCountIfRequested {
let frontend = FormatFrontend(
configurationOptions: configurationOptions,
lintFormatOptions: formatOptions,
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftFormatTests/PrettyPrint/GarbageTextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//

fileprivate let bom: Unicode.Scalar = "\u{feff}"
fileprivate let unknownScalar: Unicode.Scalar = "\u{fffe}"
private let bom: Unicode.Scalar = "\u{feff}"
private let unknownScalar: Unicode.Scalar = "\u{fffe}"

final class GarbageTextTests: PrettyPrintTestCase {
func testHashBang() {
Expand Down