From abcee058c95f1974431e0fe683bda58a6bd9ffd6 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Fri, 3 Nov 2023 23:30:46 +0900 Subject: [PATCH] feat: validate the element amount in tuples A valid tuple type must have between 2 and 12 elements. Empty tuples carry no data at all, tuples with one element are equivalent to the type of that single element and tuples with 13 or more elements are above a reasonable limit. --- crates/stef-build/src/decode.rs | 20 +- crates/stef-build/src/definition.rs | 17 +- crates/stef-build/src/encode.rs | 30 +- crates/stef-compiler/src/highlight.rs | 10 +- crates/stef-compiler/src/resolve/mod.rs | 50 +-- crates/stef-compiler/src/validate/generics.rs | 6 +- crates/stef-compiler/src/validate/mod.rs | 16 +- crates/stef-compiler/src/validate/tuples.rs | 128 ++++++++ .../inputs/validate/alias_tuple_empty.stef | 1 + .../inputs/validate/alias_tuple_single.stef | 1 + .../validate/alias_tuple_too_large.stef | 1 + .../validate/enum_named_tuple_empty.stef | 6 + .../validate/enum_named_tuple_single.stef | 6 + .../validate/enum_named_tuple_too_large.stef | 6 + .../validate/enum_unnamed_tuple_empty.stef | 4 + .../validate/enum_unnamed_tuple_single.stef | 4 + .../enum_unnamed_tuple_too_large.stef | 4 + .../validate/struct_named_tuple_empty.stef | 3 + .../validate/struct_named_tuple_single.stef | 3 + .../struct_named_tuple_too_large.stef | 3 + .../validate/struct_unnamed_tuple_empty.stef | 1 + .../validate/struct_unnamed_tuple_single.stef | 1 + .../struct_unnamed_tuple_too_large.stef | 1 + ...error_validate@alias_tuple_empty.stef.snap | 14 + ...rror_validate@alias_tuple_single.stef.snap | 14 + ...r_validate@alias_tuple_too_large.stef.snap | 14 + ..._validate@enum_named_tuple_empty.stef.snap | 19 ++ ...validate@enum_named_tuple_single.stef.snap | 19 ++ ...idate@enum_named_tuple_too_large.stef.snap | 19 ++ ...alidate@enum_unnamed_tuple_empty.stef.snap | 17 + ...lidate@enum_unnamed_tuple_single.stef.snap | 17 + ...ate@enum_unnamed_tuple_too_large.stef.snap | 17 + ...alidate@struct_named_tuple_empty.stef.snap | 16 + ...lidate@struct_named_tuple_single.stef.snap | 16 + ...ate@struct_named_tuple_too_large.stef.snap | 16 + ...idate@struct_unnamed_tuple_empty.stef.snap | 14 + ...date@struct_unnamed_tuple_single.stef.snap | 14 + ...e@struct_unnamed_tuple_too_large.stef.snap | 14 + crates/stef-parser/src/lib.rs | 109 ++++--- crates/stef-parser/src/parser/types.rs | 11 +- .../parser__parse@alias_basic.stef.snap | 8 +- .../parser__parse@const_basic.stef.snap | 48 ++- .../parser__parse@const_string.stef.snap | 32 +- .../parser__parse@enum_basic.stef.snap | 32 +- .../parser__parse@enum_generics.stef.snap | 104 +++--- .../parser__parse@enum_many_ws.stef.snap | 32 +- .../parser__parse@enum_min_ws.stef.snap | 84 +++-- .../parser__parse@module_basic.stef.snap | 8 +- .../parser__parse@schema_basic.stef.snap | 48 ++- .../parser__parse@struct_basic.stef.snap | 16 +- .../parser__parse@struct_generics.stef.snap | 52 +-- .../parser__parse@struct_many_ws.stef.snap | 42 ++- .../parser__parse@struct_min_ws.stef.snap | 42 ++- .../parser__parse@struct_tuple.stef.snap | 16 +- .../parser__parse@types_basic.stef.snap | 210 ++++++++++-- .../parser__parse@types_generic.stef.snap | 100 +++++- .../parser__parse@types_nested.stef.snap | 56 +++- .../parser__parse@types_non_zero.stef.snap | 306 +++++++++++++++--- .../parser__parse@types_ref.stef.snap | 122 ++++--- 59 files changed, 1645 insertions(+), 395 deletions(-) create mode 100644 crates/stef-compiler/src/validate/tuples.rs create mode 100644 crates/stef-compiler/tests/inputs/validate/alias_tuple_empty.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/alias_tuple_single.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/alias_tuple_too_large.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/enum_named_tuple_empty.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/enum_named_tuple_single.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/enum_named_tuple_too_large.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_single.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_too_large.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/struct_named_tuple_empty.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/struct_named_tuple_single.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/struct_named_tuple_too_large.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_single.stef create mode 100644 crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_too_large.stef create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_single.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_too_large.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_single.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_too_large.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_single.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_too_large.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_single.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_too_large.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_single.stef.snap create mode 100644 crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_too_large.stef.snap diff --git a/crates/stef-build/src/decode.rs b/crates/stef-build/src/decode.rs index 87e6761..00b562c 100644 --- a/crates/stef-build/src/decode.rs +++ b/crates/stef-build/src/decode.rs @@ -1,6 +1,8 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; -use stef_parser::{DataType, Enum, Fields, Generics, NamedField, Struct, UnnamedField, Variant}; +use stef_parser::{ + DataType, Enum, Fields, Generics, NamedField, Struct, Type, UnnamedField, Variant, +}; pub fn compile_struct( Struct { @@ -125,7 +127,7 @@ fn compile_field_vars(fields: &Fields<'_>) -> TokenStream { let vars = vars.map(|(name, ty)| { let ty_ident = super::definition::compile_data_type(ty); - if matches!(ty, DataType::Option(_)) { + if matches!(ty.value, DataType::Option(_)) { quote! { let mut #name: #ty_ident = None; } } else { quote! { let mut #name: Option<#ty_ident> = None; } @@ -148,7 +150,7 @@ fn compile_field_matches(fields: &Fields<'_>) -> TokenStream { }| { let id = proc_macro2::Literal::u32_unsuffixed(id.get()); let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - let ty = compile_data_type(if let DataType::Option(ty) = ty { + let ty = compile_data_type(if let DataType::Option(ty) = &ty.value { ty } else { ty @@ -167,7 +169,7 @@ fn compile_field_matches(fields: &Fields<'_>) -> TokenStream { .map(|(idx, UnnamedField { ty, id, .. })| { let id = proc_macro2::Literal::u32_unsuffixed(id.get()); let name = Ident::new(&format!("n{idx}"), Span::call_site()); - let ty = compile_data_type(if let DataType::Option(ty) = ty { + let ty = compile_data_type(if let DataType::Option(ty) = &ty.value { ty } else { ty @@ -190,7 +192,7 @@ fn compile_field_assigns(fields: &Fields<'_>) -> TokenStream { let name_lit = proc_macro2::Literal::string(named.name.get()); let id = proc_macro2::Literal::u32_unsuffixed(named.id.get()); - if matches!(named.ty, DataType::Option(_)) { + if matches!(named.ty.value, DataType::Option(_)) { quote! { #name } } else { quote! { #name: #name.ok_or(::stef::buf::Error::MissingField { @@ -207,7 +209,7 @@ fn compile_field_assigns(fields: &Fields<'_>) -> TokenStream { let name = Ident::new(&format!("n{idx}"), Span::call_site()); let id = proc_macro2::Literal::u32_unsuffixed(unnamed.id.get()); - if matches!(unnamed.ty, DataType::Option(_)) { + if matches!(unnamed.ty.value, DataType::Option(_)) { quote! { #name } } else { quote! { #name.ok_or(::stef::buf::Error::MissingField { @@ -240,8 +242,8 @@ fn compile_generics(Generics(types): &Generics<'_>) -> (TokenStream, TokenStream } #[allow(clippy::needless_pass_by_value)] -fn compile_data_type(ty: &DataType<'_>) -> TokenStream { - match ty { +fn compile_data_type(ty: &Type<'_>) -> TokenStream { + match &ty.value { DataType::Bool => quote! { ::stef::buf::decode_bool(r) }, DataType::U8 => quote! { ::stef::buf::decode_u8(r) }, DataType::U16 => quote! { ::stef::buf::decode_u16(r) }, @@ -274,7 +276,7 @@ fn compile_data_type(ty: &DataType<'_>) -> TokenStream { let ty = compile_data_type(ty); quote! { ::stef::buf::decode_option(r, |r| { #ty }) } } - DataType::NonZero(ty) => match &**ty { + DataType::NonZero(ty) => match &ty.value { DataType::U8 => quote! { ::stef::buf::decode_non_zero_u8(r) }, DataType::U16 => quote! { ::stef::buf::decode_non_zero_u16(r) }, DataType::U32 => quote! { ::stef::buf::decode_non_zero_u32(r) }, diff --git a/crates/stef-build/src/definition.rs b/crates/stef-build/src/definition.rs index 42dc3d7..c289c2c 100644 --- a/crates/stef-build/src/definition.rs +++ b/crates/stef-build/src/definition.rs @@ -2,7 +2,7 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; use stef_parser::{ Comment, Const, DataType, Definition, Enum, ExternalType, Fields, Generics, Import, Literal, - Module, Name, NamedField, Schema, Struct, TypeAlias, UnnamedField, Variant, + Module, Name, NamedField, Schema, Struct, Type, TypeAlias, UnnamedField, Variant, }; use super::{decode, encode}; @@ -215,10 +215,7 @@ fn compile_fields(fields: &Fields<'_>, for_struct: bool) -> TokenStream { Fields::Named(named) => { let fields = named.iter().map( |NamedField { - comment, - name, - ty, - .. + comment, name, ty, .. }| { let comment = compile_comment(comment); let public = for_struct.then(|| quote! { pub }); @@ -258,8 +255,8 @@ fn compile_fields(fields: &Fields<'_>, for_struct: bool) -> TokenStream { } } -pub(super) fn compile_data_type(ty: &DataType<'_>) -> TokenStream { - match ty { +pub(super) fn compile_data_type(ty: &Type<'_>) -> TokenStream { + match &ty.value { DataType::Bool => quote! { bool }, DataType::U8 => quote! { u8 }, DataType::U16 => quote! { u16 }, @@ -292,7 +289,7 @@ pub(super) fn compile_data_type(ty: &DataType<'_>) -> TokenStream { let ty = compile_data_type(ty); quote! { Option<#ty> } } - DataType::NonZero(ty) => match &**ty { + DataType::NonZero(ty) => match &ty.value { DataType::U8 => quote! { ::std::num::NonZeroU8 }, DataType::U16 => quote! { ::std::num::NonZeroU16 }, DataType::U32 => quote! { ::std::num::NonZeroU32 }, @@ -350,8 +347,8 @@ pub(super) fn compile_data_type(ty: &DataType<'_>) -> TokenStream { } } -fn compile_const_data_type(ty: &DataType<'_>) -> TokenStream { - match ty { +fn compile_const_data_type(ty: &Type<'_>) -> TokenStream { + match &ty.value { DataType::Bool => quote! { bool }, DataType::U8 => quote! { u8 }, DataType::U16 => quote! { u16 }, diff --git a/crates/stef-build/src/encode.rs b/crates/stef-build/src/encode.rs index f9a6e08..e8e555e 100644 --- a/crates/stef-build/src/encode.rs +++ b/crates/stef-build/src/encode.rs @@ -1,6 +1,8 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; -use stef_parser::{DataType, Enum, Fields, Generics, NamedField, Struct, UnnamedField, Variant}; +use stef_parser::{ + DataType, Enum, Fields, Generics, NamedField, Struct, Type, UnnamedField, Variant, +}; pub fn compile_struct( Struct { @@ -45,8 +47,8 @@ fn compile_struct_fields(fields: &Fields<'_>) -> TokenStream { let id = proc_macro2::Literal::u32_unsuffixed(id.get()); let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - if let DataType::Option(ty) = ty { - let ty = compile_data_type(ty, if is_copy(ty) { + if let DataType::Option(ty) = &ty.value { + let ty = compile_data_type(ty, if is_copy(&ty.value) { quote! { *v } } else { quote! { v } @@ -177,7 +179,7 @@ fn compile_variant_fields(fields: &Fields<'_>) -> TokenStream { let id = proc_macro2::Literal::u32_unsuffixed(id.get()); let name = proc_macro2::Ident::new(name.get(), Span::call_site()); - if matches!(ty, DataType::Option(_)) { + if matches!(ty.value, DataType::Option(_)) { quote! { ::stef::buf::encode_field_option(w, #id, &#name); } } else { let ty = compile_data_type(ty, quote! { *#name }); @@ -248,8 +250,8 @@ fn is_copy(ty: &DataType<'_>) -> bool { } #[allow(clippy::needless_pass_by_value, clippy::too_many_lines)] -fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { - match ty { +fn compile_data_type(ty: &Type<'_>, name: TokenStream) -> TokenStream { + match &ty.value { DataType::Bool => quote! { ::stef::buf::encode_bool(w, #name) }, DataType::U8 => quote! { ::stef::buf::encode_u8(w, #name) }, DataType::U16 => quote! { ::stef::buf::encode_u16(w, #name) }, @@ -268,7 +270,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::Vec(ty) => { let ty = compile_data_type( ty, - if is_copy(ty) { + if is_copy(&ty.value) { quote! { *v } } else { quote! { v } @@ -279,7 +281,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::HashMap(kv) => { let ty_k = compile_data_type( &kv.0, - if is_copy(&kv.0) { + if is_copy(&kv.0.value) { quote! { *k } } else { quote! { k } @@ -287,7 +289,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { ); let ty_v = compile_data_type( &kv.1, - if is_copy(&kv.1) { + if is_copy(&kv.1.value) { quote! { *v } } else { quote! { v } @@ -298,7 +300,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::HashSet(ty) => { let ty = compile_data_type( ty, - if is_copy(ty) { + if is_copy(&ty.value) { quote! { *v } } else { quote! { v } @@ -309,7 +311,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::Option(ty) => { let ty = compile_data_type( ty, - if is_copy(ty) { + if is_copy(&ty.value) { quote! { *v } } else { quote! { v } @@ -317,7 +319,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { ); quote! { ::stef::buf::encode_option(w, &#name, |w, v| { #ty; }) } } - DataType::NonZero(ty) => match &**ty { + DataType::NonZero(ty) => match &ty.value { DataType::U8 => quote! { ::stef::buf::encode_u8(w, #name.get()) }, DataType::U16 => quote! { ::stef::buf::encode_u16(w, #name.get()) }, DataType::U32 => quote! { ::stef::buf::encode_u32(w, #name.get()) }, @@ -346,7 +348,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { let idx = proc_macro2::Literal::usize_unsuffixed(idx); compile_data_type( ty, - if is_copy(ty) { + if is_copy(&ty.value) { quote! { #name.#idx } } else { quote! { &(#name.#idx) } @@ -362,7 +364,7 @@ fn compile_data_type(ty: &DataType<'_>, name: TokenStream) -> TokenStream { DataType::Array(ty, _size) => { let ty = compile_data_type( ty, - if is_copy(ty) { + if is_copy(&ty.value) { quote! { *v } } else { quote! { v } diff --git a/crates/stef-compiler/src/highlight.rs b/crates/stef-compiler/src/highlight.rs index b86adfa..68465a8 100644 --- a/crates/stef-compiler/src/highlight.rs +++ b/crates/stef-compiler/src/highlight.rs @@ -14,6 +14,14 @@ pub fn value(value: impl Display) -> String { if cfg!(feature = "debug") { format!("❬Y❭{value}❬Y❭") } else { - value.bright_yellow().bold().to_string() + value.bright_yellow().to_string() + } +} + +pub fn focus(value: impl Display) -> String { + if cfg!(feature = "debug") { + format!("❬W❭{value}❬W❭") + } else { + value.bright_white().to_string() } } diff --git a/crates/stef-compiler/src/resolve/mod.rs b/crates/stef-compiler/src/resolve/mod.rs index de0dac0..e595cc3 100644 --- a/crates/stef-compiler/src/resolve/mod.rs +++ b/crates/stef-compiler/src/resolve/mod.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use miette::NamedSource; use stef_parser::{ - DataType, Definition, ExternalType, Fields, Generics, Import, Name, Schema, Spanned, + DataType, Definition, ExternalType, Fields, Generics, Import, Name, Schema, Spanned, Type, }; pub use self::error::{ @@ -77,18 +77,18 @@ pub(crate) struct Module<'a> { /// List of imports declared in the module. imports: Vec<&'a Import<'a>>, /// List of types that are declared in this module. - types: Vec>, + types: Vec>, /// Directly submodules located in this module. modules: HashMap<&'a str, Module<'a>>, definitions: &'a [Definition<'a>], } -struct Type<'a> { - kind: TypeKind, +struct Declaration<'a> { + kind: DeclarationKind, name: Name<'a>, } -enum TypeKind { +enum DeclarationKind { Struct { generics: usize }, Enum { generics: usize }, Alias, @@ -129,7 +129,7 @@ impl<'a> Module<'a> { })?; match definition.kind { - TypeKind::Struct { generics } | TypeKind::Enum { generics } + DeclarationKind::Struct { generics } | DeclarationKind::Enum { generics } if generics != ty.generics.len() => { Err(GenericsCount { @@ -140,13 +140,13 @@ impl<'a> Module<'a> { } .into()) } - TypeKind::Alias => Err(InvalidKind { + DeclarationKind::Alias => Err(InvalidKind { kind: "type alias", declared: definition.name.span().into(), used: ty.name.span().into(), } .into()), - TypeKind::Const => Err(InvalidKind { + DeclarationKind::Const => Err(InvalidKind { kind: "constant", declared: definition.name.span().into(), used: ty.name.span().into(), @@ -185,19 +185,19 @@ impl<'a> Module<'a> { })?; match definition.kind { - TypeKind::Alias => Err(InvalidKind { + DeclarationKind::Alias => Err(InvalidKind { kind: "alias", declared: definition.name.span().into(), used: element.span().into(), } .into()), - TypeKind::Const => Err(InvalidKind { + DeclarationKind::Const => Err(InvalidKind { kind: "const", declared: definition.name.span().into(), used: element.span().into(), } .into()), - TypeKind::Struct { generics } | TypeKind::Enum { generics } => { + DeclarationKind::Struct { generics } | DeclarationKind::Enum { generics } => { Ok(ResolvedImport::Type { schema: self.schema, name: &definition.name, @@ -238,7 +238,7 @@ impl<'a> Module<'a> { })?; match definition.kind { - TypeKind::Struct { generics } | TypeKind::Enum { generics } + DeclarationKind::Struct { generics } | DeclarationKind::Enum { generics } if generics != ty.generics.len() => { Err(RemoteGenericsCount { @@ -258,7 +258,7 @@ impl<'a> Module<'a> { } .into()) } - TypeKind::Alias => Err(RemoteInvalidKind { + DeclarationKind::Alias => Err(RemoteInvalidKind { kind: "type alias", used: ty.name.span().into(), declaration: [RemoteInvalidKindDeclaration { @@ -274,7 +274,7 @@ impl<'a> Module<'a> { }], } .into()), - TypeKind::Const => Err(RemoteInvalidKind { + DeclarationKind::Const => Err(RemoteInvalidKind { kind: "constant", used: ty.name.span().into(), declaration: [RemoteInvalidKindDeclaration { @@ -315,7 +315,7 @@ pub(crate) fn resolve_module_types<'a>( fn resolve<'a>( missing: &mut Vec>, - ty: &'a DataType<'_>, + ty: &'a Type<'_>, generics: &Generics<'_>, module: &'a Module<'_>, ) { @@ -409,24 +409,24 @@ fn visit_module_tree<'a>( visit_module_tree(m.name.get(), schema, &module.path2, &m.definitions), ); } - Definition::Struct(s) => module.types.push(Type { - kind: TypeKind::Struct { + Definition::Struct(s) => module.types.push(Declaration { + kind: DeclarationKind::Struct { generics: s.generics.0.len(), }, name: s.name.clone(), }), - Definition::Enum(e) => module.types.push(Type { - kind: TypeKind::Enum { + Definition::Enum(e) => module.types.push(Declaration { + kind: DeclarationKind::Enum { generics: e.generics.0.len(), }, name: e.name.clone(), }), - Definition::TypeAlias(a) => module.types.push(Type { - kind: TypeKind::Alias, + Definition::TypeAlias(a) => module.types.push(Declaration { + kind: DeclarationKind::Alias, name: a.name.clone(), }), - Definition::Const(c) => module.types.push(Type { - kind: TypeKind::Const, + Definition::Const(c) => module.types.push(Declaration { + kind: DeclarationKind::Const, name: c.name.clone(), }), Definition::Import(i) => module.imports.push(i), @@ -436,8 +436,8 @@ fn visit_module_tree<'a>( module } -fn visit_externals<'a>(value: &'a DataType<'_>, visit: &mut impl FnMut(&'a ExternalType<'_>)) { - match value { +fn visit_externals<'a>(value: &'a Type<'_>, visit: &mut impl FnMut(&'a ExternalType<'_>)) { + match &value.value { DataType::Bool | DataType::U8 | DataType::U16 diff --git a/crates/stef-compiler/src/validate/generics.rs b/crates/stef-compiler/src/validate/generics.rs index d69d633..5696145 100644 --- a/crates/stef-compiler/src/validate/generics.rs +++ b/crates/stef-compiler/src/validate/generics.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, ops::Range}; use miette::Diagnostic; -use stef_parser::{DataType, Enum, ExternalType, Fields, Generics, Span, Spanned, Struct}; +use stef_parser::{DataType, Enum, ExternalType, Fields, Generics, Span, Spanned, Struct, Type}; use thiserror::Error; /// Generic type parameters are considered invalid. @@ -133,8 +133,8 @@ fn validate_field_generics(value: &Fields<'_>, unvisited: &mut HashMap<&str, Spa /// Iterate recursively through the data type and invoke the closure on each discovered external /// type. -fn visit_externals(value: &DataType<'_>, visit: &mut impl FnMut(&ExternalType<'_>)) { - match value { +fn visit_externals(value: &Type<'_>, visit: &mut impl FnMut(&ExternalType<'_>)) { + match &value.value { DataType::Bool | DataType::U8 | DataType::U16 diff --git a/crates/stef-compiler/src/validate/mod.rs b/crates/stef-compiler/src/validate/mod.rs index 653f88d..001abb1 100644 --- a/crates/stef-compiler/src/validate/mod.rs +++ b/crates/stef-compiler/src/validate/mod.rs @@ -12,11 +12,13 @@ pub use self::{ DuplicateVariantId, }, names::{DuplicateFieldName, DuplicateName, DuplicateNameInModule, DuplicateVariantName}, + tuples::{InvalidTupleAmount, TupleSize}, }; mod generics; mod ids; mod names; +mod tuples; /// Reason why a schema was invalid. #[derive(Debug, Diagnostic, Error)] @@ -33,6 +35,10 @@ pub enum Error { #[error("invalid generic type found")] #[diagnostic(transparent)] InvalidGeneric(#[from] InvalidGenericType), + /// Tuple type defined with too few or too many elements. + #[error("invalid tuple element size found")] + #[diagnostic(transparent)] + TupleSize(#[from] TupleSize), } impl From for Error { @@ -72,13 +78,21 @@ fn definition(value: &Definition<'_>) -> Result<(), Error> { ids::validate_struct_ids(s)?; names::validate_struct_names(s)?; generics::validate_struct_generics(s)?; + tuples::validate_struct_tuples(s)?; } Definition::Enum(e) => { ids::validate_enum_ids(e)?; names::validate_enum_names(e)?; generics::validate_enum_generics(e)?; + tuples::validate_enum_tuples(e)?; + } + Definition::TypeAlias(a) => { + tuples::validate_alias_tuples(a)?; + } + Definition::Const(c) => { + tuples::validate_const_tuples(c)?; } - Definition::TypeAlias(_) | Definition::Const(_) | Definition::Import(_) => {} + Definition::Import(_) => {} } Ok(()) diff --git a/crates/stef-compiler/src/validate/tuples.rs b/crates/stef-compiler/src/validate/tuples.rs new file mode 100644 index 0000000..9843258 --- /dev/null +++ b/crates/stef-compiler/src/validate/tuples.rs @@ -0,0 +1,128 @@ +use std::ops::Range; + +use miette::{diagnostic, Diagnostic}; +use stef_parser::{Const, DataType, Enum, Fields, Spanned, Struct, Type, TypeAlias}; +use thiserror::Error; + +use crate::highlight; + +/// Tuple with an invalid amount of elements was encountered. +#[derive(Debug, Diagnostic, Error)] +#[error( + "tuples with {} are invalid", + highlight::focus(match amount { + InvalidTupleAmount::Empty => "zero elements", + InvalidTupleAmount::Single => "a single element", + InvalidTupleAmount::TooLarge => "more than 12 elements" + }) +)] +#[diagnostic(help("a tuple must have between 2 and 12 elements"))] +pub struct TupleSize { + /// The amount that's not allowed. + pub amount: InvalidTupleAmount, + #[label("declared here")] + declared: Range, +} + +/// Possible amount of tuple elements that are invalid. +#[derive(Debug)] +pub enum InvalidTupleAmount { + /// Tuple with zero elements. + Empty, + /// Single element tuple. + Single, + /// More than 12 elements. + TooLarge, +} + +pub(crate) fn validate_struct_tuples(value: &Struct<'_>) -> Result<(), TupleSize> { + validate_field_tuples(&value.fields) +} + +pub(crate) fn validate_enum_tuples(value: &Enum<'_>) -> Result<(), TupleSize> { + value + .variants + .iter() + .try_for_each(|variant| validate_field_tuples(&variant.fields)) +} + +fn validate_field_tuples(value: &Fields<'_>) -> Result<(), TupleSize> { + match value { + Fields::Named(named) => named + .iter() + .try_for_each(|field| validate_tuple_size(&field.ty)), + Fields::Unnamed(unnamed) => unnamed + .iter() + .try_for_each(|field| validate_tuple_size(&field.ty)), + Fields::Unit => Ok(()), + } +} + +pub(crate) fn validate_alias_tuples(value: &TypeAlias<'_>) -> Result<(), TupleSize> { + validate_tuple_size(&value.target) +} + +pub(crate) fn validate_const_tuples(value: &Const<'_>) -> Result<(), TupleSize> { + validate_tuple_size(&value.ty) +} + +fn validate_tuple_size(value: &Type<'_>) -> Result<(), TupleSize> { + visit_tuples(value, &mut |tuples| { + let amount = match tuples.len() { + 0 => InvalidTupleAmount::Empty, + 1 => InvalidTupleAmount::Single, + 2..=12 => return Ok(()), + _ => InvalidTupleAmount::TooLarge, + }; + Err(TupleSize { + amount, + declared: value.span().into(), + }) + }) +} + +/// Iterate recursively through the data type and invoke the closure on each discovered external +/// type. +fn visit_tuples( + value: &Type<'_>, + visit: &mut impl FnMut(&[Type<'_>]) -> Result<(), E>, +) -> Result<(), E> { + match &value.value { + DataType::Bool + | DataType::U8 + | DataType::U16 + | DataType::U32 + | DataType::U64 + | DataType::U128 + | DataType::I8 + | DataType::I16 + | DataType::I32 + | DataType::I64 + | DataType::I128 + | DataType::F32 + | DataType::F64 + | DataType::String + | DataType::StringRef + | DataType::Bytes + | DataType::BytesRef + | DataType::NonZero(_) + | DataType::BoxString + | DataType::BoxBytes => Ok(()), + DataType::Vec(ty) + | DataType::HashSet(ty) + | DataType::Option(ty) + | DataType::Array(ty, _) => visit_tuples(ty, visit), + DataType::HashMap(kv) => { + visit_tuples(&kv.0, visit)?; + visit_tuples(&kv.1, visit) + } + DataType::Tuple(types) => { + visit(types)?; + types.iter().try_for_each(|ty| visit_tuples(ty, visit)) + } + DataType::External(ty) => ty + .generics + .iter() + .try_for_each(|ty| visit_tuples(ty, visit)), + } +} diff --git a/crates/stef-compiler/tests/inputs/validate/alias_tuple_empty.stef b/crates/stef-compiler/tests/inputs/validate/alias_tuple_empty.stef new file mode 100644 index 0000000..99b7480 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/alias_tuple_empty.stef @@ -0,0 +1 @@ +type Sample = (); diff --git a/crates/stef-compiler/tests/inputs/validate/alias_tuple_single.stef b/crates/stef-compiler/tests/inputs/validate/alias_tuple_single.stef new file mode 100644 index 0000000..cb97ac5 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/alias_tuple_single.stef @@ -0,0 +1 @@ +type Sample = (u8); diff --git a/crates/stef-compiler/tests/inputs/validate/alias_tuple_too_large.stef b/crates/stef-compiler/tests/inputs/validate/alias_tuple_too_large.stef new file mode 100644 index 0000000..f50d521 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/alias_tuple_too_large.stef @@ -0,0 +1 @@ +type Sample = (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8); diff --git a/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_empty.stef b/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_empty.stef new file mode 100644 index 0000000..7c6e9a0 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_empty.stef @@ -0,0 +1,6 @@ +enum Sample { + One @1, + Two { + field: () @1, + } @2, +} diff --git a/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_single.stef b/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_single.stef new file mode 100644 index 0000000..b2b92e4 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_single.stef @@ -0,0 +1,6 @@ +enum Sample { + One @1, + Two { + field: (u8) @1, + } @2, +} diff --git a/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_too_large.stef b/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_too_large.stef new file mode 100644 index 0000000..435e022 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/enum_named_tuple_too_large.stef @@ -0,0 +1,6 @@ +enum Sample { + One @1, + Two { + field: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1, + } @2, +} diff --git a/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.stef b/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.stef new file mode 100644 index 0000000..63bb081 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.stef @@ -0,0 +1,4 @@ +enum Sample { + One @1, + Two(() @1) @2, +} diff --git a/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_single.stef b/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_single.stef new file mode 100644 index 0000000..a21be1f --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_single.stef @@ -0,0 +1,4 @@ +enum Sample { + One @1, + Two((u8) @1) @2, +} diff --git a/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_too_large.stef b/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_too_large.stef new file mode 100644 index 0000000..d8048a1 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_too_large.stef @@ -0,0 +1,4 @@ +enum Sample { + One @1, + Two((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1) @2, +} diff --git a/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_empty.stef b/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_empty.stef new file mode 100644 index 0000000..829d6fc --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_empty.stef @@ -0,0 +1,3 @@ +struct Sample { + field: () @1, +} diff --git a/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_single.stef b/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_single.stef new file mode 100644 index 0000000..90eb9ea --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_single.stef @@ -0,0 +1,3 @@ +struct Sample { + field: (u8) @1, +} diff --git a/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_too_large.stef b/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_too_large.stef new file mode 100644 index 0000000..12f7cd4 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/struct_named_tuple_too_large.stef @@ -0,0 +1,3 @@ +struct Sample { + field: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1, +} diff --git a/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.stef b/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.stef new file mode 100644 index 0000000..475d8a9 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.stef @@ -0,0 +1 @@ +struct Sample(() @1) diff --git a/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_single.stef b/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_single.stef new file mode 100644 index 0000000..722c255 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_single.stef @@ -0,0 +1 @@ +struct Sample((u8) @1) diff --git a/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_too_large.stef b/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_too_large.stef new file mode 100644 index 0000000..3574911 --- /dev/null +++ b/crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_too_large.stef @@ -0,0 +1 @@ +struct Sample((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1) diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.stef.snap new file mode 100644 index 0000000..0c38dc9 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_empty.stef.snap @@ -0,0 +1,14 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: type Sample = (); +input_file: crates/stef-compiler/tests/inputs/validate/alias_tuple_empty.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid + ╭─[alias_tuple_empty.stef:1:1] + 1 │ type Sample = (); + · ─┬ + · ╰── declared here + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_single.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_single.stef.snap new file mode 100644 index 0000000..c339b59 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_single.stef.snap @@ -0,0 +1,14 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: type Sample = (u8); +input_file: crates/stef-compiler/tests/inputs/validate/alias_tuple_single.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭a single element❬W❭ are invalid + ╭─[alias_tuple_single.stef:1:1] + 1 │ type Sample = (u8); + · ──┬─ + · ╰── declared here + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_too_large.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_too_large.stef.snap new file mode 100644 index 0000000..c9d66a3 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@alias_tuple_too_large.stef.snap @@ -0,0 +1,14 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "type Sample = (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);" +input_file: crates/stef-compiler/tests/inputs/validate/alias_tuple_too_large.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭more than 12 elements❬W❭ are invalid + ╭─[alias_tuple_too_large.stef:1:1] + 1 │ type Sample = (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8); + · ──────────────────────────┬───────────────────────── + · ╰── declared here + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.stef.snap new file mode 100644 index 0000000..48ccea1 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_empty.stef.snap @@ -0,0 +1,19 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "enum Sample {\n One @1,\n Two {\n field: () @1,\n } @2,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/enum_named_tuple_empty.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid + ╭─[enum_named_tuple_empty.stef:1:1] + 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/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_single.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_single.stef.snap new file mode 100644 index 0000000..fe03b57 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_single.stef.snap @@ -0,0 +1,19 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "enum Sample {\n One @1,\n Two {\n field: (u8) @1,\n } @2,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/enum_named_tuple_single.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭a single element❬W❭ are invalid + ╭─[enum_named_tuple_single.stef:1:1] + 1 │ enum Sample { + 2 │ One @1, + 3 │ Two { + 4 │ field: (u8) @1, + · ──┬─ + · ╰── declared here + 5 │ } @2, + 6 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_too_large.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_too_large.stef.snap new file mode 100644 index 0000000..3cd967b --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_named_tuple_too_large.stef.snap @@ -0,0 +1,19 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "enum Sample {\n One @1,\n Two {\n field: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1,\n } @2,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/enum_named_tuple_too_large.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭more than 12 elements❬W❭ are invalid + ╭─[enum_named_tuple_too_large.stef:1:1] + 1 │ enum Sample { + 2 │ One @1, + 3 │ Two { + 4 │ field: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1, + · ──────────────────────────┬───────────────────────── + · ╰── declared here + 5 │ } @2, + 6 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.stef.snap new file mode 100644 index 0000000..45e17c9 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_empty.stef.snap @@ -0,0 +1,17 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "enum Sample {\n One @1,\n Two(() @1) @2,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_empty.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid + ╭─[enum_unnamed_tuple_empty.stef:1:1] + 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/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_single.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_single.stef.snap new file mode 100644 index 0000000..614020a --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_single.stef.snap @@ -0,0 +1,17 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "enum Sample {\n One @1,\n Two((u8) @1) @2,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_single.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭a single element❬W❭ are invalid + ╭─[enum_unnamed_tuple_single.stef:1:1] + 1 │ enum Sample { + 2 │ One @1, + 3 │ Two((u8) @1) @2, + · ──┬─ + · ╰── declared here + 4 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_too_large.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_too_large.stef.snap new file mode 100644 index 0000000..f2c5ef2 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@enum_unnamed_tuple_too_large.stef.snap @@ -0,0 +1,17 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "enum Sample {\n One @1,\n Two((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1) @2,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/enum_unnamed_tuple_too_large.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭more than 12 elements❬W❭ are invalid + ╭─[enum_unnamed_tuple_too_large.stef:1:1] + 1 │ enum Sample { + 2 │ One @1, + 3 │ Two((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1) @2, + · ──────────────────────────┬───────────────────────── + · ╰── declared here + 4 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.stef.snap new file mode 100644 index 0000000..e90f741 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_empty.stef.snap @@ -0,0 +1,16 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "struct Sample {\n field: () @1,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/struct_named_tuple_empty.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid + ╭─[struct_named_tuple_empty.stef:1:1] + 1 │ struct Sample { + 2 │ field: () @1, + · ─┬ + · ╰── declared here + 3 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_single.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_single.stef.snap new file mode 100644 index 0000000..e485d65 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_single.stef.snap @@ -0,0 +1,16 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "struct Sample {\n field: (u8) @1,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/struct_named_tuple_single.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭a single element❬W❭ are invalid + ╭─[struct_named_tuple_single.stef:1:1] + 1 │ struct Sample { + 2 │ field: (u8) @1, + · ──┬─ + · ╰── declared here + 3 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_too_large.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_too_large.stef.snap new file mode 100644 index 0000000..09a4f93 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_named_tuple_too_large.stef.snap @@ -0,0 +1,16 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "struct Sample {\n field: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1,\n}" +input_file: crates/stef-compiler/tests/inputs/validate/struct_named_tuple_too_large.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭more than 12 elements❬W❭ are invalid + ╭─[struct_named_tuple_too_large.stef:1:1] + 1 │ struct Sample { + 2 │ field: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1, + · ──────────────────────────┬───────────────────────── + · ╰── declared here + 3 │ } + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.stef.snap new file mode 100644 index 0000000..097a87e --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_empty.stef.snap @@ -0,0 +1,14 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: struct Sample(() @1) +input_file: crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_empty.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭zero elements❬W❭ are invalid + ╭─[struct_unnamed_tuple_empty.stef:1:1] + 1 │ struct Sample(() @1) + · ─┬ + · ╰── declared here + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_single.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_single.stef.snap new file mode 100644 index 0000000..4618013 --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_single.stef.snap @@ -0,0 +1,14 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: struct Sample((u8) @1) +input_file: crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_single.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭a single element❬W❭ are invalid + ╭─[struct_unnamed_tuple_single.stef:1:1] + 1 │ struct Sample((u8) @1) + · ──┬─ + · ╰── declared here + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_too_large.stef.snap b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_too_large.stef.snap new file mode 100644 index 0000000..1cfdc7b --- /dev/null +++ b/crates/stef-compiler/tests/snapshots/compiler__error_validate@struct_unnamed_tuple_too_large.stef.snap @@ -0,0 +1,14 @@ +--- +source: crates/stef-compiler/tests/compiler.rs +description: "struct Sample((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1)" +input_file: crates/stef-compiler/tests/inputs/validate/struct_unnamed_tuple_too_large.stef +--- + × invalid tuple element size found + ╰─▶ tuples with ❬W❭more than 12 elements❬W❭ are invalid + ╭─[struct_unnamed_tuple_too_large.stef:1:1] + 1 │ struct Sample((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) @1) + · ──────────────────────────┬───────────────────────── + · ╰── declared here + ╰──── + help: a tuple must have between 2 and 12 elements + diff --git a/crates/stef-parser/src/lib.rs b/crates/stef-parser/src/lib.rs index 6918f96..1dcb620 100644 --- a/crates/stef-parser/src/lib.rs +++ b/crates/stef-parser/src/lib.rs @@ -446,7 +446,7 @@ pub struct TypeAlias<'a> { /// Potential generic type arguments. pub generics: Generics<'a>, /// Original type that is being aliased. - pub target: DataType<'a>, + pub target: Type<'a>, } impl<'a> Print for TypeAlias<'a> { @@ -534,7 +534,7 @@ pub struct NamedField<'a> { /// Unique name for this field, within the current element. pub name: Name<'a>, /// Data type that defines the shape of the contained data. - pub ty: DataType<'a>, + pub ty: Type<'a>, /// Identifier for this field, that must be unique within the current element. pub id: Id, /// Source code location. @@ -581,7 +581,7 @@ impl<'a> Display for NamedField<'a> { #[derive(Debug, Eq, PartialEq)] pub struct UnnamedField<'a> { /// Data type that defines the shape of the contained data. - pub ty: DataType<'a>, + pub ty: Type<'a>, /// Identifier for this field, that must be unique within the current element. pub id: Id, /// Source code location. @@ -704,6 +704,37 @@ impl<'a> Display for AttributeValue<'a> { } } +/// The data type which describes the shape of a field through its [`Self::value`] value, and +/// additionally carries the source span for it. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Type<'a> { + /// Possible data type of the field. + pub value: DataType<'a>, + /// Source code location. + span: Span, +} + +impl<'a> Spanned for Type<'a> { + fn span(&self) -> Span { + self.span + } +} + +impl<'a> Display for Type<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.value.fmt(f) + } +} + +impl<'a> From<(DataType<'a>, Range)> for Type<'a> { + fn from((value, span): (DataType<'a>, Range)) -> Self { + Self { + value, + span: span.into(), + } + } +} + /// Possible data type that describes the shape of a field. #[derive(Clone, Debug, Eq, PartialEq)] pub enum DataType<'a> { @@ -742,25 +773,25 @@ pub enum DataType<'a> { /// Reference version (slice) of `u8` bytes. BytesRef, /// Vector of another data type. - Vec(Box>), + Vec(Box>), /// Key-value hash map of data types. - HashMap(Box<(DataType<'a>, DataType<'a>)>), + HashMap(Box<(Type<'a>, Type<'a>)>), /// Hash set of data types (each entry is unique). - HashSet(Box>), + HashSet(Box>), /// Optional value. - Option(Box>), + Option(Box>), /// Non-zero value. /// - Integers: `n > 0` /// - Collections: `len() > 0` - NonZero(Box>), + NonZero(Box>), /// Boxed version of a string that is immutable. BoxString, /// Boxed version of a byte vector that is immutable. BoxBytes, /// Fixed size list of up to 12 types. - Tuple(Vec>), + Tuple(Vec>), /// Continuous list of values with a single time and known length. - Array(Box>, u32), + Array(Box>, u32), /// Any external, non-standard data type (like a user defined struct or enum). External(ExternalType<'a>), } @@ -768,33 +799,33 @@ pub enum DataType<'a> { impl<'a> Display for DataType<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - DataType::Bool => f.write_str("bool"), - DataType::U8 => f.write_str("u8"), - DataType::U16 => f.write_str("u16"), - DataType::U32 => f.write_str("u32"), - DataType::U64 => f.write_str("u64"), - DataType::U128 => f.write_str("u128"), - DataType::I8 => f.write_str("i8"), - DataType::I16 => f.write_str("i16"), - DataType::I32 => f.write_str("i32"), - DataType::I64 => f.write_str("i64"), - DataType::I128 => f.write_str("i128"), - DataType::F32 => f.write_str("f32"), - DataType::F64 => f.write_str("f64"), - DataType::String => f.write_str("string"), - DataType::StringRef => f.write_str("&string"), - DataType::Bytes => f.write_str("bytes"), - DataType::BytesRef => f.write_str("&bytes"), - DataType::Vec(t) => write!(f, "vec<{t}>"), - DataType::HashMap(kv) => write!(f, "hash_map<{}, {}>", kv.0, kv.1), - DataType::HashSet(t) => write!(f, "hash_set<{t}>"), - DataType::Option(t) => write!(f, "option<{t}>"), - DataType::NonZero(t) => write!(f, "non_zero<{t}>"), - DataType::BoxString => f.write_str("box"), - DataType::BoxBytes => f.write_str("box"), - DataType::Tuple(l) => concat(f, "(", l, ", ", ")"), - DataType::Array(t, size) => write!(f, "[{t}; {size}]"), - DataType::External(t) => t.fmt(f), + Self::Bool => f.write_str("bool"), + Self::U8 => f.write_str("u8"), + Self::U16 => f.write_str("u16"), + Self::U32 => f.write_str("u32"), + Self::U64 => f.write_str("u64"), + Self::U128 => f.write_str("u128"), + Self::I8 => f.write_str("i8"), + Self::I16 => f.write_str("i16"), + Self::I32 => f.write_str("i32"), + Self::I64 => f.write_str("i64"), + Self::I128 => f.write_str("i128"), + Self::F32 => f.write_str("f32"), + Self::F64 => f.write_str("f64"), + Self::String => f.write_str("string"), + Self::StringRef => f.write_str("&string"), + Self::Bytes => f.write_str("bytes"), + Self::BytesRef => f.write_str("&bytes"), + Self::Vec(t) => write!(f, "vec<{t}>"), + Self::HashMap(kv) => write!(f, "hash_map<{}, {}>", kv.0, kv.1), + Self::HashSet(t) => write!(f, "hash_set<{t}>"), + Self::Option(t) => write!(f, "option<{t}>"), + Self::NonZero(t) => write!(f, "non_zero<{t}>"), + Self::BoxString => f.write_str("box"), + Self::BoxBytes => f.write_str("box"), + Self::Tuple(l) => concat(f, "(", l, ", ", ")"), + Self::Array(t, size) => write!(f, "[{t}; {size}]"), + Self::External(t) => t.fmt(f), } } } @@ -810,7 +841,7 @@ pub struct ExternalType<'a> { /// Unique name of the type within the current scope (or the module if prefixed with a path). pub name: Name<'a>, /// Potential generic type arguments. - pub generics: Vec>, + pub generics: Vec>, } impl<'a> Display for ExternalType<'a> { @@ -924,7 +955,7 @@ pub struct Const<'a> { /// Unique identifier of this constant. pub name: Name<'a>, /// Type of the value. - pub ty: DataType<'a>, + pub ty: Type<'a>, /// Literal value that this declaration represents. pub value: Literal, } diff --git a/crates/stef-parser/src/parser/types.rs b/crates/stef-parser/src/parser/types.rs index 81fb454..1be0454 100644 --- a/crates/stef-parser/src/parser/types.rs +++ b/crates/stef-parser/src/parser/types.rs @@ -4,7 +4,8 @@ use stef_derive::{ParserError, ParserErrorCause}; use winnow::{ ascii::{dec_uint, space0}, combinator::{ - alt, cut_err, fail, opt, preceded, separated1, separated_pair, success, terminated, + alt, cut_err, fail, opt, preceded, separated0, separated1, separated_pair, success, + terminated, }, dispatch, error::ErrorKind, @@ -14,7 +15,7 @@ use winnow::{ }; use super::{imports, ws, Input, ParserExt, Result}; -use crate::{highlight, DataType, ExternalType, Name}; +use crate::{highlight, DataType, ExternalType, Name, Type}; /// Encountered an invalid type definition. #[derive(Debug, ParserError)] @@ -49,7 +50,7 @@ pub enum Cause { Segment(Box), } -pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseError> { +pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseError> { let start = input.location(); alt(( @@ -59,7 +60,9 @@ pub(super) fn parse<'i>(input: &mut Input<'i>) -> Result, ParseErro parse_array, parse_external.map(DataType::External), )) + .with_span() .parse_next(input) + .map(Into::into) .map_err(|e| { e.map(|cause| ParseError { at: start..input.location(), @@ -126,7 +129,7 @@ fn parse_tuple<'i>(input: &mut Input<'i>) -> Result, Cause> { preceded( '(', cut_err(terminated( - separated1(ws(parse.map_err(Cause::from)), ws(',')), + separated0(ws(parse.map_err(Cause::from)), ws(',')), ws(')'), )), ) diff --git a/crates/stef-parser/tests/snapshots/parser__parse@alias_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@alias_basic.stef.snap index c2ab65f..39fb321 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@alias_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@alias_basic.stef.snap @@ -26,7 +26,13 @@ Schema { generics: Generics( [], ), - target: U32, + target: Type { + value: U32, + span: Span { + start: 37, + end: 40, + }, + }, }, ), ], diff --git a/crates/stef-parser/tests/snapshots/parser__parse@const_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@const_basic.stef.snap index 8c26162..c3f54c5 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@const_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@const_basic.stef.snap @@ -21,7 +21,13 @@ Schema { end: 15, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 17, + end: 21, + }, + }, value: Bool( true, ), @@ -39,7 +45,13 @@ Schema { end: 46, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 48, + end: 52, + }, + }, value: Bool( false, ), @@ -57,7 +69,13 @@ Schema { end: 71, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 73, + end: 76, + }, + }, value: Int( 100, ), @@ -75,7 +93,13 @@ Schema { end: 95, }, }, - ty: F64, + ty: Type { + value: F64, + span: Span { + start: 97, + end: 100, + }, + }, value: Float( 5.5, ), @@ -93,7 +117,13 @@ Schema { end: 120, }, }, - ty: String, + ty: Type { + value: String, + span: Span { + start: 122, + end: 128, + }, + }, value: String( "value", ), @@ -111,7 +141,13 @@ Schema { end: 151, }, }, - ty: Bytes, + ty: Type { + value: Bytes, + span: Span { + start: 153, + end: 158, + }, + }, value: Bytes( [ 1, diff --git a/crates/stef-parser/tests/snapshots/parser__parse@const_string.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@const_string.stef.snap index 8a42ab9..feec0a8 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@const_string.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@const_string.stef.snap @@ -21,7 +21,13 @@ Schema { end: 12, }, }, - ty: String, + ty: Type { + value: String, + span: Span { + start: 14, + end: 20, + }, + }, value: String( "value", ), @@ -39,7 +45,13 @@ Schema { end: 53, }, }, - ty: String, + ty: Type { + value: String, + span: Span { + start: 55, + end: 61, + }, + }, value: String( "one two three", ), @@ -57,7 +69,13 @@ Schema { end: 109, }, }, - ty: String, + ty: Type { + value: String, + span: Span { + start: 111, + end: 117, + }, + }, value: String( "escape basics \r\n \t \u{8} \u{c} \\ \"hello\" \nunicode ❤ emoji ❤ ", ), @@ -75,7 +93,13 @@ Schema { end: 231, }, }, - ty: String, + ty: Type { + value: String, + span: Span { + start: 233, + end: 239, + }, + }, value: String( "a\n b\n c\n", ), diff --git a/crates/stef-parser/tests/snapshots/parser__parse@enum_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@enum_basic.stef.snap index d6e5d16..7fd36fc 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@enum_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@enum_basic.stef.snap @@ -70,7 +70,13 @@ Schema { fields: Unnamed( [ UnnamedField { - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 74, + end: 77, + }, + }, id: Id { value: 1, span: Span { @@ -84,7 +90,13 @@ Schema { }, }, UnnamedField { - ty: U64, + ty: Type { + value: U64, + span: Span { + start: 82, + end: 85, + }, + }, id: Id { value: 2, span: Span { @@ -135,7 +147,13 @@ Schema { end: 120, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 122, + end: 125, + }, + }, id: Id { value: 1, span: Span { @@ -161,7 +179,13 @@ Schema { end: 186, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 188, + end: 192, + }, + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@enum_generics.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@enum_generics.stef.snap index a6a22bb..e3213fc 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@enum_generics.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@enum_generics.stef.snap @@ -97,19 +97,25 @@ Schema { fields: Unnamed( [ UnnamedField { - ty: External( - ExternalType { - path: [], - name: Name { - value: "A", - span: Span { - start: 70, - end: 71, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "A", + span: Span { + start: 70, + end: 71, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 70, + end: 71, }, - ), + }, id: Id { value: 1, span: Span { @@ -123,19 +129,25 @@ Schema { }, }, UnnamedField { - ty: External( - ExternalType { - path: [], - name: Name { - value: "B", - span: Span { - start: 76, - end: 77, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "B", + span: Span { + start: 76, + end: 77, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 76, + end: 77, }, - ), + }, id: Id { value: 2, span: Span { @@ -186,19 +198,25 @@ Schema { end: 112, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "C", - span: Span { - start: 114, - end: 115, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "C", + span: Span { + start: 114, + end: 115, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 114, + end: 115, }, - ), + }, id: Id { value: 1, span: Span { @@ -222,19 +240,25 @@ Schema { end: 134, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "D", - span: Span { - start: 136, - end: 137, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "D", + span: Span { + start: 136, + end: 137, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 136, + end: 137, }, - ), + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@enum_many_ws.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@enum_many_ws.stef.snap index 8f82438..b5d74ff 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@enum_many_ws.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@enum_many_ws.stef.snap @@ -68,7 +68,13 @@ Schema { fields: Unnamed( [ UnnamedField { - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 79, + end: 82, + }, + }, id: Id { value: 1, span: Span { @@ -82,7 +88,13 @@ Schema { }, }, UnnamedField { - ty: U64, + ty: Type { + value: U64, + span: Span { + start: 93, + end: 96, + }, + }, id: Id { value: 2, span: Span { @@ -133,7 +145,13 @@ Schema { end: 164, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 169, + end: 172, + }, + }, id: Id { value: 1, span: Span { @@ -157,7 +175,13 @@ Schema { end: 209, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 214, + end: 218, + }, + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@enum_min_ws.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@enum_min_ws.stef.snap index c79633a..f937033 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@enum_min_ws.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@enum_min_ws.stef.snap @@ -74,7 +74,13 @@ Schema { fields: Unnamed( [ UnnamedField { - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 25, + end: 28, + }, + }, id: Id { value: 1, span: Span { @@ -88,7 +94,13 @@ Schema { }, }, UnnamedField { - ty: U64, + ty: Type { + value: U64, + span: Span { + start: 31, + end: 34, + }, + }, id: Id { value: 2, span: Span { @@ -102,19 +114,25 @@ Schema { }, }, UnnamedField { - ty: External( - ExternalType { - path: [], - name: Name { - value: "T", - span: Span { - start: 37, - end: 38, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + span: Span { + start: 37, + end: 38, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 37, + end: 38, }, - ), + }, id: Id { value: 3, span: Span { @@ -165,7 +183,13 @@ Schema { end: 56, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 57, + end: 60, + }, + }, id: Id { value: 1, span: Span { @@ -189,7 +213,13 @@ Schema { end: 69, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 70, + end: 74, + }, + }, id: Id { value: 2, span: Span { @@ -213,19 +243,25 @@ Schema { end: 83, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "T", - span: Span { - start: 84, - end: 85, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + span: Span { + start: 84, + end: 85, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 84, + end: 85, }, - ), + }, id: Id { value: 3, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@module_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@module_basic.stef.snap index 3ab0f94..bcd758b 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@module_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@module_basic.stef.snap @@ -117,7 +117,13 @@ Schema { end: 133, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 135, + end: 138, + }, + }, id: Id { value: 1, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@schema_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@schema_basic.stef.snap index a697aae..242c2f1 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@schema_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@schema_basic.stef.snap @@ -42,7 +42,13 @@ Schema { end: 45, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 47, + end: 50, + }, + }, id: Id { value: 1, span: Span { @@ -66,7 +72,13 @@ Schema { end: 60, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 62, + end: 66, + }, + }, id: Id { value: 2, span: Span { @@ -142,7 +154,13 @@ Schema { fields: Unnamed( [ UnnamedField { - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 129, + end: 132, + }, + }, id: Id { value: 1, span: Span { @@ -156,7 +174,13 @@ Schema { }, }, UnnamedField { - ty: U64, + ty: Type { + value: U64, + span: Span { + start: 137, + end: 140, + }, + }, id: Id { value: 2, span: Span { @@ -207,7 +231,13 @@ Schema { end: 175, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 177, + end: 180, + }, + }, id: Id { value: 1, span: Span { @@ -231,7 +261,13 @@ Schema { end: 199, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 201, + end: 205, + }, + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@struct_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@struct_basic.stef.snap index f629c9b..5ec30a6 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@struct_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@struct_basic.stef.snap @@ -42,7 +42,13 @@ Schema { end: 39, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 41, + end: 44, + }, + }, id: Id { value: 1, span: Span { @@ -68,7 +74,13 @@ Schema { end: 75, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 77, + end: 81, + }, + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@struct_generics.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@struct_generics.stef.snap index 927067c..9dec535 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@struct_generics.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@struct_generics.stef.snap @@ -57,19 +57,25 @@ Schema { end: 59, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "K", - span: Span { - start: 61, - end: 62, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "K", + span: Span { + start: 61, + end: 62, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 61, + end: 62, }, - ), + }, id: Id { value: 1, span: Span { @@ -93,19 +99,25 @@ Schema { end: 76, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "V", - span: Span { - start: 78, - end: 79, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "V", + span: Span { + start: 78, + end: 79, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 78, + end: 79, }, - ), + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@struct_many_ws.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@struct_many_ws.stef.snap index bd4dc1d..0fd8587 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@struct_many_ws.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@struct_many_ws.stef.snap @@ -50,7 +50,13 @@ Schema { end: 81, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 86, + end: 89, + }, + }, id: Id { value: 1, span: Span { @@ -74,7 +80,13 @@ Schema { end: 104, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 109, + end: 113, + }, + }, id: Id { value: 2, span: Span { @@ -98,19 +110,25 @@ Schema { end: 127, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "T", - span: Span { - start: 132, - end: 133, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + span: Span { + start: 132, + end: 133, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 132, + end: 133, }, - ), + }, id: Id { value: 3, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@struct_min_ws.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@struct_min_ws.stef.snap index 33ffdba..de18c8a 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@struct_min_ws.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@struct_min_ws.stef.snap @@ -48,7 +48,13 @@ Schema { end: 18, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 19, + end: 22, + }, + }, id: Id { value: 1, span: Span { @@ -72,7 +78,13 @@ Schema { end: 26, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 27, + end: 31, + }, + }, id: Id { value: 2, span: Span { @@ -96,19 +108,25 @@ Schema { end: 35, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "T", - span: Span { - start: 36, - end: 37, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "T", + span: Span { + start: 36, + end: 37, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 36, + end: 37, }, - ), + }, id: Id { value: 3, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@struct_tuple.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@struct_tuple.stef.snap index 0dd4b4b..849fffa 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@struct_tuple.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@struct_tuple.stef.snap @@ -32,7 +32,13 @@ Schema { fields: Unnamed( [ UnnamedField { - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 32, + end: 35, + }, + }, id: Id { value: 1, span: Span { @@ -46,7 +52,13 @@ Schema { }, }, UnnamedField { - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 40, + end: 44, + }, + }, id: Id { value: 2, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@types_basic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@types_basic.stef.snap index 22e6702..855e278 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@types_basic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@types_basic.stef.snap @@ -40,7 +40,13 @@ Schema { end: 23, }, }, - ty: Bool, + ty: Type { + value: Bool, + span: Span { + start: 25, + end: 29, + }, + }, id: Id { value: 1, span: Span { @@ -64,7 +70,13 @@ Schema { end: 41, }, }, - ty: U8, + ty: Type { + value: U8, + span: Span { + start: 43, + end: 45, + }, + }, id: Id { value: 2, span: Span { @@ -88,7 +100,13 @@ Schema { end: 57, }, }, - ty: U16, + ty: Type { + value: U16, + span: Span { + start: 59, + end: 62, + }, + }, id: Id { value: 3, span: Span { @@ -112,7 +130,13 @@ Schema { end: 74, }, }, - ty: U32, + ty: Type { + value: U32, + span: Span { + start: 76, + end: 79, + }, + }, id: Id { value: 4, span: Span { @@ -136,7 +160,13 @@ Schema { end: 91, }, }, - ty: U64, + ty: Type { + value: U64, + span: Span { + start: 93, + end: 96, + }, + }, id: Id { value: 5, span: Span { @@ -160,7 +190,13 @@ Schema { end: 108, }, }, - ty: U128, + ty: Type { + value: U128, + span: Span { + start: 110, + end: 114, + }, + }, id: Id { value: 6, span: Span { @@ -184,7 +220,13 @@ Schema { end: 126, }, }, - ty: I8, + ty: Type { + value: I8, + span: Span { + start: 128, + end: 130, + }, + }, id: Id { value: 7, span: Span { @@ -208,7 +250,13 @@ Schema { end: 142, }, }, - ty: I16, + ty: Type { + value: I16, + span: Span { + start: 144, + end: 147, + }, + }, id: Id { value: 8, span: Span { @@ -232,7 +280,13 @@ Schema { end: 159, }, }, - ty: I32, + ty: Type { + value: I32, + span: Span { + start: 161, + end: 164, + }, + }, id: Id { value: 9, span: Span { @@ -256,7 +310,13 @@ Schema { end: 176, }, }, - ty: I64, + ty: Type { + value: I64, + span: Span { + start: 178, + end: 181, + }, + }, id: Id { value: 10, span: Span { @@ -280,7 +340,13 @@ Schema { end: 194, }, }, - ty: I128, + ty: Type { + value: I128, + span: Span { + start: 196, + end: 200, + }, + }, id: Id { value: 11, span: Span { @@ -304,7 +370,13 @@ Schema { end: 213, }, }, - ty: F32, + ty: Type { + value: F32, + span: Span { + start: 215, + end: 218, + }, + }, id: Id { value: 12, span: Span { @@ -328,7 +400,13 @@ Schema { end: 231, }, }, - ty: F64, + ty: Type { + value: F64, + span: Span { + start: 233, + end: 236, + }, + }, id: Id { value: 13, span: Span { @@ -352,7 +430,13 @@ Schema { end: 249, }, }, - ty: String, + ty: Type { + value: String, + span: Span { + start: 251, + end: 257, + }, + }, id: Id { value: 14, span: Span { @@ -376,7 +460,13 @@ Schema { end: 270, }, }, - ty: StringRef, + ty: Type { + value: StringRef, + span: Span { + start: 272, + end: 279, + }, + }, id: Id { value: 15, span: Span { @@ -400,7 +490,13 @@ Schema { end: 292, }, }, - ty: Bytes, + ty: Type { + value: Bytes, + span: Span { + start: 294, + end: 299, + }, + }, id: Id { value: 16, span: Span { @@ -424,7 +520,13 @@ Schema { end: 312, }, }, - ty: BytesRef, + ty: Type { + value: BytesRef, + span: Span { + start: 314, + end: 320, + }, + }, id: Id { value: 17, span: Span { @@ -448,7 +550,13 @@ Schema { end: 333, }, }, - ty: BoxString, + ty: Type { + value: BoxString, + span: Span { + start: 335, + end: 346, + }, + }, id: Id { value: 18, span: Span { @@ -472,7 +580,13 @@ Schema { end: 359, }, }, - ty: BoxBytes, + ty: Type { + value: BoxBytes, + span: Span { + start: 361, + end: 371, + }, + }, id: Id { value: 19, span: Span { @@ -496,13 +610,37 @@ Schema { end: 384, }, }, - ty: Tuple( - [ - U32, - U32, - U32, - ], - ), + ty: Type { + value: Tuple( + [ + Type { + value: U32, + span: Span { + start: 387, + end: 390, + }, + }, + Type { + value: U32, + span: Span { + start: 392, + end: 395, + }, + }, + Type { + value: U32, + span: Span { + start: 397, + end: 400, + }, + }, + ], + ), + span: Span { + start: 386, + end: 401, + }, + }, id: Id { value: 20, span: Span { @@ -526,10 +664,22 @@ Schema { end: 414, }, }, - ty: Array( - U32, - 12, - ), + ty: Type { + value: Array( + Type { + value: U32, + span: Span { + start: 417, + end: 420, + }, + }, + 12, + ), + span: Span { + start: 416, + end: 425, + }, + }, id: Id { value: 21, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@types_generic.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@types_generic.stef.snap index bcccba4..99ab514 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@types_generic.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@types_generic.stef.snap @@ -40,9 +40,21 @@ Schema { end: 22, }, }, - ty: Vec( - U32, - ), + ty: Type { + value: Vec( + Type { + value: U32, + span: Span { + start: 28, + end: 31, + }, + }, + ), + span: Span { + start: 24, + end: 32, + }, + }, id: Id { value: 1, span: Span { @@ -66,12 +78,30 @@ Schema { end: 43, }, }, - ty: HashMap( - ( - U32, - String, + ty: Type { + value: HashMap( + ( + Type { + value: U32, + span: Span { + start: 54, + end: 57, + }, + }, + Type { + value: String, + span: Span { + start: 59, + end: 65, + }, + }, + ), ), - ), + span: Span { + start: 45, + end: 66, + }, + }, id: Id { value: 2, span: Span { @@ -95,9 +125,21 @@ Schema { end: 77, }, }, - ty: HashSet( - U32, - ), + ty: Type { + value: HashSet( + Type { + value: U32, + span: Span { + start: 88, + end: 91, + }, + }, + ), + span: Span { + start: 79, + end: 92, + }, + }, id: Id { value: 3, span: Span { @@ -121,9 +163,21 @@ Schema { end: 103, }, }, - ty: Option( - U32, - ), + ty: Type { + value: Option( + Type { + value: U32, + span: Span { + start: 112, + end: 115, + }, + }, + ), + span: Span { + start: 105, + end: 116, + }, + }, id: Id { value: 4, span: Span { @@ -147,9 +201,21 @@ Schema { end: 127, }, }, - ty: NonZero( - U32, - ), + ty: Type { + value: NonZero( + Type { + value: U32, + span: Span { + start: 138, + end: 141, + }, + }, + ), + span: Span { + start: 129, + end: 142, + }, + }, id: Id { value: 5, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@types_nested.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@types_nested.stef.snap index c8a5c92..e44b962 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@types_nested.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@types_nested.stef.snap @@ -40,18 +40,54 @@ Schema { end: 25, }, }, - ty: Vec( - Option( - NonZero( - HashMap( - ( - I64, - BoxString, - ), + ty: Type { + value: Vec( + Type { + value: Option( + Type { + value: NonZero( + Type { + value: HashMap( + ( + Type { + value: I64, + span: Span { + start: 56, + end: 59, + }, + }, + Type { + value: BoxString, + span: Span { + start: 61, + end: 72, + }, + }, + ), + ), + span: Span { + start: 47, + end: 73, + }, + }, + ), + span: Span { + start: 38, + end: 74, + }, + }, ), - ), + span: Span { + start: 31, + end: 75, + }, + }, ), - ), + span: Span { + start: 27, + end: 76, + }, + }, id: Id { value: 1, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@types_non_zero.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@types_non_zero.stef.snap index dfc25e2..26c7134 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@types_non_zero.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@types_non_zero.stef.snap @@ -40,9 +40,21 @@ Schema { end: 23, }, }, - ty: NonZero( - U8, - ), + ty: Type { + value: NonZero( + Type { + value: U8, + span: Span { + start: 34, + end: 36, + }, + }, + ), + span: Span { + start: 25, + end: 37, + }, + }, id: Id { value: 1, span: Span { @@ -66,9 +78,21 @@ Schema { end: 49, }, }, - ty: NonZero( - U16, - ), + ty: Type { + value: NonZero( + Type { + value: U16, + span: Span { + start: 60, + end: 63, + }, + }, + ), + span: Span { + start: 51, + end: 64, + }, + }, id: Id { value: 2, span: Span { @@ -92,9 +116,21 @@ Schema { end: 76, }, }, - ty: NonZero( - U32, - ), + ty: Type { + value: NonZero( + Type { + value: U32, + span: Span { + start: 87, + end: 90, + }, + }, + ), + span: Span { + start: 78, + end: 91, + }, + }, id: Id { value: 3, span: Span { @@ -118,9 +154,21 @@ Schema { end: 103, }, }, - ty: NonZero( - U64, - ), + ty: Type { + value: NonZero( + Type { + value: U64, + span: Span { + start: 114, + end: 117, + }, + }, + ), + span: Span { + start: 105, + end: 118, + }, + }, id: Id { value: 4, span: Span { @@ -144,9 +192,21 @@ Schema { end: 130, }, }, - ty: NonZero( - U128, - ), + ty: Type { + value: NonZero( + Type { + value: U128, + span: Span { + start: 141, + end: 145, + }, + }, + ), + span: Span { + start: 132, + end: 146, + }, + }, id: Id { value: 5, span: Span { @@ -170,9 +230,21 @@ Schema { end: 158, }, }, - ty: NonZero( - I8, - ), + ty: Type { + value: NonZero( + Type { + value: I8, + span: Span { + start: 169, + end: 171, + }, + }, + ), + span: Span { + start: 160, + end: 172, + }, + }, id: Id { value: 6, span: Span { @@ -196,9 +268,21 @@ Schema { end: 184, }, }, - ty: NonZero( - I16, - ), + ty: Type { + value: NonZero( + Type { + value: I16, + span: Span { + start: 195, + end: 198, + }, + }, + ), + span: Span { + start: 186, + end: 199, + }, + }, id: Id { value: 7, span: Span { @@ -222,9 +306,21 @@ Schema { end: 211, }, }, - ty: NonZero( - I32, - ), + ty: Type { + value: NonZero( + Type { + value: I32, + span: Span { + start: 222, + end: 225, + }, + }, + ), + span: Span { + start: 213, + end: 226, + }, + }, id: Id { value: 8, span: Span { @@ -248,9 +344,21 @@ Schema { end: 238, }, }, - ty: NonZero( - I64, - ), + ty: Type { + value: NonZero( + Type { + value: I64, + span: Span { + start: 249, + end: 252, + }, + }, + ), + span: Span { + start: 240, + end: 253, + }, + }, id: Id { value: 9, span: Span { @@ -274,9 +382,21 @@ Schema { end: 265, }, }, - ty: NonZero( - I128, - ), + ty: Type { + value: NonZero( + Type { + value: I128, + span: Span { + start: 276, + end: 280, + }, + }, + ), + span: Span { + start: 267, + end: 281, + }, + }, id: Id { value: 10, span: Span { @@ -300,9 +420,21 @@ Schema { end: 294, }, }, - ty: NonZero( - String, - ), + ty: Type { + value: NonZero( + Type { + value: String, + span: Span { + start: 305, + end: 311, + }, + }, + ), + span: Span { + start: 296, + end: 312, + }, + }, id: Id { value: 11, span: Span { @@ -326,9 +458,21 @@ Schema { end: 325, }, }, - ty: NonZero( - Bytes, - ), + ty: Type { + value: NonZero( + Type { + value: Bytes, + span: Span { + start: 336, + end: 341, + }, + }, + ), + span: Span { + start: 327, + end: 342, + }, + }, id: Id { value: 12, span: Span { @@ -352,11 +496,29 @@ Schema { end: 355, }, }, - ty: NonZero( - Vec( - String, + ty: Type { + value: NonZero( + Type { + value: Vec( + Type { + value: String, + span: Span { + start: 370, + end: 376, + }, + }, + ), + span: Span { + start: 366, + end: 377, + }, + }, ), - ), + span: Span { + start: 357, + end: 378, + }, + }, id: Id { value: 13, span: Span { @@ -380,14 +542,38 @@ Schema { end: 391, }, }, - ty: NonZero( - HashMap( - ( - String, - Bytes, - ), + ty: Type { + value: NonZero( + Type { + value: HashMap( + ( + Type { + value: String, + span: Span { + start: 411, + end: 417, + }, + }, + Type { + value: Bytes, + span: Span { + start: 419, + end: 424, + }, + }, + ), + ), + span: Span { + start: 402, + end: 425, + }, + }, ), - ), + span: Span { + start: 393, + end: 426, + }, + }, id: Id { value: 14, span: Span { @@ -411,11 +597,29 @@ Schema { end: 439, }, }, - ty: NonZero( - HashSet( - String, + ty: Type { + value: NonZero( + Type { + value: HashSet( + Type { + value: String, + span: Span { + start: 459, + end: 465, + }, + }, + ), + span: Span { + start: 450, + end: 466, + }, + }, ), - ), + span: Span { + start: 441, + end: 467, + }, + }, id: Id { value: 15, span: Span { diff --git a/crates/stef-parser/tests/snapshots/parser__parse@types_ref.stef.snap b/crates/stef-parser/tests/snapshots/parser__parse@types_ref.stef.snap index be1c020..d180fba 100644 --- a/crates/stef-parser/tests/snapshots/parser__parse@types_ref.stef.snap +++ b/crates/stef-parser/tests/snapshots/parser__parse@types_ref.stef.snap @@ -40,19 +40,25 @@ Schema { end: 25, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "Test123", - span: Span { - start: 27, - end: 34, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "Test123", + span: Span { + start: 27, + end: 34, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 27, + end: 34, }, - ), + }, id: Id { value: 1, span: Span { @@ -76,22 +82,40 @@ Schema { end: 56, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "KeyValue", - span: Span { - start: 58, - end: 66, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "KeyValue", + span: Span { + start: 58, + end: 66, + }, }, + generics: [ + Type { + value: U32, + span: Span { + start: 67, + end: 70, + }, + }, + Type { + value: Bool, + span: Span { + start: 72, + end: 76, + }, + }, + ], }, - generics: [ - U32, - Bool, - ], + ), + span: Span { + start: 58, + end: 77, }, - ), + }, id: Id { value: 2, span: Span { @@ -200,19 +224,25 @@ Schema { end: 148, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "K", - span: Span { - start: 150, - end: 151, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "K", + span: Span { + start: 150, + end: 151, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 150, + end: 151, }, - ), + }, id: Id { value: 1, span: Span { @@ -236,19 +266,25 @@ Schema { end: 165, }, }, - ty: External( - ExternalType { - path: [], - name: Name { - value: "V", - span: Span { - start: 167, - end: 168, + ty: Type { + value: External( + ExternalType { + path: [], + name: Name { + value: "V", + span: Span { + start: 167, + end: 168, + }, }, + generics: [], }, - generics: [], + ), + span: Span { + start: 167, + end: 168, }, - ), + }, id: Id { value: 2, span: Span {