JasonBock / Rocks

A mocking library based on the Compiler APIs (Roslyn + Mocks)
MIT License
263 stars 20 forks source link

Nested Generic Types are Not Being Handled Correctly #333

Closed JasonBock closed 1 month ago

JasonBock commented 3 months ago

To Reproduce

#nullable enable

using Rocks;
using System;

[assembly: Rock(typeof(IUseGeneric<>), BuildType.Create)]

public interface IUseGeneric<T>
{
  IAmGeneric<T> Calculate();    

  public interface IAmGeneric<T2> { }
}

Expected behavior The mock is created as expected.

Actual behavior Errors occurs:

Error - Id: CS0305, Description: Rocks\Rocks.RockGenerator\IUseGenericT_Rock_Create.g.cs(17,55): error CS0305: Using the generic type 'IUseGeneric<T>' requires 1 type arguments
Error - Id: CS0305, Description: Rocks\Rocks.RockGenerator\IUseGenericT_Rock_Create.g.cs(17,91): error CS0305: Using the generic type 'IUseGeneric<T>' requires 1 type arguments
Error - Id: CS0305, Description: Rocks\Rocks.RockGenerator\IUseGenericT_Rock_Create.g.cs(45,18): error CS0305: Using the generic type 'IUseGeneric<T>' requires 1 type arguments
Error - Id: CS0305, Description: Rocks\Rocks.RockGenerator\IUseGenericT_Rock_Create.g.cs(107,133): error CS0305: Using the generic type 'IUseGeneric<T>' requires 1 type arguments
Error - Id: CS0305, Description: Rocks\Rocks.RockGenerator\IUseGenericT_Rock_Create.g.cs(107,169): error CS0305: Using the generic type 'IUseGeneric<T>' requires 1 type arguments
Error - Id: CS0738, Description: Rocks\Rocks.RockGenerator\IUseGenericT_Rock_Create.g.cs(37,5): error CS0738: 'IUseGenericCreateExpectations<T>.Mock' does not implement interface member 'IUseGeneric<T>.Calculate()'. 'IUseGenericCreateExpectations<T>.Mock.Calculate()' cannot implement 'IUseGeneric<T>.Calculate()' because it does not have the matching return type of 'IUseGeneric<T>.IAmGeneric<T>'.

Additional context Since the return type is generic and nested within another generic type, Rocks isn't putting in the generic parameter correctly for the outer type. Need to ensure that Rocks always generates the right type name with the right number of generic parameters no matter what the nesting is. This should be for property types, parameters, return values - anywhere a type name is needed.

This was found on Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryContext<>

JasonBock commented 3 months ago

I believe the issue lies within TypeReferenceModel.BuildName() and how it handles generics.