8000 Generate non-implicit impls for top-level interfaces by clairernovotny · Pull Request #1062 · reactiveui/refit · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Generate non-implicit impls for top-level interfaces #1062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,19 @@ partial class {ns}{classDeclaration}
var derivedNonRefitMethods = derivedMethods.Except(derivedMethods, SymbolEqualityComparer.Default).Cast<IMethodSymbol>().ToList();

// Handle Refit Methods
foreach(var method in refitMethods.Concat(derivedRefitMethods))
foreach(var method in refitMethods)
{
ProcessRefitMethod(source, method);
ProcessRefitMethod(source, method, true);
}

foreach (var method in refitMethods.Concat(derivedRefitMethods))
{
ProcessRefitMethod(source, method, false);
}


// Handle non-refit Methods that aren't static or properties or have a method body
foreach(var method in nonRefitMethods.Concat(derivedNonRefitMethods))
foreach (var method in nonRefitMethods.Concat(derivedNonRefitMethods))
{
if (method.IsStatic ||
method.MethodKind == MethodKind.PropertyGet ||
Expand All @@ -292,9 +298,15 @@ partial class {ns}{classDeclaration}
return source.ToString();
}

void ProcessRefitMethod(StringBuilder source, IMethodSymbol methodSymbol)
/// <summary>
/// Generates the body of the Refit method
/// </summary>
/// <param name="source"></param>
/// <param name="methodSymbol"></param>
/// <param name="isTopLevel">True if directly from the type we're generating for, false for methods found on base interfaces</param>
void ProcessRefitMethod(StringBuilder source, IMethodSymbol methodSymbol, bool isTopLevel)
{
WriteMethodOpening(source, methodSymbol);
WriteMethodOpening(source, methodSymbol, !isTopLevel);

// Build the list of args for the array
var argList = new List<string>();
Expand Down Expand Up @@ -330,7 +342,7 @@ void ProcessRefitMethod(StringBuilder source, IMethodSymbol methodSymbol)

void ProcessDisposableMethod(StringBuilder source, IMethodSymbol methodSymbol)
{
WriteMethodOpening(source, methodSymbol);
WriteMethodOpening(source, methodSymbol, true);

source.Append(@"
Client?.Dispose();
Expand Down Expand Up @@ -396,7 +408,7 @@ void WriteConstraitsForTypeParameter(StringBuilder source, ITypeParameterSymbol

void ProcessNonRefitMethod(StringBuilder source, IMethodSymbol methodSymbol, GeneratorExecutionContext context)
{
WriteMethodOpening(source, methodSymbol);
WriteMethodOpening(source, methodSymbol, true);

source.Append(@"
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."");
Expand All @@ -411,12 +423,20 @@ void ProcessNonRefitMethod(StringBuilder source, IMethodSymbol methodSymbol, Gen
}
}

void WriteMethodOpening(StringBuilder source, IMethodSymbol methodSymbol)
void WriteMethodOpening(StringBuilder source, IMethodSymbol methodSymbol, bool isExplicitInterface)
{
var visibility = !isExplicitInterface ? "public " : string.Empty;

source.Append(@$"

/// <inheritdoc />
{methodSymbol.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {methodSymbol.ContainingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.{methodSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}(");
{visibility}{methodSymbol.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} ");

if(isExplicitInterface)
{
source.Append(@$"{methodSymbol.ContainingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.");
}
source.Append(@$"{methodSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}(");

if(methodSymbol.Parameters.Length > 0)
{
Expand Down
18 changes: 18 additions & 0 deletions Refit.Tests/InheritedInterfacesApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,24 @@ public interface IContainAandB : IAmInterfaceB, IAmInterfaceA
{

}

public interface IAmInterfaceEWithNoRefit<T>
{
public Task DoSomething(T parameter);

public Task DoSomethingElse();
}

public interface IImplementTheInterfaceAndUseRefit : IAmInterfaceEWithNoRefit<int>
{
#pragma warning disable CS0108 // Member hides inherited member; missing new keyword
[Get("/doSomething")]
public Task DoSomething(int parameter);
#pragma warning restore CS0108 // Member hides inherited member; missing new keyword

[Get("/DoSomethingElse")]
public new Task DoSomethingElse();
}
}

namespace Refit.Tests.SeparateNamespaceWithModel
Expand Down
192 changes: 192 additions & 0 deletions Refit.Tests/InterfaceStubGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,110 @@ public RefitTestsIGitHubApi(global::System.Net.Http.HttpClient client, global::R



/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.Tests.User> GetUser(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUser"", new global::System.Type[] { typeof(string) } );
return (global::System.Threading.Tasks.Task<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<global::Refit.Tests.User> GetUserObservable(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUserObservable"", new global::System.Type[] { typeof(string) } );
return (global::System.IObservable<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<global::Refit.Tests.User> GetUserCamelCase(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUserCamelCase"", new global::System.Type[] { typeof(string) } );
return (global::System.IObservable<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::System.Collections.Generic.List<global::Refit.Tests.User>> GetOrgMembers(string @orgName, global::System.Threading.CancellationToken @cancellationToken)
{
var ______arguments = new object[] { @orgName, @cancellationToken };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetOrgMembers"", new global::System.Type[] { typeof(string), typeof(global::System.Threading.CancellationToken) } );
return (global::System.Threading.Tasks.Task<global::System.Collections.Generic.List<global::Refit.Tests.User>>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.Tests.UserSearchResult> FindUsers(string @q)
{
var ______arguments = new object[] { @q };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""FindUsers"", new global::System.Type[] { typeof(string) } );
return (global::System.Threading.Tasks.Task<global::Refit.Tests.UserSearchResult>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::System.Net.Http.HttpResponseMessage> GetIndex()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetIndex"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task<global::System.Net.Http.HttpResponseMessage>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<string> GetIndexObservable()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetIndexObservable"", new global::System.Type[] { } );
return (global::System.IObservable<string>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.Tests.User> NothingToSeeHere()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""NothingToSeeHere"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.ApiResponse<global::Refit.Tests.User>> NothingToSeeHereWithMetadata()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""NothingToSeeHereWithMetadata"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task<global::Refit.ApiResponse<global::Refit.Tests.User>>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.ApiResponse<global::Refit.Tests.User>> GetUserWithMetadata(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUserWithMetadata"", new global::System.Type[] { typeof(string) } );
return (global::System.Threading.Tasks.Task<global::Refit.ApiResponse<global::Refit.Tests.User>>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<global::Refit.ApiResponse<global::Refit.Tests.User>> GetUserObservableWithMetadata(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUserObservableWithMetadata"", new global::System.Type[] { typeof(string) } );
return (global::System.IObservable<global::Refit.ApiResponse<global::Refit.Tests.User>>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.Tests.User> CreateUser(global::Refit.Tests.User @user)
{
var ______arguments = new object[] { @user };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""CreateUser"", new global::System.Type[] { typeof(global::Refit.Tests.User) } );
return (global::System.Threading.Tasks.Task<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.ApiResponse<global::Refit.Tests.User>> CreateUserWithMetadata(global::Refit.Tests.User @user)
{
var ______arguments = new object[] { @user };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""CreateUserWithMetadata"", new global::System.Type[] { typeof(global::Refit.Tests.User) } );
return (global::System.Threading.Tasks.Task<global::Refit.ApiResponse<global::Refit.Tests.User>>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
global::System.Threading.Tasks.Task<global::Refit.Tests.User> global::Refit.Tests.IGitHubApi.GetUser(string @userName)
{
Expand Down Expand Up @@ -314,6 +418,14 @@ public RefitTestsIGitHubApiDisposable(global::System.Net.Http.HttpClient client,



/// <inheritdoc />
public global::System.Threading.Tasks.Task RefitMethod()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""RefitMethod"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task)______func(this.Client, ______arguments);
}

/// <inheritdoc />
global::System.Threading.Tasks.Task global::Refit.Tests.IGitHubApiDisposable.RefitMethod()
{
Expand Down Expand Up @@ -364,6 +476,70 @@ public RefitTestsTestNestedINestedGitHubApi(global::System.Net.Http.HttpClient c



/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.Tests.User> GetUser(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUser"", new global::System.Type[] { typeof(string) } );
return (global::System.Threading.Tasks.Task<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<global::Refit.Tests.User> GetUserObservable(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUserObservable"", new global::System.Type[] { typeof(string) } );
return (global::System.IObservable<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<global::Refit.Tests.User> GetUserCamelCase(string @userName)
{
var ______arguments = new object[] { @userName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetUserCamelCase"", new global::System.Type[] { typeof(string) } );
return (global::System.IObservable<global::Refit.Tests.User>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::System.Collections.Generic.List<global::Refit.Tests.User>> GetOrgMembers(string @orgName)
{
var ______arguments = new object[] { @orgName };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetOrgMembers"", new global::System.Type[] { typeof(string) } );
return (global::System.Threading.Tasks.Task<global::System.Collections.Generic.List<global::Refit.Tests.User>>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::Refit.Tests.UserSearchResult> FindUsers(string @q)
{
var ______arguments = new object[] { @q };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""FindUsers"", new global::System.Type[] { typeof(string) } );
return (global::System.Threading.Tasks.Task<global::Refit.Tests.UserSearchResult>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task<global::System.Net.Http.HttpResponseMessage> GetIndex()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetIndex"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task<global::System.Net.Http.HttpResponseMessage>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.IObservable<string> GetIndexObservable()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetIndexObservable"", new global::System.Type[] { } );
return (global::System.IObservable<string>)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task NothingToSeeHere()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""NothingToSeeHere"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task)______func(this.Client, ______arguments);
}

/// <inheritdoc />
global::System.Threading.Tasks.Task<global::Refit.Tests.User> global::Refit.Tests.TestNested.INestedGitHubApi.GetUser(string @userName)
{
Expand Down Expand Up @@ -530,6 +706,22 @@ public IServiceWithoutNamespace(global::System.Net.Http.HttpClient client, globa



/// <inheritdoc />
public global::System.Threading.Tasks.Task GetRoot()
{
var ______arguments = new object[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""GetRoot"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task)______func(this.Client, ______arguments);
}

/// <inheritdoc />
public global::System.Threading.Tasks.Task PostRoot()
{
var ______arguments = new obj F82D ect[] { };
var ______func = requestBuilder.BuildRestResultFuncForMethod(""PostRoot"", new global::System.Type[] { } );
return (global::System.Threading.Tasks.Task)______func(this.Client, ______arguments);
}

/// <inheritdoc />
global::System.Threading.Tasks.Task global::IServiceWithoutNamespace.GetRoot()
{
Expand Down
38 changes: 38 additions & 0 deletions Refit.Tests/RestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,44 @@ public async Task InheritedInterfaceWithOnlyBaseMethodsTest()
mockHttp.VerifyNoOutstandingExpectation();
}


[Fact]
public async Task InheritedInterfaceWithoutRefitInBaseMethodsTest()
{
var mockHttp = new MockHttpMessageHandler();

var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHttp
};

var fixture = RestService.For<IImplementTheInterfaceAndUseRefit>("https://httpbin.org", settings);

mockHttp.Expect(HttpMethod.Get, "https://httpbin.org/doSomething")
.WithQueryString("parameter", "4")
.Respond("application/json", nameof(IImplementTheInterfaceAndUseRefit.DoSomething));

await fixture.DoSomething(4);
mockHttp.VerifyNoOutstandingExpectation();




mockHttp.Expect(HttpMethod.Get, "https://httpbin.org/DoSomethingElse")
.Respond("application/json", nameof(IImplementTheInterfaceAndUseRefit.DoSomethingElse));
await fixture.DoSomethingElse();
mockHttp.VerifyNoOutstandingExpectation();


mockHttp.Expect(HttpMethod.Get, "https://httpbin.org/DoSomethingElse")
.Respond("application/json", nameof(IImplementTheInterfaceAndUseRefit.DoSomethingElse));
await ((IAmInterfaceEWithNoRefit<int>)fixture).DoSomethingElse();
mockHttp.VerifyNoOutstandingExpectation();


Assert.Throws<InvalidOperationException>(() => RestService.For<IAmInterfaceEWithNoRefit<int>>("https://httpbin.org"));
}

[Fact]
public async Task DictionaryDynamicQueryparametersTest()
{
Expand Down
0