Bug: Solution with source generators does not compile with active SonarScanner

Whenever we have a dotnet6 projects that consumes code, generated by a source generator of another project in the same solution, a call to SonarScanner.MSBuild begin will cause a subsequent call to dotnet build to fail because the source generated code cannot be found.

Consuming source code generated by source generators within the same solution is a very common thing to do for integration testing and is described best in Andrew Lock’s infamous article series about source generators: Integration testing and NuGet packaging (andrewlock.net).

To reference source generated code within the same solution the consuming project contains entries like these:

  <ItemGroup>
    <ProjectReference Include="..\..\src\NetEscapades.EnumGenerators\NetEscapades.EnumGenerators.csproj" 
                      OutputItemType="Analyzer"
                      ReferenceOutputAssembly="false" />
    <ProjectReference Include="..\..\src\NetEscapades.EnumGenerators.Attributes\NetEscapades.EnumGenerators.Attributes.csproj" 
                      OutputItemType="Analyzer"
                      ReferenceOutputAssembly="true" />
  </ItemGroup>

Steps to reproduce

  1. clone this repo bitbonk/NetEscapades.EnumGenerators (which contains a very simple source generator solution):
    git clone https://github.com/bitbonk/NetEscapades.EnumGenerators.git
  2. build the project to see that it compiles just fine without the sonar scanner:
    run dotnet build in the repository root directory
  3. call begin of the sonar scanner, similar to this:

    dotnet C:\Users\bitbonk.nuget\packages\dotnet-sonarscanner\5.5.3\tools\net5.0\any\SonarScanner.MSBuild.dll begin /k:my.key /n:“My Title” /v:1.0.0-alpha.1 /d:sonar.host.url=https://my.selfhosted.sonarqube.website.com /d:sonar.login=MyLogin /d:sonar.password=MyPassword /d:sonar.coverageReportPaths=c:\source\repos\github\bitbonk\NetEscapades.EnumGenerators\artifacts\test-results\sonarqube\SonarQube.xml /d:sonar.links.homepage=https://my.website.com

  4. run dotnet build in the repository root directory again

Expected result

The build succeeds without errors

Actual Result

The build fails because none of the generated code consumed by the integration test project can be found:

C:\source\repos\github\bitbonk\NetEscapades.EnumGenerators\tests\NetEscapades.EnumGenerators.IntegrationTests\EnumWithSameDisplayNameExtensionsTests.cs(32,84): error CS1061: ‘EnumWithSameDisplayName’ does not contain a definition for ‘ToStringFast’ and no accessible extension method ‘ToStringFast’ accepting a first argument of type ‘EnumWithSameDisplayName’ could be found (are you missing a using directive or an assembly reference?) [C:\source\repos\github\bitbonk\NetEscapades.EnumGenerators\tests\NetEscapades.EnumGenerators.IntegrationTests\NetEscapades.EnumGenerators.IntegrationTests.csproj]

Hi @bitbonk,

You’re using an old version of the scanner (v5.5.3). There have been a couple of bugs related to source generators that have been fixed since then.

Does it repro with the latest version?

I can confirm, that the problem goes away with dotnet-sonarscanner 5.8.0

1 Like

My error was, that I only updated SonarAnalyzer.CSharp in the solution where I originally experienced the problem but not also the dotnet-sonarscanner tool.

Is there some documentation on how this whole analysis process works under the hood and what tool is used for what?
Currently we have the following SonarQube stuff in our solution:

  • dotnet-sonarscanner tool
  • a reference to the SonarAnalyzer.CSharp nuget package in every project
  • a .sonarqube folder with all sorts of files in it
  • a reference to SonarLint.xml and a ruelset file from the .sonarqube folder in every project

What is all of the above needed for? And what does dotnet-sonarscanner begin and end actually do under the hood? I am also under the expression that if dotnet-sonarscanner end fails or is not called, the whole build is in some sort of limbo state. I have to do git clean -xdf to make it compile again.