diff --git a/src/PatternKit.Generators/Adapter/AdapterGenerator.cs b/src/PatternKit.Generators/Adapter/AdapterGenerator.cs index de3668b..e2565a3 100644 --- a/src/PatternKit.Generators/Adapter/AdapterGenerator.cs +++ b/src/PatternKit.Generators/Adapter/AdapterGenerator.cs @@ -234,7 +234,7 @@ private void GenerateAdapterForAttribute( return; // Attribute error, let compiler handle // Reject unbound/open generic target types (e.g., typeof(IFoo<>)) - if (config.TargetType is INamedTypeSymbol targetNamed && targetNamed.IsUnboundGenericType) + if (config.TargetType.IsUnboundGenericType) { context.ReportDiagnostic(Diagnostic.Create( TargetNotInterfaceOrAbstractDescriptor, @@ -244,7 +244,7 @@ private void GenerateAdapterForAttribute( } // Reject unbound/open generic adaptee types (e.g., typeof(IFoo<>)) - if (config.AdapteeType is INamedTypeSymbol adapteeNamed && adapteeNamed.IsUnboundGenericType) + if (config.AdapteeType.IsUnboundGenericType) { context.ReportDiagnostic(Diagnostic.Create( InvalidAdapteeTypeDescriptor, diff --git a/test/PatternKit.Generators.Tests/AdapterGeneratorTests.cs b/test/PatternKit.Generators.Tests/AdapterGeneratorTests.cs index c8b0aa9..80ca415 100644 --- a/test/PatternKit.Generators.Tests/AdapterGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/AdapterGeneratorTests.cs @@ -1022,4 +1022,184 @@ public static partial class Adapters var emit = updated.Emit(Stream.Null); Assert.True(emit.Success, string.Join("\n", emit.Diagnostics)); } + + [Fact] + public void ErrorWhenHostIsNested() + { + const string source = """ + using PatternKit.Generators.Adapter; + + namespace TestNamespace; + + public interface IClock + { + System.DateTimeOffset Now { get; } + } + + public class LegacyClock { } + + public class OuterClass + { + [GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))] + public static partial class Adapters { } + } + """; + + var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenHostIsNested)); + var gen = new AdapterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var result, out _); + + // PKADP014 diagnostic is reported + var diags = result.Results.SelectMany(r => r.Diagnostics); + Assert.Contains(diags, d => d.Id == "PKADP014"); + } + + [Fact] + public void ErrorWhenHostIsGeneric() + { + const string source = """ + using PatternKit.Generators.Adapter; + + namespace TestNamespace; + + public interface IClock + { + System.DateTimeOffset Now { get; } + } + + public class LegacyClock { } + + [GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))] + public static partial class Adapters { } + """; + + var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenHostIsGeneric)); + var gen = new AdapterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var result, out _); + + // PKADP014 diagnostic is reported + var diags = result.Results.SelectMany(r => r.Diagnostics); + Assert.Contains(diags, d => d.Id == "PKADP014"); + } + + [Fact] + public void ErrorWhenMappingMethodNotAccessible() + { + const string source = """ + using PatternKit.Generators.Adapter; + + namespace TestNamespace; + + public interface IClock + { + System.DateTimeOffset Now { get; } + } + + public class LegacyClock { } + + [GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))] + public static partial class Adapters + { + [AdapterMap(TargetMember = nameof(IClock.Now))] + private static System.DateTimeOffset MapNow(LegacyClock adaptee) => default; // Private instead of public/internal + } + """; + + var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenMappingMethodNotAccessible)); + var gen = new AdapterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var result, out _); + + // PKADP015 diagnostic is reported + var diags = result.Results.SelectMany(r => r.Diagnostics); + Assert.Contains(diags, d => d.Id == "PKADP015"); + } + + [Fact] + public void ErrorWhenTargetHasStaticMembers() + { + const string source = """ + using PatternKit.Generators.Adapter; + + namespace TestNamespace; + + public interface IClock + { + System.DateTimeOffset Now { get; } + static abstract void StaticMethod(); // Static abstract member (C# 11+) + } + + public class LegacyClock { } + + [GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))] + public static partial class Adapters + { + [AdapterMap(TargetMember = nameof(IClock.Now))] + public static System.DateTimeOffset MapNow(LegacyClock adaptee) => default; + } + """; + + var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenTargetHasStaticMembers)); + var gen = new AdapterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var result, out _); + + // PKADP016 diagnostic is reported + var diags = result.Results.SelectMany(r => r.Diagnostics); + Assert.Contains(diags, d => d.Id == "PKADP016"); + } + + [Fact] + public void ErrorWhenTargetHasRefReturnProperty() + { + const string source = """ + using PatternKit.Generators.Adapter; + + namespace TestNamespace; + + public interface IClock + { + ref int RefProperty { get; } // Ref-return property + } + + public class LegacyClock { } + + [GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))] + public static partial class Adapters { } + """; + + var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenTargetHasRefReturnProperty)); + var gen = new AdapterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var result, out _); + + // PKADP017 diagnostic is reported + var diags = result.Results.SelectMany(r => r.Diagnostics); + Assert.Contains(diags, d => d.Id == "PKADP017"); + } + + [Fact] + public void ErrorWhenTargetHasRefReturnMethod() + { + const string source = """ + using PatternKit.Generators.Adapter; + + namespace TestNamespace; + + public interface IClock + { + ref int GetRefValue(); // Ref-return method + } + + public class LegacyClock { } + + [GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))] + public static partial class Adapters { } + """; + + var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenTargetHasRefReturnMethod)); + var gen = new AdapterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var result, out _); + + // PKADP017 diagnostic is reported + var diags = result.Results.SelectMany(r => r.Diagnostics); + Assert.Contains(diags, d => d.Id == "PKADP017"); + } }