Skip to content

Commit 7867cda

Browse files
committed
Merge pull request #224 from dylansturg/more_lowercase
Apply AlwaysUseLowerCamelCase in more places.
1 parent 642c2d1 commit 7867cda

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

Sources/SwiftFormat/Pipelines+Generated.swift

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class LintPipeline: SyntaxVisitor {
5151
}
5252

5353
override func visit(_ node: ClosureSignatureSyntax) -> SyntaxVisitorContinueKind {
54+
visitIfEnabled(AlwaysUseLowerCamelCase.visit, in: context, for: node)
5455
visitIfEnabled(ReturnVoidInsteadOfEmptyTuple.visit, in: context, for: node)
5556
return .visitChildren
5657
}
@@ -176,6 +177,11 @@ class LintPipeline: SyntaxVisitor {
176177
return .visitChildren
177178
}
178179

180+
override func visit(_ node: OptionalBindingConditionSyntax) -> SyntaxVisitorContinueKind {
181+
visitIfEnabled(AlwaysUseLowerCamelCase.visit, in: context, for: node)
182+
return .visitChildren
183+
}
184+
179185
override func visit(_ node: PatternBindingSyntax) -> SyntaxVisitorContinueKind {
180186
visitIfEnabled(UseSingleLinePropertyGetter.visit, in: context, for: node)
181187
return .visitChildren

Sources/SwiftFormatRules/AlwaysUseLowerCamelCase.swift

+49-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,39 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
5858
diagnoseLowerCamelCaseViolations(
5959
pat.identifier, allowUnderscores: false, description: identifierDescription(for: node))
6060
}
61-
return .skipChildren
61+
return .visitChildren
62+
}
63+
64+
public override func visit(_ node: OptionalBindingConditionSyntax) -> SyntaxVisitorContinueKind {
65+
guard let pattern = node.pattern.as(IdentifierPatternSyntax.self) else {
66+
return .visitChildren
67+
}
68+
diagnoseLowerCamelCaseViolations(
69+
pattern.identifier, allowUnderscores: false, description: identifierDescription(for: node))
70+
return .visitChildren
71+
}
72+
73+
public override func visit(_ node: ClosureSignatureSyntax) -> SyntaxVisitorContinueKind {
74+
if let input = node.input {
75+
if let closureParamList = input.as(ClosureParamListSyntax.self) {
76+
for param in closureParamList {
77+
diagnoseLowerCamelCaseViolations(
78+
param.name, allowUnderscores: false, description: identifierDescription(for: node))
79+
}
80+
} else if let parameterClause = input.as(ParameterClauseSyntax.self) {
81+
for param in parameterClause.parameterList {
82+
if let firstName = param.firstName {
83+
diagnoseLowerCamelCaseViolations(
84+
firstName, allowUnderscores: false, description: identifierDescription(for: node))
85+
}
86+
if let secondName = param.secondName {
87+
diagnoseLowerCamelCaseViolations(
88+
secondName, allowUnderscores: false, description: identifierDescription(for: node))
89+
}
90+
}
91+
}
92+
}
93+
return .visitChildren
6294
}
6395

6496
public override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
@@ -68,7 +100,19 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
68100
diagnoseLowerCamelCaseViolations(
69101
node.identifier, allowUnderscores: allowUnderscores,
70102
description: identifierDescription(for: node))
71-
return .skipChildren
103+
for param in node.signature.input.parameterList {
104+
// These identifiers aren't described using `identifierDescription(for:)` because no single
105+
// node can disambiguate the argument label from the parameter name.
106+
if let label = param.firstName {
107+
diagnoseLowerCamelCaseViolations(
108+
label, allowUnderscores: false, description: "argument label")
109+
}
110+
if let paramName = param.secondName {
111+
diagnoseLowerCamelCaseViolations(
112+
paramName, allowUnderscores: false, description: "function parameter")
113+
}
114+
}
115+
return .visitChildren
72116
}
73117

74118
public override func visit(_ node: EnumCaseElementSyntax) -> SyntaxVisitorContinueKind {
@@ -97,8 +141,11 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
97141
/// - Returns: A human readable description of the node and its identifier.
98142
fileprivate func identifierDescription<NodeType: SyntaxProtocol>(for node: NodeType) -> String {
99143
switch Syntax(node).as(SyntaxEnum.self) {
144+
case .closureSignature: return "closure parameter"
100145
case .enumCaseElement: return "enum case"
101146
case .functionDecl: return "function"
147+
case .optionalBindingCondition(let binding):
148+
return binding.letOrVarKeyword.tokenKind == .varKeyword ? "variable" : "constant"
102149
case .variableDecl(let variableDecl):
103150
return variableDecl.letOrVarKeyword.tokenKind == .varKeyword ? "variable" : "constant"
104151
default:

Tests/SwiftFormatRulesTests/AlwaysUseLowerCamelCaseTests.swift

+37
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ final class AlwaysUseLowerCamelCaseTests: LintOrFormatRuleTestCase {
2323
case UpperCamelCase
2424
case lowerCamelCase
2525
}
26+
if let Baz = foo { }
27+
guard let foo = [1, 2, 3, 4].first(where: { BadName -> Bool in
28+
let TerribleName = BadName
29+
return TerribleName != 0
30+
}) else { return }
31+
var fooVar = [1, 2, 3, 4].first(where: { BadNameInFooVar -> Bool in
32+
let TerribleNameInFooVar = BadName
33+
return TerribleName != 0
34+
})
35+
var abc = array.first(where: { (CParam1, _ CParam2: Type, cparam3) -> Bool in return true })
36+
func wellNamedFunc(_ BadFuncArg1: Int, BadFuncArgLabel goodFuncArg: String) {
37+
var PoorlyNamedVar = 0
38+
}
2639
"""
2740
performLint(AlwaysUseLowerCamelCase.self, input: input)
2841
XCTAssertDiagnosed(
@@ -39,6 +52,30 @@ final class AlwaysUseLowerCamelCaseTests: LintOrFormatRuleTestCase {
3952
line: 9, column: 8)
4053
XCTAssertDiagnosed(
4154
.nameMustBeLowerCamelCase("UpperCamelCase", description: "enum case"), line: 12, column: 8)
55+
XCTAssertDiagnosed(
56+
.nameMustBeLowerCamelCase("Baz", description: "constant"), line: 15, column: 8)
57+
XCTAssertDiagnosed(
58+
.nameMustBeLowerCamelCase("BadName", description: "closure parameter"), line: 16, column: 45)
59+
XCTAssertDiagnosed(
60+
.nameMustBeLowerCamelCase("TerribleName", description: "constant"), line: 17, column: 7)
61+
XCTAssertDiagnosed(
62+
.nameMustBeLowerCamelCase("BadNameInFooVar", description: "closure parameter"),
63+
line: 20, column: 42)
64+
XCTAssertDiagnosed(
65+
.nameMustBeLowerCamelCase("TerribleNameInFooVar", description: "constant"),
66+
line: 21, column: 7)
67+
XCTAssertDiagnosed(
68+
.nameMustBeLowerCamelCase("CParam1", description: "closure parameter"), line: 24, column: 33)
69+
XCTAssertDiagnosed(
70+
.nameMustBeLowerCamelCase("CParam2", description: "closure parameter"), line: 24, column: 44)
71+
XCTAssertDiagnosed(
72+
.nameMustBeLowerCamelCase("BadFuncArg1", description: "function parameter"),
73+
line: 25, column: 22)
74+
XCTAssertDiagnosed(
75+
.nameMustBeLowerCamelCase("BadFuncArgLabel", description: "argument label"),
76+
line: 25, column: 40)
77+
XCTAssertDiagnosed(
78+
.nameMustBeLowerCamelCase("PoorlyNamedVar", description: "variable"), line: 26, column: 7)
4279
}
4380

4481
func testIgnoresUnderscoresInTestNames() {

0 commit comments

Comments
 (0)