use rlsp_yaml_parser::node::{Document, Node};
use rlsp_yaml_parser::{ScalarStyle, Span};
use super::comment_preservation::{Comment, find_comment_on_line};
pub(super) struct ContentEntry {
pub(super) signature: String,
pub(super) blank_lines_before: usize,
pub(super) leading: Vec<String>,
}
pub(super) fn content_signature(line: &str) -> String {
if let Some((byte_pos, _)) = find_comment_on_line(line) {
line[..byte_pos].trim().to_string()
} else {
line.trim().to_string()
}
}
pub(super) fn last_content_line_from_ast(docs: &[Document<Span>]) -> Option<usize> {
fn node_last_content_line(
node: &Node<Span>,
idx: &rlsp_yaml_parser::LineIndex,
) -> Option<usize> {
match node {
Node::Scalar {
style: ScalarStyle::Literal(_) | ScalarStyle::Folded(_),
loc,
value,
..
} => {
let start_0 = idx.line_column(loc.start).0.saturating_sub(1) as usize;
let line_count = value.lines().count();
Some(start_0 + line_count.saturating_sub(1))
}
Node::Scalar { loc, .. } | Node::Alias { loc, .. } => {
Some(idx.line_column(loc.start).0.saturating_sub(1) as usize)
}
Node::Mapping { entries, .. } => entries
.iter()
.flat_map(|(k, v)| {
[
node_last_content_line(k, idx),
node_last_content_line(v, idx),
]
})
.flatten()
.max(),
Node::Sequence { items, .. } => items
.iter()
.filter_map(|n| node_last_content_line(n, idx))
.max(),
}
}
docs.iter()
.filter_map(|doc| node_last_content_line(&doc.root, doc.line_index()))
.max()
}
pub(super) fn last_content_line_idx(
original: &str,
line_to_comment: &std::collections::HashMap<usize, &Comment>,
) -> Option<usize> {
original
.lines()
.enumerate()
.filter(|(idx, line)| {
!line.trim().is_empty()
&& (!line.trim_start().starts_with('#') || line_to_comment.contains_key(idx))
})
.map(|(idx, _)| idx)
.last()
}