@@ -72,31 +72,13 @@ public final class SchemaBuilder {
7272 * Thread Safety: This is a thread-safe operation. Do NOT modify the returned
7373 * Schema objects.
7474 */
75- func resolve ( _ modelTypes: [ any PersistentModel . Type ] )
75+ func lookupAllEntities ( for modelTypes: [ any PersistentModel . Type ] )
7676 -> [ NSEntityDescription ]
7777 {
78- var entities = [ NSEntityDescription ] ( )
79- var entitiesByName = [ String : NSEntityDescription ] ( )
78+ var entities = [ NSEntityDescription ] ( )
8079
8180 lock. lock ( )
82- process ( modelTypes)
83-
84- for modelType in modelTypes {
85- guard let entity = lookupEntity ( modelType) else {
86- fatalError (
87- """
88- Could not construct `NSEntityDescription` for `PersistentModel` type
89-
90- \( modelType)
91-
92- """
93- )
94- }
95- // Return just the ones we need.
96- entities. append ( entity)
97- precondition ( entity. name != nil , " Entity w/o a name? \( entity) " )
98- if let name = entity. name { entitiesByName [ name] = entity }
99- }
81+ process ( modelTypes, entities: & entities)
10082 lock. unlock ( )
10183
10284 return entities
@@ -115,10 +97,11 @@ public final class SchemaBuilder {
11597 public func _entity< M> ( for modelType: M . Type ) -> NSEntityDescription
11698 where M: PersistentModel
11799 {
100+ var entities = [ NSEntityDescription ] ( )
118101 let modelTypes = [ modelType ]
119102 lock. lock ( )
120103 let entity = lookupEntity ( modelType) ?? {
121- process ( modelTypes)
104+ process ( modelTypes, entities : & entities )
122105 guard let entity = lookupEntity ( modelType) else {
123106 fatalError (
124107 " Could not construct Entity for PersistentModel type: \( modelType) " )
@@ -132,29 +115,33 @@ public final class SchemaBuilder {
132115
133116 // MARK: - Things that run in the lock!
134117
135- private func process( _ modelTypes: [ any PersistentModel . Type ] ) {
118+ private func process( _ modelTypes: [ any PersistentModel . Type ] ,
119+ entities: inout [ NSEntityDescription ] )
120+ {
136121 // Note: This is called recursively
137122 var allFrozen = false
138123
139124 // Create the basic entity and property data
140125 for modelType in modelTypes {
141126 guard !isFrozen( modelType) else { continue }
142127 allFrozen = false
143- /* newEntity */ _ = processModel ( modelType)
128+ if let newEntity = processModel ( modelType) {
129+ entities. append ( newEntity)
130+ }
144131 }
145132 if allFrozen { return } // all have been processed already
146133
147134 // TBD: The following does too much work, we might only need the
148135 // most of those on the "new models"
149136
150137 // This recurses into `process`, if necessary.
151- discoverTargetTypes ( entitiesByType . values )
138+ discoverTargetTypes ( in : entities , allEntities : & entities )
152139
153140 // Collect destination entity names in relships based on the modelType!
154- fillDestinationEntityNamesInRelationships ( entitiesByType . values )
141+ fillDestinationEntityNamesInRelationships ( entities )
155142
156143 // Lookup inverse relationships
157- fillInverseRelationshipData ( entitiesByType . values )
144+ fillInverseRelationshipData ( entities )
158145
159146 frozenTypes. formUnion ( entitiesByType. keys)
160147 }
@@ -164,21 +151,26 @@ public final class SchemaBuilder {
164151 * model type they point to is already tracked as an entity.
165152 * Recurses until all relationships have been processed.
166153 */
167- private func discoverTargetTypes< S > ( _ entities: S )
168- where S : Sequence , S . Element == NSEntityDescription
154+ private func discoverTargetTypes( in entities: [ NSEntityDescription ] ,
155+ allEntities : inout [ NSEntityDescription ] )
169156 {
170157 var newEntities = [ NSEntityDescription ] ( )
171158 for entity in entities {
172159 for relationship in entity. relationships {
173- guard let targetType = relationship. modelType else { continue }
174- if let newEntity = processModel ( targetType ) {
175- newEntities . append ( newEntity )
160+ guard let targetType = relationship. modelType else {
161+ assertionFailure ( " Missing type for relationship \( relationship ) " )
162+ continue
176163 }
164+ // This returns nil if the model is already processed.
165+ guard let newEntity = processModel ( targetType) else { continue }
166+
167+ allEntities. append ( newEntity)
168+ newEntities. append ( newEntity)
177169 }
178170 }
179171
180172 if !newEntities. isEmpty { // recurse if necessary
181- discoverTargetTypes ( newEntities)
173+ discoverTargetTypes ( in : newEntities, allEntities : & allEntities )
182174 }
183175 }
184176
0 commit comments