modules contain their own module scope

This commit is contained in:
Connor Skees 2021-07-31 10:53:25 -04:00
parent d101a36f0c
commit a7999d2e5b
4 changed files with 40 additions and 8 deletions

View File

@ -25,6 +25,9 @@ mod string;
pub(crate) struct Module { pub(crate) struct Module {
pub scope: Scope, pub scope: Scope,
/// A module can itself import other modules
pub modules: Modules,
/// Whether or not this module is builtin /// Whether or not this module is builtin
/// e.g. `"sass:math"` /// e.g. `"sass:math"`
is_builtin: bool, is_builtin: bool,
@ -103,12 +106,17 @@ impl Modules {
.into()), .into()),
} }
} }
pub fn merge(&mut self, other: Self) {
self.0.extend(other.0);
}
} }
impl Module { impl Module {
pub fn new_builtin() -> Self { pub fn new_builtin() -> Self {
Module { Module {
scope: Scope::default(), scope: Scope::default(),
modules: Modules::default(),
is_builtin: true, is_builtin: true,
} }
} }
@ -238,8 +246,12 @@ impl Module {
) )
} }
pub const fn new_from_scope(scope: Scope, is_builtin: bool) -> Self { pub const fn new_from_scope(scope: Scope, modules: Modules, is_builtin: bool) -> Self {
Module { scope, is_builtin } Module {
scope,
modules,
is_builtin,
}
} }
} }

View File

@ -124,6 +124,8 @@ impl<'a, 'b> Parser<'a, 'b> {
.map .map
.add_file(name.to_owned(), String::from_utf8(fs::read(&import)?)?); .add_file(name.to_owned(), String::from_utf8(fs::read(&import)?)?);
let mut modules = Modules::default();
let stmts = Parser { let stmts = Parser {
toks: &mut Lexer::new_from_file(&file), toks: &mut Lexer::new_from_file(&file),
map: self.map, map: self.map,
@ -139,7 +141,7 @@ impl<'a, 'b> Parser<'a, 'b> {
extender: self.extender, extender: self.extender,
content_scopes: self.content_scopes, content_scopes: self.content_scopes,
options: self.options, options: self.options,
modules: &mut Modules::default(), modules: &mut modules,
module_config: config, module_config: config,
} }
.parse()?; .parse()?;
@ -152,7 +154,7 @@ impl<'a, 'b> Parser<'a, 'b> {
.into()); .into());
} }
(Module::new_from_scope(global_scope, false), stmts) (Module::new_from_scope(global_scope, modules, false), stmts)
} else { } else {
return Err(("Can't find stylesheet to import.", self.span_before).into()); return Err(("Can't find stylesheet to import.", self.span_before).into());
} }
@ -226,7 +228,8 @@ impl<'a, 'b> Parser<'a, 'b> {
let module_name = match module_alias.as_deref() { let module_name = match module_alias.as_deref() {
Some("*") => { Some("*") => {
self.global_scope.merge_module(module); self.modules.merge(module.modules);
self.global_scope.merge_module_scope(module.scope);
continue; continue;
} }
Some(..) => module_alias.unwrap(), Some(..) => module_alias.unwrap(),

View File

@ -4,7 +4,7 @@ use codemap::Spanned;
use crate::{ use crate::{
atrule::mixin::Mixin, atrule::mixin::Mixin,
builtin::{modules::Module, GLOBAL_FUNCTIONS}, builtin::GLOBAL_FUNCTIONS,
common::Identifier, common::Identifier,
error::SassResult, error::SassResult,
value::{SassFunction, Value}, value::{SassFunction, Value},
@ -87,8 +87,8 @@ impl Scope {
self.functions.extend(other.functions); self.functions.extend(other.functions);
} }
pub fn merge_module(&mut self, other: Module) { pub fn merge_module_scope(&mut self, other: Scope) {
self.merge(other.scope); self.merge(other);
} }
pub fn default_var_exists(&self, s: Identifier) -> bool { pub fn default_var_exists(&self, s: Identifier) -> bool {

View File

@ -330,6 +330,23 @@ fn use_cannot_see_modules_imported_by_other_modules() {
assert_err!("Error: There is no module with the namespace \"a\".", input); assert_err!("Error: There is no module with the namespace \"a\".", input);
} }
#[test]
fn use_can_see_modules_imported_by_other_modules_when_aliased_as_star() {
let input = r#"
@use "use_can_see_modules_imported_by_other_modules_when_aliased_as_star__a" as *;
a { color: math.$e; }
"#;
tempfile!(
"use_can_see_modules_imported_by_other_modules_when_aliased_as_star__a.scss",
"@use \"sass:math\";"
);
assert_eq!(
"a {\n color: 2.7182818285;\n}\n",
&grass::from_string(input.to_string(), &grass::Options::default()).expect(input)
);
}
#[test] #[test]
fn use_modules_imported_by_other_modules_does_not_cause_conflict() { fn use_modules_imported_by_other_modules_does_not_cause_conflict() {