MCPcopy Create free account
hub / github.com/csskit/csskit / derive

Function derive

crates/csskit_derives/src/visitable.rs:176–297  ·  view source on GitHub ↗
(input: DeriveInput)

Source from the content-addressed store, hash-verified

174}
175
176pub fn derive(input: DeriveInput) -> Result<TokenStream> {
177 if matches!(input.data, Data::Union(_)) {
178 return Err(Error::new(input.ident.span(), "Cannot derive Visitable on a Union"));
179 }
180 if let Data::Struct(ref s) = input.data
181 && matches!(s.fields, Fields::Unit)
182 {
183 return Err(Error::new(input.ident.span(), "Cannot derive Visitable on this struct"));
184 }
185
186 let style: VisitStyle = VisitStyle::from(input.attrs.as_slice());
187 let is_queryable = style.visit_self();
188 let ident = &input.ident;
189 let (impl_generics, type_generics, _) = input.generics.split_for_impl();
190
191 let (visit_mut, exit_mut) = if style.visit_self() {
192 let visit_method = format_ident!("visit_{}", ident.to_string().to_snake_case());
193 let exit_method = format_ident!("exit_{}", ident.to_string().to_snake_case());
194 (quote! { v.#visit_method(self); }, quote! { v.#exit_method(self); })
195 } else {
196 (quote! {}, quote! {})
197 };
198
199 let (visit_feature, exit_feature) = if has_feature_metadata(&input.attrs) {
200 (quote! { v.visit_feature(self); }, quote! { v.exit_feature(self); })
201 } else {
202 (quote! {}, quote! {})
203 };
204
205 let mut s = Structure::try_new(&input)?;
206 s.add_bounds(AddBounds::None);
207
208 let mut wc = WhereCollector::new();
209
210 let (body_mut, body) = if style.visit_children() {
211 let accept_mut = format_ident!("accept_mut");
212 let accept = format_ident!("accept");
213 let b_mut = make_body(&s, &accept_mut, &mut wc, false);
214 let b = make_body(&s, &accept, &mut wc, true);
215 (b_mut, b)
216 } else {
217 (quote! {}, quote! { <visit_flow::VisitFlow as visit_flow::VisitFlowExt>::DESCEND })
218 };
219
220 let accept_body = if is_queryable {
221 let node_var = quote! { __node };
222 let children_block = if style.visit_self() {
223 let visit_method = format_ident!("visit_{}", ident.to_string().to_snake_case());
224 let exit_method = format_ident!("exit_{}", ident.to_string().to_snake_case());
225 quote! {
226 if let visit_flow::VisitAction::Descend = visit_flow::try_visit!(v.#visit_method(self)) {
227 visit_flow::try_visit!({ #body });
228 }
229 visit_flow::try_visit!(v.#exit_method(self));
230 }
231 } else {
232 quote! { visit_flow::try_visit!({ #body }); }
233 };

Callers

nothing calls this directly

Calls 8

ErrClass · 0.85
has_feature_metadataFunction · 0.85
make_bodyFunction · 0.85
has_queryable_skipFunction · 0.85
visit_selfMethod · 0.80
visit_childrenMethod · 0.80
extend_where_clauseMethod · 0.80
spanMethod · 0.45

Tested by

no test coverage detected