diff --git a/Directory.Build.targets b/Directory.Build.targets
deleted file mode 100644
index f4c649bda..000000000
--- a/Directory.Build.targets
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
- <_LocalTopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''"/>
-
-
-
diff --git a/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs b/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
index 328021c6d..9efc74024 100644
--- a/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
+++ b/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
@@ -102,18 +102,47 @@ sealed class PreserveAttribute : Attribute
{
methodSymbols.Add(methodSymbol!);
}
+ }
+
+ var interfaces = methodSymbols.GroupBy(m => m.ContainingType).ToDictionary(g => g.Key, v => v.ToList());
+
+ // Look through the candidate interfaces
+ var interfaceSymbols = new List();
+ foreach(var iface in receiver.CandidateInterfaces)
+ {
+ var model = compilation.GetSemanticModel(iface.SyntaxTree);
+
+ // get the symbol belonging to the interface
+ var ifaceSymbol = model.GetDeclaredSymbol(iface);
+
+ // See if we already know about it, might be a dup
+ if (ifaceSymbol is null || interfaces.ContainsKey(ifaceSymbol))
+ continue;
+
+ // The interface has no refit methods, but its base interfaces might
+ var hasDerivedRefit = ifaceSymbol.AllInterfaces
+ .SelectMany(i => i.GetMembers().OfType())
+ .Where(m => IsRefitMethod(m, httpMethodBaseAttributeSymbol))
+ .Any();
+
+ if(hasDerivedRefit)
+ {
+ // Add the interface to the generation list with an empty set of methods
+ // The logic already looks for base refit methods
+ interfaces.Add(ifaceSymbol, new List());
+ }
}
var keyCount = new Dictionary();
// group the fields by interface and generate the source
- foreach (var group in methodSymbols.GroupBy(m => m.ContainingType))
+ foreach (var group in interfaces)
{
// each group is keyed by the Interface INamedTypeSymbol and contains the members
// with a refit attribute on them. Types may contain other members, without the attribute, which we'll
// need to check for and error out on
- var classSource = ProcessInterface(group.Key, group.ToList(), preserveAttributeSymbol, disposableInterfaceSymbol, httpMethodBaseAttributeSymbol, context);
+ var classSource = ProcessInterface(group.Key, group.Value, preserveAttributeSymbol, disposableInterfaceSymbol, httpMethodBaseAttributeSymbol, context);
var keyName = group.Key.Name;
if(keyCount.TryGetValue(keyName, out var value))
@@ -123,7 +152,7 @@ sealed class PreserveAttribute : Attribute
keyCount[keyName] = value;
context.AddSource($"{keyName}_refit.cs", SourceText.From(classSource, Encoding.UTF8));
- }
+ }
}
@@ -390,6 +419,8 @@ class SyntaxReceiver : ISyntaxReceiver
{
public List CandidateMethods { get; } = new();
+ public List CandidateInterfaces { get; } = new();
+
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
// We're looking for methods with an attribute that are in an interfaces
@@ -399,6 +430,13 @@ methodDeclarationSyntax.Parent is InterfaceDeclarationSyntax &&
{
CandidateMethods.Add(methodDeclarationSyntax);
}
+
+ // We also look for interfaces that derive from others, so we can see if any base methods contain
+ // Refit methods
+ if(syntaxNode is InterfaceDeclarationSyntax iface && iface.BaseList is not null)
+ {
+ CandidateInterfaces.Add(iface);
+ }
}
}
}
diff --git a/Refit.Tests/InheritedInterfacesApi.cs b/Refit.Tests/InheritedInterfacesApi.cs
index 233d55999..a629979b4 100644
--- a/Refit.Tests/InheritedInterfacesApi.cs
+++ b/Refit.Tests/InheritedInterfacesApi.cs
@@ -47,6 +47,11 @@ public interface IAmInterfaceF_RequireUsing
[Get("/get-requiring-using")]
Task Get(List guids);
}
+
+ public interface IContainAandB : IAmInterfaceB, IAmInterfaceA
+ {
+
+ }
}
namespace Refit.Tests.SeparateNamespaceWithModel
diff --git a/Refit.Tests/Refit.Tests.csproj b/Refit.Tests/Refit.Tests.csproj
index 3601ed55d..3defea3b1 100644
--- a/Refit.Tests/Refit.Tests.csproj
+++ b/Refit.Tests/Refit.Tests.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/Refit.Tests/RestService.cs b/Refit.Tests/RestService.cs
index 07e539831..c6b3fbcb9 100644
--- a/Refit.Tests/RestService.cs
+++ b/Refit.Tests/RestService.cs
@@ -1685,6 +1685,31 @@ public async Task InheritedMethodTest()
mockHttp.VerifyNoOutstandingExpectation();
}
+
+ [Fact]
+ public async Task InheritedInterfaceWithOnlyBaseMethodsTest()
+ {
+ var mockHttp = new MockHttpMessageHandler();
+
+ var settings = new RefitSettings
+ {
+ HttpMessageHandlerFactory = () => mockHttp
+ };
+
+ var fixture = RestService.For("https://httpbin.org", settings);
+
+ mockHttp.Expect(HttpMethod.Get, "https://httpbin.org/get").Respond("application/json", nameof(IAmInterfaceA.Ping));
+ var resp = await fixture.Ping();
+ Assert.Equal(nameof(IAmInterfaceA.Ping), resp);
+ mockHttp.VerifyNoOutstandingExpectation();
+
+ mockHttp.Expect(HttpMethod.Get, "https://httpbin.org/get")
+ .Respond("application/json", nameof(IAmInterfaceB.Pong));
+ resp = await fixture.Pong();
+ Assert.Equal(nameof(IAmInterfaceB.Pong), resp);
+ mockHttp.VerifyNoOutstandingExpectation();
+ }
+
[Fact]
public async Task DictionaryDynamicQueryparametersTest()
{