rustfmt wire_format_derive and poll_token_derive

BUG=None
TEST=cargo test

Change-Id: I62f00a71ed3693352de648bb8ee576335b32019f
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1273688
Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
Daniel Verkamp 2018-10-10 09:59:55 -07:00 committed by chrome-bot
parent f5d565d693
commit 310b308166
3 changed files with 174 additions and 159 deletions

View file

@ -8,8 +8,8 @@
#![recursion_limit = "256"] #![recursion_limit = "256"]
extern crate proc_macro2;
extern crate proc_macro; extern crate proc_macro;
extern crate proc_macro2;
#[macro_use] #[macro_use]
extern crate quote; extern crate quote;
@ -20,8 +20,8 @@ extern crate syn;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro2::Span; use proc_macro2::Span;
use quote::Tokens; use quote::Tokens;
use syn::{Data, DeriveInput, Fields, Ident};
use syn::spanned::Spanned; use syn::spanned::Spanned;
use syn::{Data, DeriveInput, Fields, Ident};
/// The function that derives the actual implementation. /// The function that derives the actual implementation.
#[proc_macro_derive(P9WireFormat)] #[proc_macro_derive(P9WireFormat)]

View file

@ -207,7 +207,6 @@ impl ParseState {
Tokenized::Enum => States::Ident, Tokenized::Enum => States::Ident,
Tokenized::Visiblity => States::Start, Tokenized::Visiblity => States::Start,
_ => panic!("derives for enum types only"), _ => panic!("derives for enum types only"),
}; };
} }
@ -237,9 +236,9 @@ impl ParseState {
self.current_state = match tok { self.current_state = match tok {
Tokenized::Ident(ident) => { Tokenized::Ident(ident) => {
let mut variant = Some(EnumVariant { let mut variant = Some(EnumVariant {
name: ident, name: ident,
data: None, data: None,
}); });
mem::swap(&mut variant, &mut self.current_variant); mem::swap(&mut variant, &mut self.current_variant);
if let Some(variant) = variant { if let Some(variant) = variant {
self.model.variants.push(variant); self.model.variants.push(variant);
@ -247,14 +246,11 @@ impl ParseState {
States::VariantIdent States::VariantIdent
} }
Tokenized::IdentAndType(ident, type_) => { Tokenized::IdentAndType(ident, type_) => {
let variant_data = EnumVariantData { let variant_data = EnumVariantData { type_, name: None };
type_: type_,
name: None,
};
let mut variant = Some(EnumVariant { let mut variant = Some(EnumVariant {
name: ident, name: ident,
data: Some(variant_data), data: Some(variant_data),
}); });
mem::swap(&mut variant, &mut self.current_variant); mem::swap(&mut variant, &mut self.current_variant);
if let Some(variant) = variant { if let Some(variant) = variant {
self.model.variants.push(variant); self.model.variants.push(variant);
@ -278,12 +274,14 @@ impl ParseState {
let variant = self.current_variant.as_mut().unwrap(); let variant = self.current_variant.as_mut().unwrap();
self.current_state = match tok { self.current_state = match tok {
Tokenized::FieldIdent(ident) => { Tokenized::FieldIdent(ident) => {
assert!(variant.data.is_none(), assert!(
"enum variant can only have one field"); variant.data.is_none(),
"enum variant can only have one field"
);
variant.data = Some(EnumVariantData { variant.data = Some(EnumVariantData {
type_: "".to_owned(), type_: "".to_owned(),
name: Some(ident), name: Some(ident),
}); });
States::VariantDataType States::VariantDataType
} }
Tokenized::CloseBrace => States::VariantIdent, Tokenized::CloseBrace => States::VariantIdent,
@ -339,9 +337,10 @@ impl EnumModel {
// The capture string is for everything between the variant identifier and the `=>` in // The capture string is for everything between the variant identifier and the `=>` in
// the match arm: the variant's data capture. // the match arm: the variant's data capture.
let capture = match variant.data.as_ref() { let capture = match variant.data.as_ref() {
Some(&EnumVariantData { name: Some(ref name), .. }) => { Some(&EnumVariantData {
format!("{{ {}: data }}", name) name: Some(ref name),
} ..
}) => format!("{{ {}: data }}", name),
Some(&EnumVariantData { .. }) => "(data)".to_owned(), Some(&EnumVariantData { .. }) => "(data)".to_owned(),
None => "".to_owned(), None => "".to_owned(),
}; };
@ -355,14 +354,11 @@ impl EnumModel {
}; };
// Assembly of the match arm. // Assembly of the match arm.
write!(match_statement, write!(
"{}::{}{} => {}{},\n", match_statement,
self.name, "{}::{}{} => {}{},\n",
variant.name, self.name, variant.name, capture, index, modifer
capture, ).unwrap();
index,
modifer)
.unwrap();
} }
match_statement.push_str("}"); match_statement.push_str("}");
match_statement match_statement
@ -382,24 +378,22 @@ impl EnumModel {
// data, which includes both variant index and data bits. // data, which includes both variant index and data bits.
let data = match variant.data.as_ref() { let data = match variant.data.as_ref() {
Some(&EnumVariantData { Some(&EnumVariantData {
name: Some(ref name), name: Some(ref name),
ref type_, ref type_,
}) => format!("{{ {}: (data >> {}) as {} }}", name, variant_bits, type_), }) => format!("{{ {}: (data >> {}) as {} }}", name, variant_bits, type_),
Some(&EnumVariantData { Some(&EnumVariantData {
name: None, name: None,
ref type_, ref type_,
}) => format!("((data >> {}) as {})", variant_bits, type_), }) => format!("((data >> {}) as {})", variant_bits, type_),
None => "".to_owned(), None => "".to_owned(),
}; };
// Assembly of the match arm. // Assembly of the match arm.
write!(match_statement, write!(
"{} => {}::{}{},\n", match_statement,
index, "{} => {}::{}{},\n",
self.name, index, self.name, variant.name, data
variant.name, ).unwrap();
data)
.unwrap();
} }
match_statement.push_str("_ => unreachable!()\n}"); match_statement.push_str("_ => unreachable!()\n}");
match_statement match_statement
@ -419,9 +413,11 @@ fn poll_token_inner(src: &str) -> String {
state.handle_token(tok); state.handle_token(tok);
} }
assert_eq!(state.current_state, assert_eq!(
States::End, state.current_state,
"unexpected end after parsing source enum"); States::End,
"unexpected end after parsing source enum"
);
// Given our basic model of a user given enum that is suitable as a token, we generate the // Given our basic model of a user given enum that is suitable as a token, we generate the
// implementation. The implementation is NOT always well formed, such as when a variant's data // implementation. The implementation is NOT always well formed, such as when a variant's data
@ -429,7 +425,8 @@ fn poll_token_inner(src: &str) -> String {
// would be difficult to detect every kind of error. Importantly, every implementation that we // would be difficult to detect every kind of error. Importantly, every implementation that we
// generate here and goes on to compile succesfully is sound. // generate here and goes on to compile succesfully is sound.
let model = state.model; let model = state.model;
format!("impl PollToken for {} {{ format!(
"impl PollToken for {} {{
fn as_raw_token(&self) -> u64 {{ fn as_raw_token(&self) -> u64 {{
{} {}
}} }}
@ -438,9 +435,10 @@ fn poll_token_inner(src: &str) -> String {
{} {}
}} }}
}}", }}",
model.name, model.name,
model.generate_as_raw_token(), model.generate_as_raw_token(),
model.generate_from_raw_token()) model.generate_from_raw_token()
)
} }
/// Implements the PollToken trait for a given `enum`. /// Implements the PollToken trait for a given `enum`.

View file

@ -21,27 +21,34 @@ mod tokenized {
#[test] #[test]
fn ident() { fn ident() {
assert_eq!(Tokenized::from_str("Important"), assert_eq!(
Ident("Important".to_owned())); Tokenized::from_str("Important"),
Ident("Important".to_owned())
);
assert_eq!(Tokenized::from_str("hello,"), Ident("hello".to_owned())); assert_eq!(Tokenized::from_str("hello,"), Ident("hello".to_owned()));
assert_eq!(Tokenized::from_str("world2"), Ident("world2".to_owned())); assert_eq!(Tokenized::from_str("world2"), Ident("world2".to_owned()));
assert_eq!(Tokenized::from_str("A,"), Ident("A".to_owned())); assert_eq!(Tokenized::from_str("A,"), Ident("A".to_owned()));
} }
#[test] #[test]
fn field_ident() { fn field_ident() {
assert_eq!(Tokenized::from_str("index:"), assert_eq!(
FieldIdent("index".to_owned())); Tokenized::from_str("index:"),
FieldIdent("index".to_owned())
);
assert_eq!(Tokenized::from_str("a:"), FieldIdent("a".to_owned())); assert_eq!(Tokenized::from_str("a:"), FieldIdent("a".to_owned()));
} }
#[test] #[test]
fn ident_and_type() { fn ident_and_type() {
assert_eq!(Tokenized::from_str("a(u32)"), assert_eq!(
IdentAndType("a".to_owned(), "u32".to_owned())); Tokenized::from_str("a(u32)"),
assert_eq!(Tokenized::from_str("Socket(usize),"), IdentAndType("a".to_owned(), "u32".to_owned())
IdentAndType("Socket".to_owned(), "usize".to_owned())); );
assert_eq!(
Tokenized::from_str("Socket(usize),"),
IdentAndType("Socket".to_owned(), "usize".to_owned())
);
} }
#[test] #[test]
@ -63,27 +70,31 @@ mod tokenized {
} }
mod parse_state { mod parse_state {
use {Tokenized, States, ParseState, EnumModel, EnumVariant, EnumVariantData};
use Tokenized::*; use Tokenized::*;
use {EnumModel, EnumVariant, EnumVariantData, ParseState, States, Tokenized};
fn parse_tokens(tokens: &[Tokenized]) -> EnumModel { fn parse_tokens(tokens: &[Tokenized]) -> EnumModel {
let mut state = ParseState::new(); let mut state = ParseState::new();
for token in tokens { for token in tokens {
state.handle_token(token.clone()); state.handle_token(token.clone());
} }
assert_eq!(state.current_state, assert_eq!(
States::End, state.current_state,
"unexpected end after parsing source enum"); States::End,
"unexpected end after parsing source enum"
);
state.model state.model
} }
#[test] #[test]
fn empty_struct() { fn empty_struct() {
let model = parse_tokens(&[Visiblity, let model = parse_tokens(&[
Enum, Visiblity,
Ident("Blarg".to_owned()), Enum,
OpenBrace, Ident("Blarg".to_owned()),
CloseBrace]); OpenBrace,
CloseBrace,
]);
let expected = EnumModel { let expected = EnumModel {
name: "Blarg".to_string(), name: "Blarg".to_string(),
variants: Vec::new(), variants: Vec::new(),
@ -94,94 +105,106 @@ mod parse_state {
#[test] #[test]
#[should_panic] #[should_panic]
fn invalid_token() { fn invalid_token() {
parse_tokens(&[Visiblity, parse_tokens(&[
Enum, Visiblity,
Ident("Blarg".to_owned()), Enum,
OpenBrace, Ident("Blarg".to_owned()),
CloseBrace, OpenBrace,
CloseBrace]); CloseBrace,
CloseBrace,
]);
} }
#[test] #[test]
fn only_unit_variants() { fn only_unit_variants() {
let model = parse_tokens(&[Enum, let model = parse_tokens(&[
Ident("Foo".to_owned()), Enum,
OpenBrace, Ident("Foo".to_owned()),
Ident("A".to_owned()), OpenBrace,
Ident("B".to_owned()), Ident("A".to_owned()),
Ident("C".to_owned()), Ident("B".to_owned()),
CloseBrace]); Ident("C".to_owned()),
CloseBrace,
]);
let expected = EnumModel { let expected = EnumModel {
name: "Foo".to_string(), name: "Foo".to_string(),
variants: vec![EnumVariant { variants: vec![
name: "A".to_owned(), EnumVariant {
data: None, name: "A".to_owned(),
}, data: None,
EnumVariant { },
name: "B".to_owned(), EnumVariant {
data: None, name: "B".to_owned(),
}, data: None,
EnumVariant { },
name: "C".to_owned(), EnumVariant {
data: None, name: "C".to_owned(),
}], data: None,
},
],
}; };
assert_eq!(model, expected); assert_eq!(model, expected);
} }
#[test] #[test]
fn unnamed_data() { fn unnamed_data() {
let model = parse_tokens(&[Enum, let model = parse_tokens(&[
Ident("Foo".to_owned()), Enum,
OpenBrace, Ident("Foo".to_owned()),
IdentAndType("A".to_owned(), "u32".to_owned()), OpenBrace,
Ident("B".to_owned()), IdentAndType("A".to_owned(), "u32".to_owned()),
IdentAndType("C".to_owned(), "usize".to_owned()), Ident("B".to_owned()),
CloseBrace]); IdentAndType("C".to_owned(), "usize".to_owned()),
CloseBrace,
]);
let expected = EnumModel { let expected = EnumModel {
name: "Foo".to_string(), name: "Foo".to_string(),
variants: vec![EnumVariant { variants: vec![
name: "A".to_owned(), EnumVariant {
data: Some(EnumVariantData { name: "A".to_owned(),
name: None, data: Some(EnumVariantData {
type_: "u32".to_owned(), name: None,
}), type_: "u32".to_owned(),
}, }),
EnumVariant { },
name: "B".to_owned(), EnumVariant {
data: None, name: "B".to_owned(),
}, data: None,
EnumVariant { },
name: "C".to_owned(), EnumVariant {
data: Some(EnumVariantData { name: "C".to_owned(),
name: None, data: Some(EnumVariantData {
type_: "usize".to_owned(), name: None,
}), type_: "usize".to_owned(),
}], }),
},
],
}; };
assert_eq!(model, expected); assert_eq!(model, expected);
} }
#[test] #[test]
fn named_data() { fn named_data() {
let model = parse_tokens(&[Enum, let model = parse_tokens(&[
Ident("Foo".to_owned()), Enum,
OpenBrace, Ident("Foo".to_owned()),
Ident("A".to_owned()), OpenBrace,
OpenBrace, Ident("A".to_owned()),
FieldIdent("index".to_owned()), OpenBrace,
Ident("u16".to_owned()), FieldIdent("index".to_owned()),
CloseBrace, Ident("u16".to_owned()),
CloseBrace]); CloseBrace,
CloseBrace,
]);
let expected = EnumModel { let expected = EnumModel {
name: "Foo".to_string(), name: "Foo".to_string(),
variants: vec![EnumVariant { variants: vec![EnumVariant {
name: "A".to_owned(), name: "A".to_owned(),
data: Some(EnumVariantData { data: Some(EnumVariantData {
name: Some("index".to_owned()), name: Some("index".to_owned()),
type_: "u16".to_owned(), type_: "u16".to_owned(),
}), }),
}], }],
}; };
assert_eq!(model, expected); assert_eq!(model, expected);
} }
@ -195,40 +218,34 @@ mod enum_model {
let mut model = EnumModel { let mut model = EnumModel {
name: "Baz".to_string(), name: "Baz".to_string(),
variants: vec![EnumVariant { variants: vec![EnumVariant {
name: "A".to_owned(), name: "A".to_owned(),
data: None, data: None,
}], }],
}; };
assert_eq!(model.variant_bits(), 0); assert_eq!(model.variant_bits(), 0);
model.variants.append( model.variants.append(&mut vec![
&mut vec![ EnumVariant {
EnumVariant { name: "B".to_owned(),
name: "B".to_owned(), data: None,
data: None, },
}, EnumVariant {
EnumVariant { name: "C".to_owned(),
name: "C".to_owned(), data: None,
data: None, },
} ]);
]
);
assert_eq!(model.variant_bits(), 2); assert_eq!(model.variant_bits(), 2);
for _ in 0..1021 { for _ in 0..1021 {
model model.variants.push(EnumVariant {
.variants name: "Dynamic".to_owned(),
.push(EnumVariant { data: None,
name: "Dynamic".to_owned(), });
data: None,
});
} }
assert_eq!(model.variant_bits(), 10); assert_eq!(model.variant_bits(), 10);
model model.variants.push(EnumVariant {
.variants name: "OneMore".to_owned(),
.push(EnumVariant { data: None,
name: "OneMore".to_owned(), });
data: None,
});
assert_eq!(model.variant_bits(), 11); assert_eq!(model.variant_bits(), 11);
} }
} }