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

基于SWC Rust插件注入代码注释的实现与测试问题

在SWC中为AST添加注释并优化测试代码的方案

问题背景

之前在Babel里可以直接用addComment操作AST节点添加注释,比如把:

console.log`Hello, ${name}!`;

转换成:

/*#__PURE__*/console.log("Hello, ", name, "!");

但切换到Rust的SWC后,受内存所有权规则和性能优化限制,必须用PluginCommentsProxy来添加注释。用swc_core::ecma::transforms::testing做测试时,发现tester.comments的类型是Rc<SingleThreadedComments>,导致测试跑不通。虽然可以用泛型<C>适配,但不想为了测试加泛型降低代码可读性,想找更优的解决办法。

优化方案:不依赖泛型的测试写法

你可以手动处理注释实例,不用给测试函数加泛型。核心是创建SingleThreadedComments实例并包装成Rc,替换测试上下文的注释对象,同时保证注释能正确关联AST节点。

具体实现代码

use swc_core::ecma::transforms::testing::{test, FixtureTestConfig};
use swc_core::ecma::comments::{SingleThreadedComments, Comments};
use swc_core::common::Rc;
use swc_core::ecma::ast::Program;
use swc_core::ecma::visit::FoldWith;

// 你的注释注入转换逻辑
fn add_pure_comment_transform(program: Program, comments: Rc<SingleThreadedComments>) -> Program {
    // 创建PluginCommentsProxy用于操作注释
    let proxy = swc_core::plugin::proxy::PluginCommentsProxy::new(comments.clone());
    // 这里编写你的AST遍历逻辑,给目标节点添加注释
    // 示例:找到所有CallExpr节点,添加/*#__PURE__*/注释
    program.fold_with(&mut your_custom_transformer(proxy))
}

#[test]
fn test_add_pure_comment() {
    // 创建注释实例并包装为Rc
    let comments = Rc::new(SingleThreadedComments::default());
    
    test(
        FixtureTestConfig::default(),
        |mut context| {
            // 替换测试上下文的comments为我们创建的实例
            context.comments = comments.clone();
            Box::new(|program| add_pure_comment_transform(program, comments.clone()))
        },
        // 替换为你的测试用例路径或内联测试逻辑
        "tests/fixtures/add-pure-comment",
    );
}

关键注意点

  • 手动创建SingleThreadedComments并通过Rc包装,直接替换测试上下文的comments字段,完全不需要泛型参数。
  • 转换函数直接接收Rc<SingleThreadedComments>,用来创建PluginCommentsProxy,避免泛型带来的代码复杂度。
  • 借助Rc的克隆特性,确保注释实例在测试上下文和转换逻辑中共享,符合SWC的内存管理规则。

进一步简化:封装测试辅助函数

如果有多个测试用例,可以把注释实例的创建和上下文替换逻辑封装成辅助函数,让测试代码更简洁:

fn create_test_with_comments<F>(transformer: F) -> impl Fn(FixtureTestConfig) -> Box<dyn Fn(Program) -> Program>
where
    F: Fn(Program, Rc<SingleThreadedComments>) -> Program + 'static,
{
    move |mut config| {
        let comments = Rc::new(SingleThreadedComments::default());
        config.comments = comments.clone();
        Box::new(move |program| transformer(program, comments.clone()))
    }
}

// 使用辅助函数编写测试
#[test]
fn test_add_pure_comment_simplified() {
    test(
        FixtureTestConfig::default(),
        create_test_with_comments(|program, comments| {
            add_pure_comment_transform(program, comments)
        }),
        "tests/fixtures/add-pure-comment",
    );
}

这样既避开了泛型,又能保持测试代码的清爽可读。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:34:56