1ea88969fSopenharmony_ci//! This implementation uses [`proc_macro::Diagnostic`], nightly only.
2ea88969fSopenharmony_ci
3ea88969fSopenharmony_ciuse std::cell::Cell;
4ea88969fSopenharmony_ci
5ea88969fSopenharmony_ciuse proc_macro::{Diagnostic as PDiag, Level as PLevel};
6ea88969fSopenharmony_ci
7ea88969fSopenharmony_ciuse crate::{
8ea88969fSopenharmony_ci    abort_now, check_correctness,
9ea88969fSopenharmony_ci    diagnostic::{Diagnostic, Level, SuggestionKind},
10ea88969fSopenharmony_ci};
11ea88969fSopenharmony_ci
12ea88969fSopenharmony_cipub fn abort_if_dirty() {
13ea88969fSopenharmony_ci    check_correctness();
14ea88969fSopenharmony_ci    if IS_DIRTY.with(|c| c.get()) {
15ea88969fSopenharmony_ci        abort_now()
16ea88969fSopenharmony_ci    }
17ea88969fSopenharmony_ci}
18ea88969fSopenharmony_ci
19ea88969fSopenharmony_cipub(crate) fn cleanup() -> Vec<Diagnostic> {
20ea88969fSopenharmony_ci    IS_DIRTY.with(|c| c.set(false));
21ea88969fSopenharmony_ci    vec![]
22ea88969fSopenharmony_ci}
23ea88969fSopenharmony_ci
24ea88969fSopenharmony_cipub(crate) fn emit_diagnostic(diag: Diagnostic) {
25ea88969fSopenharmony_ci    let Diagnostic {
26ea88969fSopenharmony_ci        level,
27ea88969fSopenharmony_ci        span_range,
28ea88969fSopenharmony_ci        msg,
29ea88969fSopenharmony_ci        suggestions,
30ea88969fSopenharmony_ci        children,
31ea88969fSopenharmony_ci    } = diag;
32ea88969fSopenharmony_ci
33ea88969fSopenharmony_ci    let span = span_range.collapse().unwrap();
34ea88969fSopenharmony_ci
35ea88969fSopenharmony_ci    let level = match level {
36ea88969fSopenharmony_ci        Level::Warning => PLevel::Warning,
37ea88969fSopenharmony_ci        Level::Error => {
38ea88969fSopenharmony_ci            IS_DIRTY.with(|c| c.set(true));
39ea88969fSopenharmony_ci            PLevel::Error
40ea88969fSopenharmony_ci        }
41ea88969fSopenharmony_ci        _ => unreachable!(),
42ea88969fSopenharmony_ci    };
43ea88969fSopenharmony_ci
44ea88969fSopenharmony_ci    let mut res = PDiag::spanned(span, level, msg);
45ea88969fSopenharmony_ci
46ea88969fSopenharmony_ci    for (kind, msg, span) in suggestions {
47ea88969fSopenharmony_ci        res = match (kind, span) {
48ea88969fSopenharmony_ci            (SuggestionKind::Note, Some(span_range)) => {
49ea88969fSopenharmony_ci                res.span_note(span_range.collapse().unwrap(), msg)
50ea88969fSopenharmony_ci            }
51ea88969fSopenharmony_ci            (SuggestionKind::Help, Some(span_range)) => {
52ea88969fSopenharmony_ci                res.span_help(span_range.collapse().unwrap(), msg)
53ea88969fSopenharmony_ci            }
54ea88969fSopenharmony_ci            (SuggestionKind::Note, None) => res.note(msg),
55ea88969fSopenharmony_ci            (SuggestionKind::Help, None) => res.help(msg),
56ea88969fSopenharmony_ci        }
57ea88969fSopenharmony_ci    }
58ea88969fSopenharmony_ci
59ea88969fSopenharmony_ci    for (span_range, msg) in children {
60ea88969fSopenharmony_ci        let span = span_range.collapse().unwrap();
61ea88969fSopenharmony_ci        res = res.span_error(span, msg);
62ea88969fSopenharmony_ci    }
63ea88969fSopenharmony_ci
64ea88969fSopenharmony_ci    res.emit()
65ea88969fSopenharmony_ci}
66ea88969fSopenharmony_ci
67ea88969fSopenharmony_cithread_local! {
68ea88969fSopenharmony_ci    static IS_DIRTY: Cell<bool> = Cell::new(false);
69ea88969fSopenharmony_ci}
70