@@ -9,8 +9,8 @@ use crate::deserializable_derive::struct_field_attrs::StructFieldAttrs;
99use biome_string_case:: Case ;
1010use proc_macro_error2:: * ;
1111use proc_macro2:: { Ident , TokenStream } ;
12- use quote:: quote;
13- use syn:: { Data , GenericParam , Generics , Path , Type } ;
12+ use quote:: { format_ident , quote} ;
13+ use syn:: { Data , GenericParam , Generics , Path } ;
1414
1515pub ( crate ) struct DeriveInput {
1616 pub ident : Ident ,
@@ -75,10 +75,8 @@ impl DeriveInput {
7575 let fields = data
7676 . fields
7777 . into_iter ( )
78- . filter_map ( |field| {
79- field. ident . map ( |ident| ( ident, field. attrs , field. ty ) )
80- } )
81- . filter_map ( |( ident, attrs, ty) | {
78+ . filter_map ( |field| field. ident . map ( |ident| ( ident, field. attrs ) ) )
79+ . filter_map ( |( ident, attrs) | {
8280 let attrs = StructFieldAttrs :: try_from ( & attrs)
8381 . expect ( "Could not parse field attributes" ) ;
8482 if attrs. skip {
@@ -108,7 +106,6 @@ impl DeriveInput {
108106 ident,
109107 key,
110108 required : attrs. required ,
111- ty,
112109 validate : attrs. validate ,
113110 } )
114111 } )
@@ -202,7 +199,6 @@ pub struct DeserializableFieldData {
202199 ident : Ident ,
203200 key : String ,
204201 required : bool ,
205- ty : Type ,
206202 validate : Option < Path > ,
207203}
208204
@@ -351,11 +347,18 @@ fn generate_deserializable_struct(
351347 . fields
352348 . into_iter ( )
353349 . map ( |field_data| {
350+ let is_required = field_data. required ;
354351 let DeserializableFieldData {
355352 ident : field_ident,
356353 key,
357354 ..
358355 } = field_data;
356+ let mark_seen = if is_required {
357+ let seen_ident = format_ident ! ( "seen_{}" , field_ident) ;
358+ quote ! { #seen_ident = true ; }
359+ } else {
360+ quote ! { }
361+ } ;
359362 let deprecation_notice = field_data. deprecated . map ( |deprecated| match deprecated {
360363 DeprecatedField :: Message ( message) => quote ! {
361364 ctx. report( DeserializationDiagnostic :: new_deprecated(
@@ -386,6 +389,7 @@ fn generate_deserializable_struct(
386389
387390 quote ! {
388391 #key => {
392+ #mark_seen
389393 match Deserializable :: deserialize( ctx, & value, & key_text) #validate {
390394 Some ( value) => {
391395 #deprecation_notice
@@ -398,6 +402,13 @@ fn generate_deserializable_struct(
398402 } )
399403 . collect ( ) ;
400404
405+ let seen_declarations: Vec < _ > = required_fields
406+ . iter ( )
407+ . map ( |field_data| {
408+ let seen_ident = format_ident ! ( "seen_{}" , field_data. ident) ;
409+ quote ! { let mut #seen_ident = false ; }
410+ } )
411+ . collect ( ) ;
401412 let validator = if required_fields. is_empty ( ) {
402413 quote ! { }
403414 } else {
@@ -406,14 +417,10 @@ fn generate_deserializable_struct(
406417 . map ( |field_data| & field_data. key )
407418 . collect ( ) ;
408419 let required_fields = required_fields. iter ( ) . map ( |field_data| {
409- let DeserializableFieldData {
410- ident : field_ident,
411- key,
412- ty,
413- ..
414- } = field_data;
420+ let DeserializableFieldData { ident, key, .. } = field_data;
421+ let seen_ident = format_ident ! ( "seen_{}" , ident) ;
415422 quote ! {
416- if result . #field_ident == #ty :: default ( ) {
423+ if !#seen_ident {
417424 ctx. report( DeserializationDiagnostic :: new_missing_key(
418425 #key,
419426 range,
@@ -496,6 +503,7 @@ fn generate_deserializable_struct(
496503 ) -> Option <Self :: Output > {
497504 use biome_deserialize:: { Deserializable , DeserializationDiagnostic , Text } ;
498505 let mut result: Self :: Output = Self :: Output :: default ( ) ;
506+ #( #seen_declarations) *
499507 for ( key, value) in members. flatten( ) {
500508 let Some ( key_text) = Text :: deserialize( ctx, & key, "" ) else {
501509 continue ;
0 commit comments