Gracefully handle models searching for empty glob (#27370)

Sometimes we've seen models provide an empty string for the path search
glob. This assumes they meant "*" when that happens.

Separately, this also removes an unnecessary `clone` of a `String`.

Release Notes:

- N/A
This commit is contained in:
Richard Feldman 2025-03-25 12:32:20 -04:00 committed by GitHub
parent 430814c0a9
commit 6b7167a32d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 11 additions and 6 deletions

View file

@ -1,5 +1,6 @@
use language::{BufferSnapshot, Diff, Point, ToOffset};
use project::search::SearchQuery;
use std::iter;
use util::{paths::PathMatcher, ResultExt as _};
/// Performs an exact string replacement in a buffer, requiring precise character-for-character matching.
@ -11,8 +12,8 @@ pub async fn replace_exact(old: &str, new: &str, snapshot: &BufferSnapshot) -> O
false,
true,
true,
PathMatcher::new(&[]).ok()?,
PathMatcher::new(&[]).ok()?,
PathMatcher::new(iter::empty::<&str>()).ok()?,
PathMatcher::new(iter::empty::<&str>()).ok()?,
None,
)
.log_err()?;

View file

@ -71,7 +71,11 @@ impl Tool for PathSearchTool {
Ok(input) => (input.offset.unwrap_or(0), input.glob),
Err(err) => return Task::ready(Err(anyhow!(err))),
};
let path_matcher = match PathMatcher::new(&[glob.clone()]) {
let path_matcher = match PathMatcher::new([
// Sometimes models try to search for "". In this case, return all paths in the project.
if glob.is_empty() { "*" } else { &glob },
]) {
Ok(matcher) => matcher,
Err(err) => return Task::ready(Err(anyhow!("Invalid glob: {err}"))),
};

View file

@ -377,10 +377,10 @@ impl PartialEq for PathMatcher {
impl Eq for PathMatcher {}
impl PathMatcher {
pub fn new(globs: &[String]) -> Result<Self, globset::Error> {
pub fn new(globs: impl IntoIterator<Item = impl AsRef<str>>) -> Result<Self, globset::Error> {
let globs = globs
.iter()
.map(|glob| Glob::new(glob))
.into_iter()
.map(|as_str| Glob::new(as_str.as_ref()))
.collect::<Result<Vec<_>, _>>()?;
let sources = globs.iter().map(|glob| glob.glob().to_owned()).collect();
let mut glob_builder = GlobSetBuilder::new();