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