@@ -679,7 +679,6 @@ pub struct Config {
679
679
/// | Windows | `{FOLDERID_RoamingAppData}` | C:\Users\Alice\AppData\Roaming |
680
680
user_config_path : VfsPath ,
681
681
682
- /// FIXME @alibektas : Change this to sth better.
683
682
/// Config node whose values apply to **every** Rust project.
684
683
user_config : Option < ( GlobalLocalConfigInput , ConfigErrors ) > ,
685
684
@@ -695,6 +694,13 @@ pub struct Config {
695
694
/// Clone of the value that is stored inside a `GlobalState`.
696
695
source_root_parent_map : Arc < FxHashMap < SourceRootId , SourceRootId > > ,
697
696
697
+ /// Use case : It is an error to have an empty value for `check_command`.
698
+ /// Since it is a `global` command at the moment, its final value can only be determined by
699
+ /// traversing through `global` configs and the `client` config. However the non-null value constraint
700
+ /// is config level agnostic, so this requires an independent error storage
701
+ /// FIXME : bad name I know...
702
+ other_errors : ConfigErrors ,
703
+
698
704
detached_files : Vec < AbsPathBuf > ,
699
705
}
700
706
@@ -715,6 +721,7 @@ impl Config {
715
721
/// The return tuple's bool component signals whether the `GlobalState` should call its `update_configuration()` method.
716
722
fn apply_change_with_sink ( & self , change : ConfigChange ) -> ( Config , bool ) {
717
723
let mut config = self . clone ( ) ;
724
+ config. other_errors = ConfigErrors :: default ( ) ;
718
725
719
726
let mut should_update = false ;
720
727
@@ -743,6 +750,7 @@ impl Config {
743
750
744
751
if let Some ( mut json) = change. client_config_change {
745
752
tracing:: info!( "updating config from JSON: {:#}" , json) ;
753
+
746
754
if !( json. is_null ( ) || json. as_object ( ) . map_or ( false , |it| it. is_empty ( ) ) ) {
747
755
let mut json_errors = vec ! [ ] ;
748
756
let detached_files = get_field :: < Vec < Utf8PathBuf > > (
@@ -758,6 +766,35 @@ impl Config {
758
766
759
767
patch_old_style:: patch_json_for_outdated_configs ( & mut json) ;
760
768
769
+ let snips = self . completion_snippets_custom ( ) . to_owned ( ) ;
770
+
771
+ for ( name, def) in snips. iter ( ) {
772
+ if def. prefix . is_empty ( ) && def. postfix . is_empty ( ) {
773
+ continue ;
774
+ }
775
+ let scope = match def. scope {
776
+ SnippetScopeDef :: Expr => SnippetScope :: Expr ,
777
+ SnippetScopeDef :: Type => SnippetScope :: Type ,
778
+ SnippetScopeDef :: Item => SnippetScope :: Item ,
779
+ } ;
780
+ #[ allow( clippy:: single_match) ]
781
+ match Snippet :: new (
782
+ & def. prefix ,
783
+ & def. postfix ,
784
+ & def. body ,
785
+ def. description . as_ref ( ) . unwrap_or ( name) ,
786
+ & def. requires ,
787
+ scope,
788
+ ) {
789
+ Some ( snippet) => config. snippets . push ( snippet) ,
790
+ None => json_errors. push ( (
791
+ name. to_owned ( ) ,
792
+ <serde_json:: Error as serde:: de:: Error >:: custom ( format ! (
793
+ "snippet {name} is invalid or triggers are missing" ,
794
+ ) ) ,
795
+ ) ) ,
796
+ }
797
+ }
761
798
config. client_config = (
762
799
FullConfigInput :: from_json ( json, & mut json_errors) ,
763
800
ConfigErrors (
@@ -797,8 +834,15 @@ impl Config {
797
834
) ) ;
798
835
should_update = true ;
799
836
}
800
- // FIXME
801
- Err ( _) => ( ) ,
837
+ Err ( e) => {
838
+ config. root_ratoml = Some ( (
839
+ GlobalLocalConfigInput :: from_toml ( toml:: map:: Map :: default ( ) , & mut vec ! [ ] ) ,
840
+ ConfigErrors ( vec ! [ ConfigErrorInner :: ParseError {
841
+ reason: e. message( ) . to_owned( ) ,
842
+ }
843
+ . into( ) ] ) ,
844
+ ) ) ;
845
+ }
802
846
}
803
847
}
804
848
@@ -833,8 +877,18 @@ impl Config {
833
877
) ,
834
878
) ;
835
879
}
836
- // FIXME
837
- Err ( _) => ( ) ,
880
+ Err ( e) => {
881
+ config. root_ratoml = Some ( (
882
+ GlobalLocalConfigInput :: from_toml (
883
+ toml:: map:: Map :: default ( ) ,
884
+ & mut vec ! [ ] ,
885
+ ) ,
886
+ ConfigErrors ( vec ! [ ConfigErrorInner :: ParseError {
887
+ reason: e. message( ) . to_owned( ) ,
888
+ }
889
+ . into( ) ] ) ,
890
+ ) ) ;
891
+ }
838
892
}
839
893
}
840
894
}
@@ -844,45 +898,13 @@ impl Config {
844
898
config. source_root_parent_map = source_root_map;
845
899
}
846
900
847
- let snips = self . completion_snippets_custom ( ) . to_owned ( ) ;
848
-
849
- for ( name, def) in snips. iter ( ) {
850
- if def. prefix . is_empty ( ) && def. postfix . is_empty ( ) {
851
- continue ;
852
- }
853
- let scope = match def. scope {
854
- SnippetScopeDef :: Expr => SnippetScope :: Expr ,
855
- SnippetScopeDef :: Type => SnippetScope :: Type ,
856
- SnippetScopeDef :: Item => SnippetScope :: Item ,
857
- } ;
858
- #[ allow( clippy:: single_match) ]
859
- match Snippet :: new (
860
- & def. prefix ,
861
- & def. postfix ,
862
- & def. body ,
863
- def. description . as_ref ( ) . unwrap_or ( name) ,
864
- & def. requires ,
865
- scope,
866
- ) {
867
- Some ( snippet) => config. snippets . push ( snippet) ,
868
- // FIXME
869
- // None => error_sink.0.push(ConfigErrorInner::Json {
870
- // config_key: "".to_owned(),
871
- // error: <serde_json::Error as serde::de::Error>::custom(format!(
872
- // "snippet {name} is invalid or triggers are missing",
873
- // )),
874
- // }),
875
- None => ( ) ,
876
- }
901
+ if config. check_command ( ) . is_empty ( ) {
902
+ config. other_errors . 0 . push ( Arc :: new ( ConfigErrorInner :: Json {
903
+ config_key : "/check/command" . to_owned ( ) ,
904
+ error : serde_json:: Error :: custom ( "expected a non-empty string" ) ,
905
+ } ) ) ;
877
906
}
878
907
879
- // FIXME: bring this back
880
- // if config.check_command().is_empty() {
881
- // error_sink.0.push(ConfigErrorInner::Json {
882
- // config_key: "/check/command".to_owned(),
883
- // error: serde_json::Error::custom("expected a non-empty string"),
884
- // });
885
- // }
886
908
( config, should_update)
887
909
}
888
910
@@ -900,6 +922,7 @@ impl Config {
900
922
. chain ( config. root_ratoml . as_ref ( ) . into_iter ( ) . flat_map ( |it| it. 1 . 0 . iter ( ) ) )
901
923
. chain ( config. user_config . as_ref ( ) . into_iter ( ) . flat_map ( |it| it. 1 . 0 . iter ( ) ) )
902
924
. chain ( config. ratoml_files . values ( ) . flat_map ( |it| it. 1 . 0 . iter ( ) ) )
925
+ . chain ( config. other_errors . 0 . iter ( ) )
903
926
. cloned ( )
904
927
. collect ( ) ,
905
928
) ;
@@ -1140,9 +1163,10 @@ pub struct ClientCommandsConfig {
1140
1163
pub enum ConfigErrorInner {
1141
1164
Json { config_key : String , error : serde_json:: Error } ,
1142
1165
Toml { config_key : String , error : toml:: de:: Error } ,
1166
+ ParseError { reason : String } ,
1143
1167
}
1144
1168
1145
- #[ derive( Clone , Debug ) ]
1169
+ #[ derive( Clone , Debug , Default ) ]
1146
1170
pub struct ConfigErrors ( Vec < Arc < ConfigErrorInner > > ) ;
1147
1171
1148
1172
impl ConfigErrors {
@@ -1164,6 +1188,7 @@ impl fmt::Display for ConfigErrors {
1164
1188
f ( & ": " ) ?;
1165
1189
f ( e)
1166
1190
}
1191
+ ConfigErrorInner :: ParseError { reason } => f ( reason) ,
1167
1192
} ) ;
1168
1193
write ! ( f, "invalid config value{}:\n {}" , if self . 0 . len( ) == 1 { "" } else { "s" } , errors)
1169
1194
}
@@ -1217,6 +1242,7 @@ impl Config {
1217
1242
root_ratoml : None ,
1218
1243
root_ratoml_path,
1219
1244
detached_files : Default :: default ( ) ,
1245
+ other_errors : Default :: default ( ) ,
1220
1246
}
1221
1247
}
1222
1248
@@ -2597,6 +2623,7 @@ macro_rules! _impl_for_config_data {
2597
2623
}
2598
2624
}
2599
2625
2626
+
2600
2627
& self . default_config. global. $field
2601
2628
}
2602
2629
) *
@@ -3299,7 +3326,7 @@ fn validate_toml_table(
3299
3326
ptr. push_str ( k) ;
3300
3327
3301
3328
match v {
3302
- // This is a table config, any entry in it is therefor valid
3329
+ // This is a table config, any entry in it is therefore valid
3303
3330
toml:: Value :: Table ( _) if verify ( ptr) => ( ) ,
3304
3331
toml:: Value :: Table ( table) => validate_toml_table ( known_ptrs, table, ptr, error_sink) ,
3305
3332
_ if !verify ( ptr) => error_sink
0 commit comments