【发布时间】:2021-12-17 23:17:28
【问题描述】:
我目前正在使用 netstandard2.0 库中的 Roslyn 构建 C# 源代码生成器。在.csproj 中,我引用了以下 Roslyn 包:
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
</ItemGroup>
源代码生成器使用 Roslyn 的 SyntaxFactory 创建附加代码。然后它使用context.Compilation.AddSyntaxTrees() 将生成的代码添加到编译中(context 是传递给生成器的Execute 方法的GeneratorExecutionContext)。
问题是我在调用AddSyntaxTrees() 时遇到以下异常:
System.ArgumentException: 语言版本不一致。参数名称:syntaxTrees
我了解异常的原因。 SyntaxFactory 创建的语法树将其语言版本设置为 CSharp10。但是编译上下文的语言版本设置为CSharp8。
有没有办法告诉SyntaxFactory 它应该生成的语言版本?
我知道我也可以使用 Microsoft.CodeAnalysis.Analyzers 的 3.7 版(根据 this table)。但这是否也不会阻止我使用最新的 Roslyn 功能(但不确定那可能是什么)。此外,我如何确定使用源生成器的目标库将永远只使用相同的语言版本编译?或者我是否需要针对不同语言版本的源生成器的不同版本?另外 - 这在不同的 IDE 中可能会有所不同吗?
【问题讨论】:
-
我有点担心“然后它使用 context.Compilation.AddSyntaxTrees() 将生成的代码添加到编译中(上下文是传递给生成器的 Execute 方法的 GeneratorExecutionContext)。”因为那里存在一些可能存在问题的性能影响。您创建的树是否取决于原始编译的内容?您是否需要进行第一次不可能的二次绑定?
-
@Jason:感谢您关注其他问题。我需要编译的语义模型来生成代码。而且我刚刚意识到调用
AddSyntaxTrees并没有真正将代码添加到编译结果中。但是,使用从compilationUnit.ToFullString()检索到的代码切换到context.AddSource是可行的。这是它应该怎么做还是有更聪明的方法?这感觉像是一个不必要的复杂化(将语法树格式化为字符串,以便编译器可以重新解析它)。 -
是的,我们要求您直接给我们文本而不是树;原因有些模糊:可能会生成不代表实际可解析代码的语法树;例如,您可以以不带括号的方式嵌套二进制表达式,这违反了解析器实际应用运算符优先级的方式。 (你可以想出这些问题没有尽头。)我们没有试图弄清楚编译器应该如何处理所有这些疯狂的情况,而是决定输入是文本,所以我们总是将其重新解析为更标准的形式。