You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

增量C# Source Generator预处理器符号列表为空的问题求助

问题

我正在编写一款可用于.NET(net9.0)和Unity(6.0)项目的增量C# Source Generator,期望根据预处理器符号(如UNITY、UNITY_WEBGL)区分运行环境,分别生成Task(.NET环境)或Awaitable(Unity环境)。我编写了如下代码尝试获取预处理器符号:

public void Initialize(IncrementalGeneratorInitializationContext context)
{   
    // Add the marker attribute to the compilation
    context.RegisterPostInitializationOutput(ctx =>
    {
        ...
    });

    // Extract defined preprocessor symbols
    var compileForUnityCheck = context.CompilationProvider.Select((compilation, _) =>
    {
        if (compilation is CSharpCompilation cSharpCompilation)
        {
            var parseOptions = cSharpCompilation.SyntaxTrees.FirstOrDefault()?.Options as CSharpParseOptions;

            if (parseOptions != null)
            {
                var preprocessorSymbols = parseOptions.PreprocessorSymbolNames;
                return preprocessorSymbols.Any(s => s is "UNITY_WEBGL" or "UNITY");
            }
        }
        return false;
    });
        
    var thingsToGenerate = context.SyntaxProvider
            .ForAttributeWithMetadataName(
                ...
        
    var combinedProvider = thingsToGenerate.Combine(compileForUnityCheck);
        
    // Generate source code for each interface found
    context.RegisterSourceOutput(combinedProvider,
            static (spc, combined) => Execute(combined, spc));
}

但断点显示获取到的预处理器符号列表为空,生成器的其余逻辑运行正常。请问如何正确获取这些预处理器符号?(开发环境:Rider,MacOS)

解决方案

直接通过单棵语法树的解析选项获取预处理器符号不可靠,因为大部分全局定义的符号会存在于编译的全局配置中,而非单棵语法树里。正确的做法是同时读取全局编译选项和语法树本地的符号:

var compileForUnityCheck = context.CompilationProvider.Select((compilation, _) =>
{
    if (compilation is CSharpCompilation cSharpCompilation)
    {
        // 获取全局编译配置中的预处理器符号
        var globalSymbols = cSharpCompilation.Options.PreprocessorSymbols;
        // 收集所有语法树中定义的本地预处理器符号
        var localSymbols = cSharpCompilation.SyntaxTrees
            .Select(tree => tree.Options as CSharpParseOptions)
            .Where(options => options != null)
            .SelectMany(options => options.PreprocessorSymbolNames);
        
        // 合并两类符号,检查是否存在目标Unity符号
        return globalSymbols.Concat(localSymbols)
                           .Any(s => s is "UNITY_WEBGL" or "UNITY");
    }
    return false;
});

另外调试时需注意:

  • 确认测试项目已正确配置预处理器符号:Unity项目需在Player Settings中启用UNITY等符号,.NET项目在项目属性的"生成"选项卡中添加符号。
  • Rider调试Source Generator时,确保编译上下文加载了完整的项目配置,避免增量编译的部分上下文导致符号丢失。

内容的提问来源于stack exchange,提问作者Stephen Starkie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:22:41