Skip to content

Commit ac13efe

Browse files
CopilotDreamescaper
andcommitted
Implement ScanForTypes collection return feature (Type[] and IEnumerable<T>)
Co-authored-by: Dreamescaper <17177729+Dreamescaper@users.noreply.github.com>
1 parent 2a6409d commit ac13efe

7 files changed

Lines changed: 454 additions & 29 deletions

ServiceScan.SourceGenerator.Tests/CustomHandlerTests.cs

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,4 +1343,320 @@ public class MyService : IService { }
13431343

13441344
Assert.Contains(results.Diagnostics, d => d.Descriptor == DiagnosticDescriptors.CantMixServiceRegistrationsAndServiceHandler);
13451345
}
1346+
1347+
[Fact]
1348+
public void ScanForTypesAttribute_ReturnsTypeArray_WithNoHandler()
1349+
{
1350+
var source = """
1351+
using ServiceScan.SourceGenerator;
1352+
using System;
1353+
1354+
namespace GeneratorTests;
1355+
1356+
public static partial class ServicesExtensions
1357+
{
1358+
[ScanForTypes(AssignableTo = typeof(IService))]
1359+
public static partial Type[] GetServiceTypes();
1360+
}
1361+
""";
1362+
1363+
var services =
1364+
"""
1365+
namespace GeneratorTests;
1366+
1367+
public interface IService { }
1368+
public class MyService1 : IService { }
1369+
public class MyService2 : IService { }
1370+
""";
1371+
1372+
var compilation = CreateCompilation(source, services);
1373+
1374+
var results = CSharpGeneratorDriver
1375+
.Create(_generator)
1376+
.RunGenerators(compilation)
1377+
.GetRunResult();
1378+
1379+
var expected = """
1380+
namespace GeneratorTests;
1381+
1382+
public static partial class ServicesExtensions
1383+
{
1384+
public static partial global::System.Type[] GetServiceTypes()
1385+
{
1386+
return [typeof(global::GeneratorTests.MyService1), typeof(global::GeneratorTests.MyService2)];
1387+
}
1388+
}
1389+
""";
1390+
Assert.Equal(expected, results.GeneratedTrees[2].ToString());
1391+
}
1392+
1393+
[Fact]
1394+
public void ScanForTypesAttribute_ReturnsIEnumerableType_WithNoHandler()
1395+
{
1396+
var source = """
1397+
using ServiceScan.SourceGenerator;
1398+
using System;
1399+
using System.Collections.Generic;
1400+
1401+
namespace GeneratorTests;
1402+
1403+
public static partial class ServicesExtensions
1404+
{
1405+
[ScanForTypes(AssignableTo = typeof(IService))]
1406+
public static partial IEnumerable<Type> GetServiceTypes();
1407+
}
1408+
""";
1409+
1410+
var services =
1411+
"""
1412+
namespace GeneratorTests;
1413+
1414+
public interface IService { }
1415+
public class MyService1 : IService { }
1416+
public class MyService2 : IService { }
1417+
""";
1418+
1419+
var compilation = CreateCompilation(source, services);
1420+
1421+
var results = CSharpGeneratorDriver
1422+
.Create(_generator)
1423+
.RunGenerators(compilation)
1424+
.GetRunResult();
1425+
1426+
var expected = """
1427+
namespace GeneratorTests;
1428+
1429+
public static partial class ServicesExtensions
1430+
{
1431+
public static partial global::System.Collections.Generic.IEnumerable<global::System.Type> GetServiceTypes()
1432+
{
1433+
return [typeof(global::GeneratorTests.MyService1), typeof(global::GeneratorTests.MyService2)];
1434+
}
1435+
}
1436+
""";
1437+
Assert.Equal(expected, results.GeneratedTrees[2].ToString());
1438+
}
1439+
1440+
[Fact]
1441+
public void ScanForTypesAttribute_ReturnsResponseArray_WithHandler()
1442+
{
1443+
var source = """
1444+
using ServiceScan.SourceGenerator;
1445+
1446+
namespace GeneratorTests;
1447+
1448+
public static partial class ServicesExtensions
1449+
{
1450+
[ScanForTypes(AssignableTo = typeof(IService), Handler = nameof(GetServiceInfo))]
1451+
public static partial ServiceInfo[] GetServiceInfos();
1452+
1453+
private static ServiceInfo GetServiceInfo<T>() => new ServiceInfo(typeof(T).Name);
1454+
}
1455+
""";
1456+
1457+
var services =
1458+
"""
1459+
namespace GeneratorTests;
1460+
1461+
public interface IService { }
1462+
public class MyService1 : IService { }
1463+
public class MyService2 : IService { }
1464+
1465+
public class ServiceInfo
1466+
{
1467+
public ServiceInfo(string name) { }
1468+
}
1469+
""";
1470+
1471+
var compilation = CreateCompilation(source, services);
1472+
1473+
var results = CSharpGeneratorDriver
1474+
.Create(_generator)
1475+
.RunGenerators(compilation)
1476+
.GetRunResult();
1477+
1478+
var expected = """
1479+
namespace GeneratorTests;
1480+
1481+
public static partial class ServicesExtensions
1482+
{
1483+
public static partial global::GeneratorTests.ServiceInfo[] GetServiceInfos()
1484+
{
1485+
return [GetServiceInfo<global::GeneratorTests.MyService1>(), GetServiceInfo<global::GeneratorTests.MyService2>()];
1486+
}
1487+
}
1488+
""";
1489+
Assert.Equal(expected, results.GeneratedTrees[2].ToString());
1490+
}
1491+
1492+
[Fact]
1493+
public void ScanForTypesAttribute_ReturnsIEnumerableResponse_WithHandler()
1494+
{
1495+
var source = """
1496+
using ServiceScan.SourceGenerator;
1497+
using System.Collections.Generic;
1498+
1499+
namespace GeneratorTests;
1500+
1501+
public static partial class ServicesExtensions
1502+
{
1503+
[ScanForTypes(AssignableTo = typeof(IService), Handler = nameof(GetServiceInfo))]
1504+
public static partial IEnumerable<ServiceInfo> GetServiceInfos();
1505+
1506+
private static ServiceInfo GetServiceInfo<T>() => new ServiceInfo(typeof(T).Name);
1507+
}
1508+
""";
1509+
1510+
var services =
1511+
"""
1512+
namespace GeneratorTests;
1513+
1514+
public interface IService { }
1515+
public class MyService1 : IService { }
1516+
public class MyService2 : IService { }
1517+
1518+
public class ServiceInfo
1519+
{
1520+
public ServiceInfo(string name) { }
1521+
}
1522+
""";
1523+
1524+
var compilation = CreateCompilation(source, services);
1525+
1526+
var results = CSharpGeneratorDriver
1527+
.Create(_generator)
1528+
.RunGenerators(compilation)
1529+
.GetRunResult();
1530+
1531+
var expected = """
1532+
namespace GeneratorTests;
1533+
1534+
public static partial class ServicesExtensions
1535+
{
1536+
public static partial global::System.Collections.Generic.IEnumerable<global::GeneratorTests.ServiceInfo> GetServiceInfos()
1537+
{
1538+
return [GetServiceInfo<global::GeneratorTests.MyService1>(), GetServiceInfo<global::GeneratorTests.MyService2>()];
1539+
}
1540+
}
1541+
""";
1542+
Assert.Equal(expected, results.GeneratedTrees[2].ToString());
1543+
}
1544+
1545+
[Fact]
1546+
public void ScanForTypesAttribute_ReturnsTypeArray_MultipleAttributes()
1547+
{
1548+
var source = """
1549+
using ServiceScan.SourceGenerator;
1550+
using System;
1551+
1552+
namespace GeneratorTests;
1553+
1554+
public static partial class ServicesExtensions
1555+
{
1556+
[ScanForTypes(AssignableTo = typeof(IFirstService))]
1557+
[ScanForTypes(AssignableTo = typeof(ISecondService))]
1558+
public static partial Type[] GetServiceTypes();
1559+
}
1560+
""";
1561+
1562+
var services =
1563+
"""
1564+
namespace GeneratorTests;
1565+
1566+
public interface IFirstService { }
1567+
public interface ISecondService { }
1568+
public class MyService1 : IFirstService { }
1569+
public class MyService2 : ISecondService { }
1570+
""";
1571+
1572+
var compilation = CreateCompilation(source, services);
1573+
1574+
var results = CSharpGeneratorDriver
1575+
.Create(_generator)
1576+
.RunGenerators(compilation)
1577+
.GetRunResult();
1578+
1579+
var expected = """
1580+
namespace GeneratorTests;
1581+
1582+
public static partial class ServicesExtensions
1583+
{
1584+
public static partial global::System.Type[] GetServiceTypes()
1585+
{
1586+
return [typeof(global::GeneratorTests.MyService1), typeof(global::GeneratorTests.MyService2)];
1587+
}
1588+
}
1589+
""";
1590+
Assert.Equal(expected, results.GeneratedTrees[2].ToString());
1591+
}
1592+
1593+
[Fact]
1594+
public void ScanForTypesAttribute_HandlerReturnTypeMismatch_ReportsDiagnostic()
1595+
{
1596+
var source = """
1597+
using ServiceScan.SourceGenerator;
1598+
1599+
namespace GeneratorTests;
1600+
1601+
public static partial class ServicesExtensions
1602+
{
1603+
[ScanForTypes(AssignableTo = typeof(IService), Handler = nameof(GetServiceName))]
1604+
public static partial ServiceInfo[] GetServiceInfos();
1605+
1606+
private static string GetServiceName<T>() => typeof(T).Name;
1607+
}
1608+
""";
1609+
1610+
var services =
1611+
"""
1612+
namespace GeneratorTests;
1613+
1614+
public interface IService { }
1615+
public class MyService : IService { }
1616+
1617+
public class ServiceInfo { }
1618+
""";
1619+
1620+
var compilation = CreateCompilation(source, services);
1621+
1622+
var results = CSharpGeneratorDriver
1623+
.Create(_generator)
1624+
.RunGenerators(compilation)
1625+
.GetRunResult();
1626+
1627+
Assert.Equal(results.Diagnostics.Single().Descriptor, DiagnosticDescriptors.WrongHandlerReturnTypeForCollectionReturn);
1628+
}
1629+
1630+
[Fact]
1631+
public void ScanForTypesAttribute_NoHandlerNonTypeCollection_ReportsDiagnostic()
1632+
{
1633+
var source = """
1634+
using ServiceScan.SourceGenerator;
1635+
1636+
namespace GeneratorTests;
1637+
1638+
public static partial class ServicesExtensions
1639+
{
1640+
[ScanForTypes(AssignableTo = typeof(IService))]
1641+
public static partial string[] GetServiceNames();
1642+
}
1643+
""";
1644+
1645+
var services =
1646+
"""
1647+
namespace GeneratorTests;
1648+
1649+
public interface IService { }
1650+
public class MyService : IService { }
1651+
""";
1652+
1653+
var compilation = CreateCompilation(source, services);
1654+
1655+
var results = CSharpGeneratorDriver
1656+
.Create(_generator)
1657+
.RunGenerators(compilation)
1658+
.GetRunResult();
1659+
1660+
Assert.Equal(results.Diagnostics.Single().Descriptor, DiagnosticDescriptors.MissingCustomHandlerOnGenerateServiceHandler);
1661+
}
13461662
}

0 commit comments

Comments
 (0)