Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@
* Rewrite `quick_discouraged_call` rule with SwiftSyntax.
[SimplyDanny](https://github.com/SimplyDanny)

* `multiline_parameters`: add optional checks for **function call arguments**.
When `check_calls` is enabled, the rule enforces that call arguments are either
all on one line (subject to `max_number_of_single_line_parameters`) or
one per line, mirroring the behavior for function/initializer declarations.
Trailing closures are ignored by default.
[GandaLF2006](https://github.com/GandaLF2006)

### Bug Fixes

* Ensure that header matched against always end in a newline in `file_header` rule.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@ struct MultilineParametersConfiguration: SeverityBasedRuleConfiguration {
private(set) var allowsSingleLine = true
@ConfigurationElement(key: "max_number_of_single_line_parameters")
private(set) var maxNumberOfSingleLineParameters: Int?
@ConfigurationElement(key: "check_calls")
private(set) var checkCalls = false

func validate() throws {
if checkCalls, maxNumberOfSingleLineParameters == nil {
Issue.inconsistentConfiguration(
ruleID: Parent.identifier,
message: """
Option '\($checkCalls.key)' has no effect when \
'\($maxNumberOfSingleLineParameters.key)' is nil.
"""
).print()
}
guard let maxNumberOfSingleLineParameters else {
return
}
Expand All @@ -32,5 +43,15 @@ struct MultilineParametersConfiguration: SeverityBasedRuleConfiguration {
"""
).print()
}

if checkCalls, !allowsSingleLine {
Issue.inconsistentConfiguration(
ruleID: Parent.identifier,
message: """
Option '\($checkCalls.key)' has no effect when \
'\($allowsSingleLine.key)' is false.
"""
).print()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ struct MultilineParametersRule: Rule {
static let description = RuleDescription(
identifier: "multiline_parameters",
name: "Multiline Parameters",
description: "Functions and methods parameters should be either on the same line, or one per line",
description: """
Functions, initializers, and function call arguments should be either on the same line, or one per line
""",
kind: .style,
nonTriggeringExamples: MultilineParametersRuleExamples.nonTriggeringExamples,
triggeringExamples: MultilineParametersRuleExamples.triggeringExamples
Expand All @@ -28,8 +30,28 @@ private extension MultilineParametersRule {
}
}

override func visitPost(_ node: FunctionCallExprSyntax) {
guard node.arguments.isNotEmpty else { return }
guard configuration.checkCalls else { return }
guard node.trailingClosure == nil else { return }

if containsViolation(for: node.arguments) {
let anchor = node.calledExpression.positionAfterSkippingLeadingTrivia
violations.append(anchor)
}
}

private func containsViolation(for signature: FunctionSignatureSyntax) -> Bool {
let parameterPositions = signature.parameterClause.parameters.map(\.positionAfterSkippingLeadingTrivia)
return containsViolation(parameterPositions: parameterPositions)
}

private func containsViolation(for arguments: LabeledExprListSyntax) -> Bool {
let argumentPositions = arguments.map(\.positionAfterSkippingLeadingTrivia)
return containsViolation(parameterPositions: argumentPositions)
}

private func containsViolation(parameterPositions: [AbsolutePosition]) -> Bool {
guard parameterPositions.isNotEmpty else {
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,20 @@ internal struct MultilineParametersRuleExamples {
param3: [String]
) { }
""", configuration: ["max_number_of_single_line_parameters": 2]),
Example("""
foo(
param1: "param1",
param2: false,
param3: []
)
""", configuration: ["max_number_of_single_line_parameters": 2]),
Example("""
foo(param1: 1,
param2: false,
param3: [])
""", configuration: ["max_number_of_single_line_parameters": 1]),
Example("foo(param1: 1, param2: false)",
configuration: ["max_number_of_single_line_parameters": 2]),
]

static let triggeringExamples: [Example] = [
Expand Down Expand Up @@ -360,6 +374,27 @@ internal struct MultilineParametersRuleExamples {
""", configuration: ["max_number_of_single_line_parameters": 3]),
Example("""
func ↓foo(param1: Int, param2: Bool, param3: [String]) { }
""", configuration: ["max_number_of_single_line_parameters": 2]),
""", configuration: [
"max_number_of_single_line_parameters": 2,
"check_calls": true,
]),
Example("↓foo(param1: 1, param2: false, param3: [])",
configuration: [
"max_number_of_single_line_parameters": 2,
"check_calls": true,
]),
Example("""
func ↓foo(param1: Int,
param2: Bool, param3: [String]) { }
""", configuration: [
"max_number_of_single_line_parameters": 3,
"check_calls": true,
]),
Example("""
↓foo(param1: Int, param2: Bool, param3: [String])
""", configuration: [
"max_number_of_single_line_parameters": 2,
"check_calls": true,
]),
]
}
1 change: 1 addition & 0 deletions Tests/IntegrationTests/default_rule_configurations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ multiline_literal_brackets:
multiline_parameters:
severity: warning
allows_single_line: true
check_calls: false
meta:
opt-in: true
correctable: false
Expand Down