Skip to content

Commit 16664ae

Browse files
Merge pull request #28 from TimeWarpEngineering/Cramer/2025-07-31/filename-rule
Fix interface delegation to include inherited interface members
2 parents b51ac46 + 3fe50be commit 16664ae

File tree

7 files changed

+128
-9
lines changed

7 files changed

+128
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,4 @@ __pycache__/
316316
/.aider.tags.cache.v3/cache.db-shm
317317
/.aider.tags.cache.v3/cache.db-wal
318318
/.aider.input.history
319+
.nuget-cache/

Directory.Build.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
<!-- Output packages to our local feed directory -->
1616
<PackageOutputPath>$(PackagesDirectory)</PackageOutputPath>
1717

18+
<!-- Use local NuGet cache instead of global -->
19+
<RestorePackagesPath>$(RepositoryRoot).nuget-cache/</RestorePackagesPath>
20+
1821
<!-- Suppress .NET preview SDK message -->
1922
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
2023
</PropertyGroup>

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<ItemGroup>
3-
<PackageVersion Include="TimeWarp.SourceGenerators" Version="1.0.0-beta.6" />
3+
<PackageVersion Include="TimeWarp.SourceGenerators" Version="$(Version)" />
44
<PackageVersion Include="FakeItEasy" Version="7.3.1" />
55
<PackageVersion Include="Fixie" Version="3.2.0" />
66
<PackageVersion Include="Fixie.TestAdapter" Version="3.3.0" />

source/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<!-- Default package metadata (can be overridden in individual projects) -->
66
<PropertyGroup Label="Package Metadata">
7-
<Version>1.0.0-beta.6</Version>
7+
<Version>1.0.0-beta.7</Version>
88
<Authors>Steven T. Cramer</Authors>
99
<Product>TimeWarp.SourceGenerators</Product>
1010
<PackageId>TimeWarp.SourceGenerators</PackageId>

source/timewarp-source-generators/interface-delegation-generator.cs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,59 @@ private static List<string> GenerateInterfaceDelegation(
267267
SemanticModel semanticModel)
268268
{
269269
var code = new List<string>();
270+
var processedMembers = new HashSet<string>();
270271

271-
// Get all members of the interface
272+
// Process the interface and all inherited interfaces
273+
if (interfaceType is INamedTypeSymbol namedInterface)
274+
{
275+
ProcessInterfaceMembers(namedInterface, delegateMemberName, classSymbol, code, processedMembers);
276+
}
277+
278+
return code;
279+
}
280+
281+
private static void ProcessInterfaceMembers(
282+
INamedTypeSymbol interfaceType,
283+
string delegateMemberName,
284+
INamedTypeSymbol classSymbol,
285+
List<string> code,
286+
HashSet<string> processedMembers)
287+
{
288+
// First, recursively process all base interfaces
289+
foreach (INamedTypeSymbol baseInterface in interfaceType.AllInterfaces)
290+
{
291+
ProcessInterfaceMembersCore(baseInterface, delegateMemberName, classSymbol, code, processedMembers);
292+
}
293+
294+
// Then process the current interface's own members
295+
ProcessInterfaceMembersCore(interfaceType, delegateMemberName, classSymbol, code, processedMembers);
296+
}
297+
298+
private static void ProcessInterfaceMembersCore(
299+
INamedTypeSymbol interfaceType,
300+
string delegateMemberName,
301+
INamedTypeSymbol classSymbol,
302+
List<string> code,
303+
HashSet<string> processedMembers)
304+
{
272305
ImmutableArray<ISymbol> interfaceMembers = interfaceType.GetMembers();
273306

274307
foreach (ISymbol member in interfaceMembers)
275308
{
309+
// Create a unique key for this member to avoid duplicates
310+
string memberKey = $"{member.Name}_{member.Kind}";
311+
if (member is IMethodSymbol method)
312+
{
313+
// Include return type and parameter types in key to handle overloads and different return types
314+
string returnType = method.ReturnType.ToDisplayString();
315+
string paramTypes = string.Join(",", method.Parameters.Select(p => p.Type.ToDisplayString()));
316+
memberKey = $"{member.Name}_{method.MethodKind}_{returnType}_{paramTypes}";
317+
}
318+
319+
// Skip if we've already processed this member
320+
if (!processedMembers.Add(memberKey))
321+
continue;
322+
276323
// Skip if the class already implements this member explicitly
277324
ISymbol? existingImplementation = classSymbol.GetMembers(member.Name)
278325
.FirstOrDefault(m => !m.IsImplicitlyDeclared);
@@ -282,8 +329,8 @@ private static List<string> GenerateInterfaceDelegation(
282329

283330
switch (member)
284331
{
285-
case IMethodSymbol method when method.MethodKind == MethodKind.Ordinary:
286-
code.Add(GenerateMethodDelegation(method, delegateMemberName));
332+
case IMethodSymbol methodSymbol when methodSymbol.MethodKind == MethodKind.Ordinary:
333+
code.Add(GenerateMethodDelegation(methodSymbol, delegateMemberName));
287334
break;
288335

289336
case IPropertySymbol property:
@@ -295,8 +342,6 @@ private static List<string> GenerateInterfaceDelegation(
295342
break;
296343
}
297344
}
298-
299-
return code;
300345
}
301346

302347
private static string GenerateMethodDelegation(IMethodSymbol method, string delegateMemberName)
@@ -375,7 +420,7 @@ private static string GenerateSourceFile(
375420
builder.AppendLine();
376421
}
377422

378-
builder.AppendLine($"// Interface delegation for {className}");
423+
builder.AppendLine($"// Interface delegation for {className} - YO YO YO MAMA v2 with inherited interfaces!");
379424
builder.AppendLine($"public partial class {className}");
380425
builder.AppendLine("{");
381426

tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/DataService.implements.g.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace TimeWarp.SourceGenerators.TestConsole;
55

6-
// Interface delegation for DataService
6+
// Interface delegation for DataService - YO YO YO MAMA v2 with inherited interfaces!
77
public partial class DataService
88
{
99
// Delegation to _logger for TimeWarp.SourceGenerators.TestConsole.ILogger
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// <auto-generated/>
2+
#nullable enable
3+
4+
namespace TimeWarp.SourceGenerators.TestConsole;
5+
6+
// Interface delegation for StringListWrapper - YO YO YO MAMA v2 with inherited interfaces!
7+
public partial class StringListWrapper
8+
{
9+
// Delegation to InnerList for System.Collections.Generic.IList<string>
10+
public void Add(string item)
11+
{
12+
InnerList.Add(item);
13+
}
14+
15+
public void Clear()
16+
{
17+
InnerList.Clear();
18+
}
19+
20+
public bool Contains(string item)
21+
{
22+
return InnerList.Contains(item);
23+
}
24+
25+
public void CopyTo(string[] array, int arrayIndex)
26+
{
27+
InnerList.CopyTo(array, arrayIndex);
28+
}
29+
30+
public bool Remove(string item)
31+
{
32+
return InnerList.Remove(item);
33+
}
34+
35+
public int Count
36+
{
37+
get => InnerList.Count;
38+
}
39+
40+
public bool IsReadOnly
41+
{
42+
get => InnerList.IsReadOnly;
43+
}
44+
45+
public System.Collections.Generic.IEnumerator<string> GetEnumerator()
46+
{
47+
return InnerList.GetEnumerator();
48+
}
49+
50+
public int IndexOf(string item)
51+
{
52+
return InnerList.IndexOf(item);
53+
}
54+
55+
public void Insert(int index, string item)
56+
{
57+
InnerList.Insert(index, item);
58+
}
59+
60+
public void RemoveAt(int index)
61+
{
62+
InnerList.RemoveAt(index);
63+
}
64+
65+
public string this[int index]
66+
{
67+
get => InnerList[index]; set => InnerList[index] = value;
68+
}
69+
70+
}

0 commit comments

Comments
 (0)