对于多个(非常高级)分析,我想要Roslyn SDK:1。仅对“新”代码应用诊断(保留过时的代码)2。检测死代码(对于公共方法,定义应用程序的入口点)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核心2.1和.NET 4.6.1运行它(因为Microsoft.CodeAnalysis.Workspaces.MSBuild被追踪为.NET 4.6.1)
我得到的错误(基于不同的设置):
.NET 4.6.1
使用以下消息处理文件'cusotom project.vbproj.or.csproj'时Msbuild失败: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 \ NuGet \ NuGet.Build”实例化“GetReferenceNearestTargetFrameworkTask”任务。 Tasks.dll”。请验证是否使用与计算机上安装的Microsoft.Build.Framework程序集相同的Microsoft.Build.Framework程序集版本构建了任务程序集,并确保主机应用程序没有缺少Microsoft.Build.Framework的绑定重定向。无法将“NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask”类型的对象强制转换为“Microsoft.Build.Framework.ITask”。
带有MSBUILD_EXE_PATH的.NET 4.6.1
使用以下消息处理文件'cusotom project.vbproj.or.csproj'时Msbuild失败:C:\ Program Files(x86)\ MSBuild \ 14.0 \ bin \ Microsoft.Common.CurrentVersion.targets:(1407,5):“ AssignProjectConfiguration“无法从程序集”Microsoft.Build.Tasks.Core,Version = 14.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a“实例化任务。请验证是否使用与计算机上安装的Microsoft.Build.Framework程序集相同的Microsoft.Build.Framework程序集版本构建了任务程序集,并确保主机应用程序没有缺少Microsoft.Build.Framework的绑定重定向。无法将“Microsoft.Build.Tasks.AssignProjectConfiguration”类型的对象强制转换为“Microsoft.Build.Framework.ITask”。
.NET Core 2.1
使用消息处理文件'cusotom project.vbproj.or.csproj'时Msbuild失败:找不到导入的项目“\ bin \ Debug \ netcoreapp2.1 \ Microsoft..targets”。确认声明中的路径是否正确,以及该文件是否存在于磁盘上。 *
.NET Core 2.1(带MSBUILD_EXE_PATH)
使用以下消息处理文件'cusotom project.vbproj.or.csproj'时,Msbuild失败:Program Files \ dotnet \ sdk .. \ Microsoft.Common.CurrentVersion.targets:(1544,5):“Microsoft.Build.Tasks。 ResolveNonMSBuildProjectOutput“无法从程序集Microsoft.Build.Tasks.Core,Version = 15.1.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a加载任务。确认声明是否正确,程序集及其所有依赖项是否可用,以及该任务是否包含实现Microsoft.Build.Framework.ITask的公共类。
我设置路径的方式:
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", @"Program Files\dotnet\sdk\..\MSBuild.dll");
我也尝试过,因为这是在某处提出的,但这并没有改变任何东西。
好的,所以这里似乎有几件事情在起作用。
MSBuildWorkspace.Create()
方法之前,应将其配置为使用本地计算机上的特定msbuild配置。这是使用MEF解决所有必需依赖项所必需的。看看Dustin Campbell写的here的描述。
除Microsoft.Build.Locator外,不要在应用程序输出中包含任何Microsoft.Build.*
程序集。如果您的应用程序包含Microsoft.Build.dll
,Microsoft.Build.Framework.dll
,Microsoft.Build.Tasks.Core
或Microsoft.Build.Utiltiies.Core
,它们可能会干扰MSBuildLocator已安装的程序集解析处理程序。MSBuildLocator
,它可以在Microsoft.MSBuild.Locator
nuget包中找到(这里)。