| // SPDX-License-Identifier: Apache-2.0 OR MIT | |
| use std::fmt::Display; | |
| use proc_macro2::TokenStream; | |
| use quote::quote_spanned; | |
| use syn::{spanned::Spanned, Error}; | |
| pub(crate) struct DiagCtxt(TokenStream); | |
| pub(crate) struct ErrorGuaranteed(()); | |
| impl DiagCtxt { | |
| pub(crate) fn error(&mut self, span: impl Spanned, msg: impl Display) -> ErrorGuaranteed { | |
| let error = Error::new(span.span(), msg); | |
| self.0.extend(error.into_compile_error()); | |
| ErrorGuaranteed(()) | |
| } | |
| pub(crate) fn warn(&mut self, span: impl Spanned, msg: impl Display) { | |
| // Have the message start on a new line for visual clarity. | |
| let msg = format!("\n{}", msg); | |
| self.0.extend(quote_spanned!(span.span() => | |
| // Approximate using deprecated warning while `proc_macro_diagnostic` is unstable. | |
| const _: () = { | |
| #[deprecated = #msg] | |
| const fn warn() {} | |
| warn(); | |
| }; | |
| )); | |
| } | |
| pub(crate) fn with( | |
| fun: impl FnOnce(&mut DiagCtxt) -> Result<TokenStream, ErrorGuaranteed>, | |
| ) -> TokenStream { | |
| let mut dcx = Self(TokenStream::new()); | |
| match fun(&mut dcx) { | |
| Ok(mut stream) => { | |
| stream.extend(dcx.0); | |
| stream | |
| } | |
| Err(ErrorGuaranteed(())) => dcx.0, | |
| } | |
| } | |
| } |