kinetics_parser/
parser.rs1use std::path::PathBuf;
2
3use crate::{environment::Environment, Cron, Endpoint, Worker};
4use color_eyre::eyre;
5use syn::{parse::Parse, visit::Visit, Attribute, ItemFn};
6use walkdir::WalkDir;
7
8#[derive(Debug, Clone)]
10pub struct ParsedFunction {
11 pub rust_function_name: String,
13
14 pub relative_path: String,
16
17 pub role: Role,
19}
20
21impl ParsedFunction {
22 pub fn escape_path(path: &str) -> String {
24 return path
25 .replace("_", "Undrscr")
26 .replace("_", "Dash")
27 .split(&['.', '/'])
28 .filter(|s| !s.eq(&"rs"))
29 .map(|s| match s.chars().next() {
30 Some(first) => first.to_uppercase().collect::<String>() + &s[1..],
31 None => String::new(),
32 })
33 .collect::<String>()
34 .replacen("Src", "", 1);
35 }
36
37 pub fn func_name(&self, is_local: bool) -> String {
43 let rust_name = &self.rust_function_name;
44 let full_path = format!("{}/{rust_name}", self.relative_path);
45 let default_func_name = Self::escape_path(&full_path);
46
47 format!(
49 "{}{}",
50 self.role.name().unwrap_or(&default_func_name),
51 if is_local { "Local" } else { "" }
52 )
53 }
54}
55
56#[derive(Debug, Clone)]
57pub enum Role {
58 Endpoint(Endpoint),
59 Cron(Cron),
60 Worker(Worker),
61}
62
63impl Role {
64 pub fn name(&self) -> Option<&String> {
65 match self {
66 Role::Endpoint(params) => params.name.as_ref(),
67 Role::Cron(params) => params.name.as_ref(),
68 Role::Worker(params) => params.name.as_ref(),
69 }
70 }
71
72 pub fn environment(&self) -> &Environment {
73 match self {
74 Role::Endpoint(params) => ¶ms.environment,
75 Role::Cron(params) => ¶ms.environment,
76 Role::Worker(params) => ¶ms.environment,
77 }
78 }
79}
80
81#[derive(Debug, Default)]
82pub struct Parser {
83 pub functions: Vec<ParsedFunction>,
85
86 pub relative_path: String,
88}
89
90impl Parser {
91 pub fn new(path: Option<&PathBuf>) -> eyre::Result<Self> {
95 let mut parser: Parser = Default::default();
96
97 if path.is_some() {
98 parser.walk_dir(path.unwrap())?;
99 }
100
101 Ok(parser)
102 }
103
104 pub fn walk_dir(&mut self, path: &PathBuf) -> eyre::Result<()> {
105 for entry in WalkDir::new(path)
106 .into_iter()
107 .filter_map(|e| e.ok())
108 .filter(|e| e.path().extension().is_some_and(|ext| ext == "rs"))
109 {
110 let content = std::fs::read_to_string(entry.path())?;
111 let syntax = syn::parse_file(&content)?;
112
113 self.set_relative_path(entry.path().strip_prefix(path)?.to_str());
116
117 self.visit_file(&syntax);
118 }
119
120 Ok(())
121 }
122
123 pub fn set_relative_path(&mut self, file_path: Option<&str>) {
124 self.relative_path = file_path.map_or_else(|| "".to_string(), |s| s.to_string());
125 }
126
127 fn parse_endpoint(&mut self, attr: &Attribute) -> syn::Result<Endpoint> {
128 attr.parse_args_with(Endpoint::parse)
129 }
130
131 fn parse_worker(&mut self, attr: &Attribute) -> syn::Result<Worker> {
132 attr.parse_args_with(Worker::parse)
133 }
134
135 fn parse_cron(&mut self, attr: &Attribute) -> syn::Result<Cron> {
136 attr.parse_args_with(Cron::parse)
137 }
138
139 fn parse_attr_role(&self, input: &Attribute) -> String {
144 let path = input.path();
145
146 if path.segments.len() == 1 {
147 let ident = &path.segments[0].ident;
148 return ident.to_string();
149 }
150
151 if path.segments.len() == 2 && &path.segments[0].ident == "kinetics_macro" {
152 let ident = &path.segments[1].ident;
153 return ident.to_string();
154 }
155
156 "".to_string()
157 }
158}
159
160impl Visit<'_> for Parser {
161 fn visit_item_fn(&mut self, item: &ItemFn) {
163 for attr in &item.attrs {
164 let role = match self.parse_attr_role(attr).as_str() {
166 "endpoint" => {
167 let params = self.parse_endpoint(attr).unwrap();
168 Role::Endpoint(params)
169 }
170 "worker" => {
171 let params = self.parse_worker(attr).unwrap();
172 Role::Worker(params)
173 }
174 "cron" => {
175 let params = self.parse_cron(attr).unwrap();
176 Role::Cron(params)
177 }
178 _ => continue,
179 };
180
181 self.functions.push(ParsedFunction {
182 role,
183 rust_function_name: item.sig.ident.to_string(),
184 relative_path: self.relative_path.clone(),
185 });
186 }
187
188 }
190}