上次在 Unity 開發者大會聽到的內容之一-靜態程式碼分析, 能幫助開發人員快速的code reviewer, 避免人工檢查疏失, 甚至整合進CI流程中, 是個值得嘗試看看的東西.
靜態程式碼分析, 就是在不運行程式的情況下, 進行語法/語句/語意的分析(compiler做的事), 檢查是否有特定的程式碼不合規範, 提前發現並修正, 像是 Visual Studio “Squiggles" 分析 C++, “Resharper" 也有分析 C# 的功能.
為什麼要用靜態程式碼分析, 有幾個好處:
- 縮短開發時間
- 提早發現程式碼的 Bug
- 避免人工檢查的遺漏
- 加入到自動化 (CI) 流程
程式碼更新前, 通常會經過幾個人 Code Review 確認程式碼的品質, 但數量多時難免會有遺漏. 利用靜態程式碼分析可以避免遺漏也能節省一些檢查時間.
Unity 開發者大會介紹了 UnityEngineAnalyzer, 是一個基於 Roslyn 向外擴展的靜態分析器. Roslyn 是 .NET Compiler, 支援 C#, Visual Basic 語言編譯, 以及提供完整的程式碼分析 API. 個人認為強大的地方在於可擴展, 又是 Git 開源專案, 可根據 API 自定義專屬的分析器.
PS. Roslyn 目前只支援 VS2015 以上的版本.
UnityEngineAnalyzer 是一個 Roslyn 的擴充應用, 可以對 Unity 程式碼進行靜態分析, 提供獨立運行與作為 VS 插件運行, 也有 HTML report 和 Json report. meng-hui GitHub 上有介紹現階段提供的 C# 程式碼診斷, 以及安裝方法. 目前的檢查包括:
- DoNotUseOnGUI
- DoNotUseStringMethods
- EmptyMonoBehaviourMethod
- UseCompareTag
- DoNotUseFindMethodsInUpdate
- DoNotUseCoroutines
- DoNotUseForEachInUpdate
- other AOT …
PS. 部分檢查項目隨 Unity 版本更新後有修正掉, 例如 foreach 造成額外 GC 的問題在 Unity 5.5.1 之後的版本已經修正了.
檢查測試的程式碼如下:
// AOT0001: System.Runtime.Remoting is not suppported
using System.Runtime.Remoting;
// AOT0002: System.Reflection.Emit is not supported
using System.Reflection.Emit;
using UnityEngine;
class FooBehaviour : MonoBehaviour
{
void Start()
{
// AOT0003: Reflection only works for looking up existing types
Type.GetType("");
// UEA0002: Using string methods can lead to code that is hard to maintain
SendMessage("");
// UEA0006: Use of coroutines cause some allocations
StartCoroutine("");
}
// UEA0001: Using OnGUI causes allocations and GC spikes
void OnGUI()
{
}
// UEA0003: Empty MonoBehaviour methods are executed and incur a small overhead
void FixedUpdate()
{
}
void OnTriggerEnter(Collider other)
{
// UEA0004: Using CompareTag for tag comparison does not cause allocations
if (other.tag == "")
{
}
}
void Update()
{
// UEA0005: Warning to cache the result of find in Start or Awake
GameObject.Find("");
}
}
PS. 程式碼取自 meng-hui GitHub 範例.
安裝 UnityEngineAnalyzer 有幾種方式:
(一)下載 Source code 在本地端 build, 以 commandline 執行
Source code GitHub
下載解壓縮後, 直接用 VS 開啟 (記得要是 VS2015以後的版本). build 之前還要安裝 Roslyn 插件, 畢竟 UnityEngineAnalyzer 是基於 Roslyn API 延伸的套件, 不然沒辦法 compile/build. 接著按照官方指示:
- 打開命令提示字元視窗
- 執行 UnityEngineAnalyzer.CLI.exe (在專案目錄下的 bin\ or bin\debug\)
- 查看診斷結果
- (Optional) 在專案目錄下會產生 report.json 和 UnityReport.html 分析結果文檔
Example:
> UnityEngineAnalyzer.CLI.exe D:\TestCode\TestGame.CSharp.csproj
(二)VS2015 整合, NuGet 安裝 package
- Tools > Nuget Package Manager > Manage Nuget Packages for Solution
工具 > NuGet 封裝管理員 > 管理方案的NuGet套件… - 搜尋 UnityEngineAnalyzer
- 安裝選 game logic 的專案 (不要選到 editor 的)
VS 環境下可以在 Error List 看到診斷結果
(二)VS2015 整合, 直接安裝 VSIX 插件
目前沒看到官方提供 VSIX 安裝檔, 只能自己來. Source code GitHub 下載的可以 build 出 VSIX 安裝檔. build 出來直接安裝即可, 完成後到Tools > Extensions and Updates(工具 > 擴充功能和更新)會看到:
另外, UnityEngineAnalyzer 也能客製化增加新的檢查項目. 這部分還沒研究清楚, 以後有需求需要加一些檢查項目的話, 會在分享出來的 😀