Add check for duplicate variable definition (fixes #320)

This commit is contained in:
elkowar 2022-08-29 14:07:53 +02:00
parent eba1c032ae
commit e1d9e5cfff
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
3 changed files with 25 additions and 2 deletions

View file

@ -9,6 +9,7 @@ use simplexpr::SimplExpr;
use super::{ use super::{
file_provider::{FilesError, YuckFiles}, file_provider::{FilesError, YuckFiles},
script_var_definition::ScriptVarDefinition, script_var_definition::ScriptVarDefinition,
validate::ValidationError,
var_definition::VarDefinition, var_definition::VarDefinition,
widget_definition::WidgetDefinition, widget_definition::WidgetDefinition,
widget_use::WidgetUse, widget_use::WidgetUse,
@ -91,10 +92,24 @@ impl Config {
fn append_toplevel(&mut self, files: &mut YuckFiles, toplevel: TopLevel) -> AstResult<()> { fn append_toplevel(&mut self, files: &mut YuckFiles, toplevel: TopLevel) -> AstResult<()> {
match toplevel { match toplevel {
TopLevel::VarDefinition(x) => { 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) => { 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) => { TopLevel::WidgetDefinition(x) => {
self.widget_definitions.insert(x.name.clone(), x); self.widget_definitions.insert(x.name.clone(), x);

View file

@ -32,12 +32,16 @@ pub enum ValidationError {
/// True if the error occurred inside a widget definition, false if it occurred in a window definition /// True if the error occurred inside a widget definition, false if it occurred in a window definition
in_definition: bool, in_definition: bool,
}, },
#[error("Variable named `{name}` defined twice")]
VariableDefinedTwice { span: Span, name: VarName },
} }
impl Spanned for ValidationError { impl Spanned for ValidationError {
fn span(&self) -> Span { fn span(&self) -> Span {
match self { match self {
ValidationError::UnknownWidget(span, _) => *span, ValidationError::UnknownWidget(span, _) => *span,
ValidationError::VariableDefinedTwice { span, .. } => *span,
ValidationError::MissingAttr { use_span, .. } => *use_span, ValidationError::MissingAttr { use_span, .. } => *use_span,
ValidationError::UnknownVariable { span, .. } => *span, ValidationError::UnknownVariable { span, .. } => *span,
ValidationError::AccidentalBuiltinOverride(span, ..) => *span, ValidationError::AccidentalBuiltinOverride(span, ..) => *span,

View file

@ -199,6 +199,10 @@ impl ToDiagnostic for ValidationError {
label = span => "Defined here", label = span => "Defined here",
note = "Hint: Give your widget a different name. You could call it \"John\" for example. That's a cool name." 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"
},
} }
} }
} }