C# 源代码生成器:如何调试生成代码中的编译器错误?
C# source generators: How to debug compiler errors in the generated code?
我正在试验 C# source generators。我花了大约一天的时间,我发现这是一次非常令人沮丧和痛苦的经历。 IntelliSense 极其不可靠。它偶尔会工作,但大多数情况下不会,而且我还没有弄清楚它的任何系统。 (重新启动 Visual Studio 没有帮助。)
但更根本的是,我在调试生成的代码中的错误时遇到了很大的麻烦。当我在源代码生成器中的模板中出错并尝试编译时,我可能会在生成的文件中出现类似“方法必须具有 return 类型”的错误。但是当我双击错误时,它并没有带我到生成的代码。这使得很难看出它有什么问题。
有什么技巧吗?编译失败时有没有办法检查生成的代码?更一般地说,生成的代码何时可用于 IntelliSense 以及何时不可使用?
我正在使用 Visual Studio Professional 2022 版本 17.1.6 和 ReSharper 2022.1。
提前致谢!
我找到了解决问题的部分方法。
首先,在使用源代码生成器时,不要在 Visual Studio 中使用 ReSharper 构建器。它不会给出正确的错误消息。相反,从命令行 运行 dotnet build
。这样你会得到更好的错误信息。
事实上,我的部分问题可能是由于 ReSharper 中的错误或限制引起的(虽然我没有对此进行调查,所以这纯属猜测)。
其次,您可以测试源代码生成器的内部结构,而无需 运行编译时生成源代码。
- 重构您的源代码生成器并提取一个助手 class(我们可以称之为 SourceGeneratorHelper.cs)来获取您的输入(例如 XML ) 并产生输出(例如 StringBuilder).
- 制作一个单独的 C# 测试项目 SourceGeneratorHelperTest.csproj 用于测试 class SourceGeneratorHelper.cs。在此项目中,将您的源代码生成器项目作为常规项目来引用 - 即,不要在您的项目引用中使用
OutputItemType="Analyzer"
。
- 现在您可以对源代码生成器的内部进行单元测试。您还可以将生成的 C# 代码转储到文件并检查它。
此外,正如 NightOwl888 指出的那样,我可以将其添加到引用项目中,以便将生成的文件吐出到磁盘(
as explained in this article):
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
我还没有解决智能感知问题,但现在我至少可以忍受这个生成器了。
我正在试验 C# source generators。我花了大约一天的时间,我发现这是一次非常令人沮丧和痛苦的经历。 IntelliSense 极其不可靠。它偶尔会工作,但大多数情况下不会,而且我还没有弄清楚它的任何系统。 (重新启动 Visual Studio 没有帮助。)
但更根本的是,我在调试生成的代码中的错误时遇到了很大的麻烦。当我在源代码生成器中的模板中出错并尝试编译时,我可能会在生成的文件中出现类似“方法必须具有 return 类型”的错误。但是当我双击错误时,它并没有带我到生成的代码。这使得很难看出它有什么问题。
有什么技巧吗?编译失败时有没有办法检查生成的代码?更一般地说,生成的代码何时可用于 IntelliSense 以及何时不可使用?
我正在使用 Visual Studio Professional 2022 版本 17.1.6 和 ReSharper 2022.1。
提前致谢!
我找到了解决问题的部分方法。
首先,在使用源代码生成器时,不要在 Visual Studio 中使用 ReSharper 构建器。它不会给出正确的错误消息。相反,从命令行 运行 dotnet build
。这样你会得到更好的错误信息。
事实上,我的部分问题可能是由于 ReSharper 中的错误或限制引起的(虽然我没有对此进行调查,所以这纯属猜测)。
其次,您可以测试源代码生成器的内部结构,而无需 运行编译时生成源代码。
- 重构您的源代码生成器并提取一个助手 class(我们可以称之为 SourceGeneratorHelper.cs)来获取您的输入(例如 XML ) 并产生输出(例如 StringBuilder).
- 制作一个单独的 C# 测试项目 SourceGeneratorHelperTest.csproj 用于测试 class SourceGeneratorHelper.cs。在此项目中,将您的源代码生成器项目作为常规项目来引用 - 即,不要在您的项目引用中使用
OutputItemType="Analyzer"
。 - 现在您可以对源代码生成器的内部进行单元测试。您还可以将生成的 C# 代码转储到文件并检查它。
此外,正如 NightOwl888 指出的那样,我可以将其添加到引用项目中,以便将生成的文件吐出到磁盘( as explained in this article):
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
我还没有解决智能感知问题,但现在我至少可以忍受这个生成器了。