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

如何在Rust Proc Macro中获取保留空白符的原始源码?

获取Proc Macro输入的原始源码字符串

直接将TokenStream转为字符串会丢失空白符(换行、缩进等),因为TokenStream本质是抽象的token序列,不保留原始格式信息。要获取带原始格式的源码,得利用Rust提供的Span API来读取源码文本。

解决方案:利用Span获取原始源码

每个token都带有Span信息,标记了它在源码中的位置。我们可以合并输入所有token的span,得到覆盖整个宏输入范围的span,再通过source_text()方法读取对应位置的原始文本。

示例代码:

#[proc_macro]
pub fn my_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let tokens: Vec<_> = input.into_iter().collect();
    if tokens.is_empty() {
        return proc_macro::TokenStream::new();
    }

    // 获取第一个和最后一个token的span,合并得到整个输入的范围
    let full_span = tokens[0].span().join(tokens.last().unwrap().span()).unwrap();
    // 读取原始源码文本
    let source = full_span.source_text().unwrap();

    println!("{}", source);
    // 输出会保留原始换行:
    // "{
    // one
    // two
    // three
    // }"

    // 如果需要去掉外层大括号,可对字符串做处理
    let inner_source = source.trim()
        .trim_start_matches('{')
        .trim_end_matches('}')
        .trim();
    println!("{}", inner_source);
    // 输出:"one\ntwo\nthree"

    proc_macro::TokenStream::new()
}

注意事项

  1. 版本要求:Span::source_text()是Rust 1.59及以上的稳定API,确保你的编译环境满足版本要求。
  2. Span合并失败:span.join()可能返回None(比如输入的token来自不同文件),实际使用中建议添加错误处理逻辑,避免panic。
  3. 复杂DSL处理:如果你的DSL结构复杂,可结合syn库解析输入,通过解析后节点的span来获取源码,比手动处理token更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 16:05:48