@@ -22,21 +22,151 @@ let basicFormatFile = SourceFile {
22
22
path: [ AccessPathComponent ( name: " SwiftSyntax " ) ]
23
23
)
24
24
25
- ClassDecl ( modifiers : [ DeclModifier ( name : . open) ] , identifier : " BasicFormat " , inheritanceClause : TypeInheritanceClause { InheritedType ( typeName : Type ( " SyntaxRewriter " ) ) } ) {
25
+ ClassDecl ( " open class BasicFormat: SyntaxRewriter " ) {
26
26
VariableDecl ( " public var indentationLevel: Int = 0 " )
27
27
VariableDecl ( " open var indentation: TriviaPiece { .spaces(indentationLevel * 4) } " )
28
28
VariableDecl ( " public var indentedNewline: Trivia { Trivia(pieces: [.newlines(1), indentation]) } " )
29
29
VariableDecl ( " private var lastRewrittenToken: TokenSyntax? " )
30
+ VariableDecl ( " private var putNextTokenOnNewLine: Bool = false " )
30
31
31
- for node in SYNTAX_NODES where !node. isBase {
32
- if node. isSyntaxCollection {
33
- makeSyntaxCollectionRewriteFunc ( node: node)
34
- } else {
35
- makeLayoutNodeRewriteFunc ( node: node)
32
+ FunctionDecl ( """
33
+ open override func visitPre(_ node: Syntax) {
34
+ if let keyPath = getKeyPath(node), shouldIndent(keyPath) {
35
+ indentationLevel += 1
36
+ }
37
+ if let parent = node.parent, childrenSeparatedByNewline(parent) {
38
+ putNextTokenOnNewLine = true
39
+ }
40
+ }
41
+ """
42
+ )
43
+ FunctionDecl ( """
44
+ open override func visitPost(_ node: Syntax) {
45
+ if let keyPath = getKeyPath(node), shouldIndent(keyPath) {
46
+ indentationLevel -= 1
47
+ }
48
+ }
49
+ """
50
+ )
51
+
52
+ FunctionDecl ( """
53
+ open override func visit(_ node: TokenSyntax) -> TokenSyntax {
54
+ var leadingTrivia = node.leadingTrivia
55
+ var trailingTrivia = node.trailingTrivia
56
+ if requiresLeadingSpace(node.tokenKind) && leadingTrivia.isEmpty && lastRewrittenToken?.trailingTrivia.isEmpty != false {
57
+ leadingTrivia += .space
58
+ }
59
+ if requiresTrailingSpace(node.tokenKind) && trailingTrivia.isEmpty {
60
+ trailingTrivia += .space
61
+ }
62
+ if let keyPath = getKeyPath(Syntax(node)), requiresLeadingNewline(keyPath), !(leadingTrivia.first?.isNewline ?? false) {
63
+ leadingTrivia = .newline + leadingTrivia
64
+ }
65
+ leadingTrivia = leadingTrivia.indented(indentation: indentation)
66
+ trailingTrivia = trailingTrivia.indented(indentation: indentation)
67
+ let rewritten = TokenSyntax(
68
+ node.tokenKind,
69
+ leadingTrivia: leadingTrivia,
70
+ trailingTrivia: trailingTrivia,
71
+ presence: node.presence
72
+ )
73
+ lastRewrittenToken = rewritten
74
+ putNextTokenOnNewLine = false
75
+ return rewritten
76
+ }
77
+ """
78
+ )
79
+
80
+ FunctionDecl ( " open func shouldIndent(_ keyPath: AnyKeyPath) -> Bool " ) {
81
+ SwitchStmt ( expression: Expr ( " keyPath " ) ) {
82
+ for node in SYNTAX_NODES where !node. isBase {
83
+ for child in node. children where child. isIndented {
84
+ SwitchCase ( " case \\ \( node. type. syntaxBaseName) . \( child. swiftName) : " ) {
85
+ ReturnStmt ( " return true " )
86
+ }
87
+ }
88
+ }
89
+ SwitchCase ( " default: " ) {
90
+ ReturnStmt ( " return false " )
91
+ }
92
+ }
93
+ }
94
+
95
+ FunctionDecl ( " open func requiresLeadingNewline(_ keyPath: AnyKeyPath) -> Bool " ) {
96
+ SwitchStmt ( expression: Expr ( " keyPath " ) ) {
97
+ for node in SYNTAX_NODES where !node. isBase {
98
+ for child in node. children where child. requiresLeadingNewline {
99
+ SwitchCase ( " case \\ \( node. type. syntaxBaseName) . \( child. swiftName) : " ) {
100
+ ReturnStmt ( " return true " )
101
+ }
102
+ }
103
+ }
104
+ SwitchCase ( " default: " ) {
105
+ ReturnStmt ( " return putNextTokenOnNewLine " )
106
+ }
107
+ }
108
+ }
109
+
110
+ FunctionDecl ( " open func childrenSeparatedByNewline(_ node: Syntax) -> Bool " ) {
111
+ SwitchStmt ( expression: Expr ( " node.as(SyntaxEnum.self) " ) ) {
112
+ for node in SYNTAX_NODES where !node. isBase {
113
+ if node. elementsSeparatedByNewline {
114
+ SwitchCase ( " case . \( node. swiftSyntaxKind) : " ) {
115
+ ReturnStmt ( " return true " )
116
+ }
117
+ }
118
+ }
119
+ SwitchCase ( " default: " ) {
120
+ ReturnStmt ( " return false " )
121
+ }
122
+ }
123
+ }
124
+
125
+ FunctionDecl ( " open func requiresLeadingSpace(_ tokenKind: TokenKind) -> Bool " ) {
126
+ SwitchStmt ( expression: Expr ( " tokenKind " ) ) {
127
+ for token in SYNTAX_TOKENS {
128
+ if token. requiresLeadingSpace {
129
+ SwitchCase ( " case . \( token. swiftKind) : " ) {
130
+ ReturnStmt ( " return true " )
131
+ }
132
+ }
133
+ }
134
+ SwitchCase ( " default: " ) {
135
+ ReturnStmt ( " return false " )
136
+ }
137
+ }
138
+ }
139
+
140
+ FunctionDecl ( " open func requiresTrailingSpace(_ tokenKind: TokenKind) -> Bool " ) {
141
+ SwitchStmt ( expression: Expr ( " tokenKind " ) ) {
142
+ for token in SYNTAX_TOKENS {
143
+ if token. requiresTrailingSpace {
144
+ SwitchCase ( " case . \( token. swiftKind) : " ) {
145
+ ReturnStmt ( " return true " )
146
+ }
147
+ }
148
+ }
149
+ SwitchCase ( #"case .contextualKeyword("async"):"# ) {
150
+ ReturnStmt ( " return true " )
151
+ }
152
+ SwitchCase ( " default: " ) {
153
+ ReturnStmt ( " return false " )
154
+ }
36
155
}
37
156
}
38
157
39
- createTokenFormatFunction ( )
158
+ FunctionDecl ( """
159
+ private func getKeyPath(_ node: Syntax) -> AnyKeyPath? {
160
+ guard let parent = node.parent else {
161
+ return nil
162
+ }
163
+ guard case .layout(let childrenKeyPaths) = parent.kind.syntaxNodeType.structure else {
164
+ return nil
165
+ }
166
+ return childrenKeyPaths[node.indexInParent]
167
+ }
168
+ """
169
+ )
40
170
}
41
171
}
42
172
@@ -55,52 +185,6 @@ private func createChildVisitCall(childType: SyntaxBuildableType, rewrittenExpr:
55
185
}
56
186
}
57
187
58
- private func makeLayoutNodeRewriteFunc( node: Node ) -> FunctionDecl {
59
- let rewriteResultType : String
60
- if node. type. baseType? . syntaxKind == " Syntax " && node. type. syntaxKind != " Missing " {
61
- rewriteResultType = node. type. syntaxBaseName
62
- } else {
63
- rewriteResultType = node. type. baseType? . syntaxBaseName ?? node. type. syntaxBaseName
64
- }
65
- return FunctionDecl ( """
66
-
67
- open override func visit(_ node: \( node. type. syntaxBaseName) ) -> \( rewriteResultType)
68
- """ ) {
69
- for child in node. children {
70
- if child. isIndented {
71
- SequenceExpr ( " indentationLevel += 1 " )
72
- }
73
- let variableLetVar = child. requiresLeadingNewline ? " var " : " let "
74
- VariableDecl ( " \( variableLetVar) \( child. swiftName) = \( createChildVisitCall ( childType: child. type, rewrittenExpr: MemberAccessExpr ( " node. \( child. swiftName) " ) ) ) " )
75
- if child. requiresLeadingNewline {
76
- IfStmt (
77
- """
78
- if \( child. swiftName) .leadingTrivia.first?.isNewline != true {
79
- \( child. swiftName) .leadingTrivia = indentedNewline + \( child. swiftName) .leadingTrivia
80
- }
81
- """
82
- )
83
- }
84
- if child. isIndented {
85
- SequenceExpr ( " indentationLevel -= 1 " )
86
- }
87
- }
88
- let reconstructed = FunctionCallExpr ( callee: node. type. syntaxBaseName) {
89
- for child in node. children {
90
- TupleExprElement (
91
- label: child. isUnexpectedNodes ? nil : child. swiftName,
92
- expression: Expr ( child. swiftName)
93
- )
94
- }
95
- }
96
- if rewriteResultType != node. type. syntaxBaseName {
97
- ReturnStmt ( " return \( rewriteResultType) ( \( reconstructed) ) " )
98
- } else {
99
- ReturnStmt ( " return \( reconstructed) " )
100
- }
101
- }
102
- }
103
-
104
188
private func makeSyntaxCollectionRewriteFunc( node: Node ) -> FunctionDecl {
105
189
let rewriteResultType = node. type. syntaxBaseName
106
190
return FunctionDecl ( """
@@ -132,70 +216,3 @@ private func makeSyntaxCollectionRewriteFunc(node: Node) -> FunctionDecl {
132
216
}
133
217
}
134
218
135
- private func createTokenFormatFunction( ) -> FunctionDecl {
136
- return FunctionDecl ( """
137
-
138
- open override func visit(_ node: TokenSyntax) -> TokenSyntax
139
- """ ) {
140
- VariableDecl ( " var leadingTrivia = node.leadingTrivia " )
141
- VariableDecl ( " var trailingTrivia = node.trailingTrivia " )
142
- SwitchStmt ( expression: MemberAccessExpr ( base: " node " , name: " tokenKind " ) ) {
143
- for token in SYNTAX_TOKENS where token. name != " ContextualKeyword " {
144
- SwitchCase ( " case . \( token. swiftKind) : " ) {
145
- if token. requiresLeadingSpace {
146
- IfStmt (
147
- """
148
- if leadingTrivia.isEmpty && lastRewrittenToken?.trailingTrivia.isEmpty != false {
149
- leadingTrivia += .space
150
- }
151
- """
152
- )
153
- }
154
- if token. requiresTrailingSpace {
155
- IfStmt (
156
- """
157
- if trailingTrivia.isEmpty {
158
- trailingTrivia += .space
159
- }
160
- """
161
- )
162
- }
163
- if !token. requiresLeadingSpace && !token. requiresTrailingSpace {
164
- BreakStmt ( " break " )
165
- }
166
- }
167
- }
168
- SwitchCase ( " case .eof: " ) {
169
- BreakStmt ( " break " )
170
- }
171
- SwitchCase ( " case .contextualKeyword: " ) {
172
- SwitchStmt (
173
- """
174
- switch node.text {
175
- case " async " :
176
- if trailingTrivia.isEmpty {
177
- trailingTrivia += .space
178
- }
179
- default:
180
- break
181
- }
182
- """
183
- )
184
- }
185
- }
186
- SequenceExpr ( " leadingTrivia = leadingTrivia.indented(indentation: indentation) " )
187
- SequenceExpr ( " trailingTrivia = trailingTrivia.indented(indentation: indentation) " )
188
- VariableDecl (
189
- """
190
- let rewritten = TokenSyntax(
191
- node.tokenKind,
192
- leadingTrivia: leadingTrivia,
193
- trailingTrivia: trailingTrivia,
194
- presence: node.presence
195
- )
196
- """
197
- )
198
- SequenceExpr ( " lastRewrittenToken = rewritten " )
199
- ReturnStmt ( " return rewritten " )
200
- }
201
- }
0 commit comments