Skip to content

Commit

Permalink
1.0.0-rc.1 (#8)
Browse files Browse the repository at this point in the history
Changes:
- Make `DeprecatedWarningBuilder` clone
- Use generic function arguments like `Into<String>` instead of
hard-coded types.
- Cleanup repo
- Bump to semver `1.0.0-rc.1`
- Add `derive_debug` default feature

---------

Signed-off-by: Oliver Tale-Yazdi <[email protected]>
  • Loading branch information
ggwpez authored Oct 8, 2023
1 parent 49fc5a2 commit d8c71a2
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
run: cargo build --all-targets --all-features --locked

- name: Test
run: TRYBUILD=overwrite cargo test --locked --all-targets --all-features
run: cargo test --locked --all-targets --all-features

- name: Clippy
run: cargo clippy --locked --all-targets --all-features -- -D warnings
Expand Down
30 changes: 15 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ readme = "README.md"

members = [
"proc-macro-warning",

"ui-tests/derive",
"ui-tests/ui",
]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Building a warning is easy with the builder pattern.
```rust
use proc_macro_warning::Warning;

let warning = Warning::new_deprecated("my_macro")
let warning = Warning::new_deprecated("OldStuffUsed")
.old("my_macro()")
.new("my_macro::new()")
.help_link("https:://example.com")
Expand Down
10 changes: 6 additions & 4 deletions proc-macro-warning/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "proc-macro-warning"
version = "0.4.2"
version = "1.0.0-rc.1"
edition = "2021"
license = "GPL-3.0 OR Apache-2.0"
authors = ["Oliver Tale-Yazdi <[email protected]>"]
Expand All @@ -11,12 +11,14 @@ readme.workspace = true
build = "build.rs"

[dependencies]
proc-macro2 = { version = "1.0.66", default-features = false }
proc-macro2 = { version = "1.0.68", default-features = false }
quote = { version = "1.0.33", default-features = false }
syn = { version = "2.0.29", default-features = false }
syn = { version = "2.0.38", default-features = false }

[dev-dependencies]
derive = { path = "../ui-tests/derive" }

[features]
default = []
default = ["derive_debug"]

derive_debug = []
73 changes: 45 additions & 28 deletions proc-macro-warning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,30 @@

#![doc = include_str!(env!("README_PATH"))]
#![deny(unsafe_code)]
#![deny(missing_docs)]

use core::ops::Deref;
use proc_macro2::Span;
use quote::{quote_spanned, ToTokens};
use syn::{spanned::Spanned, Ident};

mod test;

/// Creates a compile-time warning for proc macro use. See [DeprecatedWarningBuilder] for usage.
#[derive(Clone)]
#[cfg_attr(feature = "derive_debug", derive(Debug))]
pub enum Warning {
/// A *deprecation* warning that notifies users of outdated types and functions.
Deprecated {
/// The name of the warning.
name: String,
/// The index of the warning. Name++Index must be unique.
index: Option<usize>,
/// The message of the warning.
message: String,
/// The help links to be displayed next to the message.
links: Vec<String>,
/// The span of the warning.
span: Span,
},
}
Expand All @@ -29,14 +37,15 @@ pub enum Warning {
///
/// Any content will be pasted as-is.
#[derive(Clone)]
#[cfg_attr(feature = "derive_debug", derive(Debug))]
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,
name: Ident,
/// The exact note to be used for `note = ""`.
note: String,
/// The span of the warning.
Expand All @@ -49,13 +58,13 @@ pub enum FormattedWarning {
impl FormattedWarning {
/// Create a new deprecated warning that already was formatted by the caller.
#[must_use]
pub fn new_deprecated<'a, S, T>(name: S, note: T, span: Span) -> Self
pub fn new_deprecated<S, T>(name: S, note: T, span: Span) -> Self
where
S: Into<&'a str>,
S: AsRef<str>,
T: Into<String>,
{
Self::Deprecated {
name: syn::Ident::new(name.into(), span),
name: Ident::new(name.as_ref(), span),
note: note.into(),
span: Some(span),
}
Expand Down Expand Up @@ -89,7 +98,8 @@ impl FormattedWarning {
/// }
/// };
/// ```
#[derive(Default)]
#[derive(Default, Clone)]
#[cfg_attr(feature = "derive_debug", derive(Debug))]
pub struct DeprecatedWarningBuilder {
title: String,
index: Option<usize>,
Expand All @@ -104,53 +114,59 @@ impl DeprecatedWarningBuilder {
///
/// The title must be unique for each warning.
#[must_use]
pub fn from_title(title: &str) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { title: title.into(), ..Default::default() }
pub fn from_title<S: Into<String>>(title: S) -> Self {
Self { title: title.into(), ..Default::default() }
}

/// Set an optional index in case that a warning appears multiple times.
///
/// Must be set if a warning appears multiple times.
#[must_use]
pub fn index(self, index: usize) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { index: Some(index), ..self }
pub fn index<S: Into<usize>>(self, index: S) -> Self {
Self { index: Some(index.into()), ..self }
}

/// The old *deprecated* way of doing something.
///
/// Should complete the sentence "It is deprecated to ...".
#[must_use]
pub fn old(self, old: &str) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { old: Some(old.into()), ..self }
pub fn old<S: Into<String>>(self, old: S) -> Self {
Self { old: Some(old.into()), ..self }
}

/// The *new* way of doing something.
///
/// Should complete the sentence "Please instead ...".
#[must_use]
pub fn new(self, new: &str) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { new: Some(new.into()), ..self }
pub fn new<S: Into<String>>(self, new: S) -> Self {
Self { new: Some(new.into()), ..self }
}

/// A help link for the user to explain the transition and justification.
#[must_use]
pub fn help_link(self, link: &str) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { links: vec![link.into()], ..self }
pub fn help_link<S: Into<String>>(self, link: S) -> Self {
Self { links: vec![link.into()], ..self }
}

/// Multiple help links for the user to explain the transition and justification.
#[must_use]
pub fn help_links(self, links: &[&str]) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { links: links.iter().map(|s| s.deref().into()).collect(), ..self }
pub fn help_links(self, links: &[&str]) -> Self {
Self { links: links.iter().map(|s| s.deref().into()).collect(), ..self }
}

/// The span of the warning.
/// Set the span of the warning.
#[must_use]
pub fn span(self, span: Span) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder { span: Some(span), ..self }
pub fn span(self, span: Span) -> Self {
Self { span: Some(span), ..self }
}

/// Build the warning.
/// Set the span of the warning to the span of `s`.
#[must_use]
pub fn spanned<S: Spanned>(self, spanned: S) -> Self {
Self { span: Some(spanned.span()), ..self }
}

/// Fallibly build a warning.
pub fn maybe_build(self) -> Result<Warning, String> {
let span = self.span.unwrap_or_else(Span::call_site);
let title = self.title;
Expand All @@ -171,14 +187,14 @@ impl DeprecatedWarningBuilder {
impl Warning {
/// Create a new *deprecated* warning.
#[must_use]
pub fn new_deprecated(title: &str) -> DeprecatedWarningBuilder {
pub fn new_deprecated<S: Into<String>>(title: S) -> DeprecatedWarningBuilder {
DeprecatedWarningBuilder::from_title(title)
}

/// Sanitize the warning message.
fn final_deprecated_message(&self) -> String {
let (message, links) = match self {
Warning::Deprecated { message, links, .. } => (message, links),
Self::Deprecated { message, links, .. } => (message, links),
};

let lines = message.trim().lines().map(|line| line.trim_start());
Expand All @@ -195,23 +211,24 @@ impl Warning {
}

/// Sanitize the warning name.
fn final_deprecated_name(&self) -> syn::Ident {
fn final_deprecated_name(&self) -> Ident {
let (index, name, span) = match self {
Warning::Deprecated { index, name, span, .. } => (*index, name, *span),
Self::Deprecated { index, name, span, .. } => (*index, name, *span),
};

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

Ident::new(&name, span)
}
}

impl From<Warning> for FormattedWarning {
fn from(val: Warning) -> Self {
match val {
Warning::Deprecated { span, .. } => FormattedWarning::Deprecated {
Warning::Deprecated { span, .. } => Self::Deprecated {
name: val.final_deprecated_name(),
note: val.final_deprecated_message(),
span: Some(span),
Expand All @@ -230,7 +247,7 @@ impl ToTokens for Warning {
impl ToTokens for FormattedWarning {
fn to_tokens(&self, stream: &mut proc_macro2::TokenStream) {
let (name, note, span) = match self {
FormattedWarning::Deprecated { name, note, span } => (name, note, span),
Self::Deprecated { name, note, span } => (name, note, span),
};
let span = span.unwrap_or_else(Span::call_site);

Expand Down
Loading

0 comments on commit d8c71a2

Please sign in to comment.