diff --git a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift index 1d75123631e..e43852c8eb8 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift @@ -152,6 +152,9 @@ public let EXPR_NODES: [Node] = [ kind: .awaitExpr, base: .expr, nameForDiagnostics: "'await' expression", + traits: [ + "EffectfulExpr" + ], children: [ Child( name: "awaitKeyword", @@ -1914,6 +1917,9 @@ public let EXPR_NODES: [Node] = [ try! foo() ``` """, + traits: [ + "EffectfulExpr" + ], children: [ Child( name: "tryKeyword", diff --git a/CodeGeneration/Sources/SyntaxSupport/Traits.swift b/CodeGeneration/Sources/SyntaxSupport/Traits.swift index 8838ecb7ad5..b465db97ecd 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Traits.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Traits.swift @@ -66,6 +66,18 @@ public let TRAITS: [Trait] = [ Child(name: "memberBlock", kind: .node(kind: .memberBlock)), ] ), + Trait( + traitName: "EffectfulExpr", + documentation: "Syntax trait for effectful expressions, such as `try` and `await`.", + children: [ + Child(name: "expression", kind: .node(kind: .expr)), + Child( + name: "keyword", + kind: .token(choices: [.keyword(.try), .keyword(.await)]), + documentation: "The token that represents the specific keyword of the effectful expression." + ), + ] + ), Trait( traitName: "EffectSpecifiers", children: [ diff --git a/Release Notes/610.md b/Release Notes/610.md new file mode 100644 index 00000000000..b5381b1e0b9 --- /dev/null +++ b/Release Notes/610.md @@ -0,0 +1,25 @@ +# Swift Syntax 610 Release Notes + +## New APIs + +- `EffectfulExprSyntax` + - Description: A protocol for unified handling of `try` and `await` expressions, with a `keyword` property to identify the expression's specific keyword. + - Issue: https://github.com/apple/swift-syntax/issues/2549 + - Pull Request: https://github.com/apple/swift-syntax/pull/2572 + +## API Behavior Changes + +## Deprecations + +## API-Incompatible Changes + +## Template + +- *Affected API or two word description* + - Description: *A 1-2 sentence description of the new/modified API* + - Issue: *If an issue exists for this change, a link to the issue* + - Pull Request: *Link to the pull request(s) that introduces this change* + - Migration steps: Steps that adopters of swift-syntax should take to move to the new API (required for deprecations and API-incompatible changes). + - Notes: *In case of deprecations or API-incompatible changes, the reason why this change was made and the suggested alternative* + +*Insert entries in chronological order, with newer entries at the bottom* diff --git a/Sources/SwiftSyntax/CustomTraits.swift b/Sources/SwiftSyntax/CustomTraits.swift index f1daddf5722..b5cb64cdf8e 100644 --- a/Sources/SwiftSyntax/CustomTraits.swift +++ b/Sources/SwiftSyntax/CustomTraits.swift @@ -21,6 +21,17 @@ extension ActorDeclSyntax { } } +extension AwaitExprSyntax { + public var keyword: TokenSyntax { + get { + return awaitKeyword + } + set { + awaitKeyword = newValue + } + } +} + extension ClassDeclSyntax { public var introducer: TokenSyntax { get { @@ -76,6 +87,17 @@ extension StructDeclSyntax { } } +extension TryExprSyntax { + public var keyword: TokenSyntax { + get { + return tryKeyword + } + set { + tryKeyword = newValue + } + } +} + //==========================================================================// // IMPORTANT: If you are tempted to add an extension here, please insert // // it in alphabetical order above // diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index b43846641b6..97b3f573f0f 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -392,6 +392,7 @@ These articles are intended for developers wishing to contribute to SwiftSyntax - - +- - - - diff --git a/Sources/SwiftSyntax/generated/SyntaxTraits.swift b/Sources/SwiftSyntax/generated/SyntaxTraits.swift index 1034e136ffc..efffaaa0683 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTraits.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTraits.swift @@ -132,6 +132,55 @@ public extension SyntaxProtocol { } } +// MARK: - EffectfulExprSyntax + +/// Syntax trait for effectful expressions, such as `try` and `await`. +public protocol EffectfulExprSyntax: SyntaxProtocol { + var expression: ExprSyntax { + get + set + } + + /// The token that represents the specific keyword of the effectful expression. + /// + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds: + /// - `try` + /// - `await` + var keyword: TokenSyntax { + get + set + } +} + +public extension EffectfulExprSyntax { + /// Without this function, the `with` function defined on `SyntaxProtocol` + /// does not work on existentials of this protocol type. + @_disfavoredOverload + func with(_ keyPath: WritableKeyPath, _ newChild: T) -> EffectfulExprSyntax { + var copy: EffectfulExprSyntax = self + copy[keyPath: keyPath] = newChild + return copy + } +} + +public extension SyntaxProtocol { + /// Check whether the non-type erased version of this syntax node conforms to + /// `EffectfulExprSyntax`. + /// Note that this will incur an existential conversion. + func isProtocol(_: EffectfulExprSyntax.Protocol) -> Bool { + return self.asProtocol(EffectfulExprSyntax.self) != nil + } + + /// Return the non-type erased version of this syntax node if it conforms to + /// `EffectfulExprSyntax`. Otherwise return `nil`. + /// Note that this will incur an existential conversion. + func asProtocol(_: EffectfulExprSyntax.Protocol) -> EffectfulExprSyntax? { + return Syntax(self).asProtocol(SyntaxProtocol.self) as? EffectfulExprSyntax + } +} + // MARK: - EffectSpecifiersSyntax public protocol EffectSpecifiersSyntax: SyntaxProtocol { @@ -689,6 +738,8 @@ extension AttributedTypeSyntax: WithAttributesSyntax {} extension AvailabilityArgumentSyntax: WithTrailingCommaSyntax {} +extension AwaitExprSyntax: EffectfulExprSyntax {} + extension CatchClauseSyntax: WithCodeBlockSyntax {} extension CatchItemSyntax: WithTrailingCommaSyntax {} @@ -831,6 +882,8 @@ extension SwitchCaseSyntax: WithStatementsSyntax {} extension SwitchExprSyntax: BracedSyntax {} +extension TryExprSyntax: EffectfulExprSyntax {} + extension TupleExprSyntax: ParenthesizedSyntax {} extension TuplePatternElementSyntax: WithTrailingCommaSyntax {}