Skip to content

Commit

Permalink
Merge pull request swiftlang#35 from nkcsgexi/enum-visit
Browse files Browse the repository at this point in the history
Using enum case instead of boolean value to indicate how SyntaxVisitor should continue.
  • Loading branch information
nkcsgexi authored Nov 14, 2018
2 parents 63034c2 + 98c080c commit d62ad83
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Sources/SwiftSyntax/RawSyntax.swift
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ extension RawSyntax {
if shouldVisit {
// Visit this node realizes a syntax node.
visitor.visitPre()
visitChildren = visitor.visit()
visitChildren = visitor.visit() == .visitChildren
}
if visitChildren {
for (offset, element) in layout.enumerated() {
Expand Down
11 changes: 6 additions & 5 deletions Sources/SwiftSyntax/SyntaxClassifier.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fileprivate class _SyntaxClassifier: SyntaxVisitor {
}
}

override func visit(_ token: TokenSyntax) {
override func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
assert(token.isPresent)
// FIXME: We need to come up with some way in which the SyntaxClassifier can
// classify trivia (i.e. comments). In particular we need to be able to
Expand All @@ -91,16 +91,17 @@ fileprivate class _SyntaxClassifier: SyntaxVisitor {
assert(classifications[token] == nil,
"\(token) has already been classified")
classifications[token] = classification
return .skipChildren
}

% for node in SYNTAX_NODES:
% if is_visitable(node):
override func visit(_ node: ${node.name}) -> Bool {
override func visit(_ node: ${node.name}) -> SyntaxVisitorContinueKind {
if skipNodeIds.contains(node.raw.id) {
return false
return .skipChildren
}
% if node.is_unknown() or node.is_syntax_collection():
return true
return .visitChildren
% else:
% for child in node.children:
% if child.is_optional:
Expand All @@ -123,7 +124,7 @@ fileprivate class _SyntaxClassifier: SyntaxVisitor {
% end
% end
% end
return false
return .skipChildren
% end
}
% end
Expand Down
52 changes: 32 additions & 20 deletions Sources/SwiftSyntax/SyntaxRewriter.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,35 @@ open class SyntaxRewriter {
}
}

/// The enum describes how the SyntaxVistor should continue after visiting
/// the current node.
public enum SyntaxVisitorContinueKind {

/// The visitor should visit the descendents of the current node.
case visitChildren

/// The visitor should avoid visiting the descendents of the current node.
case skipChildren
}

open class SyntaxVisitor {
public init() {}
% for node in SYNTAX_NODES:
% if is_visitable(node):
/// Visting ${node.name} specifically.
/// - Parameter node: the node we are visiting.
/// - Returns: whether we should visit the descendents of node.
open func visit(_ node: ${node.name}) -> Bool {
return true
/// - Returns: how should we continue visiting.
open func visit(_ node: ${node.name}) -> SyntaxVisitorContinueKind {
return .visitChildren
}
% end
% end

/// Visting UnknownSyntax specifically.
/// - Parameter node: the node we are visiting.
/// - Returns: whether we should visit the descendents of node.
open func visit(_ node: UnknownSyntax) -> Bool {
return true
/// - Returns: how should we continue visiting.
open func visit(_ node: UnknownSyntax) -> SyntaxVisitorContinueKind {
return .visitChildren
}

/// Whether we should ever visit a given syntax kind.
Expand All @@ -128,7 +139,9 @@ open class SyntaxVisitor {
return true
}

open func visit(_ token: TokenSyntax) {}
open func visit(_ token: TokenSyntax) -> SyntaxVisitorContinueKind {
return .skipChildren
}

/// The function called before visiting the node and its descendents.
/// - node: the node we are about to visit.
Expand All @@ -138,18 +151,17 @@ open class SyntaxVisitor {
/// - node: the node we just finished visiting.
open func visitPost(_ node: Syntax) {}

public func visit(_ node: Syntax) -> Bool {
public func visit(_ node: Syntax) -> SyntaxVisitorContinueKind {
switch node.raw.kind {
case .token: visit(node as! TokenSyntax)
case .token: return visit(node as! TokenSyntax)
% for node in SYNTAX_NODES:
% if is_visitable(node):
case .${node.swift_syntax_kind}: return visit(node as! ${node.name})
% end
% end
case .unknown: return visit(node as! UnknownSyntax)
default: break
default: return .skipChildren
}
return false
}
}

Expand All @@ -158,7 +170,7 @@ open class SyntaxVisitor {
/// otherwise the node is represented as a child index list from a realized
/// ancestor.
class PendingSyntaxNode {
let parent: PendingSyntaxNode?
let parent: PendingSyntaxNode!
private var kind: PendingSyntaxNodeKind

private enum PendingSyntaxNodeKind {
Expand All @@ -174,7 +186,7 @@ class PendingSyntaxNode {
case .realized(let node):
return node
case .virtual(let index):
let _node = parent!.node.child(at: index)!
let _node = parent.node.child(at: index)!
kind = .realized(node: _node)
return _node
}
Expand All @@ -199,7 +211,7 @@ class PendingSyntaxNode {
/// not interesting to users' SyntaxVisitor.
class RawSyntaxVisitor {
private let visitor: SyntaxVisitor
private var currentNode: PendingSyntaxNode?
private var currentNode: PendingSyntaxNode!

required init(_ visitor: SyntaxVisitor, _ root: Syntax) {
self.visitor = visitor
Expand All @@ -215,25 +227,25 @@ class RawSyntaxVisitor {
}

func addChildIdx(_ idx: Int) {
currentNode = PendingSyntaxNode(currentNode!, idx)
currentNode = PendingSyntaxNode(currentNode, idx)
}

func moveUp() {
currentNode = currentNode!.parent
currentNode = currentNode.parent
}

func visitPre() {
visitor.visitPre(currentNode!.node)
visitor.visitPre(currentNode.node)
}

func visitPost() {
visitor.visitPost(currentNode!.node)
visitor.visitPost(currentNode.node)
}

// The current raw syntax node is interesting for the user, so realize a
// correponding syntax node and feed it into the visitor.
func visit() -> Bool {
return visitor.visit(currentNode!.node)
func visit() -> SyntaxVisitorContinueKind {
return visitor.visit(currentNode.node)
}
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/lit-test-helper/ClassifiedSyntaxTreePrinter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,12 @@ class ClassifiedSyntaxTreePrinter: SyntaxVisitor {
}
}

override func visit(_ node: TokenSyntax) {
override func visit(_ node: TokenSyntax) -> SyntaxVisitorContinueKind {
visit(node.leadingTrivia)
let classification = classifications[node] ?? SyntaxClassification.none
recordCurrentClassification(classification)
result += node.text
visit(node.trailingTrivia)
return .skipChildren
}
}
3 changes: 2 additions & 1 deletion Tests/SwiftSyntaxTest/AbsolutePosition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ public class AbsolutePositionTestCase: XCTestCase {
_ = node.byteSize
_ = node.positionAfterSkippingLeadingTrivia
}
override func visit(_ node: TokenSyntax) {
override func visit(_ node: TokenSyntax) -> SyntaxVisitorContinueKind {
XCTAssertEqual(node.positionAfterSkippingLeadingTrivia.utf8Offset,
node.position.utf8Offset + node.leadingTrivia.byteSize)
return .skipChildren
}
}
parsed.walk(Visitor())
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftSyntaxTest/DiagnosticTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ public class DiagnosticTestCase: XCTestCase {
self.url = url
self.engine = engine
}
override func visit(_ function: FunctionDeclSyntax) -> Bool {
override func visit(_ function: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
let startLoc = function.identifier.startLocation(in: url)
let endLoc = function.endLocation(in: url)
engine.diagnose(.badFunction(function.identifier), location: startLoc) {
$0.highlight(function.identifier.sourceRange(in: self.url))
}
engine.diagnose(.endOfFunction(function.identifier), location: endLoc)
return true
return .visitChildren
}
}

Expand Down
8 changes: 4 additions & 4 deletions Tests/SwiftSyntaxTest/VisitorTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public class SyntaxVisitorTestCase: XCTestCase {
public func testBasic() {
class FuncCounter: SyntaxVisitor {
var funcCount = 0
override func visit(_ node: FunctionDeclSyntax) -> Bool {
override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
funcCount += 1
return true
return .visitChildren
}
}
XCTAssertNoThrow(try {
Expand Down Expand Up @@ -70,9 +70,9 @@ public class SyntaxVisitorTestCase: XCTestCase {
class VisitCollections: SyntaxVisitor {
var numberOfCodeBlockItems = 0

override func visit(_ items: CodeBlockItemListSyntax) -> Bool {
override func visit(_ items: CodeBlockItemListSyntax) -> SyntaxVisitorContinueKind {
numberOfCodeBlockItems += items.count
return true
return .visitChildren
}
}

Expand Down

0 comments on commit d62ad83

Please sign in to comment.