V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
youxingzhi
V2EX  ›  Rust

求助!关于使用 oxc 来解析并修改 JS 代码时遇到的生命周期相关的问题

  •  
  •   youxingzhi · 36 天前 · 778 次点击
    这是一个创建于 36 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我正在使用 oxc 来解析并修改 JS 代码。

    const b = require('b.js')
    

    如上所示,我想给模块名(b.js)加上一个前缀,这个前缀是动态的。

    下面是我的代码,代码仓库见这里。现在的问题是 new_name 会在函数执行完后销毁,但是 Atom::from 声明了一个生命周期('a),所以编译器报错:new_name does not live long enough.

    怎么解决这个问题呀?跪求大佬指点。

    #![allow(clippy::print_stdout)]
    use itertools::Itertools;
    use oxc_allocator::Allocator;
    use oxc_ast::ast::*;
    use oxc_codegen::{CodeGenerator, CodegenOptions};
    use oxc_parser::Parser;
    use oxc_semantic::SemanticBuilder;
    use oxc_span::SourceType;
    use oxc_traverse::{traverse_mut, Traverse, TraverseCtx};
    use std::ops::DerefMut;
    use std::{env, path::Path, sync::Arc};
    
    struct MyTransform {
        prefix: String,
    }
    
    impl<'a> Traverse<'a> for MyTransform {
        fn enter_call_expression(&mut self, node: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) {
            if node.is_require_call() {
                let argument: &mut Argument<'a> = &mut node.arguments.deref_mut()[0];
                match argument {
                    Argument::StringLiteral(string_literal) => {
                        let old_name = string_literal.value.as_str();
                        let new_name = format!("{}{}", self.prefix, old_name);
    
                        // !!!!!! `new_name` does not live long enough
                        string_literal.value = Atom::from(new_name.as_str());
                    }
                    _ => {}
                }
            }
        }
    }
    
    fn main() -> std::io::Result<()> {
        let name = env::args().nth(1).unwrap_or_else(|| "test.js".to_string());
        let path = Path::new(&name);
        let source_text = Arc::new(std::fs::read_to_string(path)?);
        let source_type = SourceType::from_path(path).unwrap();
    
        // Memory arena where Semantic and Parser allocate objects
        let allocator = Allocator::default();
    
        // 1 Parse the source text into an AST
        let parser_ret = Parser::new(&allocator, &source_text, source_type).parse();
        if !parser_ret.errors.is_empty() {
            let error_message: String = parser_ret
                .errors
                .into_iter()
                .map(|error| format!("{:?}", error.with_source_code(Arc::clone(&source_text))))
                .join("\n");
            println!("Parsing failed:\n\n{error_message}",);
            return Ok(());
        }
    
        let mut program = parser_ret.program;
    
        // 2 Semantic Analyze
        let semantic = SemanticBuilder::new(&source_text)
            .build_module_record(path, &program)
            // Enable additional syntax checks not performed by the parser
            .with_check_syntax_error(true)
            .build(&program);
    
        if !semantic.errors.is_empty() {
            let error_message: String = semantic
                .errors
                .into_iter()
                .map(|error| format!("{:?}", error.with_source_code(Arc::clone(&source_text))))
                .join("\n");
            println!("Semantic analysis failed:\n\n{error_message}",);
        }
        let (symbols, scopes) = semantic.semantic.into_symbol_table_and_scope_tree();
    
        // 3 Transform
        let t = &mut MyTransform {
            prefix: "ayou".to_string(),
        };
        traverse_mut(t, &allocator, &mut program, symbols, scopes);
    
        // 4 Generate Code
        let new_code = CodeGenerator::new()
            .with_options(CodegenOptions {
                ..CodegenOptions::default()
            })
            .build(&program)
            .code;
    
        println!("{}", new_code);
    
        Ok(())
    }
    
    2 条回复    2024-10-25 14:11:32 +08:00
    PTLin
        1
    PTLin  
       36 天前
    把出问题的代码改成 string_literal.value = Atom::from_in(new_name, &ctx.ast.allocator);
    youxingzhi
        2
    youxingzhi  
    OP
       36 天前
    嗯,谢谢。这样也可以:string_literal.value = ctx.ast.atom(new_name.as_str());
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2230 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 01:35 · PVG 09:35 · LAX 17:35 · JFK 20:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.