1use anyhow::Result;
8use swc_common::{sync::Lrc, FileName, SourceFile, SourceMap};
9use swc_ecma_ast::{EsVersion, Module};
10use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
11
12fn syntax_for_file(filename: &str) -> Syntax {
14 if filename.ends_with(".tsx") || filename.ends_with(".mtsx") || filename.ends_with(".ctsx") {
16 Syntax::Typescript(swc_ecma_parser::TsSyntax {
18 tsx: true,
19 decorators: true, dts: false,
21 ..Default::default()
22 })
23 } else if filename.ends_with(".ts") || filename.ends_with(".mts") || filename.ends_with(".cts")
24 {
25 let is_dts = filename.ends_with(".d.ts");
27 Syntax::Typescript(swc_ecma_parser::TsSyntax {
28 tsx: false,
29 decorators: true, dts: is_dts,
31 ..Default::default()
32 })
33 } else if filename.ends_with(".jsx")
34 || filename.ends_with(".mjsx")
35 || filename.ends_with(".cjsx")
36 {
37 Syntax::Es(swc_ecma_parser::EsSyntax {
39 jsx: true,
40 decorators: false,
41 ..Default::default()
42 })
43 } else {
44 Syntax::Es(swc_ecma_parser::EsSyntax {
46 jsx: true, decorators: false,
48 ..Default::default()
49 })
50 }
51}
52
53pub fn parse_source(src: &str, source_map: &Lrc<SourceMap>, filename: &str) -> Result<Module> {
65 let syntax = syntax_for_file(filename);
67
68 let source_file: Lrc<SourceFile> =
70 source_map.new_source_file(FileName::Custom(filename.into()).into(), src.to_string());
71
72 let input = StringInput::from(&*source_file);
74
75 let lexer = Lexer::new(syntax, EsVersion::Es2022, input, None);
77
78 let mut parser = Parser::new_from(lexer);
80
81 parser.parse_module().map_err(|e| {
83 let error_msg = e.kind().msg();
84 anyhow::anyhow!("Parse error: {}", error_msg)
85 .context(format!("Failed to parse source file: {}", filename))
86 })
87}
88
89#[deprecated(since = "0.1.0", note = "Use parse_source instead")]
93pub fn parse_typescript(src: &str, source_map: &Lrc<SourceMap>, filename: &str) -> Result<Module> {
94 parse_source(src, source_map, filename)
95}
96
97#[cfg(test)]
98#[path = "parser/tests.rs"]
99mod tests;