@@ -23,6 +23,7 @@ use crate::project_model::{ProjectModel, RacerFallbackModel, RacerProjectModel};
23
23
use crate :: server:: Output ;
24
24
25
25
use std:: collections:: { HashMap , HashSet } ;
26
+ use std:: convert:: TryFrom ;
26
27
use std:: io;
27
28
use std:: path:: { Path , PathBuf } ;
28
29
use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
@@ -281,12 +282,21 @@ impl InitActionContext {
281
282
fn file_edition ( & self , file : PathBuf ) -> Option < Edition > {
282
283
let files_to_crates = self . file_to_crates . lock ( ) . unwrap ( ) ;
283
284
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 ( ) ;
285
289
286
290
let mut iter = editions. into_iter ( ) ;
287
291
match ( iter. next ( ) , iter. next ( ) ) {
288
292
( 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
+ }
290
300
}
291
301
}
292
302
@@ -425,6 +435,24 @@ impl InitActionContext {
425
435
}
426
436
}
427
437
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
+
428
456
/// Some notifications come with sequence numbers, we check that these are in
429
457
/// order. However, clients might be buggy about sequence numbers so we do cope
430
458
/// with them being wrong.
@@ -662,4 +690,28 @@ mod test {
662
690
assert ! ( !watch. is_relevant_save_doc( & did_save( "file:///c:/some/dir/inner/Cargo.lock" ) ) ) ;
663
691
assert ! ( !watch. is_relevant_save_doc( & did_save( "file:///c:/Cargo.toml" ) ) ) ;
664
692
}
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
+ }
665
717
}
0 commit comments