diff --git a/Sources/ManagedModels/SchemaGeneration/SchemaBuilder.swift b/Sources/ManagedModels/SchemaGeneration/SchemaBuilder.swift index ccc1b46..c5e0ff5 100644 --- a/Sources/ManagedModels/SchemaGeneration/SchemaBuilder.swift +++ b/Sources/ManagedModels/SchemaGeneration/SchemaBuilder.swift @@ -130,18 +130,20 @@ public final class SchemaBuilder { } assertionFailure("Type frozen, but no entity found?") } + allFrozen = false if let newEntity = processModel(modelType) { entities.append(newEntity) } } - if allFrozen { return } // all have been processed already // TBD: The following does too much work, we might only need the // most of those on the "new models" // This recurses into `process`, if necessary. discoverTargetTypes(in: entities, allEntities: &entities) + + if allFrozen { return } // Collect destination entity names in relships based on the modelType! fillDestinationEntityNamesInRelationships(entities) @@ -168,7 +170,16 @@ public final class SchemaBuilder { continue } // This returns nil if the model is already processed. - guard let newEntity = processModel(targetType) else { continue } + guard let newEntity = processModel(targetType) else { + guard let existingEntity = lookupEntity(targetType) else { + assertionFailure("Type marked as processed, but no entity?") + continue + } + if !allEntities.contains(where: { $0 === existingEntity }) { + allEntities.append(existingEntity) + } + continue + } allEntities.append(newEntity) newEntities.append(newEntity) diff --git a/Tests/ManagedModelTests/SchemaGenerationTests.swift b/Tests/ManagedModelTests/SchemaGenerationTests.swift index bdcb725..4e51543 100644 --- a/Tests/ManagedModelTests/SchemaGenerationTests.swift +++ b/Tests/ManagedModelTests/SchemaGenerationTests.swift @@ -193,4 +193,33 @@ final class SchemaGenerationTests: XCTestCase { XCTAssertNotNil(mom.entitiesByName["Person"]) XCTAssertNotNil(mom.entitiesByName["Address"]) } + + func testDuplicateGeneration() throws { + let cache = SchemaBuilder() + + try autoreleasepool { + let entities = cache.lookupAllEntities(for: [ + Fixtures.PersonAddressSchema.Person.self + ]) + XCTAssertEqual(entities.count, 2) + + let address = try XCTUnwrap( + entities.first(where: { $0.name == "Address" }) + ) + XCTAssertEqual(address.attributes.count, 2) + } + + // second run + try autoreleasepool { + let entities = cache.lookupAllEntities(for: [ + Fixtures.PersonAddressSchema.Person.self + ]) + XCTAssertEqual(entities.count, 2) + + let address = try XCTUnwrap( + entities.first(where: { $0.name == "Address" }) + ) + XCTAssertEqual(address.attributes.count, 2) + } + } }