Skip to content

Commit 97628a8

Browse files
committed
Merge pull request #222 from dylansturg/accurate_decltypes
Specify the type of decl to rename in AlwaysUseLowerCamelCase.
1 parent 9080762 commit 97628a8

File tree

2 files changed

+67
-24
lines changed

2 files changed

+67
-24
lines changed

Sources/SwiftFormatRules/AlwaysUseLowerCamelCase.swift

+31-7
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
5555
guard let pat = binding.pattern.as(IdentifierPatternSyntax.self) else {
5656
continue
5757
}
58-
diagnoseLowerCamelCaseViolations(pat.identifier, allowUnderscores: false)
58+
diagnoseLowerCamelCaseViolations(
59+
pat.identifier, allowUnderscores: false, description: identifierDescription(for: node))
5960
}
6061
return .skipChildren
6162
}
@@ -64,26 +65,47 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
6465
// We allow underscores in test names, because there's an existing convention of using
6566
// underscores to separate phrases in very detailed test names.
6667
let allowUnderscores = testCaseFuncs.contains(node)
67-
diagnoseLowerCamelCaseViolations(node.identifier, allowUnderscores: allowUnderscores)
68+
diagnoseLowerCamelCaseViolations(
69+
node.identifier, allowUnderscores: allowUnderscores,
70+
description: identifierDescription(for: node))
6871
return .skipChildren
6972
}
7073

7174
public override func visit(_ node: EnumCaseElementSyntax) -> SyntaxVisitorContinueKind {
72-
diagnoseLowerCamelCaseViolations(node.identifier, allowUnderscores: false)
75+
diagnoseLowerCamelCaseViolations(
76+
node.identifier, allowUnderscores: false, description: identifierDescription(for: node))
7377
return .skipChildren
7478
}
7579

76-
private func diagnoseLowerCamelCaseViolations(_ identifier: TokenSyntax, allowUnderscores: Bool) {
80+
private func diagnoseLowerCamelCaseViolations(
81+
_ identifier: TokenSyntax, allowUnderscores: Bool, description: String
82+
) {
7783
guard case .identifier(let text) = identifier.tokenKind else { return }
7884
if text.isEmpty { return }
7985
if (text.dropFirst().contains("_") && !allowUnderscores) || ("A"..."Z").contains(text.first!) {
80-
diagnose(.variableNameMustBeLowerCamelCase(text), on: identifier) {
86+
diagnose(.nameMustBeLowerCamelCase(text, description: description), on: identifier) {
8187
$0.highlight(identifier.sourceRange(converter: self.context.sourceLocationConverter))
8288
}
8389
}
8490
}
8591
}
8692

93+
/// Returns a human readable description of the node type that can be used to describe the
94+
/// identifier of the node in diagnostics from this rule.
95+
///
96+
/// - Parameter node: A node whose identifier may be used in diagnostics.
97+
/// - Returns: A human readable description of the node and its identifier.
98+
fileprivate func identifierDescription<NodeType: SyntaxProtocol>(for node: NodeType) -> String {
99+
switch Syntax(node).as(SyntaxEnum.self) {
100+
case .enumCaseElement: return "enum case"
101+
case .functionDecl: return "function"
102+
case .variableDecl(let variableDecl):
103+
return variableDecl.letOrVarKeyword.tokenKind == .varKeyword ? "variable" : "constant"
104+
default:
105+
return "identifier"
106+
}
107+
}
108+
87109
extension ReturnClauseSyntax {
88110
/// Whether this return clause specifies an explicit `Void` return type.
89111
fileprivate var isVoid: Bool {
@@ -98,7 +120,9 @@ extension ReturnClauseSyntax {
98120
}
99121

100122
extension Diagnostic.Message {
101-
public static func variableNameMustBeLowerCamelCase(_ name: String) -> Diagnostic.Message {
102-
return .init(.warning, "rename variable '\(name)' using lower-camel-case")
123+
public static func nameMustBeLowerCamelCase(
124+
_ name: String, description: String
125+
) -> Diagnostic.Message {
126+
return .init(.warning, "rename \(description) '\(name)' using lower-camel-case")
103127
}
104128
}

Tests/SwiftFormatRulesTests/AlwaysUseLowerCamelCaseTests.swift

+36-17
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,26 @@ final class AlwaysUseLowerCamelCaseTests: LintOrFormatRuleTestCase {
1919
class UnitTests: XCTestCase {
2020
func test_HappyPath_Through_GoodCode() {}
2121
}
22+
enum FooBarCases {
23+
case UpperCamelCase
24+
case lowerCamelCase
25+
}
2226
"""
2327
performLint(AlwaysUseLowerCamelCase.self, input: input)
24-
XCTAssertDiagnosed(.variableNameMustBeLowerCamelCase("Test"), line: 1, column: 5)
25-
XCTAssertNotDiagnosed(.variableNameMustBeLowerCamelCase("foo"))
26-
XCTAssertDiagnosed(.variableNameMustBeLowerCamelCase("bad_name"), line: 3, column: 5)
27-
XCTAssertNotDiagnosed(.variableNameMustBeLowerCamelCase("_okayName"))
28-
XCTAssertNotDiagnosed(.variableNameMustBeLowerCamelCase("Foo"))
29-
XCTAssertDiagnosed(.variableNameMustBeLowerCamelCase("FooFunc"), line: 6, column: 8)
3028
XCTAssertDiagnosed(
31-
.variableNameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode"), line: 9, column: 8)
29+
.nameMustBeLowerCamelCase("Test", description: "constant"), line: 1, column: 5)
30+
XCTAssertNotDiagnosed(.nameMustBeLowerCamelCase("foo", description: "variable"))
31+
XCTAssertDiagnosed(
32+
.nameMustBeLowerCamelCase("bad_name", description: "variable"), line: 3, column: 5)
33+
XCTAssertNotDiagnosed(.nameMustBeLowerCamelCase("_okayName", description: "variable"))
34+
XCTAssertNotDiagnosed(.nameMustBeLowerCamelCase("Foo", description: "struct"))
35+
XCTAssertDiagnosed(
36+
.nameMustBeLowerCamelCase("FooFunc", description: "function"), line: 6, column: 8)
37+
XCTAssertDiagnosed(
38+
.nameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode", description: "function"),
39+
line: 9, column: 8)
40+
XCTAssertDiagnosed(
41+
.nameMustBeLowerCamelCase("UpperCamelCase", description: "enum case"), line: 12, column: 8)
3242
}
3343

3444
func testIgnoresUnderscoresInTestNames() {
@@ -50,21 +60,30 @@ final class AlwaysUseLowerCamelCaseTests: LintOrFormatRuleTestCase {
5060
}
5161
"""
5262
performLint(AlwaysUseLowerCamelCase.self, input: input)
53-
XCTAssertDiagnosed(.variableNameMustBeLowerCamelCase("Test"), line: 3, column: 5)
54-
XCTAssertDiagnosed(.variableNameMustBeLowerCamelCase("My_Constant_Value"), line: 5, column: 14)
55-
XCTAssertNotDiagnosed(.variableNameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode"))
56-
XCTAssertDiagnosed(.variableNameMustBeLowerCamelCase("FooFunc"), line: 7, column: 16)
5763
XCTAssertDiagnosed(
58-
.variableNameMustBeLowerCamelCase("helperFunc_For_HappyPath_Setup"), line: 8, column: 16)
64+
.nameMustBeLowerCamelCase("Test", description: "constant"), line: 3, column: 5)
65+
XCTAssertDiagnosed(
66+
.nameMustBeLowerCamelCase("My_Constant_Value", description: "constant"), line: 5, column: 14)
67+
XCTAssertNotDiagnosed(
68+
.nameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode", description: "function"))
69+
XCTAssertDiagnosed(
70+
.nameMustBeLowerCamelCase("FooFunc", description: "function"), line: 7, column: 16)
71+
XCTAssertDiagnosed(
72+
.nameMustBeLowerCamelCase("helperFunc_For_HappyPath_Setup", description: "function"),
73+
line: 8, column: 16)
5974
XCTAssertDiagnosed(
60-
.variableNameMustBeLowerCamelCase("testLikeMethod_With_Underscores"), line: 9, column: 16)
75+
.nameMustBeLowerCamelCase("testLikeMethod_With_Underscores", description: "function"),
76+
line: 9, column: 16)
6177
XCTAssertDiagnosed(
62-
.variableNameMustBeLowerCamelCase("testLikeMethod_With_Underscores2"), line: 10, column: 16)
78+
.nameMustBeLowerCamelCase("testLikeMethod_With_Underscores2", description: "function"),
79+
line: 10, column: 16)
6380
XCTAssertNotDiagnosed(
64-
.variableNameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode_ReturnsVoid"))
81+
.nameMustBeLowerCamelCase(
82+
"test_HappyPath_Through_GoodCode_ReturnsVoid", description: "function"))
6583
XCTAssertNotDiagnosed(
66-
.variableNameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode_ReturnsShortVoid"))
84+
.nameMustBeLowerCamelCase(
85+
"test_HappyPath_Through_GoodCode_ReturnsShortVoid", description: "function"))
6786
XCTAssertNotDiagnosed(
68-
.variableNameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode_Throws"))
87+
.nameMustBeLowerCamelCase("test_HappyPath_Through_GoodCode_Throws", description: "function"))
6988
}
7089
}

0 commit comments

Comments
 (0)