Skip to content

Commit 773b4a5

Browse files
committed
Auto merge of rust-lang#17019 - Wilfred:source_root_prefixes, r=Veykril
fix: VFS should not confuse paths with source roots that have the same prefix Previously, the VFS would assign paths to the source root that had the longest string prefix match. This would break when we had source roots in subdirectories: ``` /foo /foo/bar ``` Given a file `/foo/bar_baz.rs`, we would attribute it to the `/foo/bar` source root, which is wrong. As a result, we would attribute paths to the wrong crate when a crate was in a subdirectory of another one. This is more common in larger monorepos, but could occur in any Rust project. Fix this in the VFS, and add a test.
2 parents 9b19462 + b03844d commit 773b4a5

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

crates/vfs/src/file_set.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ impl FileSetConfig {
132132
///
133133
/// `scratch_space` is used as a buffer and will be entirely replaced.
134134
fn classify(&self, path: &VfsPath, scratch_space: &mut Vec<u8>) -> usize {
135+
// `path` is a file, but r-a only cares about the containing directory. We don't
136+
// want `/foo/bar_baz.rs` to be attributed to source root directory `/foo/bar`.
137+
let path = path.parent().unwrap_or_else(|| path.clone());
138+
135139
scratch_space.clear();
136140
path.encode(scratch_space);
137141
let automaton = PrefixOf::new(scratch_space.as_slice());

crates/vfs/src/file_set/tests.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,26 @@ fn name_prefix() {
4040
let partition = file_set.partition(&vfs).into_iter().map(|it| it.len()).collect::<Vec<_>>();
4141
assert_eq!(partition, vec![1, 1, 0]);
4242
}
43+
44+
/// Ensure that we don't consider `/foo/bar_baz.rs` to be in the
45+
/// `/foo/bar/` root.
46+
#[test]
47+
fn name_prefix_partially_matches() {
48+
let mut file_set = FileSetConfig::builder();
49+
file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo".into())]);
50+
file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo/bar".into())]);
51+
let file_set = file_set.build();
52+
53+
let mut vfs = Vfs::default();
54+
55+
// These two are both in /foo.
56+
vfs.set_file_contents(VfsPath::new_virtual_path("/foo/lib.rs".into()), Some(Vec::new()));
57+
vfs.set_file_contents(VfsPath::new_virtual_path("/foo/bar_baz.rs".into()), Some(Vec::new()));
58+
59+
// Only this file is in /foo/bar.
60+
vfs.set_file_contents(VfsPath::new_virtual_path("/foo/bar/biz.rs".into()), Some(Vec::new()));
61+
62+
let partition = file_set.partition(&vfs).into_iter().map(|it| it.len()).collect::<Vec<_>>();
63+
64+
assert_eq!(partition, vec![2, 1, 0]);
65+
}

0 commit comments

Comments
 (0)