Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fmt
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
  • Loading branch information
ggwpez committed May 14, 2023
commit 1b1dba8de1b69c981651165fffddf260c33d7bed
78 changes: 38 additions & 40 deletions proc-macro-warning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,33 @@ mod test;

/// Creates a compile-time warning for proc macro use. See [DeprecatedWarningBuilder] for usage.
#[derive(Clone)]
pub struct Warning {
pub name: String,
pub index: Option<usize>,
pub message: String,
pub links: Vec<String>,
pub span: Span,
pub enum Warning {
/// A *deprecation* warning that notifies users of outdated types and functions.
Deprecated {
name: String,
index: Option<usize>,
message: String,
links: Vec<String>,
span: Span,
},
}

/// A compile-time warning that was already subject to formatting.
///
///
/// Any content will be pasted as-is.
#[derive(Clone)]
pub enum FormattedWarning {
/// A *deprecation* warning.
Deprecated {
/// Unique name of this warning.
///
///
/// Must be unique in the case that multiple of these warnings are emitted, for example by
/// appending a counter.
name: syn::Ident,
/// The exact note to be used for `note = ""`.
note: String,
/// The span of the warning.
///
///
/// Should be set to the original location of where the warning should be emitted.
span: Option<Span>,
},
Expand Down Expand Up @@ -69,7 +72,7 @@ impl FormattedWarning {
/// .old("my_macro()")
/// .new("my_macro::new()")
/// .help_link("https:://example.com")
/// // Normally you use the input span, but this is an example:
/// // Normally you use the input span, but this is an example:
/// .span(proc_macro2::Span::call_site())
/// .build();
///
Expand Down Expand Up @@ -154,7 +157,7 @@ impl DeprecatedWarningBuilder {
let new = self.new.ok_or("Missing new")?;
let message = format!("It is deprecated to {}.\nPlease instead {}.", old, new);

Ok(Warning { name: title, index: self.index, message, links: self.links, span })
Ok(Warning::Deprecated { name: title, index: self.index, message, links: self.links, span })
}

/// Unwraps [`Self::maybe_build`] for convenience.
Expand All @@ -165,58 +168,53 @@ impl DeprecatedWarningBuilder {
}

impl Warning {
/// Create a new *raw* warning.
pub fn new_raw(
name: String,
index: Option<usize>,
message: String,
help_links: Vec<String>,
span: Span,
) -> Warning {
Warning { name, index, message, links: help_links, span }
}

/// Create a new *deprecated* warning.
#[must_use]
pub fn new_deprecated(title: &str) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder::from_title(title)
}

/// Sanitize the warning message.
fn final_message(&self) -> String {
let lines = self.message.trim().lines().map(|line| line.trim_start());
fn final_deprecated_message(&self) -> String {
let (message, links) = match self {
Warning::Deprecated { message, links, .. } => (message, links),
};

let lines = message.trim().lines().map(|line| line.trim_start());
// Prepend two tabs to each line
let message = lines.map(|line| format!("\t\t{}", line)).collect::<Vec<_>>().join("\n");

if !self.links.is_empty() {
let link = self
.links
.iter()
.map(|l| format!("<{}>", l))
.collect::<Vec<_>>()
.join("\n\t\t\t");
if !links.is_empty() {
let link =
links.iter().map(|l| format!("<{}>", l)).collect::<Vec<_>>().join("\n\t\t\t");
format!("\n{}\n\n\t\tFor more info see:\n\t\t\t{}", message, link)
} else {
format!("\n{}", message)
}
}

/// Sanitize the warning name.
fn final_name(&self) -> syn::Ident {
let name = match self.index {
Some(i) => format!("{}_{}", self.name, i),
None => self.name.clone(),
fn final_deprecated_name(&self) -> syn::Ident {
let (index, name, span) = match self {
Warning::Deprecated { index, name, span, .. } => (*index, name, *span),
};

let name = match index {
Some(i) => format!("{}_{}", name, i),
None => name.clone(),
};
syn::Ident::new(&name, self.span)
syn::Ident::new(&name, span)
}
}

impl Into<FormattedWarning> for Warning {
fn into(self) -> FormattedWarning {
FormattedWarning::Deprecated {
name: self.final_name(),
note: self.final_message(),
span: Some(self.span),
match self {
Self::Deprecated { span, .. } => FormattedWarning::Deprecated {
name: self.final_deprecated_name(),
note: self.final_deprecated_message(),
span: Some(span),
},
}
}
}
Expand Down
27 changes: 11 additions & 16 deletions ui-tests/derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,43 @@
//! TESTING ONLY - DO NOT USE.

use proc_macro::TokenStream;
use syn::spanned::Spanned;
use quote::ToTokens;
use syn::spanned::Spanned;

#[proc_macro_derive(Deprecated)]
pub fn deprecated(input: TokenStream) -> TokenStream {
impl_dep(input, true)
impl_dep(input, true)
}

#[proc_macro_derive(DeprecatedNoSpan)]
pub fn deprecated2(input: TokenStream) -> TokenStream {
impl_dep(input, false)
impl_dep(input, false)
}

fn impl_dep(input: TokenStream, span: bool) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
let input = syn::parse_macro_input!(input as syn::DeriveInput);

let warning = proc_macro_warning::Warning::new_deprecated("test")
.old("foo").new("bar");
let warning = if span {
warning.span(input.span())
} else {
warning
}.build();
let warning = proc_macro_warning::Warning::new_deprecated("test").old("foo").new("bar");
let warning = if span { warning.span(input.span()) } else { warning }.build();

warning.into_token_stream().into()
warning.into_token_stream().into()
}

#[proc_macro_derive(DeprecatedRaw)]
pub fn deprecated_raw(input: TokenStream) -> TokenStream {
impl_dep_raw(input)
impl_dep_raw(input)
}

fn impl_dep_raw(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
let input = syn::parse_macro_input!(input as syn::DeriveInput);

let warning = proc_macro_warning::FormattedWarning::new_deprecated(
let warning = proc_macro_warning::FormattedWarning::new_deprecated(
"VeryOldStuff",
"\nMy message do noooooooooooooooooooooooooooooot formaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat
or chaaaaaaaaaaaaange this, also no line breaks please ;)
other veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy looooooooooooooooooooooong lineeeeeeeeeeeeeeee",
input.span(),
);

warning.into_token_stream().into()
warning.into_token_stream().into()
}