From 37a304bf2500da61885a2bae2af8907fdfbafbb3 Mon Sep 17 00:00:00 2001 From: ya7010 Date: Wed, 10 Jun 2026 18:38:28 +0900 Subject: [PATCH] refactor: remove proc-macro-error2 dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit メンテナンス状況に左右される外部依存を排除するため、proc-macro-error2 を削除し、 既存の `crate::Error` / `to_compile_errors()` 機構にエラー処理を統一する。 - `SingleIdentPath::new` / `NamedField::new` / `UnnamedField::new` を `Result<_, crate::Error>` 化し、panic ベースの `abort\!` を排除 - `collect_serde_rename_map` を `Result` 化 - `#[proc_macro_error]` 属性と依存宣言を削除 - エラーメッセージと span は従来と同一の表示を維持 Closes #112 Co-Authored-By: Claude Opus 4.8 --- Cargo.toml | 1 - crates/serde_valid_derive/Cargo.toml | 1 - .../src/attribute/common/message_format.rs | 5 +++- .../field_validate/generic/custom.rs | 4 ++- .../src/attribute/field_validate/meta.rs | 5 +++- .../src/attribute/struct_validate/meta.rs | 5 +++- .../src/attribute/variant_validate/meta.rs | 5 +++- .../src/derive/enum_derive.rs | 2 +- .../src/derive/named_struct_derive.rs | 4 +-- .../src/derive/unnamed_struct_derive.rs | 2 +- crates/serde_valid_derive/src/error.rs | 21 +++++++++++++++ crates/serde_valid_derive/src/lib.rs | 2 -- crates/serde_valid_derive/src/serde/rename.rs | 6 ++--- .../src/types/field/named.rs | 16 +++++------- .../src/types/field/unnamed.rs | 9 +++---- .../src/types/single_ident_path.rs | 26 +++---------------- 16 files changed, 61 insertions(+), 53 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 00d19c6e..231bf29a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ keywords = ["json_schema", "serde", "validation"] [workspace.dependencies] itertools = "^0.14.0" paste = "^1.0" -proc-macro-error2 = { version = "^2.0", default-features = false } proc-macro2 = "^1.0" quote = "^1.0" regex = "^1.12" diff --git a/crates/serde_valid_derive/Cargo.toml b/crates/serde_valid_derive/Cargo.toml index 10d289c7..61e13392 100644 --- a/crates/serde_valid_derive/Cargo.toml +++ b/crates/serde_valid_derive/Cargo.toml @@ -17,7 +17,6 @@ proc-macro = true [dependencies] itertools.workspace = true paste.workspace = true -proc-macro-error2 = { workspace = true } proc-macro2 = { workspace = true } quote = { workspace = true } strsim = { workspace = true } diff --git a/crates/serde_valid_derive/src/attribute/common/message_format.rs b/crates/serde_valid_derive/src/attribute/common/message_format.rs index 6a0ddd96..964e6515 100644 --- a/crates/serde_valid_derive/src/attribute/common/message_format.rs +++ b/crates/serde_valid_derive/src/attribute/common/message_format.rs @@ -23,6 +23,7 @@ pub fn extract_custom_message_format( syn::Meta::NameValue(name_value) => &name_value.path, }; let custom_message_name = SingleIdentPath::new(custom_message_path) + .map_err(|error| vec![error])? .ident() .to_string(); @@ -71,7 +72,9 @@ fn extract_custom_message_format_from_meta_list( #[cfg(feature = "fluent")] message_type @ (MetaListCustomMessage::I18n | MetaListCustomMessage::Fluent) => { let path = &meta_list.path; - let path_ident = SingleIdentPath::new(path).ident(); + let path_ident = SingleIdentPath::new(path) + .map_err(|error| vec![error])? + .ident(); let message_fn_define = meta_list .parse_args_with(CommaSeparatedNestedMetas::parse_terminated) .map_err(|error| { diff --git a/crates/serde_valid_derive/src/attribute/field_validate/generic/custom.rs b/crates/serde_valid_derive/src/attribute/field_validate/generic/custom.rs index 526ef665..386ed00e 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/generic/custom.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/generic/custom.rs @@ -12,7 +12,9 @@ pub fn extract_generic_custom_validator_from_meta_list( rename_map: &RenameMap, ) -> Result { let path = &meta_list.path; - let path_ident = SingleIdentPath::new(path).ident(); + let path_ident = SingleIdentPath::new(path) + .map_err(|error| vec![error])? + .ident(); let field_name = field.name(); let field_key = field.key(); let nested = meta_list diff --git a/crates/serde_valid_derive/src/attribute/field_validate/meta.rs b/crates/serde_valid_derive/src/attribute/field_validate/meta.rs index d2c79dfa..70b59d8e 100644 --- a/crates/serde_valid_derive/src/attribute/field_validate/meta.rs +++ b/crates/serde_valid_derive/src/attribute/field_validate/meta.rs @@ -91,7 +91,10 @@ fn inner_extract_field_validator( syn::Meta::NameValue(name_value) => &name_value.path, }; - let validation_name = SingleIdentPath::new(validation_path).ident().to_string(); + let validation_name = SingleIdentPath::new(validation_path) + .map_err(|error| vec![error])? + .ident() + .to_string(); let validator = match ( MetaPathFieldValidation::from_str(&validation_name), diff --git a/crates/serde_valid_derive/src/attribute/struct_validate/meta.rs b/crates/serde_valid_derive/src/attribute/struct_validate/meta.rs index 3a301f90..91e9fdda 100644 --- a/crates/serde_valid_derive/src/attribute/struct_validate/meta.rs +++ b/crates/serde_valid_derive/src/attribute/struct_validate/meta.rs @@ -87,7 +87,10 @@ fn inner_extract_struct_validator( syn::Meta::NameValue(name_value) => &name_value.path, }; - let validation_name = SingleIdentPath::new(validation_path).ident().to_string(); + let validation_name = SingleIdentPath::new(validation_path) + .map_err(|error| vec![error])? + .ident() + .to_string(); let validator = match ( MetaPathStructValidation::from_str(&validation_name), MetaListStructValidation::from_str(&validation_name), diff --git a/crates/serde_valid_derive/src/attribute/variant_validate/meta.rs b/crates/serde_valid_derive/src/attribute/variant_validate/meta.rs index 10618a0e..b39a7492 100644 --- a/crates/serde_valid_derive/src/attribute/variant_validate/meta.rs +++ b/crates/serde_valid_derive/src/attribute/variant_validate/meta.rs @@ -87,7 +87,10 @@ fn inner_extract_variant_validator( syn::Meta::NameValue(name_value) => &name_value.path, }; - let validation_name = SingleIdentPath::new(validation_path).ident().to_string(); + let validation_name = SingleIdentPath::new(validation_path) + .map_err(|error| vec![error])? + .ident() + .to_string(); let validator = match ( MetaPathStructValidation::from_str(&validation_name), MetaListStructValidation::from_str(&validation_name), diff --git a/crates/serde_valid_derive/src/derive/enum_derive.rs b/crates/serde_valid_derive/src/derive/enum_derive.rs index a6215e60..bb6dac2d 100644 --- a/crates/serde_valid_derive/src/derive/enum_derive.rs +++ b/crates/serde_valid_derive/src/derive/enum_derive.rs @@ -95,7 +95,7 @@ fn expand_enum_variant_named_fields_validation( let variant_ident = &variant.ident; let mut fields_idents = CommaSeparatedTokenStreams::new(); - let rename_map = collect_serde_rename_map(named_fields); + let rename_map = collect_serde_rename_map(named_fields)?; let enum_validates = match collect_variant_custom_from_variant(&input.attrs) { Ok(validations) => { diff --git a/crates/serde_valid_derive/src/derive/named_struct_derive.rs b/crates/serde_valid_derive/src/derive/named_struct_derive.rs index ab6a6bd0..5903a97c 100644 --- a/crates/serde_valid_derive/src/derive/named_struct_derive.rs +++ b/crates/serde_valid_derive/src/derive/named_struct_derive.rs @@ -14,7 +14,7 @@ pub fn expand_named_struct_derive( ) -> Result { let ident = &input.ident; let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl(); - let rename_map = collect_serde_rename_map(fields); + let rename_map = collect_serde_rename_map(fields)?; let mut warnings = vec![]; let mut errors = vec![]; @@ -110,7 +110,7 @@ fn collect_named_field_validators<'a>( ) -> Result>, crate::Errors> { let mut errors = vec![]; - let named_field = NamedField::new(field); + let named_field = NamedField::new(field).map_err(|error| vec![error])?; let validators = named_field .attrs() .iter() diff --git a/crates/serde_valid_derive/src/derive/unnamed_struct_derive.rs b/crates/serde_valid_derive/src/derive/unnamed_struct_derive.rs index 92278873..12b15aa7 100644 --- a/crates/serde_valid_derive/src/derive/unnamed_struct_derive.rs +++ b/crates/serde_valid_derive/src/derive/unnamed_struct_derive.rs @@ -111,7 +111,7 @@ fn collect_unnamed_field_validators( ) -> Result>, crate::Errors> { let mut errors = vec![]; - let unnamed_field = UnnamedField::new(index, field); + let unnamed_field = UnnamedField::new(index, field).map_err(|error| vec![error])?; let validators = unnamed_field .attrs() diff --git a/crates/serde_valid_derive/src/error.rs b/crates/serde_valid_derive/src/error.rs index 71777dbc..92e8001b 100644 --- a/crates/serde_valid_derive/src/error.rs +++ b/crates/serde_valid_derive/src/error.rs @@ -174,6 +174,27 @@ impl Error { Self::new(input.span(), "#[derive(Validate)] does not support Union.") } + pub fn path_must_be_single_ident(path: &syn::Path) -> Self { + let path_str = path + .segments + .iter() + .map(|segment| segment.ident.to_string()) + .collect::>() + .join("::"); + Self::new( + path.span(), + format!("Path(='{path_str}') must be single ident path."), + ) + } + + pub fn named_fields_struct_required(field: &syn::Field) -> Self { + Self::new(field.span(), "struct must be named fields struct.") + } + + pub fn unnamed_fields_struct_required(field: &syn::Field) -> Self { + Self::new(field.span(), "struct must be unnamed fields struct.") + } + pub fn validate_meta_name_value_not_supported(name_value: &syn::MetaNameValue) -> Self { Self::new(name_value.span(), "#[validate = ???] not supported.") } diff --git a/crates/serde_valid_derive/src/lib.rs b/crates/serde_valid_derive/src/lib.rs index df028e48..0752e00f 100644 --- a/crates/serde_valid_derive/src/lib.rs +++ b/crates/serde_valid_derive/src/lib.rs @@ -10,11 +10,9 @@ use derive::expand_derive; use error::to_compile_errors; use error::{Error, Errors}; use proc_macro::TokenStream; -use proc_macro_error2::proc_macro_error; use syn::{parse_macro_input, DeriveInput}; #[proc_macro_derive(Validate, attributes(rule, validate, serde_valid))] -#[proc_macro_error] pub fn derive_validate(tokens: TokenStream) -> TokenStream { let input = parse_macro_input!(tokens as DeriveInput); diff --git a/crates/serde_valid_derive/src/serde/rename.rs b/crates/serde_valid_derive/src/serde/rename.rs index 429a58aa..3d4d2c6e 100644 --- a/crates/serde_valid_derive/src/serde/rename.rs +++ b/crates/serde_valid_derive/src/serde/rename.rs @@ -6,10 +6,10 @@ use quote::{quote, ToTokens}; pub type RenameMap = HashMap; -pub fn collect_serde_rename_map(fields: &syn::FieldsNamed) -> RenameMap { +pub fn collect_serde_rename_map(fields: &syn::FieldsNamed) -> Result { let mut renames = RenameMap::new(); for field in fields.named.iter() { - let named_field = NamedField::new(field); + let named_field = NamedField::new(field).map_err(|error| vec![error])?; for attribute in named_field.attrs() { if attribute.path().is_ident("serde") { if let Some(rename) = find_rename_from_serde_attributes(attribute) { @@ -21,7 +21,7 @@ pub fn collect_serde_rename_map(fields: &syn::FieldsNamed) -> RenameMap { } } } - renames + Ok(renames) } fn find_rename_from_serde_attributes(attribute: &syn::Attribute) -> Option { diff --git a/crates/serde_valid_derive/src/types/field/named.rs b/crates/serde_valid_derive/src/types/field/named.rs index a7e47c0a..d5f8c686 100644 --- a/crates/serde_valid_derive/src/types/field/named.rs +++ b/crates/serde_valid_derive/src/types/field/named.rs @@ -1,8 +1,6 @@ use super::Field; -use proc_macro_error2::abort; use quote::quote; use std::borrow::Cow; -use syn::spanned::Spanned; #[derive(Debug, Clone)] pub struct NamedField<'a> { @@ -11,14 +9,14 @@ pub struct NamedField<'a> { } impl<'a> NamedField<'a> { - pub fn new(field: &'a syn::Field) -> Self { - if field.ident.is_none() { - abort!(field.span(), "struct must be named fields struct.") - } - Self { - name: field.ident.as_ref().unwrap().to_string(), + pub fn new(field: &'a syn::Field) -> Result { + let Some(ident) = field.ident.as_ref() else { + return Err(crate::Error::named_fields_struct_required(field)); + }; + Ok(Self { + name: ident.to_string(), field: Cow::Borrowed(field), - } + }) } } diff --git a/crates/serde_valid_derive/src/types/field/unnamed.rs b/crates/serde_valid_derive/src/types/field/unnamed.rs index 53d68bb3..42965271 100644 --- a/crates/serde_valid_derive/src/types/field/unnamed.rs +++ b/crates/serde_valid_derive/src/types/field/unnamed.rs @@ -1,5 +1,4 @@ use super::Field; -use proc_macro_error2::abort; use quote::quote; use std::borrow::Cow; use std::convert::AsRef; @@ -14,16 +13,16 @@ pub struct UnnamedField<'a> { } impl<'a> UnnamedField<'a> { - pub fn new(index: usize, field: &'a syn::Field) -> Self { + pub fn new(index: usize, field: &'a syn::Field) -> Result { if field.ident.is_some() { - abort!(field.span(), "struct must be unnamed fields struct.") + return Err(crate::Error::unnamed_fields_struct_required(field)); } - Self { + Ok(Self { name: index.to_string(), index, ident: syn::Ident::new(&format!("__{}", index), field.span()), field: Cow::Borrowed(field), - } + }) } } diff --git a/crates/serde_valid_derive/src/types/single_ident_path.rs b/crates/serde_valid_derive/src/types/single_ident_path.rs index 91554d9a..a8c21780 100644 --- a/crates/serde_valid_derive/src/types/single_ident_path.rs +++ b/crates/serde_valid_derive/src/types/single_ident_path.rs @@ -1,34 +1,14 @@ -use proc_macro_error2::abort; -use syn::spanned::Spanned; - pub struct SingleIdentPath<'a>(&'a syn::Path); impl<'a> SingleIdentPath<'a> { - pub fn new(path: &'a syn::Path) -> Self { + pub fn new(path: &'a syn::Path) -> Result { if path.get_ident().is_none() { - abort!( - path.span(), - "Path(='{}') must be single ident path.", - path_to_string(path) - ) + return Err(crate::Error::path_must_be_single_ident(path)); } - Self(path) + Ok(Self(path)) } pub fn ident(&self) -> &'a syn::Ident { self.0.get_ident().unwrap() } } - -fn path_to_string(path: &syn::Path) -> String { - path.segments - .pairs() - .map(|pair| match pair { - syn::punctuated::Pair::Punctuated(seg, ..) => { - format!("{}::", seg.ident) - } - syn::punctuated::Pair::End(seg) => seg.ident.to_string(), - }) - .collect::>() - .join("") -}