Allow matching of context items in outline view

This commit is contained in:
Antonio Scandurra 2022-01-14 11:09:02 +01:00
parent e7f1398f3a
commit a64ba8b687
4 changed files with 44 additions and 64 deletions

View file

@ -1712,7 +1712,6 @@ impl MultiBufferSnapshot {
..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end), ..self.anchor_in_excerpt(excerpt_id.clone(), item.range.end),
text: item.text, text: item.text,
highlight_ranges: item.highlight_ranges, highlight_ranges: item.highlight_ranges,
name_ranges: item.name_ranges,
}) })
.collect(), .collect(),
)) ))

View file

@ -1864,15 +1864,11 @@ impl BufferSnapshot {
let item_node = mat.nodes_for_capture_index(item_capture_ix).next()?; let item_node = mat.nodes_for_capture_index(item_capture_ix).next()?;
let range = item_node.start_byte()..item_node.end_byte(); let range = item_node.start_byte()..item_node.end_byte();
let mut text = String::new(); let mut text = String::new();
let mut name_ranges = Vec::new();
let mut highlight_ranges = Vec::new(); let mut highlight_ranges = Vec::new();
for capture in mat.captures { for capture in mat.captures {
let node_is_name;
if capture.index == name_capture_ix { if capture.index == name_capture_ix {
node_is_name = true;
} else if capture.index == context_capture_ix { } else if capture.index == context_capture_ix {
node_is_name = false;
} else { } else {
continue; continue;
} }
@ -1881,18 +1877,6 @@ impl BufferSnapshot {
if !text.is_empty() { if !text.is_empty() {
text.push(' '); text.push(' ');
} }
if node_is_name {
let mut start = text.len() as u32;
let end = start + range.len() as u32;
// When multiple names are captured, then the matcheable text
// includes the whitespace in between the names.
if !name_ranges.is_empty() {
start -= 1;
}
name_ranges.push(start..end);
}
let mut offset = range.start; let mut offset = range.start;
chunks.seek(offset); chunks.seek(offset);
@ -1926,7 +1910,6 @@ impl BufferSnapshot {
depth: stack.len() - 1, depth: stack.len() - 1,
range: self.anchor_after(range.start)..self.anchor_before(range.end), range: self.anchor_after(range.start)..self.anchor_before(range.end),
text, text,
name_ranges,
highlight_ranges, highlight_ranges,
}) })
}) })

View file

@ -13,7 +13,6 @@ pub struct OutlineItem<T> {
pub depth: usize, pub depth: usize,
pub range: Range<T>, pub range: Range<T>,
pub text: String, pub text: String,
pub name_ranges: Vec<Range<u32>>,
pub highlight_ranges: Vec<(Range<usize>, HighlightStyle)>, pub highlight_ranges: Vec<(Range<usize>, HighlightStyle)>,
} }
@ -22,16 +21,9 @@ impl<T> Outline<T> {
Self { Self {
candidates: items candidates: items
.iter() .iter()
.map(|item| { .map(|item| StringMatchCandidate {
let text = item char_bag: item.text.as_str().into(),
.name_ranges string: item.text.clone(),
.iter()
.map(|range| &item.text[range.start as usize..range.end as usize])
.collect::<String>();
StringMatchCandidate {
char_bag: text.as_str().into(),
string: text,
}
}) })
.collect(), .collect(),
items, items,
@ -53,20 +45,8 @@ impl<T> Outline<T> {
let mut tree_matches = Vec::new(); let mut tree_matches = Vec::new();
let mut prev_item_ix = 0; let mut prev_item_ix = 0;
for mut string_match in matches { for string_match in matches {
let outline_match = &self.items[string_match.candidate_index]; let outline_match = &self.items[string_match.candidate_index];
let mut name_ranges = outline_match.name_ranges.iter();
let mut name_range = name_ranges.next().unwrap();
let mut preceding_ranges_len = 0;
for position in &mut string_match.positions {
while *position >= preceding_ranges_len + name_range.len() as usize {
preceding_ranges_len += name_range.len();
name_range = name_ranges.next().unwrap();
}
*position = name_range.start as usize + (*position - preceding_ranges_len);
}
let insertion_ix = tree_matches.len(); let insertion_ix = tree_matches.len();
let mut cur_depth = outline_match.depth; let mut cur_depth = outline_match.depth;
for (ix, item) in self.items[prev_item_ix..string_match.candidate_index] for (ix, item) in self.items[prev_item_ix..string_match.candidate_index]

View file

@ -302,6 +302,9 @@ async fn test_outline(mut cx: gpui::TestAppContext) {
(function_item (function_item
"fn" @context "fn" @context
name: (_) @name) @item name: (_) @name) @item
(mod_item
"mod" @context
name: (_) @name) @item
"#, "#,
) )
.unwrap(), .unwrap(),
@ -313,6 +316,7 @@ async fn test_outline(mut cx: gpui::TestAppContext) {
age: usize, age: usize,
} }
mod module {
enum LoginState { enum LoginState {
LoggedOut, LoggedOut,
LoggingOn, LoggingOn,
@ -321,6 +325,9 @@ async fn test_outline(mut cx: gpui::TestAppContext) {
time: Instant, time: Instant,
} }
} }
}
impl Eq for Person {}
impl Drop for Person { impl Drop for Person {
fn drop(&mut self) { fn drop(&mut self) {
@ -339,39 +346,50 @@ async fn test_outline(mut cx: gpui::TestAppContext) {
outline outline
.items .items
.iter() .iter()
.map(|item| (item.text.as_str(), item.name_ranges.as_ref(), item.depth)) .map(|item| (item.text.as_str(), item.depth))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
&[ &[
("struct Person", [7..13].as_slice(), 0), ("struct Person", 0),
("name", &[0..4], 1), ("name", 1),
("age", &[0..3], 1), ("age", 1),
("enum LoginState", &[5..15], 0), ("mod module", 0),
("LoggedOut", &[0..9], 1), ("enum LoginState", 1),
("LoggingOn", &[0..9], 1), ("LoggedOut", 2),
("LoggedIn", &[0..8], 1), ("LoggingOn", 2),
("person", &[0..6], 2), ("LoggedIn", 2),
("time", &[0..4], 2), ("person", 3),
("impl Drop for Person", &[5..9, 13..20], 0), ("time", 3),
("fn drop", &[3..7], 1), ("impl Eq for Person", 0),
("impl Drop for Person", 0),
("fn drop", 1),
] ]
); );
assert_eq!( assert_eq!(
search(&outline, "oon", &cx).await, search(&outline, "oon", &cx).await,
&[ &[
("mod module", vec![]), // included as the parent of a match
("enum LoginState", vec![]), // included as the parent of a match ("enum LoginState", vec![]), // included as the parent of a match
("LoggingOn", vec![1, 7, 8]), // matches ("LoggingOn", vec![1, 7, 8]), // matches
("impl Drop for Person", vec![7, 18, 19]), // matches in two disjoint names ("impl Eq for Person", vec![9, 16, 17]), // matches part of the context
("impl Drop for Person", vec![11, 18, 19]), // matches in two disjoint names
] ]
); );
assert_eq!( assert_eq!(
search(&outline, "dp p", &cx).await, search(&outline, "dp p", &cx).await,
&[("impl Drop for Person", vec![5, 8, 13, 14])] &[("impl Drop for Person", vec![5, 8, 9, 14])]
); );
assert_eq!( assert_eq!(
search(&outline, "dpn", &cx).await, search(&outline, "dpn", &cx).await,
&[("impl Drop for Person", vec![5, 8, 19])] &[("impl Drop for Person", vec![5, 8, 19])]
); );
assert_eq!(
search(&outline, "impl", &cx).await,
&[
("impl Eq for Person", vec![0, 1, 2, 3]),
("impl Drop for Person", vec![0, 1, 2, 3])
]
);
async fn search<'a>( async fn search<'a>(
outline: &'a Outline<Anchor>, outline: &'a Outline<Anchor>,