CS0436 warning when importing builders into another project.
When importing builders generated with BuilderGenerator into another project, the following warnings are produced:
/home/user/repos/example/Tests/BuilderGenerator/BuilderGenerator.BuilderGenerator/BuilderBaseClass.cs(26,16): warning CS0436: The type 'Builder<T>' in 'BuilderGenerator/BuilderGenerator.BuilderGenerator/BuilderBaseClass.cs' conflicts with the imported type 'Builder<T>' in 'SharedEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'BuilderGenerator/BuilderGenerator.BuilderGenerator/BuilderBaseClass.cs'. [/home/user/repos/example/Tests/Tests.csproj]
BuilderGenerator is being used to generate builders in a project shared by multiple other projects (including Tests). This has the following .csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Disabled because BuilderGenerator produces code missing the #nullable annotation -->
<NoWarn>$(NoWarn);CS8669</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\MyWebApi\MyWebApi.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="BuilderGenerator" Version="2.3.0" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
One of the applications using it (Tests) has the following .csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bogus" Version="34.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
<PackageReference Include="Moq" Version="4.20.69" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<None Update="testsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyWebApi\MyWebApi.csproj" />
<ProjectReference Include="..\Libs\SharedEntities\SharedEntities.csproj" />
</ItemGroup>
</Project>
I unfortunately don't have time right now to submit a minimal reproduction, so I understand if this issue gets closed. I'll try and remember to come back to this when I have more time.
First: It doesn't appear that I'm getting notifications from GitHub on these issues, or it got lost in the shuffle/wall of notifications from work. Sorry about that.
Second: I'll have to reproduce this, I guess. That sounds messy. It seems like you shouldn't be seeing the one in the package itself, though, and that's probably where the problem lies. The whole reason I have to inject that file into the project referencing the library is because an assembly isn't supposed to be able to be used as an analyzer AND as a library at the same time.
After doing a lot of research about source generators for a course I've been developing, I have found that this is a not-too-uncommon problem, although it's usually the attribute class that causes the problem. The issue is normally that two different projects use the same generator. Both then have a definition of the marker attribute class for the generators. When a third project references both of the others, we now have a duplicate definition. There are a few solutions to this.
- Alter the name of the marker attribute for each project so they don't collide. I'm not even going to consider this because it's objectively awful
- Define the attribute in a separate project which is then required by the generator project. This would be something like
BuilderGenerator.CoreorBuilderGenerator.Common. - Define the attribute in a separate project (like
BuilderGenerator.Core), but package it directly into the generator package as a library. Andrew Lock referenced this in a blog series on source generators if you're interested in the gory details. https://andrewlock.net/creating-a-source-generator-part-8-solving-the-source-generator-marker-attribute-problem-part2/