欢迎光临散文网 会员登陆 & 注册

分析器:常见问题杂记

2023-07-07 18:23 作者:扑克子  | 我要投稿

分析器简介

本文分析器主要指以“Analyzer”模式引用的项目或NuGet包,例如源生成器(source generator)、代码分析器(analyzer)、代码修复器(codefixer)等

注:其中源生成器和代码分析器的“血缘关系”更近,可能因为都是.NET使用的分析器,而代码修复器是提供给Visual Studio使用的,所以关系疏远一些

分析器引用别的项目时的问题

根据MSDN和Visual Studio自带的代码示例,所有分析器和源生成器都必须包含以下两个库:

所有代码修复器都必须包含以下这个库:

肯定不止我一个人(bushi)想到,为什么不把一些最简单的类型、或者一些工具库给所有的分析器共享呢?这样引用时就不需要写字符串而是nameof(xxx)了,多优雅

可惜由于分析器项目的限制,除了以上说的必须包含的库,其他库都不能引用。但这也不是说每次写分析器都要手动实现.NET的新特性,Sergio Pedri[1]大佬实现了Poly#[2](PolySharp)库,这个库实现了绝大部分可以实现的特性,并且可以被分析器项目“引用”。因为它是把所有需要的代码生成到你的项目里,而非直接引用,所以绕过了分析器不能引用项目的限制

引用这个库的方法和其他库一样,在NuGet里下载并添加包引用即可

目标平台问题

分析器项目与普通项目不同,分析器本身的dll不会被用户项目直接引用,而是被编译平台(如.NET SDK或Visual Studio等)引用,从而对代码进行分析。所以分析器本身的dll不会被包含进用户项目生成的应用里(源生成器生成的代码会)

既然分析器的dll是被编译平台引用而非用户项目,那源生成器的目标平台就应该与编译平台有关,而非用户项目。例如,在x64架构的电脑上编译x86的应用程序,此时一般的用户项目目标平台都应该设置为x86,但分析器项目的目标平台却应该与电脑保持一致(x64),因为编译项目时,是电脑上x64的.NET SDK调用了分析器项目

为了保证项目编译的可移植性,如何判断编译电脑的架构并设置为对应平台呢?此时简单地将目标平台设为AnyCPU即可,AnyCPU正是根据自身电脑架构获取的目标平台。

又如使用GitHub Action时,分析器项目经常会遇到如下错误(CS8034):

这显然是因为目标平台设置错误,但使用Visual Studio手动编译就没有问题,sln文件里的平台映射(platform map)也确实是AnyCPU啊?这是因为解决方案的平台映射不一定会被所有地方遵循,最稳妥的方案是在csproj文件里指定目标平台。故在分析器项目中加上如下一行(PlatformTarget)即可:

不过为了直接运行也不出错,建议平台映射里的AnyCPU也要保留

IDE兼容性问题

既然分析器是被编译平台调用,那分析器的Roslyn版本也要与编译平台一致

所有源生成器和代码分析器都会引用以下的库

而代码修复器则会使用

这两个库的版本都和Roslyn的版本相同(截至本文发布,是4.6.0),而Visual Studio的版本也是相关(VS2022的版本目前是VS 17.6.xxx)。所以如果使用了4.6.0的Roslyn,低于17.6.xxx版本的VS就无法使用了。例如VS2022的版本号是VS 17.xxx,VS2019的版本号是VS 16.xxx。如果编写的分析器需要有较为广泛的兼容性,可能需要降低版本,放弃新特性

分析器的调试方式

分析器在生成(运行)时,默认不会启动调试器,所以需要手动添加:

推荐重新生成时采用Debug模式,Release模式会优化代码,导致有些地方可能看不到需要的变量值

源生成器可以参见我之前写过的文章:源生成器(三):调试方法及传递引用,代码分析器也一样,同样可以用这种方法

但代码修复器就有些不同了,添加启动调试器代码并重新生成后,需要先重启VS,这样VS才会重新加载代码生成器(然而添加启动调试器重启后再修改代码修复器代码或者删除启动调试器,都不需要重启VS,只要重新生成一下即可,十分奇怪)

然后将鼠标放到代码分析器提供的警告上,他会出现修复错误的提示(此处两条相同的提示一条来自于VS本身,一条来自于Resharper,并不是BUG):

点击显示可能的修补程序后,这个框会一闪而过:

然后跳出选择调试器的对话框,注意此处与源生成器或代码分析器不同,此处没有该解决方案本身而是别的打开的解决方案(如果有的话)或者新的VS实例,任选一个即可。我们点开后就可以开心地进行调试了

目标框架问题

所有分析器项目的目标框架都必须是.NET Standard2.0。据说因为是VS正在由.NET Framework向.NET (Core)迁移,所以使用这个折衷的方式来兼容两方。如果有朝一日VS完全用.NET重写的话,我们就能用上完全版的分析器了

引用图片

[ちにく] ID = 76601561
[牛土] ID = 87164382

参考资料

[1] Sergio Pedri(https://github.com/Sergio0694)

[2] Poly#(https://github.com/Sergio0694/PolySharp)

[3] 感谢Huo Yaoyuan大佬的无私耐心解答x(https://github.com/huoyaoyuan)

[4] 学习时参考了walterlv大佬的博客(https://blog.walterlv.com)

分析器:常见问题杂记的评论 (共 条)

分享到微博请遵守国家法律