From 81d42c4af3f46433352a80209b9f166c6f6c70ca Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 12:43:47 +0200 Subject: [PATCH 1/2] fix(strawberryshake): resolve output type for composite field selected directly and via fragment A composite (object/interface) field selected BOTH directly AND via a fragment (an inline fragment of the same type OR a named fragment spread) at the same selection level made CSharpGenerator.Generate throw: System.InvalidOperationException: Could not find an output type for the specified field syntax. Root cause: the field selections are merged onto a single canonical FieldNode, but two code paths disagree on which node is canonical. FieldCollector merges in document order (direct selection wins), while FragmentHelper builds the parent type model's fields by processing inline fragments first (fragment selection wins). The parent property therefore referenced a merged-away duplicate node, whose sub-selection set was never registered in OperationModel's selection-set lookup, so TypeDescriptorMapper.GetFieldTypeDescriptor could not resolve the field's result type and threw. Fix: track the merged-away duplicate field nodes on FieldSelection and register their sub-selection sets against the same result type in InterfaceTypeSelectionSetAnalyzer, so the property type resolves regardless of which equivalent node the parent model captured. This makes the mixed direct+fragment case behave identically to the already-working homogeneous cases (both direct, both in fragments). Adds FragmentDirectAndSpreadGeneratorTests covering the three repros plus the two control cases. --- .../Analyzers/FieldCollector.cs | 29 +- .../Analyzers/FieldSelection.cs | 14 +- .../InterfaceTypeSelectionSetAnalyzer.cs | 26 + .../FragmentDirectAndSpreadGeneratorTests.cs | 78 ++ ...elected_Direct_And_Via_InlineFragment.snap | 836 +++++++++++++++++ ...Selected_Direct_And_Via_NamedFragment.snap | 848 +++++++++++++++++ ..._CompositeField_Selected_Direct_Twice.snap | 830 +++++++++++++++++ ...Field_Selected_In_Two_InlineFragments.snap | 842 +++++++++++++++++ ...elected_Direct_And_Via_InlineFragment.snap | 871 ++++++++++++++++++ 9 files changed, 4371 insertions(+), 3 deletions(-) create mode 100644 src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/FragmentDirectAndSpreadGeneratorTests.cs create mode 100644 src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap create mode 100644 src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap create mode 100644 src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap create mode 100644 src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap create mode 100644 src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs index 4b012847c20..d723b328116 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs @@ -163,12 +163,29 @@ internal static void ResolveFieldSelection( { if (fieldSelection.IsConditional && !IsConditional(fieldSyntax)) { + // the previously selected field becomes a merged-away duplicate of the + // field we now promote to the canonical selection. fieldSelection = new FieldSelection( field, fieldSyntax, - path.Append(responseName)); + path.Append(responseName), + duplicates: AppendDuplicate( + fieldSelection.Duplicates, + fieldSelection.SyntaxNode)); fields[responseName] = fieldSelection; } + else if (!ReferenceEquals(fieldSelection.SyntaxNode, fieldSyntax)) + { + // the same response name is selected again, for example both directly and + // through a fragment. We keep the first selection canonical but remember the + // duplicate so its sub-selection set can still be resolved later. + fields[responseName] = new FieldSelection( + field, + fieldSelection.SyntaxNode, + fieldSelection.Path, + fieldSelection.IsConditional, + AppendDuplicate(fieldSelection.Duplicates, fieldSyntax)); + } } else { @@ -190,6 +207,16 @@ internal static void ResolveFieldSelection( private static bool IsConditional(IHasDirectives _) => false; + private static IReadOnlyList AppendDuplicate( + IReadOnlyList duplicates, + FieldNode duplicate) + { + var list = new List(duplicates.Count + 1); + list.AddRange(duplicates); + list.Add(duplicate); + return list; + } + private void ResolveFragmentSpread( FragmentSpreadNode fragmentSpreadSyntax, IOutputTypeDefinition type, diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldSelection.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldSelection.cs index cd0f3273444..015edd588b2 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldSelection.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldSelection.cs @@ -10,13 +10,15 @@ public FieldSelection( IOutputFieldDefinition field, FieldNode syntaxNode, Path path, - bool isConditional = true) + bool isConditional = true, + IReadOnlyList? duplicates = null) { ResponseName = syntaxNode.Alias?.Value ?? syntaxNode.Name.Value; Field = field; SyntaxNode = syntaxNode; IsConditional = isConditional; Path = path; + Duplicates = duplicates ?? []; } public string ResponseName { get; } @@ -29,6 +31,14 @@ public FieldSelection( public bool IsConditional { get; } + /// + /// The other field syntax nodes that select the same response name at this level and were + /// merged into this selection. They carry the same field but a potentially different + /// sub-selection set, for example when a field is selected both directly and through a + /// fragment. + /// + public IReadOnlyList Duplicates { get; } + public FieldSelection WithPath(Path path) => - new(Field, SyntaxNode, path, IsConditional); + new(Field, SyntaxNode, path, IsConditional, Duplicates); } diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/InterfaceTypeSelectionSetAnalyzer.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/InterfaceTypeSelectionSetAnalyzer.cs index 5c991de7e37..228b35fec12 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/InterfaceTypeSelectionSetAnalyzer.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/InterfaceTypeSelectionSetAnalyzer.cs @@ -77,6 +77,8 @@ private OutputTypeModel AnalyzeWithDefaults( selectionVariants.ReturnType.SyntaxNode, returnType.SelectionSet); + RegisterDuplicateSelectionSets(context, fieldSelection, returnType); + foreach (var selectionSet in selectionVariants.Variants) { returnTypeFragment = FragmentHelper.CreateFragmentNode( @@ -109,6 +111,28 @@ private OutputTypeModel AnalyzeWithDefaults( return returnType; } + // A composite field can be selected more than once at the same level, for example both + // directly and through a fragment. The selections are merged onto a single canonical field + // syntax node, but the parent type model may reference one of the merged-away duplicates as + // the property's syntax node. We register those duplicate sub-selection sets against the same + // result type so the property type can still be resolved later. + private static void RegisterDuplicateSelectionSets( + IDocumentAnalyzerContext context, + FieldSelection fieldSelection, + OutputTypeModel returnType) + { + foreach (var duplicate in fieldSelection.Duplicates) + { + if (duplicate.SelectionSet is { } selectionSet) + { + context.RegisterSelectionSet( + returnType.Type, + selectionSet, + returnType.SelectionSet); + } + } + } + private OutputTypeModel AnalyzeWithHoistedFragment( IDocumentAnalyzerContext context, FieldSelection fieldSelection, @@ -136,6 +160,8 @@ private OutputTypeModel AnalyzeWithHoistedFragment( selectionVariants.ReturnType.SyntaxNode, returnType.SelectionSet); + RegisterDuplicateSelectionSets(context, fieldSelection, returnType); + foreach (var selectionSet in selectionVariants.Variants) { returnTypeFragment = FragmentHelper.CreateFragmentNode( diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/FragmentDirectAndSpreadGeneratorTests.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/FragmentDirectAndSpreadGeneratorTests.cs new file mode 100644 index 00000000000..bfaa532ef01 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/FragmentDirectAndSpreadGeneratorTests.cs @@ -0,0 +1,78 @@ +using static StrawberryShake.CodeGeneration.CSharp.GeneratorTestHelper; + +namespace StrawberryShake.CodeGeneration.CSharp; + +public class FragmentDirectAndSpreadGeneratorTests +{ + private const string Schema = + "type Query { me: User } " + + "type User { id: ID! name: String avatar: Image bestFriend: User } " + + "type Image { url: String! width: Int height: Int }"; + + private const string KeyExtension = "extend schema @key(fields: \"id\")"; + + [Fact] + public void Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment() + { + // arrange + // avatar is selected both directly ({ url }) and inside an inline fragment ({ width }). + + // act & assert + AssertResult( + "query Q { me { avatar { url } ... on User { avatar { width } } } }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment() + { + // arrange + // avatar is selected both directly ({ url }) and via a named fragment spread ({ width }). + + // act & assert + AssertResult( + "query Q { me { avatar { url } ...UF } } fragment UF on User { avatar { width } }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment() + { + // arrange + // bestFriend (a self-referencing User) is selected both directly and via an inline fragment. + + // act & assert + AssertResult( + "query Q { me { bestFriend { id } ... on User { bestFriend { name } } } }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice() + { + // arrange + // control: avatar selected twice directly must keep working. + + // act & assert + AssertResult( + "query Q { me { avatar { url } avatar { width } } }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments() + { + // arrange + // control: avatar selected only inside fragments must keep working. + + // act & assert + AssertResult( + "query Q { me { ... on User { avatar { url } } ... on User { avatar { width } } } }", + Schema, + KeyExtension); + } +} diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap new file mode 100644 index 00000000000..f19e934c26e --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap @@ -0,0 +1,836 @@ +// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable BuiltInTypeReferenceStyle +// ReSharper disable ConvertToAutoProperty +// ReSharper disable InconsistentNaming +// ReSharper disable PartialTypeWithSinglePart +// ReSharper disable PreferConcreteValueOverDefault +// ReSharper disable RedundantNameQualifier +// ReSharper disable SuggestVarOrType_SimpleTypes +// ReSharper disable UnusedMember.Global +// ReSharper disable UnusedMethodReturnValue.Local +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedVariable + +// FooClient + +// +#nullable enable annotations +#nullable disable warnings + +namespace Foo.Bar +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResult : global::System.IEquatable, IQResult + { + public QResult(global::Foo.Bar.IQ_Me? me) + { + Me = me; + } + + public global::Foo.Bar.IQ_Me? Me { get; } + + public virtual global::System.Boolean Equals(QResult? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Me is null && other.Me is null) || Me != null && Me.Equals(other.Me))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((QResult)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Me != null) + { + hash ^= 397 * Me.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_User : global::System.IEquatable, IQ_Me_User + { + public Q_Me_User(global::Foo.Bar.IQ_Me_Avatar? avatar) + { + Avatar = avatar; + } + + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + + public virtual global::System.Boolean Equals(Q_Me_User? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Avatar is null && other.Avatar is null) || Avatar != null && Avatar.Equals(other.Avatar))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_User)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Avatar != null) + { + hash ^= 397 * Avatar.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_Avatar_Image : global::System.IEquatable, IQ_Me_Avatar_Image + { + public Q_Me_Avatar_Image(global::System.String url) + { + Url = url; + } + + public global::System.String Url { get; } + + public virtual global::System.Boolean Equals(Q_Me_Avatar_Image? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (Url.Equals(other.Url)); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_Avatar_Image)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + hash ^= 397 * Url.GetHashCode(); + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQResult + { + public global::Foo.Bar.IQ_Me? Me { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me + { + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_User : IQ_Me + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar + { + public global::System.String Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar_Image : IQ_Me_Avatar + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// ... on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQueryDocument : global::StrawberryShake.IDocument + { + private QQueryDocument() + { + } + + public static QQueryDocument Instance { get; } = new QQueryDocument(); + public global::StrawberryShake.OperationKind Kind => global::StrawberryShake.OperationKind.Query; + public global::System.ReadOnlySpan Body => "query Q { me { __typename avatar { __typename url } ... on User { avatar { __typename width } } ... on User { id } } }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "58b41973217c025b3a638f424018bfdf91a904f1"); + + public override global::System.String ToString() + { +#if NETCOREAPP3_1_OR_GREATER + return global::System.Text.Encoding.UTF8.GetString(Body); +#else + return global::System.Text.Encoding.UTF8.GetString(Body.ToArray()); +#endif + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// ... on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQuery : global::Foo.Bar.IQQuery + { + private readonly global::StrawberryShake.IOperationExecutor _operationExecutor; + private readonly global::System.Collections.Immutable.ImmutableArray> _configure = global::System.Collections.Immutable.ImmutableArray>.Empty; + public QQuery(global::StrawberryShake.IOperationExecutor operationExecutor) + { + _operationExecutor = operationExecutor ?? throw new global::System.ArgumentNullException(nameof(operationExecutor)); + } + + private QQuery(global::StrawberryShake.IOperationExecutor operationExecutor, global::System.Collections.Immutable.ImmutableArray> configure) + { + _operationExecutor = operationExecutor; + _configure = configure; + } + + global::System.Type global::StrawberryShake.IOperationRequestFactory.ResultType => typeof(IQResult); + + public global::Foo.Bar.IQQuery With(global::System.Action configure) + { + return new global::Foo.Bar.QQuery(_operationExecutor, _configure.Add(configure)); + } + + public global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.RequestUri"] = requestUri); + } + + public global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.HttpClient"] = httpClient); + } + + public async global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default) + { + var request = CreateRequest(); + foreach (var configure in _configure) + { + configure(request); + } + + return await _operationExecutor.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + } + + public global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null) + { + var request = CreateRequest(); + return _operationExecutor.Watch(request, strategy); + } + + private global::StrawberryShake.OperationRequest CreateRequest() + { + return CreateRequest(null); + } + + private global::StrawberryShake.OperationRequest CreateRequest(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return new global::StrawberryShake.OperationRequest(id: QQueryDocument.Instance.Hash.Value, name: "Q", document: QQueryDocument.Instance, strategy: global::StrawberryShake.RequestStrategy.Default); + } + + global::StrawberryShake.OperationRequest global::StrawberryShake.IOperationRequestFactory.Create(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return CreateRequest(); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceInterfaceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// ... on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQQuery : global::StrawberryShake.IOperationRequestFactory + { + global::Foo.Bar.IQQuery With(global::System.Action configure); + global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri); + global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient); + global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default); + global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null); + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClient : global::Foo.Bar.IFooClient + { + private readonly global::Foo.Bar.IQQuery _q; + public FooClient(global::Foo.Bar.IQQuery q) + { + _q = q ?? throw new global::System.ArgumentNullException(nameof(q)); + } + + public static global::System.String ClientName => "FooClient"; + public global::Foo.Bar.IQQuery Q => _q; + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientInterfaceGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IFooClient + { + global::Foo.Bar.IQQuery Q { get; } + } +} + +namespace Foo.Bar.State +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class UserEntity + { + public UserEntity(global::Foo.Bar.State.ImageData? avatar = default !) + { + Avatar = avatar; + } + + public global::Foo.Bar.State.ImageData? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultDataFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultFactory : global::StrawberryShake.IOperationResultDataFactory + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityMapper _q_Me_UserFromUserEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Me_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Me_UserFromUserEntityMapper = q_Me_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Me_UserFromUserEntityMapper)); + } + + global::System.Type global::StrawberryShake.IOperationResultDataFactory.ResultType => typeof(global::Foo.Bar.IQResult); + + public QResult Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + if (dataInfo is QResultInfo info) + { + return new QResult(MapIQ_Me(info.Me, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Me? MapIQ_Me(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + return _q_Me_UserFromUserEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + throw new global::System.NotSupportedException(); + } + + global::System.Object global::StrawberryShake.IOperationResultDataFactory.Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot) + { + return Create(dataInfo, snapshot); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInfoGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultInfo : global::StrawberryShake.IOperationResultDataInfo + { + private readonly global::System.Collections.Generic.IReadOnlyCollection _entityIds; + private readonly global::System.UInt64 _version; + public QResultInfo(global::StrawberryShake.EntityId? me, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Me = me; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Me { get; } + public global::System.Collections.Generic.IReadOnlyCollection EntityIds => _entityIds; + public global::System.UInt64 Version => _version; + + public global::StrawberryShake.IOperationResultDataInfo WithVersion(global::System.UInt64 version) + { + return new QResultInfo(Me, _entityIds, version); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.JsonResultBuilderGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QBuilder : global::StrawberryShake.OperationResultBuilder + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityIdSerializer _idSerializer; + private readonly global::StrawberryShake.Serialization.ILeafValueParser _stringParser; + public QBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer)); + ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory)); + _stringParser = serializerResolver.GetLeafValueParser("String") ?? throw new global::System.ArgumentException("No serializer for type `String` found."); + } + + protected override global::StrawberryShake.IOperationResultDataFactory ResultDataFactory { get; } + + protected override global::StrawberryShake.IOperationResultDataInfo BuildData(global::System.Text.Json.JsonElement obj) + { + var entityIds = new global::System.Collections.Generic.HashSet(); + global::StrawberryShake.IEntityStoreSnapshot snapshot = default !; + global::StrawberryShake.EntityId? meId = default !; + _entityStore.Update(session => + { + meId = Update_IQ_MeEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "me"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(meId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_MeEntity(global::StrawberryShake.IEntityStoreUpdateSession session, global::System.Text.Json.JsonElement? obj, global::System.Collections.Generic.ISet entityIds) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + global::StrawberryShake.EntityId entityId = _idSerializer.Parse(obj.Value); + entityIds.Add(entityId); + if (entityId.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.UserEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::Foo.Bar.State.ImageData? Deserialize_IQ_Me_Avatar(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + var typename = obj.Value.GetProperty("__typename").GetString(); + if (typename?.Equals("Image", global::System.StringComparison.Ordinal) ?? false) + { + return new global::Foo.Bar.State.ImageData(typename, url: Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "url"))); + } + + throw new global::System.NotSupportedException(); + } + + private global::System.String Deserialize_NonNullableString(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + throw new global::System.ArgumentNullException(); + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + throw new global::System.ArgumentNullException(); + } + + return _stringParser.Parse(obj.Value.GetString()!); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.DataTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class ImageData + { + public ImageData(global::System.String __typename, global::System.String? url = default !) + { + this.__typename = __typename ?? throw new global::System.ArgumentNullException(nameof(__typename)); + Url = url; + } + + public global::System.String __typename { get; } + public global::System.String? Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Me_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Me_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Me_User(MapIQ_Me_Avatar(entity.Avatar, snapshot)); + } + + private global::Foo.Bar.IQ_Me_Avatar? MapIQ_Me_Avatar(global::Foo.Bar.State.ImageData? data, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (data is null) + { + return null; + } + + IQ_Me_Avatar returnValue = default !; + if (data.__typename.Equals("Image", global::System.StringComparison.Ordinal)) + { + returnValue = new Q_Me_Avatar_Image(data.Url ?? throw new global::System.ArgumentNullException()); + } + else + { + throw new global::System.NotSupportedException(); + } + + return returnValue; + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityIdFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientEntityIdFactory : global::StrawberryShake.IEntityIdSerializer + { + private static readonly global::System.Text.Json.JsonWriterOptions _options = new global::System.Text.Json.JsonWriterOptions() + { + Indented = false + }; + public global::StrawberryShake.EntityId Parse(global::System.Text.Json.JsonElement obj) + { + global::System.String __typename = obj.GetProperty("__typename").GetString()!; + return __typename switch + { + "User" => ParseUserEntityId(obj, __typename), + _ => throw new global::System.NotSupportedException()}; + } + + public global::System.String Format(global::StrawberryShake.EntityId entityId) + { + return entityId.Name switch + { + "User" => FormatUserEntityId(entityId), + _ => throw new global::System.NotSupportedException()}; + } + + private global::StrawberryShake.EntityId ParseUserEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatUserEntityId(global::StrawberryShake.EntityId entityId) + { + using var writer = new global::StrawberryShake.Internal.ArrayWriter(); + using var jsonWriter = new global::System.Text.Json.Utf8JsonWriter(writer, _options); + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("__typename", entityId.Name); + jsonWriter.WriteString("id", (global::System.String)entityId.Value); + jsonWriter.WriteEndObject(); + jsonWriter.Flush(); + return global::System.Text.Encoding.UTF8.GetString(writer.GetInternalBuffer(), 0, writer.Length); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.StoreAccessorGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientStoreAccessor : global::StrawberryShake.StoreAccessor + { + public FooClientStoreAccessor(global::StrawberryShake.IOperationStore operationStore, global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer entityIdSerializer, global::System.Collections.Generic.IEnumerable requestFactories, global::System.Collections.Generic.IEnumerable resultDataFactories) : base(operationStore, entityStore, entityIdSerializer, requestFactories, resultDataFactories) + { + } + } +} + +namespace Microsoft.Extensions.DependencyInjection +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.DependencyInjectionGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public static partial class FooClientServiceCollectionExtensions + { + public static global::StrawberryShake.IClientBuilder AddFooClient(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + var serviceCollection = new global::Microsoft.Extensions.DependencyInjection.ServiceCollection(); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + ConfigureClientDefault(sp, serviceCollection, strategy); + return new ClientServiceProvider(global::Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(serviceCollection)); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::Foo.Bar.State.FooClientStoreAccessor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + return new global::StrawberryShake.ClientBuilder("FooClient", services, serviceCollection); + } + + private static global::Microsoft.Extensions.DependencyInjection.IServiceCollection ConfigureClientDefault(global::System.IServiceProvider parentServices, global::Microsoft.Extensions.DependencyInjection.ServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services, sp => new global::StrawberryShake.OperationStore(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + var clientFactory = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(parentServices); + return new global::StrawberryShake.Transport.Http.HttpConnection(() => clientFactory.CreateClient("FooClient")); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Me_UserFromUserEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::StrawberryShake.Serialization.SerializerResolver(global::System.Linq.Enumerable.Concat(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(parentServices), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QResultFactory>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QBuilder>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, sp => new global::StrawberryShake.OperationExecutor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), strategy)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::StrawberryShake.Json.JsonResultPatcher>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + return services; + } + + private sealed class ClientServiceProvider : System.IServiceProvider, System.IDisposable + { + private readonly System.IServiceProvider _provider; + public ClientServiceProvider(System.IServiceProvider provider) + { + _provider = provider; + } + + public object? GetService(System.Type serviceType) + { + return _provider.GetService(serviceType); + } + + public void Dispose() + { + if (_provider is System.IDisposable d) + { + d.Dispose(); + } + } + } + } +} + + diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap new file mode 100644 index 00000000000..5d80fc25a56 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap @@ -0,0 +1,848 @@ +// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable BuiltInTypeReferenceStyle +// ReSharper disable ConvertToAutoProperty +// ReSharper disable InconsistentNaming +// ReSharper disable PartialTypeWithSinglePart +// ReSharper disable PreferConcreteValueOverDefault +// ReSharper disable RedundantNameQualifier +// ReSharper disable SuggestVarOrType_SimpleTypes +// ReSharper disable UnusedMember.Global +// ReSharper disable UnusedMethodReturnValue.Local +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedVariable + +// FooClient + +// +#nullable enable annotations +#nullable disable warnings + +namespace Foo.Bar +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResult : global::System.IEquatable, IQResult + { + public QResult(global::Foo.Bar.IQ_Me? me) + { + Me = me; + } + + public global::Foo.Bar.IQ_Me? Me { get; } + + public virtual global::System.Boolean Equals(QResult? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Me is null && other.Me is null) || Me != null && Me.Equals(other.Me))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((QResult)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Me != null) + { + hash ^= 397 * Me.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_User : global::System.IEquatable, IQ_Me_User + { + public Q_Me_User(global::Foo.Bar.IQ_Me_Avatar? avatar) + { + Avatar = avatar; + } + + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + + public virtual global::System.Boolean Equals(Q_Me_User? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Avatar is null && other.Avatar is null) || Avatar != null && Avatar.Equals(other.Avatar))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_User)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Avatar != null) + { + hash ^= 397 * Avatar.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_Avatar_Image : global::System.IEquatable, IQ_Me_Avatar_Image + { + public Q_Me_Avatar_Image(global::System.String url) + { + Url = url; + } + + public global::System.String Url { get; } + + public virtual global::System.Boolean Equals(Q_Me_Avatar_Image? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (Url.Equals(other.Url)); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_Avatar_Image)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + hash ^= 397 * Url.GetHashCode(); + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQResult + { + public global::Foo.Bar.IQ_Me? Me { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IUF + { + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me : IUF + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_User : IQ_Me + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar + { + public global::System.String Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar_Image : IQ_Me_Avatar + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQueryDocument : global::StrawberryShake.IDocument + { + private QQueryDocument() + { + } + + public static QQueryDocument Instance { get; } = new QQueryDocument(); + public global::StrawberryShake.OperationKind Kind => global::StrawberryShake.OperationKind.Query; + public global::System.ReadOnlySpan Body => "query Q { me { __typename avatar { __typename url } ...UF ... on User { id } } } fragment UF on User { avatar { __typename width } }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "652cd902f97a94a97be838942227be38b7bc409e"); + + public override global::System.String ToString() + { +#if NETCOREAPP3_1_OR_GREATER + return global::System.Text.Encoding.UTF8.GetString(Body); +#else + return global::System.Text.Encoding.UTF8.GetString(Body.ToArray()); +#endif + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQuery : global::Foo.Bar.IQQuery + { + private readonly global::StrawberryShake.IOperationExecutor _operationExecutor; + private readonly global::System.Collections.Immutable.ImmutableArray> _configure = global::System.Collections.Immutable.ImmutableArray>.Empty; + public QQuery(global::StrawberryShake.IOperationExecutor operationExecutor) + { + _operationExecutor = operationExecutor ?? throw new global::System.ArgumentNullException(nameof(operationExecutor)); + } + + private QQuery(global::StrawberryShake.IOperationExecutor operationExecutor, global::System.Collections.Immutable.ImmutableArray> configure) + { + _operationExecutor = operationExecutor; + _configure = configure; + } + + global::System.Type global::StrawberryShake.IOperationRequestFactory.ResultType => typeof(IQResult); + + public global::Foo.Bar.IQQuery With(global::System.Action configure) + { + return new global::Foo.Bar.QQuery(_operationExecutor, _configure.Add(configure)); + } + + public global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.RequestUri"] = requestUri); + } + + public global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.HttpClient"] = httpClient); + } + + public async global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default) + { + var request = CreateRequest(); + foreach (var configure in _configure) + { + configure(request); + } + + return await _operationExecutor.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + } + + public global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null) + { + var request = CreateRequest(); + return _operationExecutor.Watch(request, strategy); + } + + private global::StrawberryShake.OperationRequest CreateRequest() + { + return CreateRequest(null); + } + + private global::StrawberryShake.OperationRequest CreateRequest(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return new global::StrawberryShake.OperationRequest(id: QQueryDocument.Instance.Hash.Value, name: "Q", document: QQueryDocument.Instance, strategy: global::StrawberryShake.RequestStrategy.Default); + } + + global::StrawberryShake.OperationRequest global::StrawberryShake.IOperationRequestFactory.Create(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return CreateRequest(); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceInterfaceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQQuery : global::StrawberryShake.IOperationRequestFactory + { + global::Foo.Bar.IQQuery With(global::System.Action configure); + global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri); + global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient); + global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default); + global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null); + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClient : global::Foo.Bar.IFooClient + { + private readonly global::Foo.Bar.IQQuery _q; + public FooClient(global::Foo.Bar.IQQuery q) + { + _q = q ?? throw new global::System.ArgumentNullException(nameof(q)); + } + + public static global::System.String ClientName => "FooClient"; + public global::Foo.Bar.IQQuery Q => _q; + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientInterfaceGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IFooClient + { + global::Foo.Bar.IQQuery Q { get; } + } +} + +namespace Foo.Bar.State +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class UserEntity + { + public UserEntity(global::Foo.Bar.State.ImageData? avatar = default !) + { + Avatar = avatar; + } + + public global::Foo.Bar.State.ImageData? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultDataFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultFactory : global::StrawberryShake.IOperationResultDataFactory + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityMapper _q_Me_UserFromUserEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Me_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Me_UserFromUserEntityMapper = q_Me_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Me_UserFromUserEntityMapper)); + } + + global::System.Type global::StrawberryShake.IOperationResultDataFactory.ResultType => typeof(global::Foo.Bar.IQResult); + + public QResult Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + if (dataInfo is QResultInfo info) + { + return new QResult(MapIQ_Me(info.Me, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Me? MapIQ_Me(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + return _q_Me_UserFromUserEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + throw new global::System.NotSupportedException(); + } + + global::System.Object global::StrawberryShake.IOperationResultDataFactory.Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot) + { + return Create(dataInfo, snapshot); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInfoGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultInfo : global::StrawberryShake.IOperationResultDataInfo + { + private readonly global::System.Collections.Generic.IReadOnlyCollection _entityIds; + private readonly global::System.UInt64 _version; + public QResultInfo(global::StrawberryShake.EntityId? me, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Me = me; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Me { get; } + public global::System.Collections.Generic.IReadOnlyCollection EntityIds => _entityIds; + public global::System.UInt64 Version => _version; + + public global::StrawberryShake.IOperationResultDataInfo WithVersion(global::System.UInt64 version) + { + return new QResultInfo(Me, _entityIds, version); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.JsonResultBuilderGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QBuilder : global::StrawberryShake.OperationResultBuilder + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityIdSerializer _idSerializer; + private readonly global::StrawberryShake.Serialization.ILeafValueParser _stringParser; + public QBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer)); + ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory)); + _stringParser = serializerResolver.GetLeafValueParser("String") ?? throw new global::System.ArgumentException("No serializer for type `String` found."); + } + + protected override global::StrawberryShake.IOperationResultDataFactory ResultDataFactory { get; } + + protected override global::StrawberryShake.IOperationResultDataInfo BuildData(global::System.Text.Json.JsonElement obj) + { + var entityIds = new global::System.Collections.Generic.HashSet(); + global::StrawberryShake.IEntityStoreSnapshot snapshot = default !; + global::StrawberryShake.EntityId? meId = default !; + _entityStore.Update(session => + { + meId = Update_IQ_MeEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "me"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(meId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_MeEntity(global::StrawberryShake.IEntityStoreUpdateSession session, global::System.Text.Json.JsonElement? obj, global::System.Collections.Generic.ISet entityIds) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + global::StrawberryShake.EntityId entityId = _idSerializer.Parse(obj.Value); + entityIds.Add(entityId); + if (entityId.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.UserEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::Foo.Bar.State.ImageData? Deserialize_IQ_Me_Avatar(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + var typename = obj.Value.GetProperty("__typename").GetString(); + if (typename?.Equals("Image", global::System.StringComparison.Ordinal) ?? false) + { + return new global::Foo.Bar.State.ImageData(typename, url: Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "url"))); + } + + throw new global::System.NotSupportedException(); + } + + private global::System.String Deserialize_NonNullableString(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + throw new global::System.ArgumentNullException(); + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + throw new global::System.ArgumentNullException(); + } + + return _stringParser.Parse(obj.Value.GetString()!); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.DataTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class ImageData + { + public ImageData(global::System.String __typename, global::System.String? url = default !) + { + this.__typename = __typename ?? throw new global::System.ArgumentNullException(nameof(__typename)); + Url = url; + } + + public global::System.String __typename { get; } + public global::System.String? Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Me_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Me_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Me_User(MapIQ_Me_Avatar(entity.Avatar, snapshot)); + } + + private global::Foo.Bar.IQ_Me_Avatar? MapIQ_Me_Avatar(global::Foo.Bar.State.ImageData? data, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (data is null) + { + return null; + } + + IQ_Me_Avatar returnValue = default !; + if (data.__typename.Equals("Image", global::System.StringComparison.Ordinal)) + { + returnValue = new Q_Me_Avatar_Image(data.Url ?? throw new global::System.ArgumentNullException()); + } + else + { + throw new global::System.NotSupportedException(); + } + + return returnValue; + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityIdFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientEntityIdFactory : global::StrawberryShake.IEntityIdSerializer + { + private static readonly global::System.Text.Json.JsonWriterOptions _options = new global::System.Text.Json.JsonWriterOptions() + { + Indented = false + }; + public global::StrawberryShake.EntityId Parse(global::System.Text.Json.JsonElement obj) + { + global::System.String __typename = obj.GetProperty("__typename").GetString()!; + return __typename switch + { + "User" => ParseUserEntityId(obj, __typename), + _ => throw new global::System.NotSupportedException()}; + } + + public global::System.String Format(global::StrawberryShake.EntityId entityId) + { + return entityId.Name switch + { + "User" => FormatUserEntityId(entityId), + _ => throw new global::System.NotSupportedException()}; + } + + private global::StrawberryShake.EntityId ParseUserEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatUserEntityId(global::StrawberryShake.EntityId entityId) + { + using var writer = new global::StrawberryShake.Internal.ArrayWriter(); + using var jsonWriter = new global::System.Text.Json.Utf8JsonWriter(writer, _options); + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("__typename", entityId.Name); + jsonWriter.WriteString("id", (global::System.String)entityId.Value); + jsonWriter.WriteEndObject(); + jsonWriter.Flush(); + return global::System.Text.Encoding.UTF8.GetString(writer.GetInternalBuffer(), 0, writer.Length); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.StoreAccessorGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientStoreAccessor : global::StrawberryShake.StoreAccessor + { + public FooClientStoreAccessor(global::StrawberryShake.IOperationStore operationStore, global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer entityIdSerializer, global::System.Collections.Generic.IEnumerable requestFactories, global::System.Collections.Generic.IEnumerable resultDataFactories) : base(operationStore, entityStore, entityIdSerializer, requestFactories, resultDataFactories) + { + } + } +} + +namespace Microsoft.Extensions.DependencyInjection +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.DependencyInjectionGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public static partial class FooClientServiceCollectionExtensions + { + public static global::StrawberryShake.IClientBuilder AddFooClient(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + var serviceCollection = new global::Microsoft.Extensions.DependencyInjection.ServiceCollection(); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + ConfigureClientDefault(sp, serviceCollection, strategy); + return new ClientServiceProvider(global::Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(serviceCollection)); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::Foo.Bar.State.FooClientStoreAccessor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + return new global::StrawberryShake.ClientBuilder("FooClient", services, serviceCollection); + } + + private static global::Microsoft.Extensions.DependencyInjection.IServiceCollection ConfigureClientDefault(global::System.IServiceProvider parentServices, global::Microsoft.Extensions.DependencyInjection.ServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services, sp => new global::StrawberryShake.OperationStore(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + var clientFactory = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(parentServices); + return new global::StrawberryShake.Transport.Http.HttpConnection(() => clientFactory.CreateClient("FooClient")); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Me_UserFromUserEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::StrawberryShake.Serialization.SerializerResolver(global::System.Linq.Enumerable.Concat(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(parentServices), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QResultFactory>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QBuilder>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, sp => new global::StrawberryShake.OperationExecutor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), strategy)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::StrawberryShake.Json.JsonResultPatcher>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + return services; + } + + private sealed class ClientServiceProvider : System.IServiceProvider, System.IDisposable + { + private readonly System.IServiceProvider _provider; + public ClientServiceProvider(System.IServiceProvider provider) + { + _provider = provider; + } + + public object? GetService(System.Type serviceType) + { + return _provider.GetService(serviceType); + } + + public void Dispose() + { + if (_provider is System.IDisposable d) + { + d.Dispose(); + } + } + } + } +} + + diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap new file mode 100644 index 00000000000..99d241874e6 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap @@ -0,0 +1,830 @@ +// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable BuiltInTypeReferenceStyle +// ReSharper disable ConvertToAutoProperty +// ReSharper disable InconsistentNaming +// ReSharper disable PartialTypeWithSinglePart +// ReSharper disable PreferConcreteValueOverDefault +// ReSharper disable RedundantNameQualifier +// ReSharper disable SuggestVarOrType_SimpleTypes +// ReSharper disable UnusedMember.Global +// ReSharper disable UnusedMethodReturnValue.Local +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedVariable + +// FooClient + +// +#nullable enable annotations +#nullable disable warnings + +namespace Foo.Bar +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResult : global::System.IEquatable, IQResult + { + public QResult(global::Foo.Bar.IQ_Me? me) + { + Me = me; + } + + public global::Foo.Bar.IQ_Me? Me { get; } + + public virtual global::System.Boolean Equals(QResult? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Me is null && other.Me is null) || Me != null && Me.Equals(other.Me))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((QResult)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Me != null) + { + hash ^= 397 * Me.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_User : global::System.IEquatable, IQ_Me_User + { + public Q_Me_User(global::Foo.Bar.IQ_Me_Avatar? avatar) + { + Avatar = avatar; + } + + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + + public virtual global::System.Boolean Equals(Q_Me_User? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Avatar is null && other.Avatar is null) || Avatar != null && Avatar.Equals(other.Avatar))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_User)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Avatar != null) + { + hash ^= 397 * Avatar.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_Avatar_Image : global::System.IEquatable, IQ_Me_Avatar_Image + { + public Q_Me_Avatar_Image(global::System.String url) + { + Url = url; + } + + public global::System.String Url { get; } + + public virtual global::System.Boolean Equals(Q_Me_Avatar_Image? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (Url.Equals(other.Url)); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_Avatar_Image)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + hash ^= 397 * Url.GetHashCode(); + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQResult + { + public global::Foo.Bar.IQ_Me? Me { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me + { + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_User : IQ_Me + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar + { + public global::System.String Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar_Image : IQ_Me_Avatar + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// avatar { + /// __typename + /// width + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQueryDocument : global::StrawberryShake.IDocument + { + private QQueryDocument() + { + } + + public static QQueryDocument Instance { get; } = new QQueryDocument(); + public global::StrawberryShake.OperationKind Kind => global::StrawberryShake.OperationKind.Query; + public global::System.ReadOnlySpan Body => "query Q { me { __typename avatar { __typename url } avatar { __typename width } ... on User { id } } }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "dcb411ee73f23c010d5a11d7bbe9f43d07c9458b"); + + public override global::System.String ToString() + { +#if NETCOREAPP3_1_OR_GREATER + return global::System.Text.Encoding.UTF8.GetString(Body); +#else + return global::System.Text.Encoding.UTF8.GetString(Body.ToArray()); +#endif + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// avatar { + /// __typename + /// width + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQuery : global::Foo.Bar.IQQuery + { + private readonly global::StrawberryShake.IOperationExecutor _operationExecutor; + private readonly global::System.Collections.Immutable.ImmutableArray> _configure = global::System.Collections.Immutable.ImmutableArray>.Empty; + public QQuery(global::StrawberryShake.IOperationExecutor operationExecutor) + { + _operationExecutor = operationExecutor ?? throw new global::System.ArgumentNullException(nameof(operationExecutor)); + } + + private QQuery(global::StrawberryShake.IOperationExecutor operationExecutor, global::System.Collections.Immutable.ImmutableArray> configure) + { + _operationExecutor = operationExecutor; + _configure = configure; + } + + global::System.Type global::StrawberryShake.IOperationRequestFactory.ResultType => typeof(IQResult); + + public global::Foo.Bar.IQQuery With(global::System.Action configure) + { + return new global::Foo.Bar.QQuery(_operationExecutor, _configure.Add(configure)); + } + + public global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.RequestUri"] = requestUri); + } + + public global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.HttpClient"] = httpClient); + } + + public async global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default) + { + var request = CreateRequest(); + foreach (var configure in _configure) + { + configure(request); + } + + return await _operationExecutor.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + } + + public global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null) + { + var request = CreateRequest(); + return _operationExecutor.Watch(request, strategy); + } + + private global::StrawberryShake.OperationRequest CreateRequest() + { + return CreateRequest(null); + } + + private global::StrawberryShake.OperationRequest CreateRequest(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return new global::StrawberryShake.OperationRequest(id: QQueryDocument.Instance.Hash.Value, name: "Q", document: QQueryDocument.Instance, strategy: global::StrawberryShake.RequestStrategy.Default); + } + + global::StrawberryShake.OperationRequest global::StrawberryShake.IOperationRequestFactory.Create(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return CreateRequest(); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceInterfaceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// avatar { + /// __typename + /// url + /// } + /// avatar { + /// __typename + /// width + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQQuery : global::StrawberryShake.IOperationRequestFactory + { + global::Foo.Bar.IQQuery With(global::System.Action configure); + global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri); + global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient); + global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default); + global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null); + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClient : global::Foo.Bar.IFooClient + { + private readonly global::Foo.Bar.IQQuery _q; + public FooClient(global::Foo.Bar.IQQuery q) + { + _q = q ?? throw new global::System.ArgumentNullException(nameof(q)); + } + + public static global::System.String ClientName => "FooClient"; + public global::Foo.Bar.IQQuery Q => _q; + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientInterfaceGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IFooClient + { + global::Foo.Bar.IQQuery Q { get; } + } +} + +namespace Foo.Bar.State +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class UserEntity + { + public UserEntity(global::Foo.Bar.State.ImageData? avatar = default !) + { + Avatar = avatar; + } + + public global::Foo.Bar.State.ImageData? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultDataFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultFactory : global::StrawberryShake.IOperationResultDataFactory + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityMapper _q_Me_UserFromUserEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Me_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Me_UserFromUserEntityMapper = q_Me_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Me_UserFromUserEntityMapper)); + } + + global::System.Type global::StrawberryShake.IOperationResultDataFactory.ResultType => typeof(global::Foo.Bar.IQResult); + + public QResult Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + if (dataInfo is QResultInfo info) + { + return new QResult(MapIQ_Me(info.Me, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Me? MapIQ_Me(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + return _q_Me_UserFromUserEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + throw new global::System.NotSupportedException(); + } + + global::System.Object global::StrawberryShake.IOperationResultDataFactory.Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot) + { + return Create(dataInfo, snapshot); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInfoGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultInfo : global::StrawberryShake.IOperationResultDataInfo + { + private readonly global::System.Collections.Generic.IReadOnlyCollection _entityIds; + private readonly global::System.UInt64 _version; + public QResultInfo(global::StrawberryShake.EntityId? me, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Me = me; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Me { get; } + public global::System.Collections.Generic.IReadOnlyCollection EntityIds => _entityIds; + public global::System.UInt64 Version => _version; + + public global::StrawberryShake.IOperationResultDataInfo WithVersion(global::System.UInt64 version) + { + return new QResultInfo(Me, _entityIds, version); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.JsonResultBuilderGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QBuilder : global::StrawberryShake.OperationResultBuilder + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityIdSerializer _idSerializer; + private readonly global::StrawberryShake.Serialization.ILeafValueParser _stringParser; + public QBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer)); + ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory)); + _stringParser = serializerResolver.GetLeafValueParser("String") ?? throw new global::System.ArgumentException("No serializer for type `String` found."); + } + + protected override global::StrawberryShake.IOperationResultDataFactory ResultDataFactory { get; } + + protected override global::StrawberryShake.IOperationResultDataInfo BuildData(global::System.Text.Json.JsonElement obj) + { + var entityIds = new global::System.Collections.Generic.HashSet(); + global::StrawberryShake.IEntityStoreSnapshot snapshot = default !; + global::StrawberryShake.EntityId? meId = default !; + _entityStore.Update(session => + { + meId = Update_IQ_MeEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "me"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(meId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_MeEntity(global::StrawberryShake.IEntityStoreUpdateSession session, global::System.Text.Json.JsonElement? obj, global::System.Collections.Generic.ISet entityIds) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + global::StrawberryShake.EntityId entityId = _idSerializer.Parse(obj.Value); + entityIds.Add(entityId); + if (entityId.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.UserEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::Foo.Bar.State.ImageData? Deserialize_IQ_Me_Avatar(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + var typename = obj.Value.GetProperty("__typename").GetString(); + if (typename?.Equals("Image", global::System.StringComparison.Ordinal) ?? false) + { + return new global::Foo.Bar.State.ImageData(typename, url: Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "url"))); + } + + throw new global::System.NotSupportedException(); + } + + private global::System.String Deserialize_NonNullableString(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + throw new global::System.ArgumentNullException(); + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + throw new global::System.ArgumentNullException(); + } + + return _stringParser.Parse(obj.Value.GetString()!); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.DataTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class ImageData + { + public ImageData(global::System.String __typename, global::System.String? url = default !) + { + this.__typename = __typename ?? throw new global::System.ArgumentNullException(nameof(__typename)); + Url = url; + } + + public global::System.String __typename { get; } + public global::System.String? Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Me_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Me_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Me_User(MapIQ_Me_Avatar(entity.Avatar, snapshot)); + } + + private global::Foo.Bar.IQ_Me_Avatar? MapIQ_Me_Avatar(global::Foo.Bar.State.ImageData? data, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (data is null) + { + return null; + } + + IQ_Me_Avatar returnValue = default !; + if (data.__typename.Equals("Image", global::System.StringComparison.Ordinal)) + { + returnValue = new Q_Me_Avatar_Image(data.Url ?? throw new global::System.ArgumentNullException()); + } + else + { + throw new global::System.NotSupportedException(); + } + + return returnValue; + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityIdFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientEntityIdFactory : global::StrawberryShake.IEntityIdSerializer + { + private static readonly global::System.Text.Json.JsonWriterOptions _options = new global::System.Text.Json.JsonWriterOptions() + { + Indented = false + }; + public global::StrawberryShake.EntityId Parse(global::System.Text.Json.JsonElement obj) + { + global::System.String __typename = obj.GetProperty("__typename").GetString()!; + return __typename switch + { + "User" => ParseUserEntityId(obj, __typename), + _ => throw new global::System.NotSupportedException()}; + } + + public global::System.String Format(global::StrawberryShake.EntityId entityId) + { + return entityId.Name switch + { + "User" => FormatUserEntityId(entityId), + _ => throw new global::System.NotSupportedException()}; + } + + private global::StrawberryShake.EntityId ParseUserEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatUserEntityId(global::StrawberryShake.EntityId entityId) + { + using var writer = new global::StrawberryShake.Internal.ArrayWriter(); + using var jsonWriter = new global::System.Text.Json.Utf8JsonWriter(writer, _options); + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("__typename", entityId.Name); + jsonWriter.WriteString("id", (global::System.String)entityId.Value); + jsonWriter.WriteEndObject(); + jsonWriter.Flush(); + return global::System.Text.Encoding.UTF8.GetString(writer.GetInternalBuffer(), 0, writer.Length); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.StoreAccessorGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientStoreAccessor : global::StrawberryShake.StoreAccessor + { + public FooClientStoreAccessor(global::StrawberryShake.IOperationStore operationStore, global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer entityIdSerializer, global::System.Collections.Generic.IEnumerable requestFactories, global::System.Collections.Generic.IEnumerable resultDataFactories) : base(operationStore, entityStore, entityIdSerializer, requestFactories, resultDataFactories) + { + } + } +} + +namespace Microsoft.Extensions.DependencyInjection +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.DependencyInjectionGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public static partial class FooClientServiceCollectionExtensions + { + public static global::StrawberryShake.IClientBuilder AddFooClient(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + var serviceCollection = new global::Microsoft.Extensions.DependencyInjection.ServiceCollection(); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + ConfigureClientDefault(sp, serviceCollection, strategy); + return new ClientServiceProvider(global::Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(serviceCollection)); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::Foo.Bar.State.FooClientStoreAccessor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + return new global::StrawberryShake.ClientBuilder("FooClient", services, serviceCollection); + } + + private static global::Microsoft.Extensions.DependencyInjection.IServiceCollection ConfigureClientDefault(global::System.IServiceProvider parentServices, global::Microsoft.Extensions.DependencyInjection.ServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services, sp => new global::StrawberryShake.OperationStore(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + var clientFactory = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(parentServices); + return new global::StrawberryShake.Transport.Http.HttpConnection(() => clientFactory.CreateClient("FooClient")); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Me_UserFromUserEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::StrawberryShake.Serialization.SerializerResolver(global::System.Linq.Enumerable.Concat(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(parentServices), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QResultFactory>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QBuilder>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, sp => new global::StrawberryShake.OperationExecutor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), strategy)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::StrawberryShake.Json.JsonResultPatcher>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + return services; + } + + private sealed class ClientServiceProvider : System.IServiceProvider, System.IDisposable + { + private readonly System.IServiceProvider _provider; + public ClientServiceProvider(System.IServiceProvider provider) + { + _provider = provider; + } + + public object? GetService(System.Type serviceType) + { + return _provider.GetService(serviceType); + } + + public void Dispose() + { + if (_provider is System.IDisposable d) + { + d.Dispose(); + } + } + } + } +} + + diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap new file mode 100644 index 00000000000..0eb1074b5d1 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap @@ -0,0 +1,842 @@ +// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable BuiltInTypeReferenceStyle +// ReSharper disable ConvertToAutoProperty +// ReSharper disable InconsistentNaming +// ReSharper disable PartialTypeWithSinglePart +// ReSharper disable PreferConcreteValueOverDefault +// ReSharper disable RedundantNameQualifier +// ReSharper disable SuggestVarOrType_SimpleTypes +// ReSharper disable UnusedMember.Global +// ReSharper disable UnusedMethodReturnValue.Local +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedVariable + +// FooClient + +// +#nullable enable annotations +#nullable disable warnings + +namespace Foo.Bar +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResult : global::System.IEquatable, IQResult + { + public QResult(global::Foo.Bar.IQ_Me? me) + { + Me = me; + } + + public global::Foo.Bar.IQ_Me? Me { get; } + + public virtual global::System.Boolean Equals(QResult? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Me is null && other.Me is null) || Me != null && Me.Equals(other.Me))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((QResult)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Me != null) + { + hash ^= 397 * Me.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_User : global::System.IEquatable, IQ_Me_User + { + public Q_Me_User(global::Foo.Bar.IQ_Me_Avatar? avatar) + { + Avatar = avatar; + } + + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + + public virtual global::System.Boolean Equals(Q_Me_User? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Avatar is null && other.Avatar is null) || Avatar != null && Avatar.Equals(other.Avatar))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_User)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Avatar != null) + { + hash ^= 397 * Avatar.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_Avatar_Image : global::System.IEquatable, IQ_Me_Avatar_Image + { + public Q_Me_Avatar_Image(global::System.String url) + { + Url = url; + } + + public global::System.String Url { get; } + + public virtual global::System.Boolean Equals(Q_Me_Avatar_Image? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (Url.Equals(other.Url)); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_Avatar_Image)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + hash ^= 397 * Url.GetHashCode(); + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQResult + { + public global::Foo.Bar.IQ_Me? Me { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me + { + public global::Foo.Bar.IQ_Me_Avatar? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_User : IQ_Me + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar + { + public global::System.String Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_Avatar_Image : IQ_Me_Avatar + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// ... on User { + /// avatar { + /// __typename + /// url + /// } + /// } + /// ... on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQueryDocument : global::StrawberryShake.IDocument + { + private QQueryDocument() + { + } + + public static QQueryDocument Instance { get; } = new QQueryDocument(); + public global::StrawberryShake.OperationKind Kind => global::StrawberryShake.OperationKind.Query; + public global::System.ReadOnlySpan Body => "query Q { me { __typename ... on User { avatar { __typename url } } ... on User { avatar { __typename width } } ... on User { id } } }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "5f4e06783b85053a9e4984d5f0e8c79c9e5aa7b4"); + + public override global::System.String ToString() + { +#if NETCOREAPP3_1_OR_GREATER + return global::System.Text.Encoding.UTF8.GetString(Body); +#else + return global::System.Text.Encoding.UTF8.GetString(Body.ToArray()); +#endif + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// ... on User { + /// avatar { + /// __typename + /// url + /// } + /// } + /// ... on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQuery : global::Foo.Bar.IQQuery + { + private readonly global::StrawberryShake.IOperationExecutor _operationExecutor; + private readonly global::System.Collections.Immutable.ImmutableArray> _configure = global::System.Collections.Immutable.ImmutableArray>.Empty; + public QQuery(global::StrawberryShake.IOperationExecutor operationExecutor) + { + _operationExecutor = operationExecutor ?? throw new global::System.ArgumentNullException(nameof(operationExecutor)); + } + + private QQuery(global::StrawberryShake.IOperationExecutor operationExecutor, global::System.Collections.Immutable.ImmutableArray> configure) + { + _operationExecutor = operationExecutor; + _configure = configure; + } + + global::System.Type global::StrawberryShake.IOperationRequestFactory.ResultType => typeof(IQResult); + + public global::Foo.Bar.IQQuery With(global::System.Action configure) + { + return new global::Foo.Bar.QQuery(_operationExecutor, _configure.Add(configure)); + } + + public global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.RequestUri"] = requestUri); + } + + public global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.HttpClient"] = httpClient); + } + + public async global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default) + { + var request = CreateRequest(); + foreach (var configure in _configure) + { + configure(request); + } + + return await _operationExecutor.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + } + + public global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null) + { + var request = CreateRequest(); + return _operationExecutor.Watch(request, strategy); + } + + private global::StrawberryShake.OperationRequest CreateRequest() + { + return CreateRequest(null); + } + + private global::StrawberryShake.OperationRequest CreateRequest(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return new global::StrawberryShake.OperationRequest(id: QQueryDocument.Instance.Hash.Value, name: "Q", document: QQueryDocument.Instance, strategy: global::StrawberryShake.RequestStrategy.Default); + } + + global::StrawberryShake.OperationRequest global::StrawberryShake.IOperationRequestFactory.Create(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return CreateRequest(); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceInterfaceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// ... on User { + /// avatar { + /// __typename + /// url + /// } + /// } + /// ... on User { + /// avatar { + /// __typename + /// width + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQQuery : global::StrawberryShake.IOperationRequestFactory + { + global::Foo.Bar.IQQuery With(global::System.Action configure); + global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri); + global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient); + global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default); + global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null); + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClient : global::Foo.Bar.IFooClient + { + private readonly global::Foo.Bar.IQQuery _q; + public FooClient(global::Foo.Bar.IQQuery q) + { + _q = q ?? throw new global::System.ArgumentNullException(nameof(q)); + } + + public static global::System.String ClientName => "FooClient"; + public global::Foo.Bar.IQQuery Q => _q; + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientInterfaceGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IFooClient + { + global::Foo.Bar.IQQuery Q { get; } + } +} + +namespace Foo.Bar.State +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class UserEntity + { + public UserEntity(global::Foo.Bar.State.ImageData? avatar = default !) + { + Avatar = avatar; + } + + public global::Foo.Bar.State.ImageData? Avatar { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultDataFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultFactory : global::StrawberryShake.IOperationResultDataFactory + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityMapper _q_Me_UserFromUserEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Me_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Me_UserFromUserEntityMapper = q_Me_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Me_UserFromUserEntityMapper)); + } + + global::System.Type global::StrawberryShake.IOperationResultDataFactory.ResultType => typeof(global::Foo.Bar.IQResult); + + public QResult Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + if (dataInfo is QResultInfo info) + { + return new QResult(MapIQ_Me(info.Me, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Me? MapIQ_Me(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + return _q_Me_UserFromUserEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + throw new global::System.NotSupportedException(); + } + + global::System.Object global::StrawberryShake.IOperationResultDataFactory.Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot) + { + return Create(dataInfo, snapshot); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInfoGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultInfo : global::StrawberryShake.IOperationResultDataInfo + { + private readonly global::System.Collections.Generic.IReadOnlyCollection _entityIds; + private readonly global::System.UInt64 _version; + public QResultInfo(global::StrawberryShake.EntityId? me, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Me = me; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Me { get; } + public global::System.Collections.Generic.IReadOnlyCollection EntityIds => _entityIds; + public global::System.UInt64 Version => _version; + + public global::StrawberryShake.IOperationResultDataInfo WithVersion(global::System.UInt64 version) + { + return new QResultInfo(Me, _entityIds, version); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.JsonResultBuilderGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QBuilder : global::StrawberryShake.OperationResultBuilder + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityIdSerializer _idSerializer; + private readonly global::StrawberryShake.Serialization.ILeafValueParser _stringParser; + public QBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer)); + ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory)); + _stringParser = serializerResolver.GetLeafValueParser("String") ?? throw new global::System.ArgumentException("No serializer for type `String` found."); + } + + protected override global::StrawberryShake.IOperationResultDataFactory ResultDataFactory { get; } + + protected override global::StrawberryShake.IOperationResultDataInfo BuildData(global::System.Text.Json.JsonElement obj) + { + var entityIds = new global::System.Collections.Generic.HashSet(); + global::StrawberryShake.IEntityStoreSnapshot snapshot = default !; + global::StrawberryShake.EntityId? meId = default !; + _entityStore.Update(session => + { + meId = Update_IQ_MeEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "me"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(meId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_MeEntity(global::StrawberryShake.IEntityStoreUpdateSession session, global::System.Text.Json.JsonElement? obj, global::System.Collections.Generic.ISet entityIds) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + global::StrawberryShake.EntityId entityId = _idSerializer.Parse(obj.Value); + entityIds.Add(entityId); + if (entityId.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.UserEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_IQ_Me_Avatar(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "avatar")))); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::Foo.Bar.State.ImageData? Deserialize_IQ_Me_Avatar(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + var typename = obj.Value.GetProperty("__typename").GetString(); + if (typename?.Equals("Image", global::System.StringComparison.Ordinal) ?? false) + { + return new global::Foo.Bar.State.ImageData(typename, url: Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "url"))); + } + + throw new global::System.NotSupportedException(); + } + + private global::System.String Deserialize_NonNullableString(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + throw new global::System.ArgumentNullException(); + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + throw new global::System.ArgumentNullException(); + } + + return _stringParser.Parse(obj.Value.GetString()!); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.DataTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class ImageData + { + public ImageData(global::System.String __typename, global::System.String? url = default !) + { + this.__typename = __typename ?? throw new global::System.ArgumentNullException(nameof(__typename)); + Url = url; + } + + public global::System.String __typename { get; } + public global::System.String? Url { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Me_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Me_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Me_User(MapIQ_Me_Avatar(entity.Avatar, snapshot)); + } + + private global::Foo.Bar.IQ_Me_Avatar? MapIQ_Me_Avatar(global::Foo.Bar.State.ImageData? data, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (data is null) + { + return null; + } + + IQ_Me_Avatar returnValue = default !; + if (data.__typename.Equals("Image", global::System.StringComparison.Ordinal)) + { + returnValue = new Q_Me_Avatar_Image(data.Url ?? throw new global::System.ArgumentNullException()); + } + else + { + throw new global::System.NotSupportedException(); + } + + return returnValue; + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityIdFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientEntityIdFactory : global::StrawberryShake.IEntityIdSerializer + { + private static readonly global::System.Text.Json.JsonWriterOptions _options = new global::System.Text.Json.JsonWriterOptions() + { + Indented = false + }; + public global::StrawberryShake.EntityId Parse(global::System.Text.Json.JsonElement obj) + { + global::System.String __typename = obj.GetProperty("__typename").GetString()!; + return __typename switch + { + "User" => ParseUserEntityId(obj, __typename), + _ => throw new global::System.NotSupportedException()}; + } + + public global::System.String Format(global::StrawberryShake.EntityId entityId) + { + return entityId.Name switch + { + "User" => FormatUserEntityId(entityId), + _ => throw new global::System.NotSupportedException()}; + } + + private global::StrawberryShake.EntityId ParseUserEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatUserEntityId(global::StrawberryShake.EntityId entityId) + { + using var writer = new global::StrawberryShake.Internal.ArrayWriter(); + using var jsonWriter = new global::System.Text.Json.Utf8JsonWriter(writer, _options); + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("__typename", entityId.Name); + jsonWriter.WriteString("id", (global::System.String)entityId.Value); + jsonWriter.WriteEndObject(); + jsonWriter.Flush(); + return global::System.Text.Encoding.UTF8.GetString(writer.GetInternalBuffer(), 0, writer.Length); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.StoreAccessorGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientStoreAccessor : global::StrawberryShake.StoreAccessor + { + public FooClientStoreAccessor(global::StrawberryShake.IOperationStore operationStore, global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer entityIdSerializer, global::System.Collections.Generic.IEnumerable requestFactories, global::System.Collections.Generic.IEnumerable resultDataFactories) : base(operationStore, entityStore, entityIdSerializer, requestFactories, resultDataFactories) + { + } + } +} + +namespace Microsoft.Extensions.DependencyInjection +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.DependencyInjectionGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public static partial class FooClientServiceCollectionExtensions + { + public static global::StrawberryShake.IClientBuilder AddFooClient(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + var serviceCollection = new global::Microsoft.Extensions.DependencyInjection.ServiceCollection(); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + ConfigureClientDefault(sp, serviceCollection, strategy); + return new ClientServiceProvider(global::Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(serviceCollection)); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::Foo.Bar.State.FooClientStoreAccessor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + return new global::StrawberryShake.ClientBuilder("FooClient", services, serviceCollection); + } + + private static global::Microsoft.Extensions.DependencyInjection.IServiceCollection ConfigureClientDefault(global::System.IServiceProvider parentServices, global::Microsoft.Extensions.DependencyInjection.ServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services, sp => new global::StrawberryShake.OperationStore(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + var clientFactory = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(parentServices); + return new global::StrawberryShake.Transport.Http.HttpConnection(() => clientFactory.CreateClient("FooClient")); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Me_UserFromUserEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::StrawberryShake.Serialization.SerializerResolver(global::System.Linq.Enumerable.Concat(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(parentServices), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QResultFactory>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QBuilder>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, sp => new global::StrawberryShake.OperationExecutor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), strategy)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::StrawberryShake.Json.JsonResultPatcher>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + return services; + } + + private sealed class ClientServiceProvider : System.IServiceProvider, System.IDisposable + { + private readonly System.IServiceProvider _provider; + public ClientServiceProvider(System.IServiceProvider provider) + { + _provider = provider; + } + + public object? GetService(System.Type serviceType) + { + return _provider.GetService(serviceType); + } + + public void Dispose() + { + if (_provider is System.IDisposable d) + { + d.Dispose(); + } + } + } + } +} + + diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap new file mode 100644 index 00000000000..9c69a29d3a1 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap @@ -0,0 +1,871 @@ +// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable BuiltInTypeReferenceStyle +// ReSharper disable ConvertToAutoProperty +// ReSharper disable InconsistentNaming +// ReSharper disable PartialTypeWithSinglePart +// ReSharper disable PreferConcreteValueOverDefault +// ReSharper disable RedundantNameQualifier +// ReSharper disable SuggestVarOrType_SimpleTypes +// ReSharper disable UnusedMember.Global +// ReSharper disable UnusedMethodReturnValue.Local +// ReSharper disable UnusedType.Global +// ReSharper disable UnusedVariable + +// FooClient + +// +#nullable enable annotations +#nullable disable warnings + +namespace Foo.Bar +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResult : global::System.IEquatable, IQResult + { + public QResult(global::Foo.Bar.IQ_Me? me) + { + Me = me; + } + + public global::Foo.Bar.IQ_Me? Me { get; } + + public virtual global::System.Boolean Equals(QResult? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Me is null && other.Me is null) || Me != null && Me.Equals(other.Me))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((QResult)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Me != null) + { + hash ^= 397 * Me.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_User : global::System.IEquatable, IQ_Me_User + { + public Q_Me_User(global::Foo.Bar.IQ_Me_BestFriend? bestFriend) + { + BestFriend = bestFriend; + } + + public global::Foo.Bar.IQ_Me_BestFriend? BestFriend { get; } + + public virtual global::System.Boolean Equals(Q_Me_User? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((BestFriend is null && other.BestFriend is null) || BestFriend != null && BestFriend.Equals(other.BestFriend))); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_User)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (BestFriend != null) + { + hash ^= 397 * BestFriend.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_BestFriend_User : global::System.IEquatable, IQ_Me_BestFriend_User + { + public Q_Me_BestFriend_User(global::System.String id) + { + Id = id; + } + + public global::System.String Id { get; } + + public virtual global::System.Boolean Equals(Q_Me_BestFriend_User? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (Id.Equals(other.Id)); + } + + public override global::System.Boolean Equals(global::System.Object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((Q_Me_BestFriend_User)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + hash ^= 397 * Id.GetHashCode(); + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQResult + { + public global::Foo.Bar.IQ_Me? Me { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me + { + public global::Foo.Bar.IQ_Me_BestFriend? BestFriend { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_User : IQ_Me + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_BestFriend + { + public global::System.String Id { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me_BestFriend_User : IQ_Me_BestFriend + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// bestFriend { + /// __typename + /// id + /// ... on User { + /// id + /// } + /// } + /// ... on User { + /// bestFriend { + /// __typename + /// name + /// ... on User { + /// id + /// } + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQueryDocument : global::StrawberryShake.IDocument + { + private QQueryDocument() + { + } + + public static QQueryDocument Instance { get; } = new QQueryDocument(); + public global::StrawberryShake.OperationKind Kind => global::StrawberryShake.OperationKind.Query; + public global::System.ReadOnlySpan Body => "query Q { me { __typename bestFriend { __typename id ... on User { id } } ... on User { bestFriend { __typename name ... on User { id } } } ... on User { id } } }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "8d0cc4b150b80593858bffd2ccaf7e155750a041"); + + public override global::System.String ToString() + { +#if NETCOREAPP3_1_OR_GREATER + return global::System.Text.Encoding.UTF8.GetString(Body); +#else + return global::System.Text.Encoding.UTF8.GetString(Body.ToArray()); +#endif + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// bestFriend { + /// __typename + /// id + /// ... on User { + /// id + /// } + /// } + /// ... on User { + /// bestFriend { + /// __typename + /// name + /// ... on User { + /// id + /// } + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QQuery : global::Foo.Bar.IQQuery + { + private readonly global::StrawberryShake.IOperationExecutor _operationExecutor; + private readonly global::System.Collections.Immutable.ImmutableArray> _configure = global::System.Collections.Immutable.ImmutableArray>.Empty; + public QQuery(global::StrawberryShake.IOperationExecutor operationExecutor) + { + _operationExecutor = operationExecutor ?? throw new global::System.ArgumentNullException(nameof(operationExecutor)); + } + + private QQuery(global::StrawberryShake.IOperationExecutor operationExecutor, global::System.Collections.Immutable.ImmutableArray> configure) + { + _operationExecutor = operationExecutor; + _configure = configure; + } + + global::System.Type global::StrawberryShake.IOperationRequestFactory.ResultType => typeof(IQResult); + + public global::Foo.Bar.IQQuery With(global::System.Action configure) + { + return new global::Foo.Bar.QQuery(_operationExecutor, _configure.Add(configure)); + } + + public global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.RequestUri"] = requestUri); + } + + public global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient) + { + return With(r => r.ContextData["StrawberryShake.Transport.Http.HttpConnection.HttpClient"] = httpClient); + } + + public async global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default) + { + var request = CreateRequest(); + foreach (var configure in _configure) + { + configure(request); + } + + return await _operationExecutor.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + } + + public global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null) + { + var request = CreateRequest(); + return _operationExecutor.Watch(request, strategy); + } + + private global::StrawberryShake.OperationRequest CreateRequest() + { + return CreateRequest(null); + } + + private global::StrawberryShake.OperationRequest CreateRequest(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return new global::StrawberryShake.OperationRequest(id: QQueryDocument.Instance.Hash.Value, name: "Q", document: QQueryDocument.Instance, strategy: global::StrawberryShake.RequestStrategy.Default); + } + + global::StrawberryShake.OperationRequest global::StrawberryShake.IOperationRequestFactory.Create(global::System.Collections.Generic.IReadOnlyDictionary? variables) + { + return CreateRequest(); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationServiceInterfaceGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// bestFriend { + /// __typename + /// id + /// ... on User { + /// id + /// } + /// } + /// ... on User { + /// bestFriend { + /// __typename + /// name + /// ... on User { + /// id + /// } + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQQuery : global::StrawberryShake.IOperationRequestFactory + { + global::Foo.Bar.IQQuery With(global::System.Action configure); + global::Foo.Bar.IQQuery WithRequestUri(global::System.Uri requestUri); + global::Foo.Bar.IQQuery WithHttpClient(global::System.Net.Http.HttpClient httpClient); + global::System.Threading.Tasks.Task> ExecuteAsync(global::System.Threading.CancellationToken cancellationToken = default); + global::System.IObservable> Watch(global::StrawberryShake.ExecutionStrategy? strategy = null); + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClient : global::Foo.Bar.IFooClient + { + private readonly global::Foo.Bar.IQQuery _q; + public FooClient(global::Foo.Bar.IQQuery q) + { + _q = q ?? throw new global::System.ArgumentNullException(nameof(q)); + } + + public static global::System.String ClientName => "FooClient"; + public global::Foo.Bar.IQQuery Q => _q; + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ClientInterfaceGenerator + /// + /// Represents the FooClient GraphQL client + /// + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IFooClient + { + global::Foo.Bar.IQQuery Q { get; } + } +} + +namespace Foo.Bar.State +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class UserEntity + { + public UserEntity(global::StrawberryShake.EntityId? bestFriend = default !, global::System.String id = default !) + { + BestFriend = bestFriend; + Id = id; + } + + public global::StrawberryShake.EntityId? BestFriend { get; } + public global::System.String Id { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultDataFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultFactory : global::StrawberryShake.IOperationResultDataFactory + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityMapper _q_Me_UserFromUserEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Me_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Me_UserFromUserEntityMapper = q_Me_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Me_UserFromUserEntityMapper)); + } + + global::System.Type global::StrawberryShake.IOperationResultDataFactory.ResultType => typeof(global::Foo.Bar.IQResult); + + public QResult Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + if (dataInfo is QResultInfo info) + { + return new QResult(MapIQ_Me(info.Me, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Me? MapIQ_Me(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + return _q_Me_UserFromUserEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + throw new global::System.NotSupportedException(); + } + + global::System.Object global::StrawberryShake.IOperationResultDataFactory.Create(global::StrawberryShake.IOperationResultDataInfo dataInfo, global::StrawberryShake.IEntityStoreSnapshot? snapshot) + { + return Create(dataInfo, snapshot); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInfoGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QResultInfo : global::StrawberryShake.IOperationResultDataInfo + { + private readonly global::System.Collections.Generic.IReadOnlyCollection _entityIds; + private readonly global::System.UInt64 _version; + public QResultInfo(global::StrawberryShake.EntityId? me, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Me = me; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Me { get; } + public global::System.Collections.Generic.IReadOnlyCollection EntityIds => _entityIds; + public global::System.UInt64 Version => _version; + + public global::StrawberryShake.IOperationResultDataInfo WithVersion(global::System.UInt64 version) + { + return new QResultInfo(Me, _entityIds, version); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.JsonResultBuilderGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class QBuilder : global::StrawberryShake.OperationResultBuilder + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityIdSerializer _idSerializer; + private readonly global::StrawberryShake.Serialization.ILeafValueParser _iDParser; + public QBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer)); + ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory)); + _iDParser = serializerResolver.GetLeafValueParser("ID") ?? throw new global::System.ArgumentException("No serializer for type `ID` found."); + } + + protected override global::StrawberryShake.IOperationResultDataFactory ResultDataFactory { get; } + + protected override global::StrawberryShake.IOperationResultDataInfo BuildData(global::System.Text.Json.JsonElement obj) + { + var entityIds = new global::System.Collections.Generic.HashSet(); + global::StrawberryShake.IEntityStoreSnapshot snapshot = default !; + global::StrawberryShake.EntityId? meId = default !; + _entityStore.Update(session => + { + meId = Update_IQ_MeEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "me"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(meId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_MeEntity(global::StrawberryShake.IEntityStoreUpdateSession session, global::System.Text.Json.JsonElement? obj, global::System.Collections.Generic.ISet entityIds) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + global::StrawberryShake.EntityId entityId = _idSerializer.Parse(obj.Value); + entityIds.Add(entityId); + if (entityId.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.UserEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Update_IQ_Me_BestFriendEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "bestFriend"), entityIds), entity.Id)); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Update_IQ_Me_BestFriendEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "bestFriend"), entityIds), default !)); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::StrawberryShake.EntityId? Update_IQ_Me_BestFriendEntity(global::StrawberryShake.IEntityStoreUpdateSession session, global::System.Text.Json.JsonElement? obj, global::System.Collections.Generic.ISet entityIds) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + global::StrawberryShake.EntityId entityId = _idSerializer.Parse(obj.Value); + entityIds.Add(entityId); + if (entityId.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.UserEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(entity.BestFriend, Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(default !, Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")))); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::System.String Deserialize_NonNullableString(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + throw new global::System.ArgumentNullException(); + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + throw new global::System.ArgumentNullException(); + } + + return _iDParser.Parse(obj.Value.GetString()!); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + private readonly global::StrawberryShake.IEntityMapper _q_Me_BestFriend_UserFromUserEntityMapper; + public Q_Me_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Me_BestFriend_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Me_BestFriend_UserFromUserEntityMapper = q_Me_BestFriend_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Me_BestFriend_UserFromUserEntityMapper)); + } + + public Q_Me_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Me_User(MapIQ_Me_BestFriend(entity.BestFriend, snapshot)); + } + + private global::Foo.Bar.IQ_Me_BestFriend? MapIQ_Me_BestFriend(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("User", global::System.StringComparison.Ordinal)) + { + return _q_Me_BestFriend_UserFromUserEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + throw new global::System.NotSupportedException(); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Me_BestFriend_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Me_BestFriend_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Me_BestFriend_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Me_BestFriend_User(entity.Id); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityIdFactoryGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientEntityIdFactory : global::StrawberryShake.IEntityIdSerializer + { + private static readonly global::System.Text.Json.JsonWriterOptions _options = new global::System.Text.Json.JsonWriterOptions() + { + Indented = false + }; + public global::StrawberryShake.EntityId Parse(global::System.Text.Json.JsonElement obj) + { + global::System.String __typename = obj.GetProperty("__typename").GetString()!; + return __typename switch + { + "User" => ParseUserEntityId(obj, __typename), + _ => throw new global::System.NotSupportedException()}; + } + + public global::System.String Format(global::StrawberryShake.EntityId entityId) + { + return entityId.Name switch + { + "User" => FormatUserEntityId(entityId), + _ => throw new global::System.NotSupportedException()}; + } + + private global::StrawberryShake.EntityId ParseUserEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatUserEntityId(global::StrawberryShake.EntityId entityId) + { + using var writer = new global::StrawberryShake.Internal.ArrayWriter(); + using var jsonWriter = new global::System.Text.Json.Utf8JsonWriter(writer, _options); + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("__typename", entityId.Name); + jsonWriter.WriteString("id", (global::System.String)entityId.Value); + jsonWriter.WriteEndObject(); + jsonWriter.Flush(); + return global::System.Text.Encoding.UTF8.GetString(writer.GetInternalBuffer(), 0, writer.Length); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.StoreAccessorGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class FooClientStoreAccessor : global::StrawberryShake.StoreAccessor + { + public FooClientStoreAccessor(global::StrawberryShake.IOperationStore operationStore, global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer entityIdSerializer, global::System.Collections.Generic.IEnumerable requestFactories, global::System.Collections.Generic.IEnumerable resultDataFactories) : base(operationStore, entityStore, entityIdSerializer, requestFactories, resultDataFactories) + { + } + } +} + +namespace Microsoft.Extensions.DependencyInjection +{ + // StrawberryShake.CodeGeneration.CSharp.Generators.DependencyInjectionGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public static partial class FooClientServiceCollectionExtensions + { + public static global::StrawberryShake.IClientBuilder AddFooClient(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + var serviceCollection = new global::Microsoft.Extensions.DependencyInjection.ServiceCollection(); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + ConfigureClientDefault(sp, serviceCollection, strategy); + return new ClientServiceProvider(global::Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(serviceCollection)); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::Foo.Bar.State.FooClientStoreAccessor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + return new global::StrawberryShake.ClientBuilder("FooClient", services, serviceCollection); + } + + private static global::Microsoft.Extensions.DependencyInjection.IServiceCollection ConfigureClientDefault(global::System.IServiceProvider parentServices, global::Microsoft.Extensions.DependencyInjection.ServiceCollection services, global::StrawberryShake.ExecutionStrategy strategy = global::StrawberryShake.ExecutionStrategy.NetworkOnly) + { + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAddSingleton(services, sp => new global::StrawberryShake.OperationStore(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => + { + var clientFactory = global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(parentServices); + return new global::StrawberryShake.Transport.Http.HttpConnection(() => clientFactory.CreateClient("FooClient")); + }); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Me_UserFromUserEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Me_BestFriend_UserFromUserEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => new global::StrawberryShake.Serialization.SerializerResolver(global::System.Linq.Enumerable.Concat(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(parentServices), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)))); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QResultFactory>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.QBuilder>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, sp => new global::StrawberryShake.OperationExecutor(global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), () => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(sp), global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp), strategy)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::StrawberryShake.Json.JsonResultPatcher>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(services, sp => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(sp)); + return services; + } + + private sealed class ClientServiceProvider : System.IServiceProvider, System.IDisposable + { + private readonly System.IServiceProvider _provider; + public ClientServiceProvider(System.IServiceProvider provider) + { + _provider = provider; + } + + public object? GetService(System.Type serviceType) + { + return _provider.GetService(serviceType); + } + + public void Dispose() + { + if (_provider is System.IDisposable d) + { + d.Dispose(); + } + } + } + } +} + + From 68caf340d0b1c5bb237e55ff54a3a585b6881cae Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 13:05:36 +0200 Subject: [PATCH 2/2] chore: add UTF-8 BOM to new snapshots to match repo convention --- ...n_CompositeField_Selected_Direct_And_Via_InlineFragment.snap | 2 +- ...en_CompositeField_Selected_Direct_And_Via_NamedFragment.snap | 2 +- ...hould_Succeed_When_CompositeField_Selected_Direct_Twice.snap | 2 +- ...eed_When_CompositeField_Selected_In_Two_InlineFragments.snap | 2 +- ...ReferencingField_Selected_Direct_And_Via_InlineFragment.snap | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap index f19e934c26e..f9672ef7a92 100644 --- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_InlineFragment.snap @@ -1,4 +1,4 @@ -// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable ArrangeObjectCreationWhenTypeEvident // ReSharper disable BuiltInTypeReferenceStyle // ReSharper disable ConvertToAutoProperty // ReSharper disable InconsistentNaming diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap index 5d80fc25a56..c95029ad6fd 100644 --- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_And_Via_NamedFragment.snap @@ -1,4 +1,4 @@ -// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable ArrangeObjectCreationWhenTypeEvident // ReSharper disable BuiltInTypeReferenceStyle // ReSharper disable ConvertToAutoProperty // ReSharper disable InconsistentNaming diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap index 99d241874e6..f7166b6517f 100644 --- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_Direct_Twice.snap @@ -1,4 +1,4 @@ -// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable ArrangeObjectCreationWhenTypeEvident // ReSharper disable BuiltInTypeReferenceStyle // ReSharper disable ConvertToAutoProperty // ReSharper disable InconsistentNaming diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap index 0eb1074b5d1..3d1b5c8487e 100644 --- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_CompositeField_Selected_In_Two_InlineFragments.snap @@ -1,4 +1,4 @@ -// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable ArrangeObjectCreationWhenTypeEvident // ReSharper disable BuiltInTypeReferenceStyle // ReSharper disable ConvertToAutoProperty // ReSharper disable InconsistentNaming diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap index 9c69a29d3a1..d1728a03627 100644 --- a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/FragmentDirectAndSpreadGeneratorTests.Generate_Should_Succeed_When_SelfReferencingField_Selected_Direct_And_Via_InlineFragment.snap @@ -1,4 +1,4 @@ -// ReSharper disable ArrangeObjectCreationWhenTypeEvident +// ReSharper disable ArrangeObjectCreationWhenTypeEvident // ReSharper disable BuiltInTypeReferenceStyle // ReSharper disable ConvertToAutoProperty // ReSharper disable InconsistentNaming