@@ -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
@@ -741,8 +748,10 @@ impl Config {
741
748
}
742
749
}
743
750
751
+
744
752
if let Some ( mut json) = change. client_config_change {
745
753
tracing:: info!( "updating config from JSON: {:#}" , json) ;
754
+
746
755
if !( json. is_null ( ) || json. as_object ( ) . map_or ( false , |it| it. is_empty ( ) ) ) {
747
756
let mut json_errors = vec ! [ ] ;
748
757
let detached_files = get_field :: < Vec < Utf8PathBuf > > (
@@ -758,6 +767,35 @@ impl Config {
758
767
759
768
patch_old_style:: patch_json_for_outdated_configs ( & mut json) ;
760
769
770
+ let snips = self . completion_snippets_custom ( ) . to_owned ( ) ;
771
+
772
+ for ( name, def) in snips. iter ( ) {
773
+ if def. prefix . is_empty ( ) && def. postfix . is_empty ( ) {
774
+ continue ;
775
+ }
776
+ let scope = match def. scope {
777
+ SnippetScopeDef :: Expr => SnippetScope :: Expr ,
778
+ SnippetScopeDef :: Type => SnippetScope :: Type ,
779
+ SnippetScopeDef :: Item => SnippetScope :: Item ,
780
+ } ;
781
+ #[ allow( clippy:: single_match) ]
782
+ match Snippet :: new (
783
+ & def. prefix ,
784
+ & def. postfix ,
785
+ & def. body ,
786
+ def. description . as_ref ( ) . unwrap_or ( name) ,
787
+ & def. requires ,
788
+ scope,
789
+ ) {
790
+ Some ( snippet) => config. snippets . push ( snippet) ,
791
+ None => json_errors. push ( (
792
+ name. to_owned ( ) ,
793
+ <serde_json:: Error as serde:: de:: Error >:: custom ( format ! (
794
+ "snippet {name} is invalid or triggers are missing" ,
795
+ ) ) ,
796
+ ) ) ,
797
+ }
798
+ }
761
799
config. client_config = (
762
800
FullConfigInput :: from_json ( json, & mut json_errors) ,
763
801
ConfigErrors (
@@ -797,8 +835,15 @@ impl Config {
797
835
) ) ;
798
836
should_update = true ;
799
837
}
800
- // FIXME
801
- Err ( _) => ( ) ,
838
+ Err ( e) => {
839
+ config. root_ratoml = Some ( (
840
+ GlobalLocalConfigInput :: from_toml ( toml:: map:: Map :: default ( ) , & mut vec ! [ ] ) ,
841
+ ConfigErrors ( vec ! [ ConfigErrorInner :: ParseError {
842
+ reason: e. message( ) . to_owned( ) ,
843
+ }
844
+ . into( ) ] ) ,
845
+ ) ) ;
846
+ }
802
847
}
803
848
}
804
849
@@ -833,8 +878,18 @@ impl Config {
833
878
) ,
834
879
) ;
835
880
}
836
- // FIXME
837
- Err ( _) => ( ) ,
881
+ Err ( e) => {
882
+ config. root_ratoml = Some ( (
883
+ GlobalLocalConfigInput :: from_toml (
884
+ toml:: map:: Map :: default ( ) ,
885
+ & mut vec ! [ ] ,
886
+ ) ,
887
+ ConfigErrors ( vec ! [ ConfigErrorInner :: ParseError {
888
+ reason: e. message( ) . to_owned( ) ,
889
+ }
890
+ . into( ) ] ) ,
891
+ ) ) ;
892
+ }
838
893
}
839
894
}
840
895
}
@@ -844,45 +899,13 @@ impl Config {
844
899
config. source_root_parent_map = source_root_map;
845
900
}
846
901
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
- }
902
+ if config. check_command ( ) . is_empty ( ) {
903
+ config. other_errors . 0 . push ( Arc :: new ( ConfigErrorInner :: Json {
904
+ config_key : "/check/command" . to_owned ( ) ,
905
+ error : serde_json:: Error :: custom ( "expected a non-empty string" ) ,
906
+ } ) ) ;
877
907
}
878
908
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
909
( config, should_update)
887
910
}
888
911
@@ -900,6 +923,7 @@ impl Config {
900
923
. chain ( config. root_ratoml . as_ref ( ) . into_iter ( ) . flat_map ( |it| it. 1 . 0 . iter ( ) ) )
901
924
. chain ( config. user_config . as_ref ( ) . into_iter ( ) . flat_map ( |it| it. 1 . 0 . iter ( ) ) )
902
925
. chain ( config. ratoml_files . values ( ) . flat_map ( |it| it. 1 . 0 . iter ( ) ) )
926
+ . chain ( config. other_errors . 0 . iter ( ) )
903
927
. cloned ( )
904
928
. collect ( ) ,
905
929
) ;
@@ -1140,9 +1164,10 @@ pub struct ClientCommandsConfig {
1140
1164
pub enum ConfigErrorInner {
1141
1165
Json { config_key : String , error : serde_json:: Error } ,
1142
1166
Toml { config_key : String , error : toml:: de:: Error } ,
1167
+ ParseError { reason : String } ,
1143
1168
}
1144
1169
1145
- #[ derive( Clone , Debug ) ]
1170
+ #[ derive( Clone , Debug , Default ) ]
1146
1171
pub struct ConfigErrors ( Vec < Arc < ConfigErrorInner > > ) ;
1147
1172
1148
1173
impl ConfigErrors {
@@ -1164,6 +1189,7 @@ impl fmt::Display for ConfigErrors {
1164
1189
f ( & ": " ) ?;
1165
1190
f ( e)
1166
1191
}
1192
+ ConfigErrorInner :: ParseError { reason } => f ( reason) ,
1167
1193
} ) ;
1168
1194
write ! ( f, "invalid config value{}:\n {}" , if self . 0 . len( ) == 1 { "" } else { "s" } , errors)
1169
1195
}
@@ -1217,6 +1243,7 @@ impl Config {
1217
1243
root_ratoml : None ,
1218
1244
root_ratoml_path,
1219
1245
detached_files : Default :: default ( ) ,
1246
+ other_errors : Default :: default ( ) ,
1220
1247
}
1221
1248
}
1222
1249
@@ -2597,6 +2624,7 @@ macro_rules! _impl_for_config_data {
2597
2624
}
2598
2625
}
2599
2626
2627
+
2600
2628
& self . default_config. global. $field
2601
2629
}
2602
2630
) *
@@ -3299,7 +3327,7 @@ fn validate_toml_table(
3299
3327
ptr. push_str ( k) ;
3300
3328
3301
3329
match v {
3302
- // This is a table config, any entry in it is therefor valid
3330
+ // This is a table config, any entry in it is therefore valid
3303
3331
toml:: Value :: Table ( _) if verify ( ptr) => ( ) ,
3304
3332
toml:: Value :: Table ( table) => validate_toml_table ( known_ptrs, table, ptr, error_sink) ,
3305
3333
_ if !verify ( ptr) => error_sink
0 commit comments