@@ -27,16 +27,221 @@ let basicFormatFile = SourceFile {
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 (
81
+ modifiers: [ DeclModifier ( name: . open) ] ,
82
+ identifier: . identifier( " shouldIndent " ) ,
83
+ signature: FunctionSignature (
84
+ input: ParameterClause ( parameterList: [
85
+ FunctionParameter (
86
+ firstName: Token . wildcard,
87
+ secondName: . identifier( " keyPath " ) ,
88
+ colon: . colon,
89
+ type: SimpleTypeIdentifier ( " AnyKeyPath " )
90
+
91
+ )
92
+ ] ) ,
93
+ output: ReturnClause ( returnType: SimpleTypeIdentifier ( " Bool " ) )
94
+ )
95
+ ) {
96
+ SwitchStmt ( expression: Expr ( " keyPath " ) ) {
97
+ for node in SYNTAX_NODES where !node. isBase {
98
+ for child in node. children where child. isIndented {
99
+ SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: KeyPathExpr ( " \\ \( node. type. syntaxBaseName) . \( child. swiftName) " ) ) ) ] ) ) {
100
+ ReturnStmt ( " return true " )
101
+ }
102
+ }
103
+ }
104
+ SwitchCase ( label: SwitchDefaultLabel ( ) ) {
105
+ ReturnStmt ( " return false " )
106
+ }
107
+ }
108
+ }
109
+
110
+ FunctionDecl (
111
+ modifiers: [ DeclModifier ( name: . open) ] ,
112
+ identifier: . identifier( " requiresLeadingNewline " ) ,
113
+ signature: FunctionSignature (
114
+ input: ParameterClause ( parameterList: [
115
+ FunctionParameter (
116
+ firstName: Token . wildcard,
117
+ secondName: . identifier( " keyPath " ) ,
118
+ colon: . colon,
119
+ type: SimpleTypeIdentifier ( " AnyKeyPath " )
120
+
121
+ )
122
+ ] ) ,
123
+ output: ReturnClause ( returnType: SimpleTypeIdentifier ( " Bool " ) )
124
+ )
125
+ ) {
126
+ SwitchStmt ( expression: Expr ( " keyPath " ) ) {
127
+ for node in SYNTAX_NODES where !node. isBase {
128
+ for child in node. children where child. requiresLeadingNewline {
129
+ SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: KeyPathExpr ( " \\ \( node. type. syntaxBaseName) . \( child. swiftName) " ) ) ) ] ) ) {
130
+ ReturnStmt ( " return true " )
131
+ }
132
+ }
133
+ }
134
+ SwitchCase ( label: SwitchDefaultLabel ( ) ) {
135
+ ReturnStmt ( " return putNextTokenOnNewLine " )
136
+ }
137
+ }
138
+ }
139
+
140
+ FunctionDecl (
141
+ modifiers: [ DeclModifier ( name: . open) ] ,
142
+ identifier: . identifier( " childrenSeparatedByNewline " ) ,
143
+ signature: FunctionSignature (
144
+ input: ParameterClause ( parameterList: [
145
+ FunctionParameter (
146
+ firstName: Token . wildcard,
147
+ secondName: . identifier( " node " ) ,
148
+ colon: . colon,
149
+ type: SimpleTypeIdentifier ( " Syntax " )
150
+
151
+ )
152
+ ] ) ,
153
+ output: ReturnClause ( returnType: SimpleTypeIdentifier ( " Bool " ) )
154
+ )
155
+ ) {
156
+ SwitchStmt ( expression: Expr ( " node.as(SyntaxEnum.self) " ) ) {
157
+ for node in SYNTAX_NODES where !node. isBase {
158
+ if node. elementsSeparatedByNewline {
159
+ SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: MemberAccessExpr ( " . \( node. swiftSyntaxKind) " ) ) ) ] ) ) {
160
+ ReturnStmt ( " return true " )
161
+ }
162
+ }
163
+ }
164
+ SwitchCase ( label: SwitchDefaultLabel ( ) ) {
165
+ ReturnStmt ( " return false " )
166
+ }
167
+ }
168
+ }
169
+
170
+ FunctionDecl (
171
+ modifiers: [ DeclModifier ( name: . open) ] ,
172
+ identifier: . identifier( " requiresLeadingSpace " ) ,
173
+ signature: FunctionSignature (
174
+ input: ParameterClause ( parameterList: [
175
+ FunctionParameter (
176
+ firstName: Token . wildcard,
177
+ secondName: . identifier( " tokenKind " ) ,
178
+ colon: . colon,
179
+ type: SimpleTypeIdentifier ( " TokenKind " )
180
+
181
+ )
182
+ ] ) ,
183
+ output: ReturnClause ( returnType: SimpleTypeIdentifier ( " Bool " ) )
184
+ )
185
+ ) {
186
+ SwitchStmt ( expression: Expr ( " tokenKind " ) ) {
187
+ for token in SYNTAX_TOKENS {
188
+ if token. requiresLeadingSpace {
189
+ SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: MemberAccessExpr ( " . \( token. swiftKind) " ) ) ) ] ) ) {
190
+ ReturnStmt ( " return true " )
191
+ }
192
+ }
193
+ }
194
+ SwitchCase ( label: SwitchDefaultLabel ( ) ) {
195
+ ReturnStmt ( " return false " )
196
+ }
36
197
}
37
198
}
38
199
39
- createTokenFormatFunction ( )
200
+ FunctionDecl (
201
+ modifiers: [ DeclModifier ( name: . open) ] ,
202
+ identifier: . identifier( " requiresTrailingSpace " ) ,
203
+ signature: FunctionSignature (
204
+ input: ParameterClause ( parameterList: [
205
+ FunctionParameter (
206
+ firstName: Token . wildcard,
207
+ secondName: . identifier( " tokenKind " ) ,
208
+ colon: . colon,
209
+ type: SimpleTypeIdentifier ( " TokenKind " )
210
+
211
+ )
212
+ ] ) ,
213
+ output: ReturnClause ( returnType: SimpleTypeIdentifier ( " Bool " ) )
214
+ )
215
+ ) {
216
+ SwitchStmt ( expression: Expr ( " tokenKind " ) ) {
217
+ for token in SYNTAX_TOKENS {
218
+ if token. requiresTrailingSpace {
219
+ SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: MemberAccessExpr ( " . \( token. swiftKind) " ) ) ) ] ) ) {
220
+ ReturnStmt ( " return true " )
221
+ }
222
+ }
223
+ }
224
+ SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: FunctionCallExpr ( #".contextualKeyword("async")"# ) ) ) ] ) ) {
225
+ ReturnStmt ( " return true " )
226
+ }
227
+ SwitchCase ( label: SwitchDefaultLabel ( ) ) {
228
+ ReturnStmt ( " return false " )
229
+ }
230
+ }
231
+ }
232
+
233
+ FunctionDecl ( """
234
+ private func getKeyPath(_ node: Syntax) -> AnyKeyPath? {
235
+ guard let parent = node.parent else {
236
+ return nil
237
+ }
238
+ guard case .layout(let childrenKeyPaths) = type(of: parent.asProtocol(SyntaxProtocol.self)).structure else {
239
+ return nil
240
+ }
241
+ return childrenKeyPaths[node.indexInParent]
242
+ }
243
+ """
244
+ )
40
245
}
41
246
}
42
247
@@ -55,65 +260,6 @@ private func createChildVisitCall(childType: SyntaxBuildableType, rewrittenExpr:
55
260
}
56
261
}
57
262
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
- leadingTrivia: . newline,
67
- modifiers: [ DeclModifier ( name: . open) , DeclModifier ( name: TokenSyntax . contextualKeyword ( " override " , trailingTrivia: . space) ) ] ,
68
- identifier: . identifier( " visit " ) ,
69
- signature: FunctionSignature (
70
- input: ParameterClause ( parameterList: [
71
- FunctionParameter (
72
- firstName: Token . wildcard,
73
- secondName: . identifier( " node " ) ,
74
- colon: . colon,
75
- type: Type ( node. type. syntaxBaseName)
76
-
77
- )
78
- ] ) ,
79
- output: ReturnClause ( returnType: Type ( rewriteResultType) )
80
- )
81
- ) {
82
- for child in node. children {
83
- if child. isIndented {
84
- SequenceExpr ( " indentationLevel += 1 " )
85
- }
86
- let variableLetVar = child. requiresLeadingNewline ? " var " : " let "
87
- VariableDecl ( " \( variableLetVar) \( child. swiftName) = \( createChildVisitCall ( childType: child. type, rewrittenExpr: MemberAccessExpr ( " node. \( child. swiftName) " ) ) ) " )
88
- if child. requiresLeadingNewline {
89
- IfStmt (
90
- """
91
- if \( child. swiftName) .leadingTrivia.first?.isNewline != true {
92
- \( child. swiftName) .leadingTrivia = indentedNewline + \( child. swiftName) .leadingTrivia
93
- }
94
- """
95
- )
96
- }
97
- if child. isIndented {
98
- SequenceExpr ( " indentationLevel -= 1 " )
99
- }
100
- }
101
- let reconstructed = FunctionCallExpr ( calledExpression: Expr ( " \( node. type. syntaxBaseName) " ) ) {
102
- for child in node. children {
103
- TupleExprElement (
104
- label: child. isUnexpectedNodes ? nil : child. swiftName,
105
- expression: Expr ( child. swiftName)
106
- )
107
- }
108
- }
109
- if rewriteResultType != node. type. syntaxBaseName {
110
- ReturnStmt ( " return \( rewriteResultType) ( \( reconstructed) ) " )
111
- } else {
112
- ReturnStmt ( " return \( reconstructed) " )
113
- }
114
- }
115
- }
116
-
117
263
private func makeSyntaxCollectionRewriteFunc( node: Node ) -> FunctionDecl {
118
264
let rewriteResultType = node. type. syntaxBaseName
119
265
return FunctionDecl (
@@ -157,84 +303,3 @@ private func makeSyntaxCollectionRewriteFunc(node: Node) -> FunctionDecl {
157
303
ReturnStmt ( " return \( node. type. syntaxBaseName) (formattedChildren) " )
158
304
}
159
305
}
160
-
161
- private func createTokenFormatFunction( ) -> FunctionDecl {
162
- return FunctionDecl (
163
- leadingTrivia: . newline,
164
- modifiers: [ DeclModifier ( name: . open) , DeclModifier ( name: TokenSyntax . contextualKeyword ( " override " , trailingTrivia: . space) ) ] ,
165
- identifier: . identifier( " visit " ) ,
166
- signature: FunctionSignature (
167
- input: ParameterClause ( parameterList: [
168
- FunctionParameter (
169
- firstName: Token . wildcard,
170
- secondName: . identifier( " node " ) ,
171
- colon: . colon,
172
- type: Type ( " TokenSyntax " )
173
-
174
- )
175
- ] ) ,
176
- output: ReturnClause ( returnType: Type ( " TokenSyntax " ) )
177
- )
178
- ) {
179
- VariableDecl ( " var leadingTrivia = node.leadingTrivia " )
180
- VariableDecl ( " var trailingTrivia = node.trailingTrivia " )
181
- SwitchStmt ( expression: MemberAccessExpr ( base: " node " , name: " tokenKind " ) ) {
182
- for token in SYNTAX_TOKENS where token. name != " ContextualKeyword " {
183
- SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: MemberAccessExpr ( name: token. swiftKind) ) ) ] ) ) {
184
- if token. requiresLeadingSpace {
185
- IfStmt (
186
- """
187
- if leadingTrivia.isEmpty && lastRewrittenToken?.trailingTrivia.isEmpty != false {
188
- leadingTrivia += .space
189
- }
190
- """
191
- )
192
- }
193
- if token. requiresTrailingSpace {
194
- IfStmt (
195
- """
196
- if trailingTrivia.isEmpty {
197
- trailingTrivia += .space
198
- }
199
- """
200
- )
201
- }
202
- if !token. requiresLeadingSpace && !token. requiresTrailingSpace {
203
- BreakStmt ( " break " )
204
- }
205
- }
206
- }
207
- SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: MemberAccessExpr ( name: " eof " ) ) ) ] ) ) {
208
- BreakStmt ( " break " )
209
- }
210
- SwitchCase ( label: SwitchCaseLabel ( caseItems: [ CaseItem ( pattern: ExpressionPattern ( expression: MemberAccessExpr ( name: " contextualKeyword " ) ) ) ] ) ) {
211
- SwitchStmt (
212
- """
213
- switch node.text {
214
- case " async " :
215
- if trailingTrivia.isEmpty {
216
- trailingTrivia += .space
217
- }
218
- default:
219
- break
220
- }
221
- """
222
- )
223
- }
224
- }
225
- SequenceExpr ( " leadingTrivia = leadingTrivia.indented(indentation: indentation) " )
226
- SequenceExpr ( " trailingTrivia = trailingTrivia.indented(indentation: indentation) " )
227
- VariableDecl (
228
- """
229
- let rewritten = TokenSyntax(
230
- node.tokenKind,
231
- leadingTrivia: leadingTrivia,
232
- trailingTrivia: trailingTrivia,
233
- presence: node.presence
234
- )
235
- """
236
- )
237
- SequenceExpr ( " lastRewrittenToken = rewritten " )
238
- ReturnStmt ( " return rewritten " )
239
- }
240
- }
0 commit comments