diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FragmentHelper.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FragmentHelper.cs index de8be54c391..62a778d43ac 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FragmentHelper.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FragmentHelper.cs @@ -455,8 +455,16 @@ private static IReadOnlyList CreateImplements( var fields = new HashSet(); levels.Push(fields); - implements.Add( - CreateInterface(context, child, selectionPath, levels, rootImplements)); + var @interface = + CreateInterface(context, child, selectionPath, levels, rootImplements); + + // the same named fragment can be spread more than once in a single selection + // set. Each spread resolves to the same cached interface model, so we must not + // list it twice or the generated type would declare a duplicate base interface. + if (!implements.Contains(@interface)) + { + implements.Add(@interface); + } // we add all the fields of this interface to the parent fields level so that we // do not create the interface field multiple time on the various levels. diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/DuplicateFragmentSpreadGeneratorTests.cs b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/DuplicateFragmentSpreadGeneratorTests.cs new file mode 100644 index 00000000000..14a7eda806c --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/DuplicateFragmentSpreadGeneratorTests.cs @@ -0,0 +1,96 @@ +using static StrawberryShake.CodeGeneration.CSharp.GeneratorTestHelper; + +namespace StrawberryShake.CodeGeneration.CSharp; + +public class DuplicateFragmentSpreadGeneratorTests +{ + private const string Schema = + "interface Node { id: ID! } " + + "type Query { me: User node(id: ID!): Node pet: Pet } " + + "type User implements Node { id: ID! name: String email: String bestFriend: User } " + + "union Pet = Dog | Cat " + + "type Dog { id: ID! name: String } " + + "type Cat { id: ID! name: String }"; + + private const string KeyExtension = "extend schema @key(fields: \"id\")"; + + [Fact] + public void Generate_Should_Compile_When_Same_Object_Fragment_Spread_Twice() + { + // arrange + // spreading the same fragment twice must not list its interface twice (CS0528). + + // act & assert + AssertResult( + "query Q { me { ...UF ...UF } } fragment UF on User { id name }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Compile_When_Same_Interface_Fragment_Spread_Twice() + { + // arrange + // duplicate spread on an interface-typed field must dedupe the base interface list. + + // act & assert + AssertResult( + "query Q { node(id: \"1\") { ...NF ...NF } } fragment NF on Node { id }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Compile_When_Single_Fragment_Spread() + { + // arrange + // control: a single spread already works and must keep working. + + // act & assert + AssertResult( + "query Q { me { ...UF } } fragment UF on User { id name }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Compile_When_Two_Different_Fragments_Spread() + { + // arrange + // control: two distinct fragments must both remain in the interface list. + + // act & assert + AssertResult( + "query Q { me { ...UF ...UG } } " + + "fragment UF on User { id name } " + + "fragment UG on User { email }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Compile_When_Same_Fragment_Spread_At_Different_Levels() + { + // arrange + // control: the same fragment at different selection levels must each be emitted. + + // act & assert + AssertResult( + "query Q { me { ...UF bestFriend { ...UF } } } fragment UF on User { id name }", + Schema, + KeyExtension); + } + + [Fact] + public void Generate_Should_Compile_When_Same_Fragment_Spread_Twice_On_Union_Member() + { + // arrange + // duplicate spread targeting a union member must also dedupe the base interface list. + + // act & assert + AssertResult( + "query Q { pet { ...DF ...DF } } fragment DF on Dog { name }", + Schema, + KeyExtension); + } +} diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Fragment_Spread_At_Different_Levels.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Fragment_Spread_At_Different_Levels.snap new file mode 100644 index 00000000000..672d1c10d6b --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Fragment_Spread_At_Different_Levels.snap @@ -0,0 +1,905 @@ +// 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::System.String id, global::System.String? name, global::Foo.Bar.IQ_Me_BestFriend? bestFriend) + { + Id = id; + Name = name; + BestFriend = bestFriend; + } + + public global::System.String Id { get; } + public global::System.String? Name { get; } + 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 (Id.Equals(other.Id)) && ((Name is null && other.Name is null) || Name != null && Name.Equals(other.Name)) && ((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; + hash ^= 397 * Id.GetHashCode(); + if (Name != null) + { + hash ^= 397 * Name.GetHashCode(); + } + + 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, global::System.String? name) + { + Id = id; + Name = name; + } + + public global::System.String Id { get; } + public global::System.String? Name { 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)) && ((Name is null && other.Name is null) || Name != null && Name.Equals(other.Name)); + } + + 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(); + if (Name != null) + { + hash ^= 397 * Name.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::System.String Id { get; } + public global::System.String? Name { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me : IUF + { + 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 : IUF + { + } + + // 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 + /// ...UF + /// bestFriend { + /// __typename + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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 ...UF bestFriend { __typename ...UF ... on User { id } } ... on User { id } } } fragment UF on User { id name }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "d74ee670ff3afc4f832cdee839cf6549a12e8248"); + + 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 + /// ...UF + /// bestFriend { + /// __typename + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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 + /// ...UF + /// bestFriend { + /// __typename + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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::System.String id = default !, global::System.String? name = default !, global::StrawberryShake.EntityId? bestFriend = default !) + { + Id = id; + Name = name; + BestFriend = bestFriend; + } + + public global::System.String Id { get; } + public global::System.String? Name { get; } + public global::StrawberryShake.EntityId? BestFriend { 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; + 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)); + _iDParser = serializerResolver.GetLeafValueParser("ID") ?? throw new global::System.ArgumentException("No serializer for type `ID` found."); + _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_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")), Update_IQ_Me_BestFriendEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "bestFriend"), entityIds))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")), Update_IQ_Me_BestFriendEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "bestFriend"), entityIds))); + } + + 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()!); + } + + private global::System.String? Deserialize_String(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + return _stringParser.Parse(obj.Value.GetString()!); + } + + 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(Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")), entity.BestFriend)); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")), default !)); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + } + + // 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(entity.Id, entity.Name, 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, entity.Name); + } + } + + // 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(); + } + } + } + } +} + + diff --git a/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Fragment_Spread_Twice_On_Union_Member.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Fragment_Spread_Twice_On_Union_Member.snap new file mode 100644 index 00000000000..01909566955 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Fragment_Spread_Twice_On_Union_Member.snap @@ -0,0 +1,841 @@ +// 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_Pet? pet) + { + Pet = pet; + } + + public global::Foo.Bar.IQ_Pet? Pet { 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 (((Pet is null && other.Pet is null) || Pet != null && Pet.Equals(other.Pet))); + } + + 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 (Pet != null) + { + hash ^= 397 * Pet.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Pet_Dog : global::System.IEquatable, IQ_Pet_Dog + { + public Q_Pet_Dog(global::System.String? name) + { + Name = name; + } + + public global::System.String? Name { get; } + + public virtual global::System.Boolean Equals(Q_Pet_Dog? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return (((Name is null && other.Name is null) || Name != null && Name.Equals(other.Name))); + } + + 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_Pet_Dog)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + if (Name != null) + { + hash ^= 397 * Name.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Pet_Cat : global::System.IEquatable, IQ_Pet_Cat + { + public Q_Pet_Cat() + { + } + + public virtual global::System.Boolean Equals(Q_Pet_Cat? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (other.GetType() != GetType()) + { + return false; + } + + return true; + } + + 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_Pet_Cat)obj); + } + + public override global::System.Int32 GetHashCode() + { + unchecked + { + int hash = 5; + 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_Pet? Pet { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Pet + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IDF + { + public global::System.String? Name { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Pet_Dog : IQ_Pet, IDF + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Pet_Cat : IQ_Pet + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// pet { + /// __typename + /// ...DF + /// ...DF + /// ... on Dog { + /// id + /// } + /// ... on Cat { + /// id + /// } + /// } + /// } + /// + /// fragment DF on Dog { + /// name + /// } + /// + /// + [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 { pet { __typename ...DF ...DF ... on Dog { id } ... on Cat { id } } } fragment DF on Dog { name }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "6de07ea4f0c8bf144ba023790250fbefc8e1918d"); + + 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 { + /// pet { + /// __typename + /// ...DF + /// ...DF + /// ... on Dog { + /// id + /// } + /// ... on Cat { + /// id + /// } + /// } + /// } + /// + /// fragment DF on Dog { + /// name + /// } + /// + /// + [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 { + /// pet { + /// __typename + /// ...DF + /// ...DF + /// ... on Dog { + /// id + /// } + /// ... on Cat { + /// id + /// } + /// } + /// } + /// + /// fragment DF on Dog { + /// name + /// } + /// + /// + [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 DogEntity + { + public DogEntity(global::System.String? name = default !) + { + Name = name; + } + + public global::System.String? Name { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.EntityTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")] + public partial class CatEntity + { + } + + // 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_Pet_DogFromDogEntityMapper; + private readonly global::StrawberryShake.IEntityMapper _q_Pet_CatFromCatEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Pet_DogFromDogEntityMapper, global::StrawberryShake.IEntityMapper q_Pet_CatFromCatEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Pet_DogFromDogEntityMapper = q_Pet_DogFromDogEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Pet_DogFromDogEntityMapper)); + _q_Pet_CatFromCatEntityMapper = q_Pet_CatFromCatEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Pet_CatFromCatEntityMapper)); + } + + 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_Pet(info.Pet, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Pet? MapIQ_Pet(global::StrawberryShake.EntityId? entityId, global::StrawberryShake.IEntityStoreSnapshot snapshot) + { + if (entityId is null) + { + return null; + } + + if (entityId.Value.Name.Equals("Dog", global::System.StringComparison.Ordinal)) + { + return _q_Pet_DogFromDogEntityMapper.Map(snapshot.GetEntity(entityId.Value) ?? throw new global::StrawberryShake.GraphQLClientException()); + } + + if (entityId.Value.Name.Equals("Cat", global::System.StringComparison.Ordinal)) + { + return _q_Pet_CatFromCatEntityMapper.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? pet, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Pet = pet; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Pet { 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(Pet, _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? petId = default !; + _entityStore.Update(session => + { + petId = Update_IQ_PetEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "pet"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(petId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_PetEntity(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("Dog", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.DogEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.DogEntity(Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.DogEntity(Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")))); + } + + return entityId; + } + + if (entityId.Name.Equals("Cat", global::System.StringComparison.Ordinal)) + { + if (session.CurrentSnapshot.TryGetEntity(entityId, out global::Foo.Bar.State.CatEntity? entity)) + { + session.SetEntity(entityId, new global::Foo.Bar.State.CatEntity()); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.CatEntity()); + } + + return entityId; + } + + throw new global::System.NotSupportedException(); + } + + private global::System.String? Deserialize_String(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + return _stringParser.Parse(obj.Value.GetString()!); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Pet_DogFromDogEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Pet_DogFromDogEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Pet_Dog Map(global::Foo.Bar.State.DogEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Pet_Dog(entity.Name); + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultFromEntityTypeMapperGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Pet_CatFromCatEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Pet_CatFromCatEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Pet_Cat Map(global::Foo.Bar.State.CatEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Pet_Cat(); + } + } + + // 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 + { + "Dog" => ParseDogEntityId(obj, __typename), + "Cat" => ParseCatEntityId(obj, __typename), + _ => throw new global::System.NotSupportedException()}; + } + + public global::System.String Format(global::StrawberryShake.EntityId entityId) + { + return entityId.Name switch + { + "Dog" => FormatDogEntityId(entityId), + "Cat" => FormatCatEntityId(entityId), + _ => throw new global::System.NotSupportedException()}; + } + + private global::StrawberryShake.EntityId ParseDogEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatDogEntityId(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); + } + + private global::StrawberryShake.EntityId ParseCatEntityId(global::System.Text.Json.JsonElement obj, global::System.String type) + { + return new global::StrawberryShake.EntityId(type, obj.GetProperty("id").GetString()!); + } + + private global::System.String FormatCatEntityId(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_Pet_DogFromDogEntityMapper>(services); + global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Foo.Bar.State.Q_Pet_CatFromCatEntityMapper>(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__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Interface_Fragment_Spread_Twice.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Interface_Fragment_Spread_Twice.snap new file mode 100644 index 00000000000..2841ff461ae --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Interface_Fragment_Spread_Twice.snap @@ -0,0 +1,696 @@ +// 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_Node? node) + { + Node = node; + } + + public global::Foo.Bar.IQ_Node? Node { 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 (((Node is null && other.Node is null) || Node != null && Node.Equals(other.Node))); + } + + 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 (Node != null) + { + hash ^= 397 * Node.GetHashCode(); + } + + return hash; + } + } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial class Q_Node_User : global::System.IEquatable, IQ_Node_User + { + public Q_Node_User(global::System.String id) + { + Id = id; + } + + public global::System.String Id { get; } + + public virtual global::System.Boolean Equals(Q_Node_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_Node_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_Node? Node { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface INF + { + public global::System.String Id { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Node : INF + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Node_User : IQ_Node + { + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// node(id: "1") { + /// __typename + /// ...NF + /// ...NF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment NF on Node { + /// 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 { node(id: \"1\") { __typename ...NF ...NF ... on User { id } } } fragment NF on Node { id }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "05f3da2fff3b0a1e4138ba461ebec1075e2f2373"); + + 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 { + /// node(id: "1") { + /// __typename + /// ...NF + /// ...NF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment NF on Node { + /// 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 { + /// node(id: "1") { + /// __typename + /// ...NF + /// ...NF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment NF on Node { + /// 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::System.String id = default !) + { + Id = id; + } + + 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_Node_UserFromUserEntityMapper; + public QResultFactory(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityMapper q_Node_UserFromUserEntityMapper) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + _q_Node_UserFromUserEntityMapper = q_Node_UserFromUserEntityMapper ?? throw new global::System.ArgumentNullException(nameof(q_Node_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_Node(info.Node, snapshot)); + } + + throw new global::System.ArgumentException("QResultInfo expected."); + } + + private global::Foo.Bar.IQ_Node? MapIQ_Node(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_Node_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? node, global::System.Collections.Generic.IReadOnlyCollection entityIds, global::System.UInt64 version) + { + Node = node; + _entityIds = entityIds ?? throw new global::System.ArgumentNullException(nameof(entityIds)); + _version = version; + } + + public global::StrawberryShake.EntityId? Node { 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(Node, _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? nodeId = default !; + _entityStore.Update(session => + { + nodeId = Update_IQ_NodeEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "node"), entityIds); + snapshot = session.CurrentSnapshot; + }); + return new QResultInfo(nodeId, entityIds, snapshot.Version); + } + + private global::StrawberryShake.EntityId? Update_IQ_NodeEntity(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_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(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_Node_UserFromUserEntityMapper : global::StrawberryShake.IEntityMapper + { + private readonly global::StrawberryShake.IEntityStore _entityStore; + public Q_Node_UserFromUserEntityMapper(global::StrawberryShake.IEntityStore entityStore) + { + _entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore)); + } + + public Q_Node_User Map(global::Foo.Bar.State.UserEntity entity, global::StrawberryShake.IEntityStoreSnapshot? snapshot = null) + { + if (snapshot is null) + { + snapshot = _entityStore.CurrentSnapshot; + } + + return new Q_Node_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_Node_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__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Object_Fragment_Spread_Twice.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Object_Fragment_Spread_Twice.snap new file mode 100644 index 00000000000..6e01590bb21 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Same_Object_Fragment_Spread_Twice.snap @@ -0,0 +1,726 @@ +// 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::System.String id, global::System.String? name) + { + Id = id; + Name = name; + } + + public global::System.String Id { get; } + public global::System.String? Name { 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 (Id.Equals(other.Id)) && ((Name is null && other.Name is null) || Name != null && Name.Equals(other.Name)); + } + + 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; + hash ^= 397 * Id.GetHashCode(); + if (Name != null) + { + hash ^= 397 * Name.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::System.String Id { get; } + public global::System.String? Name { 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.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// ...UF + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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 ...UF ...UF ... on User { id } } } fragment UF on User { id name }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "71be448f229f1312d28d3b91e79710a8df60ea5a"); + + 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 + /// ...UF + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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 + /// ...UF + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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::System.String id = default !, global::System.String? name = default !) + { + Id = id; + Name = name; + } + + public global::System.String Id { get; } + public global::System.String? Name { 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; + 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)); + _iDParser = serializerResolver.GetLeafValueParser("ID") ?? throw new global::System.ArgumentException("No serializer for type `ID` found."); + _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_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")))); + } + + 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()!); + } + + private global::System.String? Deserialize_String(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + return _stringParser.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; + 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(entity.Id, entity.Name); + } + } + + // 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__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Single_Fragment_Spread.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Single_Fragment_Spread.snap new file mode 100644 index 00000000000..b6783a78b1e --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Single_Fragment_Spread.snap @@ -0,0 +1,723 @@ +// 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::System.String id, global::System.String? name) + { + Id = id; + Name = name; + } + + public global::System.String Id { get; } + public global::System.String? Name { 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 (Id.Equals(other.Id)) && ((Name is null && other.Name is null) || Name != null && Name.Equals(other.Name)); + } + + 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; + hash ^= 397 * Id.GetHashCode(); + if (Name != null) + { + hash ^= 397 * Name.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::System.String Id { get; } + public global::System.String? Name { 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.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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 ...UF ... on User { id } } } fragment UF on User { id name }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "f7ed571f5ace501da96de73ac2f435910d704def"); + + 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 + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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 + /// ...UF + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// + [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::System.String id = default !, global::System.String? name = default !) + { + Id = id; + Name = name; + } + + public global::System.String Id { get; } + public global::System.String? Name { 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; + 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)); + _iDParser = serializerResolver.GetLeafValueParser("ID") ?? throw new global::System.ArgumentException("No serializer for type `ID` found."); + _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_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")))); + } + + 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()!); + } + + private global::System.String? Deserialize_String(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + return _stringParser.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; + 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(entity.Id, entity.Name); + } + } + + // 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__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Two_Different_Fragments_Spread.snap b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Two_Different_Fragments_Spread.snap new file mode 100644 index 00000000000..4584fe2a4d6 --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/__snapshots__/DuplicateFragmentSpreadGeneratorTests.Generate_Should_Compile_When_Two_Different_Fragments_Spread.snap @@ -0,0 +1,754 @@ +// 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::System.String id, global::System.String? name, global::System.String? email) + { + Id = id; + Name = name; + Email = email; + } + + public global::System.String Id { get; } + public global::System.String? Name { get; } + public global::System.String? Email { 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 (Id.Equals(other.Id)) && ((Name is null && other.Name is null) || Name != null && Name.Equals(other.Name)) && ((Email is null && other.Email is null) || Email != null && Email.Equals(other.Email)); + } + + 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; + hash ^= 397 * Id.GetHashCode(); + if (Name != null) + { + hash ^= 397 * Name.GetHashCode(); + } + + if (Email != null) + { + hash ^= 397 * Email.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::System.String Id { get; } + public global::System.String? Name { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IUG + { + public global::System.String? Email { get; } + } + + // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator + [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")] + public partial interface IQ_Me : IUF, IUG + { + } + + // 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.OperationDocumentGenerator + /// + /// Represents the operation service of the Q GraphQL operation + /// + /// query Q { + /// me { + /// __typename + /// ...UF + /// ...UG + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// fragment UG on User { + /// email + /// } + /// + /// + [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 ...UF ...UG ... on User { id } } } fragment UF on User { id name } fragment UG on User { email }"u8; + public global::StrawberryShake.DocumentHash Hash { get; } = new global::StrawberryShake.DocumentHash("sha1Hash", "0262c25f22fb0fa110c488bcc536a03cd2d4931a"); + + 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 + /// ...UF + /// ...UG + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// fragment UG on User { + /// email + /// } + /// + /// + [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 + /// ...UF + /// ...UG + /// ... on User { + /// id + /// } + /// } + /// } + /// + /// fragment UF on User { + /// id + /// name + /// } + /// + /// fragment UG on User { + /// email + /// } + /// + /// + [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::System.String id = default !, global::System.String? name = default !, global::System.String? email = default !) + { + Id = id; + Name = name; + Email = email; + } + + public global::System.String Id { get; } + public global::System.String? Name { get; } + public global::System.String? Email { 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; + 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)); + _iDParser = serializerResolver.GetLeafValueParser("ID") ?? throw new global::System.ArgumentException("No serializer for type `ID` found."); + _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_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "email")))); + } + else + { + session.SetEntity(entityId, new global::Foo.Bar.State.UserEntity(Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "name")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "email")))); + } + + 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()!); + } + + private global::System.String? Deserialize_String(global::System.Text.Json.JsonElement? obj) + { + if (!obj.HasValue) + { + return null; + } + + if (obj.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null) + { + return null; + } + + return _stringParser.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; + 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(entity.Id, entity.Name, entity.Email); + } + } + + // 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(); + } + } + } + } +} + +