From 2737f20013cfe0d1fbf6b4a80ef101917183119a Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Tue, 24 Oct 2023 15:55:01 +0900 Subject: [PATCH] feat: nicely report compiler errors Extend parser structs with spans to generate nice error reports with annotated source code, like being done for parser errors. --- Cargo.lock | 8 +- crates/stef-build/Cargo.toml | 2 +- crates/stef-build/src/decode.rs | 24 +- crates/stef-build/src/definition.rs | 8 +- crates/stef-build/src/encode.rs | 25 +- crates/stef-build/src/lib.rs | 35 +- crates/stef-compiler/Cargo.toml | 1 + crates/stef-compiler/src/ids.rs | 70 ++- crates/stef-compiler/src/lib.rs | 5 +- crates/stef-compiler/src/names.rs | 46 +- crates/stef-parser/src/lib.rs | 134 ++++- crates/stef-parser/src/parser.rs | 6 +- crates/stef-parser/src/parser/enums.rs | 18 +- crates/stef-parser/src/parser/fields.rs | 23 +- .../parser__parse@enum-basic.stef.snap | 138 +++++- .../parser__parse@enum-generics.stef.snap | 138 +++++- .../parser__parse@enum-many-ws.stef.snap | 138 +++++- .../parser__parse@enum-min-ws.stef.snap | 174 +++++-- .../parser__parse@module-basic.stef.snap | 44 +- .../parser__parse@schema-basic.stef.snap | 182 +++++-- .../parser__parse@struct-basic.stef.snap | 44 +- .../parser__parse@struct-generics.stef.snap | 44 +- .../parser__parse@struct-many-ws.stef.snap | 44 +- .../parser__parse@struct-min-ws.stef.snap | 66 ++- .../parser__parse@struct-tuple.stef.snap | 28 +- .../parser__parse@types-basic.stef.snap | 462 ++++++++++++++---- .../parser__parse@types-generic.stef.snap | 110 ++++- .../parser__parse@types-nested.stef.snap | 22 +- .../parser__parse@types-non-zero.stef.snap | 330 ++++++++++--- .../parser__parse@types-ref.stef.snap | 110 ++++- crates/stef-playground/Cargo.toml | 1 - crates/stef-playground/build.rs | 2 +- 32 files changed, 1991 insertions(+), 491 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88ae58c..9dac4a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,12 +74,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - [[package]] name = "atty" version = "0.2.14" @@ -726,6 +720,7 @@ dependencies = [ name = "stef-compiler" version = "0.1.0" dependencies = [ + "miette", "stef-parser", "thiserror", ] @@ -755,7 +750,6 @@ dependencies = [ name = "stef-playground" version = "0.1.0" dependencies = [ - "anyhow", "stef", "stef-build", ] diff --git a/crates/stef-build/Cargo.toml b/crates/stef-build/Cargo.toml index 8baa2ef..3ad32f1 100644 --- a/crates/stef-build/Cargo.toml +++ b/crates/stef-build/Cargo.toml @@ -11,7 +11,7 @@ license.workspace = true [dependencies] glob = "0.3.1" -miette.workspace = true +miette = { workspace = true, features = ["fancy-no-backtrace"] } prettyplease = "0.2.15" proc-macro2.workspace = true quote.workspace = true diff --git a/crates/stef-build/src/decode.rs b/crates/stef-build/src/decode.rs index fdd033c..52f9d97 100644 --- a/crates/stef-build/src/decode.rs +++ b/crates/stef-build/src/decode.rs @@ -79,10 +79,11 @@ fn compile_variant( name, fields, id, + .. }: &Variant<'_>, ) -> TokenStream { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); - let name = Ident::new(name, Span::call_site()); + let id = proc_macro2::Literal::u32_unsuffixed(id.get()); + let name = Ident::new(name.get(), Span::call_site()); let field_vars = compile_field_vars(fields); let field_matches = compile_field_matches(fields); let field_assigns = compile_field_assigns(fields); @@ -111,7 +112,7 @@ fn compile_variant( fn compile_field_vars(fields: &Fields<'_>) -> TokenStream { let vars: Box> = match fields { Fields::Named(named) => Box::new(named.iter().map(|named| { - let name = Ident::new(named.name, Span::call_site()); + let name = Ident::new(named.name.get(), Span::call_site()); (name, &named.ty) })), Fields::Unnamed(unnamed) => Box::new(unnamed.iter().enumerate().map(|(idx, unnamed)| { @@ -143,9 +144,10 @@ fn compile_field_matches(fields: &Fields<'_>) -> TokenStream { name, ty, id, + .. }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); - let name = proc_macro2::Ident::new(name, Span::call_site()); + 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 { ty } else { @@ -162,8 +164,8 @@ fn compile_field_matches(fields: &Fields<'_>) -> TokenStream { let calls = unnamed .iter() .enumerate() - .map(|(idx, UnnamedField { ty, id })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); + .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 { ty @@ -184,9 +186,9 @@ fn compile_field_assigns(fields: &Fields<'_>) -> TokenStream { match fields { Fields::Named(named) => { let assigns = named.iter().map(|named| { - let name = Ident::new(named.name, Span::call_site()); - let name_lit = proc_macro2::Literal::string(named.name); - let id = proc_macro2::Literal::u32_unsuffixed(named.id.0); + let name = Ident::new(named.name.get(), Span::call_site()); + 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(_)) { quote! { #name } @@ -203,7 +205,7 @@ fn compile_field_assigns(fields: &Fields<'_>) -> TokenStream { Fields::Unnamed(unnamed) => { let assigns = unnamed.iter().enumerate().map(|(idx, unnamed)| { let name = Ident::new(&format!("n{idx}"), Span::call_site()); - let id = proc_macro2::Literal::u32_unsuffixed(unnamed.id.0); + let id = proc_macro2::Literal::u32_unsuffixed(unnamed.id.get()); if matches!(unnamed.ty, DataType::Option(_)) { quote! { #name } diff --git a/crates/stef-build/src/definition.rs b/crates/stef-build/src/definition.rs index e1cbe8a..d3fc0bb 100644 --- a/crates/stef-build/src/definition.rs +++ b/crates/stef-build/src/definition.rs @@ -125,10 +125,11 @@ fn compile_variant( name, fields, id: _, + .. }: &Variant<'_>, ) -> TokenStream { let comment = compile_comment(comment); - let name = Ident::new(name, Span::call_site()); + let name = Ident::new(name.get(), Span::call_site()); let fields = compile_fields(fields, false); quote! { @@ -215,10 +216,11 @@ fn compile_fields(fields: &Fields<'_>, for_struct: bool) -> TokenStream { name, ty, id: _, + .. }| { let comment = compile_comment(comment); let public = for_struct.then(|| quote! { pub }); - let name = Ident::new(name, Span::call_site()); + let name = Ident::new(name.get(), Span::call_site()); let ty = compile_data_type(ty); quote! { #comment @@ -232,7 +234,7 @@ fn compile_fields(fields: &Fields<'_>, for_struct: bool) -> TokenStream { } } } Fields::Unnamed(unnamed) => { - let fields = unnamed.iter().map(|UnnamedField { ty, id: _ }| { + let fields = unnamed.iter().map(|UnnamedField { ty, id: _, .. }| { let ty = compile_data_type(ty); quote! { #ty } }); diff --git a/crates/stef-build/src/encode.rs b/crates/stef-build/src/encode.rs index 1a0e47e..e9fc36c 100644 --- a/crates/stef-build/src/encode.rs +++ b/crates/stef-build/src/encode.rs @@ -40,9 +40,10 @@ fn compile_struct_fields(fields: &Fields<'_>) -> TokenStream { name, ty, id, + .. }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); - let name = proc_macro2::Ident::new(name, Span::call_site()); + 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) { @@ -67,8 +68,8 @@ fn compile_struct_fields(fields: &Fields<'_>) -> TokenStream { let calls = unnamed .iter() .enumerate() - .map(|(idx, UnnamedField { ty, id })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); + .map(|(idx, UnnamedField { ty, id, .. })| { + let id = proc_macro2::Literal::u32_unsuffixed(id.get()); let idx = proc_macro2::Literal::usize_unsuffixed(idx); let ty = compile_data_type(ty, quote! { self.#idx }); @@ -120,17 +121,18 @@ fn compile_variant( name, fields, id, + .. }: &Variant<'_>, ) -> TokenStream { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); - let name = Ident::new(name, Span::call_site()); + let id = proc_macro2::Literal::u32_unsuffixed(id.get()); + let name = Ident::new(name.get(), Span::call_site()); let fields_body = compile_variant_fields(fields); match fields { Fields::Named(named) => { let field_names = named .iter() - .map(|NamedField { name, .. }| Ident::new(name, Span::call_site())); + .map(|NamedField { name, .. }| Ident::new(name.get(), Span::call_site())); quote! { Self::#name{ #(#field_names,)* } => { @@ -170,9 +172,10 @@ fn compile_variant_fields(fields: &Fields<'_>) -> TokenStream { name, ty, id, + .. }| { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); - let name = proc_macro2::Ident::new(name, Span::call_site()); + 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(_)) { quote! { ::stef::buf::encode_field_option(w, #id, &#name); } @@ -192,8 +195,8 @@ fn compile_variant_fields(fields: &Fields<'_>) -> TokenStream { let calls = unnamed .iter() .enumerate() - .map(|(idx, UnnamedField { ty, id })| { - let id = proc_macro2::Literal::u32_unsuffixed(id.0); + .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(ty, quote! { *#name }); diff --git a/crates/stef-build/src/lib.rs b/crates/stef-build/src/lib.rs index b080004..6e4fb93 100644 --- a/crates/stef-build/src/lib.rs +++ b/crates/stef-build/src/lib.rs @@ -8,6 +8,7 @@ use std::{ path::{Path, PathBuf}, }; +use miette::{NamedSource, Report}; use stef_parser::Schema; use thiserror::Error; @@ -17,7 +18,7 @@ mod decode; mod definition; mod encode; -type Result = std::result::Result; +pub type Result = std::result::Result; #[derive(Debug, Error)] pub enum Error { @@ -38,17 +39,25 @@ pub enum Error { source: std::io::Error, file: PathBuf, }, - #[error("failed parsing schema from {file:?}: {message}")] - Parse { message: String, file: PathBuf }, - #[error("failed compiling schema from {file:?}")] - Compile { - #[source] - source: stef_compiler::Error, - file: PathBuf, - }, + #[error("failed parsing schema from {file:?}:\n{report:?}")] + Parse { report: Report, file: PathBuf }, + #[error("failed compiling schema from {file:?}:\n{report:?}")] + Compile { report: Report, file: PathBuf }, } pub fn compile(schemas: &[impl AsRef], _includes: &[impl AsRef]) -> Result<()> { + miette::set_hook(Box::new(|_| { + Box::new( + miette::MietteHandlerOpts::new() + .color(true) + .context_lines(3) + .force_graphical(true) + .terminal_links(true) + .build(), + ) + })) + .ok(); + let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); for schema in schemas.iter().map(AsRef::as_ref) { @@ -64,12 +73,14 @@ pub fn compile(schemas: &[impl AsRef], _includes: &[impl AsRef]) -> R })?; let schema = Schema::parse(&input).map_err(|e| Error::Parse { - message: format!("{e:?}"), + report: e + .with_source_code(NamedSource::new(path.display().to_string(), input.clone())), file: path.clone(), })?; - stef_compiler::validate_schema(&schema).map_err(|source| Error::Compile { - source, + stef_compiler::validate_schema(&schema).map_err(|e| Error::Compile { + report: Report::new(e) + .with_source_code(NamedSource::new(path.display().to_string(), input.clone())), file: path.clone(), })?; diff --git a/crates/stef-compiler/Cargo.toml b/crates/stef-compiler/Cargo.toml index 25bbde6..929a1af 100644 --- a/crates/stef-compiler/Cargo.toml +++ b/crates/stef-compiler/Cargo.toml @@ -10,5 +10,6 @@ repository.workspace = true license.workspace = true [dependencies] +miette.workspace = true stef-parser = { path = "../stef-parser" } thiserror.workspace = true diff --git a/crates/stef-compiler/src/ids.rs b/crates/stef-compiler/src/ids.rs index b575af2..e09e496 100644 --- a/crates/stef-compiler/src/ids.rs +++ b/crates/stef-compiler/src/ids.rs @@ -1,37 +1,55 @@ -use std::collections::HashMap; +use std::{collections::HashMap, ops::Range}; -use stef_parser::{Enum, Fields, Id, Struct}; +use miette::Diagnostic; +use stef_parser::{Enum, Fields, Id, Spanned, Struct}; use thiserror::Error; -#[derive(Debug, Error)] +#[derive(Debug, Diagnostic, Error)] pub enum DuplicateId { #[error("duplicate ID in an enum variant")] + #[diagnostic(transparent)] EnumVariant(#[from] DuplicateVariantId), #[error("duplicate ID in a field")] + #[diagnostic(transparent)] Field(#[from] DuplicateFieldId), } -#[derive(Debug, Error)] -#[error("duplicate ID {} in enum variant `{name}`, already used in `{other_name}`", id.0)] +#[derive(Debug, Diagnostic, Error)] +#[error("duplicate ID {} in enum variant `{name}`, already used in `{other_name}`", id.get())] +#[diagnostic(help("the IDs for each variant of an enum must be unique"))] pub struct DuplicateVariantId { pub id: Id, pub name: String, pub other_name: String, + #[label("first declared here")] + pub first: Range, + #[label("used here again")] + pub second: Range, } -#[derive(Debug, Error)] +#[derive(Debug, Diagnostic, Error)] pub enum DuplicateFieldId { - #[error("duplicate ID {} in field `{name}`, already used in `{other_name}`", id.0)] + #[error("duplicate ID {} in field `{name}`, already used in `{other_name}`", id.get())] + #[diagnostic(help("the IDs for each field must be unique"))] Named { id: Id, name: String, other_name: String, + #[label("first declared here")] + first: Range, + #[label("used here again")] + second: Range, }, - #[error("duplicate ID {} in field {position}, already used in {other_position}", id.0)] + #[error("duplicate ID {} in field {position}, already used in {other_position}", id.get())] + #[diagnostic(help("the IDs for each field must be unique"))] Unnamed { id: Id, position: usize, other_position: usize, + #[label("first declared here")] + first: Range, + #[label("used here again")] + second: Range, }, } @@ -49,12 +67,14 @@ pub(crate) fn validate_enum_ids(value: &Enum<'_>) -> Result<(), DuplicateId> { .iter() .find_map(|variant| { visited - .insert(variant.id, variant.name) - .map(|other_name| { + .insert(variant.id.get(), (variant.name.get(), variant.id.span())) + .map(|(other_name, other_span)| { DuplicateVariantId { - id: variant.id, - name: variant.name.to_owned(), + id: variant.id.clone(), + name: variant.name.get().to_owned(), other_name: other_name.to_owned(), + first: other_span.into(), + second: variant.id.span().into(), } .into() }) @@ -75,13 +95,15 @@ fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> { named .iter() .find_map(|field| { - visited.insert(field.id, field.name).map(|other_field| { - DuplicateFieldId::Named { - id: field.id, - name: field.name.to_owned(), + visited + .insert(field.id.get(), (field.name.get(), field.id.span())) + .map(|(other_field, other_span)| DuplicateFieldId::Named { + id: field.id.clone(), + name: field.name.get().to_owned(), other_name: other_field.to_owned(), - } - }) + first: other_span.into(), + second: field.id.span().into(), + }) }) .map_or(Ok(()), Err)?; } @@ -91,13 +113,15 @@ fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> { .iter() .enumerate() .find_map(|(pos, field)| { - visited - .insert(field.id, pos) - .map(|other_position| DuplicateFieldId::Unnamed { - id: field.id, + visited.insert(field.id.get(), (pos, field.id.span())).map( + |(other_position, other_span)| DuplicateFieldId::Unnamed { + id: field.id.clone(), position: pos, other_position, - }) + first: other_span.into(), + second: field.id.span().into(), + }, + ) }) .map_or(Ok(()), Err)?; } diff --git a/crates/stef-compiler/src/lib.rs b/crates/stef-compiler/src/lib.rs index 34ff561..f6d0dc6 100644 --- a/crates/stef-compiler/src/lib.rs +++ b/crates/stef-compiler/src/lib.rs @@ -4,6 +4,7 @@ #![allow(clippy::missing_errors_doc)] pub use ids::{DuplicateFieldId, DuplicateId, DuplicateVariantId}; +use miette::Diagnostic; use stef_parser::{Definition, Schema}; use thiserror::Error; @@ -12,11 +13,13 @@ use self::names::{DuplicateFieldName, DuplicateName}; mod ids; mod names; -#[derive(Debug, Error)] +#[derive(Debug, Diagnostic, Error)] pub enum Error { #[error("duplicate ID found")] + #[diagnostic(transparent)] DuplicateId(#[from] DuplicateId), #[error("duplicate name found")] + #[diagnostic(transparent)] DuplicateName(#[from] DuplicateName), } diff --git a/crates/stef-compiler/src/names.rs b/crates/stef-compiler/src/names.rs index ef29d88..95f9fc5 100644 --- a/crates/stef-compiler/src/names.rs +++ b/crates/stef-compiler/src/names.rs @@ -1,26 +1,39 @@ -use std::collections::HashSet; +use std::{collections::HashMap, ops::Range}; -use stef_parser::{Enum, Fields, Struct}; +use miette::Diagnostic; +use stef_parser::{Enum, Fields, Spanned, Struct}; use thiserror::Error; -#[derive(Debug, Error)] +#[derive(Debug, Diagnostic, Error)] pub enum DuplicateName { #[error("duplicate name in an enum variant")] + #[diagnostic(transparent)] EnumVariant(#[from] DuplicateVariantName), #[error("duplicate name in a field")] + #[diagnostic(transparent)] Field(#[from] DuplicateFieldName), } -#[derive(Debug, Error)] +#[derive(Debug, Diagnostic, Error)] #[error("duplicate variant name `{name}` in enum")] +#[diagnostic(help("the names of each variant must be unique"))] pub struct DuplicateVariantName { pub name: String, + #[label("first declared here")] + pub first: Range, + #[label("used here again")] + pub second: Range, } -#[derive(Debug, Error)] +#[derive(Debug, Diagnostic, Error)] #[error("duplicate field name `{name}`")] +#[diagnostic(help("the names of each field must be unique"))] pub struct DuplicateFieldName { pub name: String, + #[label("first declared here")] + pub first: Range, + #[label("used here again")] + pub second: Range, } /// Ensure all field names inside a struct are unique. @@ -31,15 +44,18 @@ pub(crate) fn validate_struct_names(value: &Struct<'_>) -> Result<(), DuplicateF /// Ensure all names inside an enum are unique, which means all variants have a unique name, plus /// all potential fields in a variant are unique (within that variant). pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName> { - let mut visited = HashSet::with_capacity(value.variants.len()); + let mut visited = HashMap::with_capacity(value.variants.len()); value .variants .iter() .find_map(|variant| { - (!visited.insert(variant.name)) - .then(|| { + visited + .insert(variant.name.get(), variant.name.span()) + .map(|first| { DuplicateVariantName { - name: variant.name.to_owned(), + name: variant.name.get().to_owned(), + first: first.into(), + second: variant.name.span().into(), } .into() }) @@ -56,13 +72,17 @@ pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName> fn validate_field_names(value: &Fields<'_>) -> Result<(), DuplicateFieldName> { match value { Fields::Named(named) => { - let mut visited = HashSet::with_capacity(named.len()); + let mut visited = HashMap::with_capacity(named.len()); named .iter() .find_map(|field| { - (!visited.insert(field.name)).then(|| DuplicateFieldName { - name: field.name.to_owned(), - }) + visited + .insert(field.name.get(), field.name.span()) + .map(|first| DuplicateFieldName { + name: field.name.get().to_owned(), + first: first.into(), + second: field.name.span().into(), + }) }) .map_or(Ok(()), Err)?; } diff --git a/crates/stef-parser/src/lib.rs b/crates/stef-parser/src/lib.rs index 3ebde34..c09a683 100644 --- a/crates/stef-parser/src/lib.rs +++ b/crates/stef-parser/src/lib.rs @@ -20,7 +20,10 @@ #![deny(rust_2018_idioms, clippy::all)] #![warn(missing_docs, clippy::pedantic)] -use std::fmt::{self, Display}; +use std::{ + fmt::{self, Display}, + ops::Range, +}; pub use miette::{Diagnostic, LabeledSpan}; use miette::{IntoDiagnostic, Report, Result}; @@ -50,6 +53,35 @@ trait Print { } } +/// Source code span that marks the location of any element in the schema that it was parsed from. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub struct Span { + start: usize, + end: usize, +} + +impl From> for Span { + fn from(value: Range) -> Self { + Self { + start: value.start, + end: value.end, + } + } +} + +impl From for Range { + fn from(value: Span) -> Self { + value.start..value.end + } +} + +/// Implemented by any parsed schema element that can report the source code span that it originated +/// from. This helps during error reporting to visualize the exact location of a problem. +pub trait Spanned { + /// Get the source code span of this schema element. + fn span(&self) -> Span; +} + /// Shorthand for calling [`Schema::parse`]. /// /// # Errors @@ -331,11 +363,13 @@ pub struct Variant<'a> { /// Optional variant-level comment. pub comment: Comment<'a>, /// Unique for this variant, within the enum it belongs to. - pub name: &'a str, + pub name: Name<'a>, /// Fields of this variant, if any. pub fields: Fields<'a>, /// Identifier for this variant, that must be unique within the current enum. pub id: Id, + /// Source code location. + span: Span, } impl<'a> Print for Variant<'a> { @@ -345,18 +379,25 @@ impl<'a> Print for Variant<'a> { name, fields, id, + span: _, } = self; comment.print(f, level)?; Self::indent(f, level)?; - f.write_str(name)?; + f.write_str(name.get())?; fields.print(f, level)?; write!(f, " {id},") } } +impl<'a> Spanned for Variant<'a> { + fn span(&self) -> Span { + self.span + } +} + impl<'a> Display for Variant<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.print(f, 0) @@ -464,11 +505,13 @@ pub struct NamedField<'a> { /// Optional field-level comment. pub comment: Comment<'a>, /// Unique name for this field, within the current element. - pub name: &'a str, + pub name: Name<'a>, /// Data type that defines the shape of the contained data. pub ty: DataType<'a>, /// Identifier for this field, that must be unique within the current element. pub id: Id, + /// Source code location. + span: Span, } impl<'a> Print for NamedField<'a> { @@ -478,6 +521,7 @@ impl<'a> Print for NamedField<'a> { name, ty, id, + span: _, } = self; comment.print(f, level)?; @@ -487,6 +531,12 @@ impl<'a> Print for NamedField<'a> { } } +impl<'a> Spanned for NamedField<'a> { + fn span(&self) -> Span { + self.span + } +} + impl<'a> Display for NamedField<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.print(f, 0) @@ -507,11 +557,19 @@ pub struct UnnamedField<'a> { pub ty: DataType<'a>, /// Identifier for this field, that must be unique within the current element. pub id: Id, + /// Source code location. + span: Span, +} + +impl<'a> Spanned for UnnamedField<'a> { + fn span(&self) -> Span { + self.span + } } impl<'a> Display for UnnamedField<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { ty, id } = self; + let Self { ty, id, span: _ } = self; write!(f, "{ty} {id}") } } @@ -763,13 +821,71 @@ impl<'a> Display for Generics<'a> { /// ```txt /// @1 /// ``` -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct Id(pub u32); +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Id { + /// Raw integer value. + value: u32, + /// Source code location. + span: Span, +} + +impl Id { + /// Retrieve the raw integer value of this identifier. + #[must_use] + pub const fn get(&self) -> u32 { + self.value + } +} + +impl Spanned for Id { + fn span(&self) -> Span { + self.span + } +} impl Display for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self(id) = *self; - write!(f, "@{id}") + let Self { value, span: _ } = *self; + write!(f, "@{value}") + } +} + +/// An arbitrary name of any element, which additionally carries a span into the schema to mark its +/// location. +#[derive(Debug, Eq, PartialEq)] +pub struct Name<'a> { + /// Raw string value. + value: &'a str, + /// Source code location. + span: Span, +} + +impl<'a> Name<'a> { + /// Retrieve the raw string value of this name. + #[must_use] + pub const fn get(&self) -> &str { + self.value + } +} + +impl<'a> Spanned for Name<'a> { + fn span(&self) -> Span { + self.span + } +} + +impl<'a> Display for Name<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.value.fmt(f) + } +} + +impl<'a> From<(&'a str, Range)> for Name<'a> { + fn from((value, span): (&'a str, Range)) -> Self { + Self { + value, + span: span.into(), + } } } diff --git a/crates/stef-parser/src/parser.rs b/crates/stef-parser/src/parser.rs index a2c0490..a186914 100644 --- a/crates/stef-parser/src/parser.rs +++ b/crates/stef-parser/src/parser.rs @@ -115,8 +115,12 @@ mod ids { pub(super) fn parse(input: &mut Input<'_>) -> Result { preceded('@', dec_uint) + .with_span() .parse_next(input) - .map(Id) + .map(|(value, span)| Id { + value, + span: span.into(), + }) .map_err(|e| { e.map(|e: ErrorKind| ParseError { at: input.location()..input.location(), diff --git a/crates/stef-parser/src/parser/enums.rs b/crates/stef-parser/src/parser/enums.rs index ebe34a2..690af1f 100644 --- a/crates/stef-parser/src/parser/enums.rs +++ b/crates/stef-parser/src/parser/enums.rs @@ -124,7 +124,7 @@ fn parse_variants<'i>(input: &mut Input<'i>) -> Result>, Cause> preceded( '{', cut_err(terminated( - terminated(separated1(ws(parse_variant), ws(',')), opt(ws(','))), + terminated(separated1(parse_variant, ws(',')), opt(ws(','))), ws('}'), )), ) @@ -133,17 +133,21 @@ fn parse_variants<'i>(input: &mut Input<'i>) -> Result>, Cause> fn parse_variant<'i>(input: &mut Input<'i>) -> Result, Cause> { ( - comments::parse.map_err(Cause::from), - preceded(space0, parse_variant_name), - preceded(space0, fields::parse.map_err(Cause::from)), - preceded(space0, ids::parse.map_err(Cause::from)), + ws(comments::parse.map_err(Cause::from)), + ( + preceded(space0, parse_variant_name.with_span()), + preceded(space0, fields::parse.map_err(Cause::from)), + preceded(space0, ids::parse.map_err(Cause::from)), + ) + .with_span(), ) .parse_next(input) - .map(|(comment, name, fields, id)| Variant { + .map(|(comment, ((name, fields, id), span))| Variant { comment, - name, + name: name.into(), fields, id, + span: span.into(), }) } diff --git a/crates/stef-parser/src/parser/fields.rs b/crates/stef-parser/src/parser/fields.rs index 154e9ba..9e5dfd4 100644 --- a/crates/stef-parser/src/parser/fields.rs +++ b/crates/stef-parser/src/parser/fields.rs @@ -115,25 +115,34 @@ fn parse_unit(input: &mut Input<'_>) -> Result<(), Cause> { fn parse_unnamed_field<'i>(input: &mut Input<'i>) -> Result, Cause> { ( ws(types::parse.map_err(Cause::from)), - ws(cut_err(ids::parse.map_err(Cause::from))), + preceded(space0, cut_err(ids::parse.map_err(Cause::from))), ) + .with_span() .parse_next(input) - .map(|(ty, id)| UnnamedField { ty, id }) + .map(|((ty, id), span)| UnnamedField { + ty, + id, + span: span.into(), + }) } fn parse_named_field<'i>(input: &mut Input<'i>) -> Result, Cause> { ( ws(comments::parse.map_err(Cause::from)), - delimited(space0, parse_field_name, ':'), - preceded(space0, types::parse.map_err(Cause::from)), - preceded(space0, ids::parse.map_err(Cause::from)), + ( + delimited(space0, parse_field_name.with_span(), ':'), + preceded(space0, types::parse.map_err(Cause::from)), + preceded(space0, ids::parse.map_err(Cause::from)), + ) + .with_span(), ) .parse_next(input) - .map(|(comment, name, ty, id)| NamedField { + .map(|(comment, ((name, ty, id), span))| NamedField { comment, - name, + name: name.into(), ty, id, + span: span.into(), }) } 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 26ea14a..c6baa25 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 @@ -24,11 +24,25 @@ Schema { comment: Comment( [], ), - name: "One", + name: Name { + value: "One", + span: Span { + start: 35, + end: 38, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 39, + end: 41, + }, + }, + span: Span { + start: 35, + end: 41, + }, }, Variant { comment: Comment( @@ -36,43 +50,93 @@ Schema { "Second variant", ], ), - name: "Two", + name: Name { + value: "Two", + span: Span { + start: 70, + end: 73, + }, + }, fields: Unnamed( [ UnnamedField { ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 78, + end: 80, + }, + }, + span: Span { + start: 74, + end: 80, + }, }, UnnamedField { ty: U64, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 86, + end: 88, + }, + }, + span: Span { + start: 81, + end: 88, + }, }, ], ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 90, + end: 92, + }, + }, + span: Span { + start: 66, + end: 92, + }, }, Variant { comment: Comment( [], ), - name: "Three", + name: Name { + value: "Three", + span: Span { + start: 98, + end: 103, + }, + }, fields: Named( [ NamedField { comment: Comment( [], ), - name: "field1", + name: Name { + value: "field1", + span: Span { + start: 114, + end: 120, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 126, + end: 128, + }, + }, + span: Span { + start: 114, + end: 128, + }, }, NamedField { comment: Comment( @@ -80,17 +144,39 @@ Schema { "Second field of third variant", ], ), - name: "field2", + name: Name { + value: "field2", + span: Span { + start: 180, + end: 186, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 193, + end: 195, + }, + }, + span: Span { + start: 172, + end: 195, + }, }, ], ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 203, + end: 205, + }, + }, + span: Span { + start: 98, + end: 205, + }, }, ], }, 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 7ae4cc1..f14a078 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 @@ -29,17 +29,37 @@ Schema { comment: Comment( [], ), - name: "One", + name: Name { + value: "One", + span: Span { + start: 54, + end: 57, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 58, + end: 60, + }, + }, + span: Span { + start: 54, + end: 60, + }, }, Variant { comment: Comment( [], ), - name: "Two", + name: Name { + value: "Two", + span: Span { + start: 66, + end: 69, + }, + }, fields: Unnamed( [ UnnamedField { @@ -50,9 +70,17 @@ Schema { generics: [], }, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 72, + end: 74, + }, + }, + span: Span { + start: 70, + end: 74, + }, }, UnnamedField { ty: External( @@ -62,28 +90,56 @@ Schema { generics: [], }, ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 78, + end: 80, + }, + }, + span: Span { + start: 75, + end: 80, + }, }, ], ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 82, + end: 84, + }, + }, + span: Span { + start: 66, + end: 84, + }, }, Variant { comment: Comment( [], ), - name: "Three", + name: Name { + value: "Three", + span: Span { + start: 90, + end: 95, + }, + }, fields: Named( [ NamedField { comment: Comment( [], ), - name: "field1", + name: Name { + value: "field1", + span: Span { + start: 106, + end: 112, + }, + }, ty: External( ExternalType { path: [], @@ -91,15 +147,29 @@ Schema { generics: [], }, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 116, + end: 118, + }, + }, + span: Span { + start: 106, + end: 118, + }, }, NamedField { comment: Comment( [], ), - name: "field2", + name: Name { + value: "field2", + span: Span { + start: 128, + end: 134, + }, + }, ty: External( ExternalType { path: [], @@ -107,15 +177,31 @@ Schema { generics: [], }, ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 138, + end: 140, + }, + }, + span: Span { + start: 128, + end: 140, + }, }, ], ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 148, + end: 150, + }, + }, + span: Span { + start: 90, + end: 150, + }, }, ], }, 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 beacc54..dbffe5a 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 @@ -24,69 +24,155 @@ Schema { comment: Comment( [], ), - name: "One", + name: Name { + value: "One", + span: Span { + start: 49, + end: 52, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 58, + end: 60, + }, + }, + span: Span { + start: 49, + end: 60, + }, }, Variant { comment: Comment( [], ), - name: "Two", + name: Name { + value: "Two", + span: Span { + start: 70, + end: 73, + }, + }, fields: Unnamed( [ UnnamedField { ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 85, + end: 87, + }, + }, + span: Span { + start: 76, + end: 87, + }, }, UnnamedField { ty: U64, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 101, + end: 103, + }, + }, + span: Span { + start: 88, + end: 103, + }, }, ], ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 108, + end: 110, + }, + }, + span: Span { + start: 70, + end: 110, + }, }, Variant { comment: Comment( [], ), - name: "Three", + name: Name { + value: "Three", + span: Span { + start: 125, + end: 130, + }, + }, fields: Named( [ NamedField { comment: Comment( [], ), - name: "field1", + name: Name { + value: "field1", + span: Span { + start: 158, + end: 164, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 178, + end: 180, + }, + }, + span: Span { + start: 158, + end: 180, + }, }, NamedField { comment: Comment( [], ), - name: "field2", + name: Name { + value: "field2", + span: Span { + start: 203, + end: 209, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 223, + end: 225, + }, + }, + span: Span { + start: 203, + end: 225, + }, }, ], ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 245, + end: 247, + }, + }, + span: Span { + start: 125, + end: 247, + }, }, ], }, 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 6adc90a..9e9aba3 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 @@ -24,30 +24,66 @@ Schema { comment: Comment( [], ), - name: "One", + name: Name { + value: "One", + span: Span { + start: 15, + end: 18, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 18, + end: 20, + }, + }, + span: Span { + start: 15, + end: 20, + }, }, Variant { comment: Comment( [], ), - name: "Two", + name: Name { + value: "Two", + span: Span { + start: 21, + end: 24, + }, + }, fields: Unnamed( [ UnnamedField { ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 28, + end: 30, + }, + }, + span: Span { + start: 25, + end: 30, + }, }, UnnamedField { ty: U64, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 34, + end: 36, + }, + }, + span: Span { + start: 31, + end: 36, + }, }, UnnamedField { ty: External( @@ -57,48 +93,104 @@ Schema { generics: [], }, ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 38, + end: 40, + }, + }, + span: Span { + start: 37, + end: 40, + }, }, ], ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 41, + end: 43, + }, + }, + span: Span { + start: 21, + end: 43, + }, }, Variant { comment: Comment( [], ), - name: "Three", + name: Name { + value: "Three", + span: Span { + start: 44, + end: 49, + }, + }, fields: Named( [ NamedField { comment: Comment( [], ), - name: "field1", + name: Name { + value: "field1", + span: Span { + start: 50, + end: 56, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 60, + end: 62, + }, + }, + span: Span { + start: 50, + end: 62, + }, }, NamedField { comment: Comment( [], ), - name: "field2", + name: Name { + value: "field2", + span: Span { + start: 63, + end: 69, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 74, + end: 76, + }, + }, + span: Span { + start: 63, + end: 76, + }, }, NamedField { comment: Comment( [], ), - name: "field3", + name: Name { + value: "field3", + span: Span { + start: 77, + end: 83, + }, + }, ty: External( ExternalType { path: [], @@ -106,15 +198,31 @@ Schema { generics: [], }, ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 85, + end: 87, + }, + }, + span: Span { + start: 77, + end: 87, + }, }, ], ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 88, + end: 90, + }, + }, + span: Span { + start: 44, + end: 90, + }, }, ], }, 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 5494f57..eec1432 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 @@ -38,11 +38,25 @@ Schema { comment: Comment( [], ), - name: "One", + name: Name { + value: "One", + span: Span { + start: 75, + end: 78, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 79, + end: 81, + }, + }, + span: Span { + start: 75, + end: 81, + }, }, ], }, @@ -68,11 +82,25 @@ Schema { comment: Comment( [], ), - name: "value", + name: Name { + value: "value", + span: Span { + start: 128, + end: 133, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 139, + end: 141, + }, + }, + span: Span { + start: 128, + end: 141, + }, }, ], ), 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 f3bcf69..739a78f 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 @@ -25,21 +25,49 @@ Schema { comment: Comment( [], ), - name: "a", + name: Name { + value: "a", + span: Span { + start: 44, + end: 45, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 51, + end: 53, + }, + }, + span: Span { + start: 44, + end: 53, + }, }, NamedField { comment: Comment( [], ), - name: "b", + name: Name { + value: "b", + span: Span { + start: 59, + end: 60, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 67, + end: 69, + }, + }, + span: Span { + start: 59, + end: 69, + }, }, ], ), @@ -64,69 +92,155 @@ Schema { comment: Comment( [], ), - name: "One", + name: Name { + value: "One", + span: Span { + start: 113, + end: 116, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 117, + end: 119, + }, + }, + span: Span { + start: 113, + end: 119, + }, }, Variant { comment: Comment( [], ), - name: "Two", + name: Name { + value: "Two", + span: Span { + start: 125, + end: 128, + }, + }, fields: Unnamed( [ UnnamedField { ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 133, + end: 135, + }, + }, + span: Span { + start: 129, + end: 135, + }, }, UnnamedField { ty: U64, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 141, + end: 143, + }, + }, + span: Span { + start: 136, + end: 143, + }, }, ], ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 145, + end: 147, + }, + }, + span: Span { + start: 125, + end: 147, + }, }, Variant { comment: Comment( [], ), - name: "Three", + name: Name { + value: "Three", + span: Span { + start: 153, + end: 158, + }, + }, fields: Named( [ NamedField { comment: Comment( [], ), - name: "field1", + name: Name { + value: "field1", + span: Span { + start: 169, + end: 175, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 181, + end: 183, + }, + }, + span: Span { + start: 169, + end: 183, + }, }, NamedField { comment: Comment( [], ), - name: "field2", + name: Name { + value: "field2", + span: Span { + start: 193, + end: 199, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 206, + end: 208, + }, + }, + span: Span { + start: 193, + end: 208, + }, }, ], ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 216, + end: 218, + }, + }, + span: Span { + start: 153, + end: 218, + }, }, ], }, 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 a24dab6..8dd810c 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 @@ -25,11 +25,25 @@ Schema { comment: Comment( [], ), - name: "a", + name: Name { + value: "a", + span: Span { + start: 38, + end: 39, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 45, + end: 47, + }, + }, + span: Span { + start: 38, + end: 47, + }, }, NamedField { comment: Comment( @@ -37,11 +51,25 @@ Schema { "Second field", ], ), - name: "b", + name: Name { + value: "b", + span: Span { + start: 74, + end: 75, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 82, + end: 84, + }, + }, + span: Span { + start: 70, + end: 84, + }, }, ], ), 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 a678310..5a2221f 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 @@ -28,7 +28,13 @@ Schema { comment: Comment( [], ), - name: "key", + name: Name { + value: "key", + span: Span { + start: 56, + end: 59, + }, + }, ty: External( ExternalType { path: [], @@ -36,15 +42,29 @@ Schema { generics: [], }, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 63, + end: 65, + }, + }, + span: Span { + start: 56, + end: 65, + }, }, NamedField { comment: Comment( [], ), - name: "value", + name: Name { + value: "value", + span: Span { + start: 71, + end: 76, + }, + }, ty: External( ExternalType { path: [], @@ -52,9 +72,17 @@ Schema { generics: [], }, ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 80, + end: 82, + }, + }, + span: Span { + start: 71, + end: 82, + }, }, ], ), 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 03fdc7f..9b59673 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 @@ -28,21 +28,49 @@ Schema { comment: Comment( [], ), - name: "a", + name: Name { + value: "a", + span: Span { + start: 95, + end: 96, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 108, + end: 110, + }, + }, + span: Span { + start: 95, + end: 110, + }, }, NamedField { comment: Comment( [], ), - name: "b", + name: Name { + value: "b", + span: Span { + start: 118, + end: 119, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 131, + end: 133, + }, + }, + span: Span { + start: 118, + end: 133, + }, }, ], ), 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 54d132a..96a8fa5 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 @@ -25,27 +25,61 @@ Schema { comment: Comment( [], ), - name: "a", + name: Name { + value: "a", + span: Span { + start: 17, + end: 18, + }, + }, ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 22, + end: 24, + }, + }, + span: Span { + start: 17, + end: 24, + }, }, NamedField { comment: Comment( [], ), - name: "b", + name: Name { + value: "b", + span: Span { + start: 25, + end: 26, + }, + }, ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 31, + end: 33, + }, + }, + span: Span { + start: 25, + end: 33, + }, }, NamedField { comment: Comment( [], ), - name: "c", + name: Name { + value: "c", + span: Span { + start: 34, + end: 35, + }, + }, ty: External( ExternalType { path: [], @@ -53,9 +87,17 @@ Schema { generics: [], }, ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 37, + end: 39, + }, + }, + span: Span { + start: 34, + end: 39, + }, }, ], ), 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 df761c2..db9fda7 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 @@ -23,15 +23,31 @@ Schema { [ UnnamedField { ty: U32, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 36, + end: 38, + }, + }, + span: Span { + start: 32, + end: 38, + }, }, UnnamedField { ty: Bool, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 45, + end: 47, + }, + }, + span: Span { + start: 39, + end: 47, + }, }, ], ), 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 7722ea9..4f101c5 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 @@ -23,197 +23,469 @@ Schema { comment: Comment( [], ), - name: "f01", + name: Name { + value: "f01", + span: Span { + start: 20, + end: 23, + }, + }, ty: Bool, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 30, + end: 32, + }, + }, + span: Span { + start: 20, + end: 32, + }, }, NamedField { comment: Comment( [], ), - name: "f02", + name: Name { + value: "f02", + span: Span { + start: 38, + end: 41, + }, + }, ty: U8, - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 46, + end: 48, + }, + }, + span: Span { + start: 38, + end: 48, + }, }, NamedField { comment: Comment( [], ), - name: "f03", + name: Name { + value: "f03", + span: Span { + start: 54, + end: 57, + }, + }, ty: U16, - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 63, + end: 65, + }, + }, + span: Span { + start: 54, + end: 65, + }, }, NamedField { comment: Comment( [], ), - name: "f04", + name: Name { + value: "f04", + span: Span { + start: 71, + end: 74, + }, + }, ty: U32, - id: Id( - 4, - ), + id: Id { + value: 4, + span: Span { + start: 80, + end: 82, + }, + }, + span: Span { + start: 71, + end: 82, + }, }, NamedField { comment: Comment( [], ), - name: "f05", + name: Name { + value: "f05", + span: Span { + start: 88, + end: 91, + }, + }, ty: U64, - id: Id( - 5, - ), + id: Id { + value: 5, + span: Span { + start: 97, + end: 99, + }, + }, + span: Span { + start: 88, + end: 99, + }, }, NamedField { comment: Comment( [], ), - name: "f06", + name: Name { + value: "f06", + span: Span { + start: 105, + end: 108, + }, + }, ty: U128, - id: Id( - 6, - ), + id: Id { + value: 6, + span: Span { + start: 115, + end: 117, + }, + }, + span: Span { + start: 105, + end: 117, + }, }, NamedField { comment: Comment( [], ), - name: "f07", + name: Name { + value: "f07", + span: Span { + start: 123, + end: 126, + }, + }, ty: I8, - id: Id( - 7, - ), + id: Id { + value: 7, + span: Span { + start: 131, + end: 133, + }, + }, + span: Span { + start: 123, + end: 133, + }, }, NamedField { comment: Comment( [], ), - name: "f08", + name: Name { + value: "f08", + span: Span { + start: 139, + end: 142, + }, + }, ty: I16, - id: Id( - 8, - ), + id: Id { + value: 8, + span: Span { + start: 148, + end: 150, + }, + }, + span: Span { + start: 139, + end: 150, + }, }, NamedField { comment: Comment( [], ), - name: "f09", + name: Name { + value: "f09", + span: Span { + start: 156, + end: 159, + }, + }, ty: I32, - id: Id( - 9, - ), + id: Id { + value: 9, + span: Span { + start: 165, + end: 167, + }, + }, + span: Span { + start: 156, + end: 167, + }, }, NamedField { comment: Comment( [], ), - name: "f10", + name: Name { + value: "f10", + span: Span { + start: 173, + end: 176, + }, + }, ty: I64, - id: Id( - 10, - ), + id: Id { + value: 10, + span: Span { + start: 182, + end: 185, + }, + }, + span: Span { + start: 173, + end: 185, + }, }, NamedField { comment: Comment( [], ), - name: "f11", + name: Name { + value: "f11", + span: Span { + start: 191, + end: 194, + }, + }, ty: I128, - id: Id( - 11, - ), + id: Id { + value: 11, + span: Span { + start: 201, + end: 204, + }, + }, + span: Span { + start: 191, + end: 204, + }, }, NamedField { comment: Comment( [], ), - name: "f12", + name: Name { + value: "f12", + span: Span { + start: 210, + end: 213, + }, + }, ty: F32, - id: Id( - 12, - ), + id: Id { + value: 12, + span: Span { + start: 219, + end: 222, + }, + }, + span: Span { + start: 210, + end: 222, + }, }, NamedField { comment: Comment( [], ), - name: "f13", + name: Name { + value: "f13", + span: Span { + start: 228, + end: 231, + }, + }, ty: F64, - id: Id( - 13, - ), + id: Id { + value: 13, + span: Span { + start: 237, + end: 240, + }, + }, + span: Span { + start: 228, + end: 240, + }, }, NamedField { comment: Comment( [], ), - name: "f14", + name: Name { + value: "f14", + span: Span { + start: 246, + end: 249, + }, + }, ty: String, - id: Id( - 14, - ), + id: Id { + value: 14, + span: Span { + start: 258, + end: 261, + }, + }, + span: Span { + start: 246, + end: 261, + }, }, NamedField { comment: Comment( [], ), - name: "f15", + name: Name { + value: "f15", + span: Span { + start: 267, + end: 270, + }, + }, ty: StringRef, - id: Id( - 15, - ), + id: Id { + value: 15, + span: Span { + start: 280, + end: 283, + }, + }, + span: Span { + start: 267, + end: 283, + }, }, NamedField { comment: Comment( [], ), - name: "f16", + name: Name { + value: "f16", + span: Span { + start: 289, + end: 292, + }, + }, ty: Bytes, - id: Id( - 16, - ), + id: Id { + value: 16, + span: Span { + start: 300, + end: 303, + }, + }, + span: Span { + start: 289, + end: 303, + }, }, NamedField { comment: Comment( [], ), - name: "f17", + name: Name { + value: "f17", + span: Span { + start: 309, + end: 312, + }, + }, ty: BytesRef, - id: Id( - 17, - ), + id: Id { + value: 17, + span: Span { + start: 321, + end: 324, + }, + }, + span: Span { + start: 309, + end: 324, + }, }, NamedField { comment: Comment( [], ), - name: "f18", + name: Name { + value: "f18", + span: Span { + start: 330, + end: 333, + }, + }, ty: BoxString, - id: Id( - 18, - ), + id: Id { + value: 18, + span: Span { + start: 347, + end: 350, + }, + }, + span: Span { + start: 330, + end: 350, + }, }, NamedField { comment: Comment( [], ), - name: "f19", + name: Name { + value: "f19", + span: Span { + start: 356, + end: 359, + }, + }, ty: BoxBytes, - id: Id( - 19, - ), + id: Id { + value: 19, + span: Span { + start: 372, + end: 375, + }, + }, + span: Span { + start: 356, + end: 375, + }, }, NamedField { comment: Comment( [], ), - name: "f20", + name: Name { + value: "f20", + span: Span { + start: 381, + end: 384, + }, + }, ty: Tuple( [ U32, @@ -221,22 +493,44 @@ Schema { U32, ], ), - id: Id( - 20, - ), + id: Id { + value: 20, + span: Span { + start: 402, + end: 405, + }, + }, + span: Span { + start: 381, + end: 405, + }, }, NamedField { comment: Comment( [], ), - name: "f21", + name: Name { + value: "f21", + span: Span { + start: 411, + end: 414, + }, + }, ty: Array( U32, 12, ), - id: Id( - 21, - ), + id: Id { + value: 21, + span: Span { + start: 426, + end: 429, + }, + }, + span: Span { + start: 411, + end: 429, + }, }, ], ), 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 7d72727..0244523 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 @@ -23,64 +23,134 @@ Schema { comment: Comment( [], ), - name: "f1", + name: Name { + value: "f1", + span: Span { + start: 20, + end: 22, + }, + }, ty: Vec( U32, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 33, + end: 35, + }, + }, + span: Span { + start: 20, + end: 35, + }, }, NamedField { comment: Comment( [], ), - name: "f2", + name: Name { + value: "f2", + span: Span { + start: 41, + end: 43, + }, + }, ty: HashMap( ( U32, String, ), ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 67, + end: 69, + }, + }, + span: Span { + start: 41, + end: 69, + }, }, NamedField { comment: Comment( [], ), - name: "f3", + name: Name { + value: "f3", + span: Span { + start: 75, + end: 77, + }, + }, ty: HashSet( U32, ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 93, + end: 95, + }, + }, + span: Span { + start: 75, + end: 95, + }, }, NamedField { comment: Comment( [], ), - name: "f4", + name: Name { + value: "f4", + span: Span { + start: 101, + end: 103, + }, + }, ty: Option( U32, ), - id: Id( - 4, - ), + id: Id { + value: 4, + span: Span { + start: 117, + end: 119, + }, + }, + span: Span { + start: 101, + end: 119, + }, }, NamedField { comment: Comment( [], ), - name: "f5", + name: Name { + value: "f5", + span: Span { + start: 125, + end: 127, + }, + }, ty: NonZero( U32, ), - id: Id( - 5, - ), + id: Id { + value: 5, + span: Span { + start: 143, + end: 145, + }, + }, + span: Span { + start: 125, + end: 145, + }, }, ], ), 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 93443cf..7a3aaa2 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 @@ -23,7 +23,13 @@ Schema { comment: Comment( [], ), - name: "value", + name: Name { + value: "value", + span: Span { + start: 20, + end: 25, + }, + }, ty: Vec( Option( NonZero( @@ -36,9 +42,17 @@ Schema { ), ), ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 77, + end: 79, + }, + }, + span: Span { + start: 20, + end: 79, + }, }, ], ), 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 7b93932..7575b19 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 @@ -23,165 +23,353 @@ Schema { comment: Comment( [], ), - name: "f01", + name: Name { + value: "f01", + span: Span { + start: 20, + end: 23, + }, + }, ty: NonZero( U8, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 38, + end: 40, + }, + }, + span: Span { + start: 20, + end: 40, + }, }, NamedField { comment: Comment( [], ), - name: "f02", + name: Name { + value: "f02", + span: Span { + start: 46, + end: 49, + }, + }, ty: NonZero( U16, ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 65, + end: 67, + }, + }, + span: Span { + start: 46, + end: 67, + }, }, NamedField { comment: Comment( [], ), - name: "f03", + name: Name { + value: "f03", + span: Span { + start: 73, + end: 76, + }, + }, ty: NonZero( U32, ), - id: Id( - 3, - ), + id: Id { + value: 3, + span: Span { + start: 92, + end: 94, + }, + }, + span: Span { + start: 73, + end: 94, + }, }, NamedField { comment: Comment( [], ), - name: "f04", + name: Name { + value: "f04", + span: Span { + start: 100, + end: 103, + }, + }, ty: NonZero( U64, ), - id: Id( - 4, - ), + id: Id { + value: 4, + span: Span { + start: 119, + end: 121, + }, + }, + span: Span { + start: 100, + end: 121, + }, }, NamedField { comment: Comment( [], ), - name: "f05", + name: Name { + value: "f05", + span: Span { + start: 127, + end: 130, + }, + }, ty: NonZero( U128, ), - id: Id( - 5, - ), + id: Id { + value: 5, + span: Span { + start: 147, + end: 149, + }, + }, + span: Span { + start: 127, + end: 149, + }, }, NamedField { comment: Comment( [], ), - name: "f06", + name: Name { + value: "f06", + span: Span { + start: 155, + end: 158, + }, + }, ty: NonZero( I8, ), - id: Id( - 6, - ), + id: Id { + value: 6, + span: Span { + start: 173, + end: 175, + }, + }, + span: Span { + start: 155, + end: 175, + }, }, NamedField { comment: Comment( [], ), - name: "f07", + name: Name { + value: "f07", + span: Span { + start: 181, + end: 184, + }, + }, ty: NonZero( I16, ), - id: Id( - 7, - ), + id: Id { + value: 7, + span: Span { + start: 200, + end: 202, + }, + }, + span: Span { + start: 181, + end: 202, + }, }, NamedField { comment: Comment( [], ), - name: "f08", + name: Name { + value: "f08", + span: Span { + start: 208, + end: 211, + }, + }, ty: NonZero( I32, ), - id: Id( - 8, - ), + id: Id { + value: 8, + span: Span { + start: 227, + end: 229, + }, + }, + span: Span { + start: 208, + end: 229, + }, }, NamedField { comment: Comment( [], ), - name: "f09", + name: Name { + value: "f09", + span: Span { + start: 235, + end: 238, + }, + }, ty: NonZero( I64, ), - id: Id( - 9, - ), + id: Id { + value: 9, + span: Span { + start: 254, + end: 256, + }, + }, + span: Span { + start: 235, + end: 256, + }, }, NamedField { comment: Comment( [], ), - name: "f10", + name: Name { + value: "f10", + span: Span { + start: 262, + end: 265, + }, + }, ty: NonZero( I128, ), - id: Id( - 10, - ), + id: Id { + value: 10, + span: Span { + start: 282, + end: 285, + }, + }, + span: Span { + start: 262, + end: 285, + }, }, NamedField { comment: Comment( [], ), - name: "f11", + name: Name { + value: "f11", + span: Span { + start: 291, + end: 294, + }, + }, ty: NonZero( String, ), - id: Id( - 11, - ), + id: Id { + value: 11, + span: Span { + start: 313, + end: 316, + }, + }, + span: Span { + start: 291, + end: 316, + }, }, NamedField { comment: Comment( [], ), - name: "f12", + name: Name { + value: "f12", + span: Span { + start: 322, + end: 325, + }, + }, ty: NonZero( Bytes, ), - id: Id( - 12, - ), + id: Id { + value: 12, + span: Span { + start: 343, + end: 346, + }, + }, + span: Span { + start: 322, + end: 346, + }, }, NamedField { comment: Comment( [], ), - name: "f13", + name: Name { + value: "f13", + span: Span { + start: 352, + end: 355, + }, + }, ty: NonZero( Vec( String, ), ), - id: Id( - 13, - ), + id: Id { + value: 13, + span: Span { + start: 379, + end: 382, + }, + }, + span: Span { + start: 352, + end: 382, + }, }, NamedField { comment: Comment( [], ), - name: "f14", + name: Name { + value: "f14", + span: Span { + start: 388, + end: 391, + }, + }, ty: NonZero( HashMap( ( @@ -190,23 +378,45 @@ Schema { ), ), ), - id: Id( - 14, - ), + id: Id { + value: 14, + span: Span { + start: 427, + end: 430, + }, + }, + span: Span { + start: 388, + end: 430, + }, }, NamedField { comment: Comment( [], ), - name: "f15", + name: Name { + value: "f15", + span: Span { + start: 436, + end: 439, + }, + }, ty: NonZero( HashSet( String, ), ), - id: Id( - 15, - ), + id: Id { + value: 15, + span: Span { + start: 468, + end: 471, + }, + }, + span: Span { + start: 436, + end: 471, + }, }, ], ), 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 4a73f6a..a17047f 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 @@ -23,7 +23,13 @@ Schema { comment: Comment( [], ), - name: "basic", + name: Name { + value: "basic", + span: Span { + start: 20, + end: 25, + }, + }, ty: External( ExternalType { path: [], @@ -31,15 +37,29 @@ Schema { generics: [], }, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 35, + end: 37, + }, + }, + span: Span { + start: 20, + end: 37, + }, }, NamedField { comment: Comment( [], ), - name: "with_generics", + name: Name { + value: "with_generics", + span: Span { + start: 43, + end: 56, + }, + }, ty: External( ExternalType { path: [], @@ -50,9 +70,17 @@ Schema { ], }, ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 78, + end: 80, + }, + }, + span: Span { + start: 43, + end: 80, + }, }, ], ), @@ -75,11 +103,25 @@ Schema { comment: Comment( [], ), - name: "Value", + name: Name { + value: "Value", + span: Span { + start: 104, + end: 109, + }, + }, fields: Unit, - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 110, + end: 112, + }, + }, + span: Span { + start: 104, + end: 112, + }, }, ], }, @@ -105,7 +147,13 @@ Schema { comment: Comment( [], ), - name: "key", + name: Name { + value: "key", + span: Span { + start: 145, + end: 148, + }, + }, ty: External( ExternalType { path: [], @@ -113,15 +161,29 @@ Schema { generics: [], }, ), - id: Id( - 1, - ), + id: Id { + value: 1, + span: Span { + start: 152, + end: 154, + }, + }, + span: Span { + start: 145, + end: 154, + }, }, NamedField { comment: Comment( [], ), - name: "value", + name: Name { + value: "value", + span: Span { + start: 160, + end: 165, + }, + }, ty: External( ExternalType { path: [], @@ -129,9 +191,17 @@ Schema { generics: [], }, ), - id: Id( - 2, - ), + id: Id { + value: 2, + span: Span { + start: 169, + end: 171, + }, + }, + span: Span { + start: 160, + end: 171, + }, }, ], ), diff --git a/crates/stef-playground/Cargo.toml b/crates/stef-playground/Cargo.toml index 2bfb7e5..0dbc0f6 100644 --- a/crates/stef-playground/Cargo.toml +++ b/crates/stef-playground/Cargo.toml @@ -14,5 +14,4 @@ publish = false stef = { path = "../stef" } [build-dependencies] -anyhow = "1.0.75" stef-build = { path = "../stef-build" } diff --git a/crates/stef-playground/build.rs b/crates/stef-playground/build.rs index d6c27f9..7118e39 100644 --- a/crates/stef-playground/build.rs +++ b/crates/stef-playground/build.rs @@ -1,4 +1,4 @@ -fn main() -> anyhow::Result<()> { +fn main() -> stef_build::Result<()> { stef_build::compile(&["src/sample.stef"], &["src/"])?; stef_build::compile(&["schemas/*.stef"], &["schemas/"])?; Ok(())