use anyhow::Result;
use swc_common::{sync::Lrc, FileName, SourceFile, SourceMap};
use swc_ecma_ast::{EsVersion, Module};
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
fn syntax_for_file(filename: &str) -> Syntax {
if filename.ends_with(".tsx") || filename.ends_with(".mtsx") || filename.ends_with(".ctsx") {
Syntax::Typescript(swc_ecma_parser::TsSyntax {
tsx: true,
decorators: true, dts: false,
..Default::default()
})
} else if filename.ends_with(".ts") || filename.ends_with(".mts") || filename.ends_with(".cts")
{
let is_dts = filename.ends_with(".d.ts");
Syntax::Typescript(swc_ecma_parser::TsSyntax {
tsx: false,
decorators: true, dts: is_dts,
..Default::default()
})
} else if filename.ends_with(".jsx")
|| filename.ends_with(".mjsx")
|| filename.ends_with(".cjsx")
{
Syntax::Es(swc_ecma_parser::EsSyntax {
jsx: true,
decorators: false,
..Default::default()
})
} else {
Syntax::Es(swc_ecma_parser::EsSyntax {
jsx: true, decorators: false,
..Default::default()
})
}
}
pub fn parse_source(src: &str, source_map: &Lrc<SourceMap>, filename: &str) -> Result<Module> {
let syntax = syntax_for_file(filename);
let source_file: Lrc<SourceFile> =
source_map.new_source_file(FileName::Custom(filename.into()).into(), src.to_string());
let input = StringInput::from(&*source_file);
let lexer = Lexer::new(syntax, EsVersion::Es2022, input, None);
let mut parser = Parser::new_from(lexer);
parser.parse_module().map_err(|e| {
let error_msg = e.kind().msg();
anyhow::anyhow!("Parse error: {}", error_msg)
.context(format!("Failed to parse source file: {}", filename))
})
}
#[deprecated(since = "0.1.0", note = "Use parse_source instead")]
pub fn parse_typescript(src: &str, source_map: &Lrc<SourceMap>, filename: &str) -> Result<Module> {
parse_source(src, source_map, filename)
}
#[cfg(test)]
#[path = "parser/tests.rs"]
mod tests;