tasks: Fix runnables retrieval to not bail when a single tag can't be matched (#12113)

This can happen with queries without `@run` indicator.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2024-05-22 13:26:12 +02:00 committed by GitHub
parent e68ef944d9
commit c440f3a71b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3005,52 +3005,56 @@ impl BufferSnapshot {
.map(|grammar| grammar.runnable_config.as_ref())
.collect::<Vec<_>>();
iter::from_fn(move || {
let test_range = syntax_matches.peek().and_then(|mat| {
test_configs[mat.grammar_index].and_then(|test_configs| {
let mut tags: SmallVec<[(Range<usize>, RunnableTag); 1]> =
SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
test_configs
.runnable_tags
.get(&capture.index)
.cloned()
.map(|tag_name| (capture.node.byte_range(), tag_name))
}));
let maximum_range = tags
.iter()
.max_by_key(|(byte_range, _)| byte_range.len())
.map(|(range, _)| range)?
.clone();
tags.sort_by_key(|(range, _)| range == &maximum_range);
let split_point = tags.partition_point(|(range, _)| range != &maximum_range);
let (extra_captures, tags) = tags.split_at(split_point);
let extra_captures = extra_captures
.into_iter()
.map(|(range, name)| {
(
name.0.to_string(),
self.text_for_range(range.clone()).collect::<String>(),
)
})
.collect();
Some(RunnableRange {
run_range: mat
.captures
.iter()
.find(|capture| capture.index == test_configs.run_capture_ix)
.map(|mat| mat.node.byte_range())?,
runnable: Runnable {
tags: tags.into_iter().cloned().map(|(_, tag)| tag).collect(),
language: mat.language,
buffer: self.remote_id(),
},
extra_captures,
buffer_id: self.remote_id(),
iter::from_fn(move || loop {
let mat = syntax_matches.peek()?;
let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
let mut tags: SmallVec<[(Range<usize>, RunnableTag); 1]> =
SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
test_configs
.runnable_tags
.get(&capture.index)
.cloned()
.map(|tag_name| (capture.node.byte_range(), tag_name))
}));
let maximum_range = tags
.iter()
.max_by_key(|(byte_range, _)| byte_range.len())
.map(|(range, _)| range)?
.clone();
tags.sort_by_key(|(range, _)| range == &maximum_range);
let split_point = tags.partition_point(|(range, _)| range != &maximum_range);
let (extra_captures, tags) = tags.split_at(split_point);
let extra_captures = extra_captures
.into_iter()
.map(|(range, name)| {
(
name.0.to_string(),
self.text_for_range(range.clone()).collect::<String>(),
)
})
.collect();
Some(RunnableRange {
run_range: mat
.captures
.iter()
.find(|capture| capture.index == test_configs.run_capture_ix)
.map(|mat| mat.node.byte_range())?,
runnable: Runnable {
tags: tags.into_iter().cloned().map(|(_, tag)| tag).collect(),
language: mat.language,
buffer: self.remote_id(),
},
extra_captures,
buffer_id: self.remote_id(),
})
});
syntax_matches.advance();
test_range
if test_range.is_some() {
// It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
// had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
return test_range;
}
})
}