From 94becb4dcb8cfd896efe8a7812e855445652bcd3 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Thu, 6 Aug 2020 04:00:45 -0400 Subject: [PATCH] implement idempotency with regard to module aliasing --- src/builtin/modules/mod.rs | 12 +++++++++++- src/parse/mod.rs | 2 +- tests/use.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/builtin/modules/mod.rs b/src/builtin/modules/mod.rs index 555aeff..708bbbe 100644 --- a/src/builtin/modules/mod.rs +++ b/src/builtin/modules/mod.rs @@ -28,8 +28,18 @@ pub(crate) struct Module(pub Scope); pub(crate) struct Modules(BTreeMap); impl Modules { - pub fn insert(&mut self, name: Identifier, module: Module) { + pub fn insert(&mut self, name: Identifier, module: Module, span: Span) -> SassResult<()> { + if self.0.contains_key(&name) { + return Err(( + format!("There's already a module with namespace \"{}\".", name), + span, + ) + .into()); + } + self.0.insert(name, module); + + Ok(()) } pub fn get(&self, name: Identifier, span: Span) -> SassResult<&Module> { diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 1d5bab7..45b67ca 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -263,7 +263,7 @@ impl<'a> Parser<'a> { }, }; - self.modules.insert(module_name.into(), module); + self.modules.insert(module_name.into(), module, span)?; } Some(Token { kind: '/', .. }) => { self.toks.next(); diff --git a/tests/use.rs b/tests/use.rs index f5e1b3f..d30af39 100644 --- a/tests/use.rs +++ b/tests/use.rs @@ -158,3 +158,36 @@ fn use_user_defined_function() { &grass::from_string(input.to_string(), &grass::Options::default()).expect(input) ); } + +#[test] +fn use_idempotent_no_alias() { + let input = "@use \"use_idempotent_no_alias\";\n@use \"use_idempotent_no_alias\";\n"; + tempfile!("use_idempotent_no_alias.scss", ""); + + assert_err!( + "Error: There's already a module with namespace \"use-idempotent-no-alias\".", + input + ); +} + +#[test] +fn use_idempotent_with_alias() { + let input = "@use \"use_idempotent_with_alias__a\" as foo;\n@use \"use_idempotent_with_alias__b\" as foo;\n"; + tempfile!("use_idempotent_with_alias__a.scss", ""); + tempfile!("use_idempotent_with_alias__b.scss", ""); + + assert_err!( + "Error: There's already a module with namespace \"foo\".", + input + ); +} + +#[test] +fn use_idempotent_builtin() { + let input = "@use \"sass:math\";\n@use \"sass:math\";\n"; + + assert_err!( + "Error: There's already a module with namespace \"math\".", + input + ); +}