Skip to content

Commit 110c45e

Browse files
committed
multiline_parameters: add optional checks for function call arguments
# Conflicts: # Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/MultilineParametersConfiguration.swift
1 parent 32f04fc commit 110c45e

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,9 +10,20 @@ 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
// swiftlint:disable:next unneeded_throws_rethrows
1517
func validate() throws(Issue) {
18+
if checkCalls, maxNumberOfSingleLineParameters == nil {
19+
Issue.inconsistentConfiguration(
20+
ruleID: Parent.identifier,
21+
message: """
22+
Option '\($checkCalls.key)' has no effect when \
23+
'\($maxNumberOfSingleLineParameters.key)' is nil.
24+
"""
25+
).print()
26+
}
1627
guard let maxNumberOfSingleLineParameters else {
1728
return
1829
}
@@ -33,5 +44,15 @@ struct MultilineParametersConfiguration: SeverityBasedRuleConfiguration {
3344
"""
3445
).print()
3546
}
47+
48+
if checkCalls, !allowsSingleLine {
49+
Issue.inconsistentConfiguration(
50+
ruleID: Parent.identifier,
51+
message: """
52+
Option '\($checkCalls.key)' has no effect when \
53+
'\($allowsSingleLine.key)' is false.
54+
"""
55+
).print()
56+
}
3657
}
3758
}

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
@@ -691,6 +691,7 @@ multiline_literal_brackets:
691691
multiline_parameters:
692692
severity: warning
693693
allows_single_line: true
694+
check_calls: false
694695
meta:
695696
opt-in: true
696697
correctable: false

0 commit comments

Comments
 (0)