resolve merge conflicts with master
This commit is contained in:
commit
123ed80e9a
@ -26,6 +26,19 @@ impl Mixin {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Content {
|
pub(crate) struct Content {
|
||||||
|
/// The literal block, serialized as a list of tokens
|
||||||
pub content: Option<Vec<Token>>,
|
pub content: Option<Vec<Token>>,
|
||||||
|
|
||||||
|
/// Optional args, e.g. `@content(a, b, c);`
|
||||||
pub content_args: Option<FuncArgs>,
|
pub content_args: Option<FuncArgs>,
|
||||||
|
|
||||||
|
/// The number of scopes at the use of `@include`
|
||||||
|
///
|
||||||
|
/// This is used to "reset" back to the state of the `@include`
|
||||||
|
/// without actually cloning the scope or putting it in an `Rc`
|
||||||
|
pub scope_len: usize,
|
||||||
|
|
||||||
|
/// Whether or not the mixin this `@content` block is inside of was
|
||||||
|
/// declared in the global scope
|
||||||
|
pub declared_at_root: bool,
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use crate::{
|
|||||||
args::{CallArgs, FuncArgs},
|
args::{CallArgs, FuncArgs},
|
||||||
atrule::{Content, Mixin},
|
atrule::{Content, Mixin},
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
|
scope::Scopes,
|
||||||
utils::read_until_closing_curly_brace,
|
utils::read_until_closing_curly_brace,
|
||||||
Token,
|
Token,
|
||||||
};
|
};
|
||||||
@ -129,6 +130,8 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let scope = self.eval_args(fn_args, args)?;
|
let scope = self.eval_args(fn_args, args)?;
|
||||||
|
|
||||||
|
let scope_len = self.scopes.len();
|
||||||
|
|
||||||
if declared_at_root {
|
if declared_at_root {
|
||||||
mem::swap(self.scopes, self.content_scopes);
|
mem::swap(self.scopes, self.content_scopes);
|
||||||
}
|
}
|
||||||
@ -138,6 +141,8 @@ impl<'a> Parser<'a> {
|
|||||||
self.content.push(Content {
|
self.content.push(Content {
|
||||||
content,
|
content,
|
||||||
content_args,
|
content_args,
|
||||||
|
scope_len,
|
||||||
|
declared_at_root,
|
||||||
});
|
});
|
||||||
|
|
||||||
let body = Parser {
|
let body = Parser {
|
||||||
@ -178,26 +183,35 @@ impl<'a> Parser<'a> {
|
|||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(Token { kind: '(', .. }) = self.toks.peek() {
|
Ok(if let Some(content) = self.content.pop() {
|
||||||
self.toks.next();
|
let (mut scope_at_decl, mixin_scope) = if content.declared_at_root {
|
||||||
let args = self.parse_call_args()?;
|
(mem::take(self.content_scopes), Scopes::new())
|
||||||
if let Some(Some(content_args)) = self.content.last().map(|v| v.content_args.clone()) {
|
|
||||||
args.max_args(content_args.len())?;
|
|
||||||
|
|
||||||
let scope = self.eval_args(content_args, args)?;
|
|
||||||
self.content_scopes.merge(scope);
|
|
||||||
} else {
|
} else {
|
||||||
args.max_args(0)?;
|
mem::take(self.scopes).split_off(content.scope_len)
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
let mut entered_scope = false;
|
||||||
|
|
||||||
|
if let Some(Token { kind: '(', .. }) = self.toks.peek() {
|
||||||
|
self.toks.next();
|
||||||
|
let args = self.parse_call_args()?;
|
||||||
|
if let Some(ref content_args) = content.content_args {
|
||||||
|
args.max_args(content_args.len())?;
|
||||||
|
|
||||||
|
let scope = self.eval_args(content_args.clone(), args)?;
|
||||||
|
scope_at_decl.enter_scope(scope);
|
||||||
|
entered_scope = true;
|
||||||
|
} else {
|
||||||
|
args.max_args(0)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(if let Some(content) = &self.content.pop() {
|
|
||||||
let stmts = if let Some(body) = content.content.clone() {
|
let stmts = if let Some(body) = content.content.clone() {
|
||||||
Parser {
|
Parser {
|
||||||
toks: &mut body.into_iter().peekmore(),
|
toks: &mut body.into_iter().peekmore(),
|
||||||
map: self.map,
|
map: self.map,
|
||||||
path: self.path,
|
path: self.path,
|
||||||
scopes: self.content_scopes,
|
scopes: &mut scope_at_decl,
|
||||||
global_scope: self.global_scope,
|
global_scope: self.global_scope,
|
||||||
super_selectors: self.super_selectors,
|
super_selectors: self.super_selectors,
|
||||||
span_before: self.span_before,
|
span_before: self.span_before,
|
||||||
@ -214,8 +228,21 @@ impl<'a> Parser<'a> {
|
|||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
self.content.push(content.clone());
|
|
||||||
self.scopes.exit_scope();
|
if entered_scope {
|
||||||
|
scope_at_decl.exit_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_at_decl.merge(mixin_scope);
|
||||||
|
|
||||||
|
if content.declared_at_root {
|
||||||
|
*self.content_scopes = scope_at_decl;
|
||||||
|
} else {
|
||||||
|
*self.scopes = scope_at_decl;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.content.push(content);
|
||||||
|
|
||||||
stmts
|
stmts
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
17
src/scope.rs
17
src/scope.rs
@ -93,6 +93,15 @@ impl Scopes {
|
|||||||
Self(Vec::new())
|
Self(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn split_off(mut self, len: usize) -> (Scopes, Scopes) {
|
||||||
|
let split = self.0.split_off(len);
|
||||||
|
(self, Scopes(split))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enter_new_scope(&mut self) {
|
pub fn enter_new_scope(&mut self) {
|
||||||
self.0.push(Scope::new());
|
self.0.push(Scope::new());
|
||||||
}
|
}
|
||||||
@ -105,12 +114,8 @@ impl Scopes {
|
|||||||
self.0.pop();
|
self.0.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge(&mut self, other: Scope) {
|
pub fn merge(&mut self, mut other: Self) {
|
||||||
if let Some(scope) = self.0.last_mut() {
|
self.0.append(&mut other.0);
|
||||||
scope.merge(other)
|
|
||||||
} else {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,20 +381,20 @@ test!(
|
|||||||
"@mixin foo {
|
"@mixin foo {
|
||||||
color: foo;
|
color: foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@include foo();
|
@include foo();
|
||||||
|
|
||||||
@mixin foo {
|
@mixin foo {
|
||||||
color: bar;
|
color: bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@mixin foo {
|
@mixin foo {
|
||||||
color: baz;
|
color: baz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include foo();
|
@include foo();
|
||||||
}",
|
}",
|
||||||
"a {\n color: foo;\n color: bar;\n}\n"
|
"a {\n color: foo;\n color: bar;\n}\n"
|
||||||
@ -449,6 +449,84 @@ test!(
|
|||||||
}",
|
}",
|
||||||
"a {\n color: foo;\n color: foo;\n}\n"
|
"a {\n color: foo;\n color: foo;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
can_access_variables_declared_before_content,
|
||||||
|
"@mixin foo {
|
||||||
|
$a: red;
|
||||||
|
|
||||||
|
@content;
|
||||||
|
|
||||||
|
color: $a;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@include foo;
|
||||||
|
}",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
content_contains_variable_declared_in_outer_scope_not_declared_at_root,
|
||||||
|
"a {
|
||||||
|
$a: red;
|
||||||
|
|
||||||
|
@mixin foo {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include foo {
|
||||||
|
color: $a;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
content_contains_variable_declared_in_outer_scope_declared_at_root,
|
||||||
|
"@mixin foo {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
$a: red;
|
||||||
|
|
||||||
|
@include foo {
|
||||||
|
color: $a;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
content_contains_variable_declared_in_outer_scope_not_declared_at_root_and_modified,
|
||||||
|
"a {
|
||||||
|
$a: red;
|
||||||
|
|
||||||
|
@mixin foo {
|
||||||
|
$a: green;
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include foo {
|
||||||
|
color: $a;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"a {\n color: green;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
content_contains_variable_declared_in_outer_scope_declared_at_root_and_modified,
|
||||||
|
"@mixin foo {
|
||||||
|
$a: green;
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
$a: red;
|
||||||
|
|
||||||
|
|
||||||
|
@include foo {
|
||||||
|
color: $a;
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
error!(
|
error!(
|
||||||
mixin_in_function,
|
mixin_in_function,
|
||||||
"@function foo() {
|
"@function foo() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user