To Reproduce
Run this code in a test:
var code =
"""
using Rocks;
[assembly: Rock(typeof(IBufferedChannel), BuildType.Create | BuildType.Make)]
public interface IBufferedChannel
{
int MaxBufferSize { get; init; }
void Consume(int count) { }
}
""";
Expected behavior
Rocks generates code with no issues.
Actual behavior
A compiler diagnostic is created:
error CS8852: Init-only property or indexer 'IBufferedChannel.MaxBufferSize' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.
Additional context
This is hard to describe why this is a problem. The issue is in the generate shim:
private sealed class ShimIBufferedChannel
: global::IBufferedChannel
{
private readonly Mock mock;
public ShimIBufferedChannel(Mock @mock) =>
this.mock = @mock;
public int MaxBufferSize
{
get => ((global::IBufferedChannel)this.mock).MaxBufferSize!;
init => ((global::IBufferedChannel)this.mock).MaxBufferSize = value!;
}
}
For some reason, calling MaxBufferSize on the "parent" mock with the cast in the init isn't allowed.
One idea to fix this is to simply not do anything in the init:
private sealed class ShimIBufferedChannel
: global::IBufferedChannel
{
private readonly Mock mock;
public ShimIBufferedChannel(Mock @mock) =>
this.mock = @mock;
public int MaxBufferSize
{
get => ((global::IBufferedChannel)this.mock).MaxBufferSize!;
init;
}
}
The init (and, for that matter, the get) will never be called from the mock instance itself. Therefore, it doesn't matter what they do. The property has to be implemented, but what it does is irrelevant.
If the property itself was a DIM, the same issue occurs within the mock when it tries to call the shim's property implementation from its' init implementation. Note that the get implementation is fine. This is really odd, because the assignment is within an init accessor, which is what the diagnostic is complaining about. But we want to call the DIM's implementation.
For reference: dotnet/roslyn#50053
This was found in DotNext.IO, DotNext.Buffers.IBufferedReader.
To Reproduce
Run this code in a test:
Expected behavior
Rocks generates code with no issues.
Actual behavior
A compiler diagnostic is created:
Additional context
This is hard to describe why this is a problem. The issue is in the generate shim:
For some reason, calling
MaxBufferSizeon the "parent" mock with the cast in theinitisn't allowed.One idea to fix this is to simply not do anything in the
init:The
init(and, for that matter, theget) will never be called from the mock instance itself. Therefore, it doesn't matter what they do. The property has to be implemented, but what it does is irrelevant.If the property itself was a DIM, the same issue occurs within the mock when it tries to call the shim's property implementation from its'
initimplementation. Note that thegetimplementation is fine. This is really odd, because the assignment is within aninitaccessor, which is what the diagnostic is complaining about. But we want to call the DIM's implementation.For reference: dotnet/roslyn#50053
This was found in
DotNext.IO, DotNext.Buffers.IBufferedReader.