Test the search inclusions/exclusions
This commit is contained in:
parent
80fc1bc276
commit
dfdf7e4866
4 changed files with 353 additions and 30 deletions
|
@ -4208,11 +4208,9 @@ impl Project {
|
||||||
if matching_paths_tx.is_closed() {
|
if matching_paths_tx.is_closed() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let matches = if !query
|
let matches = if query
|
||||||
.file_matches(Some(&entry.path))
|
.file_matches(Some(&entry.path))
|
||||||
{
|
{
|
||||||
false
|
|
||||||
} else {
|
|
||||||
abs_path.clear();
|
abs_path.clear();
|
||||||
abs_path.push(&snapshot.abs_path());
|
abs_path.push(&snapshot.abs_path());
|
||||||
abs_path.push(&entry.path);
|
abs_path.push(&entry.path);
|
||||||
|
@ -4223,6 +4221,8 @@ impl Project {
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches {
|
if matches {
|
||||||
|
|
|
@ -3335,28 +3335,348 @@ async fn test_search(cx: &mut gpui::TestAppContext) {
|
||||||
("four.rs".to_string(), vec![25..28, 36..39])
|
("four.rs".to_string(), vec![25..28, 36..39])
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
}
|
||||||
async fn search(
|
|
||||||
project: &ModelHandle<Project>,
|
#[gpui::test]
|
||||||
query: SearchQuery,
|
async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) {
|
||||||
cx: &mut gpui::TestAppContext,
|
let search_query = "file";
|
||||||
) -> Result<HashMap<String, Vec<Range<usize>>>> {
|
|
||||||
let results = project
|
let fs = FakeFs::new(cx.background());
|
||||||
.update(cx, |project, cx| project.search(query, cx))
|
fs.insert_tree(
|
||||||
.await?;
|
"/dir",
|
||||||
|
json!({
|
||||||
Ok(results
|
"one.rs": r#"// Rust file one"#,
|
||||||
.into_iter()
|
"one.ts": r#"// TypeScript file one"#,
|
||||||
.map(|(buffer, ranges)| {
|
"two.rs": r#"// Rust file two"#,
|
||||||
buffer.read_with(cx, |buffer, _| {
|
"two.ts": r#"// TypeScript file two"#,
|
||||||
let path = buffer.file().unwrap().path().to_string_lossy().to_string();
|
}),
|
||||||
let ranges = ranges
|
)
|
||||||
.into_iter()
|
.await;
|
||||||
.map(|range| range.to_offset(buffer))
|
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||||
.collect::<Vec<_>>();
|
|
||||||
(path, ranges)
|
assert!(
|
||||||
})
|
search(
|
||||||
})
|
&project,
|
||||||
.collect())
|
SearchQuery::text(
|
||||||
}
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![glob::Pattern::new("*.odd").unwrap()],
|
||||||
|
Vec::new()
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.is_empty(),
|
||||||
|
"If no inclusions match, no files should be returned"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![glob::Pattern::new("*.rs").unwrap()],
|
||||||
|
Vec::new()
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.rs".to_string(), vec![8..12]),
|
||||||
|
("two.rs".to_string(), vec![8..12]),
|
||||||
|
]),
|
||||||
|
"Rust only search should give only Rust files"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap(),
|
||||||
|
],
|
||||||
|
Vec::new()
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.ts".to_string(), vec![14..18]),
|
||||||
|
("two.ts".to_string(), vec![14..18]),
|
||||||
|
]),
|
||||||
|
"TypeScript only search should give only TypeScript files, even if other inclusions don't match anything"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.rs").unwrap(),
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap(),
|
||||||
|
],
|
||||||
|
Vec::new()
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.rs".to_string(), vec![8..12]),
|
||||||
|
("one.ts".to_string(), vec![14..18]),
|
||||||
|
("two.rs".to_string(), vec![8..12]),
|
||||||
|
("two.ts".to_string(), vec![14..18]),
|
||||||
|
]),
|
||||||
|
"Rust and typescript search should give both Rust and TypeScript files, even if other inclusions don't match anything"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) {
|
||||||
|
let search_query = "file";
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.background());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/dir",
|
||||||
|
json!({
|
||||||
|
"one.rs": r#"// Rust file one"#,
|
||||||
|
"one.ts": r#"// TypeScript file one"#,
|
||||||
|
"two.rs": r#"// Rust file two"#,
|
||||||
|
"two.ts": r#"// TypeScript file two"#,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Vec::new(),
|
||||||
|
vec![glob::Pattern::new("*.odd").unwrap()],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.rs".to_string(), vec![8..12]),
|
||||||
|
("one.ts".to_string(), vec![14..18]),
|
||||||
|
("two.rs".to_string(), vec![8..12]),
|
||||||
|
("two.ts".to_string(), vec![14..18]),
|
||||||
|
]),
|
||||||
|
"If no exclusions match, all files should be returned"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Vec::new(),
|
||||||
|
vec![glob::Pattern::new("*.rs").unwrap()],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.ts".to_string(), vec![14..18]),
|
||||||
|
("two.ts".to_string(), vec![14..18]),
|
||||||
|
]),
|
||||||
|
"Rust exclusion search should give only TypeScript files"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Vec::new(),
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.rs".to_string(), vec![8..12]),
|
||||||
|
("two.rs".to_string(), vec![8..12]),
|
||||||
|
]),
|
||||||
|
"TypeScript exclusion search should give only Rust files, even if other exclusions don't match anything"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Vec::new(),
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.rs").unwrap(),
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap().is_empty(),
|
||||||
|
"Rust and typescript exclusion should give no files, even if other exclusions don't match anything"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContext) {
|
||||||
|
let search_query = "file";
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.background());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/dir",
|
||||||
|
json!({
|
||||||
|
"one.rs": r#"// Rust file one"#,
|
||||||
|
"one.ts": r#"// TypeScript file one"#,
|
||||||
|
"two.rs": r#"// Rust file two"#,
|
||||||
|
"two.ts": r#"// TypeScript file two"#,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![glob::Pattern::new("*.odd").unwrap()],
|
||||||
|
vec![glob::Pattern::new("*.odd").unwrap()],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.is_empty(),
|
||||||
|
"If both no exclusions and inclusions match, exclusions should win and return nothing"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![glob::Pattern::new("*.ts").unwrap()],
|
||||||
|
vec![glob::Pattern::new("*.ts").unwrap()],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.is_empty(),
|
||||||
|
"If both TypeScript exclusions and inclusions match, exclusions should win and return nothing files."
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap()
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.is_empty(),
|
||||||
|
"Non-matching inclusions and exclusions should not change that."
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
search(
|
||||||
|
&project,
|
||||||
|
SearchQuery::text(
|
||||||
|
search_query,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.ts").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap()
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
glob::Pattern::new("*.rs").unwrap(),
|
||||||
|
glob::Pattern::new("*.odd").unwrap()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
cx
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
HashMap::from_iter([
|
||||||
|
("one.ts".to_string(), vec![14..18]),
|
||||||
|
("two.ts".to_string(), vec![14..18]),
|
||||||
|
]),
|
||||||
|
"Non-intersecting TypeScript inclusions and Rust exclusions should return TypeScript files"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn search(
|
||||||
|
project: &ModelHandle<Project>,
|
||||||
|
query: SearchQuery,
|
||||||
|
cx: &mut gpui::TestAppContext,
|
||||||
|
) -> Result<HashMap<String, Vec<Range<usize>>>> {
|
||||||
|
let results = project
|
||||||
|
.update(cx, |project, cx| project.search(query, cx))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(results
|
||||||
|
.into_iter()
|
||||||
|
.map(|(buffer, ranges)| {
|
||||||
|
buffer.read_with(cx, |buffer, _| {
|
||||||
|
let path = buffer.file().unwrap().path().to_string_lossy().to_string();
|
||||||
|
let ranges = ranges
|
||||||
|
.into_iter()
|
||||||
|
.map(|range| range.to_offset(buffer))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
(path, ranges)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,7 +428,7 @@ impl ProjectSearchView {
|
||||||
editor.set_text(query_text, cx);
|
editor.set_text(query_text, cx);
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
// Subcribe to query_editor in order to reraise editor events for workspace item activation purposes
|
// Subscribe to query_editor in order to reraise editor events for workspace item activation purposes
|
||||||
cx.subscribe(&query_editor, |_, _, event, cx| {
|
cx.subscribe(&query_editor, |_, _, event, cx| {
|
||||||
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
||||||
})
|
})
|
||||||
|
@ -462,7 +462,7 @@ impl ProjectSearchView {
|
||||||
|
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
// Subcribe to include_files_editor in order to reraise editor events for workspace item activation purposes
|
// Subscribe to include_files_editor in order to reraise editor events for workspace item activation purposes
|
||||||
cx.subscribe(&included_files_editor, |_, _, event, cx| {
|
cx.subscribe(&included_files_editor, |_, _, event, cx| {
|
||||||
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
||||||
})
|
})
|
||||||
|
@ -479,7 +479,7 @@ impl ProjectSearchView {
|
||||||
|
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
// Subcribe to excluded_files_editor in order to reraise editor events for workspace item activation purposes
|
// Subscribe to excluded_files_editor in order to reraise editor events for workspace item activation purposes
|
||||||
cx.subscribe(&excluded_files_editor, |_, _, event, cx| {
|
cx.subscribe(&excluded_files_editor, |_, _, event, cx| {
|
||||||
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
cx.emit(ViewEvent::EditorEvent(event.clone()))
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,6 +23,9 @@ pub trait ToolbarItemView: View {
|
||||||
|
|
||||||
fn pane_focus_update(&mut self, _pane_focused: bool, _cx: &mut ViewContext<Self>) {}
|
fn pane_focus_update(&mut self, _pane_focused: bool, _cx: &mut ViewContext<Self>) {}
|
||||||
|
|
||||||
|
/// Number of times toolbar's height will be repeated to get the effective height.
|
||||||
|
/// Useful when multiple rows one under each other are needed.
|
||||||
|
/// The rows have the same width and act as a whole when reacting to resizes and similar events.
|
||||||
fn row_count(&self) -> usize {
|
fn row_count(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue