Skip to content

Casts to children of SyntaxProtocol are not always invalid #2265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 25, 2023
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
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