use std::collections::HashSet;
use rowan::TextRange;
use crate::syntax::{SyntaxKind, SyntaxNode};
pub(crate) struct AnchorOccurrence {
pub name: String,
pub range: TextRange,
}
pub(crate) struct DocumentAnchors {
pub anchors: Vec<AnchorOccurrence>,
pub used: HashSet<String>,
}
pub(crate) fn collect_document_anchors(regions: &[&SyntaxNode]) -> Vec<DocumentAnchors> {
let mut docs = Vec::new();
for region in regions {
for document in region
.descendants()
.filter(|n| n.kind() == SyntaxKind::YAML_DOCUMENT)
{
let mut anchors = Vec::new();
let mut used = HashSet::new();
for token in document
.descendants_with_tokens()
.filter_map(|el| el.into_token())
{
match token.kind() {
SyntaxKind::YAML_ANCHOR => anchors.push(AnchorOccurrence {
name: strip_sigil(token.text()).to_string(),
range: token.text_range(),
}),
SyntaxKind::YAML_ALIAS => {
used.insert(strip_sigil(token.text()).to_string());
}
_ => {}
}
}
if !anchors.is_empty() {
docs.push(DocumentAnchors { anchors, used });
}
}
}
docs
}
fn strip_sigil(text: &str) -> &str {
text.strip_prefix('&')
.or_else(|| text.strip_prefix('*'))
.unwrap_or(text)
}