1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
// Copyright (c) 2024 Jonas Schäfer <jonas@zombofant.net>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//! Identifiers used within generated code.
use proc_macro2::Span;
use syn::*;
use crate::types::ref_ty;
/// Container struct for various identifiers used throughout the parser code.
///
/// This struct is passed around from the [`crate::compound::Compound`]
/// downward to the code generators in order to ensure that everyone is on the
/// same page about which identifiers are used for what.
///
/// The recommended usage is to bind the names which are needed into the local
/// scope like this:
///
/// ```text
/// # let scope = FromEventsScope::new();
/// let FromEventsScope {
/// ref attrs,
/// ..
/// } = scope;
/// ```
pub(crate) struct FromEventsScope {
/// Accesses the `AttrMap` from code in
/// [`crate::field::FieldBuilderPart::Init`].
pub(crate) attrs: Ident,
/// Accesses the `String` of a `rxml::Event::Text` event from code in
/// [`crate::field::FieldBuilderPart::Text`].
pub(crate) text: Ident,
/// Accesses the builder data during parsing.
///
/// This should not be used directly outside [`crate::compound`]. Most of
/// the time, using [`Self::access_field`] is the correct way to access
/// the builder data.
pub(crate) builder_data_ident: Ident,
}
impl FromEventsScope {
/// Create a fresh scope with all necessary identifiers.
pub(crate) fn new() -> Self {
// Sadly, `Ident::new` is not `const`, so we have to create even the
// well-known identifiers from scratch all the time.
Self {
attrs: Ident::new("attrs", Span::call_site()),
text: Ident::new("__xso_proc_macro_text_data", Span::call_site()),
builder_data_ident: Ident::new("__xso_proc_macro_builder_data", Span::call_site()),
}
}
/// Generate an expression which accesses the temporary value for the
/// given `member` during parsing.
pub(crate) fn access_field(&self, member: &Member) -> Expr {
Expr::Field(ExprField {
attrs: Vec::new(),
base: Box::new(Expr::Path(ExprPath {
attrs: Vec::new(),
qself: None,
path: self.builder_data_ident.clone().into(),
})),
dot_token: syn::token::Dot {
spans: [Span::call_site()],
},
member: Member::Named(mangle_member(member)),
})
}
}
/// Container struct for various identifiers used throughout the generator
/// code.
///
/// This struct is passed around from the [`crate::compound::Compound`]
/// downward to the code generators in order to ensure that everyone is on the
/// same page about which identifiers are used for what.
///
/// See [`FromEventsScope`] for recommendations on the usage.
pub(crate) struct AsItemsScope {
/// Lifetime for data borrowed by the implementation.
pub(crate) lifetime: Lifetime,
}
impl AsItemsScope {
/// Create a fresh scope with all necessary identifiers.
pub(crate) fn new(lifetime: &Lifetime) -> Self {
Self {
lifetime: lifetime.clone(),
}
}
/// Create a reference to `ty`, borrowed for the lifetime of the AsXml
/// impl.
pub(crate) fn borrow(&self, ty: Type) -> Type {
ref_ty(ty, self.lifetime.clone())
}
}
pub(crate) fn mangle_member(member: &Member) -> Ident {
match member {
Member::Named(member) => quote::format_ident!("f{}", member),
Member::Unnamed(member) => quote::format_ident!("f_u{}", member.index),
}
}