diff options
Diffstat (limited to 'tvix/nix-compat-derive/src/internal/ctx.rs')
-rw-r--r-- | tvix/nix-compat-derive/src/internal/ctx.rs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/tvix/nix-compat-derive/src/internal/ctx.rs b/tvix/nix-compat-derive/src/internal/ctx.rs new file mode 100644 index 000000000000..ba770e044bc2 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/ctx.rs @@ -0,0 +1,50 @@ +use std::cell::RefCell; +use std::fmt; +use std::thread::panicking; + +use quote::ToTokens; + +pub struct Context { + errors: RefCell<Option<Vec<syn::Error>>>, +} + +impl Context { + pub fn new() -> Context { + Context { + errors: RefCell::new(Some(Vec::new())), + } + } + + pub fn syn_error(&self, error: syn::Error) { + self.errors + .borrow_mut() + .as_mut() + .take() + .unwrap() + .push(error); + } + + pub fn error_spanned<T: ToTokens, D: fmt::Display>(&self, tokens: T, message: D) { + self.syn_error(syn::Error::new_spanned(tokens, message)); + } + + pub fn check(&self) -> syn::Result<()> { + let mut iter = self.errors.borrow_mut().take().unwrap().into_iter(); + let mut err = match iter.next() { + None => return Ok(()), + Some(err) => err, + }; + for next_err in iter { + err.combine(next_err); + } + Err(err) + } +} + +impl Drop for Context { + fn drop(&mut self) { + if self.errors.borrow().is_some() && !panicking() { + panic!("Context dropped without checking errors"); + } + } +} |