Skip to content

Commit be4493c

Browse files
committed
[Lint] Adjust capitalization rule to properly handle underscored names
1 parent 5538ecb commit be4493c

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

Sources/SwiftFormatRules/TypeNamesShouldBeCapitalized.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,20 @@ public final class TypeNamesShouldBeCapitalized : SyntaxLintRule {
5353
}
5454

5555
private func diagnoseNameConventionMismatch<T: DeclSyntaxProtocol>(_ type: T, name: TokenSyntax) {
56-
if let firstChar = name.text.first, !firstChar.isUppercase {
56+
let leadingUnderscores = name.text.prefix { $0 == "_" }
57+
if let firstChar = name.text[leadingUnderscores.endIndex...].first,
58+
firstChar.uppercased() != String(firstChar) {
5759
diagnose(.capitalizeTypeName(name: name.text), on: type, severity: .convention)
5860
}
5961
}
6062
}
6163

6264
extension Finding.Message {
6365
public static func capitalizeTypeName(name: String) -> Finding.Message {
64-
let capitalized = name.prefix(1).uppercased() + name.dropFirst()
66+
var capitalized = name
67+
let leadingUnderscores = capitalized.prefix { $0 == "_" }
68+
let charAt = leadingUnderscores.endIndex
69+
capitalized.replaceSubrange(charAt...charAt, with: capitalized[charAt].uppercased())
6570
return "type names should be capitalized: \(name) -> \(capitalized)"
6671
}
6772
}

Tests/SwiftFormatRulesTests/TypeNamesShouldBeCapitalizedTests.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,58 @@ final class TypeNamesShouldBeCapitalizedTests: LintOrFormatRuleTestCase {
7171
XCTAssertDiagnosed(.capitalizeTypeName(name: "data"))
7272
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "Value"))
7373
}
74+
75+
func testThatUnderscoredNamesAreDiagnosed() {
76+
let input =
77+
"""
78+
protocol _p {
79+
associatedtype _value
80+
associatedtype __Value
81+
}
82+
83+
protocol ___Q {
84+
}
85+
86+
struct _data {
87+
typealias _x = Int
88+
}
89+
90+
struct _Data {}
91+
92+
actor _internalActor {}
93+
94+
enum __e {
95+
}
96+
97+
enum _OtherE {
98+
}
99+
100+
func test() {
101+
class _myClass {}
102+
do {
103+
class _MyClass {}
104+
}
105+
}
106+
107+
distributed actor __greeter {}
108+
distributed actor __InternalGreeter {}
109+
"""
110+
111+
performLint(TypeNamesShouldBeCapitalized.self, input: input)
112+
113+
XCTAssertDiagnosed(.capitalizeTypeName(name: "_p"))
114+
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "___Q"))
115+
XCTAssertDiagnosed(.capitalizeTypeName(name: "_value"))
116+
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "__Value"))
117+
XCTAssertDiagnosed(.capitalizeTypeName(name: "_data"))
118+
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "_Data"))
119+
XCTAssertDiagnosed(.capitalizeTypeName(name: "_x"))
120+
XCTAssertDiagnosed(.capitalizeTypeName(name: "_internalActor"))
121+
XCTAssertDiagnosed(.capitalizeTypeName(name: "__e"))
122+
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "__OtherE"))
123+
XCTAssertDiagnosed(.capitalizeTypeName(name: "_myClass"))
124+
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "_MyClass"))
125+
XCTAssertDiagnosed(.capitalizeTypeName(name: "__greeter"))
126+
XCTAssertNotDiagnosed(.capitalizeTypeName(name: "__InternalGreeter"))
127+
}
74128
}

0 commit comments

Comments
 (0)