respect $module argument to get-function

This commit is contained in:
Connor Skees 2020-07-30 17:46:56 -04:00
parent a03ad51b71
commit a7325436ca
8 changed files with 62 additions and 69 deletions

View File

@ -1,7 +1,5 @@
use super::{Builtin, GlobalFunctionMap, GLOBAL_FUNCTIONS};
use codemap::Spanned;
use crate::{
args::CallArgs,
common::{Identifier, QuoteKind},
@ -166,7 +164,8 @@ pub(crate) fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassR
}
};
if module.is_some() && css {
let func = match if let Some(module_name) = module {
if css {
return Err((
"$css and $module may not both be passed at once.",
args.span(),
@ -174,13 +173,13 @@ pub(crate) fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassR
.into());
}
let func = match parser.scopes.get_fn(
Spanned {
node: name,
span: args.span(),
},
parser.global_scope,
) {
parser
.modules
.get(module_name.into(), args.span())?
.get_fn(name)
} else {
parser.scopes.get_fn(name, parser.global_scope)
} {
Some(f) => f,
None => match GLOBAL_FUNCTIONS.get(name.as_str()) {
Some(f) => SassFunction::Builtin(f.clone(), name),

View File

@ -32,14 +32,7 @@ fn module_functions(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<V
};
Ok(Value::Map(
parser
.modules
.get(&module)
.ok_or((
format!("There is no module with the namespace \"{}\".", module),
args.span(),
))?
.functions(),
parser.modules.get(module.into(), args.span())?.functions(),
))
}
@ -58,14 +51,7 @@ fn module_variables(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<V
};
Ok(Value::Map(
parser
.modules
.get(&module)
.ok_or((
format!("There is no module with the namespace \"{}\".", module),
args.span(),
))?
.variables(),
parser.modules.get(module.into(), args.span())?.variables(),
))
}

View File

@ -2,7 +2,7 @@
use std::collections::BTreeMap;
use codemap::Spanned;
use codemap::{Span, Spanned};
use crate::{
args::CallArgs,
@ -26,6 +26,29 @@ mod string;
#[derive(Debug, Default)]
pub(crate) struct Module(pub Scope);
#[derive(Debug, Default)]
pub(crate) struct Modules(BTreeMap<Identifier, Module>);
impl Modules {
pub fn insert(&mut self, name: Identifier, module: Module) {
self.0.insert(name, module);
}
pub fn get(&self, name: Identifier, span: Span) -> SassResult<&Module> {
match self.0.get(&name) {
Some(v) => Ok(v),
None => Err((
format!(
"There is no module with the namespace \"{}\".",
name.as_str()
),
span,
)
.into()),
}
}
}
impl Module {
pub fn get_var(&self, name: Spanned<Identifier>) -> SassResult<&Value> {
match self.0.vars.get(&name.node) {

View File

@ -81,7 +81,7 @@ grass input.scss
)]
#![cfg_attr(feature = "nightly", feature(track_caller))]
#![cfg_attr(feature = "profiling", inline(never))]
use std::{collections::HashMap, fs, path::Path};
use std::{fs, path::Path};
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
@ -95,6 +95,7 @@ use peekmore::PeekMore;
pub use crate::error::{SassError as Error, SassResult as Result};
pub(crate) use crate::token::Token;
use crate::{
builtin::modules::Modules,
lexer::Lexer,
output::Css,
parse::{
@ -293,7 +294,7 @@ pub fn from_path(p: &str, options: &Options) -> Result<String> {
extender: &mut Extender::new(empty_span),
content_scopes: &mut Scopes::new(),
options,
modules: &mut HashMap::new(),
modules: &mut Modules::default(),
}
.parse()
.map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
@ -338,7 +339,7 @@ pub fn from_string(p: String, options: &Options) -> Result<String> {
extender: &mut Extender::new(empty_span),
content_scopes: &mut Scopes::new(),
options,
modules: &mut HashMap::new(),
modules: &mut Modules::default(),
}
.parse()
.map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
@ -374,7 +375,7 @@ pub fn from_string(p: String) -> std::result::Result<String, JsValue> {
extender: &mut Extender::new(empty_span),
content_scopes: &mut Scopes::new(),
options: &Options::default(),
modules: &mut HashMap::new(),
modules: &mut Modules::default(),
}
.parse()
.map_err(|e| raw_to_parse_error(&map, *e, true).to_string())?;

View File

@ -1,4 +1,4 @@
use std::{collections::HashMap, convert::TryFrom, fs, path::Path, vec::IntoIter};
use std::{convert::TryFrom, fs, path::Path, vec::IntoIter};
use codemap::{CodeMap, Span, Spanned};
use peekmore::{PeekMore, PeekMoreIterator};
@ -11,7 +11,7 @@ use crate::{
},
builtin::modules::{
declare_module_color, declare_module_list, declare_module_map, declare_module_math,
declare_module_meta, declare_module_selector, declare_module_string, Module,
declare_module_meta, declare_module_selector, declare_module_string, Module, Modules,
},
error::SassResult,
lexer::Lexer,
@ -92,7 +92,7 @@ pub(crate) struct Parser<'a> {
pub options: &'a Options<'a>,
pub modules: &'a mut HashMap<String, Module>,
pub modules: &'a mut Modules,
}
impl<'a> Parser<'a> {
@ -262,7 +262,7 @@ impl<'a> Parser<'a> {
},
};
self.modules.insert(module_name, module);
self.modules.insert(module_name.into(), module);
}
Some(Token { kind: '/', .. }) => {
self.toks.next();

View File

@ -261,14 +261,7 @@ impl<'a> Parser<'a> {
module_span = module_span.merge(var.span);
let value = self
.modules
.get(module)
.ok_or((
format!("There is no module with the namespace \"{}\".", module),
module_span,
))?
.get_var(var)?;
let value = self.modules.get(module.into(), module_span)?.get_var(var)?;
HigherIntermediateValue::Literal(value.clone())
} else {
let fn_name = self
@ -277,11 +270,7 @@ impl<'a> Parser<'a> {
let function = self
.modules
.get(module)
.ok_or((
format!("There is no module with the namespace \"{}\".", module),
module_span,
))?
.get(module.into(), module_span)?
.get_fn(fn_name.node)
.ok_or(("Undefined function.", fn_name.span))?;
@ -341,13 +330,7 @@ impl<'a> Parser<'a> {
}
let as_ident = Identifier::from(&s);
let func = match self.scopes.get_fn(
Spanned {
node: as_ident,
span,
},
self.global_scope,
) {
let func = match self.scopes.get_fn(as_ident, self.global_scope) {
Some(f) => f,
None => {
if let Some(f) = GLOBAL_FUNCTIONS.get(as_ident.as_str()) {

View File

@ -230,17 +230,13 @@ impl Scopes {
}
}
pub fn get_fn<'a>(
&'a self,
name: Spanned<Identifier>,
global_scope: &'a Scope,
) -> Option<SassFunction> {
pub fn get_fn<'a>(&'a self, name: Identifier, global_scope: &'a Scope) -> Option<SassFunction> {
for scope in self.0.iter().rev() {
if scope.fn_exists(name.node) {
return scope.get_fn(name.node);
if scope.fn_exists(name) {
return scope.get_fn(name);
}
}
global_scope.get_fn(name.node)
global_scope.get_fn(name)
}
pub fn fn_exists(&self, name: Identifier, global_scope: &Scope) -> bool {

View File

@ -121,3 +121,8 @@ test!(
"a {\n color: call(call(get-function(get-function), darken), red, 10%);\n}\n",
"a {\n color: #cc0000;\n}\n"
);
test!(
get_function_of_module,
"@use 'sass:math';\na {\n color: call(get-function(cos, $module: math), 2);\n}\n",
"a {\n color: -0.4161468365;\n}\n"
);