分析器:常見問題雜記

分析器簡介
本文分析器主要指以“Analyzer”模式引用的項目或NuGet包,例如源生成器(source generator)、代碼分析器(analyzer)、代碼修復(fù)器(codefixer)等
注:其中源生成器和代碼分析器的“血緣關(guān)系”更近,可能因為都是.NET使用的分析器,而代碼修復(fù)器是提供給Visual Studio使用的,所以關(guān)系疏遠一些
分析器引用別的項目時的問題
根據(jù)MSDN和Visual Studio自帶的代碼示例,所有分析器和源生成器都必須包含以下兩個庫:
所有代碼修復(fù)器都必須包含以下這個庫:
肯定不止我一個人(bushi)想到,為什么不把一些最簡單的類型、或者一些工具庫給所有的分析器共享呢?這樣引用時就不需要寫字符串而是nameof(xxx)了,多優(yōu)雅
可惜由于分析器項目的限制,除了以上說的必須包含的庫,其他庫都不能引用。但這也不是說每次寫分析器都要手動實現(xiàn).NET的新特性,Sergio Pedri[1]大佬實現(xiàn)了Poly#[2](PolySharp)庫,這個庫實現(xiàn)了絕大部分可以實現(xiàn)的特性,并且可以被分析器項目“引用”。因為它是把所有需要的代碼生成到你的項目里,而非直接引用,所以繞過了分析器不能引用項目的限制
引用這個庫的方法和其他庫一樣,在NuGet里下載并添加包引用即可
目標平臺問題
分析器項目與普通項目不同,分析器本身的dll不會被用戶項目直接引用,而是被編譯平臺(如.NET SDK或Visual Studio等)引用,從而對代碼進行分析。所以分析器本身的dll不會被包含進用戶項目生成的應(yīng)用里(源生成器生成的代碼會)
既然分析器的dll是被編譯平臺引用而非用戶項目,那源生成器的目標平臺就應(yīng)該與編譯平臺有關(guān),而非用戶項目。例如,在x64架構(gòu)的電腦上編譯x86的應(yīng)用程序,此時一般的用戶項目目標平臺都應(yīng)該設(shè)置為x86,但分析器項目的目標平臺卻應(yīng)該與電腦保持一致(x64),因為編譯項目時,是電腦上x64的.NET SDK調(diào)用了分析器項目
為了保證項目編譯的可移植性,如何判斷編譯電腦的架構(gòu)并設(shè)置為對應(yīng)平臺呢?此時簡單地將目標平臺設(shè)為AnyCPU即可,AnyCPU正是根據(jù)自身電腦架構(gòu)獲取的目標平臺。
又如使用GitHub Action時,分析器項目經(jīng)常會遇到如下錯誤(CS8034):
這顯然是因為目標平臺設(shè)置錯誤,但使用Visual Studio手動編譯就沒有問題,sln文件里的平臺映射(platform map)也確實是AnyCPU???這是因為解決方案的平臺映射不一定會被所有地方遵循,最穩(wěn)妥的方案是在csproj文件里指定目標平臺。故在分析器項目中加上如下一行(PlatformTarget)即可:
不過為了直接運行也不出錯,建議平臺映射里的AnyCPU也要保留
IDE兼容性問題
既然分析器是被編譯平臺調(diào)用,那分析器的Roslyn版本也要與編譯平臺一致
所有源生成器和代碼分析器都會引用以下的庫
而代碼修復(fù)器則會使用
這兩個庫的版本都和Roslyn的版本相同(截至本文發(fā)布,是4.6.0),而Visual Studio的版本也是相關(guān)(VS2022的版本目前是VS 17.6.xxx)。所以如果使用了4.6.0的Roslyn,低于17.6.xxx版本的VS就無法使用了。例如VS2022的版本號是VS?17.xxx,VS2019的版本號是VS?16.xxx。如果編寫的分析器需要有較為廣泛的兼容性,可能需要降低版本,放棄新特性
分析器的調(diào)試方式
分析器在生成(運行)時,默認不會啟動調(diào)試器,所以需要手動添加:
推薦重新生成時采用Debug模式,Release模式會優(yōu)化代碼,導(dǎo)致有些地方可能看不到需要的變量值
源生成器可以參見我之前寫過的文章:源生成器(三):調(diào)試方法及傳遞引用,代碼分析器也一樣,同樣可以用這種方法
但代碼修復(fù)器就有些不同了,添加啟動調(diào)試器代碼并重新生成后,需要先重啟VS,這樣VS才會重新加載代碼生成器(然而添加啟動調(diào)試器重啟后再修改代碼修復(fù)器代碼或者刪除啟動調(diào)試器,都不需要重啟VS,只要重新生成一下即可,十分奇怪)
然后將鼠標放到代碼分析器提供的警告上,他會出現(xiàn)修復(fù)錯誤的提示(此處兩條相同的提示一條來自于VS本身,一條來自于Resharper,并不是BUG):

點擊顯示可能的修補程序后,這個框會一閃而過:

然后跳出選擇調(diào)試器的對話框,注意此處與源生成器或代碼分析器不同,此處沒有該解決方案本身而是別的打開的解決方案(如果有的話)或者新的VS實例,任選一個即可。我們點開后就可以開心地進行調(diào)試了

目標框架問題
所有分析器項目的目標框架都必須是.NET?Standard2.0。據(jù)說因為是VS正在由.NET?Framework向.NET?(Core)遷移,所以使用這個折衷的方式來兼容兩方。如果有朝一日VS完全用.NET重寫的話,我們就能用上完全版的分析器了
引用圖片


參考資料
[1]?Sergio Pedri(https://github.com/Sergio0694)
[2] Poly#(https://github.com/Sergio0694/PolySharp)
[3] 感謝Huo Yaoyuan大佬的無私耐心解答x(https://github.com/huoyaoyuan)
[4] 學(xué)習(xí)時參考了walterlv大佬的博客(https://blog.walterlv.com)