summaryrefslogtreecommitdiff
path: root/src/diagnostics/top_level_character_data.rs
blob: 5deb595d95e720fd91a2cdfb70f5f88c1033c2fe (plain)
use miette::Diagnostic;
use thiserror::Error;

use crate::{
	diagnostics::AstDiagnostic,
	parse::Node,
	tokenize::{Span, TokenType},
};

#[derive(Error, Debug, Diagnostic)]
#[error("Top-level character data is present")]
#[diagnostic(code(TopLevelCharacterData), severity(Error))]
pub struct TopLevelCharacterData {
	#[label(collection)]
	nodes: Vec<Span>,
}

impl AstDiagnostic for TopLevelCharacterData {
	fn handle_document(document: &crate::parse::Document<'_>) -> Option<Self> {
		let cdata_nodes = document
			.children
			.iter()
			.filter_map(|node| {
				if let Node::CharacterData(token) = node
					&& let TokenType::Data(data) = token.ty
					&& data.chars().any(|c| !c.is_whitespace())
				{
					Some(token.span)
				} else {
					None
				}
			})
			.collect::<Vec<_>>();

		if cdata_nodes.is_empty() {
			return None;
		}

		Some(Self { nodes: cdata_nodes })
	}
}