From 554008d01e8548aa1025b21475423c5077001192 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Wed, 21 Feb 2024 11:56:18 +0900 Subject: [PATCH] refactor: introduce a container for punctuation Many elements in Mabo schema files use some form of punctuation to separate from another. This common logic could be centralized in a custom container that keeps track of punctuation spans and takes care of formatting logic. This adds missing tracking of token spans that haven't be tracked before yet. --- crates/mabo-compiler/src/resolve/mod.rs | 48 +- crates/mabo-compiler/src/simplify.rs | 18 +- crates/mabo-compiler/src/validate/generics.rs | 50 +- crates/mabo-compiler/src/validate/ids.rs | 6 +- crates/mabo-compiler/src/validate/names.rs | 4 +- crates/mabo-compiler/src/validate/tuples.rs | 28 +- ...error_validate@alias_tuple_empty.mabo.snap | 14 - ..._validate@enum_named_tuple_empty.mabo.snap | 19 - ...alidate@enum_unnamed_tuple_empty.mabo.snap | 17 - ...alidate@struct_named_tuple_empty.mabo.snap | 16 - ...idate@struct_unnamed_tuple_empty.mabo.snap | 14 - .../mabo-lsp/src/handlers/document_symbols.rs | 6 +- .../mabo-lsp/src/handlers/semantic_tokens.rs | 47 +- crates/mabo-parser/src/lib.rs | 132 +- crates/mabo-parser/src/parser.rs | 59 +- crates/mabo-parser/src/parser/aliases.rs | 2 +- crates/mabo-parser/src/parser/enums.rs | 23 +- crates/mabo-parser/src/parser/fields.rs | 45 +- crates/mabo-parser/src/parser/generics.rs | 39 +- crates/mabo-parser/src/parser/structs.rs | 2 +- crates/mabo-parser/src/parser/types.rs | 30 +- crates/mabo-parser/src/punctuated.rs | 157 ++ .../inputs/invalid}/alias_tuple_empty.mabo | 0 .../invalid}/enum_named_tuple_empty.mabo | 0 .../invalid}/enum_unnamed_tuple_empty.mabo | 0 .../invalid}/struct_named_tuple_empty.mabo | 0 .../invalid}/struct_unnamed_tuple_empty.mabo | 0 .../parser__error@alias_tuple_empty.mabo.snap | 42 + ...er__error@enum_named_tuple_empty.mabo.snap | 65 + ...__error@enum_unnamed_tuple_empty.mabo.snap | 65 + ...__error@struct_named_tuple_empty.mabo.snap | 63 + ...error@struct_unnamed_tuple_empty.mabo.snap | 57 + .../parser__parse@alias_basic.mabo.snap | 4 +- .../parser__parse@attribute_multi.mabo.snap | 4 +- .../parser__parse@attribute_single.mabo.snap | 4 +- .../parser__parse@attribute_unit.mabo.snap | 4 +- .../parser__parse@attributes.mabo.snap | 4 +- .../parser__parse@attributes_min_ws.mabo.snap | 4 +- .../parser__parse@enum_basic.mabo.snap | 252 ++-- .../parser__parse@enum_generics.mabo.snap | 337 +++-- .../parser__parse@enum_many_ws.mabo.snap | 238 +-- .../parser__parse@enum_min_ws.mabo.snap | 337 ++--- .../snapshots/parser__parse@mixed.mabo.snap | 1271 +++++++++-------- .../parser__parse@module_basic.mabo.snap | 137 +- .../parser__parse@optional_ids.mabo.snap | 418 +++--- .../parser__parse@schema_basic.mabo.snap | 318 +++-- .../parser__parse@struct_basic.mabo.snap | 86 +- .../parser__parse@struct_generics.mabo.snap | 131 +- .../parser__parse@struct_many_ws.mabo.snap | 139 +- .../parser__parse@struct_min_ws.mabo.snap | 139 +- .../parser__parse@struct_tuple.mabo.snap | 52 +- .../parser__parse@types_basic.mabo.snap | 769 +++++----- .../parser__parse@types_generic.mabo.snap | 372 ++--- .../parser__parse@types_nested.mabo.snap | 77 +- .../parser__parse@types_non_zero.mabo.snap | 632 ++++---- .../parser__parse@types_ref.mabo.snap | 306 ++-- 56 files changed, 3908 insertions(+), 3195 deletions(-) delete mode 100644 crates/mabo-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.mabo.snap delete mode 100644 crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.mabo.snap delete mode 100644 crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.mabo.snap delete mode 100644 crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.mabo.snap delete mode 100644 crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.mabo.snap create mode 100644 crates/mabo-parser/src/punctuated.rs rename crates/{mabo-compiler/tests/inputs/validate => mabo-parser/tests/inputs/invalid}/alias_tuple_empty.mabo (100%) rename crates/{mabo-compiler/tests/inputs/validate => mabo-parser/tests/inputs/invalid}/enum_named_tuple_empty.mabo (100%) rename crates/{mabo-compiler/tests/inputs/validate => mabo-parser/tests/inputs/invalid}/enum_unnamed_tuple_empty.mabo (100%) rename crates/{mabo-compiler/tests/inputs/validate => mabo-parser/tests/inputs/invalid}/struct_named_tuple_empty.mabo (100%) rename crates/{mabo-compiler/tests/inputs/validate => mabo-parser/tests/inputs/invalid}/struct_unnamed_tuple_empty.mabo (100%) create mode 100644 crates/mabo-parser/tests/snapshots/parser__error@alias_tuple_empty.mabo.snap create mode 100644 crates/mabo-parser/tests/snapshots/parser__error@enum_named_tuple_empty.mabo.snap create mode 100644 crates/mabo-parser/tests/snapshots/parser__error@enum_unnamed_tuple_empty.mabo.snap create mode 100644 crates/mabo-parser/tests/snapshots/parser__error@struct_named_tuple_empty.mabo.snap create mode 100644 crates/mabo-parser/tests/snapshots/parser__error@struct_unnamed_tuple_empty.mabo.snap diff --git a/crates/mabo-compiler/src/resolve/mod.rs b/crates/mabo-compiler/src/resolve/mod.rs index 7043d51..c30756a 100644 --- a/crates/mabo-compiler/src/resolve/mod.rs +++ b/crates/mabo-compiler/src/resolve/mod.rs @@ -2,7 +2,8 @@ //! correct. use mabo_parser::{ - DataType, Definition, ExternalType, Fields, Generics, Import, Name, Schema, Spanned, Type, + punctuated::Punctuated, DataType, Definition, ExternalType, Fields, Generics, Import, Name, + Schema, Spanned, Type, }; use miette::NamedSource; use rustc_hash::FxHashMap; @@ -153,11 +154,11 @@ impl Module<'_> { match definition.kind { DeclarationKind::Struct { generics } | DeclarationKind::Enum { generics } - if generics != ty.generics.len() => + if generics != ty.generics.as_ref().map_or(0, Punctuated::len) => { Err(GenericsCount { definition: generics, - usage: ty.generics.len(), + usage: ty.generics.as_ref().map_or(0, Punctuated::len), declared: definition.name.span().into(), used: ty.name.span().into(), } @@ -256,10 +257,10 @@ impl Module<'_> { match definition.kind { DeclarationKind::Struct { generics } | DeclarationKind::Enum { generics } - if generics != ty.generics.len() => + if generics != ty.generics.as_ref().map_or(0, Punctuated::len) => { Err(RemoteGenericsCount { - amount: ty.generics.len(), + amount: ty.generics.as_ref().map_or(0, Punctuated::len), used: ty.name.span().into(), declaration: [RemoteGenericsCountDeclaration { amount: generics, @@ -321,19 +322,18 @@ pub(crate) fn resolve_module_types<'a>( module: &'a Module<'_>, missing: &mut Vec>, ) { - fn is_generic(external: &ExternalType<'_>, generics: &Generics<'_>) -> bool { - external.generics.is_empty() + fn is_generic(external: &ExternalType<'_>, generics: &Option>) -> bool { + external.generics.is_none() && external.path.is_empty() - && generics - .0 - .iter() - .any(|gen| gen.get() == external.name.get()) + && generics.as_ref().map_or(false, |g| { + g.types.values().any(|gen| gen.get() == external.name.get()) + }) } fn resolve<'a>( missing: &mut Vec>, ty: &'a Type<'_>, - generics: &Generics<'_>, + generics: &Option>, module: &'a Module<'_>, ) { visit_externals(ty, &mut |external| { @@ -348,17 +348,17 @@ pub(crate) fn resolve_module_types<'a>( fn resolve_fields<'a>( missing: &mut Vec>, fields: &'a Fields<'_>, - generics: &Generics<'_>, + generics: &Option>, module: &'a Module<'_>, ) { match fields { Fields::Named(_, named) => { - for field in named { + for field in named.values() { resolve(missing, &field.ty, generics, module); } } Fields::Unnamed(_, unnamed) => { - for field in unnamed { + for field in unnamed.values() { resolve(missing, &field.ty, generics, module); } } @@ -370,7 +370,7 @@ pub(crate) fn resolve_module_types<'a>( match def { Definition::Struct(s) => resolve_fields(missing, &s.fields, &s.generics, module), Definition::Enum(e) => { - for variant in &e.variants { + for variant in e.variants.values() { resolve_fields(missing, &variant.fields, &e.generics, module); } } @@ -424,13 +424,13 @@ fn visit_module_tree<'a>( } Definition::Struct(s) => module.types.push(Declaration { kind: DeclarationKind::Struct { - generics: s.generics.0.len(), + generics: s.generics.as_ref().map_or(0, |g| g.types.len()), }, name: s.name.clone(), }), Definition::Enum(e) => module.types.push(Declaration { kind: DeclarationKind::Enum { - generics: e.generics.0.len(), + generics: e.generics.as_ref().map_or(0, |g| g.types.len()), }, name: e.name.clone(), }), @@ -484,15 +484,17 @@ fn visit_externals<'a>(value: &'a Type<'_>, visit: &mut impl FnMut(&'a ExternalT visit_externals(value, visit); } DataType::Tuple { types, .. } => { - for ty in types { + for ty in types.values() { visit_externals(ty, visit); } } DataType::External(ty) => { visit(ty); - for ty in &ty.generics { - visit_externals(ty, visit); + if let Some(generics) = &ty.generics { + for ty in generics.values() { + visit_externals(ty, visit); + } } } } @@ -564,12 +566,12 @@ pub(crate) fn resolve_type_remotely( }); if let Some((schema, name, generics)) = found { - if generics == ty.external.generics.len() { + if generics == ty.external.generics.as_ref().map_or(0, Punctuated::len) { return Ok(()); } return Err(ResolveRemote::GenericsCount(RemoteGenericsCount { - amount: ty.external.generics.len(), + amount: ty.external.generics.as_ref().map_or(0, Punctuated::len), used: ty.external.name.span().into(), declaration: [RemoteGenericsCountDeclaration { amount: generics, diff --git a/crates/mabo-compiler/src/simplify.rs b/crates/mabo-compiler/src/simplify.rs index f6d27c9..7b8050e 100644 --- a/crates/mabo-compiler/src/simplify.rs +++ b/crates/mabo-compiler/src/simplify.rs @@ -311,8 +311,10 @@ fn comment<'a>(item: &'a mabo_parser::Comment<'_>) -> Box<[&'a str]> { } #[inline] -fn generics<'a>(item: &'a mabo_parser::Generics<'_>) -> Box<[&'a str]> { - item.0.iter().map(mabo_parser::Name::get).collect() +fn generics<'a>(item: &'a Option>) -> Box<[&'a str]> { + item.as_ref().map_or(Box::default(), |g| { + g.types.values().map(mabo_parser::Name::get).collect() + }) } #[inline] @@ -360,7 +362,7 @@ fn simplify_enum<'a>(item: &'a mabo_parser::Enum<'_>) -> Enum<'a> { generics: generics(&item.generics), variants: item .variants - .iter() + .values() .map(|variant| simplify_variant(variant, &mut id_gen)) .collect(), } @@ -386,7 +388,7 @@ fn simplify_fields<'a>(item: &'a mabo_parser::Fields<'_>) -> Fields<'a> { mabo_parser::Fields::Named(_, named) => Fields { source: item, fields: named - .iter() + .values() .map(|field| Field { source: ParserField::Named(field), comment: comment(&field.comment), @@ -400,7 +402,7 @@ fn simplify_fields<'a>(item: &'a mabo_parser::Fields<'_>) -> Fields<'a> { mabo_parser::Fields::Unnamed(_, unnamed) => Fields { source: item, fields: unnamed - .iter() + .values() .enumerate() .map(|(i, field)| Field { source: ParserField::Unnamed(field), @@ -449,7 +451,7 @@ fn simplify_type<'a>(item: &'a mabo_parser::Type<'_>) -> Type<'a> { mabo_parser::DataType::BoxString => Type::BoxString, mabo_parser::DataType::BoxBytes => Type::BoxBytes, mabo_parser::DataType::Tuple { ref types, .. } => { - Type::Tuple(types.iter().map(|ty| simplify_type(ty)).collect()) + Type::Tuple(types.values().map(|ty| simplify_type(ty)).collect()) } mabo_parser::DataType::Array { ref ty, size, .. } => { Type::Array(simplify_type(ty).into(), size) @@ -457,7 +459,9 @@ fn simplify_type<'a>(item: &'a mabo_parser::Type<'_>) -> Type<'a> { mabo_parser::DataType::External(ref ty) => Type::External(ExternalType { path: ty.path.iter().map(mabo_parser::Name::get).collect(), name: ty.name.get(), - generics: ty.generics.iter().map(|ty| simplify_type(ty)).collect(), + generics: ty.generics.as_ref().map_or(Vec::default(), |g| { + g.values().map(|ty| simplify_type(ty)).collect() + }), }), } } diff --git a/crates/mabo-compiler/src/validate/generics.rs b/crates/mabo-compiler/src/validate/generics.rs index ac07516..f98d715 100644 --- a/crates/mabo-compiler/src/validate/generics.rs +++ b/crates/mabo-compiler/src/validate/generics.rs @@ -47,12 +47,15 @@ pub struct UnusedGeneric { /// Ensure all generics in a struct are unique and used. pub fn validate_struct_generics(value: &Struct<'_>) -> Result<(), InvalidGenericType> { - validate_duplicate_generics(&value.generics)?; + let Some(generics) = &value.generics else { + return Ok(()); + }; - let mut unvisited = value - .generics - .0 - .iter() + validate_duplicate_generics(generics)?; + + let mut unvisited = generics + .types + .values() .map(|gen| (gen.get(), gen.span())) .collect::>(); @@ -69,16 +72,19 @@ pub fn validate_struct_generics(value: &Struct<'_>) -> Result<(), InvalidGeneric /// Ensure all generics in an enum are unique and used. pub fn validate_enum_generics(value: &Enum<'_>) -> Result<(), InvalidGenericType> { - validate_duplicate_generics(&value.generics)?; + let Some(generics) = &value.generics else { + return Ok(()); + }; + + validate_duplicate_generics(generics)?; - let mut unvisited = value - .generics - .0 - .iter() + let mut unvisited = generics + .types + .values() .map(|gen| (gen.get(), gen.span())) .collect::>(); - for variant in &value.variants { + for variant in value.variants.values() { validate_field_generics(&variant.fields, &mut unvisited); } @@ -94,10 +100,10 @@ pub fn validate_enum_generics(value: &Enum<'_>) -> Result<(), InvalidGenericType /// Ensure all generic type arguments are unique within a struct or enum. fn validate_duplicate_generics(value: &Generics<'_>) -> Result<(), DuplicateGenericName> { let mut visited = - FxHashMap::with_capacity_and_hasher(value.0.len(), BuildHasherDefault::default()); + FxHashMap::with_capacity_and_hasher(value.types.len(), BuildHasherDefault::default()); value - .0 - .iter() + .types + .values() .find_map(|name| { visited .insert(name.get(), name.span()) @@ -115,18 +121,18 @@ fn validate_duplicate_generics(value: &Generics<'_>) -> Result<(), DuplicateGene fn validate_field_generics(value: &Fields<'_>, unvisited: &mut FxHashMap<&str, Span>) { match &value { Fields::Named(_, named) => { - for field in named { + for field in named.values() { visit_externals(&field.ty, &mut |external| { - if external.path.is_empty() && external.generics.is_empty() { + if external.path.is_empty() && external.generics.is_none() { unvisited.remove(external.name.get()); } }); } } Fields::Unnamed(_, unnamed) => { - for field in unnamed { + for field in unnamed.values() { visit_externals(&field.ty, &mut |external| { - if external.path.is_empty() && external.generics.is_empty() { + if external.path.is_empty() && external.generics.is_none() { unvisited.remove(external.name.get()); } }); @@ -169,15 +175,17 @@ fn visit_externals(value: &Type<'_>, visit: &mut impl FnMut(&ExternalType<'_>)) visit_externals(value, visit); } DataType::Tuple { types, .. } => { - for ty in types { + for ty in types.values() { visit_externals(ty, visit); } } DataType::External(ty) => { visit(ty); - for ty in &ty.generics { - visit_externals(ty, visit); + if let Some(generics) = &ty.generics { + for ty in generics.values() { + visit_externals(ty, visit); + } } } } diff --git a/crates/mabo-compiler/src/validate/ids.rs b/crates/mabo-compiler/src/validate/ids.rs index e1469b3..5554810 100644 --- a/crates/mabo-compiler/src/validate/ids.rs +++ b/crates/mabo-compiler/src/validate/ids.rs @@ -104,7 +104,7 @@ pub(crate) fn validate_enum_ids(value: &Enum<'_>) -> Result<(), DuplicateId> { value .variants - .iter() + .values() .find_map(|variant| { let id = id_gen.next_with_span(variant.id.as_ref(), || variant.span()); @@ -138,7 +138,7 @@ fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> { let mut id_gen = IdGenerator::new(); named - .iter() + .values() .find_map(|field| { let id = id_gen.next_with_span(field.id.as_ref(), || field.span()); @@ -160,7 +160,7 @@ fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> { let mut id_gen = IdGenerator::new(); unnamed - .iter() + .values() .enumerate() .find_map(|(pos, field)| { let id = id_gen.next_with_span(field.id.as_ref(), || field.span()); diff --git a/crates/mabo-compiler/src/validate/names.rs b/crates/mabo-compiler/src/validate/names.rs index 5873ca6..9244099 100644 --- a/crates/mabo-compiler/src/validate/names.rs +++ b/crates/mabo-compiler/src/validate/names.rs @@ -81,7 +81,7 @@ pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName> FxHashMap::with_capacity_and_hasher(value.variants.len(), BuildHasherDefault::default()); value .variants - .iter() + .values() .find_map(|variant| { visited .insert(variant.name.get(), variant.name.span()) @@ -109,7 +109,7 @@ fn validate_field_names(value: &Fields<'_>) -> Result<(), DuplicateFieldName> { let mut visited = FxHashMap::with_capacity_and_hasher(named.len(), BuildHasherDefault::default()); named - .iter() + .values() .find_map(|field| { visited .insert(field.name.get(), field.name.span()) diff --git a/crates/mabo-compiler/src/validate/tuples.rs b/crates/mabo-compiler/src/validate/tuples.rs index 6f8e913..09232c7 100644 --- a/crates/mabo-compiler/src/validate/tuples.rs +++ b/crates/mabo-compiler/src/validate/tuples.rs @@ -1,6 +1,8 @@ use std::ops::Range; -use mabo_parser::{Const, DataType, Enum, Fields, Spanned, Struct, Type, TypeAlias}; +use mabo_parser::{ + punctuated::ValuesIter, Const, DataType, Enum, Fields, Spanned, Struct, Type, TypeAlias, +}; use miette::{diagnostic, Diagnostic}; use thiserror::Error; @@ -43,17 +45,17 @@ pub(crate) fn validate_struct_tuples(value: &Struct<'_>) -> Result<(), TupleSize pub(crate) fn validate_enum_tuples(value: &Enum<'_>) -> Result<(), TupleSize> { value .variants - .iter() + .values() .try_for_each(|variant| validate_field_tuples(&variant.fields)) } fn validate_field_tuples(value: &Fields<'_>) -> Result<(), TupleSize> { match value { Fields::Named(_, named) => named - .iter() + .values() .try_for_each(|field| validate_tuple_size(&field.ty)), Fields::Unnamed(_, unnamed) => unnamed - .iter() + .values() .try_for_each(|field| validate_tuple_size(&field.ty)), Fields::Unit => Ok(()), } @@ -86,7 +88,7 @@ fn validate_tuple_size(value: &Type<'_>) -> Result<(), TupleSize> { /// type. fn visit_tuples( value: &Type<'_>, - visit: &mut impl FnMut(&[Type<'_>]) -> Result<(), E>, + visit: &mut impl FnMut(ValuesIter<'_, Type<'_>>) -> Result<(), E>, ) -> Result<(), E> { match &value.value { DataType::Bool @@ -118,12 +120,16 @@ fn visit_tuples( visit_tuples(value, visit) } DataType::Tuple { types, .. } => { - visit(types)?; - types.iter().try_for_each(|ty| visit_tuples(ty, visit)) + visit(types.values())?; + types.values().try_for_each(|ty| visit_tuples(ty, visit)) + } + DataType::External(ty) => { + if let Some(generics) = &ty.generics { + generics + .values() + .try_for_each(|ty| visit_tuples(ty, visit))?; + } + Ok(()) } - DataType::External(ty) => ty - .generics - .iter() - .try_for_each(|ty| visit_tuples(ty, visit)), } } diff --git a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.mabo.snap b/crates/mabo-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.mabo.snap deleted file mode 100644 index dd45690..0000000 --- a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.mabo.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: crates/mabo-compiler/tests/compiler.rs -description: type Sample = (); -input_file: crates/mabo-compiler/tests/inputs/validate/alias_tuple_empty.mabo ---- - × invalid tuple element size found - ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid - ╭─[alias_tuple_empty.mabo:1:15] - 1 │ type Sample = (); - · ─┬ - · ╰── declared here - ╰──── - help: a tuple must have between 2 and 12 elements - diff --git a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.mabo.snap b/crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.mabo.snap deleted file mode 100644 index 5ac0641..0000000 --- a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.mabo.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/mabo-compiler/tests/compiler.rs -description: "enum Sample {\n One @1,\n Two {\n field: () @1,\n } @2,\n}" -input_file: crates/mabo-compiler/tests/inputs/validate/enum_named_tuple_empty.mabo ---- - × invalid tuple element size found - ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid - ╭─[enum_named_tuple_empty.mabo:4:16] - 1 │ enum Sample { - 2 │ One @1, - 3 │ Two { - 4 │ field: () @1, - · ─┬ - · ╰── declared here - 5 │ } @2, - 6 │ } - ╰──── - help: a tuple must have between 2 and 12 elements - diff --git a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.mabo.snap b/crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.mabo.snap deleted file mode 100644 index 1eba4e9..0000000 --- a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.mabo.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: crates/mabo-compiler/tests/compiler.rs -description: "enum Sample {\n One @1,\n Two(() @1) @2,\n}" -input_file: crates/mabo-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.mabo ---- - × invalid tuple element size found - ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid - ╭─[enum_unnamed_tuple_empty.mabo:3:9] - 1 │ enum Sample { - 2 │ One @1, - 3 │ Two(() @1) @2, - · ─┬ - · ╰── declared here - 4 │ } - ╰──── - help: a tuple must have between 2 and 12 elements - diff --git a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.mabo.snap b/crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.mabo.snap deleted file mode 100644 index 4312f4d..0000000 --- a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.mabo.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: crates/mabo-compiler/tests/compiler.rs -description: "struct Sample {\n field: () @1,\n}" -input_file: crates/mabo-compiler/tests/inputs/validate/struct_named_tuple_empty.mabo ---- - × invalid tuple element size found - ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid - ╭─[struct_named_tuple_empty.mabo:2:12] - 1 │ struct Sample { - 2 │ field: () @1, - · ─┬ - · ╰── declared here - 3 │ } - ╰──── - help: a tuple must have between 2 and 12 elements - diff --git a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.mabo.snap b/crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.mabo.snap deleted file mode 100644 index 274e6b8..0000000 --- a/crates/mabo-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.mabo.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: crates/mabo-compiler/tests/compiler.rs -description: struct Sample(() @1) -input_file: crates/mabo-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.mabo ---- - × invalid tuple element size found - ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid - ╭─[struct_unnamed_tuple_empty.mabo:1:15] - 1 │ struct Sample(() @1) - · ─┬ - · ╰── declared here - ╰──── - help: a tuple must have between 2 and 12 elements - diff --git a/crates/mabo-lsp/src/handlers/document_symbols.rs b/crates/mabo-lsp/src/handlers/document_symbols.rs index 213bb80..10af696 100644 --- a/crates/mabo-lsp/src/handlers/document_symbols.rs +++ b/crates/mabo-lsp/src/handlers/document_symbols.rs @@ -54,7 +54,7 @@ fn visit_enum(index: &Index, item: &Enum<'_>) -> Result { SymbolKind::ENUM, index.get_range(item.name.span())?, item.variants - .iter() + .values() .map(|variant| visit_variant(index, variant)) .collect::>()?, )) @@ -72,11 +72,11 @@ fn visit_variant(index: &Index, item: &Variant<'_>) -> Result { fn visit_fields(index: &Index, item: &Fields<'_>) -> Result> { match item { Fields::Named(_, named) => named - .iter() + .values() .map(|field| visit_named_field(index, field)) .collect(), Fields::Unnamed(_, unnamed) => unnamed - .iter() + .values() .enumerate() .map(|(pos, field)| visit_unnamed_field(index, field, pos)) .collect(), diff --git a/crates/mabo-lsp/src/handlers/semantic_tokens.rs b/crates/mabo-lsp/src/handlers/semantic_tokens.rs index 3909a29..dacc5af 100644 --- a/crates/mabo-lsp/src/handlers/semantic_tokens.rs +++ b/crates/mabo-lsp/src/handlers/semantic_tokens.rs @@ -249,8 +249,11 @@ impl<'a> Visitor<'a> { self.visit_generics(&item.generics)?; self.add_span(&item.brace.open(), &types::BRACE, &[])?; - for variant in &item.variants { + for (variant, comma) in &item.variants { self.visit_variant(variant)?; + if let Some(comma) = &comma { + self.add_span(comma, &types::COMMA, &[])?; + } } self.add_span(&item.brace.close(), &types::BRACE, &[]) @@ -261,9 +264,7 @@ impl<'a> Visitor<'a> { self.add_span(&item.name, &types::ENUM_MEMBER, &[modifiers::DECLARATION])?; self.visit_fields(&item.fields)?; self.visit_id(&item.id)?; - if let Some(comma) = &item.comma { - self.add_span(comma, &types::COMMA, &[])?; - } + Ok(()) } @@ -271,15 +272,21 @@ impl<'a> Visitor<'a> { match item { Fields::Named(brace, named) => { self.add_span(&brace.open(), &types::BRACE, &[])?; - for field in named { + for (field, comma) in named { self.visit_named_field(field)?; + if let Some(comma) = &comma { + self.add_span(comma, &types::COMMA, &[])?; + } } self.add_span(&brace.close(), &types::BRACE, &[])?; } Fields::Unnamed(paren, unnamed) => { self.add_span(&paren.open(), &types::PARENTHESIS, &[])?; - for field in unnamed { + for (field, comma) in unnamed { self.visit_unnamed_field(field)?; + if let Some(comma) = &comma { + self.add_span(comma, &types::COMMA, &[])?; + } } self.add_span(&paren.close(), &types::PARENTHESIS, &[])?; } @@ -295,9 +302,6 @@ impl<'a> Visitor<'a> { self.add_span(&item.colon, &types::COLON, &[])?; self.visit_type(&item.ty)?; self.visit_id(&item.id)?; - if let Some(comma) = &item.comma { - self.add_span(comma, &types::COMMA, &[])?; - } Ok(()) } @@ -389,8 +393,11 @@ impl<'a> Visitor<'a> { } DataType::Tuple { paren, types } => { self.add_span(&paren.open(), &types::PARENTHESIS, &[])?; - for ty in types { + for (ty, comma) in types { self.visit_type(ty)?; + if let Some(comma) = &comma { + self.add_span(comma, &types::COMMA, &[])?; + } } self.add_span(&paren.close(), &types::PARENTHESIS, &[]) } @@ -418,8 +425,13 @@ impl<'a> Visitor<'a> { if let Some(angle) = angle { self.add_span(&angle.open(), &types::ANGLE, &[])?; } - for ty in generics { - self.visit_type(ty)?; + if let Some(generics) = generics { + for (ty, comma) in generics { + self.visit_type(ty)?; + if let Some(comma) = &comma { + self.add_span(comma, &types::COMMA, &[])?; + } + } } if let Some(angle) = angle { self.add_span(&angle.close(), &types::ANGLE, &[])?; @@ -442,9 +454,14 @@ impl<'a> Visitor<'a> { self.add_span(item, &token_type, &[]) } - fn visit_generics(&mut self, item: &Generics<'_>) -> Result<()> { - for generic in &item.0 { - self.add_span(generic, &types::TYPE_PARAMETER, &[modifiers::DECLARATION])?; + fn visit_generics(&mut self, item: &Option>) -> Result<()> { + if let Some(generics) = item { + for (generic, comma) in &generics.types { + self.add_span(generic, &types::TYPE_PARAMETER, &[modifiers::DECLARATION])?; + if let Some(comma) = &comma { + self.add_span(comma, &types::COMMA, &[])?; + } + } } Ok(()) diff --git a/crates/mabo-parser/src/lib.rs b/crates/mabo-parser/src/lib.rs index 55fc406..3c95aca 100644 --- a/crates/mabo-parser/src/lib.rs +++ b/crates/mabo-parser/src/lib.rs @@ -27,7 +27,7 @@ pub use miette::{Diagnostic, LabeledSpan}; use miette::{IntoDiagnostic, NamedSource, Result}; use winnow::Parser; -use self::{error::ParseSchemaError, token::Punctuation}; +use self::{error::ParseSchemaError, punctuated::Punctuated, token::Punctuation}; use crate::token::Delimiter; pub mod error; @@ -35,17 +35,27 @@ mod ext; mod highlight; mod location; mod parser; +pub mod punctuated; pub mod token; -trait Print { +/// Format trait like [`Display`], with the addition of indentation awareness. +pub trait Print { /// Default indentation, 4 spaces. const INDENT: &'static str = " "; /// Write to the given formatter (like [`Display::fmt`]) but in addition, take the current /// indentation level into account. + /// + /// # Errors + /// + /// Will return `Err` if any of the formatting calls fails. fn print(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result; /// Helper to write out the indentation for the given level. + /// + /// # Errors + /// + /// Will return `Err` if any of the formatting calls fails. fn indent(f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { for _ in 0..level { f.write_str(Self::INDENT)?; @@ -318,7 +328,7 @@ pub struct Struct<'a> { /// Unique name for this struct (within its scope). pub name: Name<'a>, /// Potential generics. - pub generics: Generics<'a>, + pub generics: Option>, /// Fields of the struct, if any. pub fields: Fields<'a>, } @@ -338,7 +348,10 @@ impl Print for Struct<'_> { attributes.print(f, level)?; keyword.print(f, level)?; - write!(f, " {name}{generics}")?; + write!(f, " {name}")?; + if let Some(generics) = generics { + generics.fmt(f)?; + } kind.print(f, level)?; f.write_str("\n") @@ -377,11 +390,11 @@ pub struct Enum<'a> { /// Unique name for this enum, within its current scope. pub name: Name<'a>, /// Potential generics. - pub generics: Generics<'a>, + pub generics: Option>, /// Braces `{`...`}` around the variants. pub brace: token::Brace, /// List of possible variants that the enum can represent. - pub variants: Vec>, + pub variants: Punctuated>, } impl Print for Enum<'_> { @@ -400,15 +413,14 @@ impl Print for Enum<'_> { attributes.print(f, level)?; keyword.print(f, level)?; - writeln!(f, " {name}{generics} {}", token::Brace::OPEN)?; - - for variant in variants { - variant.print(f, level + 1)?; - f.write_str("\n")?; + write!(f, " {name}")?; + if let Some(generics) = generics { + generics.fmt(f)?; } - Self::indent(f, level)?; - writeln!(f, "{}", token::Brace::CLOSE) + f.write_char(' ')?; + variants.surround::(f, level, true)?; + f.write_char('\n') } } @@ -429,8 +441,6 @@ pub struct Variant<'a> { pub fields: Fields<'a>, /// Identifier for this variant, that must be unique within the current enum. pub id: Option, - /// Trailing comma to separate variants (might be missing if this is the last element). - pub comma: Option, /// Source code location. span: Span, } @@ -442,7 +452,6 @@ impl Print for Variant<'_> { name, fields, id, - comma, .. } = self; @@ -454,9 +463,6 @@ impl Print for Variant<'_> { if let Some(id) = id { write!(f, " {id}")?; } - if let Some(comma) = comma { - write!(f, "{comma}")?; - } Ok(()) } } @@ -491,7 +497,7 @@ pub struct TypeAlias<'a> { /// Unique name of the type alias within the current scope. pub name: Name<'a>, /// Potential generic type arguments. - pub generics: Generics<'a>, + pub generics: Option>, /// Equal operator that assigns the target type. pub equal: token::Equal, /// Original type that is being aliased. @@ -515,7 +521,11 @@ impl Print for TypeAlias<'_> { comment.print(f, level)?; keyword.print(f, level)?; - write!(f, " {name}{generics} {equal} {target}{semicolon}") + write!(f, " {name}")?; + if let Some(generics) = generics { + generics.fmt(f)?; + } + write!(f, " {equal} {target}{semicolon}") } } @@ -537,13 +547,13 @@ pub enum Fields<'a> { /// c: i32 @3, /// } /// ``` - Named(token::Brace, Vec>), + Named(token::Brace, Punctuated>), /// List of types without an explicit name. /// /// ```txt /// Sample(u8 @1, bool @2, i32 @3) /// ``` - Unnamed(token::Parenthesis, Vec>), + Unnamed(token::Parenthesis, Punctuated>), /// No attached value. /// /// ```txt @@ -556,17 +566,10 @@ impl Print for Fields<'_> { fn print(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { match self { Fields::Named(_, fields) => { - writeln!(f, " {}", token::Brace::OPEN)?; - - for field in fields { - field.print(f, level + 1)?; - f.write_char('\n')?; - } - - Self::indent(f, level)?; - f.write_char(token::Brace::CLOSE) + f.write_char(' ')?; + fields.surround::(f, level, true) } - Fields::Unnamed(_, elements) => concat::(f, elements, " "), + Fields::Unnamed(_, elements) => elements.surround::(f, 0, false), Fields::Unit => Ok(()), } } @@ -599,8 +602,6 @@ pub struct NamedField<'a> { pub ty: Type<'a>, /// Identifier for this field, that must be unique within the current element. pub id: Option, - /// Trailing comma to separate fields (might be missing if this is the last element). - pub comma: Option, /// Source code location. span: Span, } @@ -613,7 +614,6 @@ impl Print for NamedField<'_> { colon, ty, id, - comma, .. } = self; @@ -626,10 +626,6 @@ impl Print for NamedField<'_> { write!(f, " {id}")?; } - if let Some(comma) = comma { - comma.fmt(f)?; - } - Ok(()) } } @@ -660,8 +656,6 @@ pub struct UnnamedField<'a> { pub ty: Type<'a>, /// Identifier for this field, that must be unique within the current element. pub id: Option, - /// Trailing comma to separate fields (might be missing if this is the last element). - pub comma: Option, /// Source code location. span: Span, } @@ -672,23 +666,25 @@ impl Spanned for UnnamedField<'_> { } } -impl Display for UnnamedField<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { ty, id, comma, .. } = self; +impl Print for UnnamedField<'_> { + fn print(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + let Self { ty, id, .. } = self; write!(f, "{ty}")?; if let Some(id) = id { write!(f, " {id}")?; } - if let Some(comma) = comma { - comma.fmt(f)?; - } - Ok(()) } } +impl Display for UnnamedField<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.print(f, 0) + } +} + /// Comments above any other element. /// /// ```txt @@ -854,9 +850,15 @@ impl Spanned for Type<'_> { } } +impl Print for Type<'_> { + fn print(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + self.value.fmt(f) + } +} + impl Display for Type<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.value.fmt(f) + self.print(f, 0) } } @@ -966,7 +968,7 @@ pub enum DataType<'a> { /// Parenthesis `(`...`)` that delimits the tuple. paren: token::Parenthesis, /// List of types that make up the tuple. - types: Vec>, + types: Punctuated>, }, /// Continuous list of values with a single time and known length. Array { @@ -1010,7 +1012,7 @@ impl Display for DataType<'_> { Self::NonZero { ty, .. } => write!(f, "non_zero<{ty}>"), Self::BoxString => f.write_str("box"), Self::BoxBytes => f.write_str("box"), - Self::Tuple { types, .. } => concat::(f, types, ", "), + Self::Tuple { types, .. } => types.surround::(f, 0, false), Self::Array { ty, size, .. } => write!(f, "[{ty}; {size}]"), Self::External(t) => t.fmt(f), } @@ -1030,7 +1032,7 @@ pub struct ExternalType<'a> { /// Angles `<`...`>` to delimit the generic type parameters. pub angle: Option, /// Potential generic type arguments. - pub generics: Vec>, + pub generics: Option>>, } impl Display for ExternalType<'_> { @@ -1046,7 +1048,10 @@ impl Display for ExternalType<'_> { write!(f, "{segment}::")?; } name.fmt(f)?; - concat::(f, generics, ", ") + if let Some(generics) = generics { + generics.surround::(f, 0, false)?; + } + Ok(()) } } @@ -1055,12 +1060,17 @@ impl Display for ExternalType<'_> { /// ```txt /// /// ``` -#[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct Generics<'a>(pub Vec>); +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Generics<'a> { + /// Angles `<`...`>` to delimit the generic type parameters. + pub angle: token::Angle, + /// The generic types, separated by commas `,`. + pub types: Punctuated>, +} impl Display for Generics<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - concat::(f, &self.0, ", ") + self.types.surround::(f, 0, false) } } @@ -1131,9 +1141,15 @@ impl Spanned for Name<'_> { } } +impl Print for Name<'_> { + fn print(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + self.value.fmt(f) + } +} + impl Display for Name<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.value.fmt(f) + self.print(f, 0) } } diff --git a/crates/mabo-parser/src/parser.rs b/crates/mabo-parser/src/parser.rs index c7b050f..8f2f37c 100644 --- a/crates/mabo-parser/src/parser.rs +++ b/crates/mabo-parser/src/parser.rs @@ -1,8 +1,10 @@ +use std::ops::Range; + use winnow::{ ascii::{multispace0, newline, space0}, combinator::{fail, opt, peek, preceded, repeat, terminated, trace}, dispatch, - error::ParserError, + error::{ErrMode, ParserError}, prelude::*, stream::{AsChar, Stream, StreamIsPartial}, token::any, @@ -26,6 +28,7 @@ pub use self::{ use crate::{ error::{ParseDefinitionError, ParseSchemaCause}, ext::ParserExt, + punctuated::Punctuated, Definition, Schema, }; @@ -210,3 +213,57 @@ where { trace("ws", preceded(multispace0, inner)) } + +pub fn punctuate(mut f: F, mut g: G) -> impl Parser, E> +where + I: Stream, + P: Copy + From>, + E: ParserError, + F: Parser), E>, + G: Parser>), E>, +{ + trace("punctuate", move |i: &mut I| { + let mut values = Vec::new(); + let mut start_prev = None; + + loop { + let start = i.checkpoint(); + let len = i.eof_offset(); + + match f.parse_next(i) { + Ok((o, range)) => { + if i.eof_offset() == len { + return Err(ErrMode::assert(i, "`repeat` parsers must always consume")); + } + + values.push((o, range.into())); + start_prev = Some(start); + } + Err(ErrMode::Backtrack(_)) => { + i.reset(&start); + let (o, range) = match g.parse_next(i) { + Ok(o) => Ok(o), + // Both parsers failed. Lets undo the last successful action from the first + // parser and redo it with the second one to get the last value. + // + // Technically we could just take the parsed data from the first parser and + // transform it, but there is no guarantee that the parsers are similar + // enough to do this transformation. + Err(ErrMode::Backtrack(e)) => { + if let Some(start) = start_prev { + values.pop(); + i.reset(&start); + g.parse_next(i) + } else { + Err(ErrMode::Backtrack(e)) + } + } + Err(e) => Err(e), + }?; + return Ok(Punctuated::new(values, (o, range.map(Into::into)))); + } + Err(e) => return Err(e), + } + } + }) +} diff --git a/crates/mabo-parser/src/parser/aliases.rs b/crates/mabo-parser/src/parser/aliases.rs index eb34c0a..c59a923 100644 --- a/crates/mabo-parser/src/parser/aliases.rs +++ b/crates/mabo-parser/src/parser/aliases.rs @@ -71,7 +71,7 @@ pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseErr terminated(token::Type::NAME.span(), space1), cut_err(( parse_name, - opt(generics::parse.map_err(Cause::Generics)).map(Option::unwrap_or_default), + opt(generics::parse.map_err(Cause::Generics)), preceded(space0, token::Equal::VALUE.span()), preceded(space0, types::parse.map_err(Cause::from)), preceded(space0, token::Semicolon::VALUE.span()), diff --git a/crates/mabo-parser/src/parser/enums.rs b/crates/mabo-parser/src/parser/enums.rs index ce19df3..6d53110 100644 --- a/crates/mabo-parser/src/parser/enums.rs +++ b/crates/mabo-parser/src/parser/enums.rs @@ -3,16 +3,17 @@ use std::ops::Range; use mabo_derive::{ParserError, ParserErrorCause}; use winnow::{ ascii::{alphanumeric0, space0, space1}, - combinator::{cut_err, opt, preceded, repeat, terminated}, + combinator::{cut_err, opt, preceded, terminated}, error::ErrorKind, stream::Location, token::one_of, Parser, }; -use super::{comments, fields, generics, ids, ws, Input, ParserExt, Result}; +use super::{comments, fields, generics, ids, punctuate, ws, Input, ParserExt, Result}; use crate::{ highlight, + punctuated::Punctuated, token::{self, Delimiter, Punctuation}, Attributes, Comment, Enum, Name, Variant, }; @@ -93,7 +94,7 @@ pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseError> { terminated(token::Enum::NAME.span(), space1), cut_err(( parse_name, - opt(generics::parse.map_err(Cause::from)).map(Option::unwrap_or_default), + opt(generics::parse.map_err(Cause::from)), preceded(space0, parse_variants), )), ) @@ -128,10 +129,18 @@ pub(super) fn parse_name<'i>(input: &mut Input<'i>) -> Result, Cause> { }) } -fn parse_variants<'i>(input: &mut Input<'i>) -> Result<(token::Brace, Vec>), Cause> { +fn parse_variants<'i>( + input: &mut Input<'i>, +) -> Result<(token::Brace, Punctuated>), Cause> { ( token::Brace::OPEN.span(), - cut_err((repeat(1.., parse_variant), ws(token::Brace::CLOSE.span()))), + cut_err(( + punctuate( + (parse_variant, ws(token::Comma::VALUE.span())), + (parse_variant, opt(ws(token::Comma::VALUE.span()))), + ), + ws(token::Brace::CLOSE.span()), + )), ) .parse_next(input) .map(|(brace_open, (variants, brace_close))| ((brace_open, brace_close).into(), variants)) @@ -144,17 +153,15 @@ fn parse_variant<'i>(input: &mut Input<'i>) -> Result, Cause> { preceded(space0, parse_variant_name.with_span()), preceded(space0, fields::parse.map_err(Cause::from)), opt(preceded(space0, ids::parse.map_err(Cause::from))), - opt(ws(token::Comma::VALUE.span())), ) .with_span(), ) .parse_next(input) - .map(|(comment, ((name, fields, id, comma), span))| Variant { + .map(|(comment, ((name, fields, id), span))| Variant { comment, name: name.into(), fields, id, - comma: comma.map(Into::into), span: span.into(), }) } diff --git a/crates/mabo-parser/src/parser/fields.rs b/crates/mabo-parser/src/parser/fields.rs index 869003b..ab25f65 100644 --- a/crates/mabo-parser/src/parser/fields.rs +++ b/crates/mabo-parser/src/parser/fields.rs @@ -3,7 +3,7 @@ use std::ops::Range; use mabo_derive::{ParserError, ParserErrorCause}; use winnow::{ ascii::space0, - combinator::{cut_err, opt, peek, preceded, repeat}, + combinator::{cut_err, opt, peek, preceded}, dispatch, error::ErrorKind, stream::{Location, Stream}, @@ -11,9 +11,10 @@ use winnow::{ Parser, }; -use super::{comments, ids, types, ws, Input, ParserExt, Result}; +use super::{comments, ids, punctuate, types, ws, Input, ParserExt, Result}; use crate::{ highlight, location, + punctuated::Punctuated, token::{self, Delimiter, Punctuation}, Fields, Name, NamedField, UnnamedField, }; @@ -90,11 +91,16 @@ pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseError> }) } -fn parse_named<'i>(input: &mut Input<'i>) -> Result<(token::Brace, Vec>), Cause> { +fn parse_named<'i>( + input: &mut Input<'i>, +) -> Result<(token::Brace, Punctuated>), Cause> { ( token::Brace::OPEN.span(), cut_err(( - repeat(1.., parse_named_field), + punctuate( + (parse_named_field, ws(token::Comma::VALUE.span())), + (parse_named_field, opt(ws(token::Comma::VALUE.span()))), + ), ws(token::Brace::CLOSE.span()), )), ) @@ -104,11 +110,14 @@ fn parse_named<'i>(input: &mut Input<'i>) -> Result<(token::Brace, Vec( input: &mut Input<'i>, -) -> Result<(token::Parenthesis, Vec>), Cause> { +) -> Result<(token::Parenthesis, Punctuated>), Cause> { ( token::Parenthesis::OPEN.span(), cut_err(( - repeat(1.., parse_unnamed_field), + punctuate( + (parse_unnamed_field, ws(token::Comma::VALUE.span())), + (parse_unnamed_field, opt(ws(token::Comma::VALUE.span()))), + ), ws(token::Parenthesis::CLOSE.span()), )), ) @@ -124,14 +133,12 @@ fn parse_unnamed_field<'i>(input: &mut Input<'i>) -> Result, Ca ( ws(types::parse.map_err(Cause::from)), opt(preceded(space0, ids::parse.map_err(Cause::from))), - opt(ws(token::Comma::VALUE.span())), ) .with_span() .parse_next(input) - .map(|((ty, id, comma), span)| UnnamedField { + .map(|((ty, id), span)| UnnamedField { ty, id, - comma: comma.map(Into::into), span: span.into(), }) } @@ -144,22 +151,18 @@ fn parse_named_field<'i>(input: &mut Input<'i>) -> Result, Cause> preceded(space0, token::Colon::VALUE.span()), preceded(space0, types::parse.map_err(Cause::from)), opt(preceded(space0, ids::parse.map_err(Cause::from))), - opt(ws(token::Comma::VALUE.span())), ) .with_span(), ) .parse_next(input) - .map( - |(comment, ((name, colon, ty, id, comma), span))| NamedField { - comment, - name, - colon: colon.into(), - ty, - id, - comma: comma.map(Into::into), - span: span.into(), - }, - ) + .map(|(comment, ((name, colon, ty, id), span))| NamedField { + comment, + name, + colon: colon.into(), + ty, + id, + span: span.into(), + }) } fn parse_field_name<'i>(input: &mut Input<'i>) -> Result, Cause> { diff --git a/crates/mabo-parser/src/parser/generics.rs b/crates/mabo-parser/src/parser/generics.rs index c7ad872..b842854 100644 --- a/crates/mabo-parser/src/parser/generics.rs +++ b/crates/mabo-parser/src/parser/generics.rs @@ -3,15 +3,19 @@ use std::ops::Range; use mabo_derive::{ParserError, ParserErrorCause}; use winnow::{ ascii::alphanumeric0, - combinator::{cut_err, preceded, separated, terminated}, + combinator::{cut_err, opt}, error::ErrorKind, stream::Location, token::one_of, Parser, }; -use super::{ws, Input, Result}; -use crate::{highlight, Generics, Name}; +use super::{punctuate, ws, Input, Result}; +use crate::{ + highlight, + token::{self, Delimiter, Punctuation}, + Generics, Name, +}; /// Encountered an invalid `<...>` generics declaration. #[derive(Debug, ParserError)] @@ -48,18 +52,27 @@ pub enum Cause { } pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseError> { - preceded( - '<', - cut_err(terminated(separated(1.., ws(parse_name), ws(',')), ws('>'))), + ( + token::Angle::OPEN.span(), + cut_err(( + punctuate( + (ws(parse_name), ws(token::Comma::VALUE.span())), + (ws(parse_name), opt(ws(token::Comma::VALUE.span()))), + ), + ws(token::Angle::CLOSE.span()), + )), ) - .parse_next(input) - .map(Generics) - .map_err(|e| { - e.map(|cause| ParseError { - at: input.location()..input.location(), - cause, + .parse_next(input) + .map(|(angle_open, (types, angle_close))| Generics { + angle: (angle_open, angle_close).into(), + types, + }) + .map_err(|e| { + e.map(|cause| ParseError { + at: input.location()..input.location(), + cause, + }) }) - }) } fn parse_name<'i>(input: &mut Input<'i>) -> Result, Cause> { diff --git a/crates/mabo-parser/src/parser/structs.rs b/crates/mabo-parser/src/parser/structs.rs index 5ad1ba9..2b315b6 100644 --- a/crates/mabo-parser/src/parser/structs.rs +++ b/crates/mabo-parser/src/parser/structs.rs @@ -69,7 +69,7 @@ pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseError> terminated(token::Struct::NAME.span(), space1), cut_err(( parse_name, - opt(generics::parse.map_err(Cause::Generics)).map(Option::unwrap_or_default), + opt(generics::parse.map_err(Cause::Generics)), preceded(space0, fields::parse.map_err(Cause::Fields)), )), ) diff --git a/crates/mabo-parser/src/parser/types.rs b/crates/mabo-parser/src/parser/types.rs index 67d66a4..0971013 100644 --- a/crates/mabo-parser/src/parser/types.rs +++ b/crates/mabo-parser/src/parser/types.rs @@ -11,7 +11,7 @@ use winnow::{ Parser, }; -use super::{imports, ws, Input, ParserExt, Result}; +use super::{imports, punctuate, ws, Input, ParserExt, Result}; use crate::{ highlight, token::{self, Delimiter, Punctuation}, @@ -178,10 +178,15 @@ fn parse_tuple<'i>(input: &mut Input<'i>) -> Result, Cause> { ( token::Parenthesis::OPEN.span(), cut_err(( - separated( - 0.., - ws(parse.map_err(Cause::from)), - ws(token::Comma::VALUE.span()), + punctuate( + ( + ws(parse.map_err(Cause::from)), + ws(token::Comma::VALUE.span()), + ), + ( + ws(parse.map_err(Cause::from)), + opt(ws(token::Comma::VALUE.span())), + ), ), ws(token::Parenthesis::CLOSE.span()), )), @@ -229,7 +234,16 @@ fn parse_external<'i>(input: &mut Input<'i>) -> Result, Cause> opt(( token::Angle::OPEN.span(), cut_err(( - separated(1.., ws(parse.map_err(Cause::from)), ws(token::Comma::VALUE)), + punctuate( + ( + ws(parse.map_err(Cause::from)), + ws(token::Comma::VALUE.span()), + ), + ( + ws(parse.map_err(Cause::from)), + opt(ws(token::Comma::VALUE.span())), + ), + ), ws(token::Angle::CLOSE.span()), )), )), @@ -237,8 +251,8 @@ fn parse_external<'i>(input: &mut Input<'i>) -> Result, Cause> .parse_next(input) .map(|(path, name, generics)| { let (angle, generics) = match generics { - Some((open, (generics, close))) => (Some((open, close).into()), generics), - None => (None, Vec::default()), + Some((open, (generics, close))) => (Some((open, close).into()), Some(generics)), + None => (None, None), }; ExternalType { path, diff --git a/crates/mabo-parser/src/punctuated.rs b/crates/mabo-parser/src/punctuated.rs new file mode 100644 index 0000000..feb7759 --- /dev/null +++ b/crates/mabo-parser/src/punctuated.rs @@ -0,0 +1,157 @@ +//! Punctionation logic for many Mabo schema elements. The main point of interest is the +//! [`Punctuated`] container. + +use std::{ + fmt::{self, Write}, + iter, slice, +}; + +use crate::{ + token::{self, Delimiter, Punctuation}, + Print, +}; + +/// Container for a list of elements that are separated by punctuation. +/// +/// This structure is never empty, always holding at least one element. All values must be separated +/// by punctuation and the last element can have an optional trailing punctuation. +/// +/// The punctuation defaults to a comma `,` as this is the most common one. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Punctuated { + values: Vec<(T, P)>, + last: Box<(T, Option

)>, +} + +impl Punctuated { + /// Construct a new `Punctuated` from the given arguments. + pub fn new(values: Vec<(T, P)>, last: (T, Option

)) -> Self { + Self { + values, + last: Box::new(last), + } + } + + /// Returns an iterator over the values (excluding the punctuation). + #[must_use] + pub fn values(&self) -> ValuesIter<'_, T, P> { + ValuesIter { + items: self.values.iter(), + last: iter::once(&self.last.0), + } + } + + /// Returns the number of elements. + /// + /// **Note:** There is no `is_empty` method because this type always carries at least one + /// element and can never be empty. + #[allow(clippy::len_without_is_empty)] + #[must_use] + pub fn len(&self) -> usize { + self.values.len() + 1 + } +} + +impl Punctuated { + /// Returns an iterator over the elements. + #[must_use] + pub fn iter(&self) -> Iter<'_, T, P> { + Iter { + items: self.values.iter(), + last: iter::once(&self.last), + } + } +} + +impl Punctuated { + pub(crate) fn surround( + &self, + f: &mut fmt::Formatter<'_>, + level: usize, + newline: bool, + ) -> fmt::Result { + f.write_char(D::OPEN)?; + if newline { + f.write_char('\n')?; + } + + for (value, _) in &self.values { + value.print(f, level + 1)?; + f.write_str(P::VALUE)?; + f.write_char(if newline { '\n' } else { ' ' })?; + } + + self.last.0.print(f, level + 1)?; + if self.last.1.is_some() { + f.write_str(P::VALUE)?; + } + if newline { + f.write_char('\n')?; + } + + T::indent(f, level)?; + f.write_char(D::CLOSE) + } +} + +impl<'a, T, P: Copy> IntoIterator for &'a Punctuated { + type IntoIter = Iter<'a, T, P>; + type Item = (&'a T, Option

); + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// An iterator over the entries of a [`Punctuated`]. +/// +/// This `struct` is created by the [`iter`](Punctuated::iter) method on [`Punctuated`]. See +/// its documentation for more. +pub struct Iter<'a, T, P = token::Comma> { + items: slice::Iter<'a, (T, P)>, + last: iter::Once<&'a (T, Option

)>, +} + +impl<'a, T, P: Copy> Iterator for Iter<'a, T, P> { + type Item = (&'a T, Option

); + + fn next(&mut self) -> Option { + self.items + .next() + .map(|(t, p)| (t, Some(*p))) + .or_else(|| self.last.next().map(|(t, p)| (t, *p))) + } +} + +impl ExactSizeIterator for Iter<'_, T, P> { + fn len(&self) -> usize { + self.items.len() + 1 + } +} + +/// An iterator over the values of a [`Punctuated`]. +/// +/// This `struct` is created by the [`values`](Punctuated::values) method on [`Punctuated`]. See +/// its documentation for more. +pub struct ValuesIter<'a, T, P = token::Comma> { + #[allow(clippy::type_complexity)] + items: slice::Iter<'a, (T, P)>, + last: iter::Once<&'a T>, +} + +impl<'a, T, P> Iterator for ValuesIter<'a, T, P> { + type Item = &'a T; + + fn next(&mut self) -> Option { + self.items + .next() + .map(|(t, _)| t) + .or_else(|| self.last.next()) + } +} + +impl ExactSizeIterator for ValuesIter<'_, T, P> { + fn len(&self) -> usize { + self.items.len() + 1 + } +} diff --git a/crates/mabo-compiler/tests/inputs/validate/alias_tuple_empty.mabo b/crates/mabo-parser/tests/inputs/invalid/alias_tuple_empty.mabo similarity index 100% rename from crates/mabo-compiler/tests/inputs/validate/alias_tuple_empty.mabo rename to crates/mabo-parser/tests/inputs/invalid/alias_tuple_empty.mabo diff --git a/crates/mabo-compiler/tests/inputs/validate/enum_named_tuple_empty.mabo b/crates/mabo-parser/tests/inputs/invalid/enum_named_tuple_empty.mabo similarity index 100% rename from crates/mabo-compiler/tests/inputs/validate/enum_named_tuple_empty.mabo rename to crates/mabo-parser/tests/inputs/invalid/enum_named_tuple_empty.mabo diff --git a/crates/mabo-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.mabo b/crates/mabo-parser/tests/inputs/invalid/enum_unnamed_tuple_empty.mabo similarity index 100% rename from crates/mabo-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.mabo rename to crates/mabo-parser/tests/inputs/invalid/enum_unnamed_tuple_empty.mabo diff --git a/crates/mabo-compiler/tests/inputs/validate/struct_named_tuple_empty.mabo b/crates/mabo-parser/tests/inputs/invalid/struct_named_tuple_empty.mabo similarity index 100% rename from crates/mabo-compiler/tests/inputs/validate/struct_named_tuple_empty.mabo rename to crates/mabo-parser/tests/inputs/invalid/struct_named_tuple_empty.mabo diff --git a/crates/mabo-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.mabo b/crates/mabo-parser/tests/inputs/invalid/struct_unnamed_tuple_empty.mabo similarity index 100% rename from crates/mabo-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.mabo rename to crates/mabo-parser/tests/inputs/invalid/struct_unnamed_tuple_empty.mabo diff --git a/crates/mabo-parser/tests/snapshots/parser__error@alias_tuple_empty.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__error@alias_tuple_empty.mabo.snap new file mode 100644 index 0000000..ffb4132 --- /dev/null +++ b/crates/mabo-parser/tests/snapshots/parser__error@alias_tuple_empty.mabo.snap @@ -0,0 +1,42 @@ +--- +source: crates/mabo-parser/tests/parser.rs +description: type Sample = (); +input_file: crates/mabo-parser/tests/inputs/invalid/alias_tuple_empty.mabo +--- +mabo::parse::alias_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseAliasError.html) + + × Failed to parse type alias declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/alias_tuple_empty.mabo:1:16] + 1 │ type Sample = (); + · ▲ + · ╰── In this declaration + ╰──── + help: Expected type alias declaration in the form `❬B❭type = ;❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/alias_tuple_empty.mabo:1:15] + 1 │ type Sample = (); + · ┬ + · ╰── In this declaration + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/alias_tuple_empty.mabo:1:16] + 1 │ type Sample = (); + · ▲ + · ╰── In this declaration + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: × error Verify diff --git a/crates/mabo-parser/tests/snapshots/parser__error@enum_named_tuple_empty.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__error@enum_named_tuple_empty.mabo.snap new file mode 100644 index 0000000..f1ba5e9 --- /dev/null +++ b/crates/mabo-parser/tests/snapshots/parser__error@enum_named_tuple_empty.mabo.snap @@ -0,0 +1,65 @@ +--- +source: crates/mabo-parser/tests/parser.rs +description: "enum Sample {\n One @1,\n Two {\n field: () @1,\n } @2,\n}" +input_file: crates/mabo-parser/tests/inputs/invalid/enum_named_tuple_empty.mabo +--- +mabo::parse::enum_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseEnumError.html) + + × Failed to parse enum declaration + ├─▶ Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_named_tuple_empty.mabo:4:17] + 3 │ Two { + 4 │ field: () @1, + · ▲ + · ╰── In this declaration + 5 │ } @2, + ╰──── + help: Expected enum declaration in the form `❬B❭enum {...}❬B❭` + +Error: mabo::parse::id (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseFieldsError.html) + + × Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_named_tuple_empty.mabo:3:9] + 2 │ One @1, + 3 │ Two { + · ▲ + · ╰── In this declaration + 4 │ field: () @1, + ╰──── + help: Expected fields declaration in the form `❬B❭{ , , ... }❬B❭`, `❬B❭( , , ... ) + ❬B❭` or `❬B❭_nothing_❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_named_tuple_empty.mabo:4:16] + 3 │ Two { + 4 │ field: () @1, + · ┬ + · ╰── In this declaration + 5 │ } @2, + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_named_tuple_empty.mabo:4:17] + 3 │ Two { + 4 │ field: () @1, + · ▲ + · ╰── In this declaration + 5 │ } @2, + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: × error Verify diff --git a/crates/mabo-parser/tests/snapshots/parser__error@enum_unnamed_tuple_empty.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__error@enum_unnamed_tuple_empty.mabo.snap new file mode 100644 index 0000000..88423b1 --- /dev/null +++ b/crates/mabo-parser/tests/snapshots/parser__error@enum_unnamed_tuple_empty.mabo.snap @@ -0,0 +1,65 @@ +--- +source: crates/mabo-parser/tests/parser.rs +description: "enum Sample {\n One @1,\n Two(() @1) @2,\n}" +input_file: crates/mabo-parser/tests/inputs/invalid/enum_unnamed_tuple_empty.mabo +--- +mabo::parse::enum_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseEnumError.html) + + × Failed to parse enum declaration + ├─▶ Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_unnamed_tuple_empty.mabo:3:10] + 2 │ One @1, + 3 │ Two(() @1) @2, + · ▲ + · ╰── In this declaration + 4 │ } + ╰──── + help: Expected enum declaration in the form `❬B❭enum {...}❬B❭` + +Error: mabo::parse::id (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseFieldsError.html) + + × Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_unnamed_tuple_empty.mabo:3:8] + 2 │ One @1, + 3 │ Two(() @1) @2, + · ▲ + · ╰── In this declaration + 4 │ } + ╰──── + help: Expected fields declaration in the form `❬B❭{ , , ... }❬B❭`, `❬B❭( , , ... ) + ❬B❭` or `❬B❭_nothing_❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_unnamed_tuple_empty.mabo:3:9] + 2 │ One @1, + 3 │ Two(() @1) @2, + · ┬ + · ╰── In this declaration + 4 │ } + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/enum_unnamed_tuple_empty.mabo:3:10] + 2 │ One @1, + 3 │ Two(() @1) @2, + · ▲ + · ╰── In this declaration + 4 │ } + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: × error Verify diff --git a/crates/mabo-parser/tests/snapshots/parser__error@struct_named_tuple_empty.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__error@struct_named_tuple_empty.mabo.snap new file mode 100644 index 0000000..f6a3faa --- /dev/null +++ b/crates/mabo-parser/tests/snapshots/parser__error@struct_named_tuple_empty.mabo.snap @@ -0,0 +1,63 @@ +--- +source: crates/mabo-parser/tests/parser.rs +description: "struct Sample {\n field: () @1,\n}" +input_file: crates/mabo-parser/tests/inputs/invalid/struct_named_tuple_empty.mabo +--- +mabo::parse::struct_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseStructError.html) + + × Failed to parse struct declaration + ├─▶ Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_named_tuple_empty.mabo:1:1] + 1 │ ╭─▶ struct Sample { + 2 │ │ field: () @1, + 3 │ ├─▶ } + · ╰──── In this declaration + ╰──── + help: Expected struct declaration in the form `❬B❭struct {...}❬B❭` + +Error: mabo::parse::id (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseFieldsError.html) + + × Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_named_tuple_empty.mabo:1:15] + 1 │ ╭─▶ struct Sample { + 2 │ ├─▶ field: () @1, + · ╰──── In this declaration + 3 │ } + ╰──── + help: Expected fields declaration in the form `❬B❭{ , , ... }❬B❭`, `❬B❭( , , ... ) + ❬B❭` or `❬B❭_nothing_❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_named_tuple_empty.mabo:2:12] + 1 │ struct Sample { + 2 │ field: () @1, + · ┬ + · ╰── In this declaration + 3 │ } + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_named_tuple_empty.mabo:2:13] + 1 │ struct Sample { + 2 │ field: () @1, + · ▲ + · ╰── In this declaration + 3 │ } + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: × error Verify diff --git a/crates/mabo-parser/tests/snapshots/parser__error@struct_unnamed_tuple_empty.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__error@struct_unnamed_tuple_empty.mabo.snap new file mode 100644 index 0000000..e690b07 --- /dev/null +++ b/crates/mabo-parser/tests/snapshots/parser__error@struct_unnamed_tuple_empty.mabo.snap @@ -0,0 +1,57 @@ +--- +source: crates/mabo-parser/tests/parser.rs +description: struct Sample(() @1) +input_file: crates/mabo-parser/tests/inputs/invalid/struct_unnamed_tuple_empty.mabo +--- +mabo::parse::struct_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseStructError.html) + + × Failed to parse struct declaration + ├─▶ Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_unnamed_tuple_empty.mabo:1:1] + 1 │ struct Sample(() @1) + · ──────────┬────────── + · ╰── In this declaration + ╰──── + help: Expected struct declaration in the form `❬B❭struct {...}❬B❭` + +Error: mabo::parse::id (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseFieldsError.html) + + × Failed to parse fields declaration + ├─▶ Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_unnamed_tuple_empty.mabo:1:14] + 1 │ struct Sample(() @1) + · ▲ + · ╰── In this declaration + ╰──── + help: Expected fields declaration in the form `❬B❭{ , , ... }❬B❭`, `❬B❭( , , ... ) + ❬B❭` or `❬B❭_nothing_❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ├─▶ Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_unnamed_tuple_empty.mabo:1:15] + 1 │ struct Sample(() @1) + · ┬ + · ╰── In this declaration + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: mabo::parse::type_def (https://docs.rs/mabo-parser/0.1.0/mabo_parser/error/struct.ParseTypeError.html) + + × Failed to parse type definition + ╰─▶ error Verify + ╭─[invalid/struct_unnamed_tuple_empty.mabo:1:16] + 1 │ struct Sample(() @1) + · ▲ + · ╰── In this declaration + ╰──── + help: Expected type definition in the form `❬B❭❬B❭` + +Error: × error Verify diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@alias_basic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@alias_basic.mabo.snap index 7840fd4..0e420b2 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@alias_basic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@alias_basic.mabo.snap @@ -25,9 +25,7 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, equal: Equal, target: Type { value: U32, diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@attribute_multi.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@attribute_multi.mabo.snap index cacee57..929eac8 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@attribute_multi.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@attribute_multi.mabo.snap @@ -52,9 +52,7 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Unit, }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@attribute_single.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@attribute_single.mabo.snap index e9ba475..1856b2f 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@attribute_single.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@attribute_single.mabo.snap @@ -35,9 +35,7 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Unit, }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@attribute_unit.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@attribute_unit.mabo.snap index 9cd988f..5c1fa1d 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@attribute_unit.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@attribute_unit.mabo.snap @@ -29,9 +29,7 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Unit, }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@attributes.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@attributes.mabo.snap index 054964e..4d5fc2e 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@attributes.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@attributes.mabo.snap @@ -77,9 +77,7 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Unit, }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@attributes_min_ws.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@attributes_min_ws.mabo.snap index d3d81a0..549a1fc 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@attributes_min_ws.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@attributes_min_ws.mabo.snap @@ -77,9 +77,7 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Unit, }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@enum_basic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@enum_basic.mabo.snap index 71733d0..73ca2fd 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@enum_basic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@enum_basic.mabo.snap @@ -28,143 +28,153 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "One", - }, - fields: Unit, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - Variant { - comment: Comment( - [ - CommentLine { - value: "Second variant", + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "One", }, - ], - ), - name: Name { - value: "Two", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, + fields: Unit, + id: Some( + Id { + value: 1, }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - UnnamedField { - ty: Type { - value: U64, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: None, - }, - ], - ), - id: Some( - Id { - value: 2, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Three", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + ( + Variant { + comment: Comment( + [ + CommentLine { + value: "Second variant", }, - ), - comma: Some( - Comma, - ), + ], + ), + name: Name { + value: "Two", }, - NamedField { - comment: Comment( - [ - CommentLine { - value: "Second field of third variant", - }, + fields: Unnamed( + Parenthesis, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), ], - ), - name: Name { - value: "field2", + last: ( + UnnamedField { + ty: Type { + value: U64, + }, + id: Some( + Id { + value: 2, + }, + ), + }, + None, + ), }, - colon: Colon, - ty: Type { - value: Bool, + ), + id: Some( + Id { + value: 2, }, - id: Some( - Id { - value: 2, + ), + }, + Comma, + ), + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Three", + }, + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field1", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ], + last: ( + NamedField { + comment: Comment( + [ + CommentLine { + value: "Second field of third variant", + }, + ], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( - Comma, + Some( + Comma, + ), ), }, - ], - ), - id: Some( - Id { - value: 3, - }, - ), - comma: Some( + ), + id: Some( + Id { + value: 3, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@enum_generics.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@enum_generics.mabo.snap index cd2d30b..7af94ae 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@enum_generics.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@enum_generics.mabo.snap @@ -28,184 +28,213 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [ - Name { - value: "A", - }, - Name { - value: "B", - }, - Name { - value: "C", - }, - Name { - value: "D", + generics: Some( + Generics { + angle: Angle, + types: Punctuated { + values: [ + ( + Name { + value: "A", + }, + Comma, + ), + ( + Name { + value: "B", + }, + Comma, + ), + ( + Name { + value: "C", + }, + Comma, + ), + ], + last: ( + Name { + value: "D", + }, + None, + ), }, - ], + }, ), brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "One", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "One", + }, + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Two", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "A", - }, - angle: None, - generics: [], - }, - ), - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Two", }, - UnnamedField { - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "B", + fields: Unnamed( + Parenthesis, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "A", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 1, + }, + ), }, - angle: None, - generics: [], + Comma, + ), + ], + last: ( + UnnamedField { + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "B", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 2, + }, + ), }, + None, ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: None, - }, - ], - ), - id: Some( - Id { - value: 2, + ), + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Three", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Three", + }, + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), name: Name { - value: "C", + value: "field1", }, - angle: None, - generics: [], - }, - ), - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field2", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "D", + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "C", + }, + angle: None, + generics: None, + }, + ), }, - angle: None, - generics: [], + id: Some( + Id { + value: 1, + }, + ), }, + Comma, ), - }, - id: Some( - Id { - value: 2, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "D", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( - Comma, + Some( + Comma, + ), ), }, - ], - ), - id: Some( - Id { - value: 3, - }, - ), - comma: Some( + ), + id: Some( + Id { + value: 3, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@enum_many_ws.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@enum_many_ws.mabo.snap index 7988aef..a2eec1e 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@enum_many_ws.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@enum_many_ws.mabo.snap @@ -28,135 +28,145 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "One", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "One", + }, + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Two", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Two", }, - UnnamedField { - ty: Type { - value: U64, + fields: Unnamed( + Parenthesis, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ], + last: ( + UnnamedField { + ty: Type { + value: U64, + }, + id: Some( + Id { + value: 2, + }, + ), + }, + None, + ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: None, - }, - ], - ), - id: Some( - Id { - value: 2, + ), + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Three", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Three", + }, + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field1", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( - Comma, + Some( + Comma, + ), ), }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field2", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( - Comma, - ), + ), + id: Some( + Id { + value: 3, }, - ], - ), - id: Some( - Id { - value: 3, - }, - ), - comma: Some( + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@enum_min_ws.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@enum_min_ws.mabo.snap index 5194661..2d8402d 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@enum_min_ws.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@enum_min_ws.mabo.snap @@ -24,186 +24,205 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [ - Name { - value: "T", + generics: Some( + Generics { + angle: Angle, + types: Punctuated { + values: [], + last: ( + Name { + value: "T", + }, + None, + ), }, - ], + }, ), brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "One", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "One", + }, + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Two", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - UnnamedField { - ty: Type { - value: U64, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( - Comma, - ), + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Two", }, - UnnamedField { - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "T", + fields: Unnamed( + Parenthesis, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ( + UnnamedField { + ty: Type { + value: U64, + }, + id: Some( + Id { + value: 2, + }, + ), }, - angle: None, - generics: [], + Comma, + ), + ], + last: ( + UnnamedField { + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 3, + }, + ), }, + None, ), }, - id: Some( - Id { - value: 3, - }, - ), - comma: None, - }, - ], - ), - id: Some( - Id { - value: 2, + ), + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Three", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field2", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( - Comma, - ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field3", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Three", + }, + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), name: Name { - value: "T", + value: "field1", + }, + colon: Colon, + ty: Type { + value: U32, }, - angle: None, - generics: [], + id: Some( + Id { + value: 1, + }, + ), }, + Comma, ), - }, - id: Some( - Id { - value: 3, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), + }, + Comma, + ), + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field3", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 3, + }, + ), }, + None, ), - comma: None, }, - ], - ), - id: Some( - Id { - value: 3, - }, - ), - comma: None, - }, - ], + ), + id: Some( + Id { + value: 3, + }, + ), + }, + None, + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@mixed.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@mixed.mabo.snap index d7634c6..bd921ed 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@mixed.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@mixed.mabo.snap @@ -41,133 +41,135 @@ Schema { name: Name { value: "User", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "name", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "FullName", - }, - angle: None, - generics: [], - }, - ), - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - NamedField { - comment: Comment( - [ - CommentLine { - value: "Physical address, might not be specified by the user.", + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "name", }, - ], - ), - name: Name { - value: "address", - }, - colon: Colon, - ty: Type { - value: Option { - angle: Angle, + colon: Colon, ty: Type { value: External( ExternalType { path: [], name: Name { - value: "Address", + value: "FullName", }, angle: None, - generics: [], + generics: None, }, ), }, + id: Some( + Id { + value: 1, + }, + ), }, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "age", - }, - colon: Colon, - ty: Type { - value: U8, - }, - id: Some( - Id { - value: 3, + ( + NamedField { + comment: Comment( + [ + CommentLine { + value: "Physical address, might not be specified by the user.", + }, + ], + ), + name: Name { + value: "address", + }, + colon: Colon, + ty: Type { + value: Option { + angle: Angle, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "Address", + }, + angle: None, + generics: None, + }, + ), + }, + }, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "age", + }, + colon: Colon, + ty: Type { + value: U8, + }, + id: Some( + Id { + value: 3, + }, + ), + }, + Comma, ), - name: Name { - value: "birthday", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [ - Name { - value: "birthday", + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "birthday", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [ + Name { + value: "birthday", + }, + ], + name: Name { + value: "DayOfBirth", }, - ], - name: Name { - value: "DayOfBirth", + angle: None, + generics: None, }, - angle: None, - generics: [], + ), + }, + id: Some( + Id { + value: 4, }, ), }, - id: Some( - Id { - value: 4, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -187,78 +189,80 @@ Schema { name: Name { value: "FullName", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "first", - }, - colon: Colon, - ty: Type { - value: String, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "first", + }, + colon: Colon, + ty: Type { + value: String, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "middle", - }, - colon: Colon, - ty: Type { - value: Option { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "middle", + }, + colon: Colon, ty: Type { - value: String, + value: Option { + angle: Angle, + ty: Type { + value: String, + }, + }, }, + id: Some( + Id { + value: 2, + }, + ), }, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "last", - }, - colon: Colon, - ty: Type { - value: String, - }, - id: Some( - Id { - value: 3, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "last", }, - ), - comma: Some( + colon: Colon, + ty: Type { + value: String, + }, + id: Some( + Id { + value: 3, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -284,9 +288,7 @@ Schema { name: Name { value: "Name", }, - generics: Generics( - [], - ), + generics: None, equal: Equal, target: Type { value: External( @@ -296,7 +298,7 @@ Schema { value: "FullName", }, angle: None, - generics: [], + generics: None, }, ), }, @@ -315,90 +317,92 @@ Schema { name: Name { value: "Address", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [ - CommentLine { - value: "Street name.", + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [ + CommentLine { + value: "Street name.", + }, + ], + ), + name: Name { + value: "street", }, - ], - ), - name: Name { - value: "street", - }, - colon: Colon, - ty: Type { - value: String, - }, - id: Some( - Id { - value: 1, + colon: Colon, + ty: Type { + value: String, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [ - CommentLine { - value: "Number of the house in the street.", + ( + NamedField { + comment: Comment( + [ + CommentLine { + value: "Number of the house in the street.", + }, + ], + ), + name: Name { + value: "house_no", }, - ], - ), - name: Name { - value: "house_no", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "HouseNumber", - }, - angle: None, - generics: [], + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "HouseNumber", + }, + angle: None, + generics: None, + }, + ), }, - ), - }, - id: Some( - Id { - value: 2, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "city", - }, - colon: Colon, - ty: Type { - value: String, - }, - id: Some( - Id { - value: 3, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "city", }, - ), - comma: Some( + colon: Colon, + ty: Type { + value: String, + }, + id: Some( + Id { + value: 3, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -424,84 +428,92 @@ Schema { name: Name { value: "HouseNumber", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [ - CommentLine { - value: "Digit only number.", - }, - ], - ), - name: Name { - value: "Digit", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: U16, - }, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [ + CommentLine { + value: "Digit only number.", }, - ), - comma: None, + ], + ), + name: Name { + value: "Digit", }, - ], - ), - id: Some( - Id { - value: 1, + fields: Unnamed( + Parenthesis, + Punctuated { + values: [], + last: ( + UnnamedField { + ty: Type { + value: U16, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + None, + ), + }, + ), + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [ - CommentLine { - value: "Mixed _number_ with characters like `1a`.", - }, - ], - ), - name: Name { - value: "Text", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: String, + ], + last: ( + Variant { + comment: Comment( + [ + CommentLine { + value: "Mixed _number_ with characters like `1a`.", }, - id: Some( - Id { - value: 1, + ], + ), + name: Name { + value: "Text", + }, + fields: Unnamed( + Parenthesis, + Punctuated { + values: [], + last: ( + UnnamedField { + ty: Type { + value: String, + }, + id: Some( + Id { + value: 1, + }, + ), }, + None, ), - comma: None, }, - ], - ), - id: Some( - Id { - value: 2, - }, - ), - comma: Some( + ), + id: Some( + Id { + value: 2, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), Const( @@ -561,180 +573,189 @@ Schema { name: Name { value: "DayOfBirth", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Specific", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "year", - }, - colon: Colon, - ty: Type { - value: U16, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Specific", }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "month", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "year", + }, + colon: Colon, + ty: Type { + value: U16, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "month", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "Month", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 2, + }, + ), + }, + Comma, + ), + ], + last: ( + NamedField { + comment: Comment( + [], + ), name: Name { - value: "Month", + value: "day", + }, + colon: Colon, + ty: Type { + value: U8, }, - angle: None, - generics: [], + id: Some( + Id { + value: 3, + }, + ), }, + Some( + Comma, + ), ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( - Comma, - ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "day", - }, - colon: Colon, - ty: Type { - value: U8, + ), + id: Some( + Id { + value: 1, }, - id: Some( - Id { - value: 3, - }, - ), - comma: Some( - Comma, - ), - }, - ], - ), - id: Some( - Id { - value: 1, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [ - CommentLine { - value: "The user didn't want to say.", + ( + Variant { + comment: Comment( + [ + CommentLine { + value: "The user didn't want to say.", + }, + ], + ), + name: Name { + value: "Secret", }, - ], - ), - name: Name { - value: "Secret", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [ - CommentLine { - value: "Optional info from the user about why they didn't want to", - }, - CommentLine { - value: "reveal their birthday.", + fields: Named( + Brace, + Punctuated { + values: [], + last: ( + NamedField { + comment: Comment( + [ + CommentLine { + value: "Optional info from the user about why they didn't want to", + }, + CommentLine { + value: "reveal their birthday.", + }, + ], + ), + name: Name { + value: "reason", + }, + colon: Colon, + ty: Type { + value: Option { + angle: Angle, + ty: Type { + value: String, + }, + }, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ], - ), - name: Name { - value: "reason", + Some( + Comma, + ), + ), }, - colon: Colon, - ty: Type { - value: Option { - angle: Angle, - ty: Type { - value: String, - }, - }, + ), + id: Some( + Id { + value: 2, }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), - }, - ], - ), - id: Some( - Id { - value: 2, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [ - CommentLine { - value: "We never asked and nobody knows.", + ], + last: ( + Variant { + comment: Comment( + [ + CommentLine { + value: "We never asked and nobody knows.", + }, + ], + ), + name: Name { + value: "Unknown", + }, + fields: Unit, + id: Some( + Id { + value: 3, }, - ], - ), - name: Name { - value: "Unknown", + ), }, - fields: Unit, - id: Some( - Id { - value: 3, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, }, ), Const( @@ -808,216 +829,218 @@ Schema { name: Name { value: "Month", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "January", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "January", + }, + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "February", - }, - fields: Unit, - id: Some( - Id { - value: 2, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "February", + }, + fields: Unit, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "March", - }, - fields: Unit, - id: Some( - Id { - value: 3, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "March", + }, + fields: Unit, + id: Some( + Id { + value: 3, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "April", - }, - fields: Unit, - id: Some( - Id { - value: 4, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "April", + }, + fields: Unit, + id: Some( + Id { + value: 4, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "May", - }, - fields: Unit, - id: Some( - Id { - value: 5, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "May", + }, + fields: Unit, + id: Some( + Id { + value: 5, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "June", - }, - fields: Unit, - id: Some( - Id { - value: 6, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "June", + }, + fields: Unit, + id: Some( + Id { + value: 6, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "July", - }, - fields: Unit, - id: Some( - Id { - value: 7, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "July", + }, + fields: Unit, + id: Some( + Id { + value: 7, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "August", - }, - fields: Unit, - id: Some( - Id { - value: 8, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "August", + }, + fields: Unit, + id: Some( + Id { + value: 8, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "September", - }, - fields: Unit, - id: Some( - Id { - value: 9, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "September", + }, + fields: Unit, + id: Some( + Id { + value: 9, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "October", - }, - fields: Unit, - id: Some( - Id { - value: 10, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "October", + }, + fields: Unit, + id: Some( + Id { + value: 10, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "November", - }, - fields: Unit, - id: Some( - Id { - value: 11, + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "November", + }, + fields: Unit, + id: Some( + Id { + value: 11, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "December", - }, - fields: Unit, - id: Some( - Id { - value: 12, + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "December", }, - ), - comma: Some( + fields: Unit, + id: Some( + Id { + value: 12, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@module_basic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@module_basic.mabo.snap index 16aee3a..0b842d6 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@module_basic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@module_basic.mabo.snap @@ -50,29 +50,30 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "One", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "One", }, - ), - comma: Some( + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], @@ -90,66 +91,68 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "value", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "value", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "inner", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [ - Name { - value: "b", + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "inner", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [ + Name { + value: "b", + }, + ], + name: Name { + value: "Sample", }, - ], - name: Name { - value: "Sample", + angle: None, + generics: None, }, - angle: None, - generics: [], + ), + }, + id: Some( + Id { + value: 2, }, ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@optional_ids.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@optional_ids.mabo.snap index 36d3bfc..9d68f6b 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@optional_ids.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@optional_ids.mabo.snap @@ -24,65 +24,67 @@ Schema { name: Name { value: "SampleNamed", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: None, - comma: Some( + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field1", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: None, + }, Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field2", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 100, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 100, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field3", - }, - colon: Colon, - ty: Type { - value: U32, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field3", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: None, }, - id: None, - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -98,42 +100,44 @@ Schema { name: Name { value: "SampleUnnamed", }, - generics: Generics( - [], - ), + generics: None, fields: Unnamed( Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, - }, - id: None, - comma: Some( + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: None, + }, Comma, ), - }, - UnnamedField { - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 100, + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 100, + }, + ), }, - ), - comma: Some( Comma, ), - }, - UnnamedField { - ty: Type { - value: U32, + ], + last: ( + UnnamedField { + ty: Type { + value: U32, + }, + id: None, }, - id: None, - comma: None, - }, - ], + None, + ), + }, ), }, ), @@ -149,144 +153,154 @@ Schema { name: Name { value: "SampleEnum", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Named", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: None, - comma: Some( - Comma, - ), + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Named", }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field2", + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field1", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: None, + }, + Comma, + ), + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 100, + }, + ), + }, + Comma, + ), + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field3", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: None, + }, + Some( + Comma, + ), + ), }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 100, - }, - ), - comma: Some( - Comma, - ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field3", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: None, - comma: Some( - Comma, - ), - }, - ], - ), - id: None, - comma: Some( - Comma, - ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Unit", - }, - fields: Unit, - id: Some( - Id { - value: 50, + ), + id: None, }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Unnamed", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, - }, - id: None, - comma: Some( - Comma, - ), + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Unit", }, - UnnamedField { - ty: Type { - value: U32, + fields: Unit, + id: Some( + Id { + value: 50, }, - id: Some( - Id { - value: 100, + ), + }, + Comma, + ), + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Unnamed", + }, + fields: Unnamed( + Parenthesis, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: None, + }, + Comma, + ), + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 100, + }, + ), + }, + Comma, + ), + ], + last: ( + UnnamedField { + ty: Type { + value: U32, + }, + id: None, }, + None, ), - comma: Some( - Comma, - ), - }, - UnnamedField { - ty: Type { - value: U32, - }, - id: None, - comma: None, }, - ], - ), - id: None, - comma: Some( + ), + id: None, + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@schema_basic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@schema_basic.mabo.snap index 6c7446d..995399b 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@schema_basic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@schema_basic.mabo.snap @@ -28,53 +28,55 @@ Schema { name: Name { value: "SampleStruct", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "a", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "a", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "b", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "b", }, - ), - comma: Some( + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -94,135 +96,145 @@ Schema { name: Name { value: "SampleEnum", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "One", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [ + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "One", + }, + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Two", - }, - fields: Unnamed( - Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( - Comma, - ), + ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Two", }, - UnnamedField { - ty: Type { - value: U64, + fields: Unnamed( + Parenthesis, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ], + last: ( + UnnamedField { + ty: Type { + value: U64, + }, + id: Some( + Id { + value: 2, + }, + ), + }, + None, + ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: None, - }, - ], - ), - id: Some( - Id { - value: 2, + ), + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Three", - }, - fields: Named( - Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field1", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + ], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Three", + }, + fields: Named( + Brace, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field1", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), + }, + Comma, + ), + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "field2", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( - Comma, + Some( + Comma, + ), ), }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "field2", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( - Comma, - ), + ), + id: Some( + Id { + value: 3, }, - ], - ), - id: Some( - Id { - value: 3, - }, - ), - comma: Some( + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), ], diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@struct_basic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@struct_basic.mabo.snap index c0c0b24..5f82f1e 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@struct_basic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@struct_basic.mabo.snap @@ -28,57 +28,59 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "a", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "a", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [ - CommentLine { - value: "Second field", + ], + last: ( + NamedField { + comment: Comment( + [ + CommentLine { + value: "Second field", + }, + ], + ), + name: Name { + value: "b", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, }, - ], - ), - name: Name { - value: "b", - }, - colon: Colon, - ty: Type { - value: Bool, + ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@struct_generics.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@struct_generics.mabo.snap index 8ec89ad..8ac3639 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@struct_generics.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@struct_generics.mabo.snap @@ -28,78 +28,93 @@ Schema { name: Name { value: "KeyValue", }, - generics: Generics( - [ - Name { - value: "K", - }, - Name { - value: "V", + generics: Some( + Generics { + angle: Angle, + types: Punctuated { + values: [ + ( + Name { + value: "K", + }, + Comma, + ), + ], + last: ( + Name { + value: "V", + }, + None, + ), }, - ], + }, ), fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "key", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "K", - }, - angle: None, - generics: [], + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "key", }, - ), - }, - id: Some( - Id { - value: 1, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "K", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "value", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "V", + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "value", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "V", + }, + angle: None, + generics: None, }, - angle: None, - generics: [], + ), + }, + id: Some( + Id { + value: 2, }, ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@struct_many_ws.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@struct_many_ws.mabo.snap index 2cc99f0..4724abd 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@struct_many_ws.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@struct_many_ws.mabo.snap @@ -28,86 +28,97 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [ - Name { - value: "T", + generics: Some( + Generics { + angle: Angle, + types: Punctuated { + values: [], + last: ( + Name { + value: "T", + }, + None, + ), }, - ], + }, ), fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "a", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "a", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "b", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "b", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "c", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "T", + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "c", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + }, + angle: None, + generics: None, }, - angle: None, - generics: [], + ), + }, + id: Some( + Id { + value: 3, }, ), }, - id: Some( - Id { - value: 3, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@struct_min_ws.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@struct_min_ws.mabo.snap index 090c6b0..a159f07 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@struct_min_ws.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@struct_min_ws.mabo.snap @@ -24,84 +24,95 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [ - Name { - value: "T", + generics: Some( + Generics { + angle: Angle, + types: Punctuated { + values: [], + last: ( + Name { + value: "T", + }, + None, + ), }, - ], + }, ), fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "a", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "a", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "b", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "b", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "c", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "T", + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "c", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + }, + angle: None, + generics: None, }, - angle: None, - generics: [], + ), + }, + id: Some( + Id { + value: 3, }, ), }, - id: Some( - Id { - value: 3, - }, - ), - comma: None, - }, - ], + None, + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@struct_tuple.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@struct_tuple.mabo.snap index f8f7d79..c6ea62e 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@struct_tuple.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@struct_tuple.mabo.snap @@ -28,37 +28,39 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Unnamed( Parenthesis, - [ - UnnamedField { - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + UnnamedField { + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - UnnamedField { - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 2, + ], + last: ( + UnnamedField { + ty: Type { + value: Bool, }, - ), - comma: None, - }, - ], + id: Some( + Id { + value: 2, + }, + ), + }, + None, + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@types_basic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@types_basic.mabo.snap index e59f047..ede462d 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@types_basic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@types_basic.mabo.snap @@ -24,453 +24,466 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f01", - }, - colon: Colon, - ty: Type { - value: Bool, - }, - id: Some( - Id { - value: 1, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f01", + }, + colon: Colon, + ty: Type { + value: Bool, + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f02", - }, - colon: Colon, - ty: Type { - value: U8, - }, - id: Some( - Id { - value: 2, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f02", + }, + colon: Colon, + ty: Type { + value: U8, + }, + id: Some( + Id { + value: 2, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f03", - }, - colon: Colon, - ty: Type { - value: U16, - }, - id: Some( - Id { - value: 3, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f03", + }, + colon: Colon, + ty: Type { + value: U16, + }, + id: Some( + Id { + value: 3, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f04", - }, - colon: Colon, - ty: Type { - value: U32, - }, - id: Some( - Id { - value: 4, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f04", + }, + colon: Colon, + ty: Type { + value: U32, + }, + id: Some( + Id { + value: 4, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f05", - }, - colon: Colon, - ty: Type { - value: U64, - }, - id: Some( - Id { - value: 5, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f05", + }, + colon: Colon, + ty: Type { + value: U64, + }, + id: Some( + Id { + value: 5, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f06", - }, - colon: Colon, - ty: Type { - value: U128, - }, - id: Some( - Id { - value: 6, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f06", + }, + colon: Colon, + ty: Type { + value: U128, + }, + id: Some( + Id { + value: 6, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f07", - }, - colon: Colon, - ty: Type { - value: I8, - }, - id: Some( - Id { - value: 7, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f07", + }, + colon: Colon, + ty: Type { + value: I8, + }, + id: Some( + Id { + value: 7, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f08", - }, - colon: Colon, - ty: Type { - value: I16, - }, - id: Some( - Id { - value: 8, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f08", + }, + colon: Colon, + ty: Type { + value: I16, + }, + id: Some( + Id { + value: 8, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f09", - }, - colon: Colon, - ty: Type { - value: I32, - }, - id: Some( - Id { - value: 9, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f09", + }, + colon: Colon, + ty: Type { + value: I32, + }, + id: Some( + Id { + value: 9, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f10", - }, - colon: Colon, - ty: Type { - value: I64, - }, - id: Some( - Id { - value: 10, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f10", + }, + colon: Colon, + ty: Type { + value: I64, + }, + id: Some( + Id { + value: 10, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f11", - }, - colon: Colon, - ty: Type { - value: I128, - }, - id: Some( - Id { - value: 11, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f11", + }, + colon: Colon, + ty: Type { + value: I128, + }, + id: Some( + Id { + value: 11, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f12", - }, - colon: Colon, - ty: Type { - value: F32, - }, - id: Some( - Id { - value: 12, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f12", + }, + colon: Colon, + ty: Type { + value: F32, + }, + id: Some( + Id { + value: 12, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f13", - }, - colon: Colon, - ty: Type { - value: F64, - }, - id: Some( - Id { - value: 13, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f13", + }, + colon: Colon, + ty: Type { + value: F64, + }, + id: Some( + Id { + value: 13, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f14", - }, - colon: Colon, - ty: Type { - value: String, - }, - id: Some( - Id { - value: 14, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f14", + }, + colon: Colon, + ty: Type { + value: String, + }, + id: Some( + Id { + value: 14, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f15", - }, - colon: Colon, - ty: Type { - value: StringRef, - }, - id: Some( - Id { - value: 15, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f15", + }, + colon: Colon, + ty: Type { + value: StringRef, + }, + id: Some( + Id { + value: 15, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f16", - }, - colon: Colon, - ty: Type { - value: Bytes, - }, - id: Some( - Id { - value: 16, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f16", + }, + colon: Colon, + ty: Type { + value: Bytes, + }, + id: Some( + Id { + value: 16, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f17", - }, - colon: Colon, - ty: Type { - value: BytesRef, - }, - id: Some( - Id { - value: 17, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f17", + }, + colon: Colon, + ty: Type { + value: BytesRef, + }, + id: Some( + Id { + value: 17, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f18", - }, - colon: Colon, - ty: Type { - value: BoxString, - }, - id: Some( - Id { - value: 18, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f18", + }, + colon: Colon, + ty: Type { + value: BoxString, + }, + id: Some( + Id { + value: 18, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f19", - }, - colon: Colon, - ty: Type { - value: BoxBytes, - }, - id: Some( - Id { - value: 19, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f19", + }, + colon: Colon, + ty: Type { + value: BoxBytes, + }, + id: Some( + Id { + value: 19, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f20", - }, - colon: Colon, - ty: Type { - value: Tuple { - paren: Parenthesis, - types: [ - Type { - value: U32, - }, - Type { - value: U32, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f20", + }, + colon: Colon, + ty: Type { + value: Tuple { + paren: Parenthesis, + types: Punctuated { + values: [ + ( + Type { + value: U32, + }, + Comma, + ), + ( + Type { + value: U32, + }, + Comma, + ), + ], + last: ( + Type { + value: U32, + }, + None, + ), + }, }, - Type { - value: U32, + }, + id: Some( + Id { + value: 20, }, - ], - }, - }, - id: Some( - Id { - value: 20, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f21", - }, - colon: Colon, - ty: Type { - value: Array { - bracket: Bracket, - ty: Type { - value: U32, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f21", + }, + colon: Colon, + ty: Type { + value: Array { + bracket: Bracket, + ty: Type { + value: U32, + }, + semicolon: Semicolon, + size: 12, }, - semicolon: Semicolon, - size: 12, }, + id: Some( + Id { + value: 21, + }, + ), }, - id: Some( - Id { - value: 21, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@types_generic.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@types_generic.mabo.snap index 4527079..fc82845 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@types_generic.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@types_generic.mabo.snap @@ -24,142 +24,144 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f1", - }, - colon: Colon, - ty: Type { - value: Vec { - angle: Angle, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f1", + }, + colon: Colon, ty: Type { - value: U32, + value: Vec { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 1, + }, + ), }, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f2", - }, - colon: Colon, - ty: Type { - value: HashMap { - angle: Angle, - key: Type { - value: U32, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f2", }, - comma: Comma, - value: Type { - value: String, + colon: Colon, + ty: Type { + value: HashMap { + angle: Angle, + key: Type { + value: U32, + }, + comma: Comma, + value: Type { + value: String, + }, + }, }, + id: Some( + Id { + value: 2, + }, + ), }, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f3", - }, - colon: Colon, - ty: Type { - value: HashSet { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f3", + }, + colon: Colon, ty: Type { - value: U32, + value: HashSet { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 3, + }, + ), }, - }, - id: Some( - Id { - value: 3, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f4", - }, - colon: Colon, - ty: Type { - value: Option { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f4", + }, + colon: Colon, ty: Type { - value: U32, + value: Option { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 4, + }, + ), }, - }, - id: Some( - Id { - value: 4, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f5", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, - ty: Type { - value: U32, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f5", + }, + colon: Colon, + ty: Type { + value: NonZero { + angle: Angle, + ty: Type { + value: U32, + }, }, }, + id: Some( + Id { + value: 5, + }, + ), }, - id: Some( - Id { - value: 5, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -175,107 +177,109 @@ Schema { name: Name { value: "SampleUnnamed", }, - generics: Generics( - [], - ), + generics: None, fields: Unnamed( Parenthesis, - [ - UnnamedField { - ty: Type { - value: Vec { - angle: Angle, + Punctuated { + values: [ + ( + UnnamedField { ty: Type { - value: U32, + value: Vec { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 1, + }, + ), }, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( Comma, ), - }, - UnnamedField { - ty: Type { - value: HashMap { - angle: Angle, - key: Type { - value: U32, - }, - comma: Comma, - value: Type { - value: String, + ( + UnnamedField { + ty: Type { + value: HashMap { + angle: Angle, + key: Type { + value: U32, + }, + comma: Comma, + value: Type { + value: String, + }, + }, }, + id: Some( + Id { + value: 2, + }, + ), }, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( Comma, ), - }, - UnnamedField { - ty: Type { - value: HashSet { - angle: Angle, + ( + UnnamedField { ty: Type { - value: U32, + value: HashSet { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 3, + }, + ), }, - }, - id: Some( - Id { - value: 3, - }, - ), - comma: Some( Comma, ), - }, - UnnamedField { - ty: Type { - value: Option { - angle: Angle, + ( + UnnamedField { ty: Type { - value: U32, + value: Option { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 4, + }, + ), }, - }, - id: Some( - Id { - value: 4, - }, - ), - comma: Some( Comma, ), - }, - UnnamedField { - ty: Type { - value: NonZero { - angle: Angle, - ty: Type { - value: U32, + ], + last: ( + UnnamedField { + ty: Type { + value: NonZero { + angle: Angle, + ty: Type { + value: U32, + }, }, }, + id: Some( + Id { + value: 5, + }, + ), }, - id: Some( - Id { - value: 5, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@types_nested.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@types_nested.mabo.snap index 5311c26..8da85ab 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@types_nested.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@types_nested.mabo.snap @@ -24,38 +24,39 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "value", - }, - colon: Colon, - ty: Type { - value: Vec { - angle: Angle, - ty: Type { - value: Option { - angle: Angle, - ty: Type { - value: NonZero { - angle: Angle, - ty: Type { - value: HashMap { - angle: Angle, - key: Type { - value: I64, - }, - comma: Comma, - value: Type { - value: BoxString, + Punctuated { + values: [], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "value", + }, + colon: Colon, + ty: Type { + value: Vec { + angle: Angle, + ty: Type { + value: Option { + angle: Angle, + ty: Type { + value: NonZero { + angle: Angle, + ty: Type { + value: HashMap { + angle: Angle, + key: Type { + value: I64, + }, + comma: Comma, + value: Type { + value: BoxString, + }, }, }, }, @@ -64,17 +65,17 @@ Schema { }, }, }, + id: Some( + Id { + value: 1, + }, + ), }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@types_non_zero.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@types_non_zero.mabo.snap index 1f52a26..8d8be7c 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@types_non_zero.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@types_non_zero.mabo.snap @@ -24,407 +24,409 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f01", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f01", + }, + colon: Colon, ty: Type { - value: U8, + value: NonZero { + angle: Angle, + ty: Type { + value: U8, + }, + }, }, + id: Some( + Id { + value: 1, + }, + ), }, - }, - id: Some( - Id { - value: 1, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f02", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f02", + }, + colon: Colon, ty: Type { - value: U16, + value: NonZero { + angle: Angle, + ty: Type { + value: U16, + }, + }, }, + id: Some( + Id { + value: 2, + }, + ), }, - }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f03", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f03", + }, + colon: Colon, ty: Type { - value: U32, + value: NonZero { + angle: Angle, + ty: Type { + value: U32, + }, + }, }, + id: Some( + Id { + value: 3, + }, + ), }, - }, - id: Some( - Id { - value: 3, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f04", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f04", + }, + colon: Colon, ty: Type { - value: U64, + value: NonZero { + angle: Angle, + ty: Type { + value: U64, + }, + }, }, + id: Some( + Id { + value: 4, + }, + ), }, - }, - id: Some( - Id { - value: 4, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f05", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f05", + }, + colon: Colon, ty: Type { - value: U128, + value: NonZero { + angle: Angle, + ty: Type { + value: U128, + }, + }, }, + id: Some( + Id { + value: 5, + }, + ), }, - }, - id: Some( - Id { - value: 5, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f06", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f06", + }, + colon: Colon, ty: Type { - value: I8, + value: NonZero { + angle: Angle, + ty: Type { + value: I8, + }, + }, }, + id: Some( + Id { + value: 6, + }, + ), }, - }, - id: Some( - Id { - value: 6, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f07", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f07", + }, + colon: Colon, ty: Type { - value: I16, + value: NonZero { + angle: Angle, + ty: Type { + value: I16, + }, + }, }, + id: Some( + Id { + value: 7, + }, + ), }, - }, - id: Some( - Id { - value: 7, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f08", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f08", + }, + colon: Colon, ty: Type { - value: I32, + value: NonZero { + angle: Angle, + ty: Type { + value: I32, + }, + }, }, + id: Some( + Id { + value: 8, + }, + ), }, - }, - id: Some( - Id { - value: 8, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f09", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f09", + }, + colon: Colon, ty: Type { - value: I64, + value: NonZero { + angle: Angle, + ty: Type { + value: I64, + }, + }, }, + id: Some( + Id { + value: 9, + }, + ), }, - }, - id: Some( - Id { - value: 9, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f10", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f10", + }, + colon: Colon, ty: Type { - value: I128, + value: NonZero { + angle: Angle, + ty: Type { + value: I128, + }, + }, }, + id: Some( + Id { + value: 10, + }, + ), }, - }, - id: Some( - Id { - value: 10, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f11", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f11", + }, + colon: Colon, ty: Type { - value: String, + value: NonZero { + angle: Angle, + ty: Type { + value: String, + }, + }, }, + id: Some( + Id { + value: 11, + }, + ), }, - }, - id: Some( - Id { - value: 11, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f12", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f12", + }, + colon: Colon, ty: Type { - value: Bytes, + value: NonZero { + angle: Angle, + ty: Type { + value: Bytes, + }, + }, }, + id: Some( + Id { + value: 12, + }, + ), }, - }, - id: Some( - Id { - value: 12, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f13", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f13", + }, + colon: Colon, ty: Type { - value: Vec { + value: NonZero { angle: Angle, ty: Type { - value: String, + value: Vec { + angle: Angle, + ty: Type { + value: String, + }, + }, }, }, }, + id: Some( + Id { + value: 13, + }, + ), }, - }, - id: Some( - Id { - value: 13, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f14", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f14", + }, + colon: Colon, ty: Type { - value: HashMap { + value: NonZero { angle: Angle, - key: Type { - value: String, - }, - comma: Comma, - value: Type { - value: Bytes, + ty: Type { + value: HashMap { + angle: Angle, + key: Type { + value: String, + }, + comma: Comma, + value: Type { + value: Bytes, + }, + }, }, }, }, + id: Some( + Id { + value: 14, + }, + ), }, - }, - id: Some( - Id { - value: 14, - }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "f15", - }, - colon: Colon, - ty: Type { - value: NonZero { - angle: Angle, - ty: Type { - value: HashSet { - angle: Angle, - ty: Type { - value: String, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "f15", + }, + colon: Colon, + ty: Type { + value: NonZero { + angle: Angle, + ty: Type { + value: HashSet { + angle: Angle, + ty: Type { + value: String, + }, }, }, }, }, + id: Some( + Id { + value: 15, + }, + ), }, - id: Some( - Id { - value: 15, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), diff --git a/crates/mabo-parser/tests/snapshots/parser__parse@types_ref.mabo.snap b/crates/mabo-parser/tests/snapshots/parser__parse@types_ref.mabo.snap index ded432b..45a8925 100644 --- a/crates/mabo-parser/tests/snapshots/parser__parse@types_ref.mabo.snap +++ b/crates/mabo-parser/tests/snapshots/parser__parse@types_ref.mabo.snap @@ -24,80 +24,92 @@ Schema { name: Name { value: "Sample", }, - generics: Generics( - [], - ), + generics: None, fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "basic", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "Test123", - }, - angle: None, - generics: [], + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "basic", }, - ), - }, - id: Some( - Id { - value: 1, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "Test123", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "with_generics", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "KeyValue", - }, - angle: Some( - Angle, - ), - generics: [ - Type { - value: U32, - }, - Type { - value: Bool, + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "with_generics", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "KeyValue", }, - ], + angle: Some( + Angle, + ), + generics: Some( + Punctuated { + values: [ + ( + Type { + value: U32, + }, + Comma, + ), + ], + last: ( + Type { + value: Bool, + }, + None, + ), + }, + ), + }, + ), + }, + id: Some( + Id { + value: 2, }, ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ), @@ -113,29 +125,30 @@ Schema { name: Name { value: "Test123", }, - generics: Generics( - [], - ), + generics: None, brace: Brace, - variants: [ - Variant { - comment: Comment( - [], - ), - name: Name { - value: "Value", - }, - fields: Unit, - id: Some( - Id { - value: 1, + variants: Punctuated { + values: [], + last: ( + Variant { + comment: Comment( + [], + ), + name: Name { + value: "Value", }, - ), - comma: Some( + fields: Unit, + id: Some( + Id { + value: 1, + }, + ), + }, + Some( Comma, ), - }, - ], + ), + }, }, ), Struct( @@ -150,78 +163,93 @@ Schema { name: Name { value: "KeyValue", }, - generics: Generics( - [ - Name { - value: "K", - }, - Name { - value: "V", + generics: Some( + Generics { + angle: Angle, + types: Punctuated { + values: [ + ( + Name { + value: "K", + }, + Comma, + ), + ], + last: ( + Name { + value: "V", + }, + None, + ), }, - ], + }, ), fields: Named( Brace, - [ - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "key", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "K", - }, - angle: None, - generics: [], + Punctuated { + values: [ + ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "key", }, - ), - }, - id: Some( - Id { - value: 1, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "K", + }, + angle: None, + generics: None, + }, + ), + }, + id: Some( + Id { + value: 1, + }, + ), }, - ), - comma: Some( Comma, ), - }, - NamedField { - comment: Comment( - [], - ), - name: Name { - value: "value", - }, - colon: Colon, - ty: Type { - value: External( - ExternalType { - path: [], - name: Name { - value: "V", + ], + last: ( + NamedField { + comment: Comment( + [], + ), + name: Name { + value: "value", + }, + colon: Colon, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "V", + }, + angle: None, + generics: None, }, - angle: None, - generics: [], + ), + }, + id: Some( + Id { + value: 2, }, ), }, - id: Some( - Id { - value: 2, - }, - ), - comma: Some( + Some( Comma, ), - }, - ], + ), + }, ), }, ),