Skip to content

Commit 3ea358d

Browse files
authored
Merge pull request #320 from kimdv/kimdv/introduce-protocols-conformance-map
Use protocols conformance map to add protocols
2 parents 7d042fc + 7e804d5 commit 3ea358d

15 files changed

+2122
-1848
lines changed

Sources/SwiftSyntaxBuilder/BooleanLiteralExprConvenienceInitializers.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import SwiftSyntax
14+
1315
extension BooleanLiteralExpr {
1416
public init(_ value: Bool) {
15-
self.init(booleanLiteral: value ? .true : .false)
17+
self.init(booleanLiteral: value ? TokenSyntax.true : .false)
1618
}
1719
}
1820

Sources/SwiftSyntaxBuilder/Buildables.swift.gyb

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from gyb_syntax_support.kinds import lowercase_first_word
44
from gyb_syntax_support.kinds import SYNTAX_BASE_KINDS
55
from gyb_syntax_support.kinds import syntax_buildable_child_type, syntax_buildable_default_init_value
6+
from gyb_syntax_support.protocolsMap import SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES
67
# -*- mode: Swift -*-
78
# Ignore the following admonition it applies to the resulting .swift file only
89
}%
@@ -40,16 +41,18 @@ public protocol ${kind}ListBuildable: SyntaxListBuildable {
4041
}
4142

4243
% buildable_type = kind + 'Buildable'
43-
public protocol ExpressibleAs${buildable_type} {
44+
% expressible_as_type = 'ExpressibleAs' + buildable_type
45+
% expressible_as_protocols = SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.get(expressible_as_type)
46+
% if expressible_as_protocols:
47+
public protocol ${expressible_as_type}: ${', '.join(expressible_as_protocols)} {
48+
% else:
49+
public protocol ${expressible_as_type} {
50+
% end
4451
func create${buildable_type}() -> ${buildable_type}
4552
}
4653

4754
% if kind == 'Syntax':
4855
public protocol ${buildable_type}: ExpressibleAs${buildable_type}, ${kind}ListBuildable {
49-
% elif kind == 'Decl':
50-
public protocol ${buildable_type}: ExpressibleAs${buildable_type}, SyntaxBuildable, ${kind}ListBuildable, ExpressibleAsMemberDeclListItem, ExpressibleAsCodeBlockItem {
51-
% elif kind == 'Stmt':
52-
public protocol ${buildable_type}: ExpressibleAs${buildable_type}, SyntaxBuildable, ${kind}ListBuildable, ExpressibleAsCodeBlockItem {
5356
% else:
5457
public protocol ${buildable_type}: ExpressibleAs${buildable_type}, SyntaxBuildable, ${kind}ListBuildable {
5558
% end
@@ -97,22 +100,6 @@ extension ${buildable_type} {
97100
[build${kind}(format: format, leadingTrivia: leadingTrivia)]
98101
}
99102
}
100-
% if kind == 'Decl':
101-
102-
extension DeclBuildable {
103-
public func createMemberDeclListItem() -> MemberDeclListItem {
104-
MemberDeclListItem(decl: self)
105-
}
106-
}
107-
% end
108-
% if kind in ['Decl', 'Stmt']:
109-
110-
extension ${kind}Buildable {
111-
public func createCodeBlockItem() -> CodeBlockItem {
112-
CodeBlockItem(item: self)
113-
}
114-
}
115-
% end
116103

117104
% end
118105
% end
@@ -137,12 +124,15 @@ public struct ${node.syntax_kind}: ${node.base_kind}Buildable {
137124
% child_token = SYNTAX_TOKEN_MAP.get(child.syntax_kind)
138125
% param_type = syntax_buildable_child_type(child.type_name, child.syntax_kind, child.is_token(), child.is_optional)
139126
% default_value = syntax_buildable_default_init_value(child, child_token)
140-
% init_parameters.append("%s: %s%s" % (child.swift_name, param_type, default_value))
127+
% init_parameters.append("%s: ExpressibleAs%s%s" % (child.swift_name, param_type, default_value))
141128
% end
142129
${',\n '.join(init_parameters)}
143130
) {
144131
% for child in node.children:
145-
self.${child.swift_name} = ${child.swift_name}
132+
% create_method_dot = '?.' if child.is_optional else '.'
133+
% child_token = SYNTAX_TOKEN_MAP.get(child.syntax_kind)
134+
% param_type = syntax_buildable_child_type(child.type_name, child.syntax_kind, child.is_token())
135+
self.${child.swift_name} = ${child.swift_name}${create_method_dot}create${param_type}()
146136
% end
147137
}
148138

@@ -198,8 +188,8 @@ public struct ${node.syntax_kind}: ${node.base_kind}Buildable {
198188
public struct ${node.syntax_kind}: SyntaxBuildable {
199189
let elements: [${element_type}]
200190

201-
public init(_ elements: [${element_type}]) {
202-
self.elements = elements
191+
public init(_ elements: [ExpressibleAs${element_type}]) {
192+
self.elements = elements.map { $0.create${element_type}() }
203193
}
204194

205195
public func build${node.syntax_kind}(format: Format) -> ${node.syntax_kind}Syntax {
@@ -229,11 +219,17 @@ public struct ${node.syntax_kind}: SyntaxBuildable {
229219

230220
% end
231221
% if node.is_buildable() or node.is_syntax_collection():
232-
public protocol ExpressibleAs${node.syntax_kind} {
222+
% expressible_as_type = 'ExpressibleAs' + node.syntax_kind
223+
% expressible_as_protocols = SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.get(expressible_as_type)
224+
% if expressible_as_protocols:
225+
public protocol ${expressible_as_type}: ${', '.join(expressible_as_protocols)} {
226+
% else:
227+
public protocol ${expressible_as_type} {
228+
% end
233229
func create${node.syntax_kind}() -> ${node.syntax_kind}
234230
}
235231

236-
extension ${node.syntax_kind}: ExpressibleAs${node.syntax_kind} {
232+
extension ${node.syntax_kind}: ${expressible_as_type} {
237233
public func create${node.syntax_kind}() -> ${node.syntax_kind} {
238234
self
239235
}
@@ -249,4 +245,41 @@ extension TokenSyntax: ExpressibleAsTokenSyntax {
249245
public func createTokenSyntax() -> TokenSyntax {
250246
self
251247
}
252-
}
248+
}
249+
250+
// MARK: - Syntax buildable expressible as conformances
251+
252+
% for protocol, conformances in SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.items():
253+
% if 'ExpressibleAsConditionElementList' in conformances:
254+
extension ${protocol} {
255+
public func createConditionElementList() -> ConditionElementList {
256+
ConditionElementList([self])
257+
}
258+
}
259+
260+
% end
261+
% if 'ExpressibleAsConditionElement' in conformances:
262+
extension ${protocol} {
263+
public func createConditionElement() -> ConditionElement {
264+
ConditionElement(condition: self)
265+
}
266+
}
267+
268+
% end
269+
% if 'ExpressibleAsCodeBlockItem' in conformances:
270+
extension ${protocol} {
271+
public func createCodeBlockItem() -> CodeBlockItem {
272+
CodeBlockItem(item: self)
273+
}
274+
}
275+
276+
% end
277+
% if 'ExpressibleAsMemberDeclListItem' in conformances:
278+
extension ${protocol} {
279+
public func createMemberDeclListItem() -> MemberDeclListItem {
280+
MemberDeclListItem(decl: self)
281+
}
282+
}
283+
284+
% end
285+
% end

Sources/SwiftSyntaxBuilder/BuildablesConvenienceInitializers.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ extension ${node.syntax_kind} {
5353
% # When type is not handled above, use default value
5454
% param_type = syntax_buildable_child_type(child.type_name, child.syntax_kind, child.is_token(), child.is_optional)
5555
% default_value = syntax_buildable_default_init_value(child, child_token)
56-
% init_parameters.append("%s: %s%s" % (child.swift_name, param_type, default_value))
56+
% init_parameters.append("%s: ExpressibleAs%s%s" % (child.swift_name, param_type, default_value))
5757
% end
5858
% end
5959
${',\n '.join(init_parameters + init_result_builder_parameters)}

Sources/SwiftSyntaxBuilder/Tokens.swift.gyb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,30 @@
2121
import SwiftSyntax
2222

2323
/// Namespace for commonly used tokens with default trivia.
24-
public extension TokenSyntax {
24+
public extension ExpressibleAsTokenSyntax where Self == TokenSyntax {
2525
% for token in SYNTAX_TOKENS:
2626
% if token.is_keyword:
2727
/// The `${token.text.encode('utf-8').decode('unicode_escape')}` keyword
28-
static let `${lowercase_first_word(token.name)}` = SyntaxFactory.make${token.name}Keyword()
28+
static var `${lowercase_first_word(token.name)}`: TokenSyntax {
29+
SyntaxFactory.make${token.name}Keyword()
2930
% if token.requires_leading_space:
3031
.withLeadingTrivia(.spaces(1))
3132
% end
3233
% if token.requires_trailing_space:
3334
.withTrailingTrivia(.spaces(1))
35+
}
3436
% end
3537
% elif token.text:
3638
/// The `${token.text.encode('utf-8').decode('unicode_escape')}` token
37-
static let `${lowercase_first_word(token.name)}` = SyntaxFactory.make${token.name}Token()
39+
static var `${lowercase_first_word(token.name)}`: TokenSyntax {
40+
SyntaxFactory.make${token.name}Token()
3841
% if token.requires_leading_space:
3942
.withLeadingTrivia(.spaces(1))
4043
% end
4144
% if token.requires_trailing_space:
4245
.withTrailingTrivia(.spaces(1))
4346
% end
47+
}
4448
% else:
4549
static func `${lowercase_first_word(token.name)}`(_ text: String) -> TokenSyntax {
4650
SyntaxFactory.make${token.name}(text)
@@ -55,5 +59,7 @@ public extension TokenSyntax {
5559

5660
% end
5761
/// The `eof` token
58-
static let eof = SyntaxFactory.makeToken(.eof, presence: .present)
62+
static var eof: TokenSyntax {
63+
SyntaxFactory.makeToken(.eof, presence: .present)
64+
}
5965
}

0 commit comments

Comments
 (0)