stryker-mutator / stryker-net

Mutation testing for .NET core and .NET framework!
https://stryker-mutator.io
Apache License 2.0
1.76k stars 175 forks source link

Compilation fails when using compile-time logging #2634

Open mu88 opened 1 year ago

mu88 commented 1 year ago

Describe the bug When using the .NET's compile-time logging feature, Stryker fails with the following exception:

[13:52:24 WRN] Stryker.NET encountered a compile error in C:\Users\MyUser\Documents\Development\GitHub\ScreenshotCreator\src\ScreenshotCreator.Logic\Log.cs (at 49:31) with mess
age: Partial method 'Log.InvalidDimensions(ILogger, int, int, int, int)' must have an implementation part because it has accessibility modifiers. (Source code: [LoggerMessage(EventId = 6,
                      EventName = Prefix + nameof(InvalidDimensions),
                      Level = LogLevel.Warning,
                      Message =
                          "The image's dimensions are invalid. Width: {currentWidth} (expected {expectedWidth}); Height: {currentHeight} (expected {expectedHeight})")]        
    public static partial void InvalidDimensions(this ILogger logger, int currentWidth, int expectedWidth, int currentHeight, int expectedHeight);)
[13:52:24 WRN] Safe Mode! Stryker will try to continue by rolling back all mutations in method. This should not happen, please report this as an issue on github with the previous error message.
[13:52:24 FTL] Stryker.NET could not compile the project after mutation. This is probably an error for Stryker.NET and not your project. Please report this issue on github with the previous error message.
[13:52:24 INF] Time Elapsed 00:07:46.2735169
Unhandled exception.

Internal error due to compile error.

To reproduce the issue, you can use this feature branch: https://github.com/mu88/ScreenshotCreator/tree/feature/mutation-testing

Logs log-20230812.txt

Expected behavior Stryker support compile-time logging rather than failing.

Desktop (please complete the following information):

Additional context I tried to exclude the relevant files (see here), but it still fails.

dupdob commented 1 year ago

Thanks for opening an issue with a way to reproduce the problem. Sadly, this works on my machine, so I am not able to reproduce it. I am still looking into this, but solving it will be harder.

The problem you are facing is that the microsoft logging generator does not work properly. Stryker.Net's analyzers/generators support is still in the early stage; and the initial focus was on the analyzers (not the generators). While a failing analyzer is no big deal, this is more of a problem for a source generator; sadly, there is no reliable way to tell them apart. Anyway, this is the log lines that reveal the problem

2023-08-12T13:52:18.0485106+02:00  [WRN] Analyzer/Generator assembly C:\Users\MyUser\.nuget\packages\microsoft.extensions.logging.abstractions\7.0.1\analyzers\dotnet\roslyn4.4\cs\Microsoft.Extensions.Logging.Generators.dll could not be loaded. 
Generated source code may be missing. (19d16832)
System.IO.FileLoadException: Assembly with same name is already loaded.

This error is strange because:

  1. There is no reason why this assembly would already be loaded
  2. If it was actually loaded, one would expect the code generation to work properly
  3. Stryker uses LoadFrom which does not fail when assembly is already loaded (as per MS documentation)
mu88 commented 1 year ago

Thanks for looking at it 👍🏻 can I somehow work around this issue?

dupdob commented 1 year ago

I am afraid I don't have a workaround as I failed to reproduce it and I have not found the cause yet. Have you tried to build it on another machine ? (assuming you can). This is probably related to something in your setup, but can't say what as of now.

mu88 commented 1 year ago

It fails on both my private and business laptop

dupdob commented 1 year ago

Thanks. I am not sure we will able to provide a fix for this without someone on the team being able to reproduce the problem. But I still have some positive news for you:

  1. Not a workaround per se, but you should be able to run Stryker in single project mode by running it against test projects (see documentation)
  2. I will improve logging details for this so that the next release can help pinpoint the cause
mu88 commented 1 year ago

Okay, I will try that

mu88 commented 1 year ago

@dupdob the following works:

cd .\tests\Tests\
dotnet stryker --project "ScreenshotCreator.Logic"
dotnet stryker --project "ScreenshotCreator.Api"

However, this results in two different mutation reports - can I somehow merge them?

mu88 commented 1 year ago

And just FYI: when running dotnet stryker on a GitHub Action, it fails with exactly the same error, so it should be (somehow) reproducable

dupdob commented 1 year ago

thanks, I need to reproduce it on my machine for easier debugging. I feel that there is a problem with assembly resolution that surfaces in several recent issues, but not sure why or what yet...

mu88 commented 1 year ago

Maybe you can make use of this to reproduce it locally on your machine running my GitHub Action in Docker: https://github.com/nektos/act

dupdob commented 1 year ago

Thanks for this. I tried, but alas, I am working via a VM on a Mac, and I cannot use Docker within this VM.

tisonv commented 1 week ago

Hello !

Any update on that problem ?

I'm trying Striker on a .Net 8 project and I get the following :

[09:36:32 INF] Safe Mode! Stryker will flag mutations in LogHandler as compile error.
[09:36:32 WRN] Stryker.NET encountered a compile error in F:\Apd.Api\Application\Log.cs (at 21:31) with message: La méthode partielle 'Log.LogGate(ILogger, Exception, string)' doit avoir une partie implémentation, car elle a des modificateurs d'accessibilité. (Source code: [LoggerMessage(199, LogLevel.Debug, "{action}")]
    public static partial void LogGate(this ILogger logger, Exception ex, [CallerMemberName] string action = null!);)

Associated code :

    [LoggerMessage(199, LogLevel.Debug, "{action}")]
    public static partial void LogGate(this ILogger logger, Exception ex, [CallerMemberName] string action = null!);

After a lot of these errors for each of my loggers, Stryker ultimately .fails:

[09:36:32 FTL] Stryker.NET could not compile the project after mutation. This is probably an error for Stryker.NET and not your project. Please report this issue on github with the previous error message.
[09:36:32 ERR] An error occurred during the mutation test run
System.AggregateException: One or more errors occurred. (Internal error due to compile error.) (Internal error due to compile error.)
 ---> Stryker.Core.Exceptions.CompilationException: Internal error due to compile error.
   at Stryker.Core.Compiling.CSharpRollbackProcess.Start(CSharpCompilation compiler, ImmutableArray`1 diagnostics, Boolean lastAttempt, Boolean devMode) in /_/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs:line 75
   at Stryker.Core.Compiling.CsharpCompilingProcess.TryCompilation(Stream ms, Stream symbolStream, CSharpCompilation& compilation, EmitResult previousEmitResult, Boolean lastAttempt, Int32 retryCount) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 184
   at Stryker.Core.Compiling.CsharpCompilingProcess.Compile(IEnumerable`1 syntaxTrees, Stream ilStream, Stream symbolStream) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 81
   at Stryker.Core.MutationTest.CsharpMutationProcess.CompileMutations(MutationTestInput input, CsharpCompilingProcess compilingProcess) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 90
   at Stryker.Core.MutationTest.CsharpMutationProcess.Mutate(MutationTestInput input) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 80
   at Stryker.Core.MutationTest.MutationTestProcess.Mutate() in /_/src/Stryker.Core/Stryker.Core/MutationTest/MutationTestProcess.cs:line 89
   at Stryker.Core.Initialisation.ProjectMutator.MutateProject(StrykerOptions options, MutationTestInput input, IReporter reporters) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs:line 38
   at Stryker.Core.Initialisation.ProjectOrchestrator.<>c__DisplayClass7_0.<MutateProjects>b__0(MutationTestInput mutationTestInput) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectOrchestrator.cs:line 71
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.TaskReplicator.Run[TState](ReplicatableUserAction`1 action, ParallelOptions options, Boolean stopOnFirstFailure)
   at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt fromInclusive, TInt toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt fromInclusive, TInt toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
   at Stryker.Core.Initialisation.ProjectOrchestrator.MutateProjects(StrykerOptions options, IReporter reporters, ITestRunner runner) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectOrchestrator.cs:line 69
   at Stryker.Core.StrykerRunner.RunMutationTest(IStrykerInputs inputs, ILoggerFactory loggerFactory, IProjectOrchestrator projectOrchestrator) in /_/src/Stryker.Core/Stryker.Core/StrykerRunner.cs:line 63
 ---> (Inner Exception #1) Stryker.Core.Exceptions.CompilationException: Internal error due to compile error.
   at Stryker.Core.Compiling.CSharpRollbackProcess.Start(CSharpCompilation compiler, ImmutableArray`1 diagnostics, Boolean lastAttempt, Boolean devMode) in /_/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs:line 75
   at Stryker.Core.Compiling.CsharpCompilingProcess.TryCompilation(Stream ms, Stream symbolStream, CSharpCompilation& compilation, EmitResult previousEmitResult, Boolean lastAttempt, Int32 retryCount) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 184
   at Stryker.Core.Compiling.CsharpCompilingProcess.Compile(IEnumerable`1 syntaxTrees, Stream ilStream, Stream symbolStream) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 81
   at Stryker.Core.MutationTest.CsharpMutationProcess.CompileMutations(MutationTestInput input, CsharpCompilingProcess compilingProcess) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 90
   at Stryker.Core.MutationTest.CsharpMutationProcess.Mutate(MutationTestInput input) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 80
   at Stryker.Core.MutationTest.MutationTestProcess.Mutate() in /_/src/Stryker.Core/Stryker.Core/MutationTest/MutationTestProcess.cs:line 89
   at Stryker.Core.Initialisation.ProjectMutator.MutateProject(StrykerOptions options, MutationTestInput input, IReporter reporters) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs:line 38
   at Stryker.Core.Initialisation.ProjectOrchestrator.<>c__DisplayClass7_0.<MutateProjects>b__0(MutationTestInput mutationTestInput) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectOrchestrator.cs:line 71
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()<---
[09:36:32 INF] Time Elapsed 00:04:02.5002616
Unhandled exception. System.AggregateException: One or more errors occurred. (Internal error due to compile error.) (Internal error due to compile error.)
 ---> Stryker.Core.Exceptions.CompilationException: Internal error due to compile error.
   at Stryker.Core.Compiling.CSharpRollbackProcess.Start(CSharpCompilation compiler, ImmutableArray`1 diagnostics, Boolean lastAttempt, Boolean devMode) in /_/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs:line 75
   at Stryker.Core.Compiling.CsharpCompilingProcess.TryCompilation(Stream ms, Stream symbolStream, CSharpCompilation& compilation, EmitResult previousEmitResult, Boolean lastAttempt, Int32 retryCount) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 184
   at Stryker.Core.Compiling.CsharpCompilingProcess.Compile(IEnumerable`1 syntaxTrees, Stream ilStream, Stream symbolStream) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 81
   at Stryker.Core.MutationTest.CsharpMutationProcess.CompileMutations(MutationTestInput input, CsharpCompilingProcess compilingProcess) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 90
   at Stryker.Core.MutationTest.CsharpMutationProcess.Mutate(MutationTestInput input) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 80
   at Stryker.Core.MutationTest.MutationTestProcess.Mutate() in /_/src/Stryker.Core/Stryker.Core/MutationTest/MutationTestProcess.cs:line 89
   at Stryker.Core.Initialisation.ProjectMutator.MutateProject(StrykerOptions options, MutationTestInput input, IReporter reporters) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs:line 38
   at Stryker.Core.Initialisation.ProjectOrchestrator.<>c__DisplayClass7_0.<MutateProjects>b__0(MutationTestInput mutationTestInput) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectOrchestrator.cs:line 71
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.TaskReplicator.Run[TState](ReplicatableUserAction`1 action, ParallelOptions options, Boolean stopOnFirstFailure)
   at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt fromInclusive, TInt toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt fromInclusive, TInt toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
   at Stryker.Core.Initialisation.ProjectOrchestrator.MutateProjects(StrykerOptions options, IReporter reporters, ITestRunner runner) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectOrchestrator.cs:line 69
   at Stryker.Core.StrykerRunner.RunMutationTest(IStrykerInputs inputs, ILoggerFactory loggerFactory, IProjectOrchestrator projectOrchestrator) in /_/src/Stryker.Core/Stryker.Core/StrykerRunner.cs:line 63
   at Stryker.CLI.StrykerCli.RunStryker(IStrykerInputs inputs) in /_/src/Stryker.CLI/Stryker.CLI/StrykerCLI.cs:line 102
   at Stryker.CLI.StrykerCli.<>c__DisplayClass11_0.<Run>b__0() in /_/src/Stryker.CLI/Stryker.CLI/StrykerCLI.cs:line 74
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.<>c__DisplayClass143_0.<OnExecute>b__0(CancellationToken _)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
   at Stryker.CLI.StrykerCli.Run(String[] args) in /_/src/Stryker.CLI/Stryker.CLI/StrykerCLI.cs:line 80
   at Stryker.CLI.Program.Main(String[] args) in /_/src/Stryker.CLI/Stryker.CLI/Program.cs:line 14
 ---> (Inner Exception #1) Stryker.Core.Exceptions.CompilationException: Internal error due to compile error.
   at Stryker.Core.Compiling.CSharpRollbackProcess.Start(CSharpCompilation compiler, ImmutableArray`1 diagnostics, Boolean lastAttempt, Boolean devMode) in /_/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs:line 75
   at Stryker.Core.Compiling.CsharpCompilingProcess.TryCompilation(Stream ms, Stream symbolStream, CSharpCompilation& compilation, EmitResult previousEmitResult, Boolean lastAttempt, Int32 retryCount) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 184
   at Stryker.Core.Compiling.CsharpCompilingProcess.Compile(IEnumerable`1 syntaxTrees, Stream ilStream, Stream symbolStream) in /_/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs:line 81
   at Stryker.Core.MutationTest.CsharpMutationProcess.CompileMutations(MutationTestInput input, CsharpCompilingProcess compilingProcess) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 90
   at Stryker.Core.MutationTest.CsharpMutationProcess.Mutate(MutationTestInput input) in /_/src/Stryker.Core/Stryker.Core/MutationTest/CsharpMutationProcess.cs:line 80
   at Stryker.Core.MutationTest.MutationTestProcess.Mutate() in /_/src/Stryker.Core/Stryker.Core/MutationTest/MutationTestProcess.cs:line 89
   at Stryker.Core.Initialisation.ProjectMutator.MutateProject(StrykerOptions options, MutationTestInput input, IReporter reporters) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs:line 38
   at Stryker.Core.Initialisation.ProjectOrchestrator.<>c__DisplayClass7_0.<MutateProjects>b__0(MutationTestInput mutationTestInput) in /_/src/Stryker.Core/Stryker.Core/Initialisation/ProjectOrchestrator.cs:line 71
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()<---
dupdob commented 6 days ago

the problem is that the log code generator failed to load. This may be because you are targeting an non yet supported language version. There should be a warning regarding Microsoft.Extensions.Logging.Generators.dll failing to load. A general error cause should be listed there; if this is a version compatibility issue, you need to wait for next release for support. If not, this is because the generator failed to load for some other reason and we'll need to see how to replicate the context.

tisonv commented 4 days ago

There's the following warning

[07:52:49 WRN] Failed to load analyzer 'Microsoft.Extensions.Logging.Generators': Assembly with same name is already loaded (error : UnableToLoadAnalyzer, analyzer: All).
[07:52:49 WRN] Failed to load analyzer 'Microsoft.Extensions.Logging.Generators': Exception System.IO.FileLoadException: Assembly with same name is already loaded
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile)
   at Stryker.Core.Initialisation.Buildalyzer.IAnalyzerResultExtensions.AnalyzerAssemblyLoader.LoadFromPath(String fullPath) in /_/src/Stryker.Core/Stryker.Core/Initialisation/Buildalyzer/IAnalyzerResultExtensions.cs:line 134
   at Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAssembly()
   at Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Extensions`1.AddExtensions(Builder builder, String language, Func`2 shouldInclude).

Sln configuration :

<PropertyGroup>
  <TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
  <ImplicitUsings>enable</ImplicitUsings>
  <Nullable>enable</Nullable>

  <AssemblyName>_Omitted_</AssemblyName>
  <RootNamespace>_Omitted_</RootNamespace>
  <Configurations>[...],CI</Configurations>
  <Platforms>x64</Platforms>

  <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
  <EnableNETAnalyzers>True</EnableNETAnalyzers>
  <AnalysisLevel>latest-all</AnalysisLevel>

  <SupportedOSPlatformVersion>10.0.22621.0</SupportedOSPlatformVersion> 
</PropertyGroup>
dupdob commented 4 days ago

Thanks. As of know, we need a reproducing project to try and fix this issue. As I said in an earlier comment, Assembly with same name already loaded should not happen with LoadFromPath(), the method is supposed to return the already loaded assembly. Likewise FileLoadException is not listed as one of the possible exception types. It may be related to having loaded a different version of the same generators.

If you are using Stryker in solution mode, you can try in single project mode. It will be less convenient, but it may provide a workaround for this.

tisonv commented 4 days ago

It works in project mode if the project doesn't contain any log generators. If it does, Stryker fails.

I added the Microsoft.Extensions.Logging 8.0.0 dependency to all the projects in the solution but it still fails.

Any debug / log mode to check the behavior on my side ?

dupdob commented 4 days ago

if you are willing and familiar with it, you can try activating assembly resolution logging (via fuslogvw.exe) to try and figure why there are two load attempts for the logger generator. You will probably have to activate logging for successful assembly resolution, which will result in large log that may be hard to scan.

I know I tried to reproduce this issue by 'double loading' generators and it worked properly (no exception), I will see if I can reproduce it by hacking around with various versions

tisonv commented 3 days ago

Luckily I am a bit familiar I enabled the following in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion :

Sadly there weren't any references to Microsoft.Extensions.Logging.Generators or even Logging in any of the files (case not sensitive search).

I rebooted and ran Stryker straight after just in case. Same results. I ran Stryker from Powershell and Cmd. Same Results. I cleaned my nuget cache. Same Results.

I only get references to the generators when I launch Visual Studio.

tisonv commented 3 days ago

I downloaded the Stryker sources and it raises the same error I'll try to investigate tomorrow

dupdob commented 3 days ago

it is possible that explicit loading via LoadFrom does not count as 'assembly resolution', hence is not part of fuslog...

tisonv commented 3 days ago

Maybe this will help...

In Stryker.Core\Initialisation\Buildalyzer\IAnalyzerResultExtensions.cs, I get the following analyzerResult:

    [0]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk.Web\\analyzers\\cs\\Microsoft.AspNetCore.Analyzers.dll"
    [1]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk.Web\\analyzers\\cs\\Microsoft.AspNetCore.Mvc.Analyzers.dll"
    [2]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\analyzers\\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll"
    [3]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\analyzers\\Microsoft.CodeAnalysis.NetAnalyzers.dll"
    [4]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\codestyle\\cs\\Microsoft.CodeAnalysis.CodeStyle.dll"
    [5]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\codestyle\\cs\\Microsoft.CodeAnalysis.CodeStyle.Fixes.dll"
    [6]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\codestyle\\cs\\Microsoft.CodeAnalysis.CSharp.CodeStyle.dll"
    [7]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk\\targets\\..\\codestyle\\cs\\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.dll"
    [8]: "D:\\Data\\cache\\nuget\\ecocode\\1.5.1\\analyzers\\dotnet\\cs\\EcoCode.Core.dll"
    [9]: "D:\\Data\\cache\\nuget\\microsoft.entityframeworkcore.analyzers\\8.0.3\\analyzers\\dotnet\\cs\\Microsoft.EntityFrameworkCore.Analyzers.dll"
    [10]: "D:\\Data\\cache\\nuget\\sonaranalyzer.csharp\\9.32.0.97167\\analyzers\\Google.Protobuf.dll"
    [11]: "D:\\Data\\cache\\nuget\\sonaranalyzer.csharp\\9.32.0.97167\\analyzers\\SonarAnalyzer.CFG.dll"
    [12]: "D:\\Data\\cache\\nuget\\sonaranalyzer.csharp\\9.32.0.97167\\analyzers\\SonarAnalyzer.CSharp.dll"
    [13]: "D:\\Data\\cache\\nuget\\sonaranalyzer.csharp\\9.32.0.97167\\analyzers\\SonarAnalyzer.ShimLayer.dll"
    [14]: "D:\\Data\\cache\\nuget\\sonaranalyzer.csharp\\9.32.0.97167\\analyzers\\SonarAnalyzer.dll"
    [15]: "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.Interop.ComInterfaceGenerator.dll"
    [16]: "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.Interop.JavaScript.JSImportGenerator.dll"
    [17]: "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.Interop.LibraryImportGenerator.dll"
    [18]: "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.Interop.SourceGeneration.dll"
    [19]: "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\System.Text.Json.SourceGeneration.dll"
    [20]: "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\System.Text.RegularExpressions.Generator.dll"
    [21]: "C:\\Program Files\\dotnet\\packs\\Microsoft.AspNetCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.AspNetCore.App.Analyzers.dll"
    [22]: "C:\\Program Files\\dotnet\\packs\\Microsoft.AspNetCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.AspNetCore.App.CodeFixes.dll"
    [23]: "C:\\Program Files\\dotnet\\packs\\Microsoft.AspNetCore.App.Ref\\8.0.8\\analyzers\\dotnet\\cs\\Microsoft.AspNetCore.Components.Analyzers.dll"
    >> [24]: "C:\\Program Files\\dotnet\\packs\\Microsoft.AspNetCore.App.Ref\\8.0.8\\analyzers\\dotnet\\roslyn4.4\\cs\\Microsoft.Extensions.Logging.Generators.dll"
    >> [25]: "C:\\Program Files\\dotnet\\packs\\Microsoft.AspNetCore.App.Ref\\8.0.8\\analyzers\\dotnet\\roslyn4.4\\cs\\Microsoft.Extensions.Options.SourceGeneration.dll"
    [26]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk.Razor\\targets\\..\\source-generators\\Microsoft.AspNetCore.Razor.Utilities.Shared.dll"
    [27]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk.Razor\\targets\\..\\source-generators\\Microsoft.CodeAnalysis.Razor.Compiler.dll"
    [28]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk.Razor\\targets\\..\\source-generators\\Microsoft.Extensions.ObjectPool.dll"
    [29]: "C:\\Program Files\\dotnet\\sdk\\8.0.400\\Sdks\\Microsoft.NET.Sdk.Razor\\targets\\..\\source-generators\\System.Collections.Immutable.dll"

24 & 25 generate the same assembly already loaded exception. From the list here, none have a direct dependency to Microsoft.Extensions.Logging.*. In one of my test project, I have a dependency to Microsoft.AspNetCore.Mvc.Testing which has a dependency to Microsoft.Extensions.Logging.Abstractions.

Maybe a coincidence but these are the 2 assemblies that appear in the Analyzers References in Stryker when I load it in Visual Studio.

From what I seem to glance from the sources Stryker and Buildalyze share the same Context when running and that may be cause for trouble.


In GetSourceGenerators(), I added a basic

if (analyzer.Contains("Microsoft.Extensions.Logging.Generators.dll") || analyzer.Contains("Microsoft.Extensions.Options.SourceGeneration.dll"))
{
  continue;
}

Ultimately Stryker fails with a partial method must have an implementation part because it has accessibility modifiers on each LoggerMessage when compiling.

I changed the accessor of the Log class from internal static to public static in accordance to https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator but it didn't change the output.