|
| 1 | +%{ |
| 2 | + from gyb_syntax_support import SYNTAX_NODES |
| 3 | + from gyb_helpers import SyntaxBuildableNode |
| 4 | + # -*- mode: Swift -*- |
| 5 | + # Ignore the following admonition it applies to the resulting .swift file only |
| 6 | +}% |
| 7 | +//// Automatically Generated From BuildableNodes.swift.gyb. |
| 8 | +//// Do Not Edit Directly! |
| 9 | +//===----------------------------------------------------------------------===// |
| 10 | +// |
| 11 | +// This source file is part of the Swift.org open source project |
| 12 | +// |
| 13 | +// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors |
| 14 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 15 | +// |
| 16 | +// See https://swift.org/LICENSE.txt for license information |
| 17 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 18 | +// |
| 19 | +//===----------------------------------------------------------------------===// |
| 20 | + |
| 21 | +import SwiftSyntax |
| 22 | + |
| 23 | +% for node in [SyntaxBuildableNode(syntax_node) for syntax_node in SYNTAX_NODES if syntax_node.is_buildable()]: |
| 24 | +% type = node.type() |
| 25 | +% base_type = node.base_type() |
| 26 | +% if node.documentation(): |
| 27 | +/// ${node.documentation()} |
| 28 | +% end |
| 29 | +public struct ${type.buildable()}: ${base_type.buildable()}, ${type.expressible_as()} { |
| 30 | +% children = node.children() |
| 31 | +% for child in children: |
| 32 | + let ${child.name()}: ${child.type().buildable()} |
| 33 | +% end |
| 34 | + |
| 35 | + /// Creates a `${type.buildable()}` using the provided parameters. |
| 36 | + /// - Parameters: |
| 37 | +% for child in children: |
| 38 | + /// - ${child.name()}: ${child.documentation()} |
| 39 | +% end |
| 40 | + public init( |
| 41 | + ${',\n '.join(['%s: %s%s' % ( |
| 42 | + child.name(), |
| 43 | + child.type().expressible_as(), |
| 44 | + child.type().default_initialization() |
| 45 | + ) for child in children])} |
| 46 | + ) { |
| 47 | +% for child in children: |
| 48 | +% assert_stmt = child.generate_assert_stmt_text_choices(child.name()) |
| 49 | + self.${child.name()} = ${child.type().generate_expr_convert_param_type_to_storage_type(child.name())} |
| 50 | +% if assert_stmt: |
| 51 | + ${assert_stmt} |
| 52 | +% end |
| 53 | +% end |
| 54 | + } |
| 55 | + |
| 56 | +%{ |
| 57 | + create_convenience_initializer = False # Only create the convenience initializer if at least one parameter is different than in the initializer defined above |
| 58 | + # Keep track of init parameter and result builder parameters in different lists to make sure result builder params occur at the end, so they can use trailing closure syntax |
| 59 | + convenience_init_normal_parameters = [] |
| 60 | + convenience_init_result_builder_parameters = [] |
| 61 | + delegated_init_args = [] |
| 62 | + for child in node.children(): |
| 63 | + produce_expr = None # The expression that is used to call the default initializer defined above |
| 64 | + if child.type().is_syntax_collection(): # Allow initializing syntax collections with result builders |
| 65 | + create_convenience_initializer = True |
| 66 | + default_value = ' = { nil }' if child.type().is_optional else ' = { %s([]) }' % (child.type().buildable()) |
| 67 | + convenience_init_result_builder_parameters.append('@%s %sBuilder: () -> %s%s' % (child.type().non_optional().result_builder(), child.name(), child.type().expressible_as(), default_value)) |
| 68 | + produce_expr = '%sBuilder()' % child.name() |
| 69 | + elif child.type().token() and not child.type().token().text: # Allow initializing identifier or a token without default text with String value |
| 70 | + create_convenience_initializer = True |
| 71 | + if child.type().is_optional: |
| 72 | + param_type = 'String?' |
| 73 | + produce_expr = '%s.map(TokenSyntax.%s)' % (child.name(), child.type().token().swift_kind()) |
| 74 | + else: |
| 75 | + param_type = 'String' |
| 76 | + produce_expr = 'TokenSyntax.%s(%s)' % (child.type().token().swift_kind(), child.name()) |
| 77 | + convenience_init_normal_parameters.append('%s: %s' % (child.name(), param_type)) |
| 78 | + else: |
| 79 | + convenience_init_normal_parameters.append('%s: %s%s' % (child.name(), child.type().expressible_as(), child.type().default_initialization())) |
| 80 | + produce_expr = child.name() |
| 81 | + delegated_init_args.append('%s: %s' % (child.name(), produce_expr)) |
| 82 | +}% |
| 83 | +% if create_convenience_initializer: |
| 84 | + /// A convenience initializer that allows: |
| 85 | + /// - Initializing syntax collections using result builders |
| 86 | + /// - Initializing tokens without default text using strings |
| 87 | + public init( |
| 88 | + ${',\n '.join(convenience_init_normal_parameters + convenience_init_result_builder_parameters)} |
| 89 | + ) { |
| 90 | + self.init( |
| 91 | + ${',\n '.join(delegated_init_args)} |
| 92 | + ) |
| 93 | + } |
| 94 | +% end |
| 95 | + |
| 96 | + func build${type.base_name()}(format: Format, leadingTrivia: Trivia? = nil) -> ${type.syntax()} { |
| 97 | + let result = SyntaxFactory.make${type.base_name()}( |
| 98 | + ${',\n '.join(['%s: %s' % (child.name(), child.generate_expr_build_syntax_node(child.name(), 'format')) for child in children])} |
| 99 | + ) |
| 100 | + if let leadingTrivia = leadingTrivia { |
| 101 | + return result.withLeadingTrivia(leadingTrivia + (result.leadingTrivia ?? [])) |
| 102 | + } else { |
| 103 | + return result |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + /// Conformance to `${base_type.buildable()}`. |
| 108 | + public func build${base_type.base_name()}(format: Format, leadingTrivia: Trivia? = nil) -> ${base_type.syntax()} { |
| 109 | + let result = build${type.base_name()}(format: format, leadingTrivia: leadingTrivia) |
| 110 | + return ${base_type.syntax()}(result) |
| 111 | + } |
| 112 | + |
| 113 | + /// Conformance to `${type.expressible_as()}`. |
| 114 | + public func create${type.buildable_base_name()}() -> ${type.buildable()} { |
| 115 | + return self |
| 116 | + } |
| 117 | + |
| 118 | + /// `${type.buildable()}` might conform to `${base_type.expressible_as()}` via different `ExpressibleAs*` paths. |
| 119 | + /// Thus, there are multiple default implementations for `create${base_type.buildable_base_name()}`, some of which perform conversions through `ExpressibleAs*` protocols. |
| 120 | + /// To resolve the ambiguity, provide a fixed implementation that doesn't perform any conversions. |
| 121 | + public func create${base_type.buildable_base_name()}() -> ${base_type.buildable()} { |
| 122 | + return self |
| 123 | + } |
| 124 | + |
| 125 | +% if base_type.base_name() != 'Syntax': |
| 126 | + /// `${type.buildable()}` might conform to `SyntaxBuildable` via different `ExpressibleAs*` paths. |
| 127 | + /// Thus, there are multiple default implementations for `createSyntaxBuildable`, some of which perform conversions through `ExpressibleAs*` protocols. |
| 128 | + /// To resolve the ambiguity, provide a fixed implementation that doesn't perform any conversions. |
| 129 | + public func createSyntaxBuildable() -> SyntaxBuildable { |
| 130 | + return self |
| 131 | + } |
| 132 | +% end |
| 133 | +} |
| 134 | +% end |
0 commit comments