2021-05-28 08:04:00 +03:00
|
|
|
use std::path::{Path, PathBuf};
|
2022-02-09 09:33:32 +03:00
|
|
|
|
2021-08-13 13:03:04 +03:00
|
|
|
use swc_common::{chain, sync::Lrc, Mark, SourceMap, SyntaxContext};
|
2021-05-28 08:04:00 +03:00
|
|
|
use swc_ecma_ast::*;
|
|
|
|
use swc_ecma_codegen::Emitter;
|
2022-03-19 08:32:53 +03:00
|
|
|
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax, TsConfig};
|
2022-04-26 10:38:50 +03:00
|
|
|
use swc_ecma_transforms_base::{fixer::fixer, resolver};
|
2022-01-19 17:11:52 +03:00
|
|
|
use swc_ecma_visit::{
|
|
|
|
as_folder, visit_mut_obj_and_computed, Fold, FoldWith, VisitMut, VisitMutWith,
|
|
|
|
};
|
2021-08-13 13:03:04 +03:00
|
|
|
use testing::{fixture, run_test2, NormalizedOutput};
|
2021-05-28 08:04:00 +03:00
|
|
|
|
|
|
|
pub fn print(cm: Lrc<SourceMap>, module: &Module) -> String {
|
|
|
|
let mut buf = vec![];
|
|
|
|
{
|
|
|
|
let mut emitter = Emitter {
|
|
|
|
cfg: Default::default(),
|
|
|
|
cm: cm.clone(),
|
|
|
|
wr: Box::new(swc_ecma_codegen::text_writer::JsWriter::new(
|
2022-01-13 17:06:11 +03:00
|
|
|
cm, "\n", &mut buf, None,
|
2021-05-28 08:04:00 +03:00
|
|
|
)),
|
|
|
|
comments: None,
|
|
|
|
};
|
|
|
|
|
|
|
|
// println!("Emitting: {:?}", module);
|
2022-01-13 17:06:11 +03:00
|
|
|
emitter.emit_module(module).unwrap();
|
2021-05-28 08:04:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
let s = String::from_utf8_lossy(&buf);
|
|
|
|
s.to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run<F, P>(syntax: Syntax, input: &Path, op: F)
|
|
|
|
where
|
|
|
|
F: FnOnce() -> P,
|
|
|
|
P: Fold,
|
|
|
|
{
|
|
|
|
let dir = input.parent().unwrap();
|
|
|
|
let output = dir.join(format!(
|
|
|
|
"output.{}",
|
|
|
|
input.extension().unwrap().to_string_lossy(),
|
|
|
|
));
|
|
|
|
|
2021-10-16 09:12:53 +03:00
|
|
|
run_test2(false, |cm, handler| {
|
2021-05-28 08:04:00 +03:00
|
|
|
let fm = cm.load_file(input).unwrap();
|
|
|
|
|
|
|
|
let lexer = Lexer::new(syntax, EsVersion::latest(), StringInput::from(&*fm), None);
|
|
|
|
let mut parser = Parser::new_from(lexer);
|
|
|
|
|
2021-10-16 09:12:53 +03:00
|
|
|
let module = parser
|
|
|
|
.parse_module()
|
|
|
|
.map_err(|err| err.into_diagnostic(&handler).emit())?;
|
2021-05-28 08:04:00 +03:00
|
|
|
|
|
|
|
let mut folder = op();
|
|
|
|
|
|
|
|
let module = module.fold_with(&mut folder);
|
|
|
|
|
2022-01-13 17:06:11 +03:00
|
|
|
let actual = print(cm, &module);
|
2021-05-28 08:04:00 +03:00
|
|
|
let actual = NormalizedOutput::from(actual);
|
|
|
|
|
|
|
|
actual.compare_to_file(&output).unwrap();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
2021-07-29 08:18:21 +03:00
|
|
|
#[fixture("tests/resolver/**/input.js")]
|
2021-05-28 08:04:00 +03:00
|
|
|
fn test_resolver(input: PathBuf) {
|
2021-10-16 09:12:53 +03:00
|
|
|
run(
|
|
|
|
Syntax::Es(EsConfig {
|
|
|
|
jsx: true,
|
|
|
|
..Default::default()
|
|
|
|
}),
|
|
|
|
&input,
|
|
|
|
|| {
|
2022-04-26 10:38:50 +03:00
|
|
|
let unresolved_mark = Mark::fresh(Mark::root());
|
2021-10-16 09:12:53 +03:00
|
|
|
|
|
|
|
chain!(
|
2022-04-26 10:38:50 +03:00
|
|
|
resolver(unresolved_mark, Mark::new(), false),
|
|
|
|
as_folder(TsHygiene { unresolved_mark }),
|
2021-10-16 09:12:53 +03:00
|
|
|
fixer(None)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
);
|
2021-05-28 08:04:00 +03:00
|
|
|
}
|
|
|
|
|
2021-07-29 08:18:21 +03:00
|
|
|
#[fixture("tests/ts-resolver/**/input.ts")]
|
2021-05-28 08:04:00 +03:00
|
|
|
fn test_ts_resolver(input: PathBuf) {
|
2022-03-19 08:32:53 +03:00
|
|
|
run(
|
|
|
|
Syntax::Typescript(TsConfig {
|
|
|
|
decorators: true,
|
|
|
|
..Default::default()
|
|
|
|
}),
|
|
|
|
&input,
|
|
|
|
|| {
|
2022-04-26 10:38:50 +03:00
|
|
|
let unresolved_mark = Mark::fresh(Mark::root());
|
2022-03-19 08:32:53 +03:00
|
|
|
|
|
|
|
chain!(
|
2022-04-26 10:38:50 +03:00
|
|
|
resolver(unresolved_mark, Mark::new(), true),
|
|
|
|
as_folder(TsHygiene { unresolved_mark }),
|
2022-03-19 08:32:53 +03:00
|
|
|
fixer(None)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
);
|
2021-05-28 08:04:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
struct TsHygiene {
|
2022-04-26 10:38:50 +03:00
|
|
|
unresolved_mark: Mark,
|
2021-05-28 08:04:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl VisitMut for TsHygiene {
|
2022-02-09 09:33:32 +03:00
|
|
|
visit_mut_obj_and_computed!();
|
|
|
|
|
2021-05-28 08:04:00 +03:00
|
|
|
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
2022-04-26 10:38:50 +03:00
|
|
|
if SyntaxContext::empty().apply_mark(self.unresolved_mark) == i.span.ctxt {
|
|
|
|
println!("ts_hygiene: {} is unresolved", i.sym);
|
2021-05-28 08:04:00 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-02-08 13:50:22 +03:00
|
|
|
let ctxt = format!("{:?}", i.span.ctxt).replace('#', "");
|
2021-05-28 08:04:00 +03:00
|
|
|
i.sym = format!("{}__{}", i.sym, ctxt).into();
|
|
|
|
i.span = i.span.with_ctxt(SyntaxContext::empty());
|
|
|
|
}
|
|
|
|
|
2022-01-15 09:36:40 +03:00
|
|
|
fn visit_mut_prop_name(&mut self, n: &mut PropName) {
|
|
|
|
if let PropName::Computed(n) = n {
|
|
|
|
n.visit_mut_with(self);
|
2021-05-28 08:04:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_mut_ts_qualified_name(&mut self, q: &mut TsQualifiedName) {
|
|
|
|
q.left.visit_mut_with(self);
|
|
|
|
}
|
|
|
|
}
|