diff --git a/src/TestApp/ZeroQL.TestApp/Generated/GraphQL.g.cs b/src/TestApp/ZeroQL.TestApp/Generated/GraphQL.g.cs index 6f953d3..f65da3b 100644 --- a/src/TestApp/ZeroQL.TestApp/Generated/GraphQL.g.cs +++ b/src/TestApp/ZeroQL.TestApp/Generated/GraphQL.g.cs @@ -1,4 +1,4 @@ -// 291685ad31ee73dba6a2172b2f6dcc25 +// f63f7a964078b30c19f6630749226655 // This file generated for ZeroQL. // #pragma warning disable 8618 diff --git a/src/ZeroQL.SourceGenerators/Generator/GraphQLLambdaIncrementalSourceGenerator.cs b/src/ZeroQL.SourceGenerators/Generator/GraphQLLambdaIncrementalSourceGenerator.cs index 41f9f1d..ac1d8b4 100644 --- a/src/ZeroQL.SourceGenerators/Generator/GraphQLLambdaIncrementalSourceGenerator.cs +++ b/src/ZeroQL.SourceGenerators/Generator/GraphQLLambdaIncrementalSourceGenerator.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -15,19 +17,33 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var invocations = context.SyntaxProvider .CreateSyntaxProvider(FindMethods, (c, ct) => (Invocation: (InvocationExpressionSyntax)c.Node, c.SemanticModel)); - context.RegisterImplementationSourceOutput(invocations, (sourceContext, data) => - Utils.ErrorWrapper(sourceContext, data.Invocation,() => GenerateSource(sourceContext, data))); + var collectedInvocations = invocations.Collect(); + + context.RegisterImplementationSourceOutput(collectedInvocations, GenerateSource); } - + private void GenerateSource( SourceProductionContext context, - (InvocationExpressionSyntax Invocation, SemanticModel SemanticModel) input) + ImmutableArray<(InvocationExpressionSyntax Invocation, SemanticModel SemanticModel)> invocations) { - var (invocation, semanticModel) = input; - if (context.CancellationToken.IsCancellationRequested) + var processed = new HashSet(); + foreach (var input in invocations) { - return; + var (invocation, semanticModel) = input; + if (context.CancellationToken.IsCancellationRequested) + { + return; + } + + Utils.ErrorWrapper( + context, + invocation, + () => GenerateFile(context, invocation, semanticModel, processed)); } + } + + private static void GenerateFile(SourceProductionContext context, InvocationExpressionSyntax? invocation, SemanticModel? semanticModel, HashSet processed) + { var resolver = new GraphQLLambdaLikeContextResolver(); var (lambdaContext, error) = resolver.Resolve(invocation, semanticModel, context.CancellationToken).Unwrap(); @@ -65,6 +81,12 @@ private void GenerateSource( return; } + if (processed.Contains(lambdaContext.OperationHash)) + { + return; + } + + processed.Add(lambdaContext.OperationHash); context.AddSource($"ZeroQLModuleInitializer.{lambdaContext.OperationHash}.g.cs", source); } diff --git a/src/ZeroQL.SourceGenerators/Generator/GraphQLRequestIncrementalSourceGenerator.cs b/src/ZeroQL.SourceGenerators/Generator/GraphQLRequestIncrementalSourceGenerator.cs index 7096d59..2ca1f0e 100644 --- a/src/ZeroQL.SourceGenerators/Generator/GraphQLRequestIncrementalSourceGenerator.cs +++ b/src/ZeroQL.SourceGenerators/Generator/GraphQLRequestIncrementalSourceGenerator.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; @@ -18,14 +20,27 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .CreateSyntaxProvider(FindGraphQLRequests, (c, ct) => (Record: (RecordDeclarationSyntax)c.Node, c.SemanticModel)); - context.RegisterImplementationSourceOutput(invocations, (sourceContext, data) => - Utils.ErrorWrapper(sourceContext, data.Record, () => GenerateSource(sourceContext, data))); + var collectedInvocations = invocations.Collect(); + + context.RegisterImplementationSourceOutput(collectedInvocations, GenerateSource); } private void GenerateSource(SourceProductionContext context, - (RecordDeclarationSyntax Record, SemanticModel SemanticModel) input) + ImmutableArray<(RecordDeclarationSyntax Record, SemanticModel SemanticModel)> invocations) + { + var processed = new HashSet(); + foreach (var input in invocations) + { + var (record, semanticModel) = input; + Utils.ErrorWrapper( + context, + record, + () => GenerateFile(context, semanticModel, record, processed)); + } + } + + private void GenerateFile(SourceProductionContext context, SemanticModel semanticModel, RecordDeclarationSyntax record, HashSet processed) { - var (record, semanticModel) = input; var recordSymbol = semanticModel.GetDeclaredSymbol(record); var graphQLRequest = semanticModel.Compilation.GetTypeByMetadataName("ZeroQL.GraphQL`2"); @@ -67,6 +82,12 @@ private void GenerateSource(SourceProductionContext context, return; } + if (processed.Contains(requestLikeContext.OperationHash)) + { + return; + } + + processed.Add(requestLikeContext.OperationHash); context.AddSource($"ZeroQLModuleInitializer.{requestLikeContext.OperationHash}.g.cs", source); } diff --git a/src/ZeroQL.SourceGenerators/Resolver/GraphQLSourceResolver.cs b/src/ZeroQL.SourceGenerators/Resolver/GraphQLSourceResolver.cs index 38e76e8..e679483 100644 --- a/src/ZeroQL.SourceGenerators/Resolver/GraphQLSourceResolver.cs +++ b/src/ZeroQL.SourceGenerators/Resolver/GraphQLSourceResolver.cs @@ -27,6 +27,8 @@ public static string Resolve( using ZeroQL.Json; using ZeroQL.Internal; +#nullable enable + namespace {semanticModel.Compilation.Assembly.Name} {{ {SourceGeneratorInfo.CodeGenerationAttribute} @@ -44,9 +46,9 @@ public static void Init() }}; }} - public static async Task> Execute(IGraphQLClient qlClient, string queryKey, object variablesObject, CancellationToken cancellationToken) + public static async Task> Execute(IGraphQLClient qlClient, string queryKey, object? variablesObject, CancellationToken cancellationToken) {{ - var variables = ({context.RequestExecutorInputSymbol.ToGlobalName()})variablesObject; + var variables = ({context.RequestExecutorInputSymbol.ToGlobalName()})variablesObject!; var qlResponse = await qlClient.QueryPipeline.ExecuteAsync<{context.QueryTypeName}>(qlClient.HttpClient, queryKey, variablesObject, cancellationToken, queryRequest => {{ {GraphQLUploadResolver.GenerateRequestPreparations(graphQLInputTypeSafeName, typeInfo)} diff --git a/src/ZeroQL.Tests/CLI/ModuleInitializer.cs b/src/ZeroQL.Tests/CLI/ModuleInitializer.cs new file mode 100644 index 0000000..645392b --- /dev/null +++ b/src/ZeroQL.Tests/CLI/ModuleInitializer.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +namespace ZeroQL.Tests.CLI; + +public static class ModuleInitializer +{ + [ModuleInitializer] + public static void Initialize() + { + VerifyNodaTime.Enable(); + } +} \ No newline at end of file diff --git a/src/ZeroQL.Tests/Core/IntegrationTest.cs b/src/ZeroQL.Tests/Core/IntegrationTest.cs index 03d4ee6..76a7d15 100644 --- a/src/ZeroQL.Tests/Core/IntegrationTest.cs +++ b/src/ZeroQL.Tests/Core/IntegrationTest.cs @@ -1,6 +1,8 @@ using Xunit; using ZeroQL.Tests.Core.Fixtures; +[assembly: CollectionBehavior(DisableTestParallelization = true)] + namespace ZeroQL.Tests.Core; [Collection("Integration")] diff --git a/src/ZeroQL.Tests/Data/TestProject.cs b/src/ZeroQL.Tests/Data/TestProject.cs index 3b68d13..5242c9d 100644 --- a/src/ZeroQL.Tests/Data/TestProject.cs +++ b/src/ZeroQL.Tests/Data/TestProject.cs @@ -17,7 +17,6 @@ public static class TestProject static TestProject() { - VerifyNodaTime.Enable(); var manager = new AnalyzerManager(); manager.GetProject(@"../../../../TestApp/ZeroQL.TestApp/ZeroQL.TestApp.csproj"); Workspace = manager.GetWorkspace(); diff --git a/src/ZeroQL.Tests/SourceGeneration/QueryTests.LambdaModuleInitializerGenerated.verified.txt b/src/ZeroQL.Tests/SourceGeneration/QueryTests.LambdaModuleInitializerGenerated.verified.txt index 5b02e6c..6da446f 100644 --- a/src/ZeroQL.Tests/SourceGeneration/QueryTests.LambdaModuleInitializerGenerated.verified.txt +++ b/src/ZeroQL.Tests/SourceGeneration/QueryTests.LambdaModuleInitializerGenerated.verified.txt @@ -13,6 +13,8 @@ using ZeroQL.Stores; using ZeroQL.Json; using ZeroQL.Internal; +#nullable enable + namespace ZeroQL.TestApp { [System.CodeDom.Compiler.GeneratedCode("ZeroQL", "1.0.0.0")] @@ -30,9 +32,9 @@ namespace ZeroQL.TestApp }; } - public static async Task> Execute(IGraphQLClient qlClient, string queryKey, object variablesObject, CancellationToken cancellationToken) + public static async Task> Execute(IGraphQLClient qlClient, string queryKey, object? variablesObject, CancellationToken cancellationToken) { - var variables = (global::ZeroQL.Unit)variablesObject; + var variables = (global::ZeroQL.Unit)variablesObject!; var qlResponse = await qlClient.QueryPipeline.ExecuteAsync(qlClient.HttpClient, queryKey, variablesObject, cancellationToken, queryRequest => {