Skip to content

Commit 36d3063

Browse files
atamez31allevato
authored andcommitted
Implement case indent level equals switch (swiftlang#72)
1 parent eb3904a commit 36d3063

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

Diff for: Sources/Rules/CaseIndentLevelEqualsSwitch.swift

+41
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,46 @@ import SwiftSyntax
1111
///
1212
/// - SeeAlso: https://google.github.io/swift#switch-statements
1313
public final class CaseIndentLevelEqualsSwitch: SyntaxFormatRule {
14+
public override func visit(_ node: SwitchStmtSyntax) -> StmtSyntax {
15+
var cases = [Syntax]()
16+
guard let switchIndentation = node.leadingTrivia?.numberOfSpaces else { return node }
17+
var spacesDif: Int
18+
var isInvalid = false
1419

20+
// Iterates through the switch stamentent to ensure the number of spaces
21+
// in the indentation of each case is the same as the switch keyword.
22+
for caseExp in node.cases {
23+
guard let caseTrivia = caseExp.leadingTrivia else { continue }
24+
25+
if caseTrivia.numberOfSpaces != switchIndentation {
26+
spacesDif = switchIndentation - caseTrivia.numberOfSpaces
27+
diagnose(
28+
.adjustIndentationSpaces(
29+
count: spacesDif,
30+
caseText: caseExp.description),
31+
on: node
32+
)
33+
34+
let newCase = replaceTrivia(on: caseExp, token: caseExp.firstToken, leadingTrivia:
35+
Trivia.newlines(caseTrivia.numberOfNewlines).appending(.spaces(switchIndentation)))
36+
isInvalid = true
37+
cases.append(newCase)
38+
}
39+
else {
40+
cases.append(caseExp)
41+
}
42+
}
43+
return isInvalid ? node.withCases(SyntaxFactory.makeSwitchCaseList(cases)) : node
44+
}
45+
}
46+
47+
extension Diagnostic.Message {
48+
static func adjustIndentationSpaces(count: Int, caseText: String) -> Diagnostic.Message {
49+
let adjustSpaces = count < 0 ? "remove" : "add"
50+
let ending = abs(count) == 1 ? "" : "s"
51+
return Diagnostic.Message(
52+
.warning,
53+
"\(adjustSpaces) \(abs(count)) space\(ending) as indentation to the case \(caseText)"
54+
)
55+
}
1556
}

Diff for: Sources/Rules/Trivia+Convenience.swift

+11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ extension Trivia {
1212
return count
1313
}
1414

15+
/// Returns the number of newlines after this node.
16+
var numberOfNewlines: Int {
17+
var count = 0
18+
for piece in self {
19+
if case .newlines(let n) = piece {
20+
count += n
21+
}
22+
}
23+
return count
24+
}
25+
1526
/// Returns this set of trivia, without any whitespace characters.
1627
func withoutSpaces() -> Trivia {
1728
return Trivia(pieces: filter {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import Foundation
2+
import XCTest
3+
import SwiftSyntax
4+
5+
@testable import Rules
6+
7+
public class CaseIndentLevelEqualsSwitchTests: DiagnosingTestCase {
8+
public func testsInvalidCaseIndent() {
9+
XCTAssertFormatting(
10+
CaseIndentLevelEqualsSwitch.self,
11+
input: """
12+
switch order {
13+
14+
case .ascending:
15+
print("Ascending")
16+
case .descending:
17+
print("Descending")
18+
case .same:
19+
print("Same")
20+
}
21+
""",
22+
expected: """
23+
switch order {
24+
25+
case .ascending:
26+
print("Ascending")
27+
case .descending:
28+
print("Descending")
29+
case .same:
30+
print("Same")
31+
}
32+
""")
33+
}
34+
35+
public func testsInvalidNestedCaseIndent() {
36+
XCTAssertFormatting(
37+
CaseIndentLevelEqualsSwitch.self,
38+
input: """
39+
if true {
40+
switch order {
41+
case .ascending:
42+
print("Ascending")
43+
case .descending:
44+
print("Descending")
45+
case .same:
46+
print("Same")
47+
}
48+
}
49+
""",
50+
expected: """
51+
if true {
52+
switch order {
53+
case .ascending:
54+
print("Ascending")
55+
case .descending:
56+
print("Descending")
57+
case .same:
58+
print("Same")
59+
}
60+
}
61+
""")
62+
}
63+
64+
#if !os(macOS)
65+
static let allTests = [
66+
CaseIndentLevelEqualsSwitchTests.testsInvalidCaseIndent,
67+
CaseIndentLevelEqualsSwitchTests.testsInvalidNestedCaseIndent
68+
]
69+
#endif
70+
71+
}

0 commit comments

Comments
 (0)