@@ -11,5 +11,89 @@ import SwiftSyntax
11
11
///
12
12
/// - SeeAlso: https://google.github.io/swift#enum-cases
13
13
public final class OneCasePerLine : SyntaxFormatRule {
14
+
15
+ public override func visit( _ node: EnumDeclSyntax ) -> DeclSyntax {
16
+ let enumMembers = node. members. members
17
+ var newMembers : [ MemberDeclListItemSyntax ] = [ ]
18
+ var newIndx = 0
19
+
20
+ for member in enumMembers {
21
+ var numNewMembers = 0
22
+ if let caseMember = member. decl as? EnumCaseDeclSyntax {
23
+ var otherDecl : EnumCaseDeclSyntax ? = caseMember
24
+ // Add and skip single element case declarations
25
+ guard caseMember. elements. count > 1 else {
26
+ let newMember = SyntaxFactory . makeMemberDeclListItem ( decl: caseMember, semicolon: nil )
27
+ newMembers. append ( newMember)
28
+ newIndx += 1
29
+ continue
30
+ }
31
+ // Move all cases with associated/raw values to new declarations
32
+ for element in caseMember. elements {
33
+ if element. associatedValue != nil || element. rawValue != nil {
34
+ diagnose ( . moveAssociatedOrRawValueCase( name: element. identifier. text) , on: element)
35
+ let newRemovedDecl = createAssociateOrRawCaseDecl ( fullDecl: caseMember,
36
+ removedElement: element)
37
+ otherDecl = removeAssociateOrRawCaseDecl ( fullDecl: otherDecl)
38
+ let newMember = SyntaxFactory . makeMemberDeclListItem ( decl: newRemovedDecl,
39
+ semicolon: nil )
40
+ newMembers. append ( newMember)
41
+ numNewMembers += 1
42
+ }
43
+ }
44
+ // Add case declaration of remaining elements without associated/raw values, if any
45
+ if let otherDecl = otherDecl {
46
+ let newMember = SyntaxFactory . makeMemberDeclListItem ( decl: otherDecl, semicolon: nil )
47
+ newMembers. insert ( newMember, at: newIndx)
48
+ newIndx += 1
49
+ }
50
+ // Add any member that isn't an enum case declaration
51
+ } else {
52
+ newMembers. append ( member)
53
+ newIndx += 1
54
+ }
55
+ newIndx += numNewMembers
56
+ }
14
57
58
+ let newDeclList = SyntaxFactory . makeMemberDeclList ( newMembers)
59
+ let newMemberBlock = SyntaxFactory . makeMemberDeclBlock ( leftBrace: node. members. leftBrace,
60
+ members: newDeclList,
61
+ rightBrace: node. members. rightBrace)
62
+ return node. withMembers ( newMemberBlock)
63
+ }
64
+
65
+ func createAssociateOrRawCaseDecl( fullDecl: EnumCaseDeclSyntax ,
66
+ removedElement: EnumCaseElementSyntax ) -> EnumCaseDeclSyntax {
67
+ let formattedElement = removedElement. withTrailingComma ( nil )
68
+ let newElementList = SyntaxFactory . makeEnumCaseElementList ( [ formattedElement] )
69
+ let newDecl = SyntaxFactory . makeEnumCaseDecl ( attributes: fullDecl. attributes,
70
+ modifiers: fullDecl. modifiers,
71
+ caseKeyword: fullDecl. caseKeyword,
72
+ elements: newElementList)
73
+ return newDecl
74
+ }
75
+
76
+ // Returns formatted declaration of cases without associated/raw values, or nil if all cases had
77
+ // a raw or associate value
78
+ func removeAssociateOrRawCaseDecl( fullDecl: EnumCaseDeclSyntax ? ) -> EnumCaseDeclSyntax ? {
79
+ guard let fullDecl = fullDecl else { return nil }
80
+ var newList : [ EnumCaseElementSyntax ] = [ ]
81
+
82
+ for element in fullDecl. elements {
83
+ if element. associatedValue == nil && element. rawValue == nil { newList. append ( element) }
84
+ }
85
+
86
+ guard newList. count > 0 else { return nil }
87
+ let ( last, indx) = ( newList [ newList. count - 1 ] , newList. count - 1 )
88
+ if last. trailingComma != nil {
89
+ newList [ indx] = last. withTrailingComma ( nil )
90
+ }
91
+ return fullDecl. withElements ( SyntaxFactory . makeEnumCaseElementList ( newList) )
92
+ }
93
+ }
94
+
95
+ extension Diagnostic . Message {
96
+ static func moveAssociatedOrRawValueCase( name: String ) -> Diagnostic . Message {
97
+ return . init( . warning, " move \( name) case to a new line " )
98
+ }
15
99
}
0 commit comments