From 66abd0afa5122c7ec558ed64d2ae81438d264bb1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:09:41 +0000 Subject: [PATCH 1/3] Initial plan From e4dbc5229a72ca8accb5103e83e13ac47a6dea62 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:19:41 +0000 Subject: [PATCH 2/3] Fix INJ0008 and INJ0012 to detect inferred open-generic registrations --- .../RegisterTypeAnalyzer.cs | 28 ++++++++++++++ .../RegisterTypeAnalyzerTests.INJ0008.cs | 28 ++++++++++++++ .../RegisterTypeAnalyzerTests.INJ0012.cs | 38 +++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/src/Immediate.Injections.Analyzers/RegisterTypeAnalyzer.cs b/src/Immediate.Injections.Analyzers/RegisterTypeAnalyzer.cs index 0f2b086..9e0dadd 100644 --- a/src/Immediate.Injections.Analyzers/RegisterTypeAnalyzer.cs +++ b/src/Immediate.Injections.Analyzers/RegisterTypeAnalyzer.cs @@ -303,6 +303,34 @@ public bool AnalyzeRegisterType0Attribute() valid = false; } } + else if (containerSymbol.IsGenericType) + { + if (useProxy) + { + context.ReportDiagnostic( + Diagnostic.Create( + RegisterTypeAnalyzer.CannotUseProxyFactoryForOpenGeneric, + location, + containerSymbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat) + ) + ); + + valid = false; + } + + if (factory is { }) + { + context.ReportDiagnostic( + Diagnostic.Create( + RegisterTypeAnalyzer.CannotUseFactoryMethodWithOpenGeneric, + location, + containerSymbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat) + ) + ); + + valid = false; + } + } switch (registrationStrategy) { diff --git a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs index bc71962..d3e919f 100644 --- a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs +++ b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs @@ -16,4 +16,32 @@ public interface IService; public class Class : IService; """ ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task UseProxyFactoryWithInferredOpenGenericStrategyTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using Immediate.Injections.Shared; + + public interface IService; + + [{|INJ0008:{|INJ0002:RegisterSingleton(RegistrationStrategy = RegistrationStrategy.ImplementedInterfaces, UseProxyFactory = true)|}|}] + public class Class : IService; + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task UseProxyFactoryWithAssemblyDefaultInferredOpenGenericTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using Immediate.Injections.Shared; + + [assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.ImplementedInterfaces)] + + public interface IService; + + [{|INJ0008:{|INJ0002:RegisterSingleton(UseProxyFactory = true)|}|}] + public class Class : IService; + """ + ).RunAsync(TestContext.Current.CancellationToken); } diff --git a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs index f7f2bdb..b35ec04 100644 --- a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs +++ b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs @@ -21,4 +21,42 @@ public class Class : IService } """ ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task FactoryMethodWithInferredOpenGenericStrategyTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using System; + + using Immediate.Injections.Shared; + + public interface IService; + + [{|INJ0012:{|INJ0002:RegisterSingleton(RegistrationStrategy = RegistrationStrategy.ImplementedInterfaces, Factory = nameof(Factory))|}|}] + public class Class : IService + { + public static Class Factory(IServiceProvider provider) => new(); + } + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task FactoryMethodWithAssemblyDefaultInferredOpenGenericTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using System; + + using Immediate.Injections.Shared; + + [assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.ImplementedInterfaces)] + + public interface IService; + + [{|INJ0012:{|INJ0002:RegisterSingleton(Factory = nameof(Factory))|}|}] + public class Class : IService + { + public static Class Factory(IServiceProvider provider) => new(); + } + """ + ).RunAsync(TestContext.Current.CancellationToken); } From 32f2677e1e1ab33761e665cc088e5408d78d504b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Jul 2026 15:14:33 +0000 Subject: [PATCH 3/3] Add Self and SelfAndImplementedInterfaces test cases for INJ0008 and INJ0012 --- .../RegisterTypeAnalyzerTests.INJ0008.cs | 54 +++++++++++++- .../RegisterTypeAnalyzerTests.INJ0012.cs | 74 ++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs index d3e919f..b7c6d68 100644 --- a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs +++ b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0008.cs @@ -18,7 +18,18 @@ public class Class : IService; ).RunAsync(TestContext.Current.CancellationToken); [Fact] - public async Task UseProxyFactoryWithInferredOpenGenericStrategyTriggers() => + public async Task UseProxyFactoryWithInferredOpenGenericSelfStrategyTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using Immediate.Injections.Shared; + + [{|INJ0007:{|INJ0008:{|INJ0002:RegisterSingleton(RegistrationStrategy = RegistrationStrategy.Self, UseProxyFactory = true)|}|}|}] + public class Class; + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task UseProxyFactoryWithInferredOpenGenericImplementedInterfacesStrategyTriggers() => await AnalyzerTestHelpers.CreateAnalyzerTest( """ using Immediate.Injections.Shared; @@ -30,6 +41,19 @@ public class Class : IService; """ ).RunAsync(TestContext.Current.CancellationToken); + [Fact] + public async Task UseProxyFactoryWithInferredOpenGenericSelfAndImplementedInterfacesStrategyTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using Immediate.Injections.Shared; + + public interface IService; + + [{|INJ0008:{|INJ0002:RegisterSingleton(RegistrationStrategy = RegistrationStrategy.SelfAndImplementedInterfaces, UseProxyFactory = true)|}|}] + public class Class : IService; + """ + ).RunAsync(TestContext.Current.CancellationToken); + [Fact] public async Task UseProxyFactoryWithAssemblyDefaultInferredOpenGenericTriggers() => await AnalyzerTestHelpers.CreateAnalyzerTest( @@ -40,6 +64,34 @@ await AnalyzerTestHelpers.CreateAnalyzerTest( public interface IService; + [{|INJ0008:{|INJ0002:RegisterSingleton(UseProxyFactory = true)|}|}] + public class Class : IService; + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task UseProxyFactoryWithAssemblyDefaultSelfInferredOpenGenericTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using Immediate.Injections.Shared; + + [assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.Self)] + + [{|INJ0007:{|INJ0008:{|INJ0002:RegisterSingleton(UseProxyFactory = true)|}|}|}] + public class Class; + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task UseProxyFactoryWithAssemblyDefaultSelfAndImplementedInterfacesInferredOpenGenericTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using Immediate.Injections.Shared; + + [assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.SelfAndImplementedInterfaces)] + + public interface IService; + [{|INJ0008:{|INJ0002:RegisterSingleton(UseProxyFactory = true)|}|}] public class Class : IService; """ diff --git a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs index b35ec04..65b2051 100644 --- a/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs +++ b/tests/Immediate.Injections.Tests/AnalyzerTests/RegisterTypeAnalyzerTests.INJ0012.cs @@ -23,7 +23,23 @@ public class Class : IService ).RunAsync(TestContext.Current.CancellationToken); [Fact] - public async Task FactoryMethodWithInferredOpenGenericStrategyTriggers() => + public async Task FactoryMethodWithInferredOpenGenericSelfStrategyTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using System; + + using Immediate.Injections.Shared; + + [{|INJ0012:{|INJ0002:RegisterSingleton(RegistrationStrategy = RegistrationStrategy.Self, Factory = nameof(Factory))|}|}] + public class Class + { + public static Class Factory(IServiceProvider provider) => new(); + } + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task FactoryMethodWithInferredOpenGenericImplementedInterfacesStrategyTriggers() => await AnalyzerTestHelpers.CreateAnalyzerTest( """ using System; @@ -40,6 +56,24 @@ public class Class : IService """ ).RunAsync(TestContext.Current.CancellationToken); + [Fact] + public async Task FactoryMethodWithInferredOpenGenericSelfAndImplementedInterfacesStrategyTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using System; + + using Immediate.Injections.Shared; + + public interface IService; + + [{|INJ0012:{|INJ0002:RegisterSingleton(RegistrationStrategy = RegistrationStrategy.SelfAndImplementedInterfaces, Factory = nameof(Factory))|}|}] + public class Class : IService + { + public static Class Factory(IServiceProvider provider) => new(); + } + """ + ).RunAsync(TestContext.Current.CancellationToken); + [Fact] public async Task FactoryMethodWithAssemblyDefaultInferredOpenGenericTriggers() => await AnalyzerTestHelpers.CreateAnalyzerTest( @@ -52,6 +86,44 @@ await AnalyzerTestHelpers.CreateAnalyzerTest( public interface IService; + [{|INJ0012:{|INJ0002:RegisterSingleton(Factory = nameof(Factory))|}|}] + public class Class : IService + { + public static Class Factory(IServiceProvider provider) => new(); + } + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task FactoryMethodWithAssemblyDefaultSelfInferredOpenGenericTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using System; + + using Immediate.Injections.Shared; + + [assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.Self)] + + [{|INJ0012:{|INJ0002:RegisterSingleton(Factory = nameof(Factory))|}|}] + public class Class + { + public static Class Factory(IServiceProvider provider) => new(); + } + """ + ).RunAsync(TestContext.Current.CancellationToken); + + [Fact] + public async Task FactoryMethodWithAssemblyDefaultSelfAndImplementedInterfacesInferredOpenGenericTriggers() => + await AnalyzerTestHelpers.CreateAnalyzerTest( + """ + using System; + + using Immediate.Injections.Shared; + + [assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.SelfAndImplementedInterfaces)] + + public interface IService; + [{|INJ0012:{|INJ0002:RegisterSingleton(Factory = nameof(Factory))|}|}] public class Class : IService {