Files
SwiftFormat/Sources/Rules/WrapSingleLineComments.swift

68 lines
2.6 KiB
Swift

//
// WrapSingleLineComments.swift
// SwiftFormat
//
// Created by Max Desiatov on 8/11/22.
// Copyright © 2024 Nick Lockwood. All rights reserved.
//
import Foundation
public extension FormatRule {
/// Wrap single-line comments that exceed given `FormatOptions.maxWidth` setting.
static let wrapSingleLineComments = FormatRule(
help: "Wrap single line `//` comments that exceed the specified `--max-width`.",
sharedOptions: ["max-width", "indent", "tab-width", "asset-literals", "linebreaks"]
) { formatter in
let delimiterLength = "//".count
var maxWidth = formatter.options.maxWidth
guard maxWidth > 3 else {
return
}
formatter.forEach(.startOfScope("//")) { i, _ in
let startOfLine = formatter.startOfLine(at: i)
let endOfLine = formatter.endOfLine(at: i)
guard formatter.lineLength(from: startOfLine, upTo: endOfLine) > maxWidth else {
return
}
guard let startIndex = formatter.index(of: .nonSpace, after: i),
case var .commentBody(comment) = formatter.tokens[startIndex],
!comment.isCommentDirective
else {
return
}
var words = comment.components(separatedBy: " ")
comment = words.removeFirst()
let commentPrefix = comment == "/" ? "/ " : comment.hasPrefix("/") ? "/" : ""
let prefixLength = formatter.lineLength(upTo: startIndex)
var length = prefixLength + comment.count
while length <= maxWidth, let next = words.first,
length + next.count < maxWidth ||
// Don't wrap if next word won't fit on a line by itself anyway
prefixLength + commentPrefix.count + next.count > maxWidth
{
comment += " \(next)"
length += next.count + 1
words.removeFirst()
}
if words.isEmpty || comment == commentPrefix {
return
}
var prefix = formatter.tokens[i ..< startIndex]
if let token = formatter.token(at: startOfLine), case .space = token {
prefix.insert(token, at: prefix.startIndex)
}
formatter.replaceTokens(in: startIndex ..< endOfLine, with: [
.commentBody(comment), formatter.linebreakToken(for: startIndex),
] + prefix + [
.commentBody(commentPrefix + words.joined(separator: " ")),
])
}
} examples: {
nil
}
}