diff --git a/Sources/SwiftFormatCore/LegacyTriviaBehavior.swift b/Sources/SwiftFormatCore/LegacyTriviaBehavior.swift index 5011c8be8..6fc9365c3 100644 --- a/Sources/SwiftFormatCore/LegacyTriviaBehavior.swift +++ b/Sources/SwiftFormatCore/LegacyTriviaBehavior.swift @@ -20,7 +20,7 @@ private final class LegacyTriviaBehaviorRewriter: SyntaxRewriter { token = token.with(\.leadingTrivia, pendingLeadingTrivia + token.leadingTrivia) self.pendingLeadingTrivia = nil } - if token.nextToken != nil, + if token.nextToken(viewMode: .sourceAccurate) != nil, let firstIndexToMove = token.trailingTrivia.firstIndex(where: shouldTriviaPieceBeMoved) { pendingLeadingTrivia = Trivia(pieces: Array(token.trailingTrivia[firstIndexToMove...])) diff --git a/Sources/SwiftFormatCore/RuleMask.swift b/Sources/SwiftFormatCore/RuleMask.swift index b614b17b0..37dfec1c2 100644 --- a/Sources/SwiftFormatCore/RuleMask.swift +++ b/Sources/SwiftFormatCore/RuleMask.swift @@ -136,7 +136,7 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor { // MARK: - Syntax Visitation Methods override func visit(_ node: SourceFileSyntax) -> SyntaxVisitorContinueKind { - guard let firstToken = node.firstToken else { + guard let firstToken = node.firstToken(viewMode: .sourceAccurate) else { return .visitChildren } let comments = loneLineComments(in: firstToken.leadingTrivia, isFirstToken: true) @@ -159,14 +159,14 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor { } override func visit(_ node: CodeBlockItemSyntax) -> SyntaxVisitorContinueKind { - guard let firstToken = node.firstToken else { + guard let firstToken = node.firstToken(viewMode: .sourceAccurate) else { return .visitChildren } return appendRuleStatusDirectives(from: firstToken, of: Syntax(node)) } override func visit(_ node: MemberDeclListItemSyntax) -> SyntaxVisitorContinueKind { - guard let firstToken = node.firstToken else { + guard let firstToken = node.firstToken(viewMode: .sourceAccurate) else { return .visitChildren } return appendRuleStatusDirectives(from: firstToken, of: Syntax(node)) @@ -183,7 +183,7 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor { private func appendRuleStatusDirectives(from token: TokenSyntax, of node: Syntax) -> SyntaxVisitorContinueKind { - let isFirstInFile = token.previousToken == nil + let isFirstInFile = token.previousToken(viewMode: .sourceAccurate) == nil let matches = loneLineComments(in: token.leadingTrivia, isFirstToken: isFirstInFile) .compactMap(ruleStatusDirectiveMatch) let sourceRange = node.sourceRange(converter: sourceLocationConverter) diff --git a/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift b/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift index 79cc1a16f..4a74b9ed6 100644 --- a/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift +++ b/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift @@ -109,7 +109,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { betweenElementsOf collectionNode: Node ) where Node.Element == Syntax { for element in collectionNode.dropLast() { - after(element.lastToken, tokens: tokens) + after(element.lastToken(viewMode: .sourceAccurate), tokens: tokens) } } @@ -120,7 +120,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { betweenElementsOf collectionNode: Node ) where Node.Element: SyntaxProtocol { for element in collectionNode.dropLast() { - after(element.lastToken, tokens: tokens) + after(element.lastToken(viewMode: .sourceAccurate), tokens: tokens) } } @@ -131,18 +131,18 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { betweenElementsOf collectionNode: Node ) where Node.Element == DeclSyntax { for element in collectionNode.dropLast() { - after(element.lastToken, tokens: tokens) + after(element.lastToken(viewMode: .sourceAccurate), tokens: tokens) } } private func verbatimToken(_ node: Syntax, indentingBehavior: IndentingBehavior = .allLines) { - if let firstToken = node.firstToken { + if let firstToken = node.firstToken(viewMode: .sourceAccurate) { appendBeforeTokens(firstToken) } appendToken(.verbatim(Verbatim(text: node.description, indentingBehavior: indentingBehavior))) - if let lastToken = node.lastToken { + if let lastToken = node.lastToken(viewMode: .sourceAccurate) { // Extract any comments that trail the verbatim block since they belong to the next syntax // token. Leading comments don't need special handling since they belong to the current node, // and will get printed. @@ -224,7 +224,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { - guard let lastTokenOfExtendedType = node.extendedType.lastToken else { + guard let lastTokenOfExtendedType = node.extendedType.lastToken(viewMode: .sourceAccurate) else { fatalError("ExtensionDeclSyntax.extendedType must have at least one token") } arrangeTypeDeclBlock( @@ -253,29 +253,29 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { genericWhereClause: GenericWhereClauseSyntax?, members: MemberDeclBlockSyntax ) { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) arrangeAttributeList(attributes) // Prioritize keeping " :" together (corresponding group close is // below at `lastTokenBeforeBrace`). - let firstTokenAfterAttributes = modifiers?.firstToken ?? typeKeyword + let firstTokenAfterAttributes = modifiers?.firstToken(viewMode: .sourceAccurate) ?? typeKeyword before(firstTokenAfterAttributes, tokens: .open) after(typeKeyword, tokens: .break) arrangeBracesAndContents(of: members, contentsKeyPath: \.members) if let genericWhereClause = genericWhereClause { - before(genericWhereClause.firstToken, tokens: .break(.same), .open) + before(genericWhereClause.firstToken(viewMode: .sourceAccurate), tokens: .break(.same), .open) after(members.leftBrace, tokens: .close) } let lastTokenBeforeBrace = inheritanceClause?.colon - ?? genericParameterOrPrimaryAssociatedTypeClause?.lastToken + ?? genericParameterOrPrimaryAssociatedTypeClause?.lastToken(viewMode: .sourceAccurate) ?? identifier after(lastTokenBeforeBrace, tokens: .close) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } // MARK: - Function and function-like declaration nodes (initializers, deinitializers, subscripts) @@ -287,7 +287,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // has arguments. if hasArguments && config.prioritizeKeepingFunctionOutputTogether { // Due to visitation order, the matching .open break is added in ParameterClauseSyntax. - after(node.signature.lastToken, tokens: .close) + after(node.signature.lastToken(viewMode: .sourceAccurate), tokens: .close) } let mustBreak = node.body != nil || node.signature.output != nil @@ -295,7 +295,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Prioritize keeping " func (" together. Also include the ")" if the parameter // list is empty. - let firstTokenAfterAttributes = node.modifiers?.firstToken ?? node.funcKeyword + let firstTokenAfterAttributes = node.modifiers?.firstToken(viewMode: .sourceAccurate) ?? node.funcKeyword before(firstTokenAfterAttributes, tokens: .open) after(node.funcKeyword, tokens: .break) if hasArguments || node.genericParameterClause != nil { @@ -309,7 +309,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // defining a prefix or postfix operator, the token kind always comes through as // `binaryOperator`. if case .binaryOperator = node.identifier.tokenKind { - after(node.identifier.lastToken, tokens: .space) + after(node.identifier.lastToken(viewMode: .sourceAccurate), tokens: .space) } arrangeFunctionLikeDecl( @@ -329,13 +329,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // has arguments. if hasArguments && config.prioritizeKeepingFunctionOutputTogether { // Due to visitation order, the matching .open break is added in ParameterClauseSyntax. - after(node.signature.lastToken, tokens: .close) + after(node.signature.lastToken(viewMode: .sourceAccurate), tokens: .close) } arrangeParameterClause(node.signature.input, forcesBreakBeforeRightParen: node.body != nil) // Prioritize keeping " init" together. - let firstTokenAfterAttributes = node.modifiers?.firstToken ?? node.initKeyword + let firstTokenAfterAttributes = node.modifiers?.firstToken(viewMode: .sourceAccurate) ?? node.initKeyword before(firstTokenAfterAttributes, tokens: .open) if hasArguments || node.genericParameterClause != nil { @@ -367,10 +367,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: SubscriptDeclSyntax) -> SyntaxVisitorContinueKind { let hasArguments = !node.indices.parameterList.isEmpty - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) // Prioritize keeping " subscript" together. - if let firstModifierToken = node.modifiers?.firstToken { + if let firstModifierToken = node.modifiers?.firstToken(viewMode: .sourceAccurate) { before(firstModifierToken, tokens: .open) if hasArguments || node.genericParameterClause != nil { @@ -384,17 +384,17 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // arguments. if hasArguments && config.prioritizeKeepingFunctionOutputTogether { // Due to visitation order, the matching .open break is added in ParameterClauseSyntax. - after(node.result.lastToken, tokens: .close) + after(node.result.lastToken(viewMode: .sourceAccurate), tokens: .close) } arrangeAttributeList(node.attributes) if let genericWhereClause = node.genericWhereClause { - before(genericWhereClause.firstToken, tokens: .break(.same), .open) - after(genericWhereClause.lastToken, tokens: .close) + before(genericWhereClause.firstToken(viewMode: .sourceAccurate), tokens: .break(.same), .open) + after(genericWhereClause.lastToken(viewMode: .sourceAccurate), tokens: .close) } - before(node.result.firstToken, tokens: .break) + before(node.result.firstToken(viewMode: .sourceAccurate), tokens: .break) if let accessorOrCodeBlock = node.accessor { switch accessorOrCodeBlock { @@ -405,7 +405,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } } - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) arrangeParameterClause(node.indices, forcesBreakBeforeRightParen: true) @@ -421,17 +421,17 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { body: Node?, bodyContentsKeyPath: KeyPath? ) where BodyContents.Element: SyntaxProtocol { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) arrangeAttributeList(attributes) arrangeBracesAndContents(of: body, contentsKeyPath: bodyContentsKeyPath) if let genericWhereClause = genericWhereClause { - before(genericWhereClause.firstToken, tokens: .break(.same), .open) - after(body?.leftBrace ?? genericWhereClause.lastToken, tokens: .close) + before(genericWhereClause.firstToken(viewMode: .sourceAccurate), tokens: .break(.same), .open) + after(body?.leftBrace ?? genericWhereClause.lastToken(viewMode: .sourceAccurate), tokens: .close) } - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } // MARK: - Property and subscript accessor block nodes @@ -442,7 +442,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // protocol and we want to let them be placed on the same line if possible. Otherwise, we // place a newline between each accessor. let newlines: NewlineBehavior = child.body == nil ? .elective : .soft - after(child.lastToken, tokens: .break(.same, size: 1, newlines: newlines)) + after(child.lastToken(viewMode: .sourceAccurate), tokens: .break(.same, size: 1, newlines: newlines)) } return .visitChildren } @@ -484,8 +484,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // There may be a consistent breaking group around this node, see `CodeBlockItemSyntax`. This // group is necessary so that breaks around and inside of the conditions aren't forced to break // when the if-stmt spans multiple lines. - before(node.conditions.firstToken, tokens: .open) - after(node.conditions.lastToken, tokens: .close) + before(node.conditions.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(node.conditions.lastToken(viewMode: .sourceAccurate), tokens: .close) after(node.ifKeyword, tokens: .space) @@ -494,8 +494,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // the conditions. There are no breaks around the first condition because if-statements look // better without a break between the "if" and the first condition. for condition in node.conditions.dropFirst() { - before(condition.firstToken, tokens: .break(.open(kind: .continuation), size: 0)) - after(condition.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + before(condition.firstToken(viewMode: .sourceAccurate), tokens: .break(.open(kind: .continuation), size: 0)) + after(condition.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } arrangeBracesAndContents(of: node.body, contentsKeyPath: \.statements) @@ -531,8 +531,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Add break groups, using open continuation breaks, around all conditions so that continuations // inside of the conditions can stack in addition to continuations between the conditions. for condition in node.conditions { - before(condition.firstToken, tokens: .break(.open(kind: .continuation), size: 0)) - after(condition.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + before(condition.firstToken(viewMode: .sourceAccurate), tokens: .break(.open(kind: .continuation), size: 0)) + after(condition.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } before(node.elseKeyword, tokens: .break(.reset), .open) @@ -571,7 +571,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { after( typeAnnotation.colon, tokens: .break(.open(kind: .continuation), newlines: .elective(ignoresDiscretionary: true))) - after(typeAnnotation.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + after(typeAnnotation.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } arrangeBracesAndContents(of: node.body, contentsKeyPath: \.statements) @@ -591,8 +591,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // condition could be longer than the column limit since there are no breaks between the label // or while token. for condition in node.conditions.dropFirst() { - before(condition.firstToken, tokens: .break(.open(kind: .continuation), size: 0)) - after(condition.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + before(condition.firstToken(viewMode: .sourceAccurate), tokens: .break(.open(kind: .continuation), size: 0)) + after(condition.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } arrangeBracesAndContents(of: node.body, contentsKeyPath: \.statements) @@ -605,7 +605,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if config.lineBreakBeforeControlFlowKeywords { before(node.whileKeyword, tokens: .break(.same), .open) - after(node.condition.lastToken, tokens: .close) + after(node.condition.lastToken(viewMode: .sourceAccurate), tokens: .close) } else { // The length of the condition needs to force the breaks around the braces of the repeat // stmt's body, so that there's always a break before the right brace when the while & @@ -613,7 +613,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { before(node.whileKeyword, tokens: .space) // The `open` token occurs after the ending tokens for the braced `body` node. before(node.body.rightBrace, tokens: .open) - after(node.condition.lastToken, tokens: .close) + after(node.condition.lastToken(viewMode: .sourceAccurate), tokens: .close) } after(node.whileKeyword, tokens: .space) return .visitChildren @@ -635,11 +635,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // old (pre-SE-0276) behavior (a fixed space after the `catch` keyword). if catchItems.count > 1 { for catchItem in catchItems { - before(catchItem.firstToken, tokens: .break(.open(kind: .continuation))) - after(catchItem.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + before(catchItem.firstToken(viewMode: .sourceAccurate), tokens: .break(.open(kind: .continuation))) + after(catchItem.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } } else { - before(node.catchItems?.firstToken, tokens: .space) + before(node.catchItems?.firstToken(viewMode: .sourceAccurate), tokens: .space) } } @@ -661,17 +661,17 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: ReturnStmtSyntax) -> SyntaxVisitorContinueKind { if let expression = node.expression { if leftmostMultilineStringLiteral(of: expression) != nil { - before(expression.firstToken, tokens: .break(.open)) - after(expression.lastToken, tokens: .break(.close(mustBreak: false))) + before(expression.firstToken(viewMode: .sourceAccurate), tokens: .break(.open)) + after(expression.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false))) } else { - before(expression.firstToken, tokens: .break) + before(expression.firstToken(viewMode: .sourceAccurate), tokens: .break) } } return .visitChildren } override func visit(_ node: ThrowStmtSyntax) -> SyntaxVisitorContinueKind { - before(node.expression.firstToken, tokens: .break) + before(node.expression.firstToken(viewMode: .sourceAccurate), tokens: .break) return .visitChildren } @@ -690,10 +690,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // if-configuration clause requires a break here in order to be allowed on a new line. for ifConfigDecl in node.cases.filter({ $0.is(IfConfigDeclSyntax.self) }) { if config.indentSwitchCaseLabels { - before(ifConfigDecl.firstToken, tokens: .break(.open)) - after(ifConfigDecl.lastToken, tokens: .break(.close, size: 0)) + before(ifConfigDecl.firstToken(viewMode: .sourceAccurate), tokens: .break(.open)) + after(ifConfigDecl.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, size: 0)) } else { - before(ifConfigDecl.firstToken, tokens: .break(.same)) + before(ifConfigDecl.firstToken(viewMode: .sourceAccurate), tokens: .break(.same)) } } @@ -713,10 +713,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } else { openBreak = .break(.same, newlines: .soft) } - before(node.firstToken, tokens: openBreak) + before(node.firstToken(viewMode: .sourceAccurate), tokens: openBreak) - after(node.unknownAttr?.lastToken, tokens: .space) - after(node.label.lastToken, tokens: .break(.reset, size: 0), .break(.open), .open) + after(node.unknownAttr?.lastToken(viewMode: .sourceAccurate), tokens: .space) + after(node.label.lastToken(viewMode: .sourceAccurate), tokens: .break(.reset, size: 0), .break(.open), .open) // If switch/case labels were configured to be indented, insert an extra `close` break after // the case body to match the `open` break above @@ -730,10 +730,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // same effect. If instead the opening and closing tokens were omitted completely in the absence // of statements, comments within the empty case would be incorrectly indented to the same level // as the case label. - if node.label.lastToken != node.lastToken { - after(node.lastToken, tokens: afterLastTokenTokens) + if node.label.lastToken(viewMode: .sourceAccurate) != node.lastToken(viewMode: .sourceAccurate) { + after(node.lastToken(viewMode: .sourceAccurate), tokens: afterLastTokenTokens) } else { - before(node.nextToken, tokens: afterLastTokenTokens) + before(node.nextToken(viewMode: .sourceAccurate), tokens: afterLastTokenTokens) } return .visitChildren @@ -749,7 +749,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // following a `NoCasesWithOnlyFallthrough` transformation that might merge cases. let caseItems = Array(node.caseItems) for (index, item) in caseItems.enumerated() { - before(item.firstToken, tokens: .open) + before(item.firstToken(viewMode: .sourceAccurate), tokens: .open) if let trailingComma = item.trailingComma { // Insert a newline before the next item if it has a where clause and this item doesn't. let nextItemHasWhereClause = @@ -758,7 +758,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { let newlines: NewlineBehavior = requiresNewline ? .soft : .elective after(trailingComma, tokens: .close, .break(.continue, size: 1, newlines: newlines)) } else { - after(item.lastToken, tokens: .close) + after(item.lastToken(viewMode: .sourceAccurate), tokens: .close) } } @@ -837,9 +837,9 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { /// /// - Parameter node: The tuple expression element to be arranged. private func arrangeAsTupleExprElement(_ node: TupleExprElementSyntax) { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) after(node.colon, tokens: .break) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) if let trailingComma = node.trailingComma { closingDelimiterTokens.insert(trailingComma) } @@ -857,8 +857,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { insertTokens(.break(.same), betweenElementsOf: node) for element in node { - before(element.firstToken, tokens: .open) - after(element.lastToken, tokens: .close) + before(element.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(element.lastToken(viewMode: .sourceAccurate), tokens: .close) if let trailingComma = element.trailingComma { closingDelimiterTokens.insert(trailingComma) } @@ -868,12 +868,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let trailingComma = lastElement.trailingComma { ignoredTokens.insert(trailingComma) } - before(node.first?.firstToken, tokens: .commaDelimitedRegionStart) + before(node.first?.firstToken(viewMode: .sourceAccurate), tokens: .commaDelimitedRegionStart) let endToken = Token.commaDelimitedRegionEnd( hasTrailingComma: lastElement.trailingComma != nil, isSingleElement: node.first == lastElement) - after(lastElement.expression.lastToken, tokens: [endToken]) + after(lastElement.expression.lastToken(viewMode: .sourceAccurate), tokens: [endToken]) } return .visitChildren } @@ -899,9 +899,9 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { insertTokens(.break(.same), betweenElementsOf: node) for element in node { - before(element.firstToken, tokens: .open) + before(element.firstToken(viewMode: .sourceAccurate), tokens: .open) after(element.colon, tokens: .break) - after(element.lastToken, tokens: .close) + after(element.lastToken(viewMode: .sourceAccurate), tokens: .close) if let trailingComma = element.trailingComma { closingDelimiterTokens.insert(trailingComma) } @@ -911,12 +911,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let trailingComma = lastElement.trailingComma { ignoredTokens.insert(trailingComma) } - before(node.first?.firstToken, tokens: .commaDelimitedRegionStart) + before(node.first?.firstToken(viewMode: .sourceAccurate), tokens: .commaDelimitedRegionStart) let endToken = Token.commaDelimitedRegionEnd( hasTrailingComma: lastElement.trailingComma != nil, isSingleElement: node.first == node.last) - after(lastElement.lastToken, tokens: endToken) + after(lastElement.lastToken(viewMode: .sourceAccurate), tokens: endToken) } return .visitChildren } @@ -958,10 +958,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // When this function call is wrapped by a try-expr or await-expr, the group applied when // visiting that wrapping expression is sufficient. Adding another group here in that case // can result in unnecessarily breaking after the try/await keyword. - if !(base.firstToken?.previousToken(viewMode: .all)?.parent?.is(TryExprSyntax.self) ?? false - || base.firstToken?.previousToken(viewMode: .all)?.parent?.is(AwaitExprSyntax.self) ?? false) { - before(base.firstToken, tokens: .open) - after(calledMemberAccessExpr.name.lastToken, tokens: .close) + if !(base.firstToken(viewMode: .sourceAccurate)?.previousToken(viewMode: .all)?.parent?.is(TryExprSyntax.self) ?? false + || base.firstToken(viewMode: .sourceAccurate)?.previousToken(viewMode: .all)?.parent?.is(AwaitExprSyntax.self) ?? false) { + before(base.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(calledMemberAccessExpr.name.lastToken(viewMode: .sourceAccurate), tokens: .close) } } } @@ -1049,7 +1049,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { shouldGroup: Bool ) { if shouldGroup { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) } var additionalEndTokens = [Token]() @@ -1077,7 +1077,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } after(trailingComma, tokens: afterTrailingComma) } else if shouldGroup { - after(node.lastToken, tokens: additionalEndTokens + [.close]) + after(node.lastToken(viewMode: .sourceAccurate), tokens: additionalEndTokens + [.close]) } } @@ -1118,7 +1118,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: ClosureSignatureSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) arrangeAttributeList( node.attributes, suppressFinalBreak: node.input == nil && node.capture == nil) @@ -1147,16 +1147,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } else { // Group outside of the parens, so that the argument list together, preferring to break // between the argument list and the output. - before(input.firstToken, tokens: .open) - after(input.lastToken, tokens: .close) + before(input.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(input.lastToken(viewMode: .sourceAccurate), tokens: .close) } arrangeClosureParameterClause(parameterClause, forcesBreakBeforeRightParen: true) } else { // Group around the arguments, but don't use open/close breaks because there are no parens // to create a new scope. - before(input.firstToken, tokens: .open(argumentListConsistency())) - after(input.lastToken, tokens: .close) + before(input.firstToken(viewMode: .sourceAccurate), tokens: .open(argumentListConsistency())) + after(input.lastToken(viewMode: .sourceAccurate), tokens: .close) } } @@ -1168,7 +1168,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } before(node.output?.arrow, tokens: .break) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) before(node.inTok, tokens: .break(.same)) return .visitChildren } @@ -1180,15 +1180,15 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: ClosureCaptureItemSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) - after(node.specifier?.lastToken, tokens: .break) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(node.specifier?.lastToken(viewMode: .sourceAccurate), tokens: .break) before(node.assignToken, tokens: .break) after(node.assignToken, tokens: .break) if let trailingComma = node.trailingComma { before(trailingComma, tokens: .close) after(trailingComma, tokens: .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -1198,8 +1198,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let calledMemberAccessExpr = node.calledExpression.as(MemberAccessExprSyntax.self) { if let base = calledMemberAccessExpr.base, base.is(IdentifierExprSyntax.self) { - before(base.firstToken, tokens: .open) - after(calledMemberAccessExpr.name.lastToken, tokens: .close) + before(base.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(calledMemberAccessExpr.name.lastToken(viewMode: .sourceAccurate), tokens: .close) } } @@ -1292,7 +1292,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: ClosureParameterSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) arrangeAttributeList(node.attributes) before( node.secondName, @@ -1302,13 +1302,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } override func visit(_ node: EnumCaseParameterSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) before( node.secondName, tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true))) @@ -1317,13 +1317,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } override func visit(_ node: FunctionParameterSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) arrangeAttributeList(node.attributes) before( node.secondName, @@ -1333,7 +1333,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -1345,7 +1345,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // `ReturnClauseSyntax`. To maintain the previous formatting behavior, // add a special case. before(node.arrow, tokens: .break) - before(node.returnType.firstToken, tokens: .break) + before(node.returnType.firstToken(viewMode: .sourceAccurate), tokens: .break) } else { after(node.arrow, tokens: .space) } @@ -1353,8 +1353,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Member type identifier is used when the return type is a member of another type. Add a group // here so that the base, dot, and member type are kept together when they fit. if node.returnType.is(MemberTypeIdentifierSyntax.self) { - before(node.returnType.firstToken, tokens: .open) - after(node.returnType.lastToken, tokens: .close) + before(node.returnType.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(node.returnType.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -1383,13 +1383,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { breakKindClose = .same } - let tokenToOpenWith = node.condition?.lastToken ?? node.poundKeyword + let tokenToOpenWith = node.condition?.lastToken(viewMode: .sourceAccurate) ?? node.poundKeyword after(tokenToOpenWith, tokens: .break(breakKindOpen), .open) // Unlike other code blocks, where we may want a single statement to be laid out on the same // line as a parent construct, the content of an `#if` block must always be on its own line; // the newline token inserted at the end enforces this. - if let lastElemTok = node.elements?.lastToken { + if let lastElemTok = node.elements?.lastToken(viewMode: .sourceAccurate) { after(lastElemTok, tokens: .break(breakKindClose, newlines: .soft), .close) } else { before(tokenToOpenWith.nextToken(viewMode: .all), tokens: .break(breakKindClose, newlines: .soft), .close) @@ -1400,7 +1400,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { let currentIfConfigDecl = node.parent?.parent?.as(IfConfigDeclSyntax.self) if let currentIfConfigDecl = currentIfConfigDecl, - let tokenBeforeCurrentIfConfigDecl = currentIfConfigDecl.previousToken, + let tokenBeforeCurrentIfConfigDecl = currentIfConfigDecl.previousToken(viewMode: .sourceAccurate), isNestedInIfConfig(node: Syntax(tokenBeforeCurrentIfConfigDecl)) || tokenBeforeCurrentIfConfigDecl.text == "}" { breakToken = .break(.reset) @@ -1410,16 +1410,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } before( - node.firstToken, + node.firstToken(viewMode: .sourceAccurate), tokens: [ .printerControl(kind: .enableBreaking), breakToken, ] ) } else if let condition = node.condition { - before(condition.firstToken, tokens: .printerControl(kind: .disableBreaking(allowDiscretionary: true))) + before(condition.firstToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .disableBreaking(allowDiscretionary: true))) after( - condition.lastToken, + condition.lastToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .enableBreaking), .break(.reset, size: 0)) } @@ -1434,11 +1434,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Skip ignored items, because the tokens after `item.lastToken` would be ignored and leave // unclosed open tokens. for item in node where !shouldFormatterIgnore(node: Syntax(item)) { - before(item.firstToken, tokens: .open) + before(item.firstToken(viewMode: .sourceAccurate), tokens: .open) let newlines: NewlineBehavior = item != node.last && shouldInsertNewline(basedOn: item.semicolon) ? .soft : .elective let resetSize = item.semicolon != nil ? 1 : 0 - after(item.lastToken, tokens: .close, .break(.reset, size: resetSize, newlines: newlines)) + after(item.lastToken(viewMode: .sourceAccurate), tokens: .close, .break(.reset, size: resetSize, newlines: newlines)) } return .visitChildren } @@ -1461,12 +1461,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: EnumCaseDeclSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) arrangeAttributeList(node.attributes) after(node.caseKeyword, tokens: .break) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -1478,7 +1478,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: OperatorPrecedenceAndTypesSyntax) -> SyntaxVisitorContinueKind { before(node.colon, tokens: .space) after(node.colon, tokens: .break(.open), .open) - after(node.designatedTypes.lastToken ?? node.lastToken, tokens: .break(.close, size: 0), .close) + after(node.designatedTypes.lastToken(viewMode: .sourceAccurate) ?? node.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, size: 0), .close) return .visitChildren } @@ -1512,13 +1512,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: PrecedenceGroupRelationSyntax) -> SyntaxVisitorContinueKind { after(node.colon, tokens: .break(.open)) - after(node.lastToken, tokens: .break(.close, newlines: .soft)) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, newlines: .soft)) return .visitChildren } override func visit(_ node: PrecedenceGroupAssignmentSyntax) -> SyntaxVisitorContinueKind { after(node.colon, tokens: .break(.open)) - after(node.lastToken, tokens: .break(.close, newlines: .soft)) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, newlines: .soft)) return .visitChildren } @@ -1529,7 +1529,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: PrecedenceGroupAssociativitySyntax) -> SyntaxVisitorContinueKind { after(node.colon, tokens: .break(.open)) - after(node.lastToken, tokens: .break(.close, newlines: .soft)) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, newlines: .soft)) return .visitChildren } @@ -1541,11 +1541,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Skip ignored items, because the tokens after `item.lastToken` would be ignored and leave // unclosed open tokens. for item in node where !shouldFormatterIgnore(node: Syntax(item)) { - before(item.firstToken, tokens: .open) + before(item.firstToken(viewMode: .sourceAccurate), tokens: .open) let newlines: NewlineBehavior = item != node.last && shouldInsertNewline(basedOn: item.semicolon) ? .soft : .elective let resetSize = item.semicolon != nil ? 1 : 0 - after(item.lastToken, tokens: .close, .break(.reset, size: resetSize, newlines: newlines)) + after(item.lastToken(viewMode: .sourceAccurate), tokens: .close, .break(.reset, size: resetSize, newlines: newlines)) } return .visitChildren } @@ -1560,8 +1560,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // breaking behavior. if let exprStmt = node.item.as(ExpressionStmtSyntax.self), let ifStmt = exprStmt.expression.as(IfExprSyntax.self) { - before(ifStmt.conditions.firstToken, tokens: .open(.consistent)) - after(ifStmt.lastToken, tokens: .close) + before(ifStmt.conditions.firstToken(viewMode: .sourceAccurate), tokens: .open(.consistent)) + after(ifStmt.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -1589,7 +1589,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: TupleTypeElementSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) before( node.secondName, tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true))) @@ -1598,7 +1598,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -1625,7 +1625,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: TryExprSyntax) -> SyntaxVisitorContinueKind { before( - node.expression.firstToken, + node.expression.firstToken(viewMode: .sourceAccurate), tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true))) // Check for an anchor token inside of the expression to group with the try keyword. @@ -1639,7 +1639,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: AwaitExprSyntax) -> SyntaxVisitorContinueKind { before( - node.expression.firstToken, + node.expression.firstToken(viewMode: .sourceAccurate), tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true))) // Check for an anchor token inside of the expression to group with the await keyword. @@ -1672,12 +1672,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // sequence. This check has to happen here so that the `MemberAccessExprSyntax.name` is // available. if base.is(IdentifierExprSyntax.self) { - return memberAccessExpr.name.lastToken + return memberAccessExpr.name.lastToken(viewMode: .sourceAccurate) } return findTryAwaitExprConnectingToken(inExpr: base) } if expr.is(IdentifierExprSyntax.self) { - return expr.lastToken + return expr.lastToken(viewMode: .sourceAccurate) } return nil } @@ -1687,7 +1687,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: AttributeSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) switch node.argument { case .argumentList(let argumentList)?: if let leftParen = node.leftParen, let rightParen = node.rightParen { @@ -1707,7 +1707,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { case nil: break } - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -1719,24 +1719,24 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: AvailabilityLabeledArgumentSyntax) -> SyntaxVisitorContinueKind { before(node.label, tokens: .open) after(node.colon, tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true))) - after(node.value.lastToken, tokens: .close) + after(node.value.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } override func visit(_ node: AvailabilityVersionRestrictionSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) after(node.platform, tokens: .break(.continue, size: 1)) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } override func visit(_ node: ConditionElementSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) if let comma = node.trailingComma { after(comma, tokens: .close, .break(.same)) closingDelimiterTokens.insert(comma) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -1747,13 +1747,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: ImportDeclSyntax) -> SyntaxVisitorContinueKind { // Import declarations should never be wrapped. - before(node.firstToken, tokens: .printerControl(kind: .disableBreaking(allowDiscretionary: false))) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .disableBreaking(allowDiscretionary: false))) arrangeAttributeList(node.attributes) after(node.importTok, tokens: .space) after(node.importKind, tokens: .space) - after(node.lastToken, tokens: .printerControl(kind: .enableBreaking)) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .printerControl(kind: .enableBreaking)) return .visitChildren } @@ -1777,9 +1777,9 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // that it is glued to the last token of the ternary. let closeScopeToken: TokenSyntax? if let parenExpr = outermostEnclosingNode(from: Syntax(node.secondChoice)) { - closeScopeToken = parenExpr.lastToken + closeScopeToken = parenExpr.lastToken(viewMode: .sourceAccurate) } else { - closeScopeToken = node.secondChoice.lastToken + closeScopeToken = node.secondChoice.lastToken(viewMode: .sourceAccurate) } after(closeScopeToken, tokens: .break(.close(mustBreak: false), size: 0), .close, .close) return .visitChildren @@ -1813,7 +1813,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } before(node.whereKeyword, tokens: wherePrecedingBreak, .open) after(node.whereKeyword, tokens: .break) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -1827,7 +1827,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } else { breakOrSpace = .break } - after(node.lastToken, tokens: breakOrSpace) + after(node.lastToken(viewMode: .sourceAccurate), tokens: breakOrSpace) return .visitChildren } @@ -1840,7 +1840,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { before(asyncOrReasyncKeyword, tokens: .open) after(throwsOrRethrowsKeyword, tokens: .close) } - before(node.output?.firstToken, tokens: .break) + before(node.output?.firstToken(viewMode: .sourceAccurate), tokens: .break) return .visitChildren } @@ -1864,7 +1864,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // If there were spaces in the trailing trivia of the previous token, they would have been // ignored (since this expression would be expected to insert its own preceding breaks). // Preserve that whitespace verbatim for now. - if let previousToken = node.firstToken?.previousToken { + if let previousToken = node.firstToken(viewMode: .sourceAccurate)?.previousToken(viewMode: .sourceAccurate) { appendTrailingTrivia(previousToken, forced: true) } verbatimToken(Syntax(node), indentingBehavior: .none) @@ -1886,7 +1886,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let (unindentingNode, _, breakKind) = stackedIndentationBehavior(after: binOp, rhs: rhs) { beforeTokens = [.break(.open(kind: breakKind))] - after(unindentingNode.lastToken, tokens: [.break(.close(mustBreak: false), size: 0)]) + after(unindentingNode.lastToken(viewMode: .sourceAccurate), tokens: [.break(.close(mustBreak: false), size: 0)]) } else { beforeTokens = [.break(.continue)] } @@ -1896,10 +1896,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // operator token. if isCompoundExpression(rhs) { beforeTokens.append(.open) - after(rhs.lastToken, tokens: .close) + after(rhs.lastToken(viewMode: .sourceAccurate), tokens: .close) } - after(binOp.lastToken, tokens: beforeTokens) + after(binOp.lastToken(viewMode: .sourceAccurate), tokens: beforeTokens) } else if let (unindentingNode, shouldReset, breakKind) = stackedIndentationBehavior(after: binOp, rhs: rhs) { @@ -1912,27 +1912,27 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // usual single-level "continuation line or not" behavior. let openBreakTokens: [Token] = [.break(.open(kind: breakKind)), .open] if wrapsBeforeOperator { - before(binOp.firstToken, tokens: openBreakTokens) + before(binOp.firstToken(viewMode: .sourceAccurate), tokens: openBreakTokens) } else { - after(binOp.lastToken, tokens: openBreakTokens) + after(binOp.lastToken(viewMode: .sourceAccurate), tokens: openBreakTokens) } let closeBreakTokens: [Token] = (shouldReset ? [.break(.reset, size: 0)] : []) + [.break(.close(mustBreak: false), size: 0), .close] - after(unindentingNode.lastToken, tokens: closeBreakTokens) + after(unindentingNode.lastToken(viewMode: .sourceAccurate), tokens: closeBreakTokens) } else { if wrapsBeforeOperator { - before(binOp.firstToken, tokens: .break(.continue)) + before(binOp.firstToken(viewMode: .sourceAccurate), tokens: .break(.continue)) } else { - after(binOp.lastToken, tokens: .break(.continue)) + after(binOp.lastToken(viewMode: .sourceAccurate), tokens: .break(.continue)) } } if wrapsBeforeOperator { - after(binOp.lastToken, tokens: .space) + after(binOp.lastToken(viewMode: .sourceAccurate), tokens: .space) } else { - before(binOp.firstToken, tokens: .space) + before(binOp.firstToken(viewMode: .sourceAccurate), tokens: .space) } } @@ -1949,15 +1949,15 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { override func visit(_ node: AsExprSyntax) -> SyntaxVisitorContinueKind { before(node.asTok, tokens: .break(.continue), .open) - before(node.typeName.firstToken, tokens: .space) - after(node.lastToken, tokens: .close) + before(node.typeName.firstToken(viewMode: .sourceAccurate), tokens: .space) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } override func visit(_ node: IsExprSyntax) -> SyntaxVisitorContinueKind { before(node.isTok, tokens: .break(.continue), .open) - before(node.typeName.firstToken, tokens: .space) - after(node.lastToken, tokens: .close) + before(node.typeName.firstToken(viewMode: .sourceAccurate), tokens: .space) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -2002,12 +2002,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { after(node.bindingKeyword, tokens: .break(.open)) for binding in node.bindings { - before(binding.firstToken, tokens: .open) + before(binding.firstToken(viewMode: .sourceAccurate), tokens: .open) after(binding.trailingComma, tokens: .break(.same)) - after(binding.lastToken, tokens: .close) + after(binding.lastToken(viewMode: .sourceAccurate), tokens: .close) } - after(node.lastToken, tokens: .break(.close, size: 0)) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, size: 0)) } return .visitChildren @@ -2026,25 +2026,25 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { typeAnnotation.colon, tokens: .break(.open(kind: .continuation), newlines: .elective(ignoresDiscretionary: true))) closesNeeded += 1 - closeAfterToken = typeAnnotation.lastToken + closeAfterToken = typeAnnotation.lastToken(viewMode: .sourceAccurate) } if let initializer = node.initializer { let expr = initializer.value if let (unindentingNode, _, breakKind) = stackedIndentationBehavior(rhs: expr) { after(initializer.equal, tokens: .break(.open(kind: breakKind))) - after(unindentingNode.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + after(unindentingNode.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } else { after(initializer.equal, tokens: .break(.continue)) } - closeAfterToken = initializer.lastToken + closeAfterToken = initializer.lastToken(viewMode: .sourceAccurate) // When the RHS is a simple expression, even if is requires multiple lines, we don't add a // group so that as much of the expression as possible can stay on the same line as the // operator token. if isCompoundExpression(expr) { - before(expr.firstToken, tokens: .open) - after(expr.lastToken, tokens: .close) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: .close) } } @@ -2086,8 +2086,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { after(node.typealiasKeyword, tokens: .break) if let genericWhereClause = node.genericWhereClause { - before(genericWhereClause.firstToken, tokens: .break(.same), .open) - after(node.lastToken, tokens: .close) + before(genericWhereClause.firstToken(viewMode: .sourceAccurate), tokens: .break(.same), .open) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -2119,8 +2119,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: TypeAnnotationSyntax) -> SyntaxVisitorContinueKind { - before(node.type.firstToken, tokens: .open) - after(node.type.lastToken, tokens: .close) + before(node.type.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(node.type.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -2142,11 +2142,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: GenericArgumentSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -2164,22 +2164,22 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: GenericParameterSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) after(node.colon, tokens: .break) if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } override func visit(_ node: PrimaryAssociatedTypeSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -2260,8 +2260,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { after(node.associatedtypeKeyword, tokens: .break) if let genericWhereClause = node.genericWhereClause { - before(genericWhereClause.firstToken, tokens: .break(.same), .open) - after(node.lastToken, tokens: .close) + before(genericWhereClause.firstToken(viewMode: .sourceAccurate), tokens: .break(.same), .open) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -2271,16 +2271,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: GenericWhereClauseSyntax) -> SyntaxVisitorContinueKind { - guard node.whereKeyword != node.lastToken else { + guard node.whereKeyword != node.lastToken(viewMode: .sourceAccurate) else { verbatimToken(Syntax(node)) return .skipChildren } after(node.whereKeyword, tokens: .break(.open)) - after(node.lastToken, tokens: .break(.close, size: 0)) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, size: 0)) - before(node.requirementList.firstToken, tokens: .open(genericRequirementListConsistency())) - after(node.requirementList.lastToken, tokens: .close) + before(node.requirementList.firstToken(viewMode: .sourceAccurate), tokens: .open(genericRequirementListConsistency())) + after(node.requirementList.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -2294,11 +2294,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: GenericRequirementSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) if let trailingComma = node.trailingComma { after(trailingComma, tokens: .close, .break(.same)) } else { - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -2350,8 +2350,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Normally, the open-break is placed before the open token. In this case, it's intentionally // ordered differently so that the inheritance list can start on the current line and only // breaks if the first item in the list would overflow the column limit. - before(node.inheritedTypeCollection.firstToken, tokens: .open, .break(.open, size: 1)) - after(node.inheritedTypeCollection.lastToken, tokens: .break(.close, size: 0), .close) + before(node.inheritedTypeCollection.firstToken(viewMode: .sourceAccurate), tokens: .open, .break(.open, size: 1)) + after(node.inheritedTypeCollection.lastToken(viewMode: .sourceAccurate), tokens: .break(.close, size: 0), .close) return .visitChildren } @@ -2366,9 +2366,9 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } override func visit(_ node: MatchingPatternConditionSyntax) -> SyntaxVisitorContinueKind { - before(node.firstToken, tokens: .open) + before(node.firstToken(viewMode: .sourceAccurate), tokens: .open) after(node.caseKeyword, tokens: .break) - after(node.lastToken, tokens: .close) + after(node.lastToken(viewMode: .sourceAccurate), tokens: .close) return .visitChildren } @@ -2379,7 +2379,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { after( typeAnnotation.colon, tokens: .break(.open(kind: .continuation), newlines: .elective(ignoresDiscretionary: true))) - after(typeAnnotation.lastToken, tokens: .break(.close(mustBreak: false), size: 0)) + after(typeAnnotation.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0)) } return .visitChildren @@ -2403,10 +2403,10 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if let whereClause = node.whereClause { if needsBreakBeforeWhereClause { - before(whereClause.firstToken, tokens: .break(.same)) + before(whereClause.firstToken(viewMode: .sourceAccurate), tokens: .break(.same)) } - before(whereClause.firstToken, tokens: .open) - after(whereClause.lastToken, tokens: .close) + before(whereClause.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(whereClause.lastToken(viewMode: .sourceAccurate), tokens: .close) } return .visitChildren } @@ -2588,13 +2588,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { suppressFinalBreak: Bool = false ) { if let attributes = attributes { - before(attributes.firstToken, tokens: .open) + before(attributes.firstToken(viewMode: .sourceAccurate), tokens: .open) insertTokens(.break(.same), betweenElementsOf: attributes) var afterAttributeTokens = [Token.close] if !suppressFinalBreak { afterAttributeTokens.append(.break(.same)) } - after(attributes.lastToken, tokens: afterAttributeTokens) + after(attributes.lastToken(viewMode: .sourceAccurate), tokens: afterAttributeTokens) } } @@ -2860,7 +2860,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { private func afterTokensForTrailingComment(_ token: TokenSyntax) -> (isLineComment: Bool, tokens: [Token]) { - let nextToken = token.nextToken + let nextToken = token.nextToken(viewMode: .sourceAccurate) guard let trivia = nextToken?.leadingTrivia, let firstPiece = trivia.first else { @@ -3146,7 +3146,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { /// Returns true if the first token of the given node is an open delimiter that may desire /// special breaking behavior in some cases. private func startsWithOpenDelimiter(_ node: Syntax) -> Bool { - guard let token = node.firstToken else { return false } + guard let token = node.firstToken(viewMode: .sourceAccurate) else { return false } switch token.tokenKind { case .leftBrace, .leftParen, .leftSquareBracket: return true default: return false @@ -3222,8 +3222,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { ) { switch Syntax(expr).as(SyntaxEnum.self) { case .memberAccessExpr, .subscriptExpr: - before(expr.firstToken, tokens: .open) - after(expr.lastToken, tokens: .close) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: .close) default: break } @@ -3235,8 +3235,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { if expr.is(FunctionCallExprSyntax.self), let operatorExpr = operatorExpr, !isAssigningOperator(operatorExpr) { - before(expr.firstToken, tokens: .open) - after(expr.lastToken, tokens: .close) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: .open) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: .close) } } @@ -3321,12 +3321,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { /// alongside the last token of the given node. Any tokens between `node.lastToken` and the /// returned node's `lastToken` are delimiter tokens that shouldn't be preceded by a break. private func outermostEnclosingNode(from node: Syntax) -> Syntax? { - guard let afterToken = node.lastToken?.nextToken(viewMode: .all), closingDelimiterTokens.contains(afterToken) + guard let afterToken = node.lastToken(viewMode: .sourceAccurate)?.nextToken(viewMode: .all), closingDelimiterTokens.contains(afterToken) else { return nil } var parenthesizedExpr = afterToken.parent - while let nextToken = parenthesizedExpr?.lastToken?.nextToken(viewMode: .all), + while let nextToken = parenthesizedExpr?.lastToken(viewMode: .sourceAccurate)?.nextToken(viewMode: .all), closingDelimiterTokens.contains(nextToken), let nextExpr = nextToken.parent { @@ -3463,7 +3463,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // `verbatim` token in order for the first token to be printed with correct indentation. All // following lines in the ignored node are printed as-is with no changes to indentation. var nodeText = node.description - if let firstToken = node.firstToken { + if let firstToken = node.firstToken(viewMode: .sourceAccurate) { extractLeadingTrivia(firstToken) let leadingTriviaText = firstToken.leadingTrivia.reduce(into: "") { $1.write(to: &$0) } nodeText = String(nodeText.dropFirst(leadingTriviaText.count)) @@ -3472,7 +3472,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // The leading trivia of the next token, after the ignored node, may contain content that // belongs with the ignored node. The trivia extraction that is performed for `lastToken` later // excludes that content so it needs to be extracted and added to the token stream here. - if let next = node.lastToken?.nextToken(viewMode: .all), let trivia = next.leadingTrivia.first { + if let next = node.lastToken(viewMode: .sourceAccurate)?.nextToken(viewMode: .all), let trivia = next.leadingTrivia.first { switch trivia { case .lineComment, .blockComment: trivia.write(to: &nodeText) @@ -3531,8 +3531,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { (hasCompoundExpression, _) = insertContextualBreaks(base, isTopLevel: false) } if isTopLevel { - before(expr.firstToken, tokens: .contextualBreakingStart) - after(expr.lastToken, tokens: .contextualBreakingEnd) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: .contextualBreakingStart) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: .contextualBreakingEnd) } return (hasCompoundExpression, true) } else if let callingExpr = expr.asProtocol(CallingExprSyntaxProtocol.self) { @@ -3557,14 +3557,14 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { } } before(calledMemberAccessExpr.dot, tokens: beforeTokens) - after(expr.lastToken, tokens: afterTokens) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: afterTokens) if isTopLevel { - before(expr.firstToken, tokens: .contextualBreakingStart) - after(expr.lastToken, tokens: .contextualBreakingEnd) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: .contextualBreakingStart) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: .contextualBreakingEnd) } } else { - before(expr.firstToken, tokens: beforeTokens) - after(expr.lastToken, tokens: afterTokens) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: beforeTokens) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: afterTokens) } return (true, hasMemberAccess) } @@ -3572,8 +3572,8 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor { // Otherwise, it's an expression that isn't calling another expression (e.g. array or // dictionary, identifier, etc.). Wrap it in a breaking context but don't try to pre-visit // children nodes. - before(expr.firstToken, tokens: .contextualBreakingStart) - after(expr.lastToken, tokens: .contextualBreakingEnd) + before(expr.firstToken(viewMode: .sourceAccurate), tokens: .contextualBreakingStart) + after(expr.lastToken(viewMode: .sourceAccurate), tokens: .contextualBreakingEnd) let hasCompoundExpression = !expr.is(IdentifierExprSyntax.self) return (hasCompoundExpression, false) } @@ -3767,7 +3767,7 @@ fileprivate func isFormatterIgnorePresent(inTrivia trivia: Trivia, isWholeFile: fileprivate func shouldFormatterIgnore(node: Syntax) -> Bool { // Regardless of the level of nesting, if the ignore directive is present on the first token // contained within the node then the entire node is eligible for ignoring. - if let firstTrivia = node.firstToken?.leadingTrivia { + if let firstTrivia = node.firstToken(viewMode: .sourceAccurate)?.leadingTrivia { return isFormatterIgnorePresent(inTrivia: firstTrivia, isWholeFile: false) } return false @@ -3779,7 +3779,7 @@ fileprivate func shouldFormatterIgnore(node: Syntax) -> Bool { /// /// - Parameter file: The root syntax node for a source file. fileprivate func shouldFormatterIgnore(file: SourceFileSyntax) -> Bool { - if let firstTrivia = file.firstToken?.leadingTrivia { + if let firstTrivia = file.firstToken(viewMode: .sourceAccurate)?.leadingTrivia { return isFormatterIgnorePresent(inTrivia: firstTrivia, isWholeFile: true) } return false diff --git a/Sources/SwiftFormatRules/AddModifierRewriter.swift b/Sources/SwiftFormatRules/AddModifierRewriter.swift index 4f10b4c85..f58a4472e 100644 --- a/Sources/SwiftFormatRules/AddModifierRewriter.swift +++ b/Sources/SwiftFormatRules/AddModifierRewriter.swift @@ -166,18 +166,18 @@ fileprivate final class AddModifierRewriter: SyntaxRewriter { for modifiersProvider: (NodeType) -> ModifierListSyntax? ) -> NodeType { guard let modifier = modifiersProvider(node)?.firstAndOnly, - let movingLeadingTrivia = modifier.nextToken?.leadingTrivia + let movingLeadingTrivia = modifier.nextToken(viewMode: .sourceAccurate)?.leadingTrivia else { // Otherwise, there's no trivia that needs to be relocated so the node is fine. return node } let nodeWithTrivia = replaceTrivia( on: node, - token: modifier.firstToken, + token: modifier.firstToken(viewMode: .sourceAccurate), leadingTrivia: movingLeadingTrivia) return replaceTrivia( on: nodeWithTrivia, - token: modifiersProvider(nodeWithTrivia)?.first?.nextToken, + token: modifiersProvider(nodeWithTrivia)?.first?.nextToken(viewMode: .sourceAccurate), leadingTrivia: []) } } diff --git a/Sources/SwiftFormatRules/DeclSyntaxProtocol+Comments.swift b/Sources/SwiftFormatRules/DeclSyntaxProtocol+Comments.swift index a496c92c8..b695ed7fe 100644 --- a/Sources/SwiftFormatRules/DeclSyntaxProtocol+Comments.swift +++ b/Sources/SwiftFormatRules/DeclSyntaxProtocol+Comments.swift @@ -15,7 +15,7 @@ import SwiftSyntax extension DeclSyntaxProtocol { /// Searches through the leading trivia of this decl for a documentation comment. var docComment: String? { - guard let tok = firstToken else { return nil } + guard let tok = firstToken(viewMode: .sourceAccurate) else { return nil } var comment = [String]() // We need to skip trivia until we see the first comment. This trivia will include all the diff --git a/Sources/SwiftFormatRules/DoNotUseSemicolons.swift b/Sources/SwiftFormatRules/DoNotUseSemicolons.swift index 0aa080a3b..604ece259 100644 --- a/Sources/SwiftFormatRules/DoNotUseSemicolons.swift +++ b/Sources/SwiftFormatRules/DoNotUseSemicolons.swift @@ -56,7 +56,7 @@ public final class DoNotUseSemicolons: SyntaxFormatRule { defer { newItems[idx] = newItem } // Check if the leading trivia for this statement needs a new line. - if previousHadSemicolon, let firstToken = newItem.firstToken, + if previousHadSemicolon, let firstToken = newItem.firstToken(viewMode: .sourceAccurate), !firstToken.leadingTrivia.containsNewlines { let leadingTrivia = .newlines(1) + firstToken.leadingTrivia diff --git a/Sources/SwiftFormatRules/FullyIndirectEnum.swift b/Sources/SwiftFormatRules/FullyIndirectEnum.swift index aab82ed1f..880445836 100644 --- a/Sources/SwiftFormatRules/FullyIndirectEnum.swift +++ b/Sources/SwiftFormatRules/FullyIndirectEnum.swift @@ -53,14 +53,14 @@ public final class FullyIndirectEnum: SyntaxFormatRule { // If the `indirect` keyword being added would be the first token in the decl, we need to move // the leading trivia from the `enum` keyword to the new modifier to preserve the existing // line breaks/comments/indentation. - let firstTok = node.firstToken! + let firstTok = node.firstToken(viewMode: .sourceAccurate)! let leadingTrivia: Trivia let newEnumDecl: EnumDeclSyntax if firstTok.tokenKind == .keyword(.enum) { leadingTrivia = firstTok.leadingTrivia newEnumDecl = replaceTrivia( - on: node, token: node.firstToken, leadingTrivia: []) + on: node, token: node.firstToken(viewMode: .sourceAccurate), leadingTrivia: []) } else { leadingTrivia = [] newEnumDecl = node @@ -97,7 +97,7 @@ public final class FullyIndirectEnum: SyntaxFormatRule { ) -> EnumCaseDeclSyntax { if let modifiers = unformattedCase.modifiers, let first = modifiers.first { return replaceTrivia( - on: unformattedCase, token: first.firstToken, leadingTrivia: leadingTrivia + on: unformattedCase, token: first.firstToken(viewMode: .sourceAccurate), leadingTrivia: leadingTrivia ) } else { return replaceTrivia( diff --git a/Sources/SwiftFormatRules/ModifierListSyntax+Convenience.swift b/Sources/SwiftFormatRules/ModifierListSyntax+Convenience.swift index eb7cebab9..7a4b82564 100644 --- a/Sources/SwiftFormatRules/ModifierListSyntax+Convenience.swift +++ b/Sources/SwiftFormatRules/ModifierListSyntax+Convenience.swift @@ -72,12 +72,12 @@ extension ModifierListSyntax { if index == 0 { guard formatTrivia else { return inserting(modifier, at: index) } - guard let firstMod = first, let firstTok = firstMod.firstToken else { + guard let firstMod = first, let firstTok = firstMod.firstToken(viewMode: .sourceAccurate) else { return inserting(modifier, at: index) } let formattedMod = replaceTrivia( on: modifier, - token: modifier.firstToken, + token: modifier.firstToken(viewMode: .sourceAccurate), leadingTrivia: firstTok.leadingTrivia) newModifiers[0] = replaceTrivia( on: firstMod, diff --git a/Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift b/Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift index cb5f6dc01..f8966ec2c 100644 --- a/Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift +++ b/Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift @@ -150,7 +150,7 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule { // Check for any comments that are inline on the fallthrough statement. Inline comments are // always stored in the next token's leading trivia. - if let nextLeadingTrivia = onlyStatement.nextToken?.leadingTrivia, + if let nextLeadingTrivia = onlyStatement.nextToken(viewMode: .sourceAccurate)?.leadingTrivia, nextLeadingTrivia.prefix(while: { !$0.isNewline }).contains(where: { $0.isComment }) { return false diff --git a/Sources/SwiftFormatRules/NoEmptyTrailingClosureParentheses.swift b/Sources/SwiftFormatRules/NoEmptyTrailingClosureParentheses.swift index 2df45668d..6bc786e98 100644 --- a/Sources/SwiftFormatRules/NoEmptyTrailingClosureParentheses.swift +++ b/Sources/SwiftFormatRules/NoEmptyTrailingClosureParentheses.swift @@ -29,7 +29,7 @@ public final class NoEmptyTrailingClosureParentheses: SyntaxFormatRule { { return super.visit(node) } - guard let name = node.calledExpression.lastToken?.with(\.leadingTrivia, []).with(\.trailingTrivia, []) else { + guard let name = node.calledExpression.lastToken(viewMode: .sourceAccurate)?.with(\.leadingTrivia, []).with(\.trailingTrivia, []) else { return super.visit(node) } @@ -42,7 +42,7 @@ public final class NoEmptyTrailingClosureParentheses: SyntaxFormatRule { } let formattedExp = replaceTrivia( on: rewrittenCalledExpr, - token: rewrittenCalledExpr.lastToken, + token: rewrittenCalledExpr.lastToken(viewMode: .sourceAccurate), trailingTrivia: .spaces(1)) let formattedClosure = visit(trailingClosure).as(ClosureExprSyntax.self) let result = node.with(\.leftParen, nil).with(\.rightParen, nil).with(\.calledExpression, formattedExp) diff --git a/Sources/SwiftFormatRules/NoParensAroundConditions.swift b/Sources/SwiftFormatRules/NoParensAroundConditions.swift index 1ee8678a7..b860b4590 100644 --- a/Sources/SwiftFormatRules/NoParensAroundConditions.swift +++ b/Sources/SwiftFormatRules/NoParensAroundConditions.swift @@ -52,7 +52,7 @@ public final class NoParensAroundConditions: SyntaxFormatRule { } return replaceTrivia( on: visitedExpr, - token: visitedExpr.lastToken, + token: visitedExpr.lastToken(viewMode: .sourceAccurate), leadingTrivia: visitedTuple.leftParen.leadingTrivia, trailingTrivia: visitedTuple.rightParen.trailingTrivia ) diff --git a/Sources/SwiftFormatRules/OneVariableDeclarationPerLine.swift b/Sources/SwiftFormatRules/OneVariableDeclarationPerLine.swift index b21207b74..ff35a1ed1 100644 --- a/Sources/SwiftFormatRules/OneVariableDeclarationPerLine.swift +++ b/Sources/SwiftFormatRules/OneVariableDeclarationPerLine.swift @@ -163,7 +163,7 @@ private struct VariableDeclSplitter { // lines because the pretty printer will re-indent them correctly; we just // need to ensure that a newline is inserted before new decls. varDecl = replaceTrivia( - on: varDecl, token: varDecl.firstToken, leadingTrivia: .newlines(1)) + on: varDecl, token: varDecl.firstToken(viewMode: .sourceAccurate), leadingTrivia: .newlines(1)) fixedUpTrivia = true } diff --git a/Sources/SwiftFormatRules/OrderedImports.swift b/Sources/SwiftFormatRules/OrderedImports.swift index 187b79673..9b3e9730a 100644 --- a/Sources/SwiftFormatRules/OrderedImports.swift +++ b/Sources/SwiftFormatRules/OrderedImports.swift @@ -362,7 +362,7 @@ fileprivate func convertToCodeBlockItems(lines: [Line]) -> [CodeBlockItemSyntax] output.append( replaceTrivia( on: codeBlockItem, - token: codeBlockItem.firstToken, + token: codeBlockItem.firstToken(viewMode: .sourceAccurate), leadingTrivia: Trivia(pieces: triviaBuffer) ) ) @@ -509,17 +509,17 @@ fileprivate class Line { guard let syntaxNode = syntaxNode else { return nil } switch syntaxNode { case .importCodeBlock(let codeBlock, _): - return codeBlock.firstToken + return codeBlock.firstToken(viewMode: .sourceAccurate) case .nonImportCodeBlocks(let codeBlocks): - return codeBlocks.first?.firstToken + return codeBlocks.first?.firstToken(viewMode: .sourceAccurate) } } /// Returns a `LineType` the represents the type of import from the given import decl. private func importType(of importDecl: ImportDeclSyntax) -> LineType { - if let attr = importDecl.attributes?.firstToken, + if let attr = importDecl.attributes?.firstToken(viewMode: .sourceAccurate), attr.tokenKind == .atSign, - attr.nextToken?.text == "testable" + attr.nextToken(viewMode: .sourceAccurate)?.text == "testable" { return .testableImport } diff --git a/Sources/SwiftFormatRules/ReturnVoidInsteadOfEmptyTuple.swift b/Sources/SwiftFormatRules/ReturnVoidInsteadOfEmptyTuple.swift index b1e29c06e..baa0a8223 100644 --- a/Sources/SwiftFormatRules/ReturnVoidInsteadOfEmptyTuple.swift +++ b/Sources/SwiftFormatRules/ReturnVoidInsteadOfEmptyTuple.swift @@ -105,8 +105,8 @@ public final class ReturnVoidInsteadOfEmptyTuple: SyntaxFormatRule { return SimpleTypeIdentifierSyntax( name: TokenSyntax.identifier( "Void", - leadingTrivia: node.firstToken?.leadingTrivia ?? [], - trailingTrivia: node.lastToken?.trailingTrivia ?? []), + leadingTrivia: node.firstToken(viewMode: .sourceAccurate)?.leadingTrivia ?? [], + trailingTrivia: node.lastToken(viewMode: .sourceAccurate)?.trailingTrivia ?? []), genericArgumentClause: nil) } } diff --git a/Sources/SwiftFormatRules/UseShorthandTypeNames.swift b/Sources/SwiftFormatRules/UseShorthandTypeNames.swift index 8def63c71..e1844b898 100644 --- a/Sources/SwiftFormatRules/UseShorthandTypeNames.swift +++ b/Sources/SwiftFormatRules/UseShorthandTypeNames.swift @@ -258,7 +258,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { // instead of discarding the comment. wrappedType = replaceTrivia( - on: wrappedType, token: wrappedType.firstToken, leadingTrivia: leadingTrivia) + on: wrappedType, token: wrappedType.firstToken(viewMode: .sourceAccurate), leadingTrivia: leadingTrivia) } let optionalType = OptionalTypeSyntax( @@ -346,7 +346,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { // the comment. wrappedTypeExpr = replaceTrivia( - on: wrappedTypeExpr, token: wrappedTypeExpr.firstToken, leadingTrivia: leadingTrivia) + on: wrappedTypeExpr, token: wrappedTypeExpr.firstToken(viewMode: .sourceAccurate), leadingTrivia: leadingTrivia) } return OptionalChainingExprSyntax( @@ -410,7 +410,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { case .optionalType(let optionalType): let result = makeOptionalTypeExpression( wrapping: optionalType.wrappedType, - leadingTrivia: optionalType.firstToken?.leadingTrivia, + leadingTrivia: optionalType.firstToken(viewMode: .sourceAccurate)?.leadingTrivia, questionMark: optionalType.questionMark) return ExprSyntax(result) @@ -493,8 +493,8 @@ public final class UseShorthandTypeNames: SyntaxFormatRule { -> (leadingTrivia: Trivia, trailingTrivia: Trivia) { return ( - leadingTrivia: node.firstToken?.leadingTrivia ?? [], - trailingTrivia: node.lastToken?.trailingTrivia ?? [] + leadingTrivia: node.firstToken(viewMode: .sourceAccurate)?.leadingTrivia ?? [], + trailingTrivia: node.lastToken(viewMode: .sourceAccurate)?.trailingTrivia ?? [] ) } diff --git a/Sources/SwiftFormatRules/UseTripleSlashForDocumentationComments.swift b/Sources/SwiftFormatRules/UseTripleSlashForDocumentationComments.swift index d2c981433..4a976541b 100644 --- a/Sources/SwiftFormatRules/UseTripleSlashForDocumentationComments.swift +++ b/Sources/SwiftFormatRules/UseTripleSlashForDocumentationComments.swift @@ -98,7 +98,7 @@ public final class UseTripleSlashForDocumentationComments: SyntaxFormatRule { return !hasFoundDocComment ? decl : replaceTrivia( on: decl, - token: decl.firstToken, + token: decl.firstToken(viewMode: .sourceAccurate), leadingTrivia: Trivia(pieces: pieces.reversed()) ) } diff --git a/Sources/SwiftFormatRules/UseWhereClausesInForLoops.swift b/Sources/SwiftFormatRules/UseWhereClausesInForLoops.swift index 415929be7..25365e629 100644 --- a/Sources/SwiftFormatRules/UseWhereClausesInForLoops.swift +++ b/Sources/SwiftFormatRules/UseWhereClausesInForLoops.swift @@ -100,7 +100,7 @@ fileprivate func updateWithWhereCondition( statements: CodeBlockItemListSyntax ) -> ForInStmtSyntax { // Construct a new `where` clause with the condition. - let lastToken = node.sequenceExpr.lastToken + let lastToken = node.sequenceExpr.lastToken(viewMode: .sourceAccurate) var whereLeadingTrivia = Trivia() if lastToken?.trailingTrivia.containsSpaces == false { whereLeadingTrivia = .spaces(1) diff --git a/Sources/SwiftFormatRules/ValidateDocumentationComments.swift b/Sources/SwiftFormatRules/ValidateDocumentationComments.swift index cbf1bab18..c00921e8e 100644 --- a/Sources/SwiftFormatRules/ValidateDocumentationComments.swift +++ b/Sources/SwiftFormatRules/ValidateDocumentationComments.swift @@ -124,7 +124,7 @@ public final class ValidateDocumentationComments: SyntaxLintRule { let needsThrowsDesc = throwsOrRethrowsKeyword?.tokenKind == .keyword(.throws) if !needsThrowsDesc && throwsDesc != nil { - diagnose(.removeThrowsComment(funcName: name), on: throwsOrRethrowsKeyword ?? node.firstToken) + diagnose(.removeThrowsComment(funcName: name), on: throwsOrRethrowsKeyword ?? node.firstToken(viewMode: .sourceAccurate)) } else if needsThrowsDesc && throwsDesc == nil { diagnose(.documentErrorsThrown(funcName: name), on: throwsOrRethrowsKeyword) }