salsa/components/salsa-macros/src/accumulator.rs
CheaterCodes 13a2bd7461
Changed return_ref syntax to returns(as_ref) and returns(cloned) (#772)
* Changed `return_ref` syntax to `returns(as_ref)` and `returns(cloned)`

* Implement

* renamed module for return_mode

* Rename macro, fix docs, add tests, validate return modes

* Cargo fmt

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-09 07:28:54 +00:00

81 lines
2.2 KiB
Rust

use proc_macro2::TokenStream;
use crate::hygiene::Hygiene;
use crate::options::{AllowedOptions, Options};
use crate::token_stream_with_error;
// #[salsa::accumulator(jar = Jar0)]
// struct Accumulator(DataType);
pub(crate) fn accumulator(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let hygiene = Hygiene::from1(&input);
let args = syn::parse_macro_input!(args as Options<Accumulator>);
let struct_item = parse_macro_input!(input as syn::ItemStruct);
let ident = struct_item.ident.clone();
let m = StructMacro {
hygiene,
_args: args,
struct_item,
};
match m.try_expand() {
Ok(v) => crate::debug::dump_tokens(ident, v).into(),
Err(e) => token_stream_with_error(input, e),
}
}
struct Accumulator;
impl AllowedOptions for Accumulator {
const RETURNS: bool = false;
const SPECIFY: bool = false;
const NO_EQ: bool = false;
const DEBUG: bool = false;
const NO_CLONE: bool = false;
const NO_LIFETIME: bool = false;
const SINGLETON: bool = false;
const DATA: bool = false;
const DB: bool = false;
const CYCLE_FN: bool = false;
const CYCLE_INITIAL: bool = false;
const CYCLE_RESULT: bool = false;
const LRU: bool = false;
const CONSTRUCTOR_NAME: bool = false;
const ID: bool = false;
}
struct StructMacro {
hygiene: Hygiene,
_args: Options<Accumulator>,
struct_item: syn::ItemStruct,
}
#[allow(non_snake_case)]
impl StructMacro {
fn try_expand(self) -> syn::Result<TokenStream> {
let ident = self.struct_item.ident.clone();
let zalsa = self.hygiene.ident("zalsa");
let zalsa_struct = self.hygiene.ident("zalsa_struct");
let CACHE = self.hygiene.ident("CACHE");
let ingredient = self.hygiene.ident("ingredient");
let struct_item = self.struct_item;
Ok(quote! {
#struct_item
salsa::plumbing::setup_accumulator_impl! {
Struct: #ident,
unused_names: [
#zalsa,
#zalsa_struct,
#CACHE,
#ingredient,
]
}
})
}
}