use rowan::TextRange;
use crate::project::scripts::DefinitionEffects;
use crate::syntax::{SyntaxKind, SyntaxNode};
pub(crate) struct FileScan {
macro_calls: Vec<TextRange>,
quotes: Vec<TextRange>,
pub(crate) calls_eval: bool,
pub(crate) literal_include: bool,
pub(crate) dynamic_include: bool,
}
impl FileScan {
pub(crate) fn collect(root: &SyntaxNode) -> Self {
let mut scan = FileScan {
macro_calls: Vec::new(),
quotes: Vec::new(),
calls_eval: false,
literal_include: false,
dynamic_include: false,
};
let mut effects = DefinitionEffects::default();
for node in root.descendants() {
effects.observe(&node);
match node.kind() {
SyntaxKind::MACRO_CALL => scan.macro_calls.push(node.text_range()),
SyntaxKind::QUOTE_EXPR | SyntaxKind::QUOTE_SYM => {
scan.quotes.push(node.text_range())
}
_ => {}
}
}
scan.calls_eval = effects.calls_eval;
scan.literal_include = effects.literal_include;
scan.dynamic_include = effects.dynamic_include;
scan
}
pub(crate) fn in_quote(&self, range: TextRange) -> bool {
within(&self.quotes, range)
}
pub(crate) fn in_macro_call(&self, range: TextRange) -> bool {
within(&self.macro_calls, range)
}
pub(crate) fn in_skipped(&self, range: TextRange) -> bool {
self.in_quote(range) || self.in_macro_call(range)
}
}
fn within(extents: &[TextRange], range: TextRange) -> bool {
extents.iter().any(|e| e.contains_range(range))
}