Skip to content

Commit 12993b0

Browse files
committed
Casts to children of SyntaxProtocol are not always invalid
Update these overrides so they don't always fail.
1 parent 8d5fab7 commit 12993b0

File tree

3 files changed

+163
-169
lines changed

3 files changed

+163
-169
lines changed

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxBaseNodesFile.swift

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
7171
/// Force-casts the current syntax node to a given specialized syntax type.
7272
///
7373
/// - Returns: An instance of the specialized type.
74+
///
7475
/// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast.
7576
public func cast<S: \#(node.kind.protocolType)>(_ syntaxType: S.Type) -> S {
7677
return self.as(S.self)!
@@ -79,9 +80,6 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
7980
/// Checks if the current syntax node can be upcast to its base node type (``\#(node.kind.syntaxType)``).
8081
///
8182
/// - Returns: `true` since the node can always be upcast to its base node.
82-
///
83-
/// - Note: This method overloads the general `is` method and is marked deprecated to produce a warning
84-
/// informing the user that the upcast will always succeed.
8583
@available(*, deprecated, message: "This cast will always succeed")
8684
public func `is`(_ syntaxType: \#(node.kind.syntaxType).Type) -> Bool {
8785
return true
@@ -90,9 +88,6 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
9088
/// Attempts to upcast the current syntax node to its base node type (``\#(node.kind.syntaxType)``).
9189
///
9290
/// - Returns: The base node created from the current syntax node, as the node can always be upcast to its base type.
93-
///
94-
/// - Note: This method overloads the general `as` method and is marked deprecated to produce a warning
95-
/// informing the user the upcast should be performed using the target base node's initializer.
9691
@available(*, deprecated, message: "Use `\#(node.kind.syntaxType).init` for upcasting")
9792
public func `as`(_ syntaxType: \#(node.kind.syntaxType).Type) -> \#(node.kind.syntaxType)? {
9893
return \#(node.kind.syntaxType)(self)
@@ -101,46 +96,50 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
10196
/// Force-upcast the current syntax node to its base node type (``\#(node.kind.syntaxType)``).
10297
///
10398
/// - Returns: The base node created from the current syntax node, as the node can always be upcast to its base type.
104-
///
105-
/// - Note: This method overloads the general `as` method and is marked deprecated to produce a warning
106-
/// informing the user the upcast should be performed using the target base node's initializer.
10799
@available(*, deprecated, message: "Use `\#(node.kind.syntaxType).init` for upcasting")
108100
public func cast(_ syntaxType: \#(node.kind.syntaxType).Type) -> \#(node.kind.syntaxType) {
109101
return \#(node.kind.syntaxType)(self)
110102
}
111103
112-
/// 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)``.
104+
/// Checks if the current syntax node can be cast to a given node type from a base node protocol hierarchy other
105+
/// than ``\#(node.kind.protocolType)``.
113106
///
114-
/// - Returns: `false` since the node can not be cast to the node type from different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
107+
/// - Returns: `true` if the node can be cast, `false` otherwise.
115108
///
116-
/// - Note: This method overloads the general `is` method and is marked as deprecated to produce a warning,
117-
/// informing the user that the cast will always fail.
118-
@available(*, deprecated, message: "This cast will always fail")
109+
/// - Note: In most cases, this is comparing a ``\#(node.kind.protocolType)`` to a node that is not a
110+
/// ``\#(node.kind.protocolType)``, which will always fail. If the `syntaxType` argument is a generic type,
111+
/// constrain it to ``\#(node.kind.protocolType)`` instead of ``SyntaxProtocol``.
112+
@available(*, deprecated, message: "Type argument should be part of the '\#(node.kind.protocolType)' hierarchy")
119113
public func `is`<S: SyntaxProtocol>(_ syntaxType: S.Type) -> Bool {
120-
return false
114+
return self.as(syntaxType) != nil
121115
}
122116
123-
/// Attempts to cast the current syntax node to a given node type from the different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
117+
/// Attempts to cast the current syntax node to a given node type from the a base node protocol hierarchy other than
118+
/// ``\#(node.kind.protocolType)``.
124119
///
125-
/// - Returns: `nil` since the node can not be cast to the node type from different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
120+
/// - Returns: An instance of the specialized type, or `nil` if the cast fails.
126121
///
127-
/// - Note: This method overloads the general `as` method and is marked as deprecated to produce a warning,
128-
/// informing the user that the cast will always fail.
129-
@available(*, deprecated, message: "This cast will always fail")
122+
/// - Note: In most cases, this is casting a ``\#(node.kind.protocolType)`` to a node that is not a
123+
/// ``\#(node.kind.protocolType)``, which will always fail. If the `syntaxType` argument is a generic type,
124+
/// constrain it to ``\#(node.kind.protocolType)`` instead of ``SyntaxProtocol``.
125+
@available(*, deprecated, message: "Type argument should be part of the '\#(node.kind.protocolType)' hierarchy")
130126
public func `as`<S: SyntaxProtocol>(_ syntaxType: S.Type) -> S? {
131-
return nil
127+
return S.init(self)
132128
}
133129
134-
/// Force-casts the current syntax node to a given node type from the different base node protocol hierarchy than ``\#(node.kind.protocolType)``.
130+
/// Force-casts the current syntax node to a given node type from a base node protocol hierarchy other than
131+
/// ``\#(node.kind.protocolType)``.
132+
///
133+
/// - Returns: An instance of the specialized type.
135134
///
136-
/// - Returns: This method will always trigger a runtime crash and never return.
135+
/// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast.
137136
///
138-
/// - Note: This method overloads the general `cast` method and is marked as deprecated to produce a warning,
139-
/// informing the user that the cast will always fail.
140-
/// - Warning: Invoking this method will lead to a fatal error.
141-
@available(*, deprecated, message: "This cast will always fail")
137+
/// - Note: In most cases, this is casting a ``\#(node.kind.protocolType)`` to a node that is not a
138+
/// ``\#(node.kind.protocolType)``, which will always fail. If the `syntaxType` argument is a generic type,
139+
/// constrain it to ``\#(node.kind.protocolType)`` instead of ``SyntaxProtocol``.
140+
@available(*, deprecated, message: "Type argument should be part of the '\#(node.kind.protocolType)' hierarchy")
142141
public func cast<S: SyntaxProtocol>(_ syntaxType: S.Type) -> S {
143-
fatalError("\(Self.self) cannot be cast to \(S.self)")
142+
return self.as(S.self)!
144143
}
145144
}
146145
"""#

Sources/SwiftSyntax/SyntaxProtocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public extension SyntaxProtocol {
8989
return S.init(self)
9090
}
9191

92-
/// Attempts to upcast the current syntax node to ``Syntax`` node..
92+
/// Attempts to upcast the current syntax node to ``Syntax`` node.
9393
///
9494
/// - Returns: The ``Syntax`` node created from the current syntax node, as the node can always be upcast to ``Syntax`` node.
9595
///

0 commit comments

Comments
 (0)