Skip to content

Commit 2d80388

Browse files
fix(adapter): Remove redundant type checks and add missing diagnostic tests (#113)
* Initial plan * fix(adapter): Remove redundant type checks and add missing diagnostic tests Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
1 parent 4a4b68a commit 2d80388

2 files changed

Lines changed: 182 additions & 2 deletions

File tree

src/PatternKit.Generators/Adapter/AdapterGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ private void GenerateAdapterForAttribute(
234234
return; // Attribute error, let compiler handle
235235

236236
// Reject unbound/open generic target types (e.g., typeof(IFoo<>))
237-
if (config.TargetType is INamedTypeSymbol targetNamed && targetNamed.IsUnboundGenericType)
237+
if (config.TargetType.IsUnboundGenericType)
238238
{
239239
context.ReportDiagnostic(Diagnostic.Create(
240240
TargetNotInterfaceOrAbstractDescriptor,
@@ -244,7 +244,7 @@ private void GenerateAdapterForAttribute(
244244
}
245245

246246
// Reject unbound/open generic adaptee types (e.g., typeof(IFoo<>))
247-
if (config.AdapteeType is INamedTypeSymbol adapteeNamed && adapteeNamed.IsUnboundGenericType)
247+
if (config.AdapteeType.IsUnboundGenericType)
248248
{
249249
context.ReportDiagnostic(Diagnostic.Create(
250250
InvalidAdapteeTypeDescriptor,

test/PatternKit.Generators.Tests/AdapterGeneratorTests.cs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,4 +1022,184 @@ public static partial class Adapters
10221022
var emit = updated.Emit(Stream.Null);
10231023
Assert.True(emit.Success, string.Join("\n", emit.Diagnostics));
10241024
}
1025+
1026+
[Fact]
1027+
public void ErrorWhenHostIsNested()
1028+
{
1029+
const string source = """
1030+
using PatternKit.Generators.Adapter;
1031+
1032+
namespace TestNamespace;
1033+
1034+
public interface IClock
1035+
{
1036+
System.DateTimeOffset Now { get; }
1037+
}
1038+
1039+
public class LegacyClock { }
1040+
1041+
public class OuterClass
1042+
{
1043+
[GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))]
1044+
public static partial class Adapters { }
1045+
}
1046+
""";
1047+
1048+
var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenHostIsNested));
1049+
var gen = new AdapterGenerator();
1050+
_ = RoslynTestHelpers.Run(comp, gen, out var result, out _);
1051+
1052+
// PKADP014 diagnostic is reported
1053+
var diags = result.Results.SelectMany(r => r.Diagnostics);
1054+
Assert.Contains(diags, d => d.Id == "PKADP014");
1055+
}
1056+
1057+
[Fact]
1058+
public void ErrorWhenHostIsGeneric()
1059+
{
1060+
const string source = """
1061+
using PatternKit.Generators.Adapter;
1062+
1063+
namespace TestNamespace;
1064+
1065+
public interface IClock
1066+
{
1067+
System.DateTimeOffset Now { get; }
1068+
}
1069+
1070+
public class LegacyClock { }
1071+
1072+
[GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))]
1073+
public static partial class Adapters<T> { }
1074+
""";
1075+
1076+
var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenHostIsGeneric));
1077+
var gen = new AdapterGenerator();
1078+
_ = RoslynTestHelpers.Run(comp, gen, out var result, out _);
1079+
1080+
// PKADP014 diagnostic is reported
1081+
var diags = result.Results.SelectMany(r => r.Diagnostics);
1082+
Assert.Contains(diags, d => d.Id == "PKADP014");
1083+
}
1084+
1085+
[Fact]
1086+
public void ErrorWhenMappingMethodNotAccessible()
1087+
{
1088+
const string source = """
1089+
using PatternKit.Generators.Adapter;
1090+
1091+
namespace TestNamespace;
1092+
1093+
public interface IClock
1094+
{
1095+
System.DateTimeOffset Now { get; }
1096+
}
1097+
1098+
public class LegacyClock { }
1099+
1100+
[GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))]
1101+
public static partial class Adapters
1102+
{
1103+
[AdapterMap(TargetMember = nameof(IClock.Now))]
1104+
private static System.DateTimeOffset MapNow(LegacyClock adaptee) => default; // Private instead of public/internal
1105+
}
1106+
""";
1107+
1108+
var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenMappingMethodNotAccessible));
1109+
var gen = new AdapterGenerator();
1110+
_ = RoslynTestHelpers.Run(comp, gen, out var result, out _);
1111+
1112+
// PKADP015 diagnostic is reported
1113+
var diags = result.Results.SelectMany(r => r.Diagnostics);
1114+
Assert.Contains(diags, d => d.Id == "PKADP015");
1115+
}
1116+
1117+
[Fact]
1118+
public void ErrorWhenTargetHasStaticMembers()
1119+
{
1120+
const string source = """
1121+
using PatternKit.Generators.Adapter;
1122+
1123+
namespace TestNamespace;
1124+
1125+
public interface IClock
1126+
{
1127+
System.DateTimeOffset Now { get; }
1128+
static abstract void StaticMethod(); // Static abstract member (C# 11+)
1129+
}
1130+
1131+
public class LegacyClock { }
1132+
1133+
[GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))]
1134+
public static partial class Adapters
1135+
{
1136+
[AdapterMap(TargetMember = nameof(IClock.Now))]
1137+
public static System.DateTimeOffset MapNow(LegacyClock adaptee) => default;
1138+
}
1139+
""";
1140+
1141+
var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenTargetHasStaticMembers));
1142+
var gen = new AdapterGenerator();
1143+
_ = RoslynTestHelpers.Run(comp, gen, out var result, out _);
1144+
1145+
// PKADP016 diagnostic is reported
1146+
var diags = result.Results.SelectMany(r => r.Diagnostics);
1147+
Assert.Contains(diags, d => d.Id == "PKADP016");
1148+
}
1149+
1150+
[Fact]
1151+
public void ErrorWhenTargetHasRefReturnProperty()
1152+
{
1153+
const string source = """
1154+
using PatternKit.Generators.Adapter;
1155+
1156+
namespace TestNamespace;
1157+
1158+
public interface IClock
1159+
{
1160+
ref int RefProperty { get; } // Ref-return property
1161+
}
1162+
1163+
public class LegacyClock { }
1164+
1165+
[GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))]
1166+
public static partial class Adapters { }
1167+
""";
1168+
1169+
var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenTargetHasRefReturnProperty));
1170+
var gen = new AdapterGenerator();
1171+
_ = RoslynTestHelpers.Run(comp, gen, out var result, out _);
1172+
1173+
// PKADP017 diagnostic is reported
1174+
var diags = result.Results.SelectMany(r => r.Diagnostics);
1175+
Assert.Contains(diags, d => d.Id == "PKADP017");
1176+
}
1177+
1178+
[Fact]
1179+
public void ErrorWhenTargetHasRefReturnMethod()
1180+
{
1181+
const string source = """
1182+
using PatternKit.Generators.Adapter;
1183+
1184+
namespace TestNamespace;
1185+
1186+
public interface IClock
1187+
{
1188+
ref int GetRefValue(); // Ref-return method
1189+
}
1190+
1191+
public class LegacyClock { }
1192+
1193+
[GenerateAdapter(Target = typeof(IClock), Adaptee = typeof(LegacyClock))]
1194+
public static partial class Adapters { }
1195+
""";
1196+
1197+
var comp = RoslynTestHelpers.CreateCompilation(source, nameof(ErrorWhenTargetHasRefReturnMethod));
1198+
var gen = new AdapterGenerator();
1199+
_ = RoslynTestHelpers.Run(comp, gen, out var result, out _);
1200+
1201+
// PKADP017 diagnostic is reported
1202+
var diags = result.Results.SelectMany(r => r.Diagnostics);
1203+
Assert.Contains(diags, d => d.Id == "PKADP017");
1204+
}
10251205
}

0 commit comments

Comments
 (0)