diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index dba5a354a43..e4baa8ab9a0 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -82,7 +82,10 @@ public let DECL_NODES: [Node] = [ base: .decl, nameForDiagnostics: "accessor", parserFunction: "parseAccessorDecl", - traits: ["WithAttributes"], + traits: [ + "WithOptionalCodeBlock", + "WithAttributes", + ], children: [ Child( name: "attributes", @@ -493,6 +496,7 @@ public let DECL_NODES: [Node] = [ traits: [ "WithAttributes", "WithModifiers", + "WithOptionalCodeBlock", ], children: [ Child( @@ -879,6 +883,7 @@ public let DECL_NODES: [Node] = [ "WithAttributes", "WithGenericParameters", "WithModifiers", + "WithOptionalCodeBlock", ], children: [ Child( @@ -1217,6 +1222,7 @@ public let DECL_NODES: [Node] = [ "WithAttributes", "WithGenericParameters", "WithModifiers", + "WithOptionalCodeBlock", ], children: [ Child( diff --git a/CodeGeneration/Sources/SyntaxSupport/Traits.swift b/CodeGeneration/Sources/SyntaxSupport/Traits.swift index 41aca45d145..25952b21be6 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Traits.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Traits.swift @@ -151,6 +151,12 @@ public let TRAITS: [Trait] = [ Child(name: "modifiers", kind: .node(kind: .declModifierList)) ] ), + Trait( + traitName: "WithOptionalCodeBlock", + children: [ + Child(name: "body", kind: .node(kind: .codeBlock), isOptional: true) + ] + ), Trait( traitName: "WithStatements", children: [ diff --git a/Release Notes/511.md b/Release Notes/511.md index cc27e59c0af..fd03ecf4139 100644 --- a/Release Notes/511.md +++ b/Release Notes/511.md @@ -20,6 +20,10 @@ - Description: Enum to exhaustively switch over all different syntax nodes of each base type. - Pull Request: https://github.com/apple/swift-syntax/pull/2351 +- `WithOptionalCodeBlock` + - Description: A trait for syntax nodes that have an optional code block, such as `FunctionDeclSyntax` and `InitializerDeclSyntax`. + - Pull Request: https://github.com/apple/swift-syntax/pull/2359 + ## API Behavior Changes ## Deprecations diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index 02a10fe376c..a850a994cc3 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -401,6 +401,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 bca34c2f5e8..193eae03cd8 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTraits.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTraits.swift @@ -570,6 +570,43 @@ public extension SyntaxProtocol { } } +// MARK: - WithOptionalCodeBlockSyntax + + +public protocol WithOptionalCodeBlockSyntax: SyntaxProtocol { + var body: CodeBlockSyntax? { + get + set + } +} + +public extension WithOptionalCodeBlockSyntax { + /// 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) -> WithOptionalCodeBlockSyntax { + var copy: WithOptionalCodeBlockSyntax = self + copy[keyPath: keyPath] = newChild + return copy + } +} + +public extension SyntaxProtocol { + /// Check whether the non-type erased version of this syntax node conforms to + /// `WithOptionalCodeBlockSyntax`. + /// Note that this will incur an existential conversion. + func isProtocol(_: WithOptionalCodeBlockSyntax.Protocol) -> Bool { + return self.asProtocol(WithOptionalCodeBlockSyntax.self) != nil + } + + /// Return the non-type erased version of this syntax node if it conforms to + /// `WithOptionalCodeBlockSyntax`. Otherwise return `nil`. + /// Note that this will incur an existential conversion. + func asProtocol(_: WithOptionalCodeBlockSyntax.Protocol) -> WithOptionalCodeBlockSyntax? { + return Syntax(self).asProtocol(SyntaxProtocol.self) as? WithOptionalCodeBlockSyntax + } +} + // MARK: - WithStatementsSyntax @@ -649,7 +686,7 @@ public extension SyntaxProtocol { extension AccessorBlockSyntax: BracedSyntax {} -extension AccessorDeclSyntax: WithAttributesSyntax {} +extension AccessorDeclSyntax: WithOptionalCodeBlockSyntax, WithAttributesSyntax {} extension AccessorEffectSpecifiersSyntax: EffectSpecifiersSyntax {} @@ -693,7 +730,7 @@ extension DeclNameArgumentsSyntax: ParenthesizedSyntax {} extension DeferStmtSyntax: WithCodeBlockSyntax {} -extension DeinitializerDeclSyntax: WithAttributesSyntax, WithModifiersSyntax {} +extension DeinitializerDeclSyntax: WithAttributesSyntax, WithModifiersSyntax, WithOptionalCodeBlockSyntax {} extension DictionaryElementSyntax: WithTrailingCommaSyntax {} @@ -723,7 +760,7 @@ extension ExtensionDeclSyntax: DeclGroupSyntax, WithAttributesSyntax, WithModifi extension ForStmtSyntax: WithCodeBlockSyntax {} -extension FunctionDeclSyntax: NamedDeclSyntax, WithAttributesSyntax, WithGenericParametersSyntax, WithModifiersSyntax {} +extension FunctionDeclSyntax: NamedDeclSyntax, WithAttributesSyntax, WithGenericParametersSyntax, WithModifiersSyntax, WithOptionalCodeBlockSyntax {} extension FunctionEffectSpecifiersSyntax: EffectSpecifiersSyntax {} @@ -747,7 +784,7 @@ extension ImportDeclSyntax: WithAttributesSyntax, WithModifiersSyntax {} extension InheritedTypeSyntax: WithTrailingCommaSyntax {} -extension InitializerDeclSyntax: WithAttributesSyntax, WithGenericParametersSyntax, WithModifiersSyntax {} +extension InitializerDeclSyntax: WithAttributesSyntax, WithGenericParametersSyntax, WithModifiersSyntax, WithOptionalCodeBlockSyntax {} extension LabeledExprSyntax: WithTrailingCommaSyntax {} diff --git a/Sources/SwiftSyntaxBuilder/SyntaxNodeWithBody.swift b/Sources/SwiftSyntaxBuilder/SyntaxNodeWithBody.swift index 0f2ac8c3f0b..5e707d42ac6 100644 --- a/Sources/SwiftSyntaxBuilder/SyntaxNodeWithBody.swift +++ b/Sources/SwiftSyntaxBuilder/SyntaxNodeWithBody.swift @@ -40,11 +40,9 @@ extension SyntaxStringInterpolation { } } -// MARK: - HasCodeBlock - -public protocol HasTrailingCodeBlock { - var body: CodeBlockSyntax { get set } +// MARK: - HasTrailingCodeBlock +public protocol HasTrailingCodeBlock: WithCodeBlockSyntax { /// Constructs a syntax node where `header` builds the text of the node before the body in braces and `bodyBuilder` is used to build the node’s body. /// /// For example, you can construct @@ -90,11 +88,9 @@ extension ForStmtSyntax: HasTrailingCodeBlock {} extension GuardStmtSyntax: HasTrailingCodeBlock {} extension WhileStmtSyntax: HasTrailingCodeBlock {} -// MARK: - HasOptionalCodeBlock - -public protocol HasTrailingOptionalCodeBlock { - var body: CodeBlockSyntax? { get set } +// MARK: - WithOptionalCodeBlockSyntax +public extension WithOptionalCodeBlockSyntax where Self: DeclSyntaxProtocol { /// Constructs a syntax node where `header` builds the text of the node before the body in braces and `bodyBuilder` is used to build the node’s body. /// /// For example, you can construct @@ -114,10 +110,6 @@ public protocol HasTrailingOptionalCodeBlock { /// ``` /// /// Throws an error if `header` defines a different node type than the type the initializer is called on. E.g. if calling `try FunctionDeclSyntax("init") {}` - init(_ header: SyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () throws -> CodeBlockItemListSyntax) throws -} - -public extension HasTrailingOptionalCodeBlock where Self: DeclSyntaxProtocol { init(_ header: SyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () throws -> CodeBlockItemListSyntax) throws { let decl = DeclSyntax("\(header) {}") guard let castedDecl = decl.as(Self.self) else { @@ -128,11 +120,6 @@ public extension HasTrailingOptionalCodeBlock where Self: DeclSyntaxProtocol { } } -extension AccessorDeclSyntax: HasTrailingOptionalCodeBlock {} -extension DeinitializerDeclSyntax: HasTrailingOptionalCodeBlock {} -extension FunctionDeclSyntax: HasTrailingOptionalCodeBlock {} -extension InitializerDeclSyntax: HasTrailingOptionalCodeBlock {} - // MARK: HasTrailingMemberDeclBlock public protocol HasTrailingMemberDeclBlock {