From e1d9e5cfffc22525a1c1aee5ee5d94d63dc361ce Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Mon, 29 Aug 2022 14:07:53 +0200 Subject: [PATCH] Add check for duplicate variable definition (fixes #320) --- crates/yuck/src/config/config.rs | 19 +++++++++++++++++-- crates/yuck/src/config/validate.rs | 4 ++++ crates/yuck/src/format_diagnostic.rs | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/crates/yuck/src/config/config.rs b/crates/yuck/src/config/config.rs index 71d84bf..3ec6fe7 100644 --- a/crates/yuck/src/config/config.rs +++ b/crates/yuck/src/config/config.rs @@ -9,6 +9,7 @@ use simplexpr::SimplExpr; use super::{ file_provider::{FilesError, YuckFiles}, script_var_definition::ScriptVarDefinition, + validate::ValidationError, var_definition::VarDefinition, widget_definition::WidgetDefinition, widget_use::WidgetUse, @@ -91,10 +92,24 @@ impl Config { fn append_toplevel(&mut self, files: &mut YuckFiles, toplevel: TopLevel) -> AstResult<()> { match toplevel { TopLevel::VarDefinition(x) => { - self.var_definitions.insert(x.name.clone(), x); + if self.var_definitions.contains_key(&x.name) || self.script_vars.contains_key(&x.name) { + return Err(AstError::ValidationError(ValidationError::VariableDefinedTwice { + name: x.name.clone(), + span: x.span, + })); + } else { + self.var_definitions.insert(x.name.clone(), x); + } } TopLevel::ScriptVarDefinition(x) => { - self.script_vars.insert(x.name().clone(), x); + if self.var_definitions.contains_key(x.name()) || self.script_vars.contains_key(x.name()) { + return Err(AstError::ValidationError(ValidationError::VariableDefinedTwice { + name: x.name().clone(), + span: x.name_span(), + })); + } else { + self.script_vars.insert(x.name().clone(), x); + } } TopLevel::WidgetDefinition(x) => { self.widget_definitions.insert(x.name.clone(), x); diff --git a/crates/yuck/src/config/validate.rs b/crates/yuck/src/config/validate.rs index d165449..0e3967d 100644 --- a/crates/yuck/src/config/validate.rs +++ b/crates/yuck/src/config/validate.rs @@ -32,12 +32,16 @@ pub enum ValidationError { /// True if the error occurred inside a widget definition, false if it occurred in a window definition in_definition: bool, }, + + #[error("Variable named `{name}` defined twice")] + VariableDefinedTwice { span: Span, name: VarName }, } impl Spanned for ValidationError { fn span(&self) -> Span { match self { ValidationError::UnknownWidget(span, _) => *span, + ValidationError::VariableDefinedTwice { span, .. } => *span, ValidationError::MissingAttr { use_span, .. } => *use_span, ValidationError::UnknownVariable { span, .. } => *span, ValidationError::AccidentalBuiltinOverride(span, ..) => *span, diff --git a/crates/yuck/src/format_diagnostic.rs b/crates/yuck/src/format_diagnostic.rs index ce7d627..a7abf9c 100644 --- a/crates/yuck/src/format_diagnostic.rs +++ b/crates/yuck/src/format_diagnostic.rs @@ -199,6 +199,10 @@ impl ToDiagnostic for ValidationError { label = span => "Defined here", note = "Hint: Give your widget a different name. You could call it \"John\" for example. That's a cool name." }, + ValidationError::VariableDefinedTwice { span, name } => gen_diagnostic! { + msg = self, + label = span => "Defined again here" + }, } } }