fix(wgsl-in): yield conflict errors for full diagnostic(…) rule dupes in attr. pos.

This commit is contained in:
Erich Gubler 2024-11-14 09:42:38 -05:00
parent 3018912897
commit ed29b2b758
3 changed files with 34 additions and 11 deletions

View File

@ -86,6 +86,18 @@ pub struct DiagnosticFilter {
pub triggering_rule: FilterableTriggeringRule, pub triggering_rule: FilterableTriggeringRule,
} }
/// Determines whether [`DiagnosticFilterMap::add`] should consider full duplicates a conflict.
///
/// In WGSL, directive position does not consider this case a conflict, while attribute position
/// does.
#[cfg(feature = "wgsl-in")]
pub(crate) enum ShouldConflictOnFullDuplicate {
/// Use this for attributes in WGSL.
Yes,
/// Use this for directives in WGSL.
No,
}
/// A map of diagnostic filters to their severity and first occurrence's span. /// A map of diagnostic filters to their severity and first occurrence's span.
/// ///
/// Intended for front ends' first step into storing parsed [`DiagnosticFilter`]s. /// Intended for front ends' first step into storing parsed [`DiagnosticFilter`]s.
@ -104,6 +116,7 @@ impl DiagnosticFilterMap {
&mut self, &mut self,
diagnostic_filter: DiagnosticFilter, diagnostic_filter: DiagnosticFilter,
span: Span, span: Span,
should_conflict_on_full_duplicate: ShouldConflictOnFullDuplicate,
) -> Result<(), ConflictingDiagnosticRuleError> { ) -> Result<(), ConflictingDiagnosticRuleError> {
use indexmap::map::Entry; use indexmap::map::Entry;
@ -119,7 +132,11 @@ impl DiagnosticFilterMap {
} }
Entry::Occupied(entry) => { Entry::Occupied(entry) => {
let &(first_severity, first_span) = entry.get(); let &(first_severity, first_span) = entry.get();
if first_severity != new_severity { let should_conflict_on_full_duplicate = match should_conflict_on_full_duplicate {
ShouldConflictOnFullDuplicate::Yes => true,
ShouldConflictOnFullDuplicate::No => false,
};
if first_severity != new_severity || should_conflict_on_full_duplicate {
return Err(ConflictingDiagnosticRuleError { return Err(ConflictingDiagnosticRuleError {
triggering_rule, triggering_rule,
triggering_rule_spans: [first_span, span], triggering_rule_spans: [first_span, span],

View File

@ -1047,13 +1047,14 @@ impl<'a> Error<'a> {
(first_span, "first rule".into()), (first_span, "first rule".into()),
(second_span, "second rule".into()), (second_span, "second rule".into()),
], ],
notes: vec![concat!( notes: vec![
"multiple `diagnostic(…)` rules with the same rule name ", concat!(
"conflict unless the severity is the same; ", "Multiple `diagnostic(…)` rules with the same rule name ",
"delete the rule you don't want, or ", "conflict unless it is a directive and the severity is the same.",
"ensure that all severities with the same rule name match" )
) .into(),
.into()], "You should delete the rule you don't want.".into(),
],
} }
} }
Error::DiagnosticAttributeNotYetImplementedAtParseSite { Error::DiagnosticAttributeNotYetImplementedAtParseSite {

View File

@ -1,5 +1,6 @@
use crate::diagnostic_filter::{ use crate::diagnostic_filter::{
self, DiagnosticFilter, DiagnosticFilterMap, DiagnosticFilterNode, FilterableTriggeringRule, self, DiagnosticFilter, DiagnosticFilterMap, DiagnosticFilterNode, FilterableTriggeringRule,
ShouldConflictOnFullDuplicate,
}; };
use crate::front::wgsl::error::{Error, ExpectedToken}; use crate::front::wgsl::error::{Error, ExpectedToken};
use crate::front::wgsl::parse::directive::enable_extension::{ use crate::front::wgsl::parse::directive::enable_extension::{
@ -2167,7 +2168,7 @@ impl Parser {
if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) { if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) {
if let Some(filter) = self.diagnostic_filter(lexer)? { if let Some(filter) = self.diagnostic_filter(lexer)? {
let span = self.peek_rule_span(lexer); let span = self.peek_rule_span(lexer);
diagnostic_filters.add(filter, span)?; diagnostic_filters.add(filter, span, ShouldConflictOnFullDuplicate::Yes)?;
} }
} else { } else {
return Err(Error::Unexpected( return Err(Error::Unexpected(
@ -2369,7 +2370,7 @@ impl Parser {
if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) { if let Some(DirectiveKind::Diagnostic) = DirectiveKind::from_ident(name) {
if let Some(filter) = self.diagnostic_filter(lexer)? { if let Some(filter) = self.diagnostic_filter(lexer)? {
let span = self.peek_rule_span(lexer); let span = self.peek_rule_span(lexer);
diagnostic_filters.add(filter, span)?; diagnostic_filters.add(filter, span, ShouldConflictOnFullDuplicate::Yes)?;
} }
continue; continue;
} }
@ -2602,7 +2603,11 @@ impl Parser {
DirectiveKind::Diagnostic => { DirectiveKind::Diagnostic => {
if let Some(diagnostic_filter) = self.diagnostic_filter(&mut lexer)? { if let Some(diagnostic_filter) = self.diagnostic_filter(&mut lexer)? {
let span = self.peek_rule_span(&lexer); let span = self.peek_rule_span(&lexer);
diagnostic_filters.add(diagnostic_filter, span)?; diagnostic_filters.add(
diagnostic_filter,
span,
ShouldConflictOnFullDuplicate::No,
)?;
} }
lexer.expect(Token::Separator(';'))?; lexer.expect(Token::Separator(';'))?;
} }