mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
48 lines
1.8 KiB
Swift
48 lines
1.8 KiB
Swift
import Foundation
|
|
import SwiftSyntax
|
|
|
|
// MARK: - CommandVisitor
|
|
|
|
/// Visits the source syntax tree to collect all SwiftLint-style comment commands.
|
|
final class CommandVisitor: SyntaxVisitor {
|
|
private(set) var commands: [Command] = []
|
|
let locationConverter: SourceLocationConverter
|
|
|
|
init(locationConverter: SourceLocationConverter) {
|
|
self.locationConverter = locationConverter
|
|
super.init(viewMode: .sourceAccurate)
|
|
}
|
|
|
|
override func visitPost(_ node: TokenSyntax) {
|
|
collectCommands(in: node.leadingTrivia, offset: node.position)
|
|
collectCommands(in: node.trailingTrivia, offset: node.endPositionBeforeTrailingTrivia)
|
|
}
|
|
|
|
private func collectCommands(in trivia: Trivia, offset: AbsolutePosition) {
|
|
var position = offset
|
|
for piece in trivia {
|
|
switch piece {
|
|
case .lineComment(let comment):
|
|
guard let lower = comment.range(of: "swiftlint:")?.lowerBound.samePosition(in: comment.utf8) else {
|
|
break
|
|
}
|
|
let offset = comment.utf8.distance(from: comment.utf8.startIndex, to: lower)
|
|
let location = locationConverter.location(for: position.advanced(by: offset))
|
|
let line = locationConverter.sourceLines[location.line - 1]
|
|
guard let character = line.characterPosition(of: location.column) else {
|
|
break
|
|
}
|
|
let command = Command(
|
|
commandString: String(comment[lower...]),
|
|
line: location.line,
|
|
range: character..<(character + piece.sourceLength.utf8Length - offset)
|
|
)
|
|
commands.append(command)
|
|
default:
|
|
break
|
|
}
|
|
position += piece.sourceLength
|
|
}
|
|
}
|
|
}
|