Suport roslyn analyzers on additional files

Roslyn allows to write analyzers on additional files (Technically, also on other none compiling files, but that is actively discouraged). However, Sonar does not support this, due to the fact that it filters on file extensions (at least, I think that is the reason). It would be nice if this could be supported.

For those who are interested, I’ve build a dozen rules on project files (and some on resource/resx files), that run perfectly with the compiler: .NET project file analyzers

There was also a concrete request for a rule already (Rule for avoiding pre-release packages in C#) where @Martin_Strecker gave it a try to implement such a rule.

Hi @Corniel,

I don’t know if this works but you could trick SonarQube into analyzing csproj files like so:

Add the csproj file itself as content to the csproj

In “Example.csproj” add the following

  <ItemGroup>
    <Content Include="$(MSBuildProjectFile)" CopyToOutputDirectory="Never"/>
  </ItemGroup>

This tells the Scanner for dotnet to mark the csproj file for later analysis by other languages.

Use the XML scanner to add the csproj to SonarQube

In SonarQube under “project settings” → “General settings” → “Languages” → “XML” add .csproj.

Note

I do not know if this also picks up issues raised by your analyzer, but you may want to give it a try.

We use SonarCloud, but I guess that would not make the big difference here. That being said I’d like to see full support, this feels like a hack. And Sonar obviously already runs the analysis, as they are part of the build (output). It just ignores them.

Assuming, you use Azure DevOps. Did you try to add the additional files to the analysis scope in the extra properties?

      - task: SonarQubePrepare@6
        displayName: 'Prepare analysis on SonarQube'
        condition: ne(variables['Build.Reason'], 'Schedule')
        inputs:
          SonarQube: Sonarqube
          projectKey: XXXX
          projectVersion: '$(Build.BuildNumber)'
          extraProperties: |
            # Additional properties that will be passed to the scanner,
            # Put one key=value per line, example:
            sonar.sources = src/, **/*.myExtension
            # sonar.tests = test/

We’re using the following setup:

      - task: SonarCloudPrepare@2
        condition: eq( ${{ parameters.runSonar }}, 'true' )
        inputs:
          SonarCloud: 'Tjip Sonarcloud'
          organization: 'tjip'
          scannerMode: 'MSBuild'
          ProjectKey: ${{ variables.sonarProjectKey }}
          extraProperties: |
            sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/**/coverage.opencover.xml
            sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)/**/*.trx
            sonar.exclusions= ${{ parameters.exclusions }}
            sonar.sources=**/*.csproj

I’ve added sonar.sources as per your suggestion, just to test it out.

Unfortunately, even though the project I’m building against has issues in it’s csproj:

13>C:\project\project.csproj(1,1,10,11): warning Proj0201: Define the <Version> node explicitly or define the <IsPackable> node with value 'false'. (https://dotnet-project-file-analyzers.github.io/rules/Proj0201.html)
13>C:\project\project.csproj(1,1,10,11): warning Proj0202: Define the <Description> or <PackageDescription> node explicitly or define the <IsPackable> node with value 'false'. (https://dotnet-project-file-analyzers.github.io/rules/Proj0202.html)

SonarCloud shows no issues, and my pull request doesn’t have these warnings as comments either.

Adding the CsProj file as content:

  <ItemGroup>
    <Content Include="$(MSBuildProjectFile)" CopyToOutputDirectory="Never"/>
  </ItemGroup>

Does seem to work and have the desired effect of the warnings showing up in sonarcloud.

1 Like

@ahofland Can you conferm, that in your case the project file was already added as additional file? Because in that case, I would assume that also including the build file as <Content /> should can become obsolete after some small adjustments by Sonar?

This particular project had not.

But replacing:

  <ItemGroup>
    <Content Include="$(MSBuildProjectFile)" CopyToOutputDirectory="Never"/>
  </ItemGroup>

with

  <ItemGroup>
    <AdditionalFiles Include="*.csproj" Visible="false" />
  </ItemGroup>

makes the warnings dissapear in sonarcloud.

Thank you, @ahofland, for doing this investigation and for confirming that issues in the csproj can be propagated this way.

We do have some special handling for <Content Include="" /> but we lack the special handling for <AdditionalFiles />. We will look into this as it would help with some exciting analyzer enhancements, as suggested by @Corniel.
This may have undesired consequences for some users because this mechanism is most often used by source generators to generate code based on an external file. This file may or may not be desirable for upload to the Sonar server. We need to discuss internally whether we want to enable this mechanism for all users.

1 Like

Note that inlcuding Directory.Build.props and Directory.Packages.props both as <AdditionalFIles /> or <Content /> can be inconvenient. Specially when not all *.??proj files have the same nesting compared to these files, as in those cases, it can not be defined in these special .props files themselves.

I hope you can come up with a solution that does not require extra configuration in the project files themselves. (Adding them as additional files is recomanded by Microsoft anyway, so that should be fine).