kittycad_modeling_cmds_macros_impl/
modeling_cmd_enum.rs1use proc_macro2::TokenStream;
2use quote::quote_spanned;
3use syn::{spanned::Spanned, ItemMod};
4
5pub fn generate(input: ItemMod) -> TokenStream {
6 let span = input.span();
7
8 let items = input.content.as_ref().unwrap().1.iter();
11 let (variants, docs): (Vec<_>, Vec<_>) = items
12 .filter_map(|item| {
13 let syn::Item::Struct(item) = item else {
15 return None;
16 };
17 let syn::Visibility::Public(_) = item.vis else {
18 return None;
19 };
20
21 let doc = item
23 .attrs
24 .iter()
25 .filter_map(|attr| match &attr.meta {
26 syn::Meta::NameValue(syn::MetaNameValue { path, value, .. }) => {
27 if !path.is_ident("doc") {
30 return None;
31 }
32 let syn::Expr::Lit(syn::ExprLit {
34 lit: syn::Lit::Str(value),
35 ..
36 }) = value
37 else {
38 return None;
39 };
40 let doc = value.value().trim().to_owned();
41 Some(doc)
42 }
43 _ => None,
44 })
45 .collect::<Vec<_>>()
46 .join("\n");
47 Some((&item.ident, doc))
48 })
49 .unzip();
50
51 quote_spanned! {span=>
53 #input
56 #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58 #[cfg_attr(feature = "derive-jsonschema-on-enums", derive(schemars::JsonSchema))]
59 #[serde(rename_all = "snake_case", tag = "type")]
60 #[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))]
61 #[cfg_attr(feature = "ts-rs", ts(export_to = "ModelingCmd.ts"))]
62 #[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
63 pub enum ModelingCmd {#(
64 #[doc = #docs]
65 #variants(kittycad_modeling_cmds::each_cmd::#variants),
66 )*}
67 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone, ::parse_display::Display)]
69 #[serde(rename_all = "snake_case")]
70 #[cfg_attr(not(feature = "unstable_exhaustive"), non_exhaustive)]
71 pub enum ModelingCmdEndpoint{#(
72 #[doc = #docs]
73 #variants,
74 )*}
75 impl From<ModelingCmd> for ModelingCmdEndpoint {
78 fn from(v: ModelingCmd) -> Self {
79 match v {#(
80 ModelingCmd::#variants(_) => Self::#variants,
81 )*}
82 }
83 }
84 }
85}