1mod javascript;
4mod rust;
5mod generic;
6mod javascript_complete;
8
9pub use javascript::JavaScriptParser as SimpleJavaScriptParser;
11pub use javascript_complete::{
13 ComponentInfo, ExportInfo, HookInfo, ImportInfo, ImportSpecifierInfo,
14 JavaScriptAst as CompleteJavaScriptAst, JavaScriptParser as CompleteJavaScriptParser,
15 ParseResults, is_component_name,
16};
17pub use rust::{RustParser, RustAst};
18pub use generic::GenericParser;
19
20use oparry_core::Result;
21use std::path::Path;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub enum Language {
26 JavaScript,
27 TypeScript,
28 Jsx,
29 Tsx,
30 Rust,
31 Unknown,
32}
33
34impl Language {
35 pub fn from_path(path: &Path) -> Self {
37 match path.extension().and_then(|e| e.to_str()) {
38 Some("js") | Some("mjs") | Some("cjs") => Language::JavaScript,
39 Some("jsx") => Language::Jsx,
40 Some("ts") => Language::TypeScript,
41 Some("tsx") => Language::Tsx,
42 Some("rs") => Language::Rust,
43 _ => Language::Unknown,
44 }
45 }
46
47 pub fn is_javascript_variant(&self) -> bool {
49 matches!(
50 self,
51 Language::JavaScript | Language::TypeScript | Language::Jsx | Language::Tsx
52 )
53 }
54
55 pub fn is_rust(&self) -> bool {
57 matches!(self, Language::Rust)
58 }
59}
60
61#[derive(Debug)]
63pub enum ParsedCode {
64 Rust(RustAst),
65 Generic(String),
66}
67
68impl ParsedCode {
69 pub fn source(&self) -> &str {
71 match self {
72 ParsedCode::Rust(ast) => ast.source(),
73 ParsedCode::Generic(s) => s,
74 }
75 }
76}
77
78pub trait Parser: Send + Sync {
80 fn parse(&self, source: &str) -> Result<ParsedCode>;
82}
83
84pub fn parser_for_language(language: Language) -> Box<dyn Parser> {
86 match language {
87 Language::JavaScript | Language::TypeScript | Language::Jsx | Language::Tsx => {
88 Box::new(SimpleJavaScriptParser::new())
89 }
90 Language::Rust => Box::new(RustParser::new()),
91 Language::Unknown => Box::new(GenericParser),
92 }
93}
94
95pub fn parser_for_path(path: &Path) -> Box<dyn Parser> {
97 parser_for_language(Language::from_path(path))
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_language_detection() {
106 assert_eq!(Language::from_path(Path::new("test.js")), Language::JavaScript);
107 assert_eq!(Language::from_path(Path::new("test.ts")), Language::TypeScript);
108 assert_eq!(Language::from_path(Path::new("test.tsx")), Language::Tsx);
109 assert_eq!(Language::from_path(Path::new("test.rs")), Language::Rust);
110 assert_eq!(Language::from_path(Path::new("test.unknown")), Language::Unknown);
111 }
112}