Skip to content

Commit 23efd94

Browse files
committed
multiline_parameters: add optional checks for function call arguments
1 parent 57d6752 commit 23efd94

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MultilineParametersConfiguration.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,19 @@ struct MultilineParametersConfiguration: SeverityBasedRuleConfiguration {
1010
private(set) var allowsSingleLine = true
1111
@ConfigurationElement(key: "max_number_of_single_line_parameters")
1212
private(set) var maxNumberOfSingleLineParameters: Int?
13+
@ConfigurationElement(key: "check_calls")
14+
private(set) var checkCalls = false
1315

1416
func validate() throws {
17+
if checkCalls, maxNumberOfSingleLineParameters == nil {
18+
Issue.inconsistentConfiguration(
19+
ruleID: Parent.identifier,
20+
message: """
21+
Option '\($checkCalls.key)' has no effect when \
22+
'\($maxNumberOfSingleLineParameters.key)' is nil.
23+
"""
24+
).print()
25+
}
1526
guard let maxNumberOfSingleLineParameters else {
1627
return
1728
}
@@ -32,5 +43,15 @@ struct MultilineParametersConfiguration: SeverityBasedRuleConfiguration {
3243
"""
3344
).print()
3445
}
46+
47+
if checkCalls, !allowsSingleLine {
48+
Issue.inconsistentConfiguration(
49+
ruleID: Parent.identifier,
50+
message: """
51+
Option '\($checkCalls.key)' has no effect when \
52+
'\($allowsSingleLine.key)' is false.
53+
"""
54+
).print()
55+
}
3556
}
3657
}

Source/SwiftLintBuiltInRules/Rules/Style/MultilineParametersRule.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ struct MultilineParametersRule: Rule {
77
static let description = RuleDescription(
88
identifier: "multiline_parameters",
99
name: "Multiline Parameters",
10-
description: "Functions and methods parameters should be either on the same line, or one per line",
10+
description: """
11+
Functions, initializers, and function call arguments should be either on the same line, or one per line
12+
""",
1113
kind: .style,
1214
nonTriggeringExamples: MultilineParametersRuleExamples.nonTriggeringExamples,
1315
triggeringExamples: MultilineParametersRuleExamples.triggeringExamples
@@ -28,8 +30,28 @@ private extension MultilineParametersRule {
2830
}
2931
}
3032

33+
override func visitPost(_ node: FunctionCallExprSyntax) {
34+
guard node.arguments.isNotEmpty else { return }
35+
guard configuration.checkCalls else { return }
36+
guard node.trailingClosure == nil else { return }
37+
38+
if containsViolation(for: node.arguments) {
39+
let anchor = node.calledExpression.positionAfterSkippingLeadingTrivia
40+
violations.append(anchor)
41+
}
42+
}
43+
3144
private func containsViolation(for signature: FunctionSignatureSyntax) -> Bool {
3245
let parameterPositions = signature.parameterClause.parameters.map(\.positionAfterSkippingLeadingTrivia)
46+
return containsViolation(parameterPositions: parameterPositions)
47+
}
48+
49+
private func containsViolation(for arguments: LabeledExprListSyntax) -> Bool {
50+
let argumentPositions = arguments.map(\.positionAfterSkippingLeadingTrivia)
51+
return containsViolation(parameterPositions: argumentPositions)
52+
}
53+
54+
private func containsViolation(parameterPositions: [AbsolutePosition]) -> Bool {
3355
guard parameterPositions.isNotEmpty else {
3456
return false
3557
}

Source/SwiftLintBuiltInRules/Rules/Style/MultilineParametersRuleExamples.swift

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,20 @@ internal struct MultilineParametersRuleExamples {
213213
param3: [String]
214214
) { }
215215
""", configuration: ["max_number_of_single_line_parameters": 2]),
216+
Example("""
217+
foo(
218+
param1: "param1",
219+
param2: false,
220+
param3: []
221+
)
222+
""", configuration: ["max_number_of_single_line_parameters": 2]),
223+
Example("""
224+
foo(param1: 1,
225+
param2: false,
226+
param3: [])
227+
""", configuration: ["max_number_of_single_line_parameters": 1]),
228+
Example("foo(param1: 1, param2: false)",
229+
configuration: ["max_number_of_single_line_parameters": 2]),
216230
]
217231

218232
static let triggeringExamples: [Example] = [
@@ -360,6 +374,27 @@ internal struct MultilineParametersRuleExamples {
360374
""", configuration: ["max_number_of_single_line_parameters": 3]),
361375
Example("""
362376
func ↓foo(param1: Int, param2: Bool, param3: [String]) { }
363-
""", configuration: ["max_number_of_single_line_parameters": 2]),
377+
""", configuration: [
378+
"max_number_of_single_line_parameters": 2,
379+
"check_calls": true,
380+
]),
381+
Example("↓foo(param1: 1, param2: false, param3: [])",
382+
configuration: [
383+
"max_number_of_single_line_parameters": 2,
384+
"check_calls": true,
385+
]),
386+
Example("""
387+
func ↓foo(param1: Int,
388+
param2: Bool, param3: [String]) { }
389+
""", configuration: [
390+
"max_number_of_single_line_parameters": 3,
391+
"check_calls": true,
392+
]),
393+
Example("""
394+
↓foo(param1: Int, param2: Bool, param3: [String])
395+
""", configuration: [
396+
"max_number_of_single_line_parameters": 2,
397+
"check_calls": true,
398+
]),
364399
]
365400
}

Tests/IntegrationTests/default_rule_configurations.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ multiline_literal_brackets:
684684
multiline_parameters:
685685
severity: warning
686686
allows_single_line: true
687+
check_calls: false
687688
meta:
688689
opt-in: true
689690
correctable: false

0 commit comments

Comments
 (0)