SwiftSyntax “as” Conversions

I’m using SwiftSyntax 0.50200.0, and I cannot seem to find a way to coax a WithTrailingCommaSyntax existential back into a Syntax instance.

class Rewriter: SyntaxRewriter {
  override func visitAny(_ node: Syntax) -> Syntax? {
    if let entry = node.asProtocol(WithTrailingCommaSyntax.self),
      entry.trailingComma != nil,
      entry.indexInParent == entry.parent?.children.last?.indexInParent {
        let modified = entry.withTrailingComma(nil)
        return Syntax(modified) // Error: “Value of protocol type 'WithTrailingCommaSyntax' cannot conform to 'SyntaxProtocol'; only struct/enum/class types can conform to protocols”
    } else {
        return node
    }
  }
}

I discovered return modified._syntaxNode works, but that’s an underscored API and its documentation says not to use it, but instead to do what doesn’t work above.

What’s the right way to do this?

@ahoppen

Whoops, it looks like we are just missing an initialiser to construct a Syntax node from a SyntaxProtocol (and inherited protocols). Thanks for reporting this.

Adding the following initialiser to SwiftSyntax should fix the issue.

extension Syntax {
  public init(fromProtocol syntax: SyntaxProtocol) {
    self = syntax._syntaxNode
  }
}

I have opened swift-syntax#223 that adds the above initialiser. For now, feel free to copy and paste the above code snippet into your own code. That should work around the issue until the PR is merged and the code ends up in a nightly or release tag of SwiftSyntax at which point you can remove it again.

2 Likes

Thanks for fixing it so quickly.