mirror of
https://github.com/swc-project/swc.git
synced 2024-11-27 04:47:03 +03:00
feat(es/codegen): Add to_code
(#8968)
**Description:** This is a utility function for printing an AST node as a string
This commit is contained in:
parent
ea14fc8e59
commit
e80fd41ea8
@ -13,7 +13,7 @@ use swc_atoms::Atom;
|
|||||||
use swc_common::{
|
use swc_common::{
|
||||||
comments::{CommentKind, Comments},
|
comments::{CommentKind, Comments},
|
||||||
sync::Lrc,
|
sync::Lrc,
|
||||||
BytePos, SourceMapper, Span, Spanned, DUMMY_SP,
|
BytePos, SourceMap, SourceMapper, Span, Spanned, DUMMY_SP,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_codegen_macros::emitter;
|
use swc_ecma_codegen_macros::emitter;
|
||||||
@ -38,6 +38,36 @@ pub mod util;
|
|||||||
|
|
||||||
pub type Result = io::Result<()>;
|
pub type Result = io::Result<()>;
|
||||||
|
|
||||||
|
/// Generate a code from a syntax node using default options.
|
||||||
|
pub fn to_code_default(
|
||||||
|
cm: Lrc<SourceMap>,
|
||||||
|
comments: Option<&dyn Comments>,
|
||||||
|
node: impl Node,
|
||||||
|
) -> String {
|
||||||
|
let mut buf = vec![];
|
||||||
|
{
|
||||||
|
let mut emitter = Emitter {
|
||||||
|
cfg: Default::default(),
|
||||||
|
cm: cm.clone(),
|
||||||
|
comments,
|
||||||
|
wr: text_writer::JsWriter::new(cm, "\n", &mut buf, None),
|
||||||
|
};
|
||||||
|
node.emit_with(&mut emitter).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
String::from_utf8(buf).expect("codegen generated non-utf8 output")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a code from a syntax node using default options.
|
||||||
|
pub fn to_code_with_comments(comments: Option<&dyn Comments>, node: impl Node) -> String {
|
||||||
|
to_code_default(Default::default(), comments, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a code from a syntax node using default options.
|
||||||
|
pub fn to_code(node: impl Node) -> String {
|
||||||
|
to_code_with_comments(None, node)
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Node: Spanned {
|
pub trait Node: Spanned {
|
||||||
fn emit_with<W, S>(&self, e: &mut Emitter<'_, W, S>) -> Result
|
fn emit_with<W, S>(&self, e: &mut Emitter<'_, W, S>) -> Result
|
||||||
where
|
where
|
||||||
|
@ -28,7 +28,7 @@ use swc_common::{
|
|||||||
FileName, Mark, SourceMap, DUMMY_SP,
|
FileName, Mark, SourceMap, DUMMY_SP,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_codegen::Emitter;
|
use swc_ecma_codegen::{to_code_default, Emitter};
|
||||||
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
|
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
|
||||||
use swc_ecma_testing::{exec_node_js, JsExecOptions};
|
use swc_ecma_testing::{exec_node_js, JsExecOptions};
|
||||||
use swc_ecma_transforms_base::{
|
use swc_ecma_transforms_base::{
|
||||||
@ -188,26 +188,7 @@ impl<'a> Tester<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(&mut self, module: &Module, comments: &Rc<SingleThreadedComments>) -> String {
|
pub fn print(&mut self, module: &Module, comments: &Rc<SingleThreadedComments>) -> String {
|
||||||
let mut buf = vec![];
|
to_code_default(self.cm.clone(), Some(comments), module)
|
||||||
{
|
|
||||||
let mut emitter = Emitter {
|
|
||||||
cfg: Default::default(),
|
|
||||||
cm: self.cm.clone(),
|
|
||||||
wr: Box::new(swc_ecma_codegen::text_writer::JsWriter::new(
|
|
||||||
self.cm.clone(),
|
|
||||||
"\n",
|
|
||||||
&mut buf,
|
|
||||||
None,
|
|
||||||
)),
|
|
||||||
comments: Some(comments),
|
|
||||||
};
|
|
||||||
|
|
||||||
// println!("Emitting: {:?}", module);
|
|
||||||
emitter.emit_module(module).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = String::from_utf8_lossy(&buf);
|
|
||||||
s.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use swc_common::{
|
|||||||
sync::Lrc,
|
sync::Lrc,
|
||||||
Globals, Mark, SourceMap, GLOBALS,
|
Globals, Mark, SourceMap, GLOBALS,
|
||||||
};
|
};
|
||||||
use swc_ecma_codegen::{text_writer::JsWriter, Emitter};
|
use swc_ecma_codegen::to_code_default;
|
||||||
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
|
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
|
||||||
use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver};
|
use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver};
|
||||||
use swc_ecma_transforms_typescript::strip;
|
use swc_ecma_transforms_typescript::strip;
|
||||||
@ -76,18 +76,6 @@ fn main() {
|
|||||||
// Ensure that we have enough parenthesis.
|
// Ensure that we have enough parenthesis.
|
||||||
let program = module.fold_with(&mut fixer(Some(&comments)));
|
let program = module.fold_with(&mut fixer(Some(&comments)));
|
||||||
|
|
||||||
let mut buf = vec![];
|
println!("{}", to_code_default(cm, Some(&comments), program));
|
||||||
{
|
|
||||||
let mut emitter = Emitter {
|
|
||||||
cfg: swc_ecma_codegen::Config::default(),
|
|
||||||
cm: cm.clone(),
|
|
||||||
comments: Some(&comments),
|
|
||||||
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
|
|
||||||
};
|
|
||||||
|
|
||||||
emitter.emit_program(&program).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{}", String::from_utf8(buf).expect("non-utf8?"));
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
use std::{
|
use std::path::PathBuf;
|
||||||
io::{self, Write},
|
|
||||||
path::PathBuf,
|
|
||||||
sync::{Arc, RwLock},
|
|
||||||
};
|
|
||||||
|
|
||||||
use swc_common::{FileName, Mark};
|
use swc_common::{FileName, Mark};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_codegen::Emitter;
|
use swc_ecma_codegen::to_code_default;
|
||||||
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, Syntax, TsConfig};
|
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, Syntax, TsConfig};
|
||||||
use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver};
|
use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver};
|
||||||
use swc_ecma_transforms_typescript::typescript;
|
use swc_ecma_transforms_typescript::typescript;
|
||||||
@ -98,21 +94,7 @@ fn identity(entry: PathBuf) {
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
|
let js_content = {
|
||||||
|
|
||||||
{
|
|
||||||
let mut emitter = Emitter {
|
|
||||||
cfg: swc_ecma_codegen::Config::default(),
|
|
||||||
cm: cm.clone(),
|
|
||||||
wr: Box::new(swc_ecma_codegen::text_writer::JsWriter::new(
|
|
||||||
cm.clone(),
|
|
||||||
"\n",
|
|
||||||
&mut wr,
|
|
||||||
None,
|
|
||||||
)),
|
|
||||||
comments: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse source
|
// Parse source
|
||||||
let program = parser
|
let program = parser
|
||||||
.parse_typescript_module()
|
.parse_typescript_module()
|
||||||
@ -142,10 +124,8 @@ fn identity(entry: PathBuf) {
|
|||||||
Err(_) => return Ok(()),
|
Err(_) => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
emitter.emit_program(&program).unwrap();
|
to_code_default(cm.clone(), None, program)
|
||||||
}
|
};
|
||||||
|
|
||||||
let js_content = String::from_utf8_lossy(&wr.0.read().unwrap()).to_string();
|
|
||||||
|
|
||||||
println!("---------------- JS ----------------\n\n{}", js_content);
|
println!("---------------- JS ----------------\n\n{}", js_content);
|
||||||
|
|
||||||
@ -182,15 +162,3 @@ fn identity(entry: PathBuf) {
|
|||||||
})
|
})
|
||||||
.expect("failed to run test");
|
.expect("failed to run test");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Buf(Arc<RwLock<Vec<u8>>>);
|
|
||||||
impl Write for Buf {
|
|
||||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
|
||||||
self.0.write().unwrap().write(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
self.0.write().unwrap().flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user