diff --git a/.gitignore b/.gitignore
index fbb909c..c553a41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -316,3 +316,4 @@ __pycache__/
/.aider.tags.cache.v3/cache.db-shm
/.aider.tags.cache.v3/cache.db-wal
/.aider.input.history
+.nuget-cache/
diff --git a/Directory.Build.props b/Directory.Build.props
index ec6c451..fde08c3 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -15,6 +15,9 @@
$(PackagesDirectory)
+
+ $(RepositoryRoot).nuget-cache/
+
true
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 1e37705..d7363a6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,6 +1,6 @@
-
+
diff --git a/source/Directory.Build.props b/source/Directory.Build.props
index 93c8893..0dbb300 100644
--- a/source/Directory.Build.props
+++ b/source/Directory.Build.props
@@ -4,7 +4,7 @@
- 1.0.0-beta.6
+ 1.0.0-beta.7
Steven T. Cramer
TimeWarp.SourceGenerators
TimeWarp.SourceGenerators
diff --git a/source/timewarp-source-generators/interface-delegation-generator.cs b/source/timewarp-source-generators/interface-delegation-generator.cs
index 1c54c17..6864b40 100644
--- a/source/timewarp-source-generators/interface-delegation-generator.cs
+++ b/source/timewarp-source-generators/interface-delegation-generator.cs
@@ -267,12 +267,59 @@ private static List GenerateInterfaceDelegation(
SemanticModel semanticModel)
{
var code = new List();
+ var processedMembers = new HashSet();
- // Get all members of the interface
+ // Process the interface and all inherited interfaces
+ if (interfaceType is INamedTypeSymbol namedInterface)
+ {
+ ProcessInterfaceMembers(namedInterface, delegateMemberName, classSymbol, code, processedMembers);
+ }
+
+ return code;
+ }
+
+ private static void ProcessInterfaceMembers(
+ INamedTypeSymbol interfaceType,
+ string delegateMemberName,
+ INamedTypeSymbol classSymbol,
+ List code,
+ HashSet processedMembers)
+ {
+ // First, recursively process all base interfaces
+ foreach (INamedTypeSymbol baseInterface in interfaceType.AllInterfaces)
+ {
+ ProcessInterfaceMembersCore(baseInterface, delegateMemberName, classSymbol, code, processedMembers);
+ }
+
+ // Then process the current interface's own members
+ ProcessInterfaceMembersCore(interfaceType, delegateMemberName, classSymbol, code, processedMembers);
+ }
+
+ private static void ProcessInterfaceMembersCore(
+ INamedTypeSymbol interfaceType,
+ string delegateMemberName,
+ INamedTypeSymbol classSymbol,
+ List code,
+ HashSet processedMembers)
+ {
ImmutableArray interfaceMembers = interfaceType.GetMembers();
foreach (ISymbol member in interfaceMembers)
{
+ // Create a unique key for this member to avoid duplicates
+ string memberKey = $"{member.Name}_{member.Kind}";
+ if (member is IMethodSymbol method)
+ {
+ // Include return type and parameter types in key to handle overloads and different return types
+ string returnType = method.ReturnType.ToDisplayString();
+ string paramTypes = string.Join(",", method.Parameters.Select(p => p.Type.ToDisplayString()));
+ memberKey = $"{member.Name}_{method.MethodKind}_{returnType}_{paramTypes}";
+ }
+
+ // Skip if we've already processed this member
+ if (!processedMembers.Add(memberKey))
+ continue;
+
// Skip if the class already implements this member explicitly
ISymbol? existingImplementation = classSymbol.GetMembers(member.Name)
.FirstOrDefault(m => !m.IsImplicitlyDeclared);
@@ -282,8 +329,8 @@ private static List GenerateInterfaceDelegation(
switch (member)
{
- case IMethodSymbol method when method.MethodKind == MethodKind.Ordinary:
- code.Add(GenerateMethodDelegation(method, delegateMemberName));
+ case IMethodSymbol methodSymbol when methodSymbol.MethodKind == MethodKind.Ordinary:
+ code.Add(GenerateMethodDelegation(methodSymbol, delegateMemberName));
break;
case IPropertySymbol property:
@@ -295,8 +342,6 @@ private static List GenerateInterfaceDelegation(
break;
}
}
-
- return code;
}
private static string GenerateMethodDelegation(IMethodSymbol method, string delegateMemberName)
@@ -375,7 +420,7 @@ private static string GenerateSourceFile(
builder.AppendLine();
}
- builder.AppendLine($"// Interface delegation for {className}");
+ builder.AppendLine($"// Interface delegation for {className} - YO YO YO MAMA v2 with inherited interfaces!");
builder.AppendLine($"public partial class {className}");
builder.AppendLine("{");
diff --git a/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/DataService.implements.g.cs b/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/DataService.implements.g.cs
index 1a4e45f..9f17241 100644
--- a/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/DataService.implements.g.cs
+++ b/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/DataService.implements.g.cs
@@ -3,7 +3,7 @@
namespace TimeWarp.SourceGenerators.TestConsole;
-// Interface delegation for DataService
+// Interface delegation for DataService - YO YO YO MAMA v2 with inherited interfaces!
public partial class DataService
{
// Delegation to _logger for TimeWarp.SourceGenerators.TestConsole.ILogger
diff --git a/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/StringListWrapper.implements.g.cs b/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/StringListWrapper.implements.g.cs
new file mode 100644
index 0000000..f09f73f
--- /dev/null
+++ b/tests/timewarp-source-generators-test-console/generated/timewarp-source-generators/TimeWarp.SourceGenerators.InterfaceDelegationGenerator/StringListWrapper.implements.g.cs
@@ -0,0 +1,70 @@
+//
+#nullable enable
+
+namespace TimeWarp.SourceGenerators.TestConsole;
+
+// Interface delegation for StringListWrapper - YO YO YO MAMA v2 with inherited interfaces!
+public partial class StringListWrapper
+{
+ // Delegation to InnerList for System.Collections.Generic.IList
+ public void Add(string item)
+ {
+ InnerList.Add(item);
+ }
+
+ public void Clear()
+ {
+ InnerList.Clear();
+ }
+
+ public bool Contains(string item)
+ {
+ return InnerList.Contains(item);
+ }
+
+ public void CopyTo(string[] array, int arrayIndex)
+ {
+ InnerList.CopyTo(array, arrayIndex);
+ }
+
+ public bool Remove(string item)
+ {
+ return InnerList.Remove(item);
+ }
+
+ public int Count
+ {
+ get => InnerList.Count;
+ }
+
+ public bool IsReadOnly
+ {
+ get => InnerList.IsReadOnly;
+ }
+
+ public System.Collections.Generic.IEnumerator GetEnumerator()
+ {
+ return InnerList.GetEnumerator();
+ }
+
+ public int IndexOf(string item)
+ {
+ return InnerList.IndexOf(item);
+ }
+
+ public void Insert(int index, string item)
+ {
+ InnerList.Insert(index, item);
+ }
+
+ public void RemoveAt(int index)
+ {
+ InnerList.RemoveAt(index);
+ }
+
+ public string this[int index]
+ {
+ get => InnerList[index]; set => InnerList[index] = value;
+ }
+
+}