88 lines
3.7 KiB
Swift
88 lines
3.7 KiB
Swift
import SwiftSyntax
|
|
|
|
struct FunctionParameterCountRule: SwiftSyntaxRule, ConfigurationProviderRule {
|
|
var configuration = FunctionParameterCountConfiguration()
|
|
|
|
static let description = RuleDescription(
|
|
identifier: "function_parameter_count",
|
|
name: "Function Parameter Count",
|
|
description: "Number of function parameters should be low.",
|
|
kind: .metrics,
|
|
nonTriggeringExamples: [
|
|
Example("init(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("init (a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("`init`(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("init?(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("init?<T>(a: T, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("init?<T: String>(a: T, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("func f2(p1: Int, p2: Int) { }"),
|
|
Example("func f(a: Int, b: Int, c: Int, d: Int, x: Int = 42) {}"),
|
|
Example("""
|
|
func f(a: [Int], b: Int, c: Int, d: Int, f: Int) -> [Int] {
|
|
let s = a.flatMap { $0 as? [String: Int] } ?? []}}
|
|
"""),
|
|
Example("override func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}")
|
|
],
|
|
triggeringExamples: [
|
|
Example("↓func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("↓func initialValue(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}"),
|
|
Example("private ↓func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int = 2, g: Int) {}"),
|
|
Example("""
|
|
struct Foo {
|
|
init(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}
|
|
↓func bar(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}}
|
|
""")
|
|
]
|
|
)
|
|
|
|
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
|
Visitor(configuration: configuration)
|
|
}
|
|
}
|
|
|
|
private extension FunctionParameterCountRule {
|
|
final class Visitor: ViolationsSyntaxVisitor {
|
|
private let configuration: FunctionParameterCountConfiguration
|
|
|
|
init(configuration: FunctionParameterCountConfiguration) {
|
|
self.configuration = configuration
|
|
super.init(viewMode: .sourceAccurate)
|
|
}
|
|
|
|
override func visitPost(_ node: FunctionDeclSyntax) {
|
|
guard !node.modifiers.containsOverride else {
|
|
return
|
|
}
|
|
|
|
let parameterList = node.signature.input.parameterList
|
|
guard let minThreshold = configuration.severityConfiguration.params.map(\.value).min(by: <) else {
|
|
return
|
|
}
|
|
|
|
let allParameterCount = parameterList.count
|
|
if allParameterCount < minThreshold {
|
|
return
|
|
}
|
|
|
|
var parameterCount = allParameterCount
|
|
if configuration.ignoresDefaultParameters {
|
|
parameterCount -= parameterList.filter { $0.defaultArgument != nil }.count
|
|
}
|
|
|
|
for parameter in configuration.severityConfiguration.params where parameterCount > parameter.value {
|
|
let reason = "Function should have \(configuration.severityConfiguration.warning) parameters " +
|
|
"or less: it currently has \(parameterCount)"
|
|
|
|
violations.append(
|
|
ReasonedRuleViolation(
|
|
position: node.funcKeyword.positionAfterSkippingLeadingTrivia,
|
|
reason: reason,
|
|
severity: parameter.severity
|
|
)
|
|
)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|