@@ -23,6 +23,7 @@ use crate::project_model::{ProjectModel, RacerFallbackModel, RacerProjectModel};
2323use crate :: server:: Output ;
2424
2525use std:: collections:: { HashMap , HashSet } ;
26+ use std:: convert:: TryFrom ;
2627use std:: io;
2728use std:: path:: { Path , PathBuf } ;
2829use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
@@ -281,12 +282,21 @@ impl InitActionContext {
281282 fn file_edition ( & self , file : PathBuf ) -> Option < Edition > {
282283 let files_to_crates = self . file_to_crates . lock ( ) . unwrap ( ) ;
283284
284- let editions: HashSet < _ > = files_to_crates. get ( & file) ?. iter ( ) . map ( |c| c. edition ) . collect ( ) ;
285+ let editions: HashSet < _ > = files_to_crates
286+ . get ( & file)
287+ . map ( |crates| crates. iter ( ) . map ( |c| c. edition ) . collect ( ) )
288+ . unwrap_or_default ( ) ;
285289
286290 let mut iter = editions. into_iter ( ) ;
287291 match ( iter. next ( ) , iter. next ( ) ) {
288292 ( ret @ Some ( _) , None ) => ret,
289- _ => None ,
293+ ( Some ( _) , Some ( _) ) => None ,
294+ _ => {
295+ // fall back on checking the root manifest for package edition
296+ let manifest_path =
297+ cargo:: util:: important_paths:: find_root_manifest_for_wd ( & file) . ok ( ) ?;
298+ edition_from_manifest ( manifest_path)
299+ }
290300 }
291301 }
292302
@@ -425,6 +435,24 @@ impl InitActionContext {
425435 }
426436}
427437
438+ /// Read package edition from the Cargo manifest
439+ fn edition_from_manifest < P : AsRef < Path > > ( manifest_path : P ) -> Option < Edition > {
440+ #[ derive( Debug , serde:: Deserialize ) ]
441+ struct Manifest {
442+ package : Package ,
443+ }
444+ #[ derive( Debug , serde:: Deserialize ) ]
445+ struct Package {
446+ edition : Option < String > ,
447+ }
448+
449+ let manifest: Manifest = toml:: from_str ( & std:: fs:: read_to_string ( manifest_path) . ok ( ) ?) . ok ( ) ?;
450+ match manifest. package . edition {
451+ Some ( edition) => Edition :: try_from ( edition. as_str ( ) ) . ok ( ) ,
452+ None => Some ( Edition :: default ( ) ) ,
453+ }
454+ }
455+
428456/// Some notifications come with sequence numbers, we check that these are in
429457/// order. However, clients might be buggy about sequence numbers so we do cope
430458/// with them being wrong.
@@ -662,4 +690,28 @@ mod test {
662690 assert ! ( !watch. is_relevant_save_doc( & did_save( "file:///c:/some/dir/inner/Cargo.lock" ) ) ) ;
663691 assert ! ( !watch. is_relevant_save_doc( & did_save( "file:///c:/Cargo.toml" ) ) ) ;
664692 }
693+
694+ #[ test]
695+ fn explicit_edition_from_manifest ( ) -> Result < ( ) , std:: io:: Error > {
696+ use std:: { fs:: File , io:: Write } ;
697+
698+ let dir = tempfile:: tempdir ( ) ?;
699+
700+ let manifest_path = {
701+ let path = dir. path ( ) . join ( "Cargo.toml" ) ;
702+ let mut m = File :: create ( & path) ?;
703+ writeln ! (
704+ m,
705+ "[package]\n \
706+ name = \" foo\" \n \
707+ version = \" 1.0.0\" \n \
708+ edition = \" 2018\" "
709+ ) ?;
710+ path
711+ } ;
712+
713+ assert_eq ! ( edition_from_manifest( manifest_path) , Some ( Edition :: Edition2018 ) ) ;
714+
715+ Ok ( ( ) )
716+ }
665717}
0 commit comments