diff --git a/crates/util/src/paths.rs b/crates/util/src/paths.rs index 90ce3f8..e7107d3 100644 --- a/crates/util/src/paths.rs +++ b/crates/util/src/paths.rs @@ -662,8 +662,10 @@ impl PathWithPosition { let row = maybe_row.parse::().ok(); let column = maybe_column.parse::().ok(); - let (_, suffix) = trimmed.split_once(file_name).unwrap(); - let path_without_suffix = &trimmed[..trimmed.len() - suffix.len()]; + // `file_name` borrows from the last component of `trimmed`, so cut right after it + // instead of searching for its text, which may also appear in a parent directory. + let file_name_start = file_name.as_ptr() as usize - trimmed.as_ptr() as usize; + let path_without_suffix = &trimmed[..file_name_start + file_name.len()]; Self { path: Path::new(path_without_suffix).to_path_buf(), @@ -2512,6 +2514,54 @@ mod tests { ); } + #[perf] + fn path_with_position_parse_file_name_repeated_in_path() { + assert_eq!( + PathWithPosition::parse_str("foo/foo:10:2"), + PathWithPosition { + path: PathBuf::from("foo/foo"), + row: Some(10), + column: Some(2), + } + ); + + assert_eq!( + PathWithPosition::parse_str("foo/foo(10,2)"), + PathWithPosition { + path: PathBuf::from("foo/foo"), + row: Some(10), + column: Some(2), + } + ); + + assert_eq!( + PathWithPosition::parse_str("main.rs-backup/src/main.rs:10:2"), + PathWithPosition { + path: PathBuf::from("main.rs-backup/src/main.rs"), + row: Some(10), + column: Some(2), + } + ); + + assert_eq!( + PathWithPosition::parse_str("1/1:1:1"), + PathWithPosition { + path: PathBuf::from("1/1"), + row: Some(1), + column: Some(1), + } + ); + + assert_eq!( + PathWithPosition::parse_str("日本/日本:3"), + PathWithPosition { + path: PathBuf::from("日本/日本"), + row: Some(3), + column: None, + } + ); + } + #[perf] #[cfg(target_os = "windows")] fn path_with_position_parse_windows_path() {