1+ //
2+ // Extension.swift
3+ // SyntaxKit
4+ //
5+ // Created by Leo Dion.
6+ // Copyright © 2025 BrightDigit.
7+ //
8+ // Permission is hereby granted, free of charge, to any person
9+ // obtaining a copy of this software and associated documentation
10+ // files (the "Software"), to deal in the Software without
11+ // restriction, including without limitation the rights to use,
12+ // copy, modify, merge, publish, distribute, sublicense, and/or
13+ // sell copies of the Software, and to permit persons to whom the
14+ // Software is furnished to do so, subject to the following
15+ // conditions:
16+ //
17+ // The above copyright notice and this permission notice shall be
18+ // included in all copies or substantial portions of the Software.
19+ //
20+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+ // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+ // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+ // OTHER DEALINGS IN THE SOFTWARE.
28+ //
29+
30+ import SwiftSyntax
31+
32+ /// A Swift `extension` declaration.
33+ public struct Extension : CodeBlock {
34+ private let extendedType : String
35+ private let members : [ CodeBlock ]
36+ private var inheritance : [ String ] = [ ]
37+
38+ /// Creates an `extension` declaration.
39+ /// - Parameters:
40+ /// - extendedType: The name of the type being extended.
41+ /// - content: A ``CodeBlockBuilder`` that provides the members of the extension.
42+ public init ( _ extendedType: String , @CodeBlockBuilderResult _ content: ( ) -> [ CodeBlock ] ) {
43+ self . extendedType = extendedType
44+ self . members = content ( )
45+ }
46+
47+ /// Sets the inheritance for the extension.
48+ /// - Parameter types: The types to inherit from.
49+ /// - Returns: A copy of the extension with the inheritance set.
50+ public func inherits( _ types: String ... ) -> Self {
51+ var copy = self
52+ copy. inheritance = types
53+ return copy
54+ }
55+
56+ public var syntax : SyntaxProtocol {
57+ let extensionKeyword = TokenSyntax . keyword ( . extension, trailingTrivia: . space)
58+ let identifier = TokenSyntax . identifier ( extendedType, trailingTrivia: . space)
59+
60+ var inheritanceClause : InheritanceClauseSyntax ?
61+ if !inheritance. isEmpty {
62+ let inheritedTypes = inheritance. map { type in
63+ InheritedTypeSyntax ( type: IdentifierTypeSyntax ( name: . identifier( type) ) )
64+ }
65+ inheritanceClause = InheritanceClauseSyntax (
66+ colon: . colonToken( ) ,
67+ inheritedTypes: InheritedTypeListSyntax (
68+ inheritedTypes. enumerated ( ) . map { idx, inherited in
69+ var type = inherited
70+ if idx < inheritedTypes. count - 1 {
71+ type = type. with ( \. trailingComma, TokenSyntax . commaToken ( trailingTrivia: . space) )
72+ }
73+ return type
74+ }
75+ )
76+ )
77+ }
78+
79+ let memberBlock = MemberBlockSyntax (
80+ leftBrace: . leftBraceToken( leadingTrivia: . space, trailingTrivia: . newline) ,
81+ members: MemberBlockItemListSyntax (
82+ members. compactMap { member in
83+ guard let syntax = member. syntax. as ( DeclSyntax . self) else { return nil }
84+ return MemberBlockItemSyntax ( decl: syntax, trailingTrivia: . newline)
85+ } ) ,
86+ rightBrace: . rightBraceToken( leadingTrivia: . newline)
87+ )
88+
89+ return ExtensionDeclSyntax (
90+ extensionKeyword: extensionKeyword,
91+ extendedType: IdentifierTypeSyntax ( name: identifier) ,
92+ inheritanceClause: inheritanceClause,
93+ memberBlock: memberBlock
94+ )
95+ }
96+ }
0 commit comments