Skip to content

Commit d9b30ff

Browse files
committed
Fix dotnet format and coverage issues
- Add UTF-8 BOM to files missing it (CHARSET format errors) - Rename ModelBuilder static fields to _camelCase (IDE1006) - Add InternalsVisibleTo so the generator test project can reach the internal model types - Add ModelEqualityTests + EmitterTests and extra generator behavior tests, raising generator coverage from ~81% to ~98%
1 parent 2e523f8 commit d9b30ff

15 files changed

Lines changed: 384 additions & 17 deletions

File tree

bench/Autofac.Extras.AggregateService.Bench/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Autofac Project. All rights reserved.
1+
// Copyright (c) Autofac Project. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
using BenchmarkDotNet.Jobs;

src/Autofac.Extras.AggregateService.SourceGenerator/AggregateServiceModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Autofac Project. All rights reserved.
1+
// Copyright (c) Autofac Project. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
namespace Autofac.Extras.AggregateService.SourceGenerator;

src/Autofac.Extras.AggregateService.SourceGenerator/MemberKind.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Autofac Project. All rights reserved.
1+
// Copyright (c) Autofac Project. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
namespace Autofac.Extras.AggregateService.SourceGenerator;

src/Autofac.Extras.AggregateService.SourceGenerator/MemberModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Autofac Project. All rights reserved.
1+
// Copyright (c) Autofac Project. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
namespace Autofac.Extras.AggregateService.SourceGenerator;

src/Autofac.Extras.AggregateService.SourceGenerator/ModelBuilder.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ namespace Autofac.Extras.AggregateService.SourceGenerator;
1212
/// </summary>
1313
internal static class ModelBuilder
1414
{
15-
private static readonly SymbolDisplayFormat FullyQualifiedFormat = SymbolDisplayFormat.FullyQualifiedFormat;
15+
private static readonly SymbolDisplayFormat _fullyQualifiedFormat = SymbolDisplayFormat.FullyQualifiedFormat;
1616

1717
// Fully-qualified name without any type parameter/argument list, so the emitter can build
1818
// the open (IFoo<,>) and closed (IFoo<T>) forms itself without double-appending.
19-
private static readonly SymbolDisplayFormat FullyQualifiedNoTypeParametersFormat =
19+
private static readonly SymbolDisplayFormat _fullyQualifiedNoTypeParametersFormat =
2020
SymbolDisplayFormat.FullyQualifiedFormat.WithGenericsOptions(SymbolDisplayGenericsOptions.None);
2121

2222
/// <summary>
@@ -60,7 +60,7 @@ internal static class ModelBuilder
6060
return null;
6161
}
6262

63-
var fullyQualified = definition.ToDisplayString(FullyQualifiedNoTypeParametersFormat);
63+
var fullyQualified = definition.ToDisplayString(_fullyQualifiedNoTypeParametersFormat);
6464
var ns = definition.ContainingNamespace.IsGlobalNamespace
6565
? string.Empty
6666
: definition.ContainingNamespace.ToDisplayString();
@@ -174,7 +174,7 @@ private static bool IsAccessor(IMethodSymbol method)
174174
return null;
175175
}
176176

177-
var propertyType = property.Type.ToDisplayString(FullyQualifiedFormat);
177+
var propertyType = property.Type.ToDisplayString(_fullyQualifiedFormat);
178178
return new MemberModel(
179179
MemberKind.Property,
180180
property.Name,
@@ -204,7 +204,7 @@ private static bool IsAccessor(IMethodSymbol method)
204204
}
205205
}
206206

207-
var returnType = method.ReturnType.ToDisplayString(FullyQualifiedFormat);
207+
var returnType = method.ReturnType.ToDisplayString(_fullyQualifiedFormat);
208208
var typeParameters = method.TypeParameters.Select(BuildTypeParameter).ToArray();
209209

210210
// Void methods have no return type to resolve; the runtime throws when they are invoked,
@@ -245,7 +245,7 @@ private static ParameterModel[] BuildParameters(IMethodSymbol method)
245245
.OrderBy(p => p.Ordinal)
246246
.Select(p => new ParameterModel(
247247
p.Name,
248-
p.Type.ToDisplayString(FullyQualifiedFormat),
248+
p.Type.ToDisplayString(_fullyQualifiedFormat),
249249
BuildParameterModifier(p)))
250250
.ToArray();
251251

@@ -290,7 +290,7 @@ private static string BuildConstraintClause(ITypeParameterSymbol typeParameter)
290290

291291
foreach (var constraintType in typeParameter.ConstraintTypes)
292292
{
293-
constraints.Add(constraintType.ToDisplayString(FullyQualifiedFormat));
293+
constraints.Add(constraintType.ToDisplayString(_fullyQualifiedFormat));
294294
}
295295

296296
// The parameterless-constructor constraint must come last and is not combinable with the

src/Autofac.Extras.AggregateService.SourceGenerator/ParameterModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Autofac Project. All rights reserved.
1+
// Copyright (c) Autofac Project. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
namespace Autofac.Extras.AggregateService.SourceGenerator;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) Autofac Project. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using System.Runtime.CompilerServices;
5+
6+
[assembly: InternalsVisibleTo("Autofac.Extras.AggregateService.SourceGenerator.Test, PublicKey=00240000048000009400000006020000002400005253413100040000010001008728425885ef385e049261b18878327dfaaf0d666dea3bd2b0e4f18b33929ad4e5fbc9087e7eda3c1291d2de579206d9b4292456abffbe8be6c7060b36da0c33b883e3878eaf7c89fddf29e6e27d24588e81e86f3a22dd7b1a296b5f06fbfb500bbd7410faa7213ef4e2ce7622aefc03169b0324bcd30ccfe9ac8204e4960be6")]

test/Autofac.Extras.AggregateService.AotSmokeTest/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Autofac Project. All rights reserved.
1+
// Copyright (c) Autofac Project. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
using Autofac;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) Autofac Project. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
namespace Autofac.Extras.AggregateService.SourceGenerator.Test;
5+
6+
/// <summary>
7+
/// Direct unit tests for <see cref="Emitter"/> branches that the full-compilation
8+
/// harness cannot reach - notably the <c>ModuleInitializerAttribute</c> polyfill,
9+
/// which is only emitted when the consuming compilation lacks the attribute (a
10+
/// netstandard2.0 / net472 target), whereas the test host always has it.
11+
/// </summary>
12+
public class EmitterTests
13+
{
14+
[Fact]
15+
public void EmitRegistrations_EmitsModuleInitializerPolyfillWhenRequested()
16+
{
17+
var model = CreateClosedModel();
18+
19+
var source = Emitter.EmitRegistrations(new[] { model }, needsModuleInitializerPolyfill: true);
20+
21+
Assert.Contains("namespace System.Runtime.CompilerServices", source, StringComparison.Ordinal);
22+
Assert.Contains("class ModuleInitializerAttribute", source, StringComparison.Ordinal);
23+
Assert.Contains("GeneratedAggregateServiceModuleInitializer", source, StringComparison.Ordinal);
24+
}
25+
26+
[Fact]
27+
public void EmitRegistrations_OmitsModuleInitializerPolyfillWhenNotRequested()
28+
{
29+
var model = CreateClosedModel();
30+
31+
var source = Emitter.EmitRegistrations(new[] { model }, needsModuleInitializerPolyfill: false);
32+
33+
Assert.DoesNotContain("class ModuleInitializerAttribute", source, StringComparison.Ordinal);
34+
Assert.Contains("GeneratedAggregateServiceModuleInitializer", source, StringComparison.Ordinal);
35+
}
36+
37+
private static AggregateServiceModel CreateClosedModel()
38+
=> new AggregateServiceModel(
39+
interfaceFullyQualifiedName: "global::TestConsumer.IMyAggregate",
40+
interfaceNamespace: "TestConsumer",
41+
interfaceMinimalName: "TestConsumer_IMyAggregate",
42+
backingClassName: "__TestConsumer_IMyAggregate_Aggregate",
43+
isOpenGeneric: false,
44+
typeParameters: new EquatableArray<TypeParameterModel>(System.Array.Empty<TypeParameterModel>()),
45+
members: new EquatableArray<MemberModel>(System.Array.Empty<MemberModel>()));
46+
}

test/Autofac.Extras.AggregateService.SourceGenerator.Test/GeneratorBehaviorTests.cs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,133 @@ public static void Configure(ContainerBuilder builder)
180180

181181
Assert.Single(result.Diagnostics, d => d.Id == "AGSVC001");
182182
}
183+
184+
[Fact]
185+
public void NonInterfaceTypeArgumentIsNotGenerated()
186+
{
187+
// CreateInstance<T> where T is not an interface cannot be an aggregate service; the
188+
// generator must skip it (the runtime throws ArgumentException instead).
189+
var source = @"using Autofac;
190+
using Autofac.Extras.AggregateService;
191+
192+
namespace TestConsumer
193+
{
194+
public static class Registration
195+
{
196+
public static object Configure(IComponentContext context)
197+
{
198+
return AggregateServiceGenerator.CreateInstance<string>(context);
199+
}
200+
}
201+
}";
202+
203+
var driver = GeneratorTestHarness.Run(source);
204+
var result = driver.GetRunResult();
205+
206+
Assert.Empty(result.GeneratedTrees);
207+
}
208+
209+
[Fact]
210+
public void NestedInterfaceIsNotGenerated()
211+
{
212+
// An aggregate interface nested inside another type is not supported; the generator skips
213+
// it and the runtime falls back to the dynamic proxy.
214+
var source = @"using Autofac;
215+
using Autofac.Extras.AggregateService;
216+
217+
namespace TestConsumer
218+
{
219+
public interface IDep { }
220+
221+
public class Outer
222+
{
223+
public interface INested
224+
{
225+
IDep Dep { get; }
226+
}
227+
}
228+
229+
public static class Registration
230+
{
231+
public static void Configure(ContainerBuilder builder)
232+
{
233+
builder.RegisterAggregateService<Outer.INested>();
234+
}
235+
}
236+
}";
237+
238+
var driver = GeneratorTestHarness.Run(source);
239+
var result = driver.GetRunResult();
240+
241+
Assert.Empty(result.GeneratedTrees);
242+
Assert.Single(result.Diagnostics, d => d.Id == "AGSVC001");
243+
}
244+
245+
[Fact]
246+
public void InterfaceWithEventIsNotGenerated()
247+
{
248+
// Events are an unsupported member shape; the generator skips the interface and reports
249+
// AGSVC001 so the dynamic-proxy fallback is visible.
250+
var source = @"using System;
251+
using Autofac;
252+
using Autofac.Extras.AggregateService;
253+
254+
namespace TestConsumer
255+
{
256+
public interface IDep { }
257+
258+
public interface IMyAggregate
259+
{
260+
IDep Dep { get; }
261+
262+
event EventHandler Something;
263+
}
264+
265+
public static class Registration
266+
{
267+
public static void Configure(ContainerBuilder builder)
268+
{
269+
builder.RegisterAggregateService<IMyAggregate>();
270+
}
271+
}
272+
}";
273+
274+
var driver = GeneratorTestHarness.Run(source);
275+
var result = driver.GetRunResult();
276+
277+
Assert.Empty(result.GeneratedTrees);
278+
Assert.Single(result.Diagnostics, d => d.Id == "AGSVC001");
279+
}
280+
281+
[Fact]
282+
public void NullConditionalInvocationIsDiscovered()
283+
{
284+
// A null-conditional registration call (builder?.RegisterAggregateService<T>()) uses a
285+
// MemberBindingExpressionSyntax; the generator must still discover it.
286+
var source = @"using Autofac;
287+
using Autofac.Extras.AggregateService;
288+
289+
namespace TestConsumer
290+
{
291+
public interface IDep { }
292+
293+
public interface IMyAggregate
294+
{
295+
IDep Dep { get; }
296+
}
297+
298+
public static class Registration
299+
{
300+
public static void Configure(ContainerBuilder builder)
301+
{
302+
builder?.RegisterAggregateService<IMyAggregate>();
303+
}
304+
}
305+
}";
306+
307+
var driver = GeneratorTestHarness.Run(source);
308+
var result = driver.GetRunResult();
309+
310+
Assert.Contains(result.GeneratedTrees, t => t.FilePath.Contains("IMyAggregate", StringComparison.Ordinal));
311+
}
183312
}

0 commit comments

Comments
 (0)