use super::error::{Diagnostic, SemanticDiagnostic};
use super::grammar_names::GrammarNames;
use super::line_index::LineIndex;
use crate::parse::engine::ParseOutput;
use crate::parse::insn::LiteralTable;
use crate::tree::red::SyntaxNode;
use crate::types::{Pos, Span};
#[derive(Debug)]
pub struct ParsedDoc {
source: Vec<u8>,
line_index: LineIndex,
root: SyntaxNode,
}
impl ParsedDoc {
#[must_use]
pub fn new(source: Vec<u8>, output: &ParseOutput) -> Option<Self> {
let line_index = LineIndex::new(&source);
let root = output.syntax_root(&source)?;
Some(Self {
source,
line_index,
root,
})
}
#[must_use]
pub fn from_slice(source: &[u8], output: &ParseOutput) -> Option<Self> {
Self::new(source.to_vec(), output)
}
#[inline]
#[must_use]
pub const fn root(&self) -> &SyntaxNode {
&self.root
}
#[inline]
#[must_use]
pub fn source(&self) -> &[u8] {
&self.source
}
#[inline]
#[must_use]
pub fn source_str(&self) -> &str {
std::str::from_utf8(&self.source).unwrap_or("")
}
#[inline]
#[must_use]
pub const fn line_index(&self) -> &LineIndex {
&self.line_index
}
#[inline]
#[must_use]
pub fn offset_to_line_col(&self, offset: Pos) -> (u32, u32) {
self.line_index.line_col(offset)
}
#[inline]
#[must_use]
pub fn offset_to_line_col_1based(&self, offset: Pos) -> (u32, u32) {
self.line_index.line_col_1based(offset)
}
#[inline]
#[must_use]
pub fn snippet_at(&self, offset: Pos) -> String {
self.line_index.snippet_at(&self.source, offset)
}
#[must_use]
pub fn format_diagnostic(
&self,
diagnostic: &Diagnostic,
literals: Option<&LiteralTable<'_>>,
names: Option<&dyn GrammarNames>,
) -> String {
diagnostic.format_with_source(&self.source, &self.line_index, literals, names)
}
#[inline]
#[must_use]
pub fn span_slice(&self, span: Span) -> &[u8] {
span.as_slice(&self.source)
}
#[must_use]
pub fn format_semantic_diagnostic(&self, diagnostic: &SemanticDiagnostic) -> String {
diagnostic.format_with_source(&self.source, &self.line_index)
}
#[inline]
#[must_use]
pub fn node_at_offset(&self, offset: Pos) -> Option<SyntaxNode> {
self.root.node_at_offset(offset)
}
#[inline]
#[must_use]
pub fn token_at_offset(&self, offset: Pos) -> Option<crate::tree::red::SyntaxToken> {
self.root.token_at_offset(offset)
}
#[cfg(feature = "utf16")]
#[inline]
#[must_use]
pub fn offset_to_line_col_utf16(&self, offset: Pos) -> (u32, u32) {
self.line_index.line_col_utf16(self.source_str(), offset)
}
#[cfg(feature = "utf16")]
#[inline]
#[must_use]
pub fn offset_to_line_col_utf16_1based(&self, offset: Pos) -> (u32, u32) {
self.line_index
.line_col_utf16_1based(self.source_str(), offset)
}
#[cfg(feature = "utf16")]
#[inline]
#[must_use]
pub fn span_to_utf16_range(&self, span: Span) -> (u32, u32) {
super::utf16::span_to_utf16_range(span, self.source_str())
}
}