nunit/nunit.analyzers

BUG: An instance of analyzer ... cannot be created for linked source files

jcurl opened this issue · 5 comments

If I have a solution file, that has three projects nunitanalyzertest.zip:

  • Project A is the project to be tested.
  • Project B loads NUnit.Analyzers 4.0.1, NUnit 4.1.0
  • Project C loads NUnit.Analyzers 4.0.1, NUnit 4.1.0

I get an error such as:

Severity Warning
Code CS8032
Description An instance of analyzer NUnit.Analyzers.UpdateStringFormatToInterpolatableString.UpdateStringFormatToInterpolatableStringAnalyzer cannot be created from C:\Users\jcurl.nuget\packages\nunit.analyzers\4.0.1\analyzers\dotnet\cs\nunit.analyzers.dll: Could not load type 'NUnit.Analyzers.UpdateStringFormatToInterpolatableString.UpdateStringFormatToInterpolatableStringAnalyzer' from assembly 'nunit.analyzers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'..
Project x (net462, net6.0, net8.0)

And the following exception appears

System.TypeLoadException: Could not load type 'NUnit.Analyzers.UpdateStringFormatToInterpolatableString.UpdateStringFormatToInterpolatableStringAnalyzer' from assembly 'nunit.analyzers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. |
   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type) |
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase) |
   at Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Extensions`1.GetAnalyzersForTypeNames(Assembly analyzerAssembly, ImmutableHashSet`1 analyzerTypeNames, Boolean& reportedError)

Also occurs for the three frameworks that I use (net462, net6.0, net8.0)

  • NUnit.Analyzers.DisposeFidldsInTearDown.DisposeFieldsAndPropertiesInTearDownAnalyzer
  • NUnit.Analyzers.ValuesUsage.ValuesUsageAnalyzer
  • CollectinAssertUsage.CollectionAssertUsageAnalyzer
  • WithinUsage.WithinUsageAnalyzer
  • DiagnosticSuppressors.TypesThatOwnDisposableFieldsShouldBeDisposableSuppressor
  • DiagnosticSuppressors.AvoidUninstantiatedInternalClassSuppressor
  • StringAssertUsage.StringAssertUsageAnalyzer

Compatibility tests:

MS.NET.Test.Sdk NUnit NUnit3TestAdaptor NUnit.Analyzers Notes
17.6.2 3.14.0 4.5.0 4.0.1, 4.0.0, 3.10.0, 3.9.0, 3.8.0, 3.7.0 Error
17.6.2 3.14.0 4.5.0 3.6.1 OK
17.9.0 3.14.0 4.5.0 4.0.1, 4.0.0, 3.10.0, 3.9.0, 3.8.0, 3.7.0 Error
17.9.0 3.14.0 4.5.0 3.6.1 OK
17.9.0 4.1.0 4.5.0 4.0.1, 4.0.0, 3.10.0, 3.9.0, 3.8.0, 3.7.0 Error
17.9.0 4.1.0 4.5.0 3.6.1 OK

Please find attached the simplest project I can create. I tested it with Visual Studio 19.2 (latest available).

Workaround

I think the issue arises from the line in RJCP.NUnitAnalyzerTestSample.Test2.csproj

  <ItemGroup>
    <Compile Include="..\test1\ClassTest.cs" />
  </ItemGroup>

If I copy the file and change this to:

  <ItemGroup>
    <Compile Include="ClassTest.cs" />
  </ItemGroup>

it appears to work as expected. So likely the issue is related to linked files outside of the project tree.

My use case to do this is to test the same code under different environments dependent on the .csproj file. I can't merge them to a single .csproj file, they have to be separate and link the source code.

Thanks! I uploaded your repro here: https://github.com/nunit/nunit.issues/tree/main/Analyzer/IssueAnalyzer701

When I run the repro "as is", which corresponds afaic see with your next to last row, it should fail.

But it doesn't.

It works in VS:
image

And from command line:
image

Given that I have understood you correctly, it "works on my machine". What I have seen in some cases is that the Visual Studio cache under the .vs folder can cause problems like this. Can you check if that is the case by just deleting that folder (require closing VS first, and then reload afterwards).

Thank you for the fast reply. Your response makes me wonder if it is files left behind if not properly cleaned?

Regardless of the fault, all test cases pass on my machine as in your sample, both in Visual Studio and on the console with dotnet test. Even building with Visual Studio works. But the IDE shows CS8062 as in the original description.

So after getting the failure, I close VS2022, manually delete all bin and obj files. And the problem goes away. So let me extend the case to reproduce the issue:

And now it reproduces
image

  1. In the sample code, change the version to 3.7.0 for both projects
  2. Build and everything is great.
  3. Change the .csproj file to 4.0.1.
  4. Don't even need to rebuild, just wait and the error is reproduced.

Yes, that makes sense. But this is a VS error. I don't think we can do anything about it.
I have seen the same kind of error with other packages too. Not sure exactly what triggers it though.

PS: If it is enough to delete bin and obj, a Build Clean should also work.

PS2: I don't get the CS8032.

Thanks @OsirisTerje. After lots of testing, adding more configurations, double checking clean (using git, seems more reliable than a clean build), the problem doesn't occur, except when:

  • Having what appears to be link references
  • And changing the project from 3.7.0 or later.

CS8032 is the error code that VS is giving, as per the screenshot I posted. Something similar posted at dotnet/roslyn-analyzers#6395

I agree, that the problem seems to do with transitory files. I'll close this task. Thanks for testing on your side, else I'll never had the idea that it was some junk on the filesystem.

Also note that we have had the issue that the dlls in the nuget packages didn't have any version numbers - this was fixed in #508 - but I fear that this could make the problem worse (but this is more a guess than actually knowledge)