summaryrefslogtreecommitdiff
path: root/src/diagnostics/duplicate_attribute_names.rs
blob: 542d8ec970236f2987f898aeee5bbac8651aa8da (plain)
use std::collections::HashMap;

use miette::Diagnostic;
use thiserror::Error;

use crate::{
	diagnostics::AstDiagnostic,
	parse::{Attribute, Element},
	tokenize::Span,
};

#[derive(Error, Debug, Diagnostic)]
#[error("Multiple attributes have the same name")]
#[diagnostic(code(DuplicateAttributeNames), severity(Error))]
pub struct DuplicateAttributeNames {
	#[label(collection)]
	duplicates: Vec<Span>,
}

impl AstDiagnostic for DuplicateAttributeNames {
	fn handle_element(element: &Element<'_>) -> Option<Self> {
		let mut seen_attributes = HashMap::<&str, Attribute<'_>>::new();
		for attribute in element.attributes {
			let Some(name) = attribute.name_lowercase() else {
				continue;
			};
			if let Some(duplicate) = seen_attributes.get(name) {
				return Some(Self {
					duplicates: vec![
						duplicate.name_token().expect("a named attribute").span,
						attribute.name_token().expect("a named attribute").span,
					],
				});
			}

			seen_attributes.insert(name, *attribute);
		}

		None
	}
}