torn_api_codegen/model/
scope.rs

1use heck::ToUpperCamelCase;
2use indexmap::IndexMap;
3use proc_macro2::TokenStream;
4use quote::{format_ident, quote};
5
6use super::path::{Path, PathSegment};
7
8pub struct Scope {
9    pub name: String,
10    pub mod_name: String,
11    pub members: Vec<Path>,
12}
13
14impl Scope {
15    pub fn from_paths(paths: Vec<Path>) -> Vec<Scope> {
16        let mut map = IndexMap::new();
17
18        for path in paths {
19            let Some(PathSegment::Constant(first_seg)) = path.segments.first() else {
20                continue;
21            };
22
23            map.entry(first_seg.to_owned())
24                .or_insert_with(|| Scope {
25                    name: format!("{}Scope", first_seg.to_upper_camel_case()),
26                    mod_name: first_seg.clone(),
27                    members: Vec::new(),
28                })
29                .members
30                .push(path);
31        }
32
33        map.into_values().collect()
34    }
35
36    pub fn codegen(&self) -> Option<TokenStream> {
37        let name = format_ident!("{}", self.name);
38        let bulk_name = format_ident!("Bulk{}", self.name);
39
40        let mut functions = Vec::with_capacity(self.members.len());
41        let mut bulk_functions = Vec::with_capacity(self.members.len());
42
43        for member in &self.members {
44            if let Some(code) = member.codegen_scope_call() {
45                functions.push(code);
46            }
47            if let Some(code) = member.codegen_bulk_scope_call() {
48                bulk_functions.push(code);
49            }
50        }
51
52        Some(quote! {
53            #[allow(dead_code)]
54            pub struct #name<E>(E)
55            where
56                E: crate::executor::Executor;
57
58            impl<E> #name<E>
59            where
60                E: crate::executor::Executor
61            {
62                pub fn new(executor: E) -> Self {
63                    Self(executor)
64                }
65
66                #(#functions)*
67            }
68
69            #[allow(dead_code)]
70            pub struct #bulk_name<E> where
71                E: crate::executor::BulkExecutor,
72            {
73                executor: E,
74            }
75
76            impl<E> #bulk_name<E>
77            where
78                E: crate::executor::BulkExecutor
79            {
80                pub fn new(executor: E) -> Self {
81                    Self {
82                        executor,
83                    }
84                }
85
86                #(#bulk_functions)*
87            }
88        })
89    }
90}