@@ -267,32 +267,27 @@ impl SourceRootConfig {
267
267
}
268
268
269
269
/// Maps local source roots to their parent source roots by bytewise comparing of root paths .
270
- /// If a source root doesn't have a parent then its parent is declared as None .
271
- pub fn source_root_parent_map ( & self ) -> FxHashMap < SourceRootId , Option < SourceRootId > > {
270
+ /// If a `SourceRoot` doesn't have a parent and is local then it is not contained in this mapping but it can be asserted that it is a root `SourceRoot` .
271
+ pub fn source_root_parent_map ( & self ) -> FxHashMap < SourceRootId , SourceRootId > {
272
272
let roots = self . fsc . roots ( ) ;
273
- let mut map = FxHashMap :: < SourceRootId , Option < SourceRootId > > :: default ( ) ;
274
-
275
- ' outer: for ( idx, ( root, root_id) ) in roots. iter ( ) . enumerate ( ) {
276
- if !self . local_filesets . contains ( root_id) {
277
- continue ;
278
- }
279
-
280
- for ( _, ( root2, root2_id) ) in roots. iter ( ) . enumerate ( ) . take ( idx) . rev ( ) {
281
- if root2. iter ( ) . enumerate ( ) . all ( |( i, c) | & root[ i] == c) {
282
- // We are interested in parents if they are also local source roots.
283
- // So instead of a non-local parent we may take a local ancestor as a parent to a node.
284
- if self . local_filesets . contains ( root2_id) {
285
- map. insert (
286
- SourceRootId ( root_id. to_owned ( ) as u32 ) ,
287
- Some ( SourceRootId ( root2_id. to_owned ( ) as u32 ) ) ,
288
- ) ;
289
- continue ' outer;
273
+ let mut map = FxHashMap :: < SourceRootId , SourceRootId > :: default ( ) ;
274
+ roots
275
+ . iter ( )
276
+ . enumerate ( )
277
+ . filter ( |( _, ( _, id) ) | self . local_filesets . contains ( id) )
278
+ . filter_map ( |( idx, ( root, root_id) ) | {
279
+ // We are interested in parents if they are also local source roots.
280
+ // So instead of a non-local parent we may take a local ancestor as a parent to a node.
281
+ roots. iter ( ) . take ( idx) . find_map ( |( root2, root2_id) | {
282
+ if self . local_filesets . contains ( root2_id) && root. starts_with ( root2) {
283
+ return Some ( ( root_id, root2_id) ) ;
290
284
}
291
- }
292
- }
293
- map. insert ( SourceRootId ( idx as u32 ) , None ) ;
294
- }
295
-
285
+ None
286
+ } )
287
+ } )
288
+ . for_each ( |( child, parent) | {
289
+ map. insert ( SourceRootId ( * child as u32 ) , SourceRootId ( * parent as u32 ) ) ;
290
+ } ) ;
296
291
map
297
292
}
298
293
}
@@ -427,6 +422,11 @@ mod tests {
427
422
428
423
use super :: * ;
429
424
425
+ use ide_db:: base_db:: SourceRootId ;
426
+ use vfs:: { file_set:: FileSetConfigBuilder , VfsPath } ;
427
+
428
+ use crate :: SourceRootConfig ;
429
+
430
430
#[ test]
431
431
fn test_loading_rust_analyzer ( ) {
432
432
let path = Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) ) . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ;
@@ -444,202 +444,123 @@ mod tests {
444
444
assert ! ( n_crates > 20 ) ;
445
445
}
446
446
447
- mod source_root_parent {
448
- use ide_db:: base_db:: SourceRootId ;
449
- use vfs:: { file_set:: FileSetConfigBuilder , VfsPath } ;
450
-
451
- use crate :: SourceRootConfig ;
452
-
453
- macro_rules! virp {
454
- ( $s : literal) => {
455
- VfsPath :: new_virtual_path( format!( $s) )
456
- } ;
457
- }
458
-
459
- #[ test]
460
- fn test1 ( ) {
461
- let mut builder = FileSetConfigBuilder :: default ( ) ;
462
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
463
- let root2 = vec ! [ virp!( "/ROOT/def" ) ] ;
464
- builder. add_file_set ( root) ;
465
- builder. add_file_set ( root2) ;
466
- let fsc = builder. build ( ) ;
467
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 ] } ;
468
- let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
469
-
470
- assert_eq ! ( vc, vec![ ( SourceRootId ( 0 ) , None ) , ( SourceRootId ( 1 ) , None ) ] )
471
- }
447
+ #[ test]
448
+ fn unrelated_sources ( ) {
449
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
450
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
451
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def" . to_owned( ) ) ] ) ;
452
+ let fsc = builder. build ( ) ;
453
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 ] } ;
454
+ let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
455
+
456
+ assert_eq ! ( vc, vec![ ] )
457
+ }
472
458
473
- #[ test]
474
- fn test2 ( ) {
475
- let mut builder = FileSetConfigBuilder :: default ( ) ;
476
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
477
- let root2 = vec ! [ virp!( "/ROOT/def/abc" ) ] ;
478
- builder. add_file_set ( root) ;
479
- builder. add_file_set ( root2) ;
480
- let fsc = builder. build ( ) ;
481
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 ] } ;
482
- let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
483
-
484
- assert_eq ! ( vc, vec![ ( SourceRootId ( 0 ) , None ) , ( SourceRootId ( 1 ) , None ) ] )
485
- }
459
+ #[ test]
460
+ fn unrelated_source_sharing_dirname ( ) {
461
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
462
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
463
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/abc" . to_owned( ) ) ] ) ;
464
+ let fsc = builder. build ( ) ;
465
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 ] } ;
466
+ let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
467
+
468
+ assert_eq ! ( vc, vec![ ] )
469
+ }
486
470
487
- #[ test]
488
- fn test3 ( ) {
489
- let mut builder = FileSetConfigBuilder :: default ( ) ;
490
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
491
- let root2 = vec ! [ virp!( "/ROOT/abc/def" ) ] ;
492
- builder. add_file_set ( root) ;
493
- builder. add_file_set ( root2) ;
494
- let fsc = builder. build ( ) ;
495
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 ] } ;
496
- let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
497
-
498
- assert_eq ! ( vc, vec![ ( SourceRootId ( 0 ) , None ) , ( SourceRootId ( 1 ) , Some ( SourceRootId ( 0 ) ) ) ] )
499
- }
471
+ #[ test]
472
+ fn basic_child_parent ( ) {
473
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
474
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
475
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc/def" . to_owned( ) ) ] ) ;
476
+ let fsc = builder. build ( ) ;
477
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 ] } ;
478
+ let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
479
+
480
+ assert_eq ! ( vc, vec![ ( SourceRootId ( 1 ) , SourceRootId ( 0 ) ) ] )
481
+ }
500
482
501
- #[ test]
502
- fn test4 ( ) {
503
- let mut builder = FileSetConfigBuilder :: default ( ) ;
504
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
505
- let root2 = vec ! [ virp!( "/ROOT/def" ) ] ;
506
- let root3 = vec ! [ virp!( "/ROOT/def/abc" ) ] ;
507
- builder. add_file_set ( root) ;
508
- builder. add_file_set ( root2) ;
509
- builder. add_file_set ( root3) ;
510
- let fsc = builder. build ( ) ;
511
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 ] } ;
512
- let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
513
-
514
- assert_eq ! (
515
- vc,
516
- vec![
517
- ( SourceRootId ( 0 ) , None ) ,
518
- ( SourceRootId ( 1 ) , None ) ,
519
- ( SourceRootId ( 2 ) , Some ( SourceRootId ( 1 ) ) )
520
- ]
521
- )
522
- }
483
+ #[ test]
484
+ fn basic_child_parent_with_unrelated_parents_sib ( ) {
485
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
486
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
487
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def" . to_owned( ) ) ] ) ;
488
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/abc" . to_owned( ) ) ] ) ;
489
+ let fsc = builder. build ( ) ;
490
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 ] } ;
491
+ let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
492
+
493
+ assert_eq ! ( vc, vec![ ( SourceRootId ( 2 ) , SourceRootId ( 1 ) ) ] )
494
+ }
523
495
524
- #[ test]
525
- fn test5 ( ) {
526
- let mut builder = FileSetConfigBuilder :: default ( ) ;
527
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
528
- let root2 = vec ! [ virp!( "/ROOT/ghi" ) ] ;
529
- let root3 = vec ! [ virp!( "/ROOT/def/abc" ) ] ;
530
- builder. add_file_set ( root) ;
531
- builder. add_file_set ( root2) ;
532
- builder. add_file_set ( root3) ;
533
- let fsc = builder. build ( ) ;
534
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 ] } ;
535
- let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
536
-
537
- assert_eq ! (
538
- vc,
539
- vec![ ( SourceRootId ( 0 ) , None ) , ( SourceRootId ( 1 ) , None ) , ( SourceRootId ( 2 ) , None ) ]
540
- )
541
- }
496
+ #[ test]
497
+ fn deep_sources_with_parent_missing ( ) {
498
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
499
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
500
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/ghi" . to_owned( ) ) ] ) ;
501
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/abc" . to_owned( ) ) ] ) ;
502
+ let fsc = builder. build ( ) ;
503
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 ] } ;
504
+ let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
505
+
506
+ assert_eq ! ( vc, vec![ ] )
507
+ }
542
508
543
- #[ test]
544
- fn test6 ( ) {
545
- let mut builder = FileSetConfigBuilder :: default ( ) ;
546
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
547
- let root2 = vec ! [ virp!( "/ROOT/def" ) ] ;
548
- let root3 = vec ! [ virp!( "/ROOT/def/ghi/jkl" ) ] ;
549
- builder. add_file_set ( root) ;
550
- builder. add_file_set ( root2) ;
551
- builder. add_file_set ( root3) ;
552
- let fsc = builder. build ( ) ;
553
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 ] } ;
554
- let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
555
-
556
- assert_eq ! (
557
- vc,
558
- vec![
559
- ( SourceRootId ( 0 ) , None ) ,
560
- ( SourceRootId ( 1 ) , None ) ,
561
- ( SourceRootId ( 2 ) , Some ( SourceRootId ( 1 ) ) )
562
- ]
563
- )
564
- }
509
+ #[ test]
510
+ fn ancestor_can_be_parent ( ) {
511
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
512
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
513
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def" . to_owned( ) ) ] ) ;
514
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/ghi/jkl" . to_owned( ) ) ] ) ;
515
+ let fsc = builder. build ( ) ;
516
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 ] } ;
517
+ let vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
518
+
519
+ assert_eq ! ( vc, vec![ ( SourceRootId ( 2 ) , SourceRootId ( 1 ) ) ] )
520
+ }
565
521
566
- #[ test]
567
- fn test7 ( ) {
568
- let mut builder = FileSetConfigBuilder :: default ( ) ;
569
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
570
- let root2 = vec ! [ virp!( "/ROOT/def" ) ] ;
571
- let root3 = vec ! [ virp!( "/ROOT/def/ghi/jkl" ) ] ;
572
- let root4 = vec ! [ virp!( "/ROOT/def/ghi/klm" ) ] ;
573
- builder. add_file_set ( root) ;
574
- builder. add_file_set ( root2) ;
575
- builder. add_file_set ( root3) ;
576
- builder. add_file_set ( root4) ;
577
- let fsc = builder. build ( ) ;
578
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 , 3 ] } ;
579
- let mut vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
580
- vc. sort_by ( |x, y| x. 0 . 0 . cmp ( & y. 0 . 0 ) ) ;
581
-
582
- assert_eq ! (
583
- vc,
584
- vec![
585
- ( SourceRootId ( 0 ) , None ) ,
586
- ( SourceRootId ( 1 ) , None ) ,
587
- ( SourceRootId ( 2 ) , Some ( SourceRootId ( 1 ) ) ) ,
588
- ( SourceRootId ( 3 ) , Some ( SourceRootId ( 1 ) ) )
589
- ]
590
- )
591
- }
522
+ #[ test]
523
+ fn ancestor_can_be_parent_2 ( ) {
524
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
525
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
526
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def" . to_owned( ) ) ] ) ;
527
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/ghi/jkl" . to_owned( ) ) ] ) ;
528
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/ghi/klm" . to_owned( ) ) ] ) ;
529
+ let fsc = builder. build ( ) ;
530
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 2 , 3 ] } ;
531
+ let mut vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
532
+ vc. sort_by ( |x, y| x. 0 . 0 . cmp ( & y. 0 . 0 ) ) ;
533
+
534
+ assert_eq ! ( vc, vec![ ( SourceRootId ( 2 ) , SourceRootId ( 1 ) ) , ( SourceRootId ( 3 ) , SourceRootId ( 1 ) ) ] )
535
+ }
592
536
593
- #[ test]
594
- fn test8 ( ) {
595
- let mut builder = FileSetConfigBuilder :: default ( ) ;
596
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
597
- let root2 = vec ! [ virp!( "/ROOT/def" ) ] ;
598
- let root3 = vec ! [ virp!( "/ROOT/def/ghi/jkl" ) ] ;
599
- let root4 = vec ! [ virp!( "/ROOT/def/klm" ) ] ;
600
- builder. add_file_set ( root) ;
601
- builder. add_file_set ( root2) ;
602
- builder. add_file_set ( root3) ;
603
- builder. add_file_set ( root4) ;
604
- let fsc = builder. build ( ) ;
605
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 3 ] } ;
606
- let mut vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
607
- vc. sort_by ( |x, y| x. 0 . 0 . cmp ( & y. 0 . 0 ) ) ;
608
-
609
- assert_eq ! (
610
- vc,
611
- vec![
612
- ( SourceRootId ( 0 ) , None ) ,
613
- ( SourceRootId ( 1 ) , None ) ,
614
- ( SourceRootId ( 3 ) , Some ( SourceRootId ( 1 ) ) ) ,
615
- ]
616
- )
617
- }
537
+ #[ test]
538
+ fn non_locals_are_skipped ( ) {
539
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
540
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
541
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def" . to_owned( ) ) ] ) ;
542
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/ghi/jkl" . to_owned( ) ) ] ) ;
543
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/klm" . to_owned( ) ) ] ) ;
544
+ let fsc = builder. build ( ) ;
545
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 3 ] } ;
546
+ let mut vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
547
+ vc. sort_by ( |x, y| x. 0 . 0 . cmp ( & y. 0 . 0 ) ) ;
548
+
549
+ assert_eq ! ( vc, vec![ ( SourceRootId ( 3 ) , SourceRootId ( 1 ) ) , ] )
550
+ }
618
551
619
- #[ test]
620
- fn test9 ( ) {
621
- let mut builder = FileSetConfigBuilder :: default ( ) ;
622
- let root = vec ! [ virp!( "/ROOT/abc" ) ] ;
623
- let root2 = vec ! [ virp!( "/ROOT/def" ) ] ;
624
- let root3 = vec ! [ virp!( "/ROOT/def/klm" ) ] ;
625
- let root4 = vec ! [ virp!( "/ROOT/def/klm/jkl" ) ] ;
626
- builder. add_file_set ( root) ;
627
- builder. add_file_set ( root2) ;
628
- builder. add_file_set ( root3) ;
629
- builder. add_file_set ( root4) ;
630
- let fsc = builder. build ( ) ;
631
- let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 3 ] } ;
632
- let mut vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
633
- vc. sort_by ( |x, y| x. 0 . 0 . cmp ( & y. 0 . 0 ) ) ;
634
-
635
- assert_eq ! (
636
- vc,
637
- vec![
638
- ( SourceRootId ( 0 ) , None ) ,
639
- ( SourceRootId ( 1 ) , None ) ,
640
- ( SourceRootId ( 3 ) , Some ( SourceRootId ( 1 ) ) ) ,
641
- ]
642
- )
643
- }
552
+ #[ test]
553
+ fn child_binds_ancestor_if_parent_nonlocal ( ) {
554
+ let mut builder = FileSetConfigBuilder :: default ( ) ;
555
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/abc" . to_owned( ) ) ] ) ;
556
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def" . to_owned( ) ) ] ) ;
557
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/klm" . to_owned( ) ) ] ) ;
558
+ builder. add_file_set ( vec ! [ VfsPath :: new_virtual_path( "/ROOT/def/klm/jkl" . to_owned( ) ) ] ) ;
559
+ let fsc = builder. build ( ) ;
560
+ let src = SourceRootConfig { fsc, local_filesets : vec ! [ 0 , 1 , 3 ] } ;
561
+ let mut vc = src. source_root_parent_map ( ) . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
562
+ vc. sort_by ( |x, y| x. 0 . 0 . cmp ( & y. 0 . 0 ) ) ;
563
+
564
+ assert_eq ! ( vc, vec![ ( SourceRootId ( 3 ) , SourceRootId ( 1 ) ) , ] )
644
565
}
645
566
}
0 commit comments