Skip to content

Commit de9bd2c

Browse files
committed
fix: Generate valid code if no matching types found
1 parent a79dd6b commit de9bd2c

File tree

2 files changed

+74
-29
lines changed

2 files changed

+74
-29
lines changed

ServiceScan.SourceGenerator.Tests/DiagnosticTests.cs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public static partial class ServicesExtensions
135135
}
136136

137137
[Fact]
138-
public void SearchCriteriaInTheAttributeProducesNoResults()
138+
public void SearchCriteriaInTheAttributeProducesNoResults_ReturnsIServiceCollection()
139139
{
140140
var compilation = CreateCompilation(Services,
141141
"""
@@ -169,8 +169,49 @@ public static partial class ServicesExtensions
169169
{
170170
public static partial IServiceCollection AddServices(this IServiceCollection services)
171171
{
172-
return services
173-
;
172+
return services;
173+
}
174+
}
175+
""";
176+
Assert.Equal(expectedFile, results.GeneratedTrees[1].ToString());
177+
}
178+
179+
[Fact]
180+
public void SearchCriteriaInTheAttributeProducesNoResults_ReturnsVoid()
181+
{
182+
var compilation = CreateCompilation(Services,
183+
"""
184+
using ServiceScan.SourceGenerator;
185+
using Microsoft.Extensions.DependencyInjection;
186+
187+
namespace GeneratorTests;
188+
189+
public interface IHasNoImplementations { }
190+
191+
public static partial class ServicesExtensions
192+
{
193+
[GenerateServiceRegistrations(AssignableTo = typeof(IHasNoImplementations))]
194+
public static partial void AddServices(this IServiceCollection services);
195+
}
196+
""");
197+
198+
var results = CSharpGeneratorDriver
199+
.Create(_generator)
200+
.RunGenerators(compilation)
201+
.GetRunResult();
202+
203+
Assert.Equal(results.Diagnostics.Single().Descriptor, DiagnosticDescriptors.NoMatchingTypesFound);
204+
205+
var expectedFile = """
206+
using Microsoft.Extensions.DependencyInjection;
207+
208+
namespace GeneratorTests;
209+
210+
public static partial class ServicesExtensions
211+
{
212+
public static partial void AddServices(this IServiceCollection services)
213+
{
214+
174215
}
175216
}
176217
""";

ServiceScan.SourceGenerator/DependencyInjectionGenerator.cs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -52,41 +52,46 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
5252

5353
private static string GenerateRegistrationsSource(MethodModel method, EquatableArray<ServiceRegistrationModel> registrations)
5454
{
55-
var registrationsCode = string.Join("\n", registrations.Select(registration =>
56-
{
57-
if (registration.IsOpenGeneric)
58-
{
59-
return $" .Add{registration.Lifetime}(typeof({registration.ServiceTypeName}), typeof({registration.ImplementationTypeName}))";
60-
}
61-
else
55+
var registrationsCode = string.Concat(registrations
56+
.Select(registration =>
6257
{
63-
if (registration.ResolveImplementation)
58+
if (registration.IsOpenGeneric)
6459
{
65-
return $" .Add{registration.Lifetime}<{registration.ServiceTypeName}>(s => s.GetRequiredService<{registration.ImplementationTypeName}>())";
60+
return $".Add{registration.Lifetime}(typeof({registration.ServiceTypeName}), typeof({registration.ImplementationTypeName}))";
6661
}
6762
else
6863
{
69-
var addMethod = registration.KeySelector != null
70-
? $"AddKeyed{registration.Lifetime}"
71-
: $"Add{registration.Lifetime}";
72-
73-
var keySelectorInvocation = registration.KeySelectorType switch
64+
if (registration.ResolveImplementation)
7465
{
75-
KeySelectorType.GenericMethod => $"{registration.KeySelector}<{registration.ImplementationTypeName}>()",
76-
KeySelectorType.Method => $"{registration.KeySelector}(typeof({registration.ImplementationTypeName}))",
77-
KeySelectorType.TypeMember => $"{registration.ImplementationTypeName}.{registration.KeySelector}",
78-
_ => null
79-
};
80-
81-
return $" .{addMethod}<{registration.ServiceTypeName}, {registration.ImplementationTypeName}>({keySelectorInvocation})";
66+
return $".Add{registration.Lifetime}<{registration.ServiceTypeName}>(s => s.GetRequiredService<{registration.ImplementationTypeName}>())";
67+
}
68+
else
69+
{
70+
var addMethod = registration.KeySelector != null
71+
? $"AddKeyed{registration.Lifetime}"
72+
: $"Add{registration.Lifetime}";
73+
74+
var keySelectorInvocation = registration.KeySelectorType switch
75+
{
76+
KeySelectorType.GenericMethod => $"{registration.KeySelector}<{registration.ImplementationTypeName}>()",
77+
KeySelectorType.Method => $"{registration.KeySelector}(typeof({registration.ImplementationTypeName}))",
78+
KeySelectorType.TypeMember => $"{registration.ImplementationTypeName}.{registration.KeySelector}",
79+
_ => null
80+
};
81+
82+
return $".{addMethod}<{registration.ServiceTypeName}, {registration.ImplementationTypeName}>({keySelectorInvocation})";
83+
}
8284
}
83-
}
84-
}));
85+
})
86+
.Select(line => $"\n {line}"));
8587

8688
var returnType = method.ReturnsVoid ? "void" : "IServiceCollection";
87-
8889
var namespaceDeclaration = method.Namespace is null ? "" : $"namespace {method.Namespace};";
8990

91+
var methodBody = registrations.Count == 0 && method.ReturnsVoid
92+
? ""
93+
: $$"""{{(method.ReturnsVoid ? "" : "return ")}}{{method.ParameterName}}{{registrationsCode}};""";
94+
9095
var source = $$"""
9196
using Microsoft.Extensions.DependencyInjection;
9297
@@ -96,8 +101,7 @@ private static string GenerateRegistrationsSource(MethodModel method, EquatableA
96101
{
97102
{{method.MethodModifiers}} {{returnType}} {{method.MethodName}}({{(method.IsExtensionMethod ? "this" : "")}} IServiceCollection {{method.ParameterName}})
98103
{
99-
{{(method.ReturnsVoid ? "" : "return ")}}{{method.ParameterName}}
100-
{{registrationsCode.Trim()}};
104+
{{methodBody}}
101105
}
102106
}
103107
""";

0 commit comments

Comments
 (0)