pub fn parse_file_symbol_selector(selector: &str) -> Option<(&str, &str)> {
let (file, symbol) = selector.rsplit_once(':')?;
if file.trim().is_empty() || symbol.trim().is_empty() {
return None;
}
Some((file, symbol))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn splits_on_the_last_colon() {
assert_eq!(
parse_file_symbol_selector("src/utils.ts:formatDate"),
Some(("src/utils.ts", "formatDate"))
);
assert_eq!(
parse_file_symbol_selector("src/component.tsx:default"),
Some(("src/component.tsx", "default"))
);
}
#[test]
fn keeps_colons_that_belong_to_the_path() {
assert_eq!(
parse_file_symbol_selector("C:\\src\\utils.ts:foo"),
Some(("C:\\src\\utils.ts", "foo"))
);
assert_eq!(
parse_file_symbol_selector("C:/proj/src/a.ts:foo"),
Some(("C:/proj/src/a.ts", "foo"))
);
assert_eq!(
parse_file_symbol_selector("packages/core:src/index.ts:myExport"),
Some(("packages/core:src/index.ts", "myExport"))
);
}
#[test]
fn rejects_a_selector_without_a_colon() {
assert_eq!(parse_file_symbol_selector("src/utils.ts"), None);
assert_eq!(parse_file_symbol_selector(""), None);
}
#[test]
fn rejects_empty_and_whitespace_only_halves() {
assert_eq!(parse_file_symbol_selector(":"), None);
assert_eq!(parse_file_symbol_selector("src/utils.ts:"), None);
assert_eq!(parse_file_symbol_selector(":foo"), None);
assert_eq!(parse_file_symbol_selector(" : "), None);
assert_eq!(parse_file_symbol_selector("src/utils.ts:\t"), None);
assert_eq!(parse_file_symbol_selector("\t:foo"), None);
}
#[test]
fn returns_surviving_halves_verbatim() {
assert_eq!(
parse_file_symbol_selector(" src/utils.ts : foo "),
Some((" src/utils.ts ", " foo "))
);
}
}