1.Rosyln介绍

Roslyn是微软推出的开源.NET编译器平台,仓库地址:https://github.com/dotnet/Roslyn,其核心特点在于将传统“黑盒”式的编译器转变为开放的API服务。使得开发者能够参与编译过程,甚至修改编译结果,为开发者提供深度的代码分析、动态编译及代码生成能力。

2.在unity中的应用

在unity中的样例可以参考unity的官方文档:https://docs.unity3d.com/Manual/roslyn-analyzers.html。需要注意的是想要在unity editor中使用代码生成和代码分析的话,在2020.2版本之后才生效。

2.1 如何只在IDE中使用代码分析

值得一提的是虽然unity editor中的代码编译的报错警告等信息通常和ide中的一样,但是这这两者实际上是独立进行的代码分析,例如vscode是依赖csproj来进行分析的,这也是有时候需要手动在unity editor的preference中手动点击重新生成csproj的原因,所以理论上可以让两者的代码分析结果不一样。

通过unity的官方case我们知道,把生成的Analyzer的dll手动添加RoslynAnalyzer的tag,就可以让代码分析同时在unity editor和ide中生效。在ide中生效的原因是unity每次重新生成对应csproj的时候都会把有RoslynAnalyzer tag的对应项生成到csproj中,例如我们添加了一个名为UnityRoslyn的dll,csproj中就会有如下的项:

  <ItemGroup>
    <Analyzer Include="xxxAssets\Plugins\UnityRoslyn.dll" />
  </ItemGroup>

这样ide在进行代码分析的时候就会使用这个dll来进行代码分析。

那么对于比较老版本的unity不支持RoslynAnalyzer的tag,或者只想在ide中进行代码分析,避免editor编译时间变长应该如何配置呢。

首先csproj是由unity生成的,我们手动向里面添加对应的itemgroup是不行的,因为下次生成又会被自动生成的覆盖。解决方案是借助unity的asset后处理接口,在生成csproj的时候手动把这些itemgroup给添加上去:

public class ProjectFilePostprocessor : AssetPostprocessor
{
    public static string OnGeneratedSlnSolution(string path, string content)
    {
        Debug.Log("OnGeneratedSlnSolution: " + path);
        return content;
    }

    public static string OnGeneratedCSProject(string path, string content)
    {
        Debug.Log("OnGeneratedCSProject: "+path);

        int index = content.LastIndexOf("</ItemGroup>");
        if (index != -1)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(string.Format("    <Analyzer Include=\"{0}/GameMain/Plugins/ErrorProne.NET.Core.dll\" />\n", Application.dataPath));
            sb.Append(string.Format("    <Analyzer Include=\"{0}/GameMain/Plugins/ErrorProne.Net.CoreAnalyzers.dll\" />\n", Application.dataPath));
            sb.Append(string.Format("    <Analyzer Include=\"{0}/GameMain/Plugins/RuntimeContracts.dll\" />\n", Application.dataPath));
            content = content.Insert(index, sb.ToString());
        }
        return content;
    }
}

在unity重新生成sln和csproj的时候会调用到OnGeneratedSlnSolution和OnGeneratedCSProject方法,因此我们在对应的方法中添加对应的Analyzer项即可。

3.踩坑记录

我们可以通过ruleset来指定rule的严重等级,但是在vscode中手动修改rule的Action之后不会立即生效,需要reload一下或者重启vscode才会生效。