reactiveui / ReactiveUI.SourceGenerators

Use source generators to generate objects.
MIT License
29 stars 5 forks source link

[Bug]: CS8032: Analyzer couldn't be created #51

Closed fubar-coder closed 1 month ago

fubar-coder commented 1 month ago

Describe the bug 🐞

This are the error message:

CSC : warning CS8032: An instance of analyzer ReactiveUI.SourceGenerators.AsyncVoidReturningReactiveCommandMethodAnalyzer cannot be created from C:\Users\Mark Junker\.nuget\packages\reactiveui.sourcegenerators\1.1.31\analyzers\dotnet\cs\ReactiveUI.SourceGenerators.dll : Exception has been thrown by the target of an invocation.. [C:\Users\Mark Junker\source\repos\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
CSC : warning AD0001: Analyzer 'ReactiveUI.SourceGenerators.CodeAnalyzers.PropertyToReactiveFieldAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'. [C:\Users\Mark Junker\source\repos\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
CSC : warning AD0001: Analyzer 'ReactiveUI.SourceGenerators.UnsupportedCSharpLanguageVersionAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'. [C:\Users\Mark Junker\source\repos\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]

Step to reproduce

  1. Install .NET SDK 8.0.401
  2. git clone https://github.com/fubar-coder/TestReactiveUiSourceGenBug2.git
  3. dotnet build

Reproduction repository

https://github.com/fubar-coder/TestReactiveUiSourceGenBug2

Expected behavior

No build errors

Screenshots 🖼️

No response

IDE

Visual Studio 2022

Operating system

Windows 11

Version

23H2

Device

Laptop

ReactiveUI Version

20.1.52

Additional information ℹ️

This is the output in the binary build log:

Messages
    Assembly loaded during TaskRun (Microsoft.CodeAnalysis.BuildTasks.Csc): System.IO.Pipes, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a (location: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.8\System.IO.Pipes.dll, MVID: 45a7c5fa-526f-4402-9ea7-748aec4e82fd, AppDomain: Default)
    Assembly loaded during TaskRun (Microsoft.CodeAnalysis.BuildTasks.Csc): System.Security.AccessControl, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a (location: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.8\System.Security.AccessControl.dll, MVID: 8b5250e1-f9c4-43cd-8ac5-9ddb2269c1a2, AppDomain: Default)
    Microsoft (R) Visual C# Compiler version 4.11.0-3.24365.8 (9e9c7c1d)
    Copyright (C) Microsoft Corporation. All rights reserved.
    System.TypeInitializationException: The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.
    ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    --- End of inner exception stack trace ---
    at ReactiveUI.SourceGenerators.CodeAnalyzers.PropertyToReactiveFieldAnalyzer.get_SupportedDiagnostics() in c:\temp\releaser\ReactiveUI.SourceGenerators\src\ReactiveUI.SourceGenerators\CodeAnalyzers\PropertyToReactiveFieldAnalyzer.cs:line 29
    at Microsoft.CodeAnalysis.Diagnostics.AnalyzerManager.AnalyzerExecutionContext.<>c__DisplayClass21_0.<ComputeDiagnosticDescriptors_NoLock>b__0(Object _)
    at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock[TArg](DiagnosticAnalyzer analyzer, Action`1 analyze, TArg argument, Nullable`1 info, CancellationToken cancellationToken)
    -----
    System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    -----
    Analyzer 'ReactiveUI.SourceGenerators.CodeAnalyzers.PropertyToReactiveFieldAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'.
    System.TypeInitializationException: The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.
    ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    --- End of inner exception stack trace ---
    at ReactiveUI.SourceGenerators.CodeAnalyzers.PropertyToReactiveFieldAnalyzer.get_SupportedDiagnostics() in c:\temp\releaser\ReactiveUI.SourceGenerators\src\ReactiveUI.SourceGenerators\CodeAnalyzers\PropertyToReactiveFieldAnalyzer.cs:line 29
    at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.CreateDisablingMessage(DiagnosticAnalyzer analyzer, String analyzerName)
    -----
    System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    -----
    System.TypeInitializationException: The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.
    ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    --- End of inner exception stack trace ---
    at ReactiveUI.SourceGenerators.UnsupportedCSharpLanguageVersionAnalyzer.get_SupportedDiagnostics() in c:\temp\releaser\ReactiveUI.SourceGenerators\src\ReactiveUI.SourceGenerators\Diagnostics\Analyzers\UnsupportedCSharpLanguageVersionAnalyzer.cs:line 36
    at Microsoft.CodeAnalysis.Diagnostics.AnalyzerManager.AnalyzerExecutionContext.<>c__DisplayClass21_0.<ComputeDiagnosticDescriptors_NoLock>b__0(Object _)
    at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock[TArg](DiagnosticAnalyzer analyzer, Action`1 analyze, TArg argument, Nullable`1 info, CancellationToken cancellationToken)
    -----
    System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    -----
    Analyzer 'ReactiveUI.SourceGenerators.UnsupportedCSharpLanguageVersionAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'.
    System.TypeInitializationException: The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.
    ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    --- End of inner exception stack trace ---
    at ReactiveUI.SourceGenerators.UnsupportedCSharpLanguageVersionAnalyzer.get_SupportedDiagnostics() in c:\temp\releaser\ReactiveUI.SourceGenerators\src\ReactiveUI.SourceGenerators\Diagnostics\Analyzers\UnsupportedCSharpLanguageVersionAnalyzer.cs:line 36
    at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.CreateDisablingMessage(DiagnosticAnalyzer analyzer, String analyzerName)
    -----
    System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Das System kann die angegebene Datei nicht finden.
    File name: 'Microsoft.CodeAnalysis.Workspaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    at ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors..cctor()
    -----
    CompilerServer: server - server processed compilation - TestReactiveUiSourceGenBug2 (net8.0)
ChrisPulman commented 1 month ago
image
fubar-coder commented 1 month ago

This is the output of my dotnet --info:

PS C:\temp\TestReactiveUiSourceGenBug2> dotnet --info
.NET SDK:
 Version:           8.0.401
 Commit:            811edcc344
 Workload version:  8.0.400-manifests.f51a3a6b
 MSBuild version:   17.11.4+37eb419ad

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22631
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.401\

.NET workloads installed:
Configured to use loose manifests when installing new manifests.
There are no installed workloads to display.

Host:
  Version:      8.0.8
  Architecture: x64
  Commit:       08338fcaa5

.NET SDKs installed:
  3.1.426 [C:\Program Files\dotnet\sdk]
  6.0.425 [C:\Program Files\dotnet\sdk]
  8.0.400 [C:\Program Files\dotnet\sdk]
  8.0.401 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.33 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.33 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.33 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  C:\temp\TestReactiveUiSourceGenBug2\global.json

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

And this is the full build output:

PS C:\temp\TestReactiveUiSourceGenBug2> dotnet build
  Determining projects to restore...
  Restored C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj (in 590 ms).
CSC : warning CS8032: An instance of analyzer ReactiveUI.SourceGenerators.AsyncVoidReturningReactiveCommandMethodAnalyzer cannot be created from C:\Users\Mark Junker\.nuget\packages\reactiveui.sourcegenerators\1.1.31\analyzers\dotnet\cs\ReactiveUI.SourceGenerators.dll : Exception has been thrown by the target of an invocation.. [C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
CSC : warning AD0001: Analyzer 'ReactiveUI.SourceGenerators.CodeAnalyzers.PropertyToReactiveFieldAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'. [C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
CSC : warning AD0001: Analyzer 'ReactiveUI.SourceGenerators.UnsupportedCSharpLanguageVersionAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'. [C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
  TestReactiveUiSourceGenBug2 -> C:\temp\TestReactiveUiSourceGenBug2\bin\Debug\net8.0\TestReactiveUiSourceGenBug2.dll

Build succeeded.

CSC : warning CS8032: An instance of analyzer ReactiveUI.SourceGenerators.AsyncVoidReturningReactiveCommandMethodAnalyzer cannot be created from C:\Users\Mark Junker\.nuget\packages\reactiveui.sourcegenerators\1.1.31\analyzers\dotnet\cs\ReactiveUI.SourceGenerators.dll : Exception has been thrown by the target of an invocation.. [C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
CSC : warning AD0001: Analyzer 'ReactiveUI.SourceGenerators.CodeAnalyzers.PropertyToReactiveFieldAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'. [C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
CSC : warning AD0001: Analyzer 'ReactiveUI.SourceGenerators.UnsupportedCSharpLanguageVersionAnalyzer' threw an exception of type 'System.TypeInitializationException' with message 'The type initializer for 'ReactiveUI.SourceGenerators.Diagnostics.DiagnosticDescriptors' threw an exception.'. [C:\temp\TestReactiveUiSourceGenBug2\TestReactiveUiSourceGenBug2.csproj]
    3 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.96

I'll also attach a build log (both text and binary). The zip file contains the binary log. build.log msbuild.zip

jasonmalinowski commented 1 month ago

This appears to be caused by the fact the generator assembly is now referencing Microsoft.CodeAnalysis.Workspaces.CSharp and trying to trigger a load of it; I'm guessing that is happening due to https://github.com/reactiveui/ReactiveUI.SourceGenerators/commit/6de259d093b00cb5440a088ca25cbfa27e724860. The compilers don't ship this assembly so you'll see failures like this.

The fixer is best moved to its own assembly here.

fubar-coder commented 1 month ago

@jasonmalinowski Can you point to documentation (or some source code) for information about splitting the analyzer and code fixer into two different assemblies? The guide (https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix) seems to put both into the same assembly.

BTW: Why does my example code fail on my machine, but works on other machines?

EDIT: Answering my first question: the Xunit analyzers (https://github.com/xunit/xunit.analyzers) project splits them into different assemblies. But the second question, why it does work on some machines, is still puzzling me.

ChrisPulman commented 1 month ago

The code fixes still references Microsoft.CodeAnalysis.Workspaces.CSharp and the package loads both analyzers, I believe they have separated the functionality for ease of maintenance

fubar-coder commented 1 month ago

This comment might explain why I get an exception: https://github.com/dotnet/roslyn/issues/74252#issuecomment-2364691116 (somewhat).

ChrisPulman commented 1 month ago

I believe that #52 should resolve this, the error message shown in your initial post should be resolved by this fix. I have a few more things I need to update, then we can make a release.

fubar-coder commented 1 month ago

@ChrisPulman Thank you very much. I downloaded the *.nuget file from the PR build and the warning is gone! The code fix to change a property to "[Reactive]" works too!

ChrisPulman commented 1 month ago

Thank you, I will close this to keep track of what is completed, hoping to get a release out in the next few days.

jasonmalinowski commented 1 month ago

@jasonmalinowski Can you point to documentation (or some source code) for information about splitting the analyzer and code fixer into two different assemblies? The guide (https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix) seems to put both into the same assembly.

Not sure if we have documentation generally saying that somewhere, but the tutorial there is based on our templates that have separate projects for the analyzer and code fix. The docs start out with:

The analyzer with code fix template creates five projects:

  • MakeConst, which contains the analyzer.
  • MakeConst.CodeFixes, which contains the code fix.
  • MakeConst.Package, which is used to produce NuGet package for the analyzer and code fix.
  • MakeConst.Test, which is a unit test project.
  • MakeConst.Vsix, which is the default startup project that starts a second instance of Visual Studio that has loaded your new analyzer. Press F5 to start the VSIX project.

BTW: Why does my example code fail on my machine, but works on other machines?

That's hard to say without a binlog where it is working for folks. But if I had to make one guess, you might be running into a compatibility behavior. Back when Roslyn only ran on .NET Framework (...because .NET Core hadn't been invented yet) we were subject to .NET Framework assembly loading which is a bit funky. If two analyzers both depended on some library (say Newtonsoft.Json), and say analyzer A did ship it and analyzer B didn't, you might have cases where since analyzer A caused it to load, once we tried to load B the dependency was already loaded and we were good. But what happens if B loaded first? Well, we'll see A shipped it, so we'll just use that anyways. Of course, this masks the fact that if you remove extension A stuff breaks!

So it's possible somebody else shipped Microsoft.CodeAnalysis.Workspaces (which they shouldn't do) in a different analyzer and somehow that succeeded in not exploding. It's also possible that the users where it worked are running on a slightly different version of the runtime (or JIT) which happened to get lucky and not trigger a load of the Workspaces binary when we tried to load your analyzer. Either way, the advice is to split the assemblies, so it's somewhat a theoretical question.

Tutorial: Write your first analyzer and code fix - C#
This tutorial provides step-by-step instructions to build an analyzer and code fix using the .NET Compiler SDK (Roslyn APIs).
github-actions[bot] commented 4 weeks ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.