Files
SwiftLint/Source/SwiftLintBuiltInRules/Rules/Metrics/FunctionParameterCountRule.swift

78 lines
3.3 KiB
Swift

import SwiftSyntax
@SwiftSyntaxRule
struct FunctionParameterCountRule: Rule {
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) {}}
"""),
]
)
}
private extension FunctionParameterCountRule {
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
override func visitPost(_ node: FunctionDeclSyntax) {
guard !node.modifiers.contains(keyword: .override) else {
return
}
let parameterList = node.signature.parameterClause.parameters
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.defaultValue != 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
}
}
}
}