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

Function derive

crates/csskit_derives/src/peek.rs:48–185  ·  view source on GitHub ↗
(input: DeriveInput)

Source from the content-addressed store, hash-verified

46}
47
48pub fn derive(input: DeriveInput) -> Result<TokenStream> {
49 let mut where_collector = WhereCollector::new();
50 let ident = input.ident;
51 let generics = &input.generics;
52 let generic_with_a = ensure_lifetime_a(generics);
53 let (impl_generics, _, _) = generic_with_a.split_for_impl();
54 let (_, type_generics, _) = generics.split_for_impl();
55 let mut kinds = vec![];
56 let body = match input.data {
57 Data::Union(_) => return Err(Error::new(ident.span(), "Cannot derive Peek on a Union")),
58
59 Data::Struct(DataStruct { ref fields, .. }) => {
60 let parse_mode = extract_field_parse_mode(&input.attrs)?;
61 let mut checks: Vec<TokenStream> = vec![];
62 for (view, syn_field) in fields.views().into_iter().zip(fields.iter()) {
63 let atom = extract_atom(&syn_field.attrs)?;
64 let atoms = atom.map(|a| vec![a]).unwrap_or_default();
65 let peek_ty = option_inner(view.ty).unwrap_or(view.ty);
66 if let Some(kind) = map_type_to_kind(peek_ty) {
67 let ident = Ident::new(kind, Span::call_site());
68 kinds.push(quote! { ::css_lexer::Kind::#ident });
69 } else {
70 checks.push(generate_type_peek(peek_ty, &atoms, &mut where_collector));
71 }
72 if !parse_mode.any_field_can_start() && !view.is_option {
73 break;
74 }
75 }
76 quote! { #(#checks)||* }
77 }
78
79 Data::Enum(DataEnum { variants, .. }) => {
80 let mut seen: Vec<String> = vec![];
81 let mut by_type: HashMap<String, Option<Vec<Atom>>> = HashMap::new();
82
83 let mut register = |peek_ty: &Type, atom: Option<Atom>| {
84 let key = peek_ty.to_token_stream().to_string();
85 if atom.is_none()
86 && let Some(kind) = map_type_to_kind(peek_ty)
87 {
88 if !seen.contains(&kind.to_string()) {
89 seen.push(kind.to_string());
90 let ident = Ident::new(kind, Span::call_site());
91 kinds.push(quote! { ::css_lexer::Kind::#ident });
92 }
93 return;
94 }
95 match by_type.entry(key.clone()) {
96 Entry::Vacant(e) => {
97 seen.push(key);
98 e.insert(atom.map(|a| vec![a]));
99 }
100 Entry::Occupied(mut e) => match (e.get_mut(), atom) {
101 (None, _) => {}
102 (slot @ Some(_), None) => *slot = None,
103 (Some(existing), Some(a)) => {
104 let path = a.path().to_token_stream().to_string();
105 if !existing.iter().any(|x| x.path().to_token_stream().to_string() == path) {

Callers

nothing calls this directly

Calls 15

ensure_lifetime_aFunction · 0.85
ErrClass · 0.85
extract_field_parse_modeFunction · 0.85
extract_atomFunction · 0.85
option_innerFunction · 0.85
map_type_to_kindFunction · 0.85
generate_type_peekFunction · 0.85
into_iterMethod · 0.80
viewsMethod · 0.80
iterMethod · 0.80
any_field_can_startMethod · 0.80
cloneMethod · 0.80

Tested by

no test coverage detected