@@ -243,18 +243,69 @@ Tokens = [docBlock(" Doc Block comment\n * Second line *")]
243243
244244Token generation begins with the abstract syntax tree (AST) of the Swift source
245245file, provided by the [ SwiftSyntax] ( https://github.com/apple/swift-syntax )
246- library. We have a ` visit ` method for each of the different syntax node types
247- (e.g. ` FunctionDeclSyntax ` , ` GenericWhereClause ` , etc.). Within each of these
248- visit methods, we can attach pretty-printer ` Token ` objects before and after
249- syntax tokens from the AST. For example, if we wanted a group after the opening
250- brace of a function declaration, it might look like:
246+ library. We have overloaded a ` visit ` method for each of the different kinds of
247+ syntax nodes. Most of these nodes are higher-level, and are composed of other
248+ nodes. For example, ` FunctionDeclSyntax ` contains
249+ ` GenericParameterClauseSyntax ` , ` FunctionSignatureSyntax ` nodes among others.
250+ These member nodes are called via a call to ` super.visit ` at the end of the
251+ function. That being said, we visit the higher level nodes before the lower
252+ level nodes.
253+
254+ Within the visit methods, you can attach pretty-printing tokens at different
255+ points within the syntax structures. For example, if you wanted to place an
256+ indenting group around the body of a function declaration with consistent
257+ breaking, and you want the trailing brace forced to the next line, it might look
258+ like:
251259
252260```
253- # node: FunctionDeclSyntax
254- after(node.body?.leftBrace, tokens: .break(size: 1, offset: 2), .open(.consistent, 0))
261+ // In visit(_ node: FunctionDeclSyntax)
262+ after(node.body?.leftBrace, tokens: .break(offset: 2), .open(.consistent, 0))
263+ before(node.body?.rightBrace, tokens: .break(offset: -2), .close)
255264```
256265
257- All of the tokens are placed into an array, which are then passed on to the
258- * scan* phase of the pretty printer.
266+ Two dictionaries are maintained to keep track of the pretty-printing tokens
267+ attached to the syntax tokens: ` beforeMap ` , and ` afterMap ` . Calls to ` before `
268+ and ` after ` populate these dictionaries. In the above example, ` node.body? ` may
269+ return ` nil ` , in which case ` before ` and ` after ` gracefully do nothing.
270+
271+ The lowest level in the AST is ` TokenSyntax ` , and it is at this point that we
272+ actually add the syntax token and its attached pretty-printer tokens to the
273+ output array. This is done in ` visit(_ token: TokenSyntax) ` . We first check the
274+ syntax token's leading trivia for the presence of newlines and comments
275+ (excluding end-of-line comments), and add corresponding printing tokens to the
276+ output array. Next, we look at the token's entry in the ` beforeMap ` dictionary
277+ and add any accumulated ` before ` tokens to the output array. Next, we add the
278+ syntax token itself to the array. We look ahead to the leading trivia of the
279+ next syntax token to check for an end-of-line comment, and we add it to the
280+ array if needed. Finally, we add the ` after ` tokens. The ordering of the ` after `
281+ tokens is adjusted such that the token attached by lower level ` visit ` method
282+ are added to the array before the higher level ` visit ` methods.
283+
284+ The only types of trivia we are interested in are newlines and comments. Since
285+ these only appear as leading trivia, we don't need to look at trailing trivia.
286+ It is important to note that ` SwiftSyntax ` always attaches comments as the
287+ leading trivia on the following token. Spaces are handled directly by inserting
288+ ` break ` and ` space ` tokens, and backticks are handled in the * scan* and * print*
289+ phases of the algorithm, after token generation.
290+
291+ When examining trivia for comments, a distinction is made for end-of-line
292+ comments:
293+
294+ ```
295+ // not end-of-line
296+ let a = 123 // end-of-line comment
297+ let b = "abc"
298+
299+ // In the above example, "not end-of-line" is part of the leading trivia of
300+ // "let" for "let a", and "end-of-line comment" is leading trivia for "let" of
301+ // "let b".
302+ ```
303+
304+ A comment is determined to be end-of-line when it appears as the first item in a
305+ token's leading trivia (it is not preceded by a newline, and we are not at the
306+ beginning of a source file).
307+
308+ When we have visited all nodes in the AST, the array of printing tokens is then
309+ passed on to the * scan* phase of the pretty-printer.
259310
260311See: [ ` TokenStreamCreator.swift ` ] ( ../Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift )
0 commit comments