Skip to content
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
7 changes: 7 additions & 0 deletions Sources/SwiftSyntax/SyntaxBaseNodes.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,20 @@ public extension Syntax {
public struct ${node.name}: ${node.name}Protocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a `${node.name}` node from a specialized syntax node.
public init<S: ${node.name}Protocol>(_ syntax: S) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self.init(syntax._syntaxNode.data)
}

/// Create a `${node.name}` node from a specialized optional syntax node.
public init?<S: ${node.name}Protocol>(_ syntax: S?) {
guard let syntax = syntax else { return nil }
self.init(syntax)
}

/// Converts the given `Syntax` node to a `${node.name}` if possible. Returns
/// `nil` if the conversion is not possible.
public init?(_ syntax: Syntax) {
Expand Down
8 changes: 5 additions & 3 deletions Sources/SwiftSyntax/SyntaxData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ struct AbsoluteRawSyntax {
return nil
}

func replacingSelf(_ newRaw: RawSyntax) -> AbsoluteRawSyntax {
return .init(raw: newRaw, info: info)
func replacingSelf(_ newRaw: RawSyntax, newRootId: UInt32) -> AbsoluteRawSyntax {
let nodeId = SyntaxIdentifier(rootId: newRootId, indexInTree: info.nodeId.indexInTree)
let newInfo = AbsoluteSyntaxInfo(position: info.position, nodeId: nodeId)
return .init(raw: newRaw, info: newInfo)
}

static func forRoot(_ raw: RawSyntax) -> AbsoluteRawSyntax {
Expand Down Expand Up @@ -334,7 +336,7 @@ struct SyntaxData {
if let parent = parent {
let parentData = parent.data.replacingChild(newRaw, at: indexInParent)
let newParent = Syntax(parentData)
return SyntaxData(absoluteRaw.replacingSelf(newRaw), parent: newParent)
return SyntaxData(absoluteRaw.replacingSelf(newRaw, newRootId: parentData.nodeId.rootId), parent: newParent)
} else {
// Otherwise, we're already the root, so return the new root data.
return .forRoot(newRaw)
Expand Down
35 changes: 35 additions & 0 deletions Sources/SwiftSyntax/gyb_generated/SyntaxBaseNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ public extension Syntax {
public struct DeclSyntax: DeclSyntaxProtocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a `DeclSyntax` node from a specialized syntax node.
public init<S: DeclSyntaxProtocol>(_ syntax: S) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self.init(syntax._syntaxNode.data)
}

/// Create a `DeclSyntax` node from a specialized optional syntax node.
public init?<S: DeclSyntaxProtocol>(_ syntax: S?) {
guard let syntax = syntax else { return nil }
self.init(syntax)
}

/// Converts the given `Syntax` node to a `DeclSyntax` if possible. Returns
/// `nil` if the conversion is not possible.
public init?(_ syntax: Syntax) {
Expand Down Expand Up @@ -135,13 +142,20 @@ public extension Syntax {
public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a `ExprSyntax` node from a specialized syntax node.
public init<S: ExprSyntaxProtocol>(_ syntax: S) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self.init(syntax._syntaxNode.data)
}

/// Create a `ExprSyntax` node from a specialized optional syntax node.
public init?<S: ExprSyntaxProtocol>(_ syntax: S?) {
guard let syntax = syntax else { return nil }
self.init(syntax)
}

/// Converts the given `Syntax` node to a `ExprSyntax` if possible. Returns
/// `nil` if the conversion is not possible.
public init?(_ syntax: Syntax) {
Expand Down Expand Up @@ -232,13 +246,20 @@ public extension Syntax {
public struct StmtSyntax: StmtSyntaxProtocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a `StmtSyntax` node from a specialized syntax node.
public init<S: StmtSyntaxProtocol>(_ syntax: S) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self.init(syntax._syntaxNode.data)
}

/// Create a `StmtSyntax` node from a specialized optional syntax node.
public init?<S: StmtSyntaxProtocol>(_ syntax: S?) {
guard let syntax = syntax else { return nil }
self.init(syntax)
}

/// Converts the given `Syntax` node to a `StmtSyntax` if possible. Returns
/// `nil` if the conversion is not possible.
public init?(_ syntax: Syntax) {
Expand Down Expand Up @@ -329,13 +350,20 @@ public extension Syntax {
public struct TypeSyntax: TypeSyntaxProtocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a `TypeSyntax` node from a specialized syntax node.
public init<S: TypeSyntaxProtocol>(_ syntax: S) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self.init(syntax._syntaxNode.data)
}

/// Create a `TypeSyntax` node from a specialized optional syntax node.
public init?<S: TypeSyntaxProtocol>(_ syntax: S?) {
guard let syntax = syntax else { return nil }
self.init(syntax)
}

/// Converts the given `Syntax` node to a `TypeSyntax` if possible. Returns
/// `nil` if the conversion is not possible.
public init?(_ syntax: Syntax) {
Expand Down Expand Up @@ -426,13 +454,20 @@ public extension Syntax {
public struct PatternSyntax: PatternSyntaxProtocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a `PatternSyntax` node from a specialized syntax node.
public init<S: PatternSyntaxProtocol>(_ syntax: S) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self.init(syntax._syntaxNode.data)
}

/// Create a `PatternSyntax` node from a specialized optional syntax node.
public init?<S: PatternSyntaxProtocol>(_ syntax: S?) {
guard let syntax = syntax else { return nil }
self.init(syntax)
}

/// Converts the given `Syntax` node to a `PatternSyntax` if possible. Returns
/// `nil` if the conversion is not possible.
public init?(_ syntax: Syntax) {
Expand Down
3 changes: 3 additions & 0 deletions Tests/SwiftSyntaxTest/SyntaxTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,8 @@ public class SyntaxTests: XCTestCase {
case .integerLiteralExpr: break
default: XCTFail("failed to convert to SyntaxEnum")
}

XCTAssertNil(ExprSyntax(nil as IntegerLiteralExprSyntax?))
XCTAssertEqual(ExprSyntax(integerExpr).as(IntegerLiteralExprSyntax.self)!, integerExpr)
}
}
15 changes: 15 additions & 0 deletions Tests/SwiftSyntaxTest/SyntaxVisitorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,19 @@ public class SyntaxVisitorTests: XCTestCase {
XCTAssertEqual(hashBefore, parsed.hashValue)
}())
}

public func testRewriteTrivia() {
class TriviaRemover: SyntaxRewriter {
override func visit(_ token: TokenSyntax) -> Syntax {
return Syntax(token.withTrailingTrivia(.zero))
}
}

XCTAssertNoThrow(try {
let parsed = try SyntaxParser.parse(source: "let a = 5")
let visitor = TriviaRemover()
let rewritten = visitor.visit(parsed)
XCTAssertEqual(rewritten.description, "leta=5")
}())
}
}