From 4e76056979c171905fffc7bae2d3dd5050d734d6 Mon Sep 17 00:00:00 2001 From: Anthony Miller Date: Mon, 6 Jan 2025 12:20:40 -0800 Subject: [PATCH] Prevent merging of fragment fields into selection tree if disabled --- .../IRBuilderTestWrapper.swift | 10 +++++-- .../ApolloCodegenLib/ApolloCodegen.swift | 13 ++++++++-- .../Sources/IR/IR+RootFieldBuilder.swift | 26 ++++++++++++++----- apollo-ios-codegen/Sources/IR/IRBuilder.swift | 12 ++++++--- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Tests/ApolloCodegenInternalTestHelpers/IRBuilderTestWrapper.swift b/Tests/ApolloCodegenInternalTestHelpers/IRBuilderTestWrapper.swift index 8cf1c1bb1..d8848aecf 100644 --- a/Tests/ApolloCodegenInternalTestHelpers/IRBuilderTestWrapper.swift +++ b/Tests/ApolloCodegenInternalTestHelpers/IRBuilderTestWrapper.swift @@ -24,7 +24,10 @@ public class IRBuilderTestWrapper { operation operationDefinition: CompilationResult.OperationDefinition, mergingStrategy: MergedSelections.MergingStrategy = .all ) async -> IRTestWrapper { - let operation = await irBuilder.build(operation: operationDefinition) + let operation = await irBuilder.build( + operation: operationDefinition, + mergingNamedFragmentFields: mergingStrategy.contains(.namedFragments) + ) return IRTestWrapper( irObject: operation, computedSelectionSetCache: .init( @@ -38,7 +41,10 @@ public class IRBuilderTestWrapper { fragment fragmentDefinition: CompilationResult.FragmentDefinition, mergingStrategy: MergedSelections.MergingStrategy = .all ) async -> IRTestWrapper { - let fragment = await irBuilder.build(fragment: fragmentDefinition) + let fragment = await irBuilder.build( + fragment: fragmentDefinition, + mergingNamedFragmentFields: mergingStrategy.contains(.namedFragments) + ) return IRTestWrapper( irObject: fragment, computedSelectionSetCache: .init( diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift index d34b527fd..31e5033b8 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift @@ -295,10 +295,16 @@ public class ApolloCodegen { ir: IRBuilder, fileManager: ApolloFileManager ) async throws -> NonFatalErrors { + let mergeNamedFragmentFields = config.experimentalFeatures.fieldMerging.options + .contains(.namedFragments) + return try await nonFatalErrorCollectingTaskGroup() { group in for fragment in fragments { group.addTask { - let irFragment = await ir.build(fragment: fragment) + let irFragment = await ir.build( + fragment: fragment, + mergingNamedFragmentFields: mergeNamedFragmentFields + ) let errors = try await FragmentFileGenerator(irFragment: irFragment, config: self.config) .generate(forConfig: self.config, fileManager: fileManager) @@ -310,7 +316,10 @@ public class ApolloCodegen { group.addTask { async let identifier = self.operationIdentifierFactory.identifier(for: operation) - let irOperation = await ir.build(operation: operation) + let irOperation = await ir.build( + operation: operation, + mergingNamedFragmentFields: mergeNamedFragmentFields + ) let errors = try await OperationFileGenerator( irOperation: irOperation, diff --git a/apollo-ios-codegen/Sources/IR/IR+RootFieldBuilder.swift b/apollo-ios-codegen/Sources/IR/IR+RootFieldBuilder.swift index 9ce0218a9..4d416a568 100644 --- a/apollo-ios-codegen/Sources/IR/IR+RootFieldBuilder.swift +++ b/apollo-ios-codegen/Sources/IR/IR+RootFieldBuilder.swift @@ -16,23 +16,34 @@ class RootFieldBuilder { static func buildRootEntityField( forRootField rootField: CompilationResult.Field, onRootEntity rootEntity: Entity, - inIR ir: IRBuilder + inIR ir: IRBuilder, + mergingNamedFragmentFields: Bool ) async -> Result { - return await RootFieldBuilder(ir: ir, rootEntity: rootEntity) - .build(rootField: rootField) + return await RootFieldBuilder( + ir: ir, + rootEntity: rootEntity, + mergeInNamedFragmentFields: mergingNamedFragmentFields + ) + .build(rootField: rootField) } private let ir: IRBuilder private let rootEntity: Entity private let entityStorage: DefinitionEntityStorage + private let mergeInNamedFragmentFields: Bool private var referencedFragments: ReferencedFragments = [] @IsEverTrue private var containsDeferredFragment: Bool private var schema: Schema { ir.schema } - private init(ir: IRBuilder, rootEntity: Entity) { + private init( + ir: IRBuilder, + rootEntity: Entity, + mergeInNamedFragmentFields: Bool + ) { self.ir = ir self.rootEntity = rootEntity + self.mergeInNamedFragmentFields = mergeInNamedFragmentFields self.entityStorage = DefinitionEntityStorage(rootEntity: rootEntity) } @@ -398,7 +409,10 @@ class RootFieldBuilder { spreadIntoParentWithTypePath parentTypeInfo: SelectionSet.TypeInfo, deferCondition: CompilationResult.DeferCondition? = nil ) async -> NamedFragmentSpread { - let fragment = await ir.build(fragment: fragmentSpread.fragment) + let fragment = await ir.build( + fragment: fragmentSpread.fragment, + mergingNamedFragmentFields: self.mergeInNamedFragmentFields + ) referencedFragments.append(fragment) referencedFragments.append(contentsOf: fragment.referencedFragments) @@ -425,7 +439,7 @@ class RootFieldBuilder { inclusionConditions: AnyOf(scope.conditions) ) - if fragmentSpread.typeInfo.deferCondition == nil { + if mergeInNamedFragmentFields && fragmentSpread.typeInfo.deferCondition == nil { mergeAllSelectionsIntoEntitySelectionTrees(from: fragmentSpread) } diff --git a/apollo-ios-codegen/Sources/IR/IRBuilder.swift b/apollo-ios-codegen/Sources/IR/IRBuilder.swift index 7453b2b70..e77ebfa89 100644 --- a/apollo-ios-codegen/Sources/IR/IRBuilder.swift +++ b/apollo-ios-codegen/Sources/IR/IRBuilder.swift @@ -23,7 +23,8 @@ public class IRBuilder { } public func build( - operation operationDefinition: CompilationResult.OperationDefinition + operation operationDefinition: CompilationResult.OperationDefinition, + mergingNamedFragmentFields: Bool = true ) async -> Operation { let rootField = CompilationResult.Field( name: operationDefinition.operationType.rawValue, @@ -38,7 +39,8 @@ public class IRBuilder { let result = await RootFieldBuilder.buildRootEntityField( forRootField: rootField, onRootEntity: rootEntity, - inIR: self + inIR: self, + mergingNamedFragmentFields: mergingNamedFragmentFields ) return Operation( @@ -86,7 +88,8 @@ public class IRBuilder { } public func build( - fragment fragmentDefinition: CompilationResult.FragmentDefinition + fragment fragmentDefinition: CompilationResult.FragmentDefinition, + mergingNamedFragmentFields: Bool = true ) async -> NamedFragment { await builtFragmentStorage.getFragment(named: fragmentDefinition.name) { let rootField = CompilationResult.Field( @@ -102,7 +105,8 @@ public class IRBuilder { let result = await RootFieldBuilder.buildRootEntityField( forRootField: rootField, onRootEntity: rootEntity, - inIR: self + inIR: self, + mergingNamedFragmentFields: mergingNamedFragmentFields ) return NamedFragment(