Skip to content

Commit

Permalink
Merge pull request swiftlang#2265 from bnbarham/cast-sometimes-fails
Browse files Browse the repository at this point in the history
Casts to children of `SyntaxProtocol` are not always invalid
  • Loading branch information
bnbarham authored Oct 25, 2023
2 parents 48c2705 + 12993b0 commit bcd4772
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
/// Force-casts the current syntax node to a given specialized syntax type.
///
/// - Returns: An instance of the specialized type.
///
/// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast.
public func cast<S: \#(node.kind.protocolType)>(_ syntaxType: S.Type) -> S {
return self.as(S.self)!
Expand All @@ -79,9 +80,6 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
/// Checks if the current syntax node can be upcast to its base node type (``\#(node.kind.syntaxType)``).
///
/// - Returns: `true` since the node can always be upcast to its base node.
///
/// - Note: This method overloads the general `is` method and is marked deprecated to produce a warning
/// informing the user that the upcast will always succeed.
@available(*, deprecated, message: "This cast will always succeed")
public func `is`(_ syntaxType: \#(node.kind.syntaxType).Type) -> Bool {
return true
Expand All @@ -90,9 +88,6 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
/// Attempts to upcast the current syntax node to its base node type (``\#(node.kind.syntaxType)``).
///
/// - Returns: The base node created from the current syntax node, as the node can always be upcast to its base type.
///
/// - Note: This method overloads the general `as` method and is marked deprecated to produce a warning
/// informing the user the upcast should be performed using the target base node's initializer.
@available(*, deprecated, message: "Use `\#(node.kind.syntaxType).init` for upcasting")
public func `as`(_ syntaxType: \#(node.kind.syntaxType).Type) -> \#(node.kind.syntaxType)? {
return \#(node.kind.syntaxType)(self)
Expand All @@ -101,46 +96,50 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
/// Force-upcast the current syntax node to its base node type (``\#(node.kind.syntaxType)``).
///
/// - Returns: The base node created from the current syntax node, as the node can always be upcast to its base type.
///
/// - Note: This method overloads the general `as` method and is marked deprecated to produce a warning
/// informing the user the upcast should be performed using the target base node's initializer.
@available(*, deprecated, message: "Use `\#(node.kind.syntaxType).init` for upcasting")
public func cast(_ syntaxType: \#(node.kind.syntaxType).Type) -> \#(node.kind.syntaxType) {
return \#(node.kind.syntaxType)(self)
}
/// Checks if the current syntax node can be cast to a given node type from the different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
/// Checks if the current syntax node can be cast to a given node type from a base node protocol hierarchy other
/// than ``\#(node.kind.protocolType)``.
///
/// - Returns: `false` since the node can not be cast to the node type from different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
/// - Returns: `true` if the node can be cast, `false` otherwise.
///
/// - Note: This method overloads the general `is` method and is marked as deprecated to produce a warning,
/// informing the user that the cast will always fail.
@available(*, deprecated, message: "This cast will always fail")
/// - Note: In most cases, this is comparing a ``\#(node.kind.protocolType)`` to a node that is not a
/// ``\#(node.kind.protocolType)``, which will always fail. If the `syntaxType` argument is a generic type,
/// constrain it to ``\#(node.kind.protocolType)`` instead of ``SyntaxProtocol``.
@available(*, deprecated, message: "Type argument should be part of the '\#(node.kind.protocolType)' hierarchy")
public func `is`<S: SyntaxProtocol>(_ syntaxType: S.Type) -> Bool {
return false
return self.as(syntaxType) != nil
}
/// Attempts to cast the current syntax node to a given node type from the different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
/// Attempts to cast the current syntax node to a given node type from the a base node protocol hierarchy other than
/// ``\#(node.kind.protocolType)``.
///
/// - Returns: `nil` since the node can not be cast to the node type from different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
/// - Returns: An instance of the specialized type, or `nil` if the cast fails.
///
/// - Note: This method overloads the general `as` method and is marked as deprecated to produce a warning,
/// informing the user that the cast will always fail.
@available(*, deprecated, message: "This cast will always fail")
/// - Note: In most cases, this is casting a ``\#(node.kind.protocolType)`` to a node that is not a
/// ``\#(node.kind.protocolType)``, which will always fail. If the `syntaxType` argument is a generic type,
/// constrain it to ``\#(node.kind.protocolType)`` instead of ``SyntaxProtocol``.
@available(*, deprecated, message: "Type argument should be part of the '\#(node.kind.protocolType)' hierarchy")
public func `as`<S: SyntaxProtocol>(_ syntaxType: S.Type) -> S? {
return nil
return S.init(self)
}
/// Force-casts the current syntax node to a given node type from the different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
/// Force-casts the current syntax node to a given node type from a base node protocol hierarchy other than
/// ``\#(node.kind.protocolType)``.
///
/// - Returns: An instance of the specialized type.
///
/// - Returns: This method will always trigger a runtime crash and never return.
/// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast.
///
/// - Note: This method overloads the general `cast` method and is marked as deprecated to produce a warning,
/// informing the user that the cast will always fail.
/// - Warning: Invoking this method will lead to a fatal error.
@available(*, deprecated, message: "This cast will always fail")
/// - Note: In most cases, this is casting a ``\#(node.kind.protocolType)`` to a node that is not a
/// ``\#(node.kind.protocolType)``, which will always fail. If the `syntaxType` argument is a generic type,
/// constrain it to ``\#(node.kind.protocolType)`` instead of ``SyntaxProtocol``.
@available(*, deprecated, message: "Type argument should be part of the '\#(node.kind.protocolType)' hierarchy")
public func cast<S: SyntaxProtocol>(_ syntaxType: S.Type) -> S {
fatalError("\(Self.self) cannot be cast to \(S.self)")
return self.as(S.self)!
}
}
"""#
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftSyntax/SyntaxProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public extension SyntaxProtocol {
return S.init(self)
}

/// Attempts to upcast the current syntax node to ``Syntax`` node..
/// Attempts to upcast the current syntax node to ``Syntax`` node.
///
/// - Returns: The ``Syntax`` node created from the current syntax node, as the node can always be upcast to ``Syntax`` node.
///
Expand Down
Loading

0 comments on commit bcd4772

Please sign in to comment.