mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
69 lines
2.8 KiB
Swift
69 lines
2.8 KiB
Swift
//
|
|
// TrailingClosures.swift
|
|
// SwiftFormat
|
|
//
|
|
// Created by Nick Lockwood on 1/17/17.
|
|
// Copyright © 2024 Nick Lockwood. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public extension FormatRule {
|
|
/// Convert closure arguments to trailing closure syntax where possible
|
|
static let trailingClosures = FormatRule(
|
|
help: "Use trailing closure syntax where applicable.",
|
|
options: ["trailingclosures", "nevertrailing"]
|
|
) { formatter in
|
|
let useTrailing = Set([
|
|
"async", "asyncAfter", "sync", "autoreleasepool",
|
|
] + formatter.options.trailingClosures)
|
|
|
|
let nonTrailing = Set([
|
|
"performBatchUpdates",
|
|
"expect", // Special case to support autoclosure arguments in the Nimble framework
|
|
] + formatter.options.neverTrailing)
|
|
|
|
formatter.forEach(.startOfScope("(")) { i, _ in
|
|
guard let prevToken = formatter.last(.nonSpaceOrCommentOrLinebreak, before: i),
|
|
case let .identifier(name) = prevToken, // TODO: are trailing closures allowed in other cases?
|
|
!nonTrailing.contains(name), !formatter.isConditionalStatement(at: i)
|
|
else {
|
|
return
|
|
}
|
|
guard let closingIndex = formatter.index(of: .endOfScope(")"), after: i), let closingBraceIndex =
|
|
formatter.index(of: .nonSpaceOrComment, before: closingIndex, if: { $0 == .endOfScope("}") }),
|
|
let openingBraceIndex = formatter.index(of: .startOfScope("{"), before: closingBraceIndex),
|
|
formatter.index(of: .endOfScope("}"), before: openingBraceIndex) == nil
|
|
else {
|
|
return
|
|
}
|
|
guard formatter.next(.nonSpaceOrCommentOrLinebreak, after: closingIndex) != .startOfScope("{"),
|
|
var startIndex = formatter.index(of: .nonSpaceOrLinebreak, before: openingBraceIndex)
|
|
else {
|
|
return
|
|
}
|
|
switch formatter.tokens[startIndex] {
|
|
case .delimiter(","), .startOfScope("("):
|
|
break
|
|
case .delimiter(":"):
|
|
guard useTrailing.contains(name) else {
|
|
return
|
|
}
|
|
if let commaIndex = formatter.index(of: .delimiter(","), before: openingBraceIndex) {
|
|
startIndex = commaIndex
|
|
} else if formatter.index(of: .startOfScope("("), before: openingBraceIndex) == i {
|
|
startIndex = i
|
|
} else {
|
|
return
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
let wasParen = (startIndex == i)
|
|
formatter.removeParen(at: closingIndex)
|
|
formatter.replaceTokens(in: startIndex ..< openingBraceIndex, with:
|
|
wasParen ? [.space(" ")] : [.endOfScope(")"), .space(" ")])
|
|
}
|
|
}
|
|
}
|