.net - 如何使用 Roslyn SDK 编译 .NET 解决方案

标签 .net roslyn roslyn-code-analysis

对于多个(相当高级的)分析,我想要 Roslyn SDK: 1. 仅对"new"代码应用诊断(将过时代码排除在外) 2.检测死代码(对于公共(public)方法,定义应用程序的入口点) 3.批量代码修复

换句话说:仅在 visual studio 中构建并应用 DiagnosticAnalyzer 是不够的。我成功地构建了它们,并为它们编写了单元测试(受 Sonar 启发)。但是,这只能一次性分析一个(或最多几个)文件。

所以这是我的问题:我尝试了几种方法来加载完整的 .NET 解决方案并(我自己)编译它,但都失败了。

public static async Task Main(string[] args)
{
    var analyzers = (new DiagnosticAnalyzer[] { new MyCustomAnalyzer }).ToImmutableArray();

    var file = new FileInfo(@"c:\path\my_solution.sln");

    using (var workspace = MSBuildWorkspace.Create())
    {
        workspace.WorkspaceFailed += OnWorkspaceFailed;

        var solution = await workspace.OpenSolutionAsync(solutionFile.FullName);
        var dependencyGraph = solution.GetProjectDependencyGraph();
        var projectIds = dependencyGraph.GetTopologicallySortedProjects();

        foreach (var projectId in projectIds)
        {
            using (var cancel = new CancellationTokenSource())
            {
                var project = solution.GetProject(projectId);

                var compilation = (await project.GetCompilationAsync(cancel.Token))
                    .WithOptions(project.CompilationOptions)
                    .WithAnalyzers(array, cancellationToken: cancel.Token);

                foreach (var diagnostic in await compilation.GetAllDiagnosticsAsync())
                {
                    (diagnostic.Severity >= DiagnosticSeverity.Error
                        ? Console.Error
                        : Console.Out).WriteLine(diagnostic);
                    // Do magic
                }
            }
        }
    }
}

这是我包含的包列表:

<PackageReference Include="Microsoft.Build" Version="15.8.166" />
<PackageReference Include="Microsoft.Build.Framework" Version="15.8.166" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.8.166" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.8.166" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="2.9.0" />

我尝试在 .NET core 2.1 和 .NET 4.6.1 上运行它(因为 Microsoft.CodeAnalysis.Workspaces.MSBuild 被视为 .NET 4.6.1)

我得到的错误(基于不同的设置):

.NET 4.6.1

Msbuild 在处理文件“cusotom project.vbproj.or.csproj”时失败,消息为:C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft。 Common.CurrentVersion.targets:(1657、5):无法从程序集“C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\”实例化“GetReferenceNearestTargetFrameworkTask”任务NuGet\NuGet.Build.Tasks.dll”。请验证任务程序集是使用与安装在您的计算机上的相同版本的 Microsoft.Build.Framework 程序集构建的,并且您的主机应用程序没有缺少 Microsoft.Build.Framework 的绑定(bind)重定向。无法将“NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask”类型的对象转换为类型“Microsoft.Build.Framework.ITask”。

.NET 4.6.1 带 MSBUILD_EXE_PATH

Msbuild 在处理文件“cusotom project.vbproj.or.csproj”时失败,消息为:C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets: (1407 , 5): 无法从程序集“Microsoft.Build.Tasks.Core,Version=14.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”中实例化“AssignProjectConfiguration”任务。请验证任务程序集是使用与安装在您的计算机上的相同版本的 Microsoft.Build.Framework 程序集构建的,并且您的主机应用程序没有缺少 Microsoft.Build.Framework 的绑定(bind)重定向。无法将“Microsoft.Build.Tasks.AssignProjectConfiguration”类型的对象转换为类型“Microsoft.Build.Framework.ITask”。

.NET 核心 2.1

Msbuild 在处理文件“cusotom project.vbproj.or.csproj”时失败并显示消息:找不到导入的项目“\bin\Debug\netcoreapp2.1\Microsoft..targets” .确认声明中的路径正确,并且该文件存在于磁盘上。 *

.NET Core 2.1(带有 MSBUILD_EXE_PATH)

Msbuild 在处理文件“cusotom project.vbproj.or.csproj”时失败并显示消息:Program Files\dotnet\sdk..\Microsoft.Common.CurrentVersion.targets: (1544, 5): The "Microsoft.Build.Tasks.ResolveNonMSBuildProjectOutput”任务无法从程序集 Microsoft.Build.Tasks.Core、Version=15.1.0.0、Culture=neutral、PublicKeyToken=b03f5f7f11d50a3a 加载。确认声明正确,程序集及其所有依赖项可用,并且任务包含实现 Microsoft.Build.Framework.ITask 的公共(public)类。

我设置路径的方式:

Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", @"Program Files\dotnet\sdk\..\MSBuild.dll");

我也尝试了 true ,因为那是某处建议的,但这并没有改变任何东西。

最佳答案

好吧,这里似乎有几件事情在起作用。

  1. 在调用 MSBuildWorkspace.Create() 方法之前,应将其配置为使用本地计算机中的特定 msbuild 配置。这是使用 MEF 解析所有必需的依赖项所必需的。看看 Dustin Campbell 写的描述 here .

    Do not include any Microsoft.Build.* assemblies in your application output except for Microsoft.Build.Locator. If your application includes Microsoft.Build.dll, Microsoft.Build.Framework.dll, Microsoft.Build.Tasks.Core or Microsoft.Build.Utiltiies.Core, they can interfere with the assembly resolution handler that MSBuildLocator has installed.

  2. 要在您的机器上实际本地化 msbuild 实例,您应该使用辅助类 MSBuildLocator,它可以在 Microsoft.MSBuild.Locator nuget 包中找到(在这里)。

  3. 目前并不真正支持在 dotnet core 上运行这整个过程。他们更新了上面指定的 nuget 包以添加对 dotnet 核心的支持(参见 this github issue )并且可以通过预览获得 myget feed .

关于.net - 如何使用 Roslyn SDK 编译 .NET 解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53011425/

相关文章:

.net - TCP NAT-Traversal/- 使用 .NET 打洞

c# - WPF 基于异常的验证,未触发初始状态

c# - 使用 Roslyn 将自动实现的属性添加到类

c# - Microsoft.CodeAnalysis.FxCopAnalyzers 和 Microsoft.CodeAnalysis 之间有什么区别?

visual-studio-2017 - Visual Studio 2017 - 测量 "Lines of code"

.net - "dotnet test": how to run xunit tests projects in parallel?

c# - Math.Floor 或 Math.Truncate 与 (int) 在正数性能方面

c# - 我可以使用 Roslyn 来完成此 C# 语法转换吗?

c# - 使用 Roslyn 使用 CSharpSyntaxRewriter 重写标识符名称时如何防止_loosing_缩进(WhiteSpaceTrivia)

c# - 使用 Roslyn 创建命名空间代码重构