1
1
/*
2
2
This source file is part of the Swift.org open source project
3
3
4
- Copyright (c) 2022 Apple Inc. and the Swift project authors
4
+ Copyright (c) 2022-2023 Apple Inc. and the Swift project authors
5
5
Licensed under Apache License v2.0 with Runtime Library Exception
6
6
7
7
See https://swift.org/LICENSE.txt for license information
@@ -91,6 +91,43 @@ public struct DirectiveArgumentWrapped<Value>: _DirectiveArgumentProtocol {
91
91
fatalError ( )
92
92
}
93
93
94
+ // Expected argument configurations
95
+
96
+ @_disfavoredOverload
97
+ init (
98
+ wrappedValue: Value ,
99
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
100
+ parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
101
+ allowedValues: [ String ] ? = nil ,
102
+ hiddenFromDocumentation: Bool = false
103
+ ) {
104
+ self . init (
105
+ value: wrappedValue,
106
+ name: name,
107
+ transform: parseArgument,
108
+ allowedValues: allowedValues,
109
+ required: nil ,
110
+ hiddenFromDocumentation: hiddenFromDocumentation
111
+ )
112
+ }
113
+
114
+ @_disfavoredOverload
115
+ init (
116
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
117
+ parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
118
+ allowedValues: [ String ] ? = nil ,
119
+ hiddenFromDocumentation: Bool = false
120
+ ) {
121
+ self . init (
122
+ value: nil ,
123
+ name: name,
124
+ transform: parseArgument,
125
+ allowedValues: allowedValues,
126
+ required: nil ,
127
+ hiddenFromDocumentation: hiddenFromDocumentation
128
+ )
129
+ }
130
+
94
131
private init (
95
132
value: Value ? ,
96
133
name: _DirectiveArgumentName ,
@@ -99,32 +136,37 @@ public struct DirectiveArgumentWrapped<Value>: _DirectiveArgumentProtocol {
99
136
required: Bool ? ,
100
137
hiddenFromDocumentation: Bool
101
138
) {
139
+ let required = required ?? ( value == nil )
140
+
102
141
self . name = name
103
142
self . defaultValue = value
104
- if let optionallyWrappedValue = Value . self as? OptionallyWrapped . Type {
105
- self . typeDisplayName = String ( describing: optionallyWrappedValue. baseType ( ) ) + " ? "
106
- } else {
107
- self . typeDisplayName = String ( describing: Value . self)
108
- }
109
-
110
- if let required = required {
111
- self . required = required
112
- } else {
113
- self . required = defaultValue == nil
114
- }
115
-
143
+ self . typeDisplayName = typeDisplayNameDescription ( defaultValue: value, required: required)
116
144
self . parseArgument = transform
117
145
self . allowedValues = allowedValues
146
+ self . required = required
118
147
self . hiddenFromDocumentation = hiddenFromDocumentation
119
148
}
120
149
150
+ func setProperty< T> (
151
+ on containingDirective: T ,
152
+ named propertyName: String ,
153
+ to any: Any
154
+ ) where T: AutomaticDirectiveConvertible {
155
+ let path = T . keyPaths [ propertyName] as! ReferenceWritableKeyPath < T , DirectiveArgumentWrapped < Value > >
156
+ let wrappedValuePath = path. appending ( path: \Self . parsedValue)
157
+ containingDirective [ keyPath: wrappedValuePath] = any as! Value ?
158
+ }
159
+
160
+ // Warnings and errors for unexpected argument configurations
161
+
121
162
@_disfavoredOverload
163
+ @available ( * , deprecated, message: " Use an optional type or a default value to control whether or not a directive argument is required. " )
122
164
init (
123
165
wrappedValue: Value ,
124
166
name: _DirectiveArgumentName = . inferredFromPropertyName,
125
167
parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
126
168
allowedValues: [ String ] ? = nil ,
127
- required: Bool ? = nil ,
169
+ required: Bool ,
128
170
hiddenFromDocumentation: Bool = false
129
171
) {
130
172
self . init (
@@ -138,11 +180,12 @@ public struct DirectiveArgumentWrapped<Value>: _DirectiveArgumentProtocol {
138
180
}
139
181
140
182
@_disfavoredOverload
183
+ @available ( * , deprecated, message: " Use an optional type or a default value to control whether or not a directive argument is required. " )
141
184
init (
142
185
name: _DirectiveArgumentName = . inferredFromPropertyName,
143
186
parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
144
187
allowedValues: [ String ] ? = nil ,
145
- required: Bool ? = nil ,
188
+ required: Bool ,
146
189
hiddenFromDocumentation: Bool = false
147
190
) {
148
191
self . init (
@@ -154,26 +197,20 @@ public struct DirectiveArgumentWrapped<Value>: _DirectiveArgumentProtocol {
154
197
hiddenFromDocumentation: hiddenFromDocumentation
155
198
)
156
199
}
157
-
158
- func setProperty< T> (
159
- on containingDirective: T ,
160
- named propertyName: String ,
161
- to any: Any
162
- ) where T: AutomaticDirectiveConvertible {
163
- let path = T . keyPaths [ propertyName] as! ReferenceWritableKeyPath < T , DirectiveArgumentWrapped < Value > >
164
- let wrappedValuePath = path. appending ( path: \Self . parsedValue)
165
- containingDirective [ keyPath: wrappedValuePath] = any as! Value ?
166
- }
167
200
}
168
201
169
202
extension DirectiveArgumentWrapped where Value: DirectiveArgumentValueConvertible {
203
+ // Expected argument configurations
204
+
205
+ @_disfavoredOverload
170
206
init (
171
207
name: _DirectiveArgumentName = . inferredFromPropertyName,
172
208
hiddenFromDocumentation: Bool = false
173
209
) {
174
210
self . init ( value: nil , name: name, hiddenFromDocumentation: hiddenFromDocumentation)
175
211
}
176
212
213
+ @_disfavoredOverload
177
214
init (
178
215
wrappedValue: Value ,
179
216
name: _DirectiveArgumentName = . inferredFromPropertyName,
@@ -182,53 +219,169 @@ extension DirectiveArgumentWrapped where Value: DirectiveArgumentValueConvertibl
182
219
self . init ( value: wrappedValue, name: name, hiddenFromDocumentation: hiddenFromDocumentation)
183
220
}
184
221
185
- private init (
186
- value: Value ? ,
187
- name: _DirectiveArgumentName ,
188
- hiddenFromDocumentation: Bool
189
- ) {
222
+ private init ( value: Value ? , name: _DirectiveArgumentName , hiddenFromDocumentation: Bool ) {
190
223
self . name = name
191
224
self . defaultValue = value
192
225
193
- if let value = value {
194
- self . typeDisplayName = String ( describing: Value . self) + " = " + String( describing: value)
195
- } else {
196
- self . typeDisplayName = String ( describing: Value . self)
197
- }
198
-
226
+ let required = value == nil
227
+ self . typeDisplayName = typeDisplayNameDescription ( defaultValue: value, required: required)
199
228
self . parseArgument = { _, argument in
200
229
Value . init ( rawDirectiveArgumentValue: argument)
201
230
}
202
231
self . allowedValues = Value . allowedValues ( )
203
- self . required = value == nil
232
+ self . required = required
204
233
self . hiddenFromDocumentation = hiddenFromDocumentation
205
234
}
235
+
236
+ // Warnings and errors for unexpected argument configurations
237
+
238
+ @_disfavoredOverload
239
+ @available ( * , unavailable, message: " Directive argument of non-optional types without default value need to be required. Use an optional type or provide a default value to make this argument non-required. " )
240
+ init ( name: _DirectiveArgumentName = . inferredFromPropertyName, required: Bool ) {
241
+ fatalError ( )
242
+ }
206
243
}
207
244
208
- protocol OptionallyWrappedDirectiveArgumentValueConvertible : OptionallyWrapped { }
209
- extension Optional : OptionallyWrappedDirectiveArgumentValueConvertible where Wrapped: DirectiveArgumentValueConvertible { }
210
- extension DirectiveArgumentWrapped where Value: OptionallyWrappedDirectiveArgumentValueConvertible {
245
+ protocol _OptionalDirectiveArgument {
246
+ associatedtype WrappedArgument
247
+ var wrapped : WrappedArgument ? { get }
248
+ init ( wrapping: WrappedArgument ? )
249
+ }
250
+ extension Optional : _OptionalDirectiveArgument {
251
+ typealias WrappedArgument = Wrapped
252
+ var wrapped : WrappedArgument ? {
253
+ switch self {
254
+ case . some( let value) :
255
+ return value
256
+ case . none: return
257
+ nil
258
+ }
259
+ }
260
+ init ( wrapping: WrappedArgument ? ) {
261
+ if let wrapped = wrapping {
262
+ self = . some( wrapped)
263
+ } else {
264
+ self = . none
265
+ }
266
+ }
267
+ }
268
+
269
+ extension DirectiveArgumentWrapped where Value: _OptionalDirectiveArgument , Value. WrappedArgument: DirectiveArgumentValueConvertible {
270
+
271
+ // When the wrapped value is DirectiveArgumentValueConvertible, additional arguments may be omitted
272
+
273
+ init (
274
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
275
+ hiddenFromDocumentation: Bool = false
276
+ ) {
277
+ self = . init( value: nil , name: name, hiddenFromDocumentation: hiddenFromDocumentation)
278
+ }
279
+
280
+ @_disfavoredOverload
211
281
init (
212
282
wrappedValue: Value ,
213
283
name: _DirectiveArgumentName = . inferredFromPropertyName,
214
- required: Bool = false ,
215
284
hiddenFromDocumentation: Bool = false
216
285
) {
217
- let argumentValueType = Value . baseType ( ) as! DirectiveArgumentValueConvertible . Type
286
+ self = . init( value: wrappedValue, name: name, hiddenFromDocumentation: hiddenFromDocumentation)
287
+ }
288
+
289
+ private init (
290
+ value: Value ? ,
291
+ name: _DirectiveArgumentName ,
292
+ hiddenFromDocumentation: Bool
293
+ ) {
294
+ let argumentValueType = Value . WrappedArgument. self
218
295
296
+ self = . init(
297
+ value: value,
298
+ name: name,
299
+ parseArgument: { _, argument in
300
+ Value ( wrapping: argumentValueType. init ( rawDirectiveArgumentValue: argument) )
301
+ } ,
302
+ allowedValues: argumentValueType. allowedValues ( ) ,
303
+ hiddenFromDocumentation: hiddenFromDocumentation
304
+ )
305
+ }
306
+ }
307
+
308
+ extension DirectiveArgumentWrapped where Value: _OptionalDirectiveArgument {
309
+
310
+ // Expected argument configurations
311
+
312
+ @_disfavoredOverload
313
+ init (
314
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
315
+ parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
316
+ allowedValues: [ String ] ? = nil ,
317
+ hiddenFromDocumentation: Bool = false
318
+ ) {
319
+ self = . init( value: nil , name: name, parseArgument: parseArgument, allowedValues: allowedValues, hiddenFromDocumentation: hiddenFromDocumentation)
320
+ }
321
+
322
+ @_disfavoredOverload
323
+ init (
324
+ wrappedValue: Value ,
325
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
326
+ parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
327
+ allowedValues: [ String ] ? = nil ,
328
+ hiddenFromDocumentation: Bool = false
329
+ ) {
330
+ self = . init( value: wrappedValue, name: name, parseArgument: parseArgument, allowedValues: allowedValues, hiddenFromDocumentation: hiddenFromDocumentation)
331
+ }
332
+
333
+ private init (
334
+ value: Value ? ,
335
+ name: _DirectiveArgumentName ,
336
+ parseArgument: @escaping ( _ bundle: DocumentationBundle , _ argumentValue: String ) -> ( Value ? ) ,
337
+ allowedValues: [ String ] ? = nil ,
338
+ hiddenFromDocumentation: Bool = false
339
+ ) {
219
340
self . name = name
220
- self . defaultValue = wrappedValue
221
- if required {
222
- self . typeDisplayName = String ( describing: argumentValueType)
223
- } else {
224
- self . typeDisplayName = String ( describing: argumentValueType) + " ? "
225
- }
226
-
227
- self . parseArgument = { _, argument in
228
- argumentValueType. init ( rawDirectiveArgumentValue: argument)
229
- }
230
- self . allowedValues = argumentValueType. allowedValues ( )
231
- self . required = required
341
+ self . defaultValue = value
342
+ self . typeDisplayName = typeDisplayNameDescription ( optionalDefaultValue: value, required: false )
343
+ self . parseArgument = parseArgument
344
+ self . allowedValues = allowedValues
345
+ self . required = false
232
346
self . hiddenFromDocumentation = hiddenFromDocumentation
233
347
}
348
+
349
+ // Warnings and errors for unexpected argument configurations
350
+
351
+ @_disfavoredOverload
352
+ @available ( * , unavailable, message: " Directive arguments with an Optional type shouldn't be required. " )
353
+ init (
354
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
355
+ required: Bool ,
356
+ hiddenFromDocumentation: Bool = false
357
+ ) {
358
+ fatalError ( )
359
+ }
360
+
361
+ @_disfavoredOverload
362
+ @available ( * , unavailable, message: " Directive arguments with an Optional type shouldn't be required. " )
363
+ init (
364
+ wrappedValue: Value ,
365
+ name: _DirectiveArgumentName = . inferredFromPropertyName,
366
+ required: Bool ,
367
+ hiddenFromDocumentation: Bool = false
368
+ ) {
369
+ fatalError ( )
370
+ }
371
+ }
372
+
373
+ private func typeDisplayNameDescription< Value> ( defaultValue: Value ? , required: Bool ) -> String {
374
+ var name = " \( Value . self) "
375
+
376
+ if let defaultValue = defaultValue {
377
+ name += " = \( defaultValue) "
378
+ } else if !required {
379
+ name += " ? "
380
+ }
381
+
382
+ return name
383
+ }
384
+
385
+ private func typeDisplayNameDescription< Value: _OptionalDirectiveArgument > ( optionalDefaultValue: Value ? , required: Bool ) -> String {
386
+ return typeDisplayNameDescription ( defaultValue: optionalDefaultValue? . wrapped, required: required)
234
387
}
0 commit comments