#[allow(clippy::wildcard_imports)]
use super::*;
pub(super) fn callable_has_syntax_error(node: &Node<'_>, body_node: Option<&Node<'_>>) -> bool {
node.has_error() || body_node.is_some_and(tree_sitter::Node::has_error)
}
fn span_overlaps_error(span: Span, error_spans: &[Span]) -> bool {
error_spans.iter().any(|err| {
if err.start == err.end {
span.start <= err.start && err.start <= span.end
} else {
span.start < err.end && err.start < span.end
}
})
}
pub(super) fn retain_flow_events_outside_errors(
events: &mut Vec<FlowEvent>,
error_spans: &[Span],
tolerant_call_names: &[&str],
) {
events.retain_mut(|event| match event {
FlowEvent::Branch {
then_events,
else_events,
..
} => {
retain_flow_events_outside_errors(then_events, error_spans, tolerant_call_names);
retain_flow_events_outside_errors(else_events, error_spans, tolerant_call_names);
true
}
FlowEvent::Loop { body, .. } => {
retain_flow_events_outside_errors(body, error_spans, tolerant_call_names);
true
}
FlowEvent::Try {
body,
catch_events,
finally_events,
..
} => {
retain_flow_events_outside_errors(body, error_spans, tolerant_call_names);
retain_flow_events_outside_errors(catch_events, error_spans, tolerant_call_names);
retain_flow_events_outside_errors(finally_events, error_spans, tolerant_call_names);
true
}
FlowEvent::Defer { body, .. } | FlowEvent::Using { body, .. } => {
retain_flow_events_outside_errors(body, error_spans, tolerant_call_names);
true
}
leaf @ FlowEvent::Assign { .. } if assign_uses_tolerated_call(leaf, tolerant_call_names) => true,
leaf => !span_overlaps_error(leaf.span(), error_spans),
});
}
fn assign_uses_tolerated_call(event: &FlowEvent, tolerant_call_names: &[&str]) -> bool {
matches!(
event,
FlowEvent::Assign { source_call: Some(call), .. }
if tolerant_call_names.contains(&call.as_str())
)
}
pub(super) fn syntax_error_spans(tree: &tree_sitter::Tree, file: FileId) -> Vec<Span> {
let mut spans = Vec::new();
let mut stack = vec![tree.root_node()];
while let Some(node) = stack.pop() {
if node.is_error() || node.is_missing() {
spans.push(span_of(file, &node));
}
if !node.is_error() {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.has_error() || child.is_missing() {
stack.push(child);
}
}
}
}
spans
}