use super::{assert_derive_snapshot, to_deriveinput};
use crate::parse;
macro_rules! assert_parse_snapshot {
( $data:ident, $name:literal) => {
assert_derive_snapshot!(parse::derive, $data, $name)
};
}
#[test]
fn parse_simple_struct() {
let data = to_deriveinput! { struct Foo; };
assert_parse_snapshot!(data, "parse_simple_struct");
}
#[test]
fn parse_struct_with_fields() {
let data = to_deriveinput! {
struct Color {
red: CSSInt,
green: CSSInt,
blue: CSSInt,
}
};
assert_parse_snapshot!(data, "parse_struct_with_fields");
}
#[test]
fn parse_struct_with_lifetime() {
let data = to_deriveinput! {
struct Value<'a> {
content: &'a Ident,
}
};
assert_parse_snapshot!(data, "parse_struct_with_lifetime");
}
#[test]
fn parse_struct_with_single_generic() {
let data = to_deriveinput! {
struct Wrapper<T> {
value: T,
}
};
assert_parse_snapshot!(data, "parse_struct_with_single_generic");
}
#[test]
fn parse_struct_with_multiple_generics() {
let data = to_deriveinput! {
struct Container<T, U> {
first: T,
second: U,
}
};
assert_parse_snapshot!(data, "parse_struct_with_multiple_generics");
}
#[test]
fn parse_struct_with_unused_generic() {
let data = to_deriveinput! {
struct PartialWrapper<T, U> {
used: T,
}
};
assert_parse_snapshot!(data, "parse_struct_with_unused_generic");
}
#[test]
fn parse_tuple_struct_with_generics() {
let data = to_deriveinput! {
struct Pair<T, U>(T, U);
};
assert_parse_snapshot!(data, "parse_tuple_struct_with_generics");
}
#[test]
fn parse_tuple_struct() {
let data = to_deriveinput! {
struct Length(Number, Unit);
};
assert_parse_snapshot!(data, "parse_tuple_struct");
}
#[test]
fn parse_simple_enum() {
let data = to_deriveinput! {
enum Display {
Block(Ident),
Inline(Ident),
None(Ident),
}
};
assert_parse_snapshot!(data, "parse_simple_enum");
}
#[test]
fn parse_enum_with_fields() {
let data = to_deriveinput! {
enum Value {
Keyword(String),
Length(Length),
Percentage(Percentage),
}
};
assert_parse_snapshot!(data, "parse_enum_with_fields");
}
#[test]
fn parse_enum_with_struct_variants() {
let data = to_deriveinput! {
enum BorderStyle {
Solid(Ident),
Dashed { width: Length },
Dotted { radius: Length },
}
};
assert_parse_snapshot!(data, "parse_enum_with_struct_variants");
}
#[test]
fn parse_with_state_attribute() {
let data = to_deriveinput! {
#[parse(state = State::InValue)]
struct ValueInState {
content: String,
}
};
assert_parse_snapshot!(data, "parse_with_state_attribute");
}
#[test]
fn parse_with_stop_kind_attribute() {
let data = to_deriveinput! {
#[parse(stop = Kind::Semicolon)]
struct StopOnSemicolon {
items: Vec<String>,
}
};
assert_parse_snapshot!(data, "parse_with_stop_kind_attribute");
}
#[test]
fn parse_with_stop_kindset_attribute() {
let data = to_deriveinput! {
#[parse(stop = KindSet::BlockEnd)]
struct StopOnBlockEnd {
declarations: Vec<String>,
}
};
assert_parse_snapshot!(data, "parse_with_stop_kindset_attribute");
}
#[test]
fn parse_with_both_state_and_stop() {
let data = to_deriveinput! {
#[parse(state = State::InRule, stop = Kind::RightBrace)]
struct RuleContent {
declarations: Vec<String>,
}
};
assert_parse_snapshot!(data, "parse_with_both_state_and_stop");
}
#[test]
fn parse_enum_with_lifetime() {
let data = to_deriveinput! {
enum CssValue<'a> {
Keyword(&'a String),
Length(Length),
Function { name: &'a String, args: Vec<String> },
}
};
assert_parse_snapshot!(data, "parse_enum_with_lifetime");
}
#[test]
fn parse_unit_struct() {
let data = to_deriveinput! { struct Auto; };
assert_parse_snapshot!(data, "parse_unit_struct");
}
#[test]
fn parse_single_field_tuple_struct() {
let data = to_deriveinput! { struct Opacity(Number); };
assert_parse_snapshot!(data, "parse_single_field_tuple_struct");
}
#[test]
fn parse_struct_with_many_fields() {
let data = to_deriveinput! {
struct Transform {
rotate_x: Angle,
rotate_y: Angle,
rotate_z: Angle,
translate_x: Length,
translate_y: Length,
translate_z: Length,
scale_x: Number,
scale_y: Number,
scale_z: Number,
}
};
assert_parse_snapshot!(data, "parse_struct_with_many_fields");
}
#[test]
fn parse_struct_existing_lifetime() {
let data = to_deriveinput! {
struct Token<'a> {
span: &'a str,
}
};
assert_parse_snapshot!(data, "parse_struct_existing_lifetime");
}
#[test]
fn parse_enum_struct_and_tuple_mixed() {
let data = to_deriveinput! {
enum FlexValue {
Auto(Ident),
Length(Length),
Percentage(Percentage),
Calc { expr: String, unit: Unit },
MinMax { min: Length, max: Length },
}
};
assert_parse_snapshot!(data, "parse_enum_struct_and_tuple_mixed");
}
#[test]
fn parse_enum_nested_generics() {
let data = to_deriveinput! {
enum Container<T> {
Single(T),
Multiple(Vec<T>),
Optional(Option<T>),
}
};
assert_parse_snapshot!(data, "parse_enum_nested_generics");
}
#[test]
fn parse_with_multiple_state_stop_combinations() {
let data = to_deriveinput! {
#[parse(state = State::InDeclaration, stop = KindSet::DeclarationEnd)]
struct Declaration {
property: Ident,
value: CSSValue,
}
};
assert_parse_snapshot!(data, "parse_with_multiple_state_stop_combinations");
}
#[test]
fn parse_struct_with_all_must_occur() {
let data = to_deriveinput! {
#[parse(all_must_occur)]
struct AutoAndLength {
auto: AutoKeyword,
length: Length,
}
};
assert_parse_snapshot!(data, "parse_struct_with_all_must_occur");
}
#[test]
fn parse_struct_with_all_must_occur_and_state() {
let data = to_deriveinput! {
#[parse(all_must_occur, state = State::InValue)]
struct AutoAndLengthInState {
auto: AutoKeyword,
length: Length,
}
};
assert_parse_snapshot!(data, "parse_struct_with_all_must_occur_and_state");
}
#[test]
fn parse_enum_variant_with_all_must_occur() {
let data = to_deriveinput! {
enum Value {
Normal(String),
#[parse(all_must_occur)]
Complex {
auto: AutoKeyword,
length: Length
},
}
};
assert_parse_snapshot!(data, "parse_enum_variant_with_all_must_occur");
}
#[test]
fn parse_struct_with_different_keyword_variants() {
let data = to_deriveinput! {
#[parse(all_must_occur)]
struct SpecificKeywordTest {
#[atom(FooKeywords::Auto)]
auto_field: AutoValue,
#[atom(FooKeywords::None)]
none_field: NoneValue,
length: Length,
}
};
assert_parse_snapshot!(data, "parse_struct_with_different_keyword_variants");
}
#[test]
fn parse_struct_with_optional_keywords() {
let data = to_deriveinput! {
#[parse(one_must_occur)]
struct KeywordWithRange {
#[atom(FooKeywords::Auto)]
auto_value: Option<Ident>,
#[atom(FooKeywords::None)]
none_value: Option<Ident>,
}
};
assert_parse_snapshot!(data, "parse_struct_with_optional_keywords");
}
#[test]
fn parse_struct_regular_with_keyword_pattern() {
let data = to_deriveinput! {
struct RegularKeywordTest {
#[atom(FooKeywords::Auto)]
auto_value: AutoValue,
length: Length,
}
};
assert_parse_snapshot!(data, "parse_struct_regular_with_keyword_pattern");
}
#[test]
fn parse_enum_variant_with_keyword_pattern() {
let data = to_deriveinput! {
enum TestEnum {
Normal(String),
WithKeyword {
#[atom(FooKeywords::None)]
none_value: NoneValue,
other_field: Length,
},
}
};
assert_parse_snapshot!(data, "parse_enum_variant_with_keyword_pattern");
}
#[test]
fn parse_enum_variant_all_must_occur_with_keyword() {
let data = to_deriveinput! {
enum AllMustOccurEnum {
Simple(String),
#[parse(all_must_occur)]
Complex {
#[atom(FooKeywords::Auto)]
auto_field: AutoValue,
#[atom(FooKeywords::None)]
none_field: NoneValue,
length: Length,
},
}
};
assert_parse_snapshot!(data, "parse_enum_variant_all_must_occur_with_keyword");
}
#[test]
fn parse_struct_with_newtype_keyword() {
let data = to_deriveinput! {
struct NewtypeKeywordTest {
#[atom(Auto)]
auto_value: Auto,
length: Length,
}
};
assert_parse_snapshot!(data, "parse_struct_with_newtype_keyword");
}
#[test]
fn parse_struct_all_must_occur_with_newtype_keyword() {
let data = to_deriveinput! {
#[parse(all_must_occur)]
struct AllMustOccurNewtypeTest {
#[atom(Auto)]
auto_value: Auto,
#[atom(None)]
none_value: None,
length: Length,
}
};
assert_parse_snapshot!(data, "parse_struct_all_must_occur_with_newtype_keyword");
}
#[test]
fn parse_struct_one_must_occur_with_optionals() {
let data = to_deriveinput! {
#[parse(one_must_occur)]
struct OneMustOccurTest {
foo: Option<Foo>,
bar: Option<Bar>,
}
};
assert_parse_snapshot!(data, "parse_struct_one_must_occur_with_optionals");
}
#[test]
fn parse_enum_variant_with_keyword_variants() {
let data = to_deriveinput! {
enum NewtypeEnum {
#[atom(Keyword::Foo)]
Foo(Ident),
#[atom(Keyword::Bar)]
Bar(Ident),
}
};
assert_parse_snapshot!(data, "parse_enum_variant_with_keyword_variants");
}
#[test]
fn parse_enum_variant_with_keyword_variants_or_type() {
let data = to_deriveinput! {
enum NewtypeEnum {
Length(Length),
#[atom(Keyword::Foo)]
Foo(Ident),
#[atom(Keyword::Bar)]
Bar(Ident),
}
};
assert_parse_snapshot!(data, "parse_enum_variant_with_keyword_variants_or_type");
}
#[test]
fn parse_enum_struct_variant_one_must_occur() {
let data = to_deriveinput! {
enum FlexWrap {
#[atom(FooAtoms::Nowrap)]
Nowrap(Ident),
#[parse(one_must_occur)]
Wrap {
#[atom(FooAtoms::Wrap)]
wrap: Option<Ident>,
#[atom(FooAtoms::Balance)]
balance: Option<Ident>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_struct_variant_one_must_occur");
}
#[test]
fn parse_enum_struct_variants_one_must_occur_siblings() {
let data = to_deriveinput! {
enum FlexWrap {
#[atom(FooAtoms::Nowrap)]
Nowrap(Ident),
#[parse(one_must_occur)]
Wrap {
#[atom(FooAtoms::Wrap)]
wrap: Option<Ident>,
#[atom(FooAtoms::Balance)]
balance: Option<Ident>,
},
#[parse(one_must_occur)]
WrapReverse {
#[atom(FooAtoms::WrapReverse)]
wrap_reverse: Option<Ident>,
#[atom(FooAtoms::Balance)]
balance: Option<Ident>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_struct_variants_one_must_occur_siblings");
}
#[test]
fn parse_enum_variant_discriminated_by_second_field_atom() {
let data = to_deriveinput! {
enum FlowInto {
#[atom(Atoms::None)]
None(Ident),
WithElement(CustomIdent, #[atom(Atoms::Element)] Ident),
WithContent(CustomIdent, #[atom(Atoms::Content)] Ident),
Bare(CustomIdent),
}
};
assert_parse_snapshot!(data, "parse_enum_variant_discriminated_by_second_field_atom");
}
#[test]
fn parse_struct_all_must_occur_with_optional_fields() {
let data = to_deriveinput! {
#[parse(all_must_occur)]
struct StableWithOptionalEdges {
#[atom(CssAtomSet::Stable)]
stable: Ident,
#[atom(CssAtomSet::BothEdges)]
both_edges: Option<Ident>,
}
};
assert_parse_snapshot!(data, "parse_struct_all_must_occur_with_optional_fields");
}
#[test]
fn parse_enum_variant_all_must_occur_with_optional_fields() {
let data = to_deriveinput! {
enum ScrollbarGutter {
#[atom(CssAtomSet::Auto)]
Auto(Ident),
#[parse(all_must_occur)]
Stable {
#[atom(CssAtomSet::Stable)]
stable: Ident,
#[atom(CssAtomSet::BothEdges)]
both_edges: Option<Ident>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_variant_all_must_occur_with_optional_fields");
}
#[test]
fn parse_sequential_optional_keyword() {
let data = to_deriveinput! {
struct AxisWithOptionalSnap(
#[atom(CssAtomSet::X)]
Ident,
#[atom(CssAtomSet::Mandatory)]
Option<Ident>,
);
};
assert_parse_snapshot!(data, "parse_sequential_optional_keyword");
}
#[test]
fn parse_enum_one_must_occur_variant_mixed_atom_and_type_fields() {
let data = to_deriveinput! {
enum VerticalAlign {
#[parse(one_must_occur)]
First {
#[atom(CssAtomSet::First)]
first: Option<Ident>,
alignment_baseline: Option<AlignmentBaseline>,
baseline_shift: Option<BaselineShift>,
},
#[parse(one_must_occur)]
Last {
#[atom(CssAtomSet::Last)]
last: Option<Ident>,
alignment_baseline: Option<AlignmentBaseline>,
baseline_shift: Option<BaselineShift>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_one_must_occur_variant_mixed_atom_and_type_fields");
}
#[test]
fn parse_enum_one_must_occur_siblings_no_shared_atoms() {
let data = to_deriveinput! {
enum MarginTrim {
#[atom(FooAtoms::None)]
None(Ident),
#[parse(one_must_occur)]
BlockInline {
#[atom(FooAtoms::Block)]
block: Option<Ident>,
#[atom(FooAtoms::Inline)]
inline: Option<Ident>,
},
#[parse(one_must_occur)]
BlockStartBlockEnd {
#[atom(FooAtoms::BlockStart)]
block_start: Option<Ident>,
#[atom(FooAtoms::BlockEnd)]
block_end: Option<Ident>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_one_must_occur_siblings_no_shared_atoms");
}
#[test]
fn parse_enum_all_must_occur_overlapping_lead_atoms() {
let data = to_deriveinput! {
enum Foo {
#[parse(all_must_occur)]
WrapA {
#[atom(FooAtoms::Wrap)]
wrap: Option<Ident>,
#[atom(FooAtoms::A)]
a: Option<Ident>,
},
#[parse(all_must_occur)]
WrapB {
#[atom(FooAtoms::Wrap)]
wrap: Option<Ident>,
#[atom(FooAtoms::B)]
b: Option<Ident>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_all_must_occur_overlapping_lead_atoms");
}
#[test]
fn parse_enum_one_must_occur_non_ident_atom_field() {
let data = to_deriveinput! {
enum VoiceVolume {
#[parse(one_must_occur)]
Soft {
#[atom(FooAtoms::Soft)]
soft: Option<Ident>,
#[atom(FooAtoms::Db)]
decibel: Option<Decibel>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_one_must_occur_non_ident_atom_field");
}
#[test]
fn parse_enum_all_must_occur_non_atom_only_input() {
let data = to_deriveinput! {
enum Foo {
#[atom(FooAtoms::None)]
None(Ident),
#[parse(all_must_occur)]
Valued {
#[atom(FooAtoms::Auto)]
auto: Option<Ident>,
length: Option<Length>,
},
}
};
assert_parse_snapshot!(data, "parse_enum_all_must_occur_non_atom_only_input");
}