@@ -22,11 +22,6 @@ struct SyntaxBuildableType: Hashable {
22
22
let tokenKind : String ?
23
23
let isOptional : Bool
24
24
25
- /// If optional `?`, otherwise the empty string.
26
- var optionalQuestionMark : String {
27
- isOptional ? " ? " : " "
28
- }
29
-
30
25
/// Whether this is a token.
31
26
var isToken : Bool {
32
27
syntaxKind == " Token "
@@ -71,81 +66,98 @@ struct SyntaxBuildableType: Hashable {
71
66
syntaxKind
72
67
}
73
68
74
- /// Return the name of the `Buildable` type that is the main entry point for building
69
+ /// Return the `Buildable` type that is the main entry point for building
75
70
/// SwiftSyntax trees using `SwiftSyntaxBuilder`.
76
71
///
77
72
/// These names look as follows:
78
73
/// - For nodes: The node name, e.g. `IdentifierExpr` (these are implemented as structs)
79
74
/// - For base kinds: `<BaseKind>Buildable`, e.g. `ExprBuildable` (these are implemented as protocols)
80
75
/// - For token: `TokenSyntax` (tokens don't have a dedicated type in SwiftSyntaxBuilder)
81
- /// If the type is optional, this terminates with a '?'.
82
- var buildable : String {
83
- if isToken {
84
- // Tokens don't have a dedicated buildable type.
85
- return " TokenSyntax \( optionalQuestionMark) "
86
- } else if SYNTAX_BASE_KINDS . contains ( syntaxKind) {
87
- return " \( syntaxKind) Buildable \( optionalQuestionMark) "
88
- } else {
89
- return " \( syntaxKind) \( optionalQuestionMark) "
90
- }
76
+ /// If the type is optional, the type is wrapped in an `OptionalType`.
77
+ var buildable : ExpressibleAsTypeBuildable {
78
+ optionalWrapped ( type: buildableBaseName)
91
79
}
92
80
93
81
/// Whether parameters of this type should be initializable by a result builder.
94
82
/// Used for certain syntax collections and block-like structures (e.g. `CodeBlock`,
95
83
/// `MemberDeclList`).
96
84
var isBuilderInitializable : Bool {
97
- BUILDER_INITIALIZABLE_TYPES . keys. contains ( nonOptional . buildable )
85
+ BUILDER_INITIALIZABLE_TYPES . keys. contains ( buildableBaseName )
98
86
}
99
87
100
88
/// A type suitable for initializing this type through a result builder (e.g.
101
89
/// returns `CodeBlockItemList` for `CodeBlock`) and otherwise itself.
102
90
var builderInitializableType : Self {
103
- let buildable = nonOptional. buildable
104
- return Self (
105
- syntaxKind: BUILDER_INITIALIZABLE_TYPES [ buildable] . flatMap { $0 } ?? buildable,
91
+ Self (
92
+ syntaxKind: BUILDER_INITIALIZABLE_TYPES [ buildableBaseName] . flatMap { $0 } ?? buildableBaseName,
106
93
isOptional: isOptional
107
94
)
108
95
}
109
96
110
97
/// The type from `buildable()` without any question marks attached.
111
98
/// This is used for the `create*` methods defined in the `ExpressibleAs*` protocols.
112
99
var buildableBaseName : String {
113
- nonOptional. buildable
100
+ if isToken {
101
+ // Tokens don't have a dedicated buildable type.
102
+ return " TokenSyntax "
103
+ } else if SYNTAX_BASE_KINDS . contains ( syntaxKind) {
104
+ return " \( syntaxKind) Buildable "
105
+ } else {
106
+ return syntaxKind
107
+ }
114
108
}
115
109
116
- /// The `ExpressibleAs*` Swift type for this syntax kind. Tokens don't
117
- /// have an `ExpressibleAs*` type, so for those this method just returns
118
- /// `TokenSyntax`. If the type is optional, this terminates with a `?`.
119
- var expressibleAs : String {
110
+ /// The `ExpressibleAs*` Swift type for this syntax kind without any
111
+ /// question marks attached.
112
+ var expressibleAsBaseName : String {
120
113
if isToken {
121
114
// Tokens don't have a dedicated ExpressibleAs type.
122
- return buildable
115
+ return buildableBaseName
123
116
} else {
124
- return " ExpressibleAs \( buildable ) "
117
+ return " ExpressibleAs \( buildableBaseName ) "
125
118
}
126
119
}
127
120
121
+ /// The `ExpressibleAs*` Swift type for this syntax kind. Tokens don't
122
+ /// have an `ExpressibleAs*` type, so for those this method just returns
123
+ /// `TokenSyntax`. If the type is optional, this terminates with a `?`.
124
+ var expressibleAs : ExpressibleAsTypeBuildable {
125
+ optionalWrapped ( type: expressibleAsBaseName)
126
+ }
127
+
128
128
/// The corresponding `*Syntax` type defined in the `SwiftSyntax` module,
129
- /// which will eventually get built from `SwiftSyntaxBuilder`. If the type
130
- /// is optional, this terminates with a `?`.
131
- var syntax : String {
129
+ /// without any question marks attached.
130
+ var syntaxBaseName : String {
132
131
if syntaxKind == " Syntax " {
133
- return " Syntax \( optionalQuestionMark ) "
132
+ return " Syntax "
134
133
} else {
135
- return " \( syntaxKind) Syntax \( optionalQuestionMark ) "
134
+ return " \( syntaxKind) Syntax "
136
135
}
137
136
}
138
137
139
- /// Assuming that this is a base kind, return the corresponding `*ListBuildable` type.
140
- var listBuildable : String {
138
+ /// The corresponding `*Syntax` type defined in the `SwiftSyntax` module,
139
+ /// which will eventually get built from `SwiftSyntaxBuilder`. If the type
140
+ /// is optional, this terminates with a `?`.
141
+ var syntax : ExpressibleAsTypeBuildable {
142
+ optionalWrapped ( type: syntaxBaseName)
143
+ }
144
+
145
+ /// Assuming that this is a base kind, return the corresponding `*ListBuildable` type
146
+ /// without any question marks attached.
147
+ var listBuildableBaseName : String {
141
148
assert ( SYNTAX_BASE_KINDS . contains ( syntaxKind) , " ListBuildable types only exist for syntax base kinds " )
142
- return " \( syntaxKind) ListBuildable \( optionalQuestionMark) "
149
+ return " \( syntaxKind) ListBuildable "
150
+ }
151
+
152
+ /// Assuming that this is a base kind, return the corresponding `*ListBuildable` type.
153
+ var listBuildable : ExpressibleAsTypeBuildable {
154
+ optionalWrapped ( type: listBuildableBaseName)
143
155
}
144
156
145
157
/// Assuming that this is a collection type, the type of the result builder
146
158
/// that can be used to build the collection.
147
- var resultBuilder : String {
148
- " \( syntaxKind) Builder \( optionalQuestionMark ) "
159
+ var resultBuilder : ExpressibleAsTypeBuildable {
160
+ optionalWrapped ( type : " \( syntaxKind) Builder " )
149
161
}
150
162
151
163
/// The collection types in which this type occurs as an element.
@@ -167,7 +179,7 @@ struct SyntaxBuildableType: Hashable {
167
179
/// make the `ExpressibleAs*` of this type conform to the `ExpressibleAs*`
168
180
/// protocol of the convertible types.
169
181
var convertibleToTypes : [ Self ] {
170
- ( SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES [ buildable ] ?? [ ] )
182
+ ( SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES [ buildableBaseName ] ?? [ ] )
171
183
. map { Self ( syntaxKind: $0) }
172
184
}
173
185
@@ -220,13 +232,31 @@ struct SyntaxBuildableType: Hashable {
220
232
}
221
233
}
222
234
235
+ /// Wraps a type in an optional depending on whether `isOptional` is true.
236
+ func optionalWrapped( type: ExpressibleAsTypeBuildable ) -> ExpressibleAsTypeBuildable {
237
+ if isOptional {
238
+ return OptionalType ( wrappedType: type)
239
+ } else {
240
+ return type
241
+ }
242
+ }
243
+
244
+ /// Wraps a type in an optional chaining depending on whether `isOptional` is true.
245
+ func optionalChained( expr: ExpressibleAsExprBuildable ) -> ExpressibleAsExprBuildable {
246
+ if isOptional {
247
+ return OptionalChainingExpr ( expression: expr)
248
+ } else {
249
+ return expr
250
+ }
251
+ }
252
+
223
253
/// Generate an expression that converts a variable named `varName`
224
254
/// which is of `expressibleAs` type to an object of type `buildable`.
225
- func generateExprConvertParamTypeToStorageType( varName: String ) -> String {
255
+ func generateExprConvertParamTypeToStorageType( varName: String ) -> ExpressibleAsExprBuildable {
226
256
if isToken {
227
257
return varName
228
258
} else {
229
- return " \( varName) \( optionalQuestionMark ) . create\( buildableBaseName) () "
259
+ return FunctionCallExpr ( MemberAccessExpr ( base : optionalChained ( expr : varName) , name : " create \( buildableBaseName) " ) )
230
260
}
231
261
}
232
262
}
0 commit comments