JasonBock / Rocks

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

Explicit Interface Implementation With Optional Parameters and `[CallerMemberName]` Causes Issue #332

Closed JasonBock closed 3 months ago

JasonBock commented 3 months ago

To Reproduce

Run this code:

#nullable enable

using Rocks;
using System;
using System.Runtime.CompilerServices;

[assembly: Rock(typeof(ICallerParameter), BuildType.Create)]

public interface IBaseCallerParameter
{
  int Do([CallerMemberName] string? propertyName = null);
}       

public interface ICallerParameter
  : IBaseCallerParameter
{
  new string Do([CallerMemberName] string? propertyName = null);
}

Expected behavior A mock is created with no issues.

Actual behavior The following warning is generated (it's showing up in the test as an error, but technically it's a warning, use this search to find more details on this warning):

Error - Id: CS4026, Description: Rocks\Rocks.RockGenerator\ICallerParameter_Rock_Create.g.cs(76,40): error CS4026: The CallerMemberNameAttribute applied to parameter 'propertyName' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments

Additional context This one is definitely an edge case. Note that the deriving type creates a new version of Do(), so Rocks will create an explicit implementation for the base interface method. In that case, optional values are not allowed, so Rocks correctly does not add the = null value to the parameter. However, it should also remove [CallerMemberName] as well, and then things would work as expected.

I may want to ensure that this is the same case for the other "Caller" attributes: CallerArgumentExpression, CallerFilePath, and CallerLineNumber.

This was found in R3.IBindableReactiveProperty<>, in the R3 NuGet package.