n1_cli/
compiler.rs

1use swc_common::FileName;
2use swc_common::{
3    comments::SingleThreadedComments,
4    errors::{ColorConfig, Handler},
5    sync::Lrc,
6    Globals, Mark, SourceMap, GLOBALS,
7};
8use swc_ecma_codegen::to_code_default;
9use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsSyntax};
10use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver};
11use swc_ecma_transforms_typescript::strip;
12
13pub fn compile_code(code: &str) -> Result<String, Box<dyn std::error::Error>> {
14    let cm: Lrc<SourceMap> = Default::default();
15    let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone()));
16
17    let fm = cm.new_source_file(FileName::Anon.into(), code.into());
18
19    let comments = SingleThreadedComments::default();
20
21    let lexer = Lexer::new(
22        Syntax::Typescript(TsSyntax {
23            tsx: false,
24            ..Default::default()
25        }),
26        swc_core::ecma::ast::EsVersion::Es2015,
27        StringInput::from(&*fm),
28        Some(&comments),
29    );
30
31    let mut parser = Parser::new_from(lexer);
32
33    for e in parser.take_errors() {
34        e.into_diagnostic(&handler).emit();
35    }
36
37    let module = parser
38        .parse_program()
39        .map_err(|e| e.into_diagnostic(&handler).emit())
40        .expect("failed to parse module.");
41
42    let globals = Globals::default();
43    GLOBALS.set(&globals, || {
44        let unresolved_mark = Mark::new();
45        let top_level_mark = Mark::new();
46
47        // Optionally transforms decorators here before the resolver pass
48        // as it might produce runtime declarations.
49
50        // Conduct identifier scope analysis
51        let module = module.apply(resolver(unresolved_mark, top_level_mark, true));
52
53        // Remove typescript types
54        let module = module.apply(strip(unresolved_mark, top_level_mark));
55
56        // Fix up any identifiers with the same name, but different contexts
57        let module = module.apply(hygiene());
58
59        // Ensure that we have enough parenthesis.
60        let program = module.apply(fixer(Some(&comments)));
61
62        Ok(to_code_default(cm, Some(&comments), &program))
63    })
64}