diff options
Diffstat (limited to 'vendor/proc-macro-error/src/diagnostic.rs')
-rw-r--r-- | vendor/proc-macro-error/src/diagnostic.rs | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/vendor/proc-macro-error/src/diagnostic.rs b/vendor/proc-macro-error/src/diagnostic.rs deleted file mode 100644 index 983e6174f..000000000 --- a/vendor/proc-macro-error/src/diagnostic.rs +++ /dev/null @@ -1,349 +0,0 @@ -use crate::{abort_now, check_correctness, sealed::Sealed, SpanRange}; -use proc_macro2::Span; -use proc_macro2::TokenStream; - -use quote::{quote_spanned, ToTokens}; - -/// Represents a diagnostic level -/// -/// # Warnings -/// -/// Warnings are ignored on stable/beta -#[derive(Debug, PartialEq)] -pub enum Level { - Error, - Warning, - #[doc(hidden)] - NonExhaustive, -} - -/// Represents a single diagnostic message -#[derive(Debug)] -pub struct Diagnostic { - pub(crate) level: Level, - pub(crate) span_range: SpanRange, - pub(crate) msg: String, - pub(crate) suggestions: Vec<(SuggestionKind, String, Option<SpanRange>)>, - pub(crate) children: Vec<(SpanRange, String)>, -} - -/// A collection of methods that do not exist in `proc_macro::Diagnostic` -/// but still useful to have around. -/// -/// This trait is sealed and cannot be implemented outside of `proc_macro_error`. -pub trait DiagnosticExt: Sealed { - /// Create a new diagnostic message that points to the `span_range`. - /// - /// This function is the same as `Diagnostic::spanned` but produces considerably - /// better error messages for multi-token spans on stable. - fn spanned_range(span_range: SpanRange, level: Level, message: String) -> Self; - - /// Add another error message to self such that it will be emitted right after - /// the main message. - /// - /// This function is the same as `Diagnostic::span_error` but produces considerably - /// better error messages for multi-token spans on stable. - fn span_range_error(self, span_range: SpanRange, msg: String) -> Self; - - /// Attach a "help" note to your main message, the note will have it's own span on nightly. - /// - /// This function is the same as `Diagnostic::span_help` but produces considerably - /// better error messages for multi-token spans on stable. - /// - /// # Span - /// - /// The span is ignored on stable, the note effectively inherits its parent's (main message) span - fn span_range_help(self, span_range: SpanRange, msg: String) -> Self; - - /// Attach a note to your main message, the note will have it's own span on nightly. - /// - /// This function is the same as `Diagnostic::span_note` but produces considerably - /// better error messages for multi-token spans on stable. - /// - /// # Span - /// - /// The span is ignored on stable, the note effectively inherits its parent's (main message) span - fn span_range_note(self, span_range: SpanRange, msg: String) -> Self; -} - -impl DiagnosticExt for Diagnostic { - fn spanned_range(span_range: SpanRange, level: Level, message: String) -> Self { - Diagnostic { - level, - span_range, - msg: message, - suggestions: vec![], - children: vec![], - } - } - - fn span_range_error(mut self, span_range: SpanRange, msg: String) -> Self { - self.children.push((span_range, msg)); - self - } - - fn span_range_help(mut self, span_range: SpanRange, msg: String) -> Self { - self.suggestions - .push((SuggestionKind::Help, msg, Some(span_range))); - self - } - - fn span_range_note(mut self, span_range: SpanRange, msg: String) -> Self { - self.suggestions - .push((SuggestionKind::Note, msg, Some(span_range))); - self - } -} - -impl Diagnostic { - /// Create a new diagnostic message that points to `Span::call_site()` - pub fn new(level: Level, message: String) -> Self { - Diagnostic::spanned(Span::call_site(), level, message) - } - - /// Create a new diagnostic message that points to the `span` - pub fn spanned(span: Span, level: Level, message: String) -> Self { - Diagnostic::spanned_range( - SpanRange { - first: span, - last: span, - }, - level, - message, - ) - } - - /// Add another error message to self such that it will be emitted right after - /// the main message. - pub fn span_error(self, span: Span, msg: String) -> Self { - self.span_range_error( - SpanRange { - first: span, - last: span, - }, - msg, - ) - } - - /// Attach a "help" note to your main message, the note will have it's own span on nightly. - /// - /// # Span - /// - /// The span is ignored on stable, the note effectively inherits its parent's (main message) span - pub fn span_help(self, span: Span, msg: String) -> Self { - self.span_range_help( - SpanRange { - first: span, - last: span, - }, - msg, - ) - } - - /// Attach a "help" note to your main message. - pub fn help(mut self, msg: String) -> Self { - self.suggestions.push((SuggestionKind::Help, msg, None)); - self - } - - /// Attach a note to your main message, the note will have it's own span on nightly. - /// - /// # Span - /// - /// The span is ignored on stable, the note effectively inherits its parent's (main message) span - pub fn span_note(self, span: Span, msg: String) -> Self { - self.span_range_note( - SpanRange { - first: span, - last: span, - }, - msg, - ) - } - - /// Attach a note to your main message - pub fn note(mut self, msg: String) -> Self { - self.suggestions.push((SuggestionKind::Note, msg, None)); - self - } - - /// The message of main warning/error (no notes attached) - pub fn message(&self) -> &str { - &self.msg - } - - /// Abort the proc-macro's execution and display the diagnostic. - /// - /// # Warnings - /// - /// Warnings are not emitted on stable and beta, but this function will abort anyway. - pub fn abort(self) -> ! { - self.emit(); - abort_now() - } - - /// Display the diagnostic while not aborting macro execution. - /// - /// # Warnings - /// - /// Warnings are ignored on stable/beta - pub fn emit(self) { - check_correctness(); - crate::imp::emit_diagnostic(self); - } -} - -/// **NOT PUBLIC API! NOTHING TO SEE HERE!!!** -#[doc(hidden)] -impl Diagnostic { - pub fn span_suggestion(self, span: Span, suggestion: &str, msg: String) -> Self { - match suggestion { - "help" | "hint" => self.span_help(span, msg), - _ => self.span_note(span, msg), - } - } - - pub fn suggestion(self, suggestion: &str, msg: String) -> Self { - match suggestion { - "help" | "hint" => self.help(msg), - _ => self.note(msg), - } - } -} - -impl ToTokens for Diagnostic { - fn to_tokens(&self, ts: &mut TokenStream) { - use std::borrow::Cow; - - fn ensure_lf(buf: &mut String, s: &str) { - if s.ends_with('\n') { - buf.push_str(s); - } else { - buf.push_str(s); - buf.push('\n'); - } - } - - fn diag_to_tokens( - span_range: SpanRange, - level: &Level, - msg: &str, - suggestions: &[(SuggestionKind, String, Option<SpanRange>)], - ) -> TokenStream { - if *level == Level::Warning { - return TokenStream::new(); - } - - let message = if suggestions.is_empty() { - Cow::Borrowed(msg) - } else { - let mut message = String::new(); - ensure_lf(&mut message, msg); - message.push('\n'); - - for (kind, note, _span) in suggestions { - message.push_str(" = "); - message.push_str(kind.name()); - message.push_str(": "); - ensure_lf(&mut message, note); - } - message.push('\n'); - - Cow::Owned(message) - }; - - let mut msg = proc_macro2::Literal::string(&message); - msg.set_span(span_range.last); - let group = quote_spanned!(span_range.last=> { #msg } ); - quote_spanned!(span_range.first=> compile_error!#group) - } - - ts.extend(diag_to_tokens( - self.span_range, - &self.level, - &self.msg, - &self.suggestions, - )); - ts.extend( - self.children - .iter() - .map(|(span_range, msg)| diag_to_tokens(*span_range, &Level::Error, &msg, &[])), - ); - } -} - -#[derive(Debug)] -pub(crate) enum SuggestionKind { - Help, - Note, -} - -impl SuggestionKind { - fn name(&self) -> &'static str { - match self { - SuggestionKind::Note => "note", - SuggestionKind::Help => "help", - } - } -} - -#[cfg(feature = "syn-error")] -impl From<syn::Error> for Diagnostic { - fn from(err: syn::Error) -> Self { - use proc_macro2::{Delimiter, TokenTree}; - - fn gut_error(ts: &mut impl Iterator<Item = TokenTree>) -> Option<(SpanRange, String)> { - let first = match ts.next() { - // compile_error - None => return None, - Some(tt) => tt.span(), - }; - ts.next().unwrap(); // ! - - let lit = match ts.next().unwrap() { - TokenTree::Group(group) => { - // Currently `syn` builds `compile_error!` invocations - // exclusively in `ident{"..."}` (braced) form which is not - // followed by `;` (semicolon). - // - // But if it changes to `ident("...");` (parenthesized) - // or `ident["..."];` (bracketed) form, - // we will need to skip the `;` as well. - // Highly unlikely, but better safe than sorry. - - if group.delimiter() == Delimiter::Parenthesis - || group.delimiter() == Delimiter::Bracket - { - ts.next().unwrap(); // ; - } - - match group.stream().into_iter().next().unwrap() { - TokenTree::Literal(lit) => lit, - _ => unreachable!(), - } - } - _ => unreachable!(), - }; - - let last = lit.span(); - let mut msg = lit.to_string(); - - // "abc" => abc - msg.pop(); - msg.remove(0); - - Some((SpanRange { first, last }, msg)) - } - - let mut ts = err.to_compile_error().into_iter(); - - let (span_range, msg) = gut_error(&mut ts).unwrap(); - let mut res = Diagnostic::spanned_range(span_range, Level::Error, msg); - - while let Some((span_range, msg)) = gut_error(&mut ts) { - res = res.span_range_error(span_range, msg); - } - - res - } -} |