roslyn icon indicating copy to clipboard operation
roslyn copied to clipboard

Version Microsoft.CodeAnalysis 4.2.0 doesn't work

Open KondzioSSJ4 opened this issue 2 years ago • 9 comments

Version Used: 4.2.0

Steps to Reproduce:

Create 2 projects: generator with code like:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis" Version="4.2.0"/>
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

	<ItemGroup>
		<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
	</ItemGroup>

</Project>

and project that use that generator project like:

<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<TargetFramework>net6.0</TargetFramework>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
	</PropertyGroup>

	<ItemGroup>
		<ProjectReference Include="..\ExampleSourceGenerators\ExampleSourceGenerators.csproj"
						  PrivateAssets="all"
						  OutputItemType="Analyzer"/>
	</ItemGroup>

	<ItemGroup>
		<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
	</ItemGroup>
</Project>

And try to build then you will get warning like:

 warning CS8032: An instance of analyzer ExampleSourceGenerators.SomeGenerator cannot be created from ...\bin\Debug\netstandard2.0\ExampleSourceGenerators.dll : Could not load file or assembly 'Microsoft.CodeAnalysis, Version=4.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies

what for me is an error, because the generator generates other files that are required for the code to work

Expected Behavior: It works like it does for 4.1.0 version or when using Microsoft.CodeAnalysis.CSharp.Workspaces in version 4.1.0 that also works

but for some reason, I can't make a working version with 4.2.0

Actual Behavior: Generator can't find file, so generator isn't run

KondzioSSJ4 avatar May 15 '22 10:05 KondzioSSJ4

The problem is that the version of Roslyn used by your source generator has to be supported by the .Net SDK that you're using.

Experimentally, I get the same error as you when I use .Net SDK 6.0.203 or older, but it works fine on .Net SDK 6.0.300. So, you should either upgrade the version of the .Net SDK, or downgrade the version of Roslyn, so that you're in a supported combination.

Unfortunately, AFAICT, this is not well-documented. I think it would help a lot if the documentation for source generators explained the issue, and included a table listing which versions of Roslyn are supported by which SDK.

svick avatar May 15 '22 12:05 svick

In practice, generators and analyzers should targets the lowest compiler&SDK version you would use. For example when targeting .net 6, it's safe to reference 4.0.

huoyaoyuan avatar May 16 '22 07:05 huoyaoyuan

Alas, the SDK 6.0.300 seems to be not backwards-compatible with Microsoft.CodeAnalysis v4.0.1 nor v4.1.0. In both cases I get

Exception was of type 'MissingMethodException' with message 'Method not found: 'Microsoft.CodeAnalysis.IncrementalValueProvider`1<Microsoft.CodeAnalysis.MetadataReference> Microsoft.CodeAnalysis.IncrementalGeneratorInitializationContext.get_MetadataReferencesProvider()'.'

I had no issue with Microsoft.CodeAnalysis v4.1.0 and SDK 6.0.203.

The following run in github actions fails with MissingMethodException when trying to build the commit 97bb5c39abc5f58016923a5e600157bee646dabb with SDK 6.0.300. The same exception is thrown when I build the solution locally on my win10 machine and on azure devops (linux-based agent).

Do you have some recommendations?

PawelGerr avatar May 16 '22 20:05 PawelGerr

@PawelGerr

I believe that's caused by https://github.com/dotnet/roslyn/pull/58059, which says:

This is technically a breaking change, but the only thing it breaks is invalid code, so I think we should take the fix.

Though I don't know much about incremental generators, so I can't tell you why your usage of MetadataReferencesProvider would be invalid.

cc: @chsienki

svick avatar May 17 '22 09:05 svick

@svick Thx for the hint! Based on that I created a workaround. Now, the source generator works with different versions of Microsoft.CodeAnalysis and different SDKs:

  • Microsoft.CodeAnalysis 4.0.1 and 4.1.0: tested with SDK 6.0.202 and 6.0.300
  • Microsoft.CodeAnalysis 4.2.0: tested/compatible with SDK 6.0.300
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;

namespace Thinktecture;

public static class IncrementalGeneratorInitializationContextExtensions
{
   public static IncrementalValuesProvider<MetadataReference> GetMetadataReferencesProvider(this IncrementalGeneratorInitializationContext context)
   {
      var metadataProviderProperty = context.GetType().GetProperty(nameof(context.MetadataReferencesProvider))
                                     ?? throw new Exception($"The property '{nameof(context.MetadataReferencesProvider)}' not found");

      var metadataProvider = metadataProviderProperty.GetValue(context);

      if (metadataProvider is IncrementalValuesProvider<MetadataReference> metadataValuesProvider)
         return metadataValuesProvider;

      if (metadataProvider is IncrementalValueProvider<MetadataReference> metadataValueProvider)
         return metadataValueProvider.SelectMany(static (reference, _) => ImmutableArray.Create(reference));

      throw new Exception($"The '{nameof(context.MetadataReferencesProvider)}' is neither an 'IncrementalValuesProvider<{nameof(MetadataReference)}>' nor an 'IncrementalValueProvider<{nameof(MetadataReference)}>.'");
   }
}

PawelGerr avatar May 17 '22 16:05 PawelGerr

@PawelGerr We changed the metadata references provider, as it was incorrectly marked as returning a single item, when in reality it returns multiple items. If you try and combine against the single-valued version it can crash the generator runtime, which is why we opted to take a hard break.

chsienki avatar May 17 '22 17:05 chsienki

@chsienki Do you expect any issues with my workaround?

PawelGerr avatar May 17 '22 17:05 PawelGerr

No, I think the workaround looks good.

chsienki avatar May 17 '22 17:05 chsienki

Hi all, I just ran into this issue when taking my first steps towards creating a Roslyn analyser. I am running SDK version 6.0.201 and ran into the issue exactly as-described by @KondzioSSJ4 in the original comment.

In my case, downgrading my package reference for Microsoft.CodeAnalysis.CSharp.Workspaces to 4.1.0 solved the issue regarding:

...Could not load file or assembly 'Microsoft.CodeAnalysis, Version=4.2.0.0...

I'm sure upgrading my SDK would also solve the issue. It's nice that this works, but I don't really have any idea what's going on there?

So I guess my main question is, could you please give some more info as to how we could figure out this versioning conflict in future? I'm not sure what it means for a library to be "supported" by an SDK, likewise I couldn't see anything obvious on the NuGet Package Definition for Microsoft.CodeAnalysis that would suggest which versions of the SDK are supported. If there is another update to the SDK or Microsoft.CodeAnalysis package this triggers this error again, it would be great to be able to dig in and figure out what to update. Thanks very much!

NuclearFishin avatar Aug 10 '22 07:08 NuclearFishin

Hopefully this helps someone else, because it took me a little bit to track down:

My issue was as posted above my SDK version was too old for Microsoft.CodeAnalysis.

I am on Ubuntu 22.04 and am using the microsoft-prod repo. I discovered that despite having "upgraded" dotnet-* recently, I was only at version 6.0.108 using dotnet sdk check. Apparently, at some point the version format for microsoft-prod began to differ from the ubuntu repo. Ubuntu is naming packages like 6.0.108-0ubuntu1~22.04.1 while the microsoft versions were in the format 6.0.8-1 (and 108 is greater than 8).

The solution is to set the priority for a package source. Create a preferences file, eg. /etc/apt/preferences.d/99microsoft-prod

# Give microsoft repo priority
Package: *
Pin: origin packages.microsoft.com
Pin-Priority: 1000

erichiller avatar Aug 25 '22 11:08 erichiller

I got a similar issue. My source generator was failing silently during a build. As a result, some required stuff was not appropriately bootstrapped at runtime, and the app failed. I fixed it by downgrading Microsoft.CodeAnalysis.CSharp NuGet package in the project with the source generator.

I suppose, from Roslyn's perspective, if it finds unsupported assembly, it should emit an error and stop compilation. At the moment, it is not clear what went wrong.

More info about the initial issue you can find here. The solution described in this comment

byme8 avatar Dec 20 '22 22:12 byme8