From 0cbdc67f06d549d13c46f34e857113389237df5d Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Wed, 13 May 2020 01:32:29 -0400 Subject: [PATCH] improve scoping with regard to function variables existing --- src/args.rs | 13 +++++++++++++ src/atrule/function.rs | 35 ++++++++++++++++------------------- tests/scope.rs | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/args.rs b/src/args.rs index 0168c0a..6d518dd 100644 --- a/src/args.rs +++ b/src/args.rs @@ -127,6 +127,19 @@ impl CallArgs { } } + pub fn get( + &mut self, + position: usize, + name: String, + scope: &Scope, + super_selector: &Selector, + ) -> Option>> { + match self.get_named(name, scope, super_selector) { + Some(v) => return Some(v), + None => return self.get_positional(position, scope, super_selector), + } + } + pub fn get_variadic( self, scope: &Scope, diff --git a/src/atrule/function.rs b/src/atrule/function.rs index 5c81975..d0fbc56 100644 --- a/src/atrule/function.rs +++ b/src/atrule/function.rs @@ -69,11 +69,11 @@ impl Function { super_selector: &Selector, ) -> SassResult<()> { let mut scope = scope.clone(); - for (idx, arg) in self.args.0.iter().enumerate() { + for (idx, arg) in self.args.0.iter_mut().enumerate() { if arg.is_variadic { let span = args.span(); let arg_list = Value::ArgList(args.get_variadic(&scope, super_selector)?); - scope.insert_var( + self.scope.insert_var( &arg.name, Spanned { node: arg_list, @@ -82,27 +82,24 @@ impl Function { )?; break; } - let val = match args.get_positional(idx, &scope, super_selector) { + let val = match args.get(idx, arg.name.clone(), &scope, super_selector) { Some(v) => v?, - None => match args.get_named(arg.name.clone(), &scope, super_selector) { - Some(v) => v?, - None => match &arg.default { - Some(v) => Value::from_tokens( - &mut v.iter().cloned().peekmore(), - &scope, - super_selector, - )?, - None => { - return Err( - (format!("Missing argument ${}.", &arg.name), args.span()).into() - ) - } - }, + None => match arg.default.as_mut() { + Some(v) => Value::from_tokens( + &mut std::mem::take(v).into_iter().peekmore(), + &scope, + super_selector, + )?, + None => { + return Err( + (format!("Missing argument ${}.", &arg.name), args.span()).into() + ) + } }, }; - scope.insert_var(&arg.name, val)?; + scope.insert_var(&arg.name, val.clone())?; + self.scope.insert_var(&arg.name, val)?; } - self.scope.extend(scope); Ok(()) } diff --git a/tests/scope.rs b/tests/scope.rs index 24327f5..3b5fe14 100644 --- a/tests/scope.rs +++ b/tests/scope.rs @@ -23,3 +23,20 @@ test!( "$y: a;\n@mixin foo {\n $y: b !global;\n}\na {\n @include foo;\n color: $y;\n}\n", "a {\n color: b;\n}\n" ); +test!( + local_variable_exists_in_fn_mixin_scope, + "@function exists-fn($name) { + @return variable-exists($name); + } + + @mixin exists-mixin($name) { + color: variable-exists($name); + } + + a { + $x: foo; + @include exists-mixin(x); + color: exists-fn(x); + }", + "a {\n color: false;\n color: false;\n}\n" +);