@@ -25,7 +25,9 @@ public final class SwiftGenerator {
2525 private let version : String
2626
2727 private let swiftlintDisableAll : Bool
28-
28+
29+ private let mainActor : Bool
30+
2931 public typealias ImportFilter = ( String ) -> Bool
3032 private let importFilter : ImportFilter
3133
@@ -36,6 +38,7 @@ public final class SwiftGenerator {
3638 version: String ,
3739 testableImports: [ String ] ? ,
3840 swiftlintDisableAll: Bool ,
41+ mainActor: Bool ,
3942 importFilter: @escaping ImportFilter ) throws {
4043
4144 self . dependencyGraph = dependencyGraph
@@ -45,6 +48,7 @@ public final class SwiftGenerator {
4548 self . version = version
4649 self . testableImports = testableImports? . filter ( importFilter)
4750 self . swiftlintDisableAll = swiftlintDisableAll
51+ self . mainActor = mainActor
4852 self . importFilter = importFilter
4953 }
5054
@@ -69,6 +73,7 @@ public final class SwiftGenerator {
6973 dependencyGraph,
7074 inspector,
7175 objcPrefix,
76+ mainActor,
7277 version,
7378 testableImports,
7479 swiftlintDisableAll,
@@ -208,7 +213,9 @@ private final class MetaWeaverFile {
208213 private let testableImports : [ String ] ?
209214
210215 private let swiftlintDisableAll : Bool
211-
216+
217+ private let mainActor : Bool
218+
212219 private let importFilter : SwiftGenerator . ImportFilter
213220
214221 // Pre computed data
@@ -233,6 +240,7 @@ private final class MetaWeaverFile {
233240 init ( _ dependencyGraph: DependencyGraph ,
234241 _ inspector: Inspector ,
235242 _ objcPrefix: String ? ,
243+ _ mainActor: Bool ,
236244 _ version: String ,
237245 _ testableImports: [ String ] ? ,
238246 _ swiftlintDisableAll: Bool ,
@@ -241,6 +249,7 @@ private final class MetaWeaverFile {
241249 self . dependencyGraph = dependencyGraph
242250 self . inspector = inspector
243251 self . objcPrefix = objcPrefix
252+ self . mainActor = mainActor
244253 self . version = version
245254 self . testableImports = testableImports
246255 self . swiftlintDisableAll = swiftlintDisableAll
@@ -312,7 +321,7 @@ private final class MetaWeaverFile {
312321 dependencyResolverProxies ( ) ,
313322 publicDependencyInitExtensions ( ) ,
314323 propertyWrappers ( ) ,
315- providerClassAndFunctions ( )
324+ mainActor == true ? providerClassAndFunctionsMainActor ( ) : providerClassAndFunctions ( )
316325 ] . flatMap { $0 }
317326 }
318327
@@ -345,21 +354,40 @@ private final class MetaWeaverFile {
345354private extension MetaWeaverFile {
346355
347356 func mainDependencyContainer( ) throws -> Type {
348- return Type ( identifier: . mainDependencyContainer)
357+ var type = Type ( identifier: . mainDependencyContainer)
358+
359+ if self . mainActor == true {
360+ type = type. with ( actorName: " MainActor " )
361+ }
362+
363+ type = type
349364 . with ( objc: doesSupportObjc, prefix: objcPrefix)
350365 . adding ( inheritedType: doesSupportObjc ? . nsObject : nil )
351366 . adding ( member: EmptyLine ( ) )
352367 . adding ( member: Property ( variable: Variable ( name: " provider " ) . with ( immutable: true ) . with ( type: . provider) ) . with ( accessLevel: . private) )
353368 . adding ( member: EmptyLine ( ) )
354- . adding ( member: Function ( kind: . `init`( convenience: false , optional: false ) )
369+
370+
371+ if self . mainActor == true {
372+
373+ type = type. adding ( member: PlainCode ( code: """
374+ fileprivate init(provider: Provider? = nil) {
375+ self.provider = provider ?? Provider()
376+ }
377+ """ ) )
378+
379+ } else {
380+ type = type. adding ( member: Function ( kind: . `init`( convenience: false , optional: false ) )
355381 . with ( accessLevel: . fileprivate)
356382 . adding ( parameter: FunctionParameter ( name: " provider " , type: . provider) . with ( defaultValue: TypeIdentifier . provider. reference | . call( ) ) )
357383 . adding ( members: [
358384 Assignment ( variable: Reference . named ( . `self`) + . named( " provider " ) , value: Reference . named ( " provider " ) ) ,
359385 ( doesSupportObjc ? Reference . named ( . super) + . named( " init " ) | . call( ) : . none)
360386 ] )
361387 )
362- . adding ( member: dependencyGraph. hasPropertyWrapperAnnotations ? PlainCode ( code: """
388+ }
389+
390+ type = type. adding ( member: dependencyGraph. hasPropertyWrapperAnnotations ? PlainCode ( code: """
363391
364392private static var _dynamicResolvers = [Any]()
365393private static var _dynamicResolversLock = NSRecursiveLock()
@@ -392,6 +420,7 @@ static func _pushDynamicResolver<Resolver>(_ resolver: Resolver) {
392420 . adding ( members: try resolversImplementation ( ) )
393421 . adding ( members: settersImplementation ( ) )
394422 . adding ( members: try dependencyResolverCopyMethods ( ) )
423+ return type
395424 }
396425
397426 func propertyWrappers( ) throws -> [ FileBodyMember ] {
@@ -1305,6 +1334,109 @@ private extension MetaWeaverFile {
13051334 }
13061335 }
13071336
1337+ func providerClassAndFunctionsMainActor( ) throws -> [ FileBodyMember ] {
1338+ return [
1339+ EmptyLine ( ) ,
1340+ PlainCode ( code: """
1341+ // MARK: - Fatal Error
1342+
1343+ extension MainDependencyContainer {
1344+
1345+ static var onFatalError: (String, StaticString, UInt) -> Never = { message, file, line in
1346+ Swift.fatalError(message, file: file, line: line)
1347+ }
1348+
1349+ fileprivate static func fatalError(file: StaticString = #file, line: UInt = #line) -> Never {
1350+ onFatalError( " Invalid memory graph. This is never suppose to happen. Please file a ticket at https://github.com/scribd/Weaver " , file, line)
1351+ }
1352+ }
1353+
1354+ // MARK: - Provider
1355+
1356+ @MainActor private final class Provider {
1357+
1358+ typealias ParametersCopier = (Provider) -> Void
1359+ typealias Builder<T> = (ParametersCopier?) -> T
1360+
1361+ private(set) var builders: Dictionary<String, Any>
1362+
1363+ init(builders: Dictionary<String, Any> = [:]) {
1364+ self.builders = builders
1365+ }
1366+ }
1367+
1368+ @MainActor private extension Provider {
1369+
1370+ func addBuilders(_ builders: Dictionary<String, Any>) {
1371+ builders.forEach { key, value in
1372+ self.builders[key] = value
1373+ }
1374+ }
1375+
1376+ func setBuilder<T>(_ name: String, _ builder: @escaping Builder<T>) {
1377+ builders[name] = builder
1378+ }
1379+
1380+ func getBuilder<T>(_ name: String, _ type: T.Type) -> Builder<T> {
1381+ guard let builder = builders[name] as? Builder<T> else {
1382+ return Provider.fatalBuilder()
1383+ }
1384+ return builder
1385+ }
1386+
1387+ func copy() -> Provider {
1388+ return Provider(builders: builders)
1389+ }
1390+ }
1391+
1392+ private extension Provider {
1393+
1394+ static func valueBuilder<T>(_ value: T) -> Builder<T> {
1395+ return { _ in
1396+ return value
1397+ }
1398+ }
1399+
1400+ static func weakOptionalValueBuilder<T>(_ value: Optional<T>) -> Builder<Optional<T>> where T: AnyObject {
1401+ return { [weak value] _ in
1402+ return value
1403+ }
1404+ }
1405+
1406+ static func lazyBuilder<T>(_ builder: @escaping Builder<T>) -> Builder<T> {
1407+ var _value: T?
1408+ return { copyParameters in
1409+ if let value = _value {
1410+ return value
1411+ }
1412+ let value = builder(copyParameters)
1413+ _value = value
1414+ return value
1415+ }
1416+ }
1417+
1418+ static func weakLazyBuilder<T>(_ builder: @escaping Builder<T>) -> Builder<T> where T: AnyObject {
1419+ weak var _value: T?
1420+ return { copyParameters in
1421+ if let value = _value {
1422+ return value
1423+ }
1424+ let value = builder(copyParameters)
1425+ _value = value
1426+ return value
1427+ }
1428+ }
1429+
1430+ @MainActor static func fatalBuilder<T>() -> Builder<T> {
1431+ return { _ in
1432+ MainDependencyContainer.fatalError()
1433+ }
1434+ }
1435+ }
1436+ """ )
1437+ ]
1438+ }
1439+
13081440 func providerClassAndFunctions( ) throws -> [ FileBodyMember ] {
13091441 return [
13101442 EmptyLine ( ) ,
0 commit comments