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
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}