@@ -6,7 +6,9 @@ use serde::Deserialize;
66use serde_json:: { Map , Value } ;
77use thiserror:: Error ;
88
9- use ruff_linter:: { line_width:: LineLength , RuleSelector } ;
9+ use ruff_linter:: line_width:: LineLength ;
10+ use ruff_linter:: rule_selector:: ParseError ;
11+ use ruff_linter:: RuleSelector ;
1012use ruff_workspace:: options:: Options ;
1113
1214/// Maps a workspace URI to its associated client settings. Used during server initialization.
@@ -319,7 +321,9 @@ impl ResolvedClientSettings {
319321 }
320322
321323 fn new_impl ( all_settings : & [ & ClientSettings ] ) -> Self {
322- Self {
324+ let mut contains_invalid_settings = false ;
325+
326+ let settings = Self {
323327 fix_all : Self :: resolve_or ( all_settings, |settings| settings. fix_all , true ) ,
324328 organize_imports : Self :: resolve_or (
325329 all_settings,
@@ -366,6 +370,7 @@ impl ResolvedClientSettings {
366370 match ResolvedConfiguration :: try_from ( configuration) {
367371 Ok ( configuration) => Some ( configuration) ,
368372 Err ( err) => {
373+ contains_invalid_settings = true ;
369374 tracing:: error!( "Failed to resolve configuration: {err}" ) ;
370375 None
371376 }
@@ -379,34 +384,25 @@ impl ResolvedClientSettings {
379384 settings. format . as_ref ( ) ?. preview
380385 } ) ,
381386 select : Self :: resolve_optional ( all_settings, |settings| {
382- settings
383- . lint
384- . as_ref ( ) ?
385- . select
386- . as_ref ( ) ?
387- . iter ( )
388- . map ( |rule| RuleSelector :: from_str ( rule) . ok ( ) )
389- . collect ( )
387+ Self :: resolve_rules (
388+ settings. lint . as_ref ( ) ?. select . as_ref ( ) ?,
389+ RuleSelectorKey :: Select ,
390+ & mut contains_invalid_settings,
391+ )
390392 } ) ,
391393 extend_select : Self :: resolve_optional ( all_settings, |settings| {
392- settings
393- . lint
394- . as_ref ( ) ?
395- . extend_select
396- . as_ref ( ) ?
397- . iter ( )
398- . map ( |rule| RuleSelector :: from_str ( rule) . ok ( ) )
399- . collect ( )
394+ Self :: resolve_rules (
395+ settings. lint . as_ref ( ) ?. extend_select . as_ref ( ) ?,
396+ RuleSelectorKey :: ExtendSelect ,
397+ & mut contains_invalid_settings,
398+ )
400399 } ) ,
401400 ignore : Self :: resolve_optional ( all_settings, |settings| {
402- settings
403- . lint
404- . as_ref ( ) ?
405- . ignore
406- . as_ref ( ) ?
407- . iter ( )
408- . map ( |rule| RuleSelector :: from_str ( rule) . ok ( ) )
409- . collect ( )
401+ Self :: resolve_rules (
402+ settings. lint . as_ref ( ) ?. ignore . as_ref ( ) ?,
403+ RuleSelectorKey :: Ignore ,
404+ & mut contains_invalid_settings,
405+ )
410406 } ) ,
411407 exclude : Self :: resolve_optional ( all_settings, |settings| settings. exclude . clone ( ) ) ,
412408 line_length : Self :: resolve_optional ( all_settings, |settings| settings. line_length ) ,
@@ -416,6 +412,37 @@ impl ResolvedClientSettings {
416412 ConfigurationPreference :: EditorFirst ,
417413 ) ,
418414 } ,
415+ } ;
416+
417+ if contains_invalid_settings {
418+ show_err_msg ! (
419+ "Ruff received invalid client settings. Refer to the logs for more information."
420+ ) ;
421+ }
422+
423+ settings
424+ }
425+
426+ fn resolve_rules (
427+ rules : & [ String ] ,
428+ key : RuleSelectorKey ,
429+ contains_invalid_settings : & mut bool ,
430+ ) -> Option < Vec < RuleSelector > > {
431+ let ( mut known, mut unknown) = ( vec ! [ ] , vec ! [ ] ) ;
432+ for rule in rules {
433+ match RuleSelector :: from_str ( rule) {
434+ Ok ( selector) => known. push ( selector) ,
435+ Err ( ParseError :: Unknown ( _) ) => unknown. push ( rule) ,
436+ }
437+ }
438+ if !unknown. is_empty ( ) {
439+ * contains_invalid_settings = true ;
440+ tracing:: error!( "Unknown rule selectors found in {key}: {unknown:?}" ) ;
441+ }
442+ if known. is_empty ( ) {
443+ None
444+ } else {
445+ Some ( known)
419446 }
420447 }
421448
@@ -425,7 +452,7 @@ impl ResolvedClientSettings {
425452 /// Use [`ResolvedClientSettings::resolve_or`] for settings that should have default values.
426453 fn resolve_optional < T > (
427454 all_settings : & [ & ClientSettings ] ,
428- get : impl Fn ( & ClientSettings ) -> Option < T > ,
455+ get : impl FnMut ( & ClientSettings ) -> Option < T > ,
429456 ) -> Option < T > {
430457 all_settings. iter ( ) . map ( Deref :: deref) . find_map ( get)
431458 }
@@ -444,6 +471,23 @@ impl ResolvedClientSettings {
444471 }
445472}
446473
474+ #[ derive( Copy , Clone ) ]
475+ enum RuleSelectorKey {
476+ Select ,
477+ ExtendSelect ,
478+ Ignore ,
479+ }
480+
481+ impl std:: fmt:: Display for RuleSelectorKey {
482+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
483+ match self {
484+ RuleSelectorKey :: Select => f. write_str ( "lint.select" ) ,
485+ RuleSelectorKey :: ExtendSelect => f. write_str ( "lint.extendSelect" ) ,
486+ RuleSelectorKey :: Ignore => f. write_str ( "lint.ignore" ) ,
487+ }
488+ }
489+ }
490+
447491impl ResolvedClientSettings {
448492 pub ( crate ) fn fix_all ( & self ) -> bool {
449493 self . fix_all
0 commit comments