Skip to content

Commit ec7f015

Browse files
authored
Merge pull request #684 from rintaro/syntaxnode-remove
Eliminate `SyntaxNode`
2 parents fceb672 + c8ae3de commit ec7f015

File tree

6 files changed

+33
-1745
lines changed

6 files changed

+33
-1745
lines changed

Sources/SwiftSyntax/IncrementalParseTransition.swift

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ public protocol IncrementalParseReusedNodeDelegate {
2525
/// - range: The source region of the currently parsed source.
2626
/// - previousNode: The node from the previous tree that is associated with
2727
/// the skipped source region.
28-
func parserReusedNode(range: ByteSourceRange, previousNode: SyntaxNode)
28+
func parserReusedNode(range: ByteSourceRange, previousNode: Syntax)
2929
}
3030

3131
/// An implementation of `IncrementalParseReusedNodeDelegate` that just collects
3232
/// the range and re-used node into an array.
3333
public final class IncrementalParseReusedNodeCollector:
3434
IncrementalParseReusedNodeDelegate {
35-
public var rangeAndNodes: [(ByteSourceRange, SyntaxNode)] = []
35+
public var rangeAndNodes: [(ByteSourceRange, Syntax)] = []
3636

3737
public init() {}
3838

39-
public func parserReusedNode(range: ByteSourceRange, previousNode: SyntaxNode) {
39+
public func parserReusedNode(range: ByteSourceRange, previousNode: Syntax) {
4040
rangeAndNodes.append((range, previousNode))
4141
}
4242
}
@@ -226,7 +226,7 @@ public struct IncrementalParseLookup {
226226

227227
public init(transition: IncrementalParseTransition) {
228228
self.transition = transition
229-
self.cursor = .init(root: transition.previousTree.data.absoluteRaw)
229+
self.cursor = .init(root: transition.previousTree.data)
230230
}
231231

232232
fileprivate var edits: ConcurrentEdits {
@@ -246,11 +246,11 @@ public struct IncrementalParseLookup {
246246
/// - Parameters:
247247
/// - offset: The byte offset of the source string that is currently parsed.
248248
/// - kind: The `CSyntaxKind` that the parser expects at this position.
249-
/// - Returns: A `SyntaxNode` node from the previous parse invocation,
249+
/// - Returns: A `Syntax` node from the previous parse invocation,
250250
/// representing the contents of this region, if it is still valid
251251
/// to re-use. `nil` otherwise.
252252
@_spi(RawSyntax)
253-
public mutating func lookUp(_ newOffset: Int, kind: SyntaxKind) -> SyntaxNode? {
253+
public mutating func lookUp(_ newOffset: Int, kind: SyntaxKind) -> Syntax? {
254254
guard let prevOffset = translateToPreEditOffset(newOffset) else {
255255
return nil
256256
}
@@ -266,7 +266,7 @@ public struct IncrementalParseLookup {
266266

267267
mutating fileprivate func cursorLookup(
268268
prevPosition: AbsolutePosition, kind: SyntaxKind
269-
) -> SyntaxNode? {
269+
) -> Syntax? {
270270
guard !cursor.finished else { return nil }
271271

272272
while true {
@@ -348,60 +348,52 @@ public struct IncrementalParseLookup {
348348
/// Functions as an iterator that walks the tree looking for nodes with a
349349
/// certain position.
350350
fileprivate struct SyntaxCursor {
351-
var parents: [AbsoluteRawSyntax]
352-
var node: AbsoluteRawSyntax
351+
var node: SyntaxData
353352
var finished: Bool
354353
let viewMode = SyntaxTreeViewMode.sourceAccurate
355354

356-
init(root: AbsoluteRawSyntax) {
355+
init(root: SyntaxData) {
357356
self.node = root
358-
self.parents = []
359357
self.finished = false
360358
}
361359

362-
var asSyntaxNode: SyntaxNode {
363-
return SyntaxNode(node: node, parents: ArraySlice(parents))
360+
var asSyntaxNode: Syntax {
361+
return Syntax(node)
364362
}
365363

366364
/// Returns the next sibling node or the parent's sibling node if this is
367365
/// the last child. The cursor state is unmodified.
368-
/// - Returns: False if it run out of nodes to walk to.
369-
var nextSibling: AbsoluteRawSyntax? {
370-
var parents = ArraySlice(self.parents)
366+
/// - Returns: `nil` if it run out of nodes to walk to.
367+
var nextSibling: SyntaxData? {
371368
var node = self.node
372-
while !parents.isEmpty {
373-
if let sibling = node.nextSibling(parent: parents.last!, viewMode: viewMode) {
374-
return sibling
369+
while let parent = node.parent {
370+
if let sibling = node.absoluteRaw.nextSibling(parent: parent.absoluteRaw, viewMode: viewMode) {
371+
return SyntaxData(sibling, parent: Syntax(parent))
375372
}
376-
node = parents.removeLast()
373+
node = parent
377374
}
378-
379375
return nil
380376
}
381377

382378
/// Moves to the first child of the current node.
383379
/// - Returns: False if the node has no children.
384380
mutating func advanceToFirstChild() -> Bool {
385-
guard let child = node.firstChild(viewMode: viewMode) else { return false }
386-
parents.append(node)
387-
node = child
381+
guard let child = node.absoluteRaw.firstChild(viewMode: viewMode) else { return false }
382+
node = SyntaxData(child, parent: Syntax(node))
388383
return true
389384
}
390385

391386
/// Moves to the next sibling node or the parent's sibling node if this is
392387
/// the last child.
393388
/// - Returns: False if it run out of nodes to walk to.
394389
mutating func advanceToNextSibling() -> Bool {
395-
while !parents.isEmpty {
396-
if let sibling = node.nextSibling(parent: parents.last!, viewMode: viewMode) {
397-
node = sibling
398-
return true
399-
}
400-
node = parents.removeLast()
390+
guard let next = nextSibling else {
391+
finished = true
392+
return false
401393
}
402394

403-
finished = true
404-
return false
395+
self.node = next
396+
return true
405397
}
406398

407399
/// Moves to the next node in the tree with the provided `position`.

Sources/SwiftSyntax/Misc.swift.gyb

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
NODE_MAP = create_node_map()
66
# Ignore the following admonition it applies to the resulting .swift file only
77
}%
8-
//// Automatically Generated From SyntaxNodes.swift.gyb.
8+
//// Automatically Generated From Misc.swift.gyb.
99
//// Do Not Edit Directly!
1010
//===---------- Misc.swift - Miscelaneous SwiftSyntax definitions ---------===//
1111
//
@@ -19,24 +19,6 @@
1919
//
2020
//===----------------------------------------------------------------------===//
2121

22-
extension SyntaxNode {
23-
public var isUnknown: Bool { return raw.kind.isUnknown }
24-
public var asUnknown: UnknownSyntax? {
25-
guard isUnknown else { return nil }
26-
return UnknownSyntax(asSyntaxData)
27-
}
28-
% for node in SYNTAX_NODES:
29-
% if not node.is_base():
30-
31-
public var is${node.syntax_kind}: Bool { return raw.kind == .${node.swift_syntax_kind} }
32-
public var as${node.syntax_kind}: ${node.name}? {
33-
guard is${node.syntax_kind} else { return nil }
34-
return ${node.name}(asSyntaxData)
35-
}
36-
% end
37-
% end
38-
}
39-
4022
extension Syntax {
4123
/// Syntax nodes always conform to SyntaxProtocol. This API is just added
4224
/// for consistency.

Sources/SwiftSyntax/Syntax.swift

Lines changed: 3 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -655,109 +655,6 @@ extension ReversedTokenSequence: CustomReflectable {
655655
}
656656
}
657657

658-
/// Represents a node from the syntax tree.
659-
///
660-
/// This is a more efficient representation than `Syntax` because it avoids casts
661-
/// to `Syntax` for representing the parent hierarchy.
662-
/// It provides generic information, like the node's position, range, and
663-
/// a unique `id`, while still allowing getting the associated `Syntax`
664-
/// object if necessary.
665-
///
666-
/// `SyntaxParser` uses `SyntaxNode` to efficiently report which syntax nodes
667-
/// got re-used during incremental re-parsing.
668-
public struct SyntaxNode {
669-
let absoluteRaw: AbsoluteRawSyntax
670-
let parents: ArraySlice<AbsoluteRawSyntax>
671-
672-
internal init(node: AbsoluteRawSyntax, parents: ArraySlice<AbsoluteRawSyntax>) {
673-
self.absoluteRaw = node
674-
self.parents = parents
675-
}
676-
677-
var raw: RawSyntax {
678-
return absoluteRaw.raw
679-
}
680-
681-
@_spi(RawSyntax)
682-
public func withUnsafeRawSyntax<R>(_ body: (RawSyntax) throws -> R) rethrows -> R {
683-
return try body(raw)
684-
}
685-
686-
/// Converts this node to a `SyntaxData` object.
687-
///
688-
/// This operation results in wrapping all of the node's parents into
689-
/// `SyntaxData` objects. There's a cost associated with it that should be
690-
/// taken into account before used inside performance critical code.
691-
internal var asSyntaxData: SyntaxData {
692-
if let parent = parent {
693-
return SyntaxData(absoluteRaw, parent: parent.asSyntax)
694-
} else {
695-
return SyntaxData.forRoot(absoluteRaw.raw)
696-
}
697-
}
698-
699-
/// Converts this node to a `Syntax` object.
700-
///
701-
/// This operation results in wrapping this node and all of its parents into
702-
/// `Syntax` objects. There's a cost associated with it that should be taken
703-
/// into account before used inside performance critical code.
704-
public var asSyntax: Syntax {
705-
return Syntax(self.asSyntaxData)
706-
}
707-
708-
/// The parent of this syntax node, or `nil` if this node is the root.
709-
public var parent: SyntaxNode? {
710-
guard !parents.isEmpty else { return nil }
711-
return SyntaxNode(node: parents.last!, parents: parents.dropLast())
712-
}
713-
714-
/// The absolute position of the starting point of this node.
715-
public var position: AbsolutePosition {
716-
return absoluteRaw.position
717-
}
718-
719-
/// The end position of this node, including its trivia.
720-
public var endPosition: AbsolutePosition {
721-
return absoluteRaw.endPosition
722-
}
723-
724-
/// The textual byte length of this node including leading and trailing trivia.
725-
public var byteSize: Int {
726-
return totalLength.utf8Length
727-
}
728-
729-
/// The byte source range of this node including leading and trailing trivia.
730-
public var byteRange: ByteSourceRange {
731-
return ByteSourceRange(offset: position.utf8Offset, length: byteSize)
732-
}
733-
734-
/// The length of this node including all of its trivia.
735-
public var totalLength: SourceLength {
736-
return raw.totalLength
737-
}
738-
}
739-
740-
extension SyntaxNode: Identifiable {
741-
/// Returns a value representing the unique identity of the node.
742-
public var id: SyntaxIdentifier {
743-
return absoluteRaw.info.nodeId
744-
}
745-
}
746-
747-
extension SyntaxNode: CustomStringConvertible, TextOutputStreamable {
748-
/// A source-accurate description of this node.
749-
public var description: String {
750-
return raw.description
751-
}
752-
753-
/// Prints the raw value of this node to the provided stream.
754-
/// - Parameter stream: The stream to which to print the raw tree.
755-
public func write<Target>(to target: inout Target)
756-
where Target: TextOutputStream {
757-
raw.write(to: &target)
758-
}
759-
}
760-
761658
/// Expose `recursiveDescription` on raw nodes for debugging purposes.
762659
extension RawSyntaxNodeProtocol {
763660
/// Print this raw syntax node including all of its children.
@@ -766,3 +663,6 @@ extension RawSyntaxNodeProtocol {
766663
return Syntax(raw: raw).recursiveDescription
767664
}
768665
}
666+
667+
@available(*, unavailable, message: "use 'Syntax' instead")
668+
public struct SyntaxNode {}

0 commit comments

Comments
 (0)