dioxus_rsx/
diagnostics.rs

1use proc_macro2_diagnostics::Diagnostic;
2use quote::ToTokens;
3
4/// A collection of diagnostics
5///
6/// This is a wrapper type since we want it to be transparent in terms of PartialEq and Eq.
7/// This also lets us choose the expansion strategy for the diagnostics.
8#[derive(Debug, Clone, Default)]
9pub struct Diagnostics {
10    pub diagnostics: Vec<Diagnostic>,
11}
12
13impl Diagnostics {
14    pub fn new() -> Self {
15        Self {
16            diagnostics: vec![],
17        }
18    }
19
20    pub fn push(&mut self, diagnostic: Diagnostic) {
21        self.diagnostics.push(diagnostic);
22    }
23
24    pub fn extend(&mut self, diagnostics: Vec<Diagnostic>) {
25        self.diagnostics.extend(diagnostics);
26    }
27
28    pub fn is_empty(&self) -> bool {
29        self.diagnostics.is_empty()
30    }
31
32    pub fn into_diagnostics(self) -> Vec<Diagnostic> {
33        self.diagnostics
34    }
35
36    pub fn len(&self) -> usize {
37        self.diagnostics.len()
38    }
39}
40
41impl PartialEq for Diagnostics {
42    fn eq(&self, _other: &Self) -> bool {
43        true
44    }
45}
46
47impl Eq for Diagnostics {}
48
49impl ToTokens for Diagnostics {
50    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
51        for diagnostic in &self.diagnostics {
52            tokens.extend(diagnostic.clone().emit_as_expr_tokens());
53        }
54    }
55}
56
57// TODO: Ideally this would be integrated into the existing diagnostics struct, but currently all fields are public so adding
58// new fields would be a breaking change. Diagnostics also doesn't expose the message directly so we can't just modify
59// the expansion
60pub(crate) mod new_diagnostics {
61    use proc_macro2_diagnostics::SpanDiagnosticExt;
62    use std::fmt::Display;
63
64    use proc_macro2::{Span, TokenStream as TokenStream2};
65    use quote::quote_spanned;
66
67    pub(crate) fn warning_diagnostic(span: Span, message: impl Display) -> TokenStream2 {
68        let note = message.to_string();
69        // If we are compiling on nightly, use diagnostics directly which supports proper warnings through new span apis
70        if rustversion::cfg!(nightly) {
71            return span.warning(note).emit_as_item_tokens();
72        }
73        quote_spanned! { span =>
74            const _: () = {
75                #[deprecated(note = #note)]
76                struct Warning;
77                _ = Warning;
78            };
79        }
80    }
81}