From 213ef144d71329316bf1f2301aa9dfb91a201155 Mon Sep 17 00:00:00 2001 From: Timothy Makkison Date: Thu, 10 Oct 2024 23:15:48 +0100 Subject: [PATCH] feat: generate code for derived non refit methods and update tests. --- InterfaceStubGenerator.Shared/Parser.cs | 2 +- .../Incremental/InheritanceTest.cs | 3 +- Refit.GeneratorTests/InterfaceTests.cs | 1 - ...BaseTest#IGeneratedInterface.g.verified.cs | 6 +++ ...tInterfaceDerivedFromBaseTest.verified.txt | 24 ++++++++++++ Refit.Tests/InheritedInterfacesApi.cs | 8 ++++ Refit.Tests/RestService.cs | 38 +++++++++++++++---- 7 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest.verified.txt diff --git a/InterfaceStubGenerator.Shared/Parser.cs b/InterfaceStubGenerator.Shared/Parser.cs index 04a5e7b97..a603d7a6f 100644 --- a/InterfaceStubGenerator.Shared/Parser.cs +++ b/InterfaceStubGenerator.Shared/Parser.cs @@ -300,7 +300,7 @@ bool nullableEnabled .Where(m => IsRefitMethod(m, httpMethodBaseAttributeSymbol)) .ToArray(); var derivedNonRefitMethods = derivedMethods - .Except(derivedMethods, SymbolEqualityComparer.Default) + .Except(derivedRefitMethods, SymbolEqualityComparer.Default) .Cast() .ToArray(); diff --git a/Refit.GeneratorTests/Incremental/InheritanceTest.cs b/Refit.GeneratorTests/Incremental/InheritanceTest.cs index 50f9de48e..648d77583 100644 --- a/Refit.GeneratorTests/Incremental/InheritanceTest.cs +++ b/Refit.GeneratorTests/Incremental/InheritanceTest.cs @@ -74,7 +74,6 @@ public interface IGitHubApi : IDisposable [Fact] public void InheritFromInterfaceDoesRegenerate() { - // TODO: this currently generates invalid code see issue #1801 for more information var syntaxTree = CSharpSyntaxTree.ParseText(TwoInterface, CSharpParseOptions.Default); var compilation1 = Fixture.CreateLibrary(syntaxTree); @@ -94,6 +93,6 @@ public interface IGitHubApi : IBaseInterface """ ); var driver2 = driver1.RunGenerators(compilation2); - TestHelper.AssertRunReasons(driver2, IncrementalGeneratorRunReasons.Cached); + TestHelper.AssertRunReasons(driver2, IncrementalGeneratorRunReasons.Modified); } } diff --git a/Refit.GeneratorTests/InterfaceTests.cs b/Refit.GeneratorTests/InterfaceTests.cs index fa2332965..636fe6882 100644 --- a/Refit.GeneratorTests/InterfaceTests.cs +++ b/Refit.GeneratorTests/InterfaceTests.cs @@ -40,7 +40,6 @@ public interface IBaseInterface [Fact] public Task RefitInterfaceDerivedFromBaseTest() { - // TODO: this currently generates invalid code see issue #1801 for more information return Fixture.VerifyForType( """ public interface IGeneratedInterface : IBaseInterface diff --git a/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest#IGeneratedInterface.g.verified.cs b/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest#IGeneratedInterface.g.verified.cs index 4004148f6..e4f43fc5c 100644 --- a/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest#IGeneratedInterface.g.verified.cs +++ b/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest#IGeneratedInterface.g.verified.cs @@ -46,6 +46,12 @@ public RefitGeneratorTestIGeneratedInterface(global::System.Net.Http.HttpClient return await ((global::System.Threading.Tasks.Task)______func(this.Client, ______arguments)).ConfigureAwait(false); } + + /// + void global::RefitGeneratorTest.IBaseInterface.NonRefitMethod() + { + throw new global::System.NotImplementedException("Either this method has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument."); + } } } } diff --git a/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest.verified.txt b/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest.verified.txt new file mode 100644 index 000000000..9465ba630 --- /dev/null +++ b/Refit.GeneratorTests/_snapshots/InterfaceTests.RefitInterfaceDerivedFromBaseTest.verified.txt @@ -0,0 +1,24 @@ +{ + Diagnostics: [ + { + Location: /* +{ + void NonRefitMethod(); + ^^^^^^^^^^^^^^ +} +*/ + : (19,9)-(19,23), + Message: Method IBaseInterface.NonRefitMethod either has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument, + Severity: Warning, + WarningLevel: 1, + Descriptor: { + Id: RF001, + Title: Refit types must have Refit HTTP method attributes, + MessageFormat: Method {0}.{1} either has no Refit HTTP method attribute or you've used something other than a string literal for the 'path' argument, + Category: Refit, + DefaultSeverity: Warning, + IsEnabledByDefault: true + } + } + ] +} \ No newline at end of file diff --git a/Refit.Tests/InheritedInterfacesApi.cs b/Refit.Tests/InheritedInterfacesApi.cs index a0362baea..f2d1662fc 100644 --- a/Refit.Tests/InheritedInterfacesApi.cs +++ b/Refit.Tests/InheritedInterfacesApi.cs @@ -66,6 +66,14 @@ public interface IImplementTheInterfaceAndUseRefit : IAmInterfaceEWithNoRefit Test(); +#pragma warning restore CS0108 // Member hides inherited member; missing new keyword + } + public interface IMyClient { [Get("/")] diff --git a/Refit.Tests/RestService.cs b/Refit.Tests/RestService.cs index cf940c7ad..8515c1a2b 100644 --- a/Refit.Tests/RestService.cs +++ b/Refit.Tests/RestService.cs @@ -1974,19 +1974,43 @@ public async Task InheritedInterfaceWithoutRefitInBaseMethodsTest() await fixture.DoSomethingElse(); mockHttp.VerifyNoOutstandingExpectation(); - mockHttp - .Expect(HttpMethod.Get, "https://httpbin.org/DoSomethingElse") - .Respond("application/json", nameof(IImplementTheInterfaceAndUseRefit.DoSomethingElse)); - await ((IAmInterfaceEWithNoRefit)fixture).DoSomethingElse(); + // base non refit method should throw NotImplementedException + await Assert.ThrowsAsync( + () => ((IAmInterfaceEWithNoRefit)fixture).DoSomethingElse() + ); mockHttp.VerifyNoOutstandingExpectation(); + } + + [Fact] + public async Task InheritedInterfaceWithoutRefitMethodsOverrideBaseTest() + { + var mockHttp = new MockHttpMessageHandler(); + + var settings = new RefitSettings { HttpMessageHandlerFactory = () => mockHttp }; - Assert.Throws( - () => RestService.For>("https://httpbin.org") + var fixture = RestService.For( + "https://httpbin.org", + settings ); + + // inherited non refit method should throw NotImplementedException + await Assert.ThrowsAsync( + () => fixture.Test() + ); + mockHttp.VerifyNoOutstandingExpectation(); + + // base Refit method should respond + mockHttp + .Expect(HttpMethod.Get, "https://httpbin.org/get") + .WithQueryString("result", "Test") + .Respond("application/json", nameof(IAmInterfaceD.Test)); + + await ((IAmInterfaceD)fixture).Test(); + mockHttp.VerifyNoOutstandingExpectation(); } [Fact] - public async Task DictionaryDynamicQueryparametersTest() + public async Task DictionaryDynamicQueryParametersTest() { var mockHttp = new MockHttpMessageHandler();