I have this sample piece of code:
func something(_ a: Int) -> String {
if a == 10 {
return "hello"
}
return "bye"
}
I want to add a tab Trivia to every line inside a function.
Here is what I've tried:
extension SyntaxProtocol {
func appendingTabToLeadingTrivia() -> Self {
var trivia = leadingTrivia.appending(.tab)
var copy = self
copy.leadingTrivia = trivia
return copy
}
}
extension CodeBlockItemListSyntax {
func appendingTabToLeadingTriviaForAllChildren() -> Self {
var newCodeBlockItemSyntaxes: [Element] = []
// Iterate throught every CodeBlockItemList and add a `tab` Trivia
self.forEach { block in
var copy = block
copy = copy.appendingTabToLeadingTrivia()
newCodeBlockItemSyntaxes.append(copy)
}
return .init(newCodeBlockItemSyntaxes)
}
}
func modify(originalSyntax: CodeBlockItemListSyntax) {
var copy = originalSyntax.appendingTabToLeadingTriviaForAllChildren()
debugPrint(copy.description)
}
Expected
func something(_ a: Int) -> String {
if a == 10 {
return "hello"
}
return "bye"
}
Actual Result
func something(_ a: Int) -> String {
if a == 10 {
return "hello"
}
return "bye"
}
Questions:
Seems like my approach only adds a tab to the first line of a CodeBlockItemList.
How can I achieve the expected result?
2 Likes
Hi @ahoppen,
I hope you can give me some advice 
This is a very good question!
The result you see is expected. An item in a code block is not a single line but comprises complete syntax nodes. In your example, the if expression is one node and the return statement is another. By prepending some whitespace to every item, only the first token in every item experiences the indentation, that is the if keyword and the return keyword.
Now, to achieve an indentation of a whole block, you'd need to iterate over all tokens and prepend the whitespace after every (last) newline in the token's trivia.
SwiftSyntax itself doesn't seem to have such an algorithm built-in. However, as this is something important for SwiftLint, I have implemented a rewriter that would do what is explained above. It allows indentation and unindentation (Is this a term anyway?
) with tabs and spaces. It works for the single SwiftLint rule that currently uses it. So there's no guarantee I thought of all the details required to make this a general component.
1 Like
Thank you @SimplyDanny
It works for me 