diff --git a/CodeGeneration/Sources/Utils/CodeGenerationFormat.swift b/CodeGeneration/Sources/Utils/CodeGenerationFormat.swift index 30d899f87d1..65c4b7cd2a2 100644 --- a/CodeGeneration/Sources/Utils/CodeGenerationFormat.swift +++ b/CodeGeneration/Sources/Utils/CodeGenerationFormat.swift @@ -108,7 +108,7 @@ public class CodeGenerationFormat: BasicFormat { private func formatChildrenSeparatedByNewline(children: SyntaxChildren, elementType: SyntaxType.Type) -> [SyntaxType] { increaseIndentationLevel() var formattedChildren = children.map { - self.visit($0).as(SyntaxType.self)! + self.rewrite($0.cast(SyntaxType.self)).cast(SyntaxType.self) } formattedChildren = formattedChildren.map { if $0.leadingTrivia.first?.isNewline == true { diff --git a/CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxRewriterFile.swift b/CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxRewriterFile.swift index f1f281c431f..e3decfa0167 100644 --- a/CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxRewriterFile.swift +++ b/CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxRewriterFile.swift @@ -30,33 +30,28 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { open class SyntaxRewriter """ ) { - DeclSyntax("public init() {}") + DeclSyntax("public let viewMode: SyntaxTreeViewMode") - for node in SYNTAX_NODES where !node.kind.isBase { - if (node.base == .syntax || node.base == .syntaxCollection) && node.kind != .missing { - DeclSyntax( - """ - /// Visit a ``\(node.kind.syntaxType)``. - /// - Parameter node: the node that is being visited - /// - Returns: the rewritten node - open func visit(_ node: \(node.kind.syntaxType)) -> \(node.kind.syntaxType) { - return Syntax(visitChildren(node)).cast(\(node.kind.syntaxType).self) - } - """ - ) - } else { - DeclSyntax( - """ - /// Visit a ``\(node.kind.syntaxType)``. - /// - Parameter node: the node that is being visited - /// - Returns: the rewritten node - open func visit(_ node: \(node.kind.syntaxType)) -> \(raw: node.baseType.syntaxBaseName) { - return \(raw: node.baseType.syntaxBaseName)(visitChildren(node)) - } - """ - ) + DeclSyntax( + """ + public init(viewMode: SyntaxTreeViewMode = .sourceAccurate) { + self.viewMode = viewMode } - } + """ + ) + + DeclSyntax( + """ + /// Rewrite `node` and anchor, making sure that the rewritten node also has + /// a parent if `node` had one. + public func rewrite(_ node: some SyntaxProtocol) -> Syntax { + let rewritten = self.visit(node.data) + return withExtendedLifetime(rewritten) { + return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena())) + } + } + """ + ) DeclSyntax( """ @@ -105,6 +100,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { /// Visit any Syntax node. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node + @available(*, deprecated, renamed: "rewrite(_:)") public func visit(_ node: Syntax) -> Syntax { return visit(node.data) } @@ -114,11 +110,37 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { DeclSyntax( """ public func visit(_ node: T) -> T { - return visit(Syntax(node)).cast(T.self) + return visit(node.data).cast(T.self) } """ ) + for node in SYNTAX_NODES where !node.kind.isBase { + if (node.base == .syntax || node.base == .syntaxCollection) && node.kind != .missing { + DeclSyntax( + """ + /// Visit a ``\(node.kind.syntaxType)``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: \(node.kind.syntaxType)) -> \(node.kind.syntaxType) { + return Syntax(visitChildren(node)).cast(\(node.kind.syntaxType).self) + } + """ + ) + } else { + DeclSyntax( + """ + /// Visit a ``\(node.kind.syntaxType)``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: \(node.kind.syntaxType)) -> \(raw: node.baseType.syntaxBaseName) { + return \(raw: node.baseType.syntaxBaseName)(visitChildren(node)) + } + """ + ) + } + } + for baseKind in SyntaxNodeKind.allCases where baseKind.isBase && baseKind != .syntax && baseKind != .syntaxCollection { DeclSyntax( """ @@ -258,34 +280,36 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { // initialize the new layout. Once we know that we have to rewrite the // layout, we need to collect all futher children, regardless of whether // they are rewritten or not. - + // newLayout is nil until the first child node is rewritten and rewritten // nodes are being collected. var newLayout: ContiguousArray? - + // Rewritten children just to keep their 'SyntaxArena' alive until they are // wrapped with 'Syntax' var rewrittens: ContiguousArray = [] - + let syntaxNode = node._syntaxNode - + // Incrementing i manually is faster than using .enumerated() var childIndex = 0 for (raw, info) in RawSyntaxChildren(syntaxNode) { defer { childIndex += 1 } - guard let child = raw else { - // Node does not exist. If we are collecting rewritten nodes, we need to - // collect this one as well, otherwise we can ignore it. + + guard let child = raw, viewMode.shouldTraverse(node: child) else { + // Node does not exist or should not be visited. If we are collecting + // rewritten nodes, we need to collect this one as well, otherwise we + // can ignore it. if newLayout != nil { - newLayout!.append(nil) + newLayout!.append(raw) } continue } - + // Build the Syntax node to rewrite let absoluteRaw = AbsoluteRawSyntax(raw: child, info: info) let data = SyntaxData(absoluteRaw, parent: syntaxNode) - + let rewritten = visit(data) if rewritten.data.nodeId != info.nodeId { // The node was rewritten, let's handle it @@ -293,7 +317,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { // We have not yet collected any previous rewritten nodes. Initialize // the new layout with the previous nodes of the parent. This is // possible, since we know they were not rewritten. - + // The below implementation is based on Collection.map but directly // reserves enough capacity for the entire layout. newLayout = ContiguousArray() @@ -302,7 +326,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { newLayout!.append(node.raw.layoutView!.children[j]) } } - + // Now that we know we have a new layout in which we collect rewritten // nodes, add it. rewrittens.append(rewritten) @@ -315,13 +339,13 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { } } } - + if let newLayout { // A child node was rewritten. Build the updated node. - + // Sanity check, ensure the new children are the same length. precondition(newLayout.count == node.raw.layoutView!.children.count) - + let arena = SyntaxArena() let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena) // 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here. @@ -335,18 +359,5 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { } """ ) - - DeclSyntax( - """ - /// Rewrite `node` and anchor, making sure that the rewritten node also has - /// a parent if `node` had one. - public func rewrite(_ node: Syntax) -> Syntax { - let rewritten = self.visit(node) - return withExtendedLifetime(rewritten) { - return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena())) - } - } - """ - ) } } diff --git a/EditorExtension/SwiftRefactorExtension/SourceEditorCommand.swift b/EditorExtension/SwiftRefactorExtension/SourceEditorCommand.swift index 724d85882a9..efcf32545c2 100644 --- a/EditorExtension/SwiftRefactorExtension/SourceEditorCommand.swift +++ b/EditorExtension/SwiftRefactorExtension/SourceEditorCommand.swift @@ -36,6 +36,7 @@ final class SourceEditorCommand: NSObject, XCSourceEditorCommand { init(provider: any RefactoringProvider.Type) { self.provider = provider + super.init(viewMode: .sourceAccurate) } override func visitAny(_ node: Syntax) -> Syntax? { diff --git a/Sources/SwiftBasicFormat/BasicFormat.swift b/Sources/SwiftBasicFormat/BasicFormat.swift index bf732490310..948edce47d3 100644 --- a/Sources/SwiftBasicFormat/BasicFormat.swift +++ b/Sources/SwiftBasicFormat/BasicFormat.swift @@ -12,6 +12,14 @@ import SwiftSyntax +/// A rewriter that performs a "basic" format of the passed tree. +/// +/// The base implementation is primarily aimed at adding whitespace where +/// required such that re-parsing the tree's description results in the same +/// tree. But it also makes an attempt at adding in formatting, eg. splitting +/// lines where obvious and some basic indentation at nesting levels. +/// +/// Any subclasses *must* return the same node type as given. open class BasicFormat: SyntaxRewriter { /// How much indentation should be added at a new indentation level. public let indentationWidth: Trivia @@ -35,8 +43,6 @@ open class BasicFormat: SyntaxRewriter { /// This is used as a reference-point to indent user-indented code. private var anchorPoints: [TokenSyntax: Trivia] = [:] - public let viewMode: SyntaxTreeViewMode - /// The previously visited token. This is faster than accessing /// `token.previousToken` inside `visit(_:TokenSyntax)`. `nil` if no token has /// been visited yet. @@ -49,7 +55,7 @@ open class BasicFormat: SyntaxRewriter { ) { self.indentationWidth = indentationWidth self.indentationStack = [(indentation: initialIndentation, isUserDefined: false)] - self.viewMode = viewMode + super.init(viewMode: viewMode) } // MARK: - Updating indentation level @@ -70,6 +76,12 @@ open class BasicFormat: SyntaxRewriter { indentationStack.removeLast() } + open override func visit(_ node: UnexpectedNodesSyntax) -> UnexpectedNodesSyntax { + // Do not perform any formatting on unexpected nodes, the result won't make any + // sense as we rely on layout nodes to know what formatting to perform. + return node + } + open override func visitPre(_ node: Syntax) { if requiresIndent(node) { if let firstToken = node.firstToken(viewMode: viewMode), diff --git a/Sources/SwiftBasicFormat/SyntaxProtocol+Formatted.swift b/Sources/SwiftBasicFormat/SyntaxProtocol+Formatted.swift index a03c80df46d..c44671e727f 100644 --- a/Sources/SwiftBasicFormat/SyntaxProtocol+Formatted.swift +++ b/Sources/SwiftBasicFormat/SyntaxProtocol+Formatted.swift @@ -3,6 +3,6 @@ import SwiftSyntax public extension SyntaxProtocol { /// Build a syntax node from this `Buildable` and format it with the given format. func formatted(using format: BasicFormat = BasicFormat()) -> Syntax { - return format.visit(Syntax(self)) + return format.rewrite(self) } } diff --git a/Sources/SwiftOperators/OperatorTable+Folding.swift b/Sources/SwiftOperators/OperatorTable+Folding.swift index d5f7e5db0d3..dea122e274f 100644 --- a/Sources/SwiftOperators/OperatorTable+Folding.swift +++ b/Sources/SwiftOperators/OperatorTable+Folding.swift @@ -475,6 +475,7 @@ extension OperatorTable { ) { self.opPrecedence = opPrecedence self.errorHandler = errorHandler + super.init(viewMode: .fixedUp) } override func visitAny(_ node: Syntax) -> Syntax? { @@ -538,7 +539,7 @@ extension OperatorTable { opPrecedence: self, errorHandler: errorHandler ) - let result = folder.visit(Syntax(node)) + let result = folder.rewrite(node) // If the sequence folder encountered an error that caused the error // handler to throw, invoke the error handler again with the original diff --git a/Sources/SwiftParserDiagnostics/DiagnosticExtensions.swift b/Sources/SwiftParserDiagnostics/DiagnosticExtensions.swift index fb622f7cd25..4b77951a710 100644 --- a/Sources/SwiftParserDiagnostics/DiagnosticExtensions.swift +++ b/Sources/SwiftParserDiagnostics/DiagnosticExtensions.swift @@ -78,7 +78,7 @@ extension FixIt.MultiNodeChange { guard let node = node else { return FixIt.MultiNodeChange(primitiveChanges: []) } - var changes = [FixIt.Change.replace(oldNode: Syntax(node), newNode: MissingMaker().visit(Syntax(node)))] + var changes = [FixIt.Change.replace(oldNode: Syntax(node), newNode: MissingMaker().rewrite(node))] if transferTrivia { changes += FixIt.MultiNodeChange.transferTriviaAtSides(from: [node]).primitiveChanges } @@ -123,7 +123,7 @@ extension FixIt.MultiNodeChange { leadingTrivia: Trivia? = nil, trailingTrivia: Trivia? = nil ) -> Self { - var presentNode = MissingNodesBasicFormatter(viewMode: .fixedUp).visit(Syntax(node)) + var presentNode = MissingNodesBasicFormatter(viewMode: .fixedUp).rewrite(node) presentNode = PresentMaker().rewrite(presentNode) if let leadingTrivia { diff --git a/Sources/SwiftParserDiagnostics/PresenceUtils.swift b/Sources/SwiftParserDiagnostics/PresenceUtils.swift index f52a24de5fb..fc9a3a1ca3c 100644 --- a/Sources/SwiftParserDiagnostics/PresenceUtils.swift +++ b/Sources/SwiftParserDiagnostics/PresenceUtils.swift @@ -45,6 +45,10 @@ extension SyntaxProtocol { /// Transforms a syntax tree by making all missing tokens present. class PresentMaker: SyntaxRewriter { + init() { + super.init(viewMode: .fixedUp) + } + override func visit(_ token: TokenSyntax) -> TokenSyntax { if token.isMissing { let presentToken: TokenSyntax @@ -62,7 +66,12 @@ class PresentMaker: SyntaxRewriter { } } +/// Transforms a syntax tree by making all present tokens missing. class MissingMaker: SyntaxRewriter { + init() { + super.init(viewMode: .sourceAccurate) + } + override func visit(_ node: TokenSyntax) -> TokenSyntax { guard node.isPresent else { return node diff --git a/Sources/SwiftRefactor/OpaqueParameterToGeneric.swift b/Sources/SwiftRefactor/OpaqueParameterToGeneric.swift index eaa522c94b7..eaf3f236519 100644 --- a/Sources/SwiftRefactor/OpaqueParameterToGeneric.swift +++ b/Sources/SwiftRefactor/OpaqueParameterToGeneric.swift @@ -125,7 +125,7 @@ public struct OpaqueParameterToGeneric: SyntaxRefactoringProvider { in params: ParameterClauseSyntax, augmenting genericParams: GenericParameterClauseSyntax? ) -> (ParameterClauseSyntax, GenericParameterClauseSyntax)? { - let rewriter = SomeParameterRewriter() + let rewriter = SomeParameterRewriter(viewMode: .sourceAccurate) let rewrittenParams = rewriter.visit(params.parameterList) if rewriter.rewrittenSomeParameters.isEmpty { diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index f7d7d908f00..27c33cf7a2b 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -22,7 +22,59 @@ //===----------------------------------------------------------------------===// open class SyntaxRewriter { - public init() { + public let viewMode: SyntaxTreeViewMode + + public init(viewMode: SyntaxTreeViewMode = .sourceAccurate) { + self.viewMode = viewMode + } + + /// Rewrite `node` and anchor, making sure that the rewritten node also has + /// a parent if `node` had one. + public func rewrite(_ node: some SyntaxProtocol) -> Syntax { + let rewritten = self.visit(node.data) + return withExtendedLifetime(rewritten) { + return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena())) + } + } + + /// Visit a ``TokenSyntax``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ token: TokenSyntax) -> TokenSyntax { + return token + } + + /// The function called before visiting the node and its descendents. + /// - node: the node we are about to visit. + open func visitPre(_ node: Syntax) { + } + + /// Override point to choose custom visitation dispatch instead of the + /// specialized `visit(_:)` methods. Use this instead of those methods if + /// you intend to dynamically dispatch rewriting behavior. + /// - note: If this method returns a non-nil result, the specialized + /// `visit(_:)` methods will not be called for this node and the + /// visited node will be replaced by the returned node in the + /// rewritten tree. + open func visitAny(_ node: Syntax) -> Syntax? { + return nil + } + + /// The function called after visiting the node and its descendents. + /// - node: the node we just finished visiting. + open func visitPost(_ node: Syntax) { + } + + /// Visit any Syntax node. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + @available(*, deprecated, renamed: "rewrite(_:)") + public func visit(_ node: Syntax) -> Syntax { + return visit(node.data) + } + + public func visit(_ node: T) -> T { + return visit(node.data).cast(T.self) } /// Visit a ``AccessesEffectSyntax``. @@ -1971,45 +2023,6 @@ open class SyntaxRewriter { return StmtSyntax(visitChildren(node)) } - /// Visit a ``TokenSyntax``. - /// - Parameter node: the node that is being visited - /// - Returns: the rewritten node - open func visit(_ token: TokenSyntax) -> TokenSyntax { - return token - } - - /// The function called before visiting the node and its descendents. - /// - node: the node we are about to visit. - open func visitPre(_ node: Syntax) { - } - - /// Override point to choose custom visitation dispatch instead of the - /// specialized `visit(_:)` methods. Use this instead of those methods if - /// you intend to dynamically dispatch rewriting behavior. - /// - note: If this method returns a non-nil result, the specialized - /// `visit(_:)` methods will not be called for this node and the - /// visited node will be replaced by the returned node in the - /// rewritten tree. - open func visitAny(_ node: Syntax) -> Syntax? { - return nil - } - - /// The function called after visiting the node and its descendents. - /// - node: the node we just finished visiting. - open func visitPost(_ node: Syntax) { - } - - /// Visit any Syntax node. - /// - Parameter node: the node that is being visited - /// - Returns: the rewritten node - public func visit(_ node: Syntax) -> Syntax { - return visit(node.data) - } - - public func visit(_ node: T) -> T { - return visit(Syntax(node)).cast(T.self) - } - /// Visit any DeclSyntax node. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -7131,11 +7144,13 @@ open class SyntaxRewriter { defer { childIndex += 1 } - guard let child = raw else { - // Node does not exist. If we are collecting rewritten nodes, we need to - // collect this one as well, otherwise we can ignore it. + + guard let child = raw, viewMode.shouldTraverse(node: child) else { + // Node does not exist or should not be visited. If we are collecting + // rewritten nodes, we need to collect this one as well, otherwise we + // can ignore it. if newLayout != nil { - newLayout!.append(nil) + newLayout!.append(raw) } continue } @@ -7191,13 +7206,4 @@ open class SyntaxRewriter { return node } } - - /// Rewrite `node` and anchor, making sure that the rewritten node also has - /// a parent if `node` had one. - public func rewrite(_ node: Syntax) -> Syntax { - let rewritten = self.visit(node) - return withExtendedLifetime(rewritten) { - return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena())) - } - } } diff --git a/Sources/SwiftSyntaxBuilder/Indenter.swift b/Sources/SwiftSyntaxBuilder/Indenter.swift index 48e62d77e4d..39aeca548d6 100644 --- a/Sources/SwiftSyntaxBuilder/Indenter.swift +++ b/Sources/SwiftSyntaxBuilder/Indenter.swift @@ -30,6 +30,7 @@ class Indenter: SyntaxRewriter { init(indentation: Trivia) { self.indentation = indentation + super.init(viewMode: .sourceAccurate) } /// Adds `indentation` after all newlines in the syntax tree. @@ -37,7 +38,7 @@ class Indenter: SyntaxRewriter { _ node: SyntaxType, indentation: Trivia ) -> SyntaxType { - return Indenter(indentation: indentation).visit(Syntax(node)).as(SyntaxType.self)! + return Indenter(indentation: indentation).rewrite(node).as(SyntaxType.self)! } public override func visit(_ token: TokenSyntax) -> TokenSyntax { diff --git a/Sources/SwiftSyntaxMacros/MacroReplacement.swift b/Sources/SwiftSyntaxMacros/MacroReplacement.swift index 760df8499c9..09a62b718d1 100644 --- a/Sources/SwiftSyntaxMacros/MacroReplacement.swift +++ b/Sources/SwiftSyntaxMacros/MacroReplacement.swift @@ -231,6 +231,7 @@ private final class MacroExpansionRewriter: SyntaxRewriter { init(parameterReplacements: [IdentifierExprSyntax: Int], arguments: [ExprSyntax]) { self.parameterReplacements = parameterReplacements self.arguments = arguments + super.init(viewMode: .sourceAccurate) } override func visit(_ node: IdentifierExprSyntax) -> ExprSyntax { diff --git a/Sources/SwiftSyntaxMacros/MacroSystem.swift b/Sources/SwiftSyntaxMacros/MacroSystem.swift index 032b527b341..5d88efc2fb8 100644 --- a/Sources/SwiftSyntaxMacros/MacroSystem.swift +++ b/Sources/SwiftSyntaxMacros/MacroSystem.swift @@ -74,6 +74,7 @@ class MacroApplication: SyntaxRewriter { ) { self.macroSystem = macroSystem self.context = context + super.init(viewMode: .sourceAccurate) } override func visitAny(_ node: Syntax) -> Syntax? { @@ -587,6 +588,6 @@ extension SyntaxProtocol { context: context ) - return applier.visit(Syntax(self)) + return applier.rewrite(self) } } diff --git a/Sources/_SwiftSyntaxTestSupport/SyntaxProtocol+Initializer.swift b/Sources/_SwiftSyntaxTestSupport/SyntaxProtocol+Initializer.swift index 16a8b436c65..984825aaf13 100644 --- a/Sources/_SwiftSyntaxTestSupport/SyntaxProtocol+Initializer.swift +++ b/Sources/_SwiftSyntaxTestSupport/SyntaxProtocol+Initializer.swift @@ -23,7 +23,7 @@ private class InitializerExprFormat: BasicFormat { private func formatChildrenSeparatedByNewline(children: SyntaxChildren, elementType: SyntaxType.Type) -> [SyntaxType] { increaseIndentationLevel() var formattedChildren = children.map { - self.visit($0).as(SyntaxType.self)! + self.rewrite($0.cast(SyntaxType.self)).cast(SyntaxType.self) } formattedChildren = formattedChildren.map { if $0.leadingTrivia.first?.isNewline == true { diff --git a/Sources/lit-test-helper/main.swift b/Sources/lit-test-helper/main.swift index be11396da91..f11a563dda0 100644 --- a/Sources/lit-test-helper/main.swift +++ b/Sources/lit-test-helper/main.swift @@ -257,7 +257,7 @@ func performClassifySyntax(args: CommandLineArguments) throws { let result = ClassifiedSyntaxTreePrinter.print(Syntax(tree)) do { // Sanity check that we get the same result if the tree has constructed nodes. - let ctorTree = TreeReconstructor().visit(tree) + let ctorTree = TreeReconstructor(viewMode: .sourceAccurate).visit(tree) let ctorResult = ClassifiedSyntaxTreePrinter.print(Syntax(ctorTree)) if ctorResult != result { throw TestingError.classificationVerificationFailed(result, ctorResult) diff --git a/Tests/PerformanceTest/VisitorPerformanceTests.swift b/Tests/PerformanceTest/VisitorPerformanceTests.swift index 6ec95aadce8..6eec84bff5c 100644 --- a/Tests/PerformanceTest/VisitorPerformanceTests.swift +++ b/Tests/PerformanceTest/VisitorPerformanceTests.swift @@ -48,7 +48,7 @@ public class VisitorPerformanceTests: XCTestCase { try { let parsed = Parser.parse(source: try String(contentsOf: inputFile)) - let emptyRewriter = EmptyRewriter() + let emptyRewriter = EmptyRewriter(viewMode: .sourceAccurate) measure { _ = emptyRewriter.visit(parsed) diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 6128eae4a20..72e98beb5bf 100644 --- a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift +++ b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift @@ -380,4 +380,17 @@ final class BasicFormatTest: XCTestCase { """ ) } + + func testUnexpectedIsNotFormatted() { + let expr: ExprSyntax = """ + let foo=1 + """ + + assertFormatted( + tree: expr, + expected: """ + let foo=1 + """ + ) + } } diff --git a/Tests/SwiftOperatorsTest/OperatorTableTests.swift b/Tests/SwiftOperatorsTest/OperatorTableTests.swift index 71f035aef66..e5f6acd6fbe 100644 --- a/Tests/SwiftOperatorsTest/OperatorTableTests.swift +++ b/Tests/SwiftOperatorsTest/OperatorTableTests.swift @@ -60,9 +60,9 @@ class ExplicitParenFolder: SyntaxRewriter { } return OperatorTable.makeBinaryOperationExpr( - lhs: visit(Syntax(leftOperand)).as(ExprSyntax.self)!, - op: visit(Syntax(middleExpr)).as(ExprSyntax.self)!, - rhs: visit(Syntax(rightOperand)).as(ExprSyntax.self)! + lhs: visit(leftOperand), + op: visit(middleExpr), + rhs: visit(rightOperand) ) } } @@ -86,7 +86,7 @@ extension OperatorTable { // Parse and "fold" the parenthesized version. let parenthesizedParsed = Parser.parse(source: fullyParenthesizedSource) - let parenthesizedSyntax = ExplicitParenFolder().visit(parenthesizedParsed) + let parenthesizedSyntax = ExplicitParenFolder(viewMode: .sourceAccurate).visit(parenthesizedParsed) XCTAssertFalse(parenthesizedSyntax.containsExprSequence) // Make sure the two have the same structure. diff --git a/Tests/SwiftParserTest/Assertions.swift b/Tests/SwiftParserTest/Assertions.swift index dcef165bbca..3d1b48de27f 100644 --- a/Tests/SwiftParserTest/Assertions.swift +++ b/Tests/SwiftParserTest/Assertions.swift @@ -284,6 +284,8 @@ class FixItApplier: SyntaxRewriter { return messages.contains($0.message.message) } .flatMap { $0.changes } + + super.init(viewMode: .all) } public override func visitAny(_ node: Syntax) -> Syntax? { @@ -317,7 +319,7 @@ class FixItApplier: SyntaxRewriter { /// If `messages` is not `nil`, applies only Fix-Its whose message is in `messages`. public static func applyFixes(in diagnostics: [Diagnostic], withMessages messages: [String]?, to tree: T) -> Syntax { let applier = FixItApplier(diagnostics: diagnostics, withMessages: messages) - return applier.visit(Syntax(tree)) + return applier.rewrite(tree) } } @@ -485,6 +487,8 @@ class TokenPresenceFlipper: SyntaxRewriter { init(flipTokenAtIndex: Int) { self.flipTokenAtIndex = flipTokenAtIndex + + super.init(viewMode: .all) } override func visit(_ token: TokenSyntax) -> TokenSyntax { @@ -743,8 +747,8 @@ func assertBasicFormat( line: UInt = #line ) { var parser = Parser(source) - let sourceTree = Syntax(parse(&parser)) - let withoutTrivia = TriviaRemover().visit(sourceTree) + let sourceTree = parse(&parser) + let withoutTrivia = TriviaRemover(viewMode: .sourceAccurate).rewrite(sourceTree) let formatted = withoutTrivia.formatted() var formattedParser = Parser(formatted.description) diff --git a/Tests/SwiftSyntaxBuilderTest/StringInterpolationTests.swift b/Tests/SwiftSyntaxBuilderTest/StringInterpolationTests.swift index 520fd6fcde4..9640125ea7b 100644 --- a/Tests/SwiftSyntaxBuilderTest/StringInterpolationTests.swift +++ b/Tests/SwiftSyntaxBuilderTest/StringInterpolationTests.swift @@ -235,7 +235,7 @@ final class StringInterpolationTests: XCTestCase { return DeclSyntax(newFunc) } } - let rewrittenSourceFile = Rewriter().visit(sourceFile) + let rewrittenSourceFile = Rewriter(viewMode: .sourceAccurate).visit(sourceFile) XCTAssertEqual( rewrittenSourceFile.description, """ diff --git a/Tests/SwiftSyntaxTest/AbsolutePositionTests.swift b/Tests/SwiftSyntaxTest/AbsolutePositionTests.swift index 4b3a12a3742..8c06731e863 100644 --- a/Tests/SwiftSyntaxTest/AbsolutePositionTests.swift +++ b/Tests/SwiftSyntaxTest/AbsolutePositionTests.swift @@ -14,14 +14,6 @@ import _SwiftSyntaxTestSupport import SwiftSyntax import XCTest -fileprivate class FuncRenamer: SyntaxRewriter { - override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax { - let rewritten = super.visit(node).as(FunctionDeclSyntax.self)! - let modifiedFunctionDecl = rewritten.with(\.identifier, .identifier("anotherName")) - return DeclSyntax(modifiedFunctionDecl) - } -} - public class AbsolutePositionTests: XCTestCase { public func testRecursion() { var l = [CodeBlockItemSyntax]() diff --git a/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift b/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift index 9dff638264c..814f634223d 100644 --- a/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift +++ b/Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift @@ -158,7 +158,7 @@ public class SyntaxVisitorTests: XCTestCase { let closure = ClosureExprSyntax( statements: CodeBlockItemListSyntax([]) ) - let rewriter = ClosureRewriter() + let rewriter = ClosureRewriter(viewMode: .sourceAccurate) let rewritten = rewriter.visit(closure) XCTAssertEqual(closure.description, rewritten.description) } @@ -168,6 +168,7 @@ public class SyntaxVisitorTests: XCTestCase { let transform: (TokenSyntax) -> TokenSyntax init(transform: @escaping (TokenSyntax) -> TokenSyntax) { self.transform = transform + super.init(viewMode: .sourceAccurate) } override func visitAny(_ node: Syntax) -> Syntax? { if let tok = node.as(TokenSyntax.self) { @@ -235,7 +236,7 @@ public class SyntaxVisitorTests: XCTestCase { ]) ) XCTAssertEqual(source.description, "let a = 5") - let visitor = TriviaRemover() + let visitor = TriviaRemover(viewMode: .sourceAccurate) let rewritten = visitor.visit(source) XCTAssertEqual(rewritten.description, "leta=5") } diff --git a/Tests/SwiftSyntaxTest/VisitorTests.swift b/Tests/SwiftSyntaxTest/VisitorTests.swift index e602ca964ab..12e333e8d6d 100644 --- a/Tests/SwiftSyntaxTest/VisitorTests.swift +++ b/Tests/SwiftSyntaxTest/VisitorTests.swift @@ -144,8 +144,8 @@ public class VisitorTests: XCTestCase { } static func print(_ tree: Tree, viewMode: SyntaxTreeViewMode) -> String { - let printer = TreePrinter(viewMode: viewMode) - printer.walk(tree) + let printer = RewritingTreePrinter(viewMode: viewMode) + _ = printer.rewrite(Syntax(tree)) return printer.out } }