@@ -22,6 +22,7 @@ public class ApolloCodegen {
22
22
case invalidSchemaName( _ name: String , message: String )
23
23
case targetNameConflict( name: String )
24
24
case typeNameConflict( name: String , conflictingName: String , containingObject: String )
25
+ case failedToComputeOperationIdentifier( type: String , name: String , error: Swift . Error )
25
26
26
27
public var errorDescription : String ? {
27
28
switch self {
@@ -64,6 +65,8 @@ public class ApolloCodegen {
64
65
Recommend using a field alias for one of these fields to resolve this conflict. \
65
66
For more info see: https://www.apollographql.com/docs/ios/troubleshooting/codegen-troubleshooting#typenameconflict
66
67
"""
68
+ case let . failedToComputeOperationIdentifier( type, name, error) :
69
+ return " Received failure while computing operation identifier for \( type) named ' \( name) ', Error: \( error. localizedDescription) "
67
70
}
68
71
}
69
72
}
@@ -91,6 +94,9 @@ public class ApolloCodegen {
91
94
92
95
}
93
96
97
+ /// A `nil` result is treated as a cancellation, and the default operationIdentifier is used
98
+ public typealias ComputeOperationIdentifier = ( any IROperation , @escaping ( Result < String , Swift . Error > ? ) -> Void ) -> Void
99
+
94
100
/// Executes the code generation engine with a specified configuration.
95
101
///
96
102
/// - Parameters:
@@ -103,16 +109,18 @@ public class ApolloCodegen {
103
109
public static func build(
104
110
with configuration: ApolloCodegenConfiguration ,
105
111
withRootURL rootURL: URL ? = nil ,
106
- itemsToGenerate: ItemsToGenerate = [ . code]
112
+ itemsToGenerate: ItemsToGenerate = [ . code] ,
113
+ computeOperationIdentifier: ComputeOperationIdentifier ? = nil
107
114
) throws {
108
- try build ( with: configuration, rootURL: rootURL, itemsToGenerate: itemsToGenerate)
115
+ try build ( with: configuration, rootURL: rootURL, itemsToGenerate: itemsToGenerate, computeOperationIdentifier : computeOperationIdentifier )
109
116
}
110
117
111
118
internal static func build(
112
119
with configuration: ApolloCodegenConfiguration ,
113
120
rootURL: URL ? = nil ,
114
121
fileManager: ApolloFileManager = . default,
115
- itemsToGenerate: ItemsToGenerate
122
+ itemsToGenerate: ItemsToGenerate ,
123
+ computeOperationIdentifier: ComputeOperationIdentifier ? = nil
116
124
) throws {
117
125
118
126
let configContext = ConfigurationContext (
@@ -131,29 +139,34 @@ public class ApolloCodegen {
131
139
132
140
let ir = IR ( compilationResult: compilationResult)
133
141
134
- var existingGeneratedFilePaths : Set < String > ?
135
-
136
- if itemsToGenerate . contains ( . code ) && configuration . options . pruneGeneratedFiles {
137
- existingGeneratedFilePaths = try findExistingGeneratedFilePaths (
142
+ let generate : ( ) throws -> Void = {
143
+ try generateFiles (
144
+ compilationResult : compilationResult ,
145
+ ir : ir ,
138
146
config: configContext,
139
- fileManager: fileManager
147
+ fileManager: fileManager,
148
+ itemsToGenerate: itemsToGenerate,
149
+ computeOperationIdentifier: computeOperationIdentifier
140
150
)
141
151
}
142
152
143
- try generateFiles (
144
- compilationResult: compilationResult,
145
- ir: ir,
146
- config: configContext,
147
- fileManager: fileManager,
148
- itemsToGenerate: itemsToGenerate
149
- )
150
-
151
- if var existingGeneratedFilePaths {
153
+ let generateWithPruning : ( ) throws -> Void = {
154
+ var existingGeneratedFilePaths = try findExistingGeneratedFilePaths (
155
+ config: configContext,
156
+ fileManager: fileManager
157
+ )
158
+ try generate ( )
152
159
try deleteExtraneousGeneratedFiles (
153
160
from: & existingGeneratedFilePaths,
154
161
afterCodeGenerationUsing: fileManager
155
162
)
156
163
}
164
+
165
+ if itemsToGenerate. contains ( . code) && configuration. options. pruneGeneratedFiles {
166
+ try generateWithPruning ( )
167
+ } else {
168
+ try generate ( )
169
+ }
157
170
}
158
171
159
172
// MARK: Internal
@@ -412,7 +425,8 @@ public class ApolloCodegen {
412
425
ir: IR ,
413
426
config: ConfigurationContext ,
414
427
fileManager: ApolloFileManager = . default,
415
- itemsToGenerate: ItemsToGenerate
428
+ itemsToGenerate: ItemsToGenerate ,
429
+ computeOperationIdentifier: ComputeOperationIdentifier ? = nil
416
430
) throws {
417
431
418
432
if itemsToGenerate. contains ( . code) {
@@ -431,9 +445,40 @@ public class ApolloCodegen {
431
445
operationIDsFileGenerator = OperationManifestFileGenerator ( config: config)
432
446
}
433
447
434
- for operation in compilationResult. operations {
448
+ let irOperations = compilationResult. operations. map { ir. build ( operation: $0) }
449
+ var results = [ Result < String , Swift . Error > ? ] ( repeating: nil , count: irOperations. count)
450
+
451
+ if let computeOperationIdentifier {
452
+ let dispatchGroup = DispatchGroup ( )
453
+ DispatchQueue . concurrentPerform ( iterations: irOperations. count) { index in
454
+ let irOperation = irOperations [ index]
455
+ var sources : [ String ] = [ irOperation. definition. source. convertedToSingleLine ( ) ]
456
+ for fragment in irOperation. referencedFragments {
457
+ sources. append ( fragment. definition. source. convertedToSingleLine ( ) )
458
+ }
459
+ dispatchGroup. enter ( )
460
+ computeOperationIdentifier ( irOperation) { result in
461
+ results [ index] = result
462
+ dispatchGroup. leave ( )
463
+ }
464
+ }
465
+ dispatchGroup. wait ( )
466
+ }
467
+
468
+ for (index, irOperation) in irOperations. enumerated ( ) {
435
469
try autoreleasepool {
436
- let irOperation = ir. build ( operation: operation)
470
+ if let result = results [ index] {
471
+ switch result {
472
+ case . success( let operationIdentifier) :
473
+ irOperation. operationIdentifier = operationIdentifier
474
+ case . failure( let error) :
475
+ throw Error . failedToComputeOperationIdentifier (
476
+ type: irOperation. definition. operationType. rawValue,
477
+ name: irOperation. definition. name,
478
+ error: error
479
+ )
480
+ }
481
+ }
437
482
438
483
if itemsToGenerate. contains ( . code) {
439
484
try validateTypeConflicts ( for: irOperation. rootField. selectionSet, with: config, in: irOperation. definition. name)
@@ -611,4 +656,24 @@ public class ApolloCodegen {
611
656
612
657
}
613
658
659
+ public protocol IROperation : AnyObject {
660
+ var filePath : String { get }
661
+ var name : String { get }
662
+ var source : String { get }
663
+ var type : CompilationResult . OperationType { get }
664
+ }
665
+
666
+ extension IR . Operation : IROperation {
667
+ public var filePath : String { definition. filePath }
668
+ public var name : String { definition. name }
669
+ public var source : String {
670
+ var sources : [ String ] = [ definition. source. convertedToSingleLine ( ) ]
671
+ for fragment in referencedFragments {
672
+ sources. append ( fragment. definition. source. convertedToSingleLine ( ) )
673
+ }
674
+ return sources. joined ( separator: " \n " )
675
+ }
676
+ public var type : CompilationResult . OperationType { definition. operationType }
677
+ }
678
+
614
679
#endif
0 commit comments