Skip to content

Commit 9c50d12

Browse files
committed
Opt for FxHashMap<Id,Id> instead of <Id,Option<Id>> and apply requested changes
1 parent a15cc86 commit 9c50d12

File tree

3 files changed

+136
-221
lines changed

3 files changed

+136
-221
lines changed

crates/load-cargo/src/lib.rs

+134-213
Original file line numberDiff line numberDiff line change
@@ -267,32 +267,27 @@ impl SourceRootConfig {
267267
}
268268

269269
/// 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> {
272272
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));
290284
}
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+
});
296291
map
297292
}
298293
}
@@ -427,6 +422,11 @@ mod tests {
427422

428423
use super::*;
429424

425+
use ide_db::base_db::SourceRootId;
426+
use vfs::{file_set::FileSetConfigBuilder, VfsPath};
427+
428+
use crate::SourceRootConfig;
429+
430430
#[test]
431431
fn test_loading_rust_analyzer() {
432432
let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
@@ -444,202 +444,123 @@ mod tests {
444444
assert!(n_crates > 20);
445445
}
446446

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+
}
472458

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+
}
486470

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+
}
500482

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+
}
523495

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+
}
542508

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+
}
565521

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+
}
592536

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+
}
618551

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)),])
644565
}
645566
}

crates/rust-analyzer/src/global_state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub(crate) struct GlobalState {
6767
pub(crate) mem_docs: MemDocs,
6868
pub(crate) source_root_config: SourceRootConfig,
6969
/// A mapping that maps a local source root's `SourceRootId` to it parent's `SourceRootId`, if it has one.
70-
pub(crate) local_roots_parent_map: FxHashMap<SourceRootId, Option<SourceRootId>>,
70+
pub(crate) local_roots_parent_map: FxHashMap<SourceRootId, SourceRootId>,
7171
pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
7272

7373
// status

0 commit comments

Comments
 (0)