Skip to content

Commit

Permalink
More special cases for invalid rules.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaj committed Jun 12, 2022
1 parent b9e8c19 commit 321cd58
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 19 deletions.
10 changes: 10 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ pub enum Invalid {
FunctionName,
/// This at rule is not allowed here.
AtRule,
/// Mixins may not contain mixin declarations.
MixinInMixin,
/// "Mixins may not contain function declarations.
FunctionInMixin,
/// An `@error` reached.
AtError(String),
}
Expand All @@ -178,6 +182,12 @@ impl fmt::Display for Invalid {
}
Invalid::FunctionName => "Invalid function name.".fmt(out),
Invalid::AtRule => "This at-rule is not allowed here.".fmt(out),
Invalid::MixinInMixin => {
"Mixins may not contain mixin declarations.".fmt(out)
}
Invalid::FunctionInMixin => {
"Mixins may not contain function declarations.".fmt(out)
}
Invalid::AtError(msg) => msg.fmt(out),
}
}
Expand Down
53 changes: 38 additions & 15 deletions src/output/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ fn handle_item(
let p = pos.clone().opt_back("@function ");
return Err(Invalid::FunctionName.at(p));
}
check_body(body, true, false)?;
check_body(body, BodyContext::Function)?;
scope.define_function(
name.into(),
Function::closure(
Expand All @@ -338,7 +338,7 @@ fn handle_item(
}

Item::MixinDeclaration(ref name, ref args, ref body, ref pos) => {
check_body(body, true, true)?;
check_body(body, BodyContext::Mixin)?;
scope.define_mixin(
name.into(),
MixinDecl::new(args, &scope, body, pos),
Expand Down Expand Up @@ -407,7 +407,7 @@ fn handle_item(
handle_body(items, head, rule, buf, scope, file_context)?;
}
Item::Each(ref names, ref values, ref body) => {
check_body(body, true, true)?;
check_body(body, BodyContext::Each)?;
let mut rule = rule;
let pushed = scope.store_local_values(names);
for value in values.evaluate(scope.clone())?.iter_items() {
Expand Down Expand Up @@ -478,7 +478,7 @@ fn handle_item(
}

Item::Rule(ref selectors, ref body) => {
check_body(body, false, true)?;
check_body(body, BodyContext::Rule)?;
if rule.is_none() {
buf.do_separate();
}
Expand Down Expand Up @@ -526,7 +526,7 @@ fn handle_item(
}
Item::NamespaceRule(ref name, ref value, ref body) => {
if let Some(rule) = rule {
check_body(body, true, true)?;
check_body(body, BodyContext::NsRule)?;
let value = value.evaluate(scope.clone())?;
let name = name.evaluate(scope.clone())?;
if !value.is_null() {
Expand Down Expand Up @@ -579,11 +579,17 @@ fn handle_item(
Ok(())
}

fn check_body(
body: &[Item],
forbid_unknown: bool,
forbid_return: bool,
) -> Result<(), Error> {
#[derive(Clone, Copy, PartialEq, Eq)]
enum BodyContext {
Mixin,
Function,
Each,
Rule,
NsRule,
}

fn check_body(body: &[Item], context: BodyContext) -> Result<(), Error> {
let forbid_unknown = context != BodyContext::Rule;
for item in body {
match item {
Item::Forward(_, _, _, _, pos) => {
Expand All @@ -593,14 +599,31 @@ fn check_body(
return Err(Invalid::AtRule.at(pos.clone()));
}
Item::MixinDeclaration(.., ref pos) if forbid_unknown => {
return Err(Invalid::AtRule
.at(pos.clone().opt_trail_ws().opt_back("@mixin ")));
if context == BodyContext::Mixin {
return Err(
Invalid::MixinInMixin // AtRule
.at(pos
.clone()
.opt_trail_ws()
.opt_back("@mixin ")),
);
} else {
return Err(Invalid::AtRule
.at(pos.clone().opt_trail_ws().opt_back("@mixin ")));
}
}
Item::FunctionDeclaration(_, _, ref pos, _) if forbid_unknown => {
return Err(Invalid::AtRule
.at(pos.clone().opt_trail_ws().opt_back("@function ")));
if context == BodyContext::Mixin {
return Err(Invalid::FunctionInMixin
.at(pos.clone().opt_back("@function ")));
} else {
return Err(Invalid::AtRule.at(pos
.clone()
.opt_trail_ws()
.opt_back("@function ")));
}
}
Item::Return(_, ref pos) if forbid_return => {
Item::Return(_, ref pos) if context != BodyContext::Function => {
return Err(Invalid::AtRule.at(pos.clone()));
}
Item::AtRule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ fn runner() -> crate::TestRunner {
}

#[test]
#[ignore] // wrong error
fn test() {
assert_eq!(
runner().err(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ fn runner() -> crate::TestRunner {
}

#[test]
#[ignore] // wrong error
fn test() {
assert_eq!(
runner().err(
Expand Down
1 change: 0 additions & 1 deletion tests/spec/libsass_closed_issues/issue_1941/mixin_mixin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ fn runner() -> crate::TestRunner {
}

#[test]
#[ignore] // wrong error
fn test() {
assert_eq!(
runner().err(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ fn runner() -> crate::TestRunner {
}

#[test]
#[ignore] // wrong error
fn test() {
assert_eq!(
runner().err(
Expand Down

0 comments on commit 321cd58

Please sign in to comment.