Search code examples
visual-studiomsbuildcode-analysisanalyzerroslyn-code-analysis

How to show Analyzer errors/warnings during msbuild in VS Dev Cmd & using MSBuildWorkspace


I'll explain the situation with an example.

Suppose I have created a Roslyn Analyzer which throws Error when Class name is TestClass. Analyzer code is as below:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(Method, SyntaxKind.ClassDeclaration);
}

private static void Method(SyntaxNodeAnalysisContext context)
{
    var node = (ClassDeclarationSyntax)context.Node;
    var name = node.TryGetInferredMemberName();
    if(name == "TestClass")
    {
         context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation()));
    }           
}

So i install the Analyzer nupkg in some ConsoleApp project. Console project has following code in Program.cs file

using System;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }

    class TestClass
    {
        static void test()
        {
            Console.WriteLine("TestClass");
        }
    }
}

Now if i build the ConsoleApp project in Visual Studio then i get Error as "TestClass name not to be used" which is fine. But when i try to build the same project using msbuild command in Developer Command Prompt for VS 2017 i don't see any error from Analyzer. I want that all the errors shown in Error list in VS should be shown in Dev Cmd.

My end goal is to create a stand-alone code analysis tool project and then use MSBuildWorkspace to compile ConsoleApp project and get the analyzer errors/warnings. Part of code is as below:

var filePath = @"C:\Users\user\repos\ConsoleApp\ConsoleApp.sln";
var msbws = MSBuildWorkspace.Create();
var soln = await msbws.OpenSolutionAsync(filePath);
var errors = new List<Diagnostic>();
foreach (var proj in soln.Projects)
{
    var name = proj.Name;
    var compilation = await proj.GetCompilationAsync();
    errors.AddRange(compilation.GetDiagnostics().Where(n => n.Severity == DiagnosticSeverity.Error).ToList());
}
var count = errors.Count();

Above code does not show errors/warnings from analyzer.

How can i achieve this? Thanks in Advance.


Solution

  • To show analyzer errors/warnings during msbuild in VS Dev Cmd, you just have to pass rebuild switch for example msbuild Tempsolution.sln /t:rebuild

    And for MSBuidlWorkspace, this code worked for me. We have to manually specify the analyzer to use by using compilation.WithAnalyzer(ImmutableArray<DiagnosticAnalyzer>);.

    MSBuildLocator.RegisterDefaults();
    var filePath = @"C:\Users\user\repos\ConsoleApp\ConsoleApp.sln";
    var msbws = MSBuildWorkspace.Create();
    var soln = await msbws.OpenSolutionAsync(filePath);
    var errors = new List<Diagnostic>();
    foreach (var proj in soln.Projects)
    {
        var analyzer = proj.AnalyzerReferences.Where(alz => alz.Display.ToLower() == "Your analyzer name").FirstOrDefault();
        var compilation = await proj.GetCompilationAsync();
        var compWithAnalyzer = compilation.WithAnalyzers(analyzer.GetAnalyzersForAllLanguages());
        var res = compWithAnalyzer.GetAllDiagnosticsAsync().Result;
        errors.AddRange(res.Where(r => r.Severity == DiagnosticSeverity.Error).ToList());
    }
    var count = errors.Count();