use tower_lsp::lsp_types::{DocumentHighlight, DocumentHighlightKind, Position, Range};
use crate::ast::ParsedDoc;
use crate::util::word_at_position;
use crate::walk::{collect_var_refs_in_scope, refs_in_stmts};
pub fn document_highlights(
source: &str,
doc: &ParsedDoc,
position: Position,
) -> Vec<DocumentHighlight> {
let word = match word_at_position(source, position) {
Some(w) => w,
None => return vec![],
};
let word_utf16_len: u32 = word.chars().map(|c| c.len_utf16() as u32).sum();
let sv = doc.view();
if word.starts_with('$') {
let bare = word.trim_start_matches('$');
let byte_off = sv.byte_of_position(position) as usize;
let mut var_spans = Vec::new();
collect_var_refs_in_scope(&doc.program().stmts, bare, byte_off, &mut var_spans);
var_spans
.into_iter()
.map(|(span, kind)| {
let start = sv.position_of(span.start);
let end = Position {
line: start.line,
character: start.character + word_utf16_len,
};
DocumentHighlight {
range: Range { start, end },
kind: Some(kind),
}
})
.collect()
} else {
let mut spans = Vec::new();
refs_in_stmts(doc.source(), &doc.program().stmts, &word, &mut spans);
spans
.into_iter()
.map(|span| {
let start = sv.position_of(span.start);
let end = Position {
line: start.line,
character: start.character + word_utf16_len,
};
DocumentHighlight {
range: Range { start, end },
kind: Some(DocumentHighlightKind::TEXT),
}
})
.collect()
}
}