如何使增量源代码生成器在Visual Studio中运行?

iih3973s  于 2023-01-05  发布在  其他
关注(0)|答案(1)|浏览(270)

我已经按照documentation创建了一个基本的增量源代码生成器,它输出用属性标记的类的副本:

// Code found in my project
[Copy]
public class MyClass 
{ 
    public int Value { get; set; }
}

// Output from the source generator
public class Copy_MyClass 
{ 
    public int Value { get; set; }
}

源代码生成本身运行得非常好,但在Visual Studio 2022中使用它时遇到了两个问题:

  • 源代码生成器仅在生成期间执行。
  • 在重新启动Visual Studio之前,智能感知不会拾取生成的代码。
  • 我可以通过将生成的源文件写入项目目录来解决这个问题,但这并不理想,仍然存在上述问题:在我尝试构建之前,更改不会反映出来。

例如,如果我创建一个具有[Copy]属性的新类Foo,然后尝试在代码中引用Copy_Foo,Visual Studio将显示Copy_Foo未定义的错误。

[Copy]
public class Foo { }

public static class TestCopy
{
    public static void Test()
    {
        Copy_Foo foo = new Copy_Foo();
//      ^^^^^^^^ 
//      The type or namespace 'Copy_Foo' could not be found
    }
}

生成此代码将成功,但Visual Studio将继续认为Copy_Foo不存在。重新启动后,它将知道Copy_Foo存在,但在我再次重新启动之前,不会拾取对其所做的任何更改。
我创建了一个小示例,它只输出[Copy]属性。
第一个项目包含源代码生成器:
一个二个一个一个
第二个消耗生成器:

// TestSourceGenerator.Test.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

    <ItemGroup>
        <ProjectReference Include="..\TestSourceGenerator\TestSourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
    </ItemGroup>

</Project>
// MyClass.cs
namespace TestSourceGenerator.Test
{
    [Generated.CopyAttribute]
    public class MyClass
    {
    }
}

如果创建TestSourceGenerator.test项目而不使用ProjectReference,则在Visual Studio中打开它,然后编辑项目文件以引用分析器,您将看到Visual Studio在[Generated.CopyAttribute]上显示错误,但项目生成成功。
有没有办法让Visual Studio既在IDE中运行我的源代码生成器,又从生成的代码中拾取符号?根据文档,这似乎应该是一个受支持的用例,甚至是增量源代码生成器存在的主要动机之一。

htrmnn0y

htrmnn0y1#

通常有两个原因让你挣扎,如果不很好地理解,这两个原因都会让你沮丧。
一个问题是Visual Studio不允许分析器程序集在加载后卸载。一旦Visual Studio加载了您的分析器以便在IDE和Intellisense中使用,它将一直使用该版本,直到您关闭Visual Studio,或者至少直到您提高程序集版本。但是,当您点击项目的生成/重新生成时,Visual Studio将生成一个新的msbuild进程,该进程将(通常)加载一个新版本的分析器。因此,您可能最终得到一个构建良好但没有更新IDE和Intellisense的项目。这实际上是一个老问题,并且与生成器没有直接关系,请参见https://github.com/dotnet/roslyn/issues/48083以获取更多信息。(一个建议是,不要通过Visual Studio而是在单元测试的帮助下开发分析器。)
另一个缓存问题是关于IIncrementalGenerator的增量构建,但我不确定这是否与您发布的代码相关。无论如何,如果您操作正确,这个新版本的源代码生成器将缓存最后一次执行,并在相关内容未发生更改的情况下为IDE/Intellisense* 重用输出 *。这通常要求您为源语法节点的内容实现自定义等式比较器。但是,如果此比较未能考虑相关内容(即,最后一次按键时实际更改的内容),则不会执行生成器,也不会更新IDE/Intellisense。同样,msbuild可能仍能正常运行,因为每个新生成都会忽略任何以前的输出缓存,并且仅从一开始就为分析器提供每个源节点。

相关问题