Skip to content

Update to non-optional leading/trailingTrivia swift-syntax API #497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Sources/SwiftFormatCore/SyntaxProtocol+Convenience.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ extension SyntaxProtocol {
/// be returned.
/// - Returns: The absolute position of the trivia piece.
public func position(ofLeadingTriviaAt index: Trivia.Index) -> AbsolutePosition {
let leadingTrivia = self.leadingTrivia ?? []
guard leadingTrivia.indices.contains(index) else {
preconditionFailure("Index was out of bounds in the node's leading trivia.")
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
// The node's content is either a `DictionaryElementListSyntax` or a `TokenSyntax` for a colon
// token (for an empty dictionary).
if !(node.content.as(DictionaryElementListSyntax.self)?.isEmpty ?? true)
|| node.content.leadingTrivia?.numberOfComments ?? 0 > 0
|| node.content.leadingTrivia.numberOfComments > 0
|| node.rightSquare.leadingTrivia.numberOfComments > 0
{
after(node.leftSquare, tokens: .break(.open, size: 0), .open)
Expand Down Expand Up @@ -2161,7 +2161,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
appendToken(.syntax(segmentText))
}

if node.trailingTrivia?.containsBackslashes == true {
if node.trailingTrivia.containsBackslashes {
// Segments with trailing backslashes won't end with a literal newline; the backslash is
// considered trivia. To preserve the original text and wrapping, we need to manually render
// the backslash and a break into the token stream.
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftFormatRules/NoAssignmentInExpressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public final class NoAssignmentInExpressions: SyntaxFormatRule {
semicolon: nil
)
.with(\.leadingTrivia,
(returnStmt.leadingTrivia ?? []) + (assignmentExpr.leadingTrivia ?? []))
(returnStmt.leadingTrivia) + (assignmentExpr.leadingTrivia))
.with(\.trailingTrivia, []))
newItems.append(
CodeBlockItemSyntax(
item: .stmt(StmtSyntax(returnStmt.with(\.expression, nil))),
semicolon: nil
)
.with(\.leadingTrivia, [.newlines(1)])
.with(\.trailingTrivia, returnStmt.trailingTrivia?.withoutLeadingSpaces() ?? []))
.with(\.trailingTrivia, returnStmt.trailingTrivia.withoutLeadingSpaces()))

default:
newItems.append(newItem)
Expand Down
14 changes: 3 additions & 11 deletions Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,11 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
}

// Check for any comments that are adjacent to the case or fallthrough statement.
if let leadingTrivia = switchCase.leadingTrivia,
leadingTrivia.drop(while: { !$0.isNewline }).contains(where: { $0.isComment })
if switchCase.leadingTrivia.drop(while: { !$0.isNewline }).contains(where: { $0.isComment })
{
return false
}
if let leadingTrivia = onlyStatement.leadingTrivia,
leadingTrivia.drop(while: { !$0.isNewline }).contains(where: { $0.isComment })
if onlyStatement.leadingTrivia.drop(while: { !$0.isNewline }).contains(where: { $0.isComment })
{
return false
}
Expand Down Expand Up @@ -194,13 +192,7 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {

// Only the first violation case can have displaced trivia, because any non-whitespace
// trivia in the other violation cases would've prevented collapsing.
if let displacedLeadingTrivia = cases.first!.leadingTrivia?.withoutLastLine() {
let existingLeadingTrivia = newCase.leadingTrivia ?? []
let mergedLeadingTrivia = displacedLeadingTrivia + existingLeadingTrivia
return newCase.with(\.leadingTrivia, mergedLeadingTrivia)
} else {
return newCase
}
return newCase.with(\.leadingTrivia, cases.first!.leadingTrivia.withoutLastLine() + newCase.leadingTrivia)
}
}

Expand Down
34 changes: 15 additions & 19 deletions Sources/SwiftFormatRules/OrderedImports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -298,23 +298,20 @@ fileprivate func generateLines(codeBlockItemList: CodeBlockItemListSyntax, conte
}

for block in codeBlockItemList {

if let leadingTrivia = block.leadingTrivia {
afterNewline = false

for piece in leadingTrivia {
switch piece {
// Create new Line objects when we encounter newlines.
case .newlines(let N):
for _ in 0..<N {
appendNewLine()
}
default:
if afterNewline || isFirstBlock {
currentLine.leadingTrivia.append(piece) // This will be a standalone comment.
} else {
currentLine.trailingTrivia.append(piece) // This will be a trailing line comment.
}
afterNewline = false

for piece in block.leadingTrivia {
switch piece {
// Create new Line objects when we encounter newlines.
case .newlines(let N):
for _ in 0..<N {
appendNewLine()
}
default:
if afterNewline || isFirstBlock {
currentLine.leadingTrivia.append(piece) // This will be a standalone comment.
} else {
currentLine.trailingTrivia.append(piece) // This will be a trailing line comment.
}
}
}
Expand Down Expand Up @@ -491,8 +488,7 @@ fileprivate class Line {
// description includes all leading and trailing trivia. It would be unusual to have any
// non-whitespace trivia on the components of the import. Trim off the leading trivia, where
// comments could be, and trim whitespace that might be after the import.
let leadingText = importDecl.leadingTrivia?.reduce(into: "") { $1.write(to: &$0) } ?? ""
return importDecl.description.dropFirst(leadingText.count)
return importDecl.with(\.leadingTrivia, []).description
.trimmingCharacters(in: .whitespacesAndNewlines)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormatRules/UseShorthandTypeNames.swift
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
elementList: tupleExprElementList,
rightParen: TokenSyntax.rightParenToken())
wrappedTypeExpr = ExprSyntax(tupleExpr)
} else if let leadingTrivia = leadingTrivia {
} else {
// Otherwise, the argument type can safely become an optional by simply appending a "?". If
// we were given leading trivia from another node (for example, from `Optional` when
// converting a long-form to short-form), we need to transfer it over. By doing so, something
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ public final class UseTripleSlashForDocumentationComments: SyntaxFormatRule {
/// a docLineComment.
private func convertDocBlockCommentToDocLineComment(_ decl: DeclSyntax) -> DeclSyntax {
guard let commentText = decl.docComment else { return decl }
guard let declLeadingTrivia = decl.leadingTrivia else { return decl }

let docComments = commentText.components(separatedBy: "\n")
var pieces = [TriviaPiece]()

// Ensures the documentation comment is a docLineComment.
var hasFoundDocComment = false
for piece in declLeadingTrivia.reversed() {
for piece in decl.leadingTrivia.reversed() {
if case .docBlockComment(_) = piece, !hasFoundDocComment {
hasFoundDocComment = true
diagnose(.avoidDocBlockComment, on: decl)
Expand Down