测试Source Generator时context.SyntaxReceiver始终为null的解决方法
解决Source Generator中
context.SyntaxReceiver为null的问题 你遇到的问题根源很明确:默认情况下,ISourceGenerator不会自动创建SyntaxReceiver,必须你自己在Initialize方法中主动注册一个实现了ISyntaxReceiver接口的接收器实例,否则context.SyntaxReceiver就会是null。
下面是具体的修复步骤和完整代码示例:
1. 定义自定义的ISyntaxReceiver实现类
这个类负责在语法分析阶段收集你需要的代码节点(比如类、方法、属性等),你可以根据实际需求编写筛选逻辑:
public class CustomSyntaxReceiver : ISyntaxReceiver { // 示例:收集所有类声明节点,可根据需求修改 public List<ClassDeclarationSyntax> ClassDeclarations { get; } = new(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { // 筛选出我们关心的语法节点 if (syntaxNode is ClassDeclarationSyntax classDecl) { ClassDeclarations.Add(classDecl); } } }
2. 在Generator的Initialize方法中注册Receiver
修改你的CustomGenerator,在Initialize方法里通过RegisterForSyntaxNotifications注册自定义接收器:
[Generator] public class CustomGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { // 注册自定义的SyntaxReceiver,这一步是关键! context.RegisterForSyntaxNotifications(() => new CustomSyntaxReceiver()); } public void Execute(GeneratorExecutionContext context) { // 现在可以安全地获取并转换SyntaxReceiver if (context.SyntaxReceiver is CustomSyntaxReceiver receiver) { // 在这里处理收集到的语法节点,比如生成代码 foreach (var classDecl in receiver.ClassDeclarations) { // 你的代码生成逻辑... } } } }
3. 测试代码的注意事项
你的现有测试代码不需要额外修改,但要注意在Execute方法中必须将context.SyntaxReceiver转换成你自定义的实现类,才能访问其中收集到的具体数据——因为context.SyntaxReceiver是接口类型,直接调用无法获取你定义的属性或方法。
补充说明
ISyntaxReceiver是Source Generator的语法分析前置入口,它会在编译器遍历代码语法树的过程中被触发,帮你提前筛选、收集需要处理的节点,避免在Execute阶段重新遍历整个语法树,能有效提升生成效率。如果不主动注册,自然不会有接收器实例,context.SyntaxReceiver就会保持null状态。
内容的提问来源于stack exchange,提问作者Oleg
相关产品推荐
相关产品推荐

