kinetics_parser/
parser.rs1use crate::{environment::Environment, Cron, Endpoint, Worker};
2use syn::{parse::Parse, visit::Visit, Attribute, ItemFn};
3
4#[derive(Debug, Clone)]
6pub struct ParsedFunction {
7 pub rust_function_name: String,
9
10 pub relative_path: String,
12
13 pub role: Role,
15}
16
17impl ParsedFunction {
18 pub fn func_name(&self, is_local: bool) -> String {
24 let rust_name = &self.rust_function_name;
25 let full_path = format!("{}/{rust_name}", self.relative_path);
26
27 let default_func_name = full_path
28 .as_str()
29 .replace("_", "Undrscr")
30 .replace("_", "Dash")
31 .split(&['.', '/'])
32 .filter(|s| !s.eq(&"rs"))
33 .map(|s| match s.chars().next() {
34 Some(first) => first.to_uppercase().collect::<String>() + &s[1..],
35 None => String::new(),
36 })
37 .collect::<String>()
38 .replacen("Src", "", 1);
39
40 format!(
42 "{}{}",
43 self.role.name().unwrap_or(&default_func_name),
44 if is_local { "Local" } else { "" }
45 )
46 }
47}
48
49#[derive(Debug, Clone)]
50pub enum Role {
51 Endpoint(Endpoint),
52 Cron(Cron),
53 Worker(Worker),
54}
55
56impl Role {
57 pub fn name(&self) -> Option<&String> {
58 match self {
59 Role::Endpoint(params) => params.name.as_ref(),
60 Role::Cron(params) => params.name.as_ref(),
61 Role::Worker(params) => params.name.as_ref(),
62 }
63 }
64
65 pub fn environment(&self) -> &Environment {
66 match self {
67 Role::Endpoint(params) => ¶ms.environment,
68 Role::Cron(params) => ¶ms.environment,
69 Role::Worker(params) => ¶ms.environment,
70 }
71 }
72}
73
74#[derive(Debug, Default)]
75pub struct Parser {
76 pub functions: Vec<ParsedFunction>,
78
79 pub relative_path: String,
81}
82
83impl Parser {
84 pub fn new() -> Self {
85 Default::default()
86 }
87
88 pub fn set_relative_path(&mut self, file_path: Option<&str>) {
89 self.relative_path = file_path.map_or_else(|| "".to_string(), |s| s.to_string());
90 }
91
92 fn parse_endpoint(&mut self, attr: &Attribute) -> syn::Result<Endpoint> {
93 attr.parse_args_with(Endpoint::parse)
94 }
95
96 fn parse_worker(&mut self, attr: &Attribute) -> syn::Result<Worker> {
97 attr.parse_args_with(Worker::parse)
98 }
99
100 fn parse_cron(&mut self, attr: &Attribute) -> syn::Result<Cron> {
101 attr.parse_args_with(Cron::parse)
102 }
103
104 fn parse_attr_role(&self, input: &Attribute) -> String {
109 let path = input.path();
110
111 if path.segments.len() == 1 {
112 let ident = &path.segments[0].ident;
113 return ident.to_string();
114 }
115
116 if path.segments.len() == 2 && &path.segments[0].ident == "kinetics_macro" {
117 let ident = &path.segments[1].ident;
118 return ident.to_string();
119 }
120
121 "".to_string()
122 }
123}
124
125impl Visit<'_> for Parser {
126 fn visit_item_fn(&mut self, item: &ItemFn) {
128 for attr in &item.attrs {
129 let role = match self.parse_attr_role(attr).as_str() {
131 "endpoint" => {
132 let params = self.parse_endpoint(attr).unwrap();
133 Role::Endpoint(params)
134 }
135 "worker" => {
136 let params = self.parse_worker(attr).unwrap();
137 Role::Worker(params)
138 }
139 "cron" => {
140 let params = self.parse_cron(attr).unwrap();
141 Role::Cron(params)
142 }
143 _ => continue,
144 };
145
146 self.functions.push(ParsedFunction {
147 role,
148 rust_function_name: item.sig.ident.to_string(),
149 relative_path: self.relative_path.clone(),
150 });
151 }
152
153 }
155}