If you are using the default unit tests helper class that is automatically created from an 'Analyzer with Code Fix' project template, then you should be aware of the following.
The GetSortedDiagnosticsFromDocuments method tries to run the analyzers even if there are compilation errors when processing the code you provide as input. Of course, when there are compilation errors, the semantic model might be incomplete or missing.
You can change this method in this way:
// old version: no compilation errors detection
var compilationWithAnalyzers = project.GetCompilationAsync().Result.WithAnalyzers(ImmutableArray.Create(analyzer));
// new version: detect the compilation errors
var compilation = project.GetCompilationAsync().Result;
var compilerErrors = compilation.GetDiagnostics().Where(i => i.Severity == DiagnosticSeverity.Error);
if (compilerErrors.Any())
{
return compilerErrors.ToArray();
}
var compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzer));
If you then try to run the unit tests with this code and with your input string, you will notice at least 2 compilation errors:
error CS0012: The type 'List<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Collections, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
(the version number might be different)
and
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
You need to solve these errors to get your code compiled, so that you can access a valid semantic model.
- Change your
void TestMethod() to a static void Main(). This is not really necessary, but it's better to have a valid code without compiler errors.
- Add a reference to
System.Collections and System.Runtime to your dynamically generated project. There is no convenient way to do this in unit tests when you use the helper code from the project template. But to test it, you could change the CreateProject method.
By default, 4 additional references are configured. Add the missing references:
var collectionsReference = MetadataReference.CreateFromFile(typeof(Stack<>).Assembly.Location);
var runtimeReference = MetadataReference.CreateFromFile(typeof(ISet<>).Assembly.Location);
var solution = new AdhocWorkspace()
.CurrentSolution
.AddProject(projectId, TestProjectName, TestProjectName, language)
.AddMetadataReference() //...
// ...extend the AddMetadataReference chain
.AddMetadataReference(projectId, collectionsReference)
.AddMetadataReference(projectId, runtimeReference);
Then, you should be able to compile the code in your unit tests and to get a valid semantic model.
You might be willing to implement that dynamic references functionality e.g. by exposing the project object being created on-the-fly to the unit test caller.