如何在 VS Dev Cmd 和使用 MSBuildWorkspace 的 msbuild 期间显示分析器 errors/warnings

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

我会举例说明情况。

假设我创建了一个 Roslyn 分析器,它在 Class 名称为 TestClass 时抛出错误。分析器代码如下:

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()));
    }           
}

所以我在一些 ConsoleApp 项目中安装了 Analyzer nupkg。控制台项目在 Program.cs 文件

中有以下代码
using System;

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

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

现在,如果我在 Visual Studio 中构建 ConsoleApp 项目,那么我会得到 "TestClass name not to be used" 的错误,这很好。 但是,当我尝试在 VS 2017 的开发人员命令提示符 中使用 msbuild 命令构建相同的项目时,我没有看到 Analyzer 出现任何错误。我希望 VS 的错误列表中显示的所有错误都应显示在 Dev Cmd 中。

我的最终目标是创建一个独立的代码分析工具项目,然后使用 MSBuildWorkspace 编译 ConsoleApp 项目并获得分析器 errors/warnings。部分代码如下:

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();

以上代码不显示来自分析器的 errors/warnings。

我怎样才能做到这一点? 提前致谢。

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

实际上,这些警告来自代码分析机制而不是 MSBuild 警告(如 MSBxxx)。我认为 TestClass name not to be used 只是一个警告(黄色标记)而不是错误。

在VS中IDE,其环境集成了MSBuild工具(Developer Command Prompt for VS)和代码分析器。因此,您可以在 VS IDE.

中收到警告

但是,当你使用Developer Command Prompt时,它本质上是一个单独的MSBuild编译工具,它没有集成代码分析器,因此除了 MSBuild 警告和错误 (MSBxxx) 之外,您没有此类警告。 这也是工具的局限性。警告本身不会影响整个程序。

测试

你可以通过在一个空的控制台项目中输入这个来测试它:int a=1;(这是一个代码分析器警告)我确信这个警告可以在 VS 的输出 window 中显示IDE 并且不会在 VS 的开发人员命令提示中列出。

建议

作为建议,您可以尝试将这些警告视为错误,并且 代码分析器 将这些警告传递给 msbuild 并将它们指定为 错误 这样你就可以得到 DEV 中的错误。

将这些添加到您的 xxx.csproj 文件中:

<PropertyGroup>
 <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

虽然这种方法打破了构建过程,但它是可靠和实用的。而且这个方法很常用,一般用在项目的最后制作阶段,排除大型项目的所有错误和警告,防止后续可能出现的错误,万无一失。

然后,您可以使用您的代码来构建项目。

要在 VS Dev Cmd 的 msbuild 期间显示分析器 errors/warnings,例如,您只需传递重建开关 msbuild Tempsolution.sln /t:rebuild

对于 MSBuidlWorkspace,这段代码对我有用。我们必须使用 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();