Skip to content

Commit 0d22a27

Browse files
committed
Adjustments to split FunctionParameterSyntax into multiple nodes for function parameters, closure parameters and enum parameters
Companion of swiftlang/swift-syntax#1455
1 parent 89a0b6f commit 0d22a27

9 files changed

+88
-20
lines changed

Sources/SwiftFormat/Pipelines+Generated.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ class LintPipeline: SyntaxVisitor {
5555
return .visitChildren
5656
}
5757

58+
override func visit(_ node: ClosureParameterSyntax) -> SyntaxVisitorContinueKind {
59+
visitIfEnabled(NoLeadingUnderscores.visit, for: node)
60+
return .visitChildren
61+
}
62+
5863
override func visit(_ node: ClosureSignatureSyntax) -> SyntaxVisitorContinueKind {
5964
visitIfEnabled(AlwaysUseLowerCamelCase.visit, for: node)
6065
visitIfEnabled(ReturnVoidInsteadOfEmptyTuple.visit, for: node)
@@ -92,6 +97,11 @@ class LintPipeline: SyntaxVisitor {
9297
return .visitChildren
9398
}
9499

100+
override func visit(_ node: EnumCaseParameterSyntax) -> SyntaxVisitorContinueKind {
101+
visitIfEnabled(NoLeadingUnderscores.visit, for: node)
102+
return .visitChildren
103+
}
104+
95105
override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
96106
visitIfEnabled(BeginDocumentationCommentWithOneLineSummary.visit, for: node)
97107
visitIfEnabled(DontRepeatTypeInStaticProperties.visit, for: node)

Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,37 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
12571257
return .visitChildren
12581258
}
12591259

1260+
override func visit(_ node: ClosureParameterSyntax) -> SyntaxVisitorContinueKind {
1261+
before(node.firstToken, tokens: .open)
1262+
arrangeAttributeList(node.attributes)
1263+
before(
1264+
node.secondName,
1265+
tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true)))
1266+
after(node.colon, tokens: .break)
1267+
1268+
if let trailingComma = node.trailingComma {
1269+
after(trailingComma, tokens: .close, .break(.same))
1270+
} else {
1271+
after(node.lastToken, tokens: .close)
1272+
}
1273+
return .visitChildren
1274+
}
1275+
1276+
override func visit(_ node: EnumCaseParameterSyntax) -> SyntaxVisitorContinueKind {
1277+
before(node.firstToken, tokens: .open)
1278+
before(
1279+
node.secondName,
1280+
tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true)))
1281+
after(node.colon, tokens: .break)
1282+
1283+
if let trailingComma = node.trailingComma {
1284+
after(trailingComma, tokens: .close, .break(.same))
1285+
} else {
1286+
after(node.lastToken, tokens: .close)
1287+
}
1288+
return .visitChildren
1289+
}
1290+
12601291
override func visit(_ node: FunctionParameterSyntax) -> SyntaxVisitorContinueKind {
12611292
before(node.firstToken, tokens: .open)
12621293
arrangeAttributeList(node.attributes)
@@ -1413,7 +1444,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
14131444
after(node.trailingComma, tokens: .break)
14141445

14151446
if let associatedValue = node.associatedValue {
1416-
arrangeParameterClause(associatedValue, forcesBreakBeforeRightParen: false)
1447+
arrangeEnumCaseParameterClause(associatedValue, forcesBreakBeforeRightParen: false)
14171448
}
14181449

14191450
return .visitChildren
@@ -2606,6 +2637,24 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
26062637
tokens: .break(.close(mustBreak: forcesBreakBeforeRightParen), size: 0), .close)
26072638
}
26082639

2640+
/// Applies formatting to a collection of enum case parameters for a decl.
2641+
///
2642+
/// - Parameters:
2643+
/// - parameters: A node that contains the parameters that can be passed to a decl when its
2644+
/// called.
2645+
/// - forcesBreakBeforeRightParen: Whether a break should be required before the right paren
2646+
/// when the right paren is on a different line than the corresponding left paren.
2647+
private func arrangeEnumCaseParameterClause(
2648+
_ parameters: EnumCaseParameterClauseSyntax, forcesBreakBeforeRightParen: Bool
2649+
) {
2650+
guard !parameters.parameterList.isEmpty else { return }
2651+
2652+
after(parameters.leftParen, tokens: .break(.open, size: 0), .open(argumentListConsistency()))
2653+
before(
2654+
parameters.rightParen,
2655+
tokens: .break(.close(mustBreak: forcesBreakBeforeRightParen), size: 0), .close)
2656+
}
2657+
26092658
/// Applies consistent formatting to the braces and contents of the given node.
26102659
///
26112660
/// - Parameters:

Sources/SwiftFormatRules/AlwaysUseLowerCamelCase.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,8 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
7575
}
7676
} else if let parameterClause = input.as(ParameterClauseSyntax.self) {
7777
for param in parameterClause.parameterList {
78-
if let firstName = param.firstName {
79-
diagnoseLowerCamelCaseViolations(
80-
firstName, allowUnderscores: false, description: identifierDescription(for: node))
81-
}
78+
diagnoseLowerCamelCaseViolations(
79+
param.firstName, allowUnderscores: false, description: identifierDescription(for: node))
8280
if let secondName = param.secondName {
8381
diagnoseLowerCamelCaseViolations(
8482
secondName, allowUnderscores: false, description: identifierDescription(for: node))
@@ -106,10 +104,8 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
106104
for param in node.signature.input.parameterList {
107105
// These identifiers aren't described using `identifierDescription(for:)` because no single
108106
// node can disambiguate the argument label from the parameter name.
109-
if let label = param.firstName {
110-
diagnoseLowerCamelCaseViolations(
111-
label, allowUnderscores: false, description: "argument label")
112-
}
107+
diagnoseLowerCamelCaseViolations(
108+
param.firstName, allowUnderscores: false, description: "argument label")
113109
if let paramName = param.secondName {
114110
diagnoseLowerCamelCaseViolations(
115111
paramName, allowUnderscores: false, description: "function parameter")

Sources/SwiftFormatRules/AmbiguousTrailingClosureOverload.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public final class AmbiguousTrailingClosureOverload: SyntaxLintRule {
4141
for fn in functions {
4242
let params = fn.signature.input.parameterList
4343
guard let firstParam = params.firstAndOnly else { continue }
44-
guard let type = firstParam.type, type.is(FunctionTypeSyntax.self) else { continue }
44+
guard firstParam.type.is(FunctionTypeSyntax.self) else { continue }
4545
if let mods = fn.modifiers, mods.has(modifier: "static") || mods.has(modifier: "class") {
4646
staticOverloads[fn.identifier.text, default: []].append(fn)
4747
} else {

Sources/SwiftFormatRules/FunctionDeclSyntax+Convenience.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extension FunctionDeclSyntax {
1616
/// Constructs a name for a function that includes parameter labels, i.e. `foo(_:bar:)`.
1717
var fullDeclName: String {
1818
let params = signature.input.parameterList.map { param in
19-
"\(param.firstName?.text ?? "_"):"
19+
"\(param.firstName.text):"
2020
}
2121
return "\(identifier.text)(\(params.joined()))"
2222
}

Sources/SwiftFormatRules/NoLeadingUnderscores.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,15 @@ public final class NoLeadingUnderscores: SyntaxLintRule {
5656
return .visitChildren
5757
}
5858

59-
public override func visit(_ node: FunctionParameterSyntax) -> SyntaxVisitorContinueKind {
59+
public override func visit(_ node: ClosureParameterSyntax) -> SyntaxVisitorContinueKind {
60+
// If both names are provided, we want to check `secondName`, which will be the parameter name
61+
// (in that case, `firstName` is the label). If only one name is present, then it is recorded in
62+
// `firstName`, and it is both the label and the parameter name.
63+
diagnoseIfNameStartsWithUnderscore(node.secondName ?? node.firstName)
64+
return .visitChildren
65+
}
66+
67+
public override func visit(_ node: EnumCaseParameterSyntax) -> SyntaxVisitorContinueKind {
6068
// If both names are provided, we want to check `secondName`, which will be the parameter name
6169
// (in that case, `firstName` is the label). If only one name is present, then it is recorded in
6270
// `firstName`, and it is both the label and the parameter name.
@@ -66,6 +74,14 @@ public final class NoLeadingUnderscores: SyntaxLintRule {
6674
return .visitChildren
6775
}
6876

77+
public override func visit(_ node: FunctionParameterSyntax) -> SyntaxVisitorContinueKind {
78+
// If both names are provided, we want to check `secondName`, which will be the parameter name
79+
// (in that case, `firstName` is the label). If only one name is present, then it is recorded in
80+
// `firstName`, and it is both the label and the parameter name.
81+
diagnoseIfNameStartsWithUnderscore(node.secondName ?? node.firstName)
82+
return .visitChildren
83+
}
84+
6985
public override func visit(_ node: GenericParameterSyntax) -> SyntaxVisitorContinueKind {
7086
diagnoseIfNameStartsWithUnderscore(node.name)
7187
return .visitChildren

Sources/SwiftFormatRules/UseSynthesizedInitializer.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ public final class UseSynthesizedInitializer: SyntaxLintRule {
106106
guard parameters.count == properties.count else { return false }
107107
for (idx, parameter) in parameters.enumerated() {
108108

109-
guard let paramId = parameter.firstName, parameter.secondName == nil else { return false }
110-
guard let paramType = parameter.type else { return false }
109+
guard parameter.secondName == nil else { return false }
111110

112111
let property = properties[idx]
113112
let propertyId = property.firstIdentifier
@@ -124,9 +123,9 @@ public final class UseSynthesizedInitializer: SyntaxLintRule {
124123
return false
125124
}
126125

127-
if propertyId.identifier.text != paramId.text
126+
if propertyId.identifier.text != parameter.firstName.text
128127
|| propertyType.description.trimmingCharacters(
129-
in: .whitespaces) != paramType.description.trimmingCharacters(in: .whitespacesAndNewlines)
128+
in: .whitespaces) != parameter.type.description.trimmingCharacters(in: .whitespacesAndNewlines)
130129
{ return false }
131130
}
132131
return true

Sources/SwiftFormatRules/ValidateDocumentationComments.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,7 @@ fileprivate func funcParametersIdentifiers(in paramList: FunctionParameterListSy
139139
// If there is a label and an identifier, then the identifier (`secondName`) is the name that
140140
// should be documented. Otherwise, the label and identifier are the same, occupying
141141
// `firstName`.
142-
guard let parameterIdentifier = parameter.secondName ?? parameter.firstName else {
143-
continue
144-
}
142+
let parameterIdentifier = parameter.secondName ?? parameter.firstName
145143
funcParameters.append(parameterIdentifier.text)
146144
}
147145
return funcParameters

Sources/generate-pipeline/RuleCollector.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ final class RuleCollector {
126126
guard let function = member.decl.as(FunctionDeclSyntax.self) else { continue }
127127
guard function.identifier.text == "visit" else { continue }
128128
let params = function.signature.input.parameterList
129-
guard let firstType = params.firstAndOnly?.type?.as(SimpleTypeIdentifierSyntax.self) else {
129+
guard let firstType = params.firstAndOnly?.type.as(SimpleTypeIdentifierSyntax.self) else {
130130
continue
131131
}
132132
visitedNodes.append(firstType.name.text)

0 commit comments

Comments
 (0)