Skip to content

Commit d82e419

Browse files
Urist-McGitcsnover
authored andcommitted
Update to syn version 2
As there were quite substantial changes from syn version 1 to 2 some minor changes to the codebase are necessary: The `Attribute` type is more accurately typed now, that means instead of having simply a `Path` entity and some tokens after it, there is now a differentation between attributes with a `=`, in parentheses or without any other tokens but the path. This makes parsing slightly easier for us. Some test fixes were also required as these rely on the old tokens we got from an attribute. The `Spanned` trait was sealed in syn v2. We implemented it for some of the internal meta types. As we still have the span information readily available and the trait is otherwise required nowhere, simply remove the impl. Some syntax enums were marked as `non-exhaustive`. Handle these additional options in a sensible way where possible and throw compile errors in all other places. Fixes jam1garner#285. Closes jam1garner#299. Signed-off-by: Colin Snover <[email protected]>
1 parent f553fab commit d82e419

File tree

8 files changed

+83
-69
lines changed

8 files changed

+83
-69
lines changed

binrw_derive/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ either = "1.0.0"
1919
owo-colors = { version = "3.0.0", optional = true }
2020
proc-macro2 = { version = "1.0.53", features = ["span-locations"] }
2121
quote = "1.0.0"
22-
syn = { version = "1.0.66", features = ["extra-traits", "fold", "full", "visit"] }
22+
syn = { version = "2", features = ["extra-traits", "fold", "full", "visit"] }
2323

2424
[dev-dependencies]
25-
runtime-macros-derive = "0.4.0"
25+
runtime-macros = "1.1.0"
2626

2727
[features]
2828
default = []

binrw_derive/src/binrw/backtrace/syntax_highlighting.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use core::{
77
ops::Range,
88
};
99
use owo_colors::{styles::BoldDisplay, XtermColors};
10-
use proc_macro2::{Span, TokenTree};
10+
use proc_macro2::Span;
1111
use quote::ToTokens;
1212
use std::collections::HashMap;
1313
use syn::{
@@ -135,13 +135,13 @@ fn highlight_attributes(attrs: &[syn::Attribute], visit: &mut Visitor) {
135135
// |____|______ path and pound_token
136136
//
137137
syntax_info.highlight_color(attr.pound_token.span(), Color::Keyword);
138-
syntax_info.highlight_color(attr.path.span(), Color::Keyword);
138+
syntax_info.highlight_color(attr.path().span(), Color::Keyword);
139139

140140
// #[...]
141141
// ^ ^
142142
// |___|___ brackets
143143
//
144-
let span = attr.bracket_token.span;
144+
let span = attr.bracket_token.span.join();
145145
let start = start(span);
146146
let end = end(span);
147147

@@ -158,9 +158,9 @@ fn highlight_attributes(attrs: &[syn::Attribute], visit: &mut Visitor) {
158158
// ^ ^
159159
// |___|___ parens
160160
//
161-
if let Some(TokenTree::Group(group)) = attr.tokens.clone().into_iter().next() {
162-
syntax_info.highlight_color(group.span_open(), Color::Keyword);
163-
syntax_info.highlight_color(group.span_close(), Color::Keyword);
161+
if let syn::Meta::List(l) = &attr.meta {
162+
syntax_info.highlight_color(l.delimiter.span().open(), Color::Keyword);
163+
syntax_info.highlight_color(l.delimiter.span().close(), Color::Keyword);
164164
}
165165
}
166166
}
@@ -291,7 +291,7 @@ impl<'ast> Visit<'ast> for Visitor {
291291
Lit::Str(_) | Lit::ByteStr(_) => Color::String,
292292
Lit::Byte(_) | Lit::Char(_) => Color::Char,
293293
Lit::Int(_) | Lit::Float(_) | Lit::Bool(_) => Color::Number,
294-
Lit::Verbatim(_) => return,
294+
_ => return,
295295
},
296296
));
297297
}

binrw_derive/src/binrw/mod.rs

+38-27
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,19 @@ pub(super) fn derive_from_attribute(
8787
let mut mixed_rw = false;
8888
let opposite_attr = if write { "binread" } else { "binwrite" };
8989
for attr in &mut derive_input.attrs {
90-
if let Some(seg) = attr.path.segments.last() {
90+
if let Some(seg) = attr.path().segments.last() {
9191
let ident = &seg.ident;
9292
if ident == "binrw" || ident == "binread" || ident == "binwrite" {
93-
attr.tokens = quote! { (ignore) };
94-
9593
if ident == "binrw" || ident == opposite_attr {
9694
mixed_rw = true;
9795
}
96+
97+
attr.meta = syn::MetaList {
98+
path: attr.path().clone(),
99+
delimiter: syn::MacroDelimiter::Paren(syn::token::Paren::default()),
100+
tokens: quote! { ignore },
101+
}
102+
.into();
98103
}
99104
}
100105
}
@@ -151,11 +156,11 @@ pub(super) fn derive_from_input(
151156
}
152157

153158
fn is_binread_attr(attr: &syn::Attribute) -> bool {
154-
attr.path.is_ident("br") || attr.path.is_ident("brw")
159+
attr.path().is_ident("br") || attr.path().is_ident("brw")
155160
}
156161

157162
fn is_binwrite_attr(attr: &syn::Attribute) -> bool {
158-
attr.path.is_ident("bw") || attr.path.is_ident("brw")
163+
attr.path().is_ident("bw") || attr.path().is_ident("brw")
159164
}
160165

161166
fn parse(
@@ -175,7 +180,7 @@ fn parse(
175180
#[cfg_attr(coverage_nightly, coverage(off))]
176181
#[test]
177182
fn derive_binread_code_coverage_for_tool() {
178-
use runtime_macros_derive::emulate_derive_expansion_fallible;
183+
use runtime_macros::emulate_derive_macro_expansion;
179184
use std::{env, fs};
180185

181186
let derive_tests_folder = env::current_dir()
@@ -190,16 +195,19 @@ fn derive_binread_code_coverage_for_tool() {
190195
let entry = entry.unwrap();
191196
if entry.file_type().unwrap().is_file() {
192197
let file = fs::File::open(entry.path()).unwrap();
193-
if emulate_derive_expansion_fallible(file, "BinRead", |input| {
194-
parse(
195-
&input,
196-
Options {
197-
derive: true,
198-
write: false,
199-
},
200-
)
201-
.1
202-
})
198+
if emulate_derive_macro_expansion(
199+
file,
200+
&[("BinRead", |input| {
201+
parse(
202+
&syn::parse2::<syn::DeriveInput>(input).unwrap(),
203+
Options {
204+
derive: true,
205+
write: false,
206+
},
207+
)
208+
.1
209+
})],
210+
)
203211
.is_err()
204212
{
205213
run_success = false;
@@ -214,7 +222,7 @@ fn derive_binread_code_coverage_for_tool() {
214222
#[cfg_attr(coverage_nightly, coverage(off))]
215223
#[test]
216224
fn derive_binwrite_code_coverage_for_tool() {
217-
use runtime_macros_derive::emulate_derive_expansion_fallible;
225+
use runtime_macros::emulate_derive_macro_expansion;
218226
use std::{env, fs};
219227

220228
let derive_tests_folder = env::current_dir()
@@ -230,16 +238,19 @@ fn derive_binwrite_code_coverage_for_tool() {
230238
let entry = entry.unwrap();
231239
if entry.file_type().unwrap().is_file() {
232240
let file = fs::File::open(entry.path()).unwrap();
233-
if emulate_derive_expansion_fallible(file, "BinWrite", |input| {
234-
parse(
235-
&input,
236-
Options {
237-
derive: true,
238-
write: true,
239-
},
240-
)
241-
.1
242-
})
241+
if emulate_derive_macro_expansion(
242+
file,
243+
&[("BinWrite", |input| {
244+
parse(
245+
&syn::parse2::<syn::DeriveInput>(input).unwrap(),
246+
Options {
247+
derive: true,
248+
write: true,
249+
},
250+
)
251+
.1
252+
})],
253+
)
243254
.is_err()
244255
{
245256
run_success = false;

binrw_derive/src/binrw/parser/mod.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,16 @@ trait FromAttrs<Attr: syn::parse::Parse> {
4040
is_binread_attr(attr)
4141
}
4242
})
43-
.flat_map(
44-
|attr| match syn::parse2::<MetaAttrList<Attr>>(attr.tokens.clone()) {
43+
.flat_map(|attr| {
44+
let tokens = match attr.meta.require_list() {
45+
Ok(m) => m.tokens.clone(),
46+
Err(err) => return either::Right(core::iter::once(Err(err))),
47+
};
48+
match syn::parse2::<MetaAttrList<Attr>>(tokens) {
4549
Ok(list) => either::Left(list.into_iter().map(Ok)),
4650
Err(err) => either::Right(core::iter::once(Err(err))),
47-
},
48-
);
51+
}
52+
});
4953

5054
let mut all_errors = None::<syn::Error>;
5155
for attr in attrs {

binrw_derive/src/binrw/parser/types/magic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ impl TryFrom<attrs::Magic> for SpannedValue<Inner> {
9393
"expected byte string, byte, float, or int",
9494
))
9595
}
96+
_ => return Err(syn::Error::new(value.span(), "unexpected literal")),
9697
};
9798

9899
Ok(Self::new(

binrw_derive/src/binrw/parser/types/spanned_value.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ impl<T> SpannedValue<T> {
1616
pub(crate) fn into_value(self) -> T {
1717
self.value
1818
}
19+
20+
pub(crate) fn span(&self) -> Span {
21+
self.span
22+
}
1923
}
2024

2125
impl<T> AsRef<T> for SpannedValue<T> {
@@ -32,14 +36,6 @@ impl<T> core::ops::Deref for SpannedValue<T> {
3236
}
3337
}
3438

35-
// It is not possible to implement this *and* ToTokens because syn has a generic
36-
// implementation of Spanned for all ToTokens
37-
impl<T> syn::spanned::Spanned for SpannedValue<T> {
38-
fn span(&self) -> Span {
39-
self.span
40-
}
41-
}
42-
4339
impl<T: Into<To> + KeywordToken, To> From<T> for SpannedValue<To> {
4440
fn from(value: T) -> Self {
4541
let span = value.keyword_span();

binrw_derive/src/meta_types.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ impl<Keyword: Parse, ItemType: Parse> Parse for MetaList<Keyword, ItemType> {
143143
parenthesized!(content in input);
144144
Ok(MetaList {
145145
ident,
146-
fields: content.parse_terminated::<_, Token![,]>(ItemType::parse)?,
146+
fields: content.parse_terminated(ItemType::parse, Token![,])?,
147147
})
148148
}
149149
}
@@ -184,15 +184,15 @@ where
184184
Ok(Self {
185185
ident,
186186
list: Enclosure::Paren {
187-
fields: content.parse_terminated::<_, Token![,]>(ParenItemType::parse)?,
187+
fields: content.parse_terminated(ParenItemType::parse, Token![,])?,
188188
},
189189
})
190190
} else if lookahead.peek(token::Brace) {
191191
braced!(content in input);
192192
Ok(Self {
193193
ident,
194194
list: Enclosure::Brace {
195-
fields: content.parse_terminated::<_, Token![,]>(BraceItemType::parse)?,
195+
fields: content.parse_terminated(BraceItemType::parse, Token![,])?,
196196
},
197197
})
198198
} else {
@@ -268,9 +268,7 @@ impl<P> MetaAttrList<P> {
268268

269269
impl<P: Parse> Parse for MetaAttrList<P> {
270270
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
271-
let content;
272-
parenthesized!(content in input);
273-
Ok(MetaAttrList(Fields::parse_terminated(&content)?))
271+
Ok(MetaAttrList(Fields::parse_terminated(input)?))
274272
}
275273
}
276274

@@ -458,19 +456,13 @@ mod tests {
458456
try_parse_fail!(ident_type_missing_colon, "expected `:`", IdentTypeMaybeDefault, { foo u8 });
459457
try_parse_fail!(ident_type_missing_ident, "expected identifier", IdentTypeMaybeDefault, { :u8 });
460458

461-
try_parse!(meta_attr_list, MetaAttrListTest, { (1u8, 2u8, 3u8) });
462-
try_parse!(meta_attr_list_empty, MetaAttrListTest, { () });
459+
try_parse!(meta_attr_list, MetaAttrListTest, { 1u8, 2u8, 3u8 });
460+
try_parse!(meta_attr_list_empty, MetaAttrListTest, {});
463461
try_parse_fail!(
464462
meta_attr_list_wrong_type,
465463
"expected literal",
466464
MetaAttrListTest,
467-
{ (i32) }
468-
);
469-
try_parse_fail!(
470-
meta_attr_list_confused_as_list,
471-
"expected parentheses",
472-
MetaAttrListTest,
473-
{ wrong(i32) }
465+
{ i32 }
474466
);
475467

476468
#[test]
@@ -482,7 +474,7 @@ mod tests {
482474
Lit::new(proc_macro2::Literal::u8_suffixed(3)),
483475
];
484476

485-
let value = syn::parse2::<MetaAttrListTest>(quote::quote! { (1u8, 2u8, 3u8) }).unwrap();
477+
let value = syn::parse2::<MetaAttrListTest>(quote::quote! { 1u8, 2u8, 3u8 }).unwrap();
486478
assert_eq!(expected, value.into_iter().collect::<Vec<_>>()[..]);
487479
}
488480
}

binrw_derive/src/named_args/mod.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ pub(crate) fn derive_from_imports(
3939
result_name,
4040
fields: &args.map(Into::into).collect::<Vec<_>>(),
4141
generics: lifetime
42-
.map(|lifetime| [syn::GenericParam::Lifetime(syn::LifetimeDef::new(lifetime))])
42+
.map(|lifetime| {
43+
[syn::GenericParam::Lifetime(syn::LifetimeParam::new(
44+
lifetime,
45+
))]
46+
})
4347
.as_ref()
4448
.map_or(&[], |generics| generics.as_slice()),
4549
vis,
@@ -60,7 +64,7 @@ fn from_input(input: DeriveInput) -> syn::Result<TokenStream> {
6064
.into_iter()
6165
.map(|field| {
6266
let attrs = field.attrs.iter().filter_map(|attr| {
63-
attr.path
67+
attr.path()
6468
.get_ident()
6569
.filter(|ident| *ident == "named_args")
6670
.map(|_| attr.parse_args::<NamedArgAttr>())
@@ -149,9 +153,15 @@ mod kw {
149153
#[cfg_attr(coverage_nightly, coverage(off))]
150154
#[test]
151155
fn derive_named_args_code_coverage_for_tool() {
152-
use runtime_macros_derive::emulate_derive_expansion_fallible;
156+
use runtime_macros::emulate_derive_macro_expansion;
153157
let file = std::fs::File::open("../binrw/tests/named_args.rs").unwrap();
154-
emulate_derive_expansion_fallible(file, "NamedArgs", |input| derive_from_input(input)).unwrap();
158+
emulate_derive_macro_expansion(
159+
file,
160+
&[("NamedArgs", |input| {
161+
derive_from_input(syn::parse2::<syn::DeriveInput>(input).unwrap())
162+
})],
163+
)
164+
.unwrap();
155165
}
156166

157167
#[cfg(test)]
@@ -207,7 +217,7 @@ mod tests {
207217
}
208218
});
209219

210-
try_error!(missing_default_value: "expected expression" {
220+
try_error!(missing_default_value: "unexpected end of input, expected an expression" {
211221
struct Foo<A> {
212222
#[named_args(default = )]
213223
a: A,

0 commit comments

Comments
 (0)