Skip to content

Instantly share code, notes, and snippets.

@castus
Created May 1, 2018 22:04
Show Gist options
  • Save castus/8bbb4ddc88822d1b4fd7b75e6a3d5418 to your computer and use it in GitHub Desktop.
Save castus/8bbb4ddc88822d1b4fd7b75e6a3d5418 to your computer and use it in GitHub Desktop.
Add custom rules to SwiftFormat
import Foundation
extension FormatRules {
/// Linebreak after class, extension or struct
@objc public class func ststLinebreakAfterClassExtensionStruct(_ formatter: Formatter) {
guard formatter.options.removeBlankLines else { return }
formatter.forEach(.keyword) { i, token in
guard ["class", "extension", "struct"].contains(token.string),
let startOfScopeIndex = formatter.index(of: .startOfScope, after: i),
let lineBreakAfterStartOfScopeIndex = formatter.index(of: .linebreak, after: startOfScopeIndex),
let nextLineBreakAfterStartOfScopeIndex = formatter.index(of: .linebreak, after: lineBreakAfterStartOfScopeIndex)
else {
return
}
var hasOnlySpacesBetweenLineBreaks = true
for index in lineBreakAfterStartOfScopeIndex + 1 ..< nextLineBreakAfterStartOfScopeIndex {
if !formatter.tokens[index].isSpace {
hasOnlySpacesBetweenLineBreaks = false
break
}
}
if !hasOnlySpacesBetweenLineBreaks {
formatter.insertToken(.linebreak(formatter.options.linebreak), at: lineBreakAfterStartOfScopeIndex + 1)
return
}
}
}
/// Linebreak after guard
@objc public class func ststLinebreakAfterGuard(_ formatter: Formatter) {
guard formatter.options.removeBlankLines else { return }
formatter.forEach(.keyword) { i, token in
guard ["guard"].contains(token.string),
let startOfScopeIndex = formatter.index(of: .startOfScope, after: i),
let endOfScopeIndex = formatter.index(of: .endOfScope, after: startOfScopeIndex + 1),
let lineBreakAfterEndOfScopeIndex = formatter.index(of: .linebreak, after: endOfScopeIndex)
else {
return
}
formatter.insertToken(.linebreak(formatter.options.linebreak), at: lineBreakAfterEndOfScopeIndex + 1)
return
}
}
/// Linebreak after super
@objc public class func ststLinebreakAfterSuper(_ formatter: Formatter) {
guard formatter.options.removeBlankLines else { return }
formatter.forEach(.identifier) { i, token in
guard ["super"].contains(token.string),
let lineBreakAfterToken = formatter.index(of: .linebreak, after: i) else {
return
}
formatter.insertToken(.linebreak(formatter.options.linebreak), at: lineBreakAfterToken + 1)
return
}
}
/// Linebreak before return
@objc public class func ststLinebreakBeforeReturn(_ formatter: Formatter) {
guard formatter.options.removeBlankLines else { return }
formatter.forEach(.keyword) { i, token in
guard ["return"].contains(token.string),
let lineBreakBeforeToken = formatter.index(of: .linebreak, before: i) else {
return
}
var hasOnlySpacesBetweenStartOfScopeAndReturn = true
if let startOfScope = formatter.index(of: .startOfScope, before: lineBreakBeforeToken) {
for index in startOfScope + 1 ..< lineBreakBeforeToken {
if !formatter.tokens[index].isSpaceOrCommentOrLinebreak {
hasOnlySpacesBetweenStartOfScopeAndReturn = false
break
}
}
}
if !hasOnlySpacesBetweenStartOfScopeAndReturn {
formatter.insertToken(.linebreak(formatter.options.linebreak), at: lineBreakBeforeToken)
return
}
}
}
/// Linebreak at the beginning of a file
@objc public class func ststLinebreakAtTheBeginning(_ formatter: Formatter) {
if formatter.tokens[0].isLinebreak {
formatter.removeToken(at: 0)
}
formatter.insertToken(.linebreak(formatter.options.linebreak), at: 0)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment