torn_api_codegen/model/
scope.rs1use 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
39 let mut functions = Vec::with_capacity(self.members.len());
40
41 for member in &self.members {
42 if let Some(code) = member.codegen_scope_call() {
43 functions.push(code);
44 }
45 }
46
47 Some(quote! {
48 pub struct #name<'e, E>(&'e E)
49 where
50 E: crate::executor::Executor;
51
52 impl<'e, E> #name<'e, E>
53 where
54 E: crate::executor::Executor
55 {
56 pub fn new(executor: &'e E) -> Self {
57 Self(executor)
58 }
59
60 #(#functions)*
61 }
62 })
63 }
64}