use crate::parse::token_ref::TokenRef;
use crate::parse::utils::convert_multiline_with_indentation;
use crate::syntax::Parsed;
use crate::syntax::SyntaxKind;
use crate::syntax::SyntaxNode;
use crate::text::TextRange;
#[derive(Debug, Clone, Copy)]
pub struct TextBlock<'a> {
pub(crate) parsed: &'a Parsed,
pub(crate) node: &'a SyntaxNode,
}
impl<'a> TextBlock<'a> {
pub const fn can_cast(kind: SyntaxKind) -> bool {
matches!(
kind,
SyntaxKind::SUMMARY | SyntaxKind::EXTENDED_SUMMARY | SyntaxKind::DESCRIPTION | SyntaxKind::PARAGRAPH
)
}
pub fn cast(parsed: &'a Parsed, node: &'a SyntaxNode) -> Option<Self> {
Self::can_cast(node.kind()).then_some(Self { parsed, node })
}
pub fn syntax(&self) -> &'a SyntaxNode {
self.node
}
pub fn range(&self) -> TextRange {
self.node.range()
}
pub fn is_missing(&self) -> bool {
self.node.range().is_empty()
}
pub fn lines(&self) -> impl Iterator<Item = TokenRef<'a>> {
let parsed = self.parsed;
self.node
.tokens(SyntaxKind::TEXT_LINE)
.map(move |t| TokenRef::new(parsed, t))
}
pub fn text(&self) -> &'a str {
self.node.range().source_text(self.parsed.source())
}
pub fn logical_text(&self) -> String {
convert_multiline_with_indentation(self.text())
}
}
pub(crate) fn find_text_block<'a>(parsed: &'a Parsed, node: &'a SyntaxNode, kind: SyntaxKind) -> Option<TextBlock<'a>> {
node.nodes(kind)
.find(|n| !n.range().is_empty())
.and_then(|n| TextBlock::cast(parsed, n))
}