use super::types::{CaptureError, EmissionError, Spans};
use crate::diagnostic::Diagnostic;
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
#[must_use]
pub fn place(diagnostic: &Diagnostic, spans: &Spans) -> TokenStream {
refused(diagnostic.summary(), sited(diagnostic, spans))
}
pub(super) fn emission_refused(refusal: &EmissionError) -> TokenStream {
refused(&refusal.to_string(), Span::call_site())
}
impl CaptureError {
#[must_use]
pub fn placed(self, spans: &Spans) -> TokenStream {
let at = match &self {
Self::Unbounded { .. } => Span::call_site(),
Self::Unread { at, .. } => spans.at(*at),
};
refused(&self.to_string(), at)
}
}
fn sited(diagnostic: &Diagnostic, spans: &Spans) -> Span {
diagnostic
.site()
.token()
.map_or_else(Span::call_site, |handle| spans.at(handle))
}
fn refused(message: &str, span: Span) -> TokenStream {
let mut bang = Punct::new('!', Spacing::Alone);
bang.set_span(span);
let mut terminator = Punct::new(';', Spacing::Alone);
terminator.set_span(span);
let mut line = Literal::string(message);
line.set_span(span);
let mut argument = Group::new(
Delimiter::Parenthesis,
TokenStream::from(TokenTree::Literal(line)),
);
argument.set_span(span);
[
TokenTree::Ident(Ident::new("compile_error", span)),
TokenTree::Punct(bang),
TokenTree::Group(argument),
TokenTree::Punct(terminator),
]
.into_iter()
.collect()
}