swc_ast_explorer/
main.rs

1use std::{io::stdin, sync::Arc};
2
3use anyhow::Result;
4use clap::Parser;
5use owo_colors::OwoColorize;
6use regex::{NoExpand, Regex};
7use swc_core::{
8    base::{Compiler, HandlerOpts, config::IsModule, try_with_handler},
9    common::{GLOBALS, Globals, SourceMap, errors::ColorConfig, source_map::FileName},
10    ecma::{
11        ast::EsVersion,
12        parser::{Syntax, TsSyntax},
13    },
14};
15
16#[derive(Parser, Debug)]
17#[clap(author, version, about, long_about = None)]
18struct Args {
19    /// Whether to keep Span (location) markers
20    #[clap(long, value_parser, default_value_t = false)]
21    spans: bool,
22}
23
24fn main() -> Result<()> {
25    let args = Args::parse();
26
27    let mut contents = String::new();
28    stdin().read_line(&mut contents)?;
29
30    let sm = Arc::new(SourceMap::default());
31    let file = sm.new_source_file(FileName::Anon.into(), contents);
32    let target = EsVersion::latest();
33    let syntax = Syntax::Typescript(TsSyntax {
34        tsx: true,
35        decorators: false,
36        dts: false,
37        no_early_errors: true,
38        disallow_ambiguous_jsx_like: false,
39    });
40
41    let compiler = Compiler::new(sm.clone());
42    let res = GLOBALS
43        .set(&Globals::new(), || {
44            try_with_handler(
45                sm,
46                HandlerOpts {
47                    color: ColorConfig::Always,
48                    skip_filename: false,
49                },
50                |handler| compiler.parse_js(file, handler, target, syntax, IsModule::Unknown, None),
51            )
52        })
53        .map_err(|e| e.to_pretty_error());
54
55    let print = format!("{:#?}", res?);
56
57    let stripped = if args.spans {
58        print
59    } else {
60        let span = Regex::new(r"(?m)^\s+\w+: Span \{[^}]*\},\n").unwrap();
61        span.replace_all(&print, NoExpand("")).to_string()
62    };
63
64    let alernate_ws = Regex::new(r" {8}").unwrap();
65    let alternating = alernate_ws.replace_all(
66        &stripped,
67        NoExpand(&format!(
68            "{}{}",
69            "    ".on_default_color(),
70            "    ".on_black()
71        )),
72    );
73    let ws = Regex::new(r" {4}").unwrap();
74    println!("{}", ws.replace_all(&alternating, NoExpand("  ")));
75
76    Ok(())
77}