Reputation: 33
use swc_common::sync::Lrc;
use swc_common::{FileName, SourceMap};
use swc_ecma_parser::{Parser, StringInput, Syntax};
fn main() {
let cm: Lrc<SourceMap> = Default::default();
// Real usage
// let fm = cm
// .load_file(Path::new("test.js"))
// .expect("failed to load test.js");
let fm = cm.new_source_file(
FileName::Custom("test.js".into()),
"
// test
function foo() {}
"
.into(),
);
let ts_config = swc_ecma_parser::TsConfig {
decorators: true,
// dynamic_import: true,
tsx: true,
..Default::default()
};
let mut parser = Parser::new(
Syntax::Typescript(ts_config),
StringInput::from(&*fm),
Default::default(),
);
let module = parser
.parse_typescript_module()
.expect("failed to parser module");
module.body.into_iter().for_each(|module_item| {
println!("{:?}", module_item);
});
}
I am trying to parse script file and do some modification to the AST, and then generate new code based on modifed AST. But when I do a simple test, swc_ecma_parser doesn't provide comment node. See below output of println:
Stmt(Decl(Fn(FnDecl { ident: Ident { span: Span { lo: BytePos(35), hi: BytePos(38), ctxt: #0 }, sym: "foo", optional: false }, declare: false, function: Function { params: [], decorators: [], span: Span { lo: BytePos(26), hi: BytePos(43), ctxt: #0 }, body: Some(BlockStmt { span: Span { lo: BytePos(41), hi: BytePos(43), ctxt: #0 }, stmts: [] }), is_generator: false, is_async: false, type_params: None, return_type: None } })))
It only has the function declarion node, the comment // test
is stripped.
How can I get the comment, and change the comment // test
to // modified comment
. Thanks
Upvotes: 1
Views: 199
Reputation: 7963
The comments are indeed not part of the AST, but the parser handles them separately. The third argument of Parser::new
is comments: Option<&'a dyn Comments>
. In your code you provide Default::default()
here, which is simply None
for an Option
, suppressing any comment parsing. You can instead create one of the implementations of the Comments
trait, such as SingleThreadedComments
:
let comments: swc_common::comments::SingleThreadedComments = Default::default();
let mut parser = Parser::new(
Syntax::Typescript(ts_config),
StringInput::from(&*fm),
Some(&comments),
);
After invoking the parser, comments
should be updated (the API uses a shared reference for reasons). You should be able to mutably iterate through the comments using borrow_all_mut
.
Finally, it seems like swc::Compiler::print
is the method you will want to use to convert the AST back into code. Again, this method accepts comments: Option<&dyn Comments>
as its last argument.
Upvotes: 2