Skip to content

Commit 7951b9d

Browse files
committed
Fixed regression in DataLoader source generator. (#8610)
1 parent 5fe2b7e commit 7951b9d

File tree

5 files changed

+269
-0
lines changed

5 files changed

+269
-0
lines changed

src/HotChocolate/Core/src/Types.Analyzers/Helpers/SymbolExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ public static string ToFullyQualifiedWithNullRefQualifier(this ITypeSymbol typeS
4141

4242
public static string ToNullableFullyQualifiedWithNullRefQualifier(this ITypeSymbol typeSymbol)
4343
{
44+
if (typeSymbol.IsValueType)
45+
{
46+
return typeSymbol.ToFullyQualifiedWithNullRefQualifier();
47+
}
48+
4449
var value = typeSymbol.ToFullyQualifiedWithNullRefQualifier();
4550
return value[value.Length - 1] != '?' ? value + "?" : value;
4651
}

src/HotChocolate/Core/test/Types.Analyzers.Tests/DataLoaderTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,54 @@ namespace HotChocolate.Types;
22

33
public class DataLoaderTests
44
{
5+
[Fact]
6+
public async Task GenerateSource_BatchDataLoader_With_ValueType_Result_MatchesSnapshot()
7+
{
8+
await TestHelper.GetGeneratedSourceSnapshot(
9+
"""
10+
using System.Collections.Generic;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
using HotChocolate;
14+
using GreenDonut;
15+
16+
namespace TestNamespace;
17+
18+
internal static class TestClass
19+
{
20+
[DataLoader]
21+
public static Task<IReadOnlyDictionary<int, long>> GetEntityByIdAsync(
22+
IReadOnlyList<int> entityIds,
23+
CancellationToken cancellationToken)
24+
=> default!;
25+
}
26+
""").MatchMarkdownAsync();
27+
}
28+
29+
[Fact]
30+
public async Task GenerateSource_BatchDataLoader_With_Nullable_ValueType_Result_MatchesSnapshot()
31+
{
32+
await TestHelper.GetGeneratedSourceSnapshot(
33+
"""
34+
using System.Collections.Generic;
35+
using System.Threading;
36+
using System.Threading.Tasks;
37+
using HotChocolate;
38+
using GreenDonut;
39+
40+
namespace TestNamespace;
41+
42+
internal static class TestClass
43+
{
44+
[DataLoader]
45+
public static Task<IReadOnlyDictionary<int, long?>> GetEntityByIdAsync(
46+
IReadOnlyList<int> entityIds,
47+
CancellationToken cancellationToken)
48+
=> default!;
49+
}
50+
""").MatchMarkdownAsync();
51+
}
52+
553
[Fact]
654
public async Task GenerateSource_BatchDataLoader_MatchesSnapshot()
755
{

src/HotChocolate/Core/test/Types.Analyzers.Tests/Types/DataLoaders.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,20 @@ public static async Task<IDictionary<int, Author>> GetAuthorWithPagingById(
8181
PagingArguments paging,
8282
CancellationToken ct)
8383
=> await Task.FromResult(query.ToDictionary(t => t.Id));
84+
85+
[DataLoader]
86+
public static Task<IDictionary<long, long>> GetLongValuesByLong(
87+
IReadOnlyList<long> keys,
88+
IQueryable<Author> query,
89+
PagingArguments paging,
90+
CancellationToken ct)
91+
=> default!;
92+
93+
[DataLoader]
94+
public static Task<IDictionary<long, long?>> GetNullableLongValuesByLong(
95+
IReadOnlyList<long> keys,
96+
IQueryable<Author> query,
97+
PagingArguments paging,
98+
CancellationToken ct)
99+
=> default!;
84100
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# GenerateSource_BatchDataLoader_With_Nullable_ValueType_Result_MatchesSnapshot
2+
3+
## GreenDonutDataLoader.735550c.g.cs
4+
5+
```csharp
6+
// <auto-generated/>
7+
8+
#nullable enable
9+
#pragma warning disable
10+
11+
using System;
12+
using System.Runtime.CompilerServices;
13+
using Microsoft.Extensions.DependencyInjection;
14+
using GreenDonut;
15+
16+
namespace TestNamespace
17+
{
18+
public interface IEntityByIdDataLoader
19+
: global::GreenDonut.IDataLoader<int, long?>
20+
{
21+
}
22+
23+
public sealed partial class EntityByIdDataLoader
24+
: global::GreenDonut.DataLoaderBase<int, long?>
25+
, IEntityByIdDataLoader
26+
{
27+
private readonly global::System.IServiceProvider _services;
28+
29+
public EntityByIdDataLoader(
30+
global::System.IServiceProvider services,
31+
global::GreenDonut.IBatchScheduler batchScheduler,
32+
global::GreenDonut.DataLoaderOptions options)
33+
: base(batchScheduler, options)
34+
{
35+
_services = services ??
36+
throw new global::System.ArgumentNullException(nameof(services));
37+
}
38+
39+
protected override async global::System.Threading.Tasks.ValueTask FetchAsync(
40+
global::System.Collections.Generic.IReadOnlyList<int> keys,
41+
global::System.Memory<GreenDonut.Result<long?>> results,
42+
global::GreenDonut.DataLoaderFetchContext<long?> context,
43+
global::System.Threading.CancellationToken ct)
44+
{
45+
var temp = await global::TestNamespace.TestClass.GetEntityByIdAsync(keys, ct).ConfigureAwait(false);
46+
CopyResults(keys, results.Span, temp);
47+
}
48+
49+
private void CopyResults(
50+
global::System.Collections.Generic.IReadOnlyList<int> keys,
51+
global::System.Span<GreenDonut.Result<long?>> results,
52+
global::System.Collections.Generic.IReadOnlyDictionary<int, long?> resultMap)
53+
{
54+
for (var i = 0; i < keys.Count; i++)
55+
{
56+
var key = keys[i];
57+
if (resultMap.TryGetValue(key, out var value))
58+
{
59+
results[i] = global::GreenDonut.Result<long?>.Resolve(value);
60+
}
61+
else
62+
{
63+
results[i] = global::GreenDonut.Result<long?>.Resolve(default(long?));
64+
}
65+
}
66+
}
67+
}
68+
}
69+
70+
71+
```
72+
73+
## HotChocolateTypeModule.735550c.g.cs
74+
75+
```csharp
76+
// <auto-generated/>
77+
78+
#nullable enable
79+
#pragma warning disable
80+
81+
using System;
82+
using System.Runtime.CompilerServices;
83+
using HotChocolate;
84+
using HotChocolate.Types;
85+
using HotChocolate.Execution.Configuration;
86+
87+
namespace Microsoft.Extensions.DependencyInjection
88+
{
89+
public static partial class TestsTypesRequestExecutorBuilderExtensions
90+
{
91+
public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder)
92+
{
93+
builder.AddDataLoader<global::TestNamespace.IEntityByIdDataLoader, global::TestNamespace.EntityByIdDataLoader>();
94+
return builder;
95+
}
96+
}
97+
}
98+
99+
```
100+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# GenerateSource_BatchDataLoader_With_ValueType_Result_MatchesSnapshot
2+
3+
## GreenDonutDataLoader.735550c.g.cs
4+
5+
```csharp
6+
// <auto-generated/>
7+
8+
#nullable enable
9+
#pragma warning disable
10+
11+
using System;
12+
using System.Runtime.CompilerServices;
13+
using Microsoft.Extensions.DependencyInjection;
14+
using GreenDonut;
15+
16+
namespace TestNamespace
17+
{
18+
public interface IEntityByIdDataLoader
19+
: global::GreenDonut.IDataLoader<int, long>
20+
{
21+
}
22+
23+
public sealed partial class EntityByIdDataLoader
24+
: global::GreenDonut.DataLoaderBase<int, long>
25+
, IEntityByIdDataLoader
26+
{
27+
private readonly global::System.IServiceProvider _services;
28+
29+
public EntityByIdDataLoader(
30+
global::System.IServiceProvider services,
31+
global::GreenDonut.IBatchScheduler batchScheduler,
32+
global::GreenDonut.DataLoaderOptions options)
33+
: base(batchScheduler, options)
34+
{
35+
_services = services ??
36+
throw new global::System.ArgumentNullException(nameof(services));
37+
}
38+
39+
protected override async global::System.Threading.Tasks.ValueTask FetchAsync(
40+
global::System.Collections.Generic.IReadOnlyList<int> keys,
41+
global::System.Memory<GreenDonut.Result<long>> results,
42+
global::GreenDonut.DataLoaderFetchContext<long> context,
43+
global::System.Threading.CancellationToken ct)
44+
{
45+
var temp = await global::TestNamespace.TestClass.GetEntityByIdAsync(keys, ct).ConfigureAwait(false);
46+
CopyResults(keys, results.Span, temp);
47+
}
48+
49+
private void CopyResults(
50+
global::System.Collections.Generic.IReadOnlyList<int> keys,
51+
global::System.Span<GreenDonut.Result<long>> results,
52+
global::System.Collections.Generic.IReadOnlyDictionary<int, long> resultMap)
53+
{
54+
for (var i = 0; i < keys.Count; i++)
55+
{
56+
var key = keys[i];
57+
if (resultMap.TryGetValue(key, out var value))
58+
{
59+
results[i] = global::GreenDonut.Result<long>.Resolve(value);
60+
}
61+
else
62+
{
63+
results[i] = global::GreenDonut.Result<long>.Resolve(default(long));
64+
}
65+
}
66+
}
67+
}
68+
}
69+
70+
71+
```
72+
73+
## HotChocolateTypeModule.735550c.g.cs
74+
75+
```csharp
76+
// <auto-generated/>
77+
78+
#nullable enable
79+
#pragma warning disable
80+
81+
using System;
82+
using System.Runtime.CompilerServices;
83+
using HotChocolate;
84+
using HotChocolate.Types;
85+
using HotChocolate.Execution.Configuration;
86+
87+
namespace Microsoft.Extensions.DependencyInjection
88+
{
89+
public static partial class TestsTypesRequestExecutorBuilderExtensions
90+
{
91+
public static IRequestExecutorBuilder AddTestsTypes(this IRequestExecutorBuilder builder)
92+
{
93+
builder.AddDataLoader<global::TestNamespace.IEntityByIdDataLoader, global::TestNamespace.EntityByIdDataLoader>();
94+
return builder;
95+
}
96+
}
97+
}
98+
99+
```
100+

0 commit comments

Comments
 (0)