From cfd2e00ebb9f0f76642df5fcccee25a74edd5f7f Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Thu, 30 Jul 2020 18:35:34 -0400 Subject: [PATCH] respect `$module` argument to `mixin-exists` --- src/builtin/functions/meta.rs | 42 ++++++++++++++++++++++++++--------- src/builtin/modules/mod.rs | 4 ++++ src/scope.rs | 2 +- tests/meta-module.rs | 12 ++++++++++ 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/builtin/functions/meta.rs b/src/builtin/functions/meta.rs index 858f829..917ee35 100644 --- a/src/builtin/functions/meta.rs +++ b/src/builtin/functions/meta.rs @@ -110,19 +110,39 @@ pub(crate) fn global_variable_exists( } } -// todo: should check for module arg (as well as several others) pub(crate) fn mixin_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult { args.max_args(2)?; - match args.get_err(0, "name")? { - Value::String(s, _) => Ok(Value::bool( - parser.scopes.mixin_exists(s.into(), parser.global_scope), - )), - v => Err(( - format!("$name: {} is not a string.", v.inspect(args.span())?), - args.span(), - ) - .into()), - } + let name: Identifier = match args.get_err(0, "name")? { + Value::String(s, _) => s.into(), + v => { + return Err(( + format!("$name: {} is not a string.", v.inspect(args.span())?), + args.span(), + ) + .into()) + } + }; + + let module = match args.default_arg(1, "module", Value::Null)? { + Value::String(s, _) => Some(s), + Value::Null => None, + v => { + return Err(( + format!("$module: {} is not a string.", v.inspect(args.span())?), + args.span(), + ) + .into()) + } + }; + + Ok(Value::bool(if let Some(module_name) = module { + parser + .modules + .get(module_name.into(), args.span())? + .mixin_exists(name) + } else { + parser.scopes.mixin_exists(name, parser.global_scope) + })) } pub(crate) fn function_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult { diff --git a/src/builtin/modules/mod.rs b/src/builtin/modules/mod.rs index 30f153e..21e6d6c 100644 --- a/src/builtin/modules/mod.rs +++ b/src/builtin/modules/mod.rs @@ -65,6 +65,10 @@ impl Module { self.0.functions.get(&name).cloned() } + pub fn mixin_exists(&self, name: Identifier) -> bool { + self.0.mixin_exists(name) + } + pub fn insert_builtin( &mut self, name: &'static str, diff --git a/src/scope.rs b/src/scope.rs index ddf3340..7583151 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -55,7 +55,7 @@ impl Scope { self.mixins.insert(s.into(), v) } - fn mixin_exists(&self, name: Identifier) -> bool { + pub fn mixin_exists(&self, name: Identifier) -> bool { self.mixins.contains_key(&name) } diff --git a/tests/meta-module.rs b/tests/meta-module.rs index da5b626..5e3310b 100644 --- a/tests/meta-module.rs +++ b/tests/meta-module.rs @@ -1,5 +1,7 @@ #![cfg(test)] +use std::io::Write; + #[macro_use] mod macros; @@ -13,3 +15,13 @@ test!( "@use 'sass:meta';\n@use 'sass:math';\na {\n color: inspect(meta.module-variables(math));\n}\n", "a {\n color: (\"e\": 2.7182818285, \"pi\": 3.1415926536);\n}\n" ); + +#[test] +fn mixin_exists_module() { + let input = "@use \"mixin_exists_module\" as module;\na {\n color: mixin-exists(foo, $module: module);\n}"; + tempfile!("mixin_exists_module.scss", "@mixin foo {}"); + assert_eq!( + "a {\n color: true;\n}\n", + &grass::from_string(input.to_string(), &grass::Options::default()).expect(input) + ); +}