dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
34.81k stars 9.84k forks source link

HubClientProxyGenerator doesn't run when using inferred generic type arguments #43510

Open albi005 opened 1 year ago

albi005 commented 1 year ago

Is there an existing issue for this?

Describe the bug

SignalR client proxy code isn't generated when using the extension method with auto-inferred type arguments (as suggested by Visual Studio).

Expected Behavior

The proxy code is generated.

Steps To Reproduce

Add Microsoft.AspNetCore.SignalR.Client.SourceGenerator package reference, add this code to a C# file:

using Microsoft.AspNetCore.SignalR.Client;

namespace ConsoleApp4;

internal static class Program
{
    static HubConnection hubConnection = null!;

    static void Main()
    {
        hubConnection = new HubConnectionBuilder().WithUrl("...").Build();
    }

    static void Register(IClient client)
    {
        // \/ Remove type argument here \/
        hubConnection.RegisterClient<IClient>(client);
    }
}

[AttributeUsage(AttributeTargets.Method)]
internal class HubServerProxyAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method)]
internal class HubClientProxyAttribute : Attribute
{
}

internal static partial class MyCustomExtensions
{
    [HubClientProxy]
    public static partial IDisposable RegisterClient<T>(this HubConnection connection, T provider);

    [HubServerProxy]
    public static partial T GetServerProxy<T>(this HubConnection connection);
}

public interface IServerHub
{
    Task SendMessage(string message);
}

public interface IClient
{
    Task ReceiveMessage(string message);
}

public class Client : IClient
{
    public Task ReceiveMessage(string message) => Task.CompletedTask;
}

then remove the generic type argument at line 18.

BrennanConroy commented 1 year ago

Looks like the issue is with how we initially filter nodes in the parser: https://github.com/dotnet/aspnetcore/blob/3ea008c80d5cc63de7f90ddfd6823b7b006251ff/src/SignalR/clients/csharp/Client.SourceGenerator/src/HubClientProxyGenerator.Parser.cs#L137-L143 We're checking if the Generic type is specified which it isn't when you let the inference figure it out.

This case is handled later on, but it's too late at that point since we've already filtered the method call out: https://github.com/dotnet/aspnetcore/blob/3ea008c80d5cc63de7f90ddfd6823b7b006251ff/src/SignalR/clients/csharp/Client.SourceGenerator/src/HubClientProxyGenerator.Parser.cs#L254-L257

94sedighi commented 1 year ago

I would like to take a look and try to find a solution for this bug

94sedighi commented 1 year ago

@albi005 can you please say which version of C# and .NET you are using? The partial methods have different restrictions in different C# versions. The code you posted to reproduce the Issue doesn't compile in C# 11 and i'm getting the following compiler error:

Error CS8795 Partial method 'MyCustomExtensions.RegisterClient<T>(HubConnection, T)' must have an implementation part because it has accessibility modifiers.

albi005 commented 1 year ago

I just created a new console app in VS2022 17.5 preview 1 and added the above code to Program.cs.

The .csproj looks like this:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.SignalR.Client.SourceGenerator" Version="7.0.0-preview.7.22376.6" />
  </ItemGroup>

</Project>