Skip to content

[SwiftSyntax] Add SyntaxRewriter.visitAny(_:) #15212

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test/SwiftSyntax/Inputs/near-empty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
n
24 changes: 24 additions & 0 deletions test/SwiftSyntax/VisitorTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,28 @@ VisitorTests.test("RewritingNodeWithEmptyChild") {
})
}

VisitorTests.test("SyntaxRewriter.visitAny") {
class VisitAnyRewriter: SyntaxRewriter {
let transform: (TokenSyntax) -> TokenSyntax
init(transform: @escaping (TokenSyntax) -> TokenSyntax) {
self.transform = transform
}
override func visitAny(_ node: Syntax) -> Syntax? {
if let tok = node as? TokenSyntax {
return transform(tok)
}
return nil
}
}
expectDoesNotThrow({
let parsed = try SourceFileSyntax.decodeSourceFileSyntax(try
SwiftLang.parse(getInput("near-empty.swift")))
let rewriter = VisitAnyRewriter(transform: { _ in
return SyntaxFactory.makeIdentifier("")
})
let rewritten = rewriter.visit(parsed)
expectEqual(rewritten.description, "")
})
}

runAllTests()
15 changes: 15 additions & 0 deletions tools/SwiftSyntax/SyntaxRewriter.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,28 @@ open class SyntaxRewriter {
/// - 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.
open func visitAny(_ node: Syntax) -> Syntax? {
return nil
}

/// The function called after visting the node and its descendents.
/// - node: the node we just finished visiting.
open func visitPost(_ node: Syntax) {}

public func visit(_ node: Syntax) -> Syntax {
visitPre(node)
defer { visitPost(node) }

// If the global visitor returned non-nil, skip specialized dispatch.
if let newNode = visitAny(node) {
return newNode
}

switch node.raw.kind {
case .token: return visit(node as! TokenSyntax)
% for node in SYNTAX_NODES:
Expand Down