@@ -19,18 +19,27 @@ use crate::lint::rules::indentation::{MAX_LENGTH_DEFAULT,
1919 setup_indentation_size
2020 } ;
2121
22- pub fn parse_lint_cfg ( path : PathBuf ) -> Result < LintCfg , String > {
22+ pub fn parse_lint_cfg ( path : PathBuf ) -> Result < ( LintCfg , Vec < String > ) , String > {
2323 debug ! ( "Reading Lint configuration from {:?}" , path) ;
24- let file_content = fs:: read_to_string ( path) . map_err (
25- |e|e. to_string ( ) ) ?;
24+ let file_content = fs:: read_to_string ( path) . map_err ( |e| e. to_string ( ) ) ?;
2625 trace ! ( "Content is {:?}" , file_content) ;
27- serde_json:: from_str ( & file_content)
28- . map_err ( |e|e. to_string ( ) )
26+
27+ let val: serde_json:: Value = serde_json:: from_str ( & file_content)
28+ . map_err ( |e| e. to_string ( ) ) ?;
29+
30+ let mut unknowns = Vec :: new ( ) ;
31+ let cfg = LintCfg :: try_deserialize ( & val, & mut unknowns) ?;
32+
33+ Ok ( ( cfg, unknowns) )
2934}
3035
3136pub fn maybe_parse_lint_cfg ( path : PathBuf ) -> Option < LintCfg > {
3237 match parse_lint_cfg ( path) {
33- Ok ( mut cfg) => {
38+ Ok ( ( mut cfg, unknowns) ) => {
39+ if !unknowns. is_empty ( ) {
40+ // Log the unknown fields as a comma-separated list
41+ error ! ( "Unknown lint config fields: {}" , unknowns. join( ", " ) ) ;
42+ }
3443 setup_indentation_size ( & mut cfg) ;
3544 Some ( cfg)
3645 } ,
@@ -43,7 +52,6 @@ pub fn maybe_parse_lint_cfg(path: PathBuf) -> Option<LintCfg> {
4352
4453#[ derive( Clone , Debug , Serialize , Deserialize , PartialEq ) ]
4554#[ serde( default ) ]
46- #[ serde( deny_unknown_fields) ]
4755pub struct LintCfg {
4856 #[ serde( default ) ]
4957 pub sp_brace : Option < SpBraceOptions > ,
@@ -77,6 +85,21 @@ pub struct LintCfg {
7785 pub annotate_lints : bool ,
7886}
7987
88+ impl LintCfg {
89+ pub fn try_deserialize (
90+ val : & serde_json:: Value ,
91+ unknowns : & mut Vec < String > ,
92+ ) -> Result < LintCfg , String > {
93+ // Use serde_ignored to automatically track unknown fields
94+ match serde_ignored:: deserialize ( val, |json_path| {
95+ unknowns. push ( json_path. to_string ( ) ) ;
96+ } ) {
97+ Ok ( cfg) => Ok ( cfg) ,
98+ Err ( e) => Err ( e. to_string ( ) ) ,
99+ }
100+ }
101+ }
102+
80103fn get_true ( ) -> bool {
81104 true
82105}
@@ -263,8 +286,47 @@ pub mod tests {
263286 let example_path = format ! ( "{}{}" ,
264287 env!( "CARGO_MANIFEST_DIR" ) ,
265288 EXAMPLE_CFG ) ;
266- let example_cfg = parse_lint_cfg ( example_path. into ( ) ) . unwrap ( ) ;
289+ let ( example_cfg, unknowns ) = parse_lint_cfg ( example_path. into ( ) ) . unwrap ( ) ;
267290 assert_eq ! ( example_cfg, LintCfg :: default ( ) ) ;
291+ // Assert that there are no unknown fields in the example config:
292+ assert ! ( unknowns. is_empty( ) , "Example config should not have unknown fields: {:?}" , unknowns) ;
293+ }
294+
295+ #[ test]
296+ fn test_unknown_fields_detection ( ) {
297+ use crate :: lint:: LintCfg ;
298+
299+ // JSON with unknown fields
300+ let json_with_unknowns = r#"{
301+ "sp_brace": {},
302+ "unknown_field_1": true,
303+ "indent_size": {"indentation_spaces": 4},
304+ "another_unknown": "value"
305+ }"# ;
306+
307+ let val: serde_json:: Value = serde_json:: from_str ( json_with_unknowns) . unwrap ( ) ;
308+ let mut unknowns = Vec :: new ( ) ;
309+ let result = LintCfg :: try_deserialize ( & val, & mut unknowns) ;
310+
311+ assert ! ( result. is_ok( ) ) ;
312+ let cfg = result. unwrap ( ) ;
313+
314+ // Assert that unknown fields were detected
315+ assert_eq ! ( unknowns. len( ) , 2 ) ;
316+ assert ! ( unknowns. contains( & "unknown_field_1" . to_string( ) ) ) ;
317+ assert ! ( unknowns. contains( & "another_unknown" . to_string( ) ) ) ;
318+
319+ // Assert the final LintCfg matches expected json (the known fields)
320+ let expected_json = r#"{
321+ "sp_brace": {},
322+ "indent_size": {"indentation_spaces": 4}
323+ }"# ;
324+ let expected_val: serde_json:: Value = serde_json:: from_str ( expected_json) . unwrap ( ) ;
325+ let mut expected_unknowns = Vec :: new ( ) ;
326+ let expected_cfg = LintCfg :: try_deserialize ( & expected_val, & mut expected_unknowns) . unwrap ( ) ;
327+
328+ assert_eq ! ( cfg, expected_cfg) ;
329+ assert ! ( expected_unknowns. is_empty( ) ) ; // No unknown fields in the expected config
268330 }
269331
270332 #[ test]
0 commit comments