Skip to content

Commit

Permalink
Merge pull request #294 from shepmaster/bye-deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
shepmaster committed Jul 5, 2021
2 parents fd4751d + db1752e commit 42bcc33
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 237 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Rust 1.34 is now the minimum supported Rust version. This is a
**breaking change**.

### Removed

- String attribute parsing (`#[snafu(foo = "...")]`) is no longer
supported.

[0.7.0]: https://github.com/shepmaster/snafu/releases/tag/0.7.0

## [0.6.10] - 2020-12-03
Expand Down
9 changes: 3 additions & 6 deletions compatibility-tests/compile-fail/tests/ui/error-reporting.rs
Expand Up @@ -29,18 +29,15 @@ mod display {
enum FailedAttributeParsing {
#[snafu(display)]
DisplayWithoutArgument,

#[snafu(display = 42)]
StringStyleNotStringLiteral,
}

#[derive(Debug, Snafu)]
enum InvalidGeneratedCode {
#[snafu(display(foo()))]
CleanStyleBadFormatString,
FormatStringMissing,

#[snafu(display = "42")]
StringStyleBadFormatString,
#[snafu(display(42))]
FormatStringNotStringLiteral,
}
}

Expand Down
32 changes: 13 additions & 19 deletions compatibility-tests/compile-fail/tests/ui/error-reporting.stderr
Expand Up @@ -10,50 +10,44 @@ error: Only struct-like and unit enum variants are supported
11 | Alpha(i32),
| ^^^^^

error: unexpected end of input, expected parentheses or `=`
error: unexpected end of input, expected parentheses
--> $DIR/error-reporting.rs:30:16
|
30 | #[snafu(display)]
| ^^^^^^^^^

error: expected string literal
--> $DIR/error-reporting.rs:33:27
|
33 | #[snafu(display = 42)]
| ^^

error: format argument must be a string literal
--> $DIR/error-reporting.rs:39:25
--> $DIR/error-reporting.rs:36:25
|
39 | #[snafu(display(foo()))]
36 | #[snafu(display(foo()))]
| ^^^^^
|
help: you might be missing a string literal to format with
|
39 | #[snafu(display("{}", foo()))]
36 | #[snafu(display("{}", foo()))]
| ^^^^^

error: format argument must be a string literal
--> $DIR/error-reporting.rs:42:27
--> $DIR/error-reporting.rs:39:25
|
42 | #[snafu(display = "42")]
| ^^^^
39 | #[snafu(display(42))]
| ^^
|
help: you might be missing a string literal to format with
|
42 | #[snafu(display = "{}", "42")]
| ^^^^^
39 | #[snafu(display("{}", 42))]
| ^^^^^

error: Can only derive `Snafu` for tuple structs with exactly one field
--> $DIR/error-reporting.rs:59:5
--> $DIR/error-reporting.rs:56:5
|
59 | struct ShortTupleStruct();
56 | struct ShortTupleStruct();
| ^^^^^^

error: Can only derive `Snafu` for tuple structs with exactly one field
--> $DIR/error-reporting.rs:62:5
--> $DIR/error-reporting.rs:59:5
|
62 | struct LongTupleStruct(i32, i32);
59 | struct LongTupleStruct(i32, i32);
| ^^^^^^

error: cannot find attribute `serde` in this scope
Expand Down
4 changes: 2 additions & 2 deletions compatibility-tests/compile-fail/tests/ui/visibility.rs
Expand Up @@ -5,10 +5,10 @@ mod outer {
use snafu::Snafu;

#[derive(Debug, Snafu)]
#[snafu(visibility = "pub(crate)")]
#[snafu(visibility(pub(crate)))]
pub(crate) enum Error {
PubCrate,
#[snafu(visibility = "pub(in crate::outer)")]
#[snafu(visibility(pub(in crate::outer)))]
PubInPath,
#[snafu(visibility)]
Private,
Expand Down
Expand Up @@ -5,7 +5,7 @@
use snafu::Snafu;

#[derive(Debug, Snafu)]
#[snafu(visibility = "pub")]
#[snafu(visibility(pub))]
/// Enum docs
pub enum Error {
/// Variant docs
Expand Down
196 changes: 20 additions & 176 deletions snafu-derive/src/parse.rs
Expand Up @@ -3,7 +3,7 @@ use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{
parenthesized,
parse::{Parse, ParseBuffer, ParseStream, Result},
parse::{Parse, ParseStream, Result},
punctuated::Punctuated,
token, Expr, Ident, LitBool, LitStr, Path, Type,
};
Expand All @@ -19,7 +19,6 @@ mod kw {
custom_keyword!(source);
custom_keyword!(visibility);

custom_keyword!(delegate); // deprecated
custom_keyword!(from);

custom_keyword!(suffix);
Expand Down Expand Up @@ -140,13 +139,6 @@ struct BacktraceArg {

impl Parse for BacktraceArg {
fn parse(input: ParseStream) -> Result<Self> {
// TODO: Remove this with a semver-incompatible release
if input.peek(kw::delegate) {
return Err(input.error(
"`backtrace(delegate)` has been removed; use `backtrace` on a source field",
));
}

Ok(Self {
value: input.parse()?,
})
Expand Down Expand Up @@ -299,57 +291,67 @@ impl ToTokens for SuffixArg {

struct CrateRoot {
crate_root_token: kw::crate_root,
arg: CompatArg<Path>,
paren_token: token::Paren,
arg: Path,
}

impl CrateRoot {
// TODO: Remove boxed trait object
fn into_arbitrary(self) -> Box<dyn ToTokens> {
Box::new(self.arg.into_value())
Box::new(self.arg)
}
}

impl Parse for CrateRoot {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(Self {
crate_root_token: input.parse()?,
arg: input.parse()?,
paren_token: parenthesized!(content in input),
arg: content.parse()?,
})
}
}

impl ToTokens for CrateRoot {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.crate_root_token.to_tokens(tokens);
self.arg.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.arg.to_tokens(tokens);
});
}
}

struct Display {
display_token: kw::display,
args: CompatArg<Punctuated<Expr, token::Comma>>,
paren_token: token::Paren,
args: Punctuated<Expr, token::Comma>,
}

impl Display {
// TODO: Remove boxed trait object
fn into_arbitrary(self) -> Box<dyn ToTokens> {
Box::new(self.args.into_value())
Box::new(self.args)
}
}

impl Parse for Display {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(Self {
display_token: input.parse()?,
args: CompatArg::parse_with(&input, Punctuated::parse_terminated)?,
paren_token: parenthesized!(content in input),
args: Punctuated::parse_terminated(&content)?,
})
}
}

impl ToTokens for Display {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.display_token.to_tokens(tokens);
self.args.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.args.to_tokens(tokens);
});
}
}

Expand Down Expand Up @@ -501,7 +503,7 @@ impl ToTokens for SourceArg {

struct Visibility {
visibility_token: kw::visibility,
visibility: MaybeCompatArg<syn::Visibility>,
visibility: MaybeArg<syn::Visibility>,
}

impl Visibility {
Expand Down Expand Up @@ -582,161 +584,3 @@ impl<T: ToTokens> ToTokens for MaybeArg<T> {
}
}
}

// TODO: Remove this with a semver-incompatible release
enum CompatArg<T> {
Compat {
eq_token: token::Eq,
str: LitStr,
content: T,
},
Pretty {
paren_token: token::Paren,
content: T,
},
}

impl<T> CompatArg<T> {
fn into_value(self) -> T {
match self {
CompatArg::Compat { content, .. } => content,
CompatArg::Pretty { content, .. } => content,
}
}

fn parse_with<F>(input: ParseStream<'_>, mut parser: F) -> Result<Self>
where
F: FnMut(ParseStream<'_>) -> Result<T>,
{
let lookahead = input.lookahead1();
if lookahead.peek(token::Paren) {
let content;
Ok(CompatArg::Pretty {
paren_token: parenthesized!(content in input),
content: parser(&content)?,
})
} else if lookahead.peek(token::Eq) {
let eq_token = input.parse()?;
let str: LitStr = input.parse()?;

let parser_with_parens = |input: &ParseBuffer| {
let content;
parenthesized!(content in input);
parser(&content)
};

let content = str
.parse_with(parser_with_parens)
.or_else(|_| str.parse_with(parser))?;

Ok(CompatArg::Compat {
eq_token,
str,
content,
})
} else {
Err(lookahead.error())
}
}
}

impl<T: Parse> Parse for CompatArg<T> {
fn parse(input: ParseStream) -> Result<Self> {
Self::parse_with(input, Parse::parse)
}
}

impl<T: ToTokens> ToTokens for CompatArg<T> {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
CompatArg::Compat { eq_token, str, .. } => {
eq_token.to_tokens(tokens);
str.to_tokens(tokens);
}
CompatArg::Pretty {
paren_token,
content,
} => {
paren_token.surround(tokens, |tokens| {
content.to_tokens(tokens);
});
}
}
}
}

// TODO: Remove this with a semver-incompatible release
enum MaybeCompatArg<T> {
None,
Compat {
eq_token: token::Eq,
str: LitStr,
content: T,
},
Pretty {
paren_token: token::Paren,
content: T,
},
}

impl<T> MaybeCompatArg<T> {
fn into_option(self) -> Option<T> {
match self {
MaybeCompatArg::None => None,
MaybeCompatArg::Compat { content, .. } => Some(content),
MaybeCompatArg::Pretty { content, .. } => Some(content),
}
}

fn parse_with<F>(input: ParseStream<'_>, parser: F) -> Result<Self>
where
F: FnOnce(ParseStream<'_>) -> Result<T>,
{
let lookahead = input.lookahead1();
if lookahead.peek(token::Paren) {
let content;
Ok(MaybeCompatArg::Pretty {
paren_token: parenthesized!(content in input),
content: parser(&content)?,
})
} else if lookahead.peek(token::Eq) {
let eq_token = input.parse()?;
let str: LitStr = input.parse()?;
let content = str.parse_with(parser)?;

Ok(MaybeCompatArg::Compat {
eq_token,
str,
content,
})
} else {
Ok(MaybeCompatArg::None)
}
}
}

impl<T: Parse> Parse for MaybeCompatArg<T> {
fn parse(input: ParseStream) -> Result<Self> {
Self::parse_with(input, Parse::parse)
}
}

impl<T: ToTokens> ToTokens for MaybeCompatArg<T> {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
MaybeCompatArg::None => { /* no-op */ }
MaybeCompatArg::Compat { eq_token, str, .. } => {
eq_token.to_tokens(tokens);
str.to_tokens(tokens);
}
MaybeCompatArg::Pretty {
paren_token,
content,
} => {
paren_token.surround(tokens, |tokens| {
content.to_tokens(tokens);
});
}
}
}
}

0 comments on commit 42bcc33

Please sign in to comment.