SwiftLint/Source/SwiftLintBuiltInRules/Rules/Style/VerticalParameterAlignmentR...

62 lines
2.5 KiB
Swift

import SwiftSyntax
struct VerticalParameterAlignmentRule: SwiftSyntaxRule, ConfigurationProviderRule {
var configuration = SeverityConfiguration<Self>(.warning)
static let description = RuleDescription(
identifier: "vertical_parameter_alignment",
name: "Vertical Parameter Alignment",
description: "Function parameters should be aligned vertically if they're in multiple lines in a declaration",
kind: .style,
nonTriggeringExamples: VerticalParameterAlignmentRuleExamples.nonTriggeringExamples,
triggeringExamples: VerticalParameterAlignmentRuleExamples.triggeringExamples
)
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
Visitor(locationConverter: file.locationConverter)
}
}
private extension VerticalParameterAlignmentRule {
final class Visitor: ViolationsSyntaxVisitor {
private let locationConverter: SourceLocationConverter
init(locationConverter: SourceLocationConverter) {
self.locationConverter = locationConverter
super.init(viewMode: .sourceAccurate)
}
override func visitPost(_ node: FunctionDeclSyntax) {
violations.append(contentsOf: violations(for: node.signature.input.parameterList))
}
override func visitPost(_ node: InitializerDeclSyntax) {
violations.append(contentsOf: violations(for: node.signature.input.parameterList))
}
private func violations(for params: FunctionParameterListSyntax) -> [AbsolutePosition] {
guard params.count > 1 else {
return []
}
let paramLocations = params.compactMap { param -> (position: AbsolutePosition, line: Int, column: Int)? in
let position = param.positionAfterSkippingLeadingTrivia
let location = locationConverter.location(for: position)
return (position, location.line, location.column)
}
guard let firstParamLoc = paramLocations.first else { return [] }
var violations: [AbsolutePosition] = []
for (index, paramLoc) in paramLocations.enumerated() where index > 0 && paramLoc.line > firstParamLoc.line {
let previousParamLoc = paramLocations[index - 1]
if previousParamLoc.line < paramLoc.line && firstParamLoc.column != paramLoc.column {
violations.append(paramLoc.position)
}
}
return violations
}
}
}