This commit is contained in:
Connor Skees 2021-07-03 19:15:31 -04:00
parent b631ad78bc
commit 150ba14b74
34 changed files with 246 additions and 238 deletions

View File

@ -71,7 +71,7 @@ impl CallArgs {
if self.is_empty() { if self.is_empty() {
return Ok(Spanned { return Ok(Spanned {
node: "()".to_string(), node: "()".to_owned(),
span, span,
}); });
} }
@ -181,9 +181,9 @@ impl CallArgs {
err.push_str(&len.to_string()); err.push_str(&len.to_string());
err.push(' '); err.push(' ');
if len == 1 { if len == 1 {
err.push_str("was passed.") err.push_str("was passed.");
} else { } else {
err.push_str("were passed.") err.push_str("were passed.");
} }
return Err((err, self.span()).into()); return Err((err, self.span()).into());
} }

View File

@ -14,7 +14,7 @@ pub(crate) struct Function {
impl Hash for Function { impl Hash for Function {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.pos.hash(state) self.pos.hash(state);
} }
} }
@ -31,8 +31,8 @@ impl Function {
Function { Function {
args, args,
body, body,
pos,
declared_at_root, declared_at_root,
pos,
} }
} }
} }

View File

@ -100,7 +100,7 @@ impl TryFrom<&Spanned<String>> for AtRuleKind {
Ok(match unvendor(&c.node) { Ok(match unvendor(&c.node) {
"keyframes" => Self::Keyframes, "keyframes" => Self::Keyframes,
_ => Self::Unknown(c.node.to_owned()), _ => Self::Unknown(c.node.clone()),
}) })
} }
} }

View File

@ -75,7 +75,7 @@ pub(crate) fn selector_nest(args: CallArgs, parser: &mut Parser<'_>) -> SassResu
.try_fold( .try_fold(
Selector::new(span), Selector::new(span),
|parent, child| -> SassResult<Selector> { |parent, child| -> SassResult<Selector> {
Ok(child.resolve_parent_selectors(&parent, true)?) child.resolve_parent_selectors(&parent, true)
}, },
)? )?
.into_value()) .into_value())
@ -97,7 +97,7 @@ pub(crate) fn selector_append(args: CallArgs, parser: &mut Parser<'_>) -> SassRe
Ok(parsed_selectors Ok(parsed_selectors
.into_iter() .into_iter()
.try_fold(first, |parent, child| -> SassResult<Selector> { .try_fold(first, |parent, child| -> SassResult<Selector> {
Ok(Selector(SelectorList { Selector(SelectorList {
components: child components: child
.0 .0
.components .components
@ -127,7 +127,7 @@ pub(crate) fn selector_append(args: CallArgs, parser: &mut Parser<'_>) -> SassRe
.collect::<SassResult<Vec<ComplexSelector>>>()?, .collect::<SassResult<Vec<ComplexSelector>>>()?,
span, span,
}) })
.resolve_parent_selectors(&parent, false)?) .resolve_parent_selectors(&parent, false)
})? })?
.into_value()) .into_value())
} }

View File

@ -279,7 +279,7 @@ pub(crate) fn str_insert(mut args: CallArgs, parser: &mut Parser<'_>) -> SassRes
if i + 1 == idx { if i + 1 == idx {
c.to_string() + s2 c.to_string() + s2
} else if idx == 0 && i == 0 { } else if idx == 0 && i == 0 {
s2.to_string() + &c.to_string() s2.to_owned() + &c.to_string()
} else { } else {
c.to_string() c.to_string()
} }

View File

@ -533,7 +533,7 @@ fn repr(red: &Number, green: &Number, blue: &Number, alpha: &Number) -> String {
if alpha < &Number::one() { if alpha < &Number::one() {
format!("rgba({}, {}, {}, {})", red_u8, green_u8, blue_u8, alpha) format!("rgba({}, {}, {}, {})", red_u8, green_u8, blue_u8, alpha)
} else if let Some(c) = NAMED_COLORS.get_by_rgba([red_u8, green_u8, blue_u8]) { } else if let Some(c) = NAMED_COLORS.get_by_rgba([red_u8, green_u8, blue_u8]) {
(*c).to_string() (*c).to_owned()
} else { } else {
format!("#{:0>2x}{:0>2x}{:0>2x}", red_u8, green_u8, blue_u8) format!("#{:0>2x}{:0>2x}{:0>2x}", red_u8, green_u8, blue_u8)
} }

View File

@ -15,7 +15,7 @@ impl InternedString {
#[allow(dead_code)] #[allow(dead_code)]
pub fn resolve(self) -> String { pub fn resolve(self) -> String {
STRINGS.with(|interner| interner.borrow().resolve(&self.0).to_string()) STRINGS.with(|interner| interner.borrow().resolve(&self.0).to_owned())
} }
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -33,7 +33,7 @@ impl<'a> Iterator for Lexer<'a> {
.span .span
.subspan(self.pos as u64, (self.pos + len) as u64); .subspan(self.pos as u64, (self.pos + len) as u64);
self.pos += len; self.pos += len;
Some(Token { kind, pos }) Some(Token { pos, kind })
} }
} }

View File

@ -58,6 +58,8 @@ grass input.scss
clippy::panic_in_result_fn, clippy::panic_in_result_fn,
clippy::unwrap_in_result, clippy::unwrap_in_result,
clippy::map_err_ignore, clippy::map_err_ignore,
clippy::default_numeric_fallback,
clippy::if_then_some_else_none,
// temporarily allowed while under heavy development. // temporarily allowed while under heavy development.
// eventually these allows should be refactored away // eventually these allows should be refactored away

View File

@ -68,7 +68,7 @@ impl Toplevel {
if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self { if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self {
entries.push(BlockEntry::Style(s)); entries.push(BlockEntry::Style(s));
} else { } else {
panic!() panic!();
} }
} }
@ -76,7 +76,7 @@ impl Toplevel {
if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self { if let Toplevel::RuleSet(_, entries) | Toplevel::KeyframesRuleSet(_, entries) = self {
entries.push(BlockEntry::MultilineComment(s)); entries.push(BlockEntry::MultilineComment(s));
} else { } else {
panic!() panic!();
} }
} }
} }
@ -125,28 +125,28 @@ impl Css {
Stmt::Comment(s) => vals.first_mut().unwrap().push_comment(s), Stmt::Comment(s) => vals.first_mut().unwrap().push_comment(s),
Stmt::Media(m) => { Stmt::Media(m) => {
let MediaRule { query, body, .. } = *m; let MediaRule { query, body, .. } = *m;
vals.push(Toplevel::Media { query, body }) vals.push(Toplevel::Media { query, body });
} }
Stmt::Supports(s) => { Stmt::Supports(s) => {
let SupportsRule { params, body } = *s; let SupportsRule { params, body } = *s;
vals.push(Toplevel::Supports { params, body }) vals.push(Toplevel::Supports { params, body });
} }
Stmt::UnknownAtRule(u) => { Stmt::UnknownAtRule(u) => {
let UnknownAtRule { let UnknownAtRule {
params, body, name, .. params, body, name, ..
} = *u; } = *u;
vals.push(Toplevel::UnknownAtRule(Box::new(ToplevelUnknownAtRule { vals.push(Toplevel::UnknownAtRule(Box::new(ToplevelUnknownAtRule {
name,
params, params,
body, body,
name, })));
})))
} }
Stmt::Return(..) => unreachable!(), Stmt::Return(..) => unreachable!(),
Stmt::AtRoot { body } => { Stmt::AtRoot { body } => {
body.into_iter().try_for_each(|r| -> SassResult<()> { body.into_iter().try_for_each(|r| -> SassResult<()> {
vals.append(&mut self.parse_stmt(r)?); vals.append(&mut self.parse_stmt(r)?);
Ok(()) Ok(())
})? })?;
} }
Stmt::Keyframes(k) => { Stmt::Keyframes(k) => {
let Keyframes { rule, name, body } = *k; let Keyframes { rule, name, body } = *k;
@ -154,10 +154,10 @@ impl Css {
rule, rule,
name, name,
body, body,
}))) })));
} }
k @ Stmt::KeyframesRuleSet(..) => { k @ Stmt::KeyframesRuleSet(..) => {
unreachable!("@keyframes ruleset {:?}", k) unreachable!("@keyframes ruleset {:?}", k);
} }
Stmt::Import(s) => self.plain_imports.push(Toplevel::Import(s)), Stmt::Import(s) => self.plain_imports.push(Toplevel::Import(s)),
}; };
@ -183,8 +183,8 @@ impl Css {
params, body, name, .. params, body, name, ..
} = *u; } = *u;
vec![Toplevel::UnknownAtRule(Box::new(ToplevelUnknownAtRule { vec![Toplevel::UnknownAtRule(Box::new(ToplevelUnknownAtRule {
params,
name, name,
params,
body, body,
}))] }))]
} }
@ -316,10 +316,10 @@ impl Css {
if body.is_empty() { if body.is_empty() {
writeln!(buf, ";")?; writeln!(buf, ";")?;
continue; continue;
} else {
writeln!(buf, " {{")?;
} }
writeln!(buf, " {{")?;
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print( Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
buf, buf,
map, map,
@ -343,10 +343,10 @@ impl Css {
if body.is_empty() { if body.is_empty() {
writeln!(buf, " {{}}")?; writeln!(buf, " {{}}")?;
continue; continue;
} else {
writeln!(buf, " {{")?;
} }
writeln!(buf, " {{")?;
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print( Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
buf, buf,
map, map,
@ -369,10 +369,10 @@ impl Css {
if body.is_empty() { if body.is_empty() {
writeln!(buf, ";")?; writeln!(buf, ";")?;
continue; continue;
} else {
writeln!(buf, " {{")?;
} }
writeln!(buf, " {{")?;
Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print( Css::from_stmts(body, true, self.allows_charset)?._inner_pretty_print(
buf, buf,
map, map,

View File

@ -188,22 +188,16 @@ impl<'a> Parser<'a> {
let value = self.parse_value(true, &|c| match c.peek() { let value = self.parse_value(true, &|c| match c.peek() {
Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true, Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true,
Some(Token { kind: '.', .. }) => { Some(Token { kind: '.', .. }) => {
if matches!(c.peek_next(), Some(Token { kind: '.', .. })) { let next_is_dot = matches!(c.peek_next(), Some(Token { kind: '.', .. }));
c.reset_cursor(); c.reset_cursor();
true
} else { next_is_dot
c.reset_cursor();
false
}
} }
Some(Token { kind: '=', .. }) => { Some(Token { kind: '=', .. }) => {
if matches!(c.peek_next(), Some(Token { kind: '=', .. })) { let next_is_eq = matches!(c.peek_next(), Some(Token { kind: '=', .. }));
c.reset_cursor(); c.reset_cursor();
false
} else { !next_is_eq
c.reset_cursor();
true
}
} }
Some(..) | None => false, Some(..) | None => false,
}); });
@ -297,13 +291,11 @@ impl<'a> Parser<'a> {
let right = self.parse_value(true, &|c| match c.peek() { let right = self.parse_value(true, &|c| match c.peek() {
Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true, Some(Token { kind: ')', .. }) | Some(Token { kind: ',', .. }) => true,
Some(Token { kind: '.', .. }) => { Some(Token { kind: '.', .. }) => {
if matches!(c.peek_next(), Some(Token { kind: '.', .. })) { let next_is_dot =
matches!(c.peek_next(), Some(Token { kind: '.', .. }));
c.reset_cursor(); c.reset_cursor();
true
} else { next_is_dot
c.reset_cursor();
false
}
} }
Some(..) | None => false, Some(..) | None => false,
})?; })?;

View File

@ -23,7 +23,7 @@ impl<T> NeverEmptyVec<T> {
} }
pub fn push(&mut self, value: T) { pub fn push(&mut self, value: T) {
self.rest.push(value) self.rest.push(value);
} }
pub fn pop(&mut self) -> Option<T> { pub fn pop(&mut self) -> Option<T> {

View File

@ -122,7 +122,8 @@ impl<'a> Parser<'a> {
if found_true { if found_true {
self.throw_away_until_closing_curly_brace()?; self.throw_away_until_closing_curly_brace()?;
break; break;
} else { }
self.scopes.enter_new_scope(); self.scopes.enter_new_scope();
let tmp = Parser { let tmp = Parser {
toks: self.toks, toks: self.toks,
@ -146,7 +147,6 @@ impl<'a> Parser<'a> {
self.scopes.exit_scope(); self.scopes.exit_scope();
return tmp; return tmp;
} }
}
_ => { _ => {
return Err(("expected \"{\".", tok.pos()).into()); return Err(("expected \"{\".", tok.pos()).into());
} }

View File

@ -272,11 +272,11 @@ impl<'a> Parser<'a> {
v => s.push_str(v.to_css_string(interpolation.span)?.borrow()), v => s.push_str(v.to_css_string(interpolation.span)?.borrow()),
}; };
continue; continue;
} else { }
s.push('#'); s.push('#');
continue; continue;
} }
}
'\n' => return Err(("Expected \".", tok.pos()).into()), '\n' => return Err(("Expected \".", tok.pos()).into()),
'\\' => { '\\' => {
let first = match self.toks.peek() { let first = match self.toks.peek() {

View File

@ -13,15 +13,18 @@ use crate::{
use super::{Parser, Stmt}; use super::{Parser, Stmt};
#[allow(clippy::case_sensitive_file_extension_comparisons)]
fn is_plain_css_import(url: &str) -> bool { fn is_plain_css_import(url: &str) -> bool {
if url.len() < 5 { if url.len() < 5 {
return false; return false;
} }
url.ends_with(".css") let lower = url.to_ascii_lowercase();
|| url.starts_with("http://")
|| url.starts_with("https://") lower.ends_with(".css")
|| url.starts_with("//") || lower.starts_with("http://")
|| lower.starts_with("https://")
|| lower.starts_with("//")
} }
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
@ -55,7 +58,7 @@ impl<'a> Parser<'a> {
for name in &paths { for name in &paths {
if name.is_file() { if name.is_file() {
return Some(name.to_path_buf()); return Some(name.clone());
} }
} }
@ -165,10 +168,12 @@ impl<'a> Parser<'a> {
let mut list_of_imports: Vec<Stmt> = Vec::new(); let mut list_of_imports: Vec<Stmt> = Vec::new();
for file_name_element in v { for file_name_element in v {
match file_name_element { match file_name_element {
#[allow(clippy::case_sensitive_file_extension_comparisons)]
Value::String(s, QuoteKind::Quoted) => { Value::String(s, QuoteKind::Quoted) => {
if s.ends_with(".css") let lower = s.to_ascii_lowercase();
|| s.starts_with("http://") if lower.ends_with(".css")
|| s.starts_with("https://") || lower.starts_with("http://")
|| lower.starts_with("https://")
{ {
list_of_imports.push(Stmt::Import(format!("\"{}\"", s))); list_of_imports.push(Stmt::Import(format!("\"{}\"", s)));
} else { } else {

View File

@ -40,7 +40,7 @@ impl<'a, 'b> KeyframesSelectorParser<'a, 'b> {
let mut ident = self.parser.parse_identifier()?; let mut ident = self.parser.parse_identifier()?;
ident.node.make_ascii_lowercase(); ident.node.make_ascii_lowercase();
if ident.node == "to" { if ident.node == "to" {
selectors.push(KeyframesSelector::To) selectors.push(KeyframesSelector::To);
} else { } else {
return Err(("Expected \"to\" or \"from\".", tok.pos).into()); return Err(("Expected \"to\" or \"from\".", tok.pos).into());
} }
@ -49,7 +49,7 @@ impl<'a, 'b> KeyframesSelectorParser<'a, 'b> {
let mut ident = self.parser.parse_identifier()?; let mut ident = self.parser.parse_identifier()?;
ident.node.make_ascii_lowercase(); ident.node.make_ascii_lowercase();
if ident.node == "from" { if ident.node == "from" {
selectors.push(KeyframesSelector::From) selectors.push(KeyframesSelector::From);
} else { } else {
return Err(("Expected \"to\" or \"from\".", tok.pos).into()); return Err(("Expected \"to\" or \"from\".", tok.pos).into());
} }
@ -104,7 +104,7 @@ impl<'a> Parser<'a> {
'{' => { '{' => {
// todo: we can avoid the reallocation by trimming before emitting // todo: we can avoid the reallocation by trimming before emitting
// (in `output.rs`) // (in `output.rs`)
return Ok(name.trim().to_string()); return Ok(name.trim().to_owned());
} }
_ => name.push(tok.kind), _ => name.push(tok.kind),
} }

View File

@ -92,7 +92,8 @@ impl<'a> Parser<'a> {
self.whitespace_or_comment(); self.whitespace_or_comment();
buf.push(')'); buf.push(')');
return Ok(buf); return Ok(buf);
} else { }
let next_tok = self.toks.peek().cloned(); let next_tok = self.toks.peek().cloned();
let is_angle = next_tok.map_or(false, |t| t.kind == '<' || t.kind == '>'); let is_angle = next_tok.map_or(false, |t| t.kind == '<' || t.kind == '>');
if is_angle || matches!(next_tok, Some(Token { kind: '=', .. })) { if is_angle || matches!(next_tok, Some(Token { kind: '=', .. })) {
@ -108,7 +109,6 @@ impl<'a> Parser<'a> {
buf.push_str(&self.expression_until_comparison()?); buf.push_str(&self.expression_until_comparison()?);
} }
}
self.expect_char(')')?; self.expect_char(')')?;
self.whitespace_or_comment(); self.whitespace_or_comment();

View File

@ -165,13 +165,11 @@ impl<'a> Parser<'a> {
AtRuleKind::Return => { AtRuleKind::Return => {
if self.flags.in_function() { if self.flags.in_function() {
return Ok(vec![Stmt::Return(self.parse_return()?)]); return Ok(vec![Stmt::Return(self.parse_return()?)]);
} else {
return Err((
"This at-rule is not allowed here.",
kind_string.span,
)
.into());
} }
return Err(
("This at-rule is not allowed here.", kind_string.span).into()
);
} }
AtRuleKind::AtRoot => { AtRuleKind::AtRoot => {
if self.flags.in_function() { if self.flags.in_function() {
@ -215,7 +213,7 @@ impl<'a> Parser<'a> {
self.warn(&Spanned { self.warn(&Spanned {
node: message.to_css_string(span)?, node: message.to_css_string(span)?,
span, span,
}) });
} }
AtRuleKind::Debug => { AtRuleKind::Debug => {
let Spanned { let Spanned {
@ -230,7 +228,7 @@ impl<'a> Parser<'a> {
self.debug(&Spanned { self.debug(&Spanned {
node: message.inspect(span)?, node: message.inspect(span)?,
span, span,
}) });
} }
AtRuleKind::If => stmts.append(&mut self.parse_if()?), AtRuleKind::If => stmts.append(&mut self.parse_if()?),
AtRuleKind::Each => stmts.append(&mut self.parse_each()?), AtRuleKind::Each => stmts.append(&mut self.parse_each()?),
@ -253,7 +251,7 @@ impl<'a> Parser<'a> {
} }
AtRuleKind::Media => stmts.push(self.parse_media()?), AtRuleKind::Media => stmts.push(self.parse_media()?),
AtRuleKind::Unknown(_) => { AtRuleKind::Unknown(_) => {
stmts.push(self.parse_unknown_at_rule(kind_string.node)?) stmts.push(self.parse_unknown_at_rule(kind_string.node)?);
} }
AtRuleKind::Use => { AtRuleKind::Use => {
return Err(( return Err((
@ -266,7 +264,7 @@ impl<'a> Parser<'a> {
AtRuleKind::Extend => self.parse_extend()?, AtRuleKind::Extend => self.parse_extend()?,
AtRuleKind::Supports => stmts.push(self.parse_supports()?), AtRuleKind::Supports => stmts.push(self.parse_supports()?),
AtRuleKind::Keyframes => { AtRuleKind::Keyframes => {
stmts.push(self.parse_keyframes(kind_string.node)?) stmts.push(self.parse_keyframes(kind_string.node)?);
} }
} }
} }
@ -308,7 +306,7 @@ impl<'a> Parser<'a> {
if self.flags.in_keyframes() { if self.flags.in_keyframes() {
match self.is_selector_or_style()? { match self.is_selector_or_style()? {
SelectorOrStyle::ModuleVariableRedeclaration(module) => { SelectorOrStyle::ModuleVariableRedeclaration(module) => {
self.parse_module_variable_redeclaration(module)? self.parse_module_variable_redeclaration(module)?;
} }
SelectorOrStyle::Style(property, value) => { SelectorOrStyle::Style(property, value) => {
if let Some(value) = value { if let Some(value) = value {
@ -338,7 +336,7 @@ impl<'a> Parser<'a> {
match self.is_selector_or_style()? { match self.is_selector_or_style()? {
SelectorOrStyle::ModuleVariableRedeclaration(module) => { SelectorOrStyle::ModuleVariableRedeclaration(module) => {
self.parse_module_variable_redeclaration(module)? self.parse_module_variable_redeclaration(module)?;
} }
SelectorOrStyle::Style(property, value) => { SelectorOrStyle::Style(property, value) => {
if let Some(value) = value { if let Some(value) = value {
@ -422,11 +420,11 @@ impl<'a> Parser<'a> {
'{' => { '{' => {
if from_fn { if from_fn {
return Err(("Expected selector.", pos).into()); return Err(("Expected selector.", pos).into());
} else { }
found_curly = true; found_curly = true;
break; break;
} }
}
'\\' => { '\\' => {
string.push('\\'); string.push('\\');
if let Some(Token { kind, .. }) = self.toks.next() { if let Some(Token { kind, .. }) = self.toks.next() {
@ -835,7 +833,7 @@ impl<'a> Parser<'a> {
&extend_rule, &extend_rule,
&None, &None,
self.span_before, self.span_before,
) );
} }
Ok(()) Ok(())
@ -893,9 +891,9 @@ impl<'a> Parser<'a> {
let interpolation = self.parse_interpolation()?; let interpolation = self.parse_interpolation()?;
params.push_str(&interpolation.node.to_css_string(interpolation.span)?); params.push_str(&interpolation.node.to_css_string(interpolation.span)?);
continue; continue;
} else {
params.push(tok.kind);
} }
params.push(tok.kind);
} }
'\n' | ' ' | '\t' => { '\n' | ' ' | '\t' => {
self.whitespace(); self.whitespace();

View File

@ -32,12 +32,12 @@ impl<'a> Parser<'a> {
if let Some(Token { kind: '*', .. }) = self.toks.peek() { if let Some(Token { kind: '*', .. }) = self.toks.peek() {
self.toks.next(); self.toks.next();
return Ok(Some('*'.to_string())); return Ok(Some('*'.to_string()));
} else { }
let name = self.parse_identifier_no_interpolation(false)?; let name = self.parse_identifier_no_interpolation(false)?;
return Ok(Some(name.node)); return Ok(Some(name.node));
} }
}
Ok(None) Ok(None)
} }

View File

@ -37,12 +37,12 @@ impl<'a> Parser<'a> {
toks.push(*tok); toks.push(*tok);
self.toks.peek_forward(1); self.toks.peek_forward(1);
break; break;
} else { }
scope -= 1; scope -= 1;
toks.push(*tok); toks.push(*tok);
self.toks.peek_forward(1); self.toks.peek_forward(1);
} }
}
'(' => { '(' => {
toks.push(*tok); toks.push(*tok);
self.toks.peek_forward(1); self.toks.peek_forward(1);
@ -154,13 +154,13 @@ impl<'a> Parser<'a> {
return Ok(SelectorOrStyle::ModuleVariableRedeclaration( return Ok(SelectorOrStyle::ModuleVariableRedeclaration(
property.into(), property.into(),
)); ));
} else { }
if whitespace_after_property { if whitespace_after_property {
property.push(' '); property.push(' ');
} }
return Ok(SelectorOrStyle::Selector(property)); return Ok(SelectorOrStyle::Selector(property));
} }
}
_ => { _ => {
if whitespace_after_property { if whitespace_after_property {
property.push(' '); property.push(' ');
@ -219,9 +219,9 @@ impl<'a> Parser<'a> {
self.toks.next(); self.toks.next();
self.whitespace(); self.whitespace();
return Ok(styles); return Ok(styles);
} else {
continue;
} }
continue;
} }
continue; continue;
} }

View File

@ -78,9 +78,9 @@ impl<'a> Parser<'a> {
'}' => { '}' => {
if nesting == 0 { if nesting == 0 {
return Ok(()); return Ok(());
} else {
nesting -= 1;
} }
nesting -= 1;
} }
'/' => match self.toks.peek() { '/' => match self.toks.peek() {
Some(Token { kind: '/', .. }) => { Some(Token { kind: '/', .. }) => {
@ -107,9 +107,9 @@ impl<'a> Parser<'a> {
')' => { ')' => {
if scope < 1 { if scope < 1 {
return Ok(()); return Ok(());
} else {
scope -= 1;
} }
scope -= 1;
} }
'(' => scope += 1, '(' => scope += 1,
'"' | '\'' => { '"' | '\'' => {

View File

@ -42,11 +42,11 @@ impl<'a> Parser<'a> {
')' => { ')' => {
if nesting == 0 { if nesting == 0 {
break; break;
} else { }
nesting -= 1; nesting -= 1;
buf.push(')'); buf.push(')');
} }
}
q @ '\'' | q @ '"' => { q @ '\'' | q @ '"' => {
buf.push('"'); buf.push('"');
match self.parse_quoted_string(q)?.node { match self.parse_quoted_string(q)?.node {
@ -123,9 +123,9 @@ impl<'a> Parser<'a> {
buf.push(')'); buf.push(')');
self.toks.truncate_iterator_to_cursor(); self.toks.truncate_iterator_to_cursor();
return Ok(Some(buf)); return Ok(Some(buf));
} else {
break;
} }
break;
} else { } else {
break; break;
} }
@ -211,7 +211,7 @@ impl<'a> Parser<'a> {
) { ) {
return Ok(None); return Ok(None);
} }
buf.push_str("min(") buf.push_str("min(");
} }
Some(Token { kind: 'a', .. }) | Some(Token { kind: 'A', .. }) => { Some(Token { kind: 'a', .. }) | Some(Token { kind: 'A', .. }) => {
self.toks.advance_cursor(); self.toks.advance_cursor();
@ -221,7 +221,7 @@ impl<'a> Parser<'a> {
) { ) {
return Ok(None); return Ok(None);
} }
buf.push_str("max(") buf.push_str("max(");
} }
_ => return Ok(None), _ => return Ok(None),
} }

View File

@ -89,8 +89,8 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> {
Op::Mul => self.mul(val1, val2)?, Op::Mul => self.mul(val1, val2)?,
Op::Div => self.div(val1, val2, in_parens)?, Op::Div => self.div(val1, val2, in_parens)?,
Op::Rem => self.rem(val1, val2)?, Op::Rem => self.rem(val1, val2)?,
Op::And => Self::and(val1, val2)?, Op::And => Self::and(val1, val2),
Op::Or => Self::or(val1, val2)?, Op::Or => Self::or(val1, val2),
Op::Equal => Self::equal(val1, val2), Op::Equal => Self::equal(val1, val2),
Op::NotEqual => Self::not_equal(val1, val2), Op::NotEqual => Self::not_equal(val1, val2),
Op::GreaterThan => self.greater_than(val1, val2)?, Op::GreaterThan => self.greater_than(val1, val2)?,
@ -110,7 +110,7 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> {
let val = self.eval(val, in_parens)?; let val = self.eval(val, in_parens)?;
match op { match op {
Op::Minus => self.unary_minus(val), Op::Minus => self.unary_minus(val),
Op::Not => Self::unary_not(&val), Op::Not => Ok(Self::unary_not(&val)),
Op::Plus => self.unary_plus(val), Op::Plus => self.unary_plus(val),
_ => unreachable!(), _ => unreachable!(),
} }
@ -133,8 +133,8 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> {
}) })
} }
fn unary_not(val: &Value) -> SassResult<Value> { fn unary_not(val: &Value) -> Value {
Ok(Value::bool(!val.is_true())) Value::bool(!val.is_true())
} }
fn unary( fn unary(
@ -697,7 +697,7 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> {
}) })
} }
fn and(left: HigherIntermediateValue, right: HigherIntermediateValue) -> SassResult<Value> { fn and(left: HigherIntermediateValue, right: HigherIntermediateValue) -> Value {
let left = match left { let left = match left {
HigherIntermediateValue::Literal(v) => v, HigherIntermediateValue::Literal(v) => v,
v => panic!("{:?}", v), v => panic!("{:?}", v),
@ -706,10 +706,14 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> {
HigherIntermediateValue::Literal(v) => v, HigherIntermediateValue::Literal(v) => v,
v => panic!("{:?}", v), v => panic!("{:?}", v),
}; };
Ok(if left.is_true() { right } else { left }) if left.is_true() {
right
} else {
left
}
} }
fn or(left: HigherIntermediateValue, right: HigherIntermediateValue) -> SassResult<Value> { fn or(left: HigherIntermediateValue, right: HigherIntermediateValue) -> Value {
let left = match left { let left = match left {
HigherIntermediateValue::Literal(v) => v, HigherIntermediateValue::Literal(v) => v,
v => panic!("{:?}", v), v => panic!("{:?}", v),
@ -718,7 +722,11 @@ impl<'a, 'b: 'a> ValueVisitor<'a, 'b> {
HigherIntermediateValue::Literal(v) => v, HigherIntermediateValue::Literal(v) => v,
v => panic!("{:?}", v), v => panic!("{:?}", v),
}; };
Ok(if left.is_true() { left } else { right }) if left.is_true() {
left
} else {
right
}
} }
pub fn equal(left: HigherIntermediateValue, right: HigherIntermediateValue) -> Value { pub fn equal(left: HigherIntermediateValue, right: HigherIntermediateValue) -> Value {

View File

@ -78,7 +78,7 @@ impl<'a> Parser<'a> {
match val.node { match val.node {
IntermediateValue::Value(v) => { IntermediateValue::Value(v) => {
last_was_whitespace = false; last_was_whitespace = false;
space_separated.push(v.span(val.span)) space_separated.push(v.span(val.span));
} }
IntermediateValue::Op(op) => { IntermediateValue::Op(op) => {
iter.parse_op( iter.parse_op(
@ -260,7 +260,8 @@ impl<'a> Parser<'a> {
self.parse_call_args()?, self.parse_call_args()?,
)) ))
.span(self.span_before)); .span(self.span_before));
} else { }
// check for special cased CSS functions // check for special cased CSS functions
match unvendor(&lower) { match unvendor(&lower) {
"calc" | "element" | "expression" => { "calc" | "element" | "expression" => {
@ -279,7 +280,6 @@ impl<'a> Parser<'a> {
)) ))
.span(self.span_before)); .span(self.span_before));
} }
}
}; };
let call_args = self.parse_call_args()?; let call_args = self.parse_call_args()?;
@ -804,9 +804,9 @@ impl<'a> Parser<'a> {
self.toks.next(); self.toks.next();
self.toks.next(); self.toks.next();
return Some(self.parse_unicode_range(kind)); return Some(self.parse_unicode_range(kind));
} else {
self.toks.reset_cursor();
} }
self.toks.reset_cursor();
} }
return Some(self.parse_ident_value(predicate)); return Some(self.parse_ident_value(predicate));
} }
@ -1157,8 +1157,10 @@ impl<'a, 'b: 'a> IntermediateValueIterator<'a, 'b> {
} }
} }
Op::Minus => { Op::Minus => {
if self.whitespace() || !last_was_whitespace { let may_be_subtraction = self.whitespace() || !last_was_whitespace;
let right = self.single_value(in_paren)?; let right = self.single_value(in_paren)?;
if may_be_subtraction {
if let Some(left) = space_separated.pop() { if let Some(left) = space_separated.pop() {
space_separated.push(Spanned { space_separated.push(Spanned {
node: HigherIntermediateValue::BinaryOp( node: HigherIntermediateValue::BinaryOp(
@ -1176,7 +1178,6 @@ impl<'a, 'b: 'a> IntermediateValueIterator<'a, 'b> {
); );
} }
} else { } else {
let right = self.single_value(in_paren)?;
space_separated.push( space_separated.push(
right.map_node(|n| HigherIntermediateValue::UnaryOp(op.node, Box::new(n))), right.map_node(|n| HigherIntermediateValue::UnaryOp(op.node, Box::new(n))),
); );

View File

@ -157,7 +157,7 @@ impl<'a> Parser<'a> {
Some(..) | None => { Some(..) | None => {
value?; value?;
self.expect_char(';')?; self.expect_char(';')?;
unreachable!() unreachable!();
} }
} }

View File

@ -170,6 +170,7 @@ impl Attribute {
} }
impl Display for Attribute { impl Display for Attribute {
#[allow(clippy::branches_sharing_code)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('[')?; f.write_char('[')?;
write!(f, "{}", self.attr)?; write!(f, "{}", self.attr)?;
@ -249,16 +250,17 @@ enum AttributeOp {
Contains, Contains,
} }
impl Into<&'static str> for AttributeOp { impl From<AttributeOp> for &'static str {
fn into(self) -> &'static str { #[inline]
match self { fn from(op: AttributeOp) -> Self {
Self::Any => "", match op {
Self::Equals => "=", AttributeOp::Any => "",
Self::Include => "~=", AttributeOp::Equals => "=",
Self::Dash => "|=", AttributeOp::Include => "~=",
Self::Prefix => "^=", AttributeOp::Dash => "|=",
Self::Suffix => "$=", AttributeOp::Prefix => "^=",
Self::Contains => "*=", AttributeOp::Suffix => "$=",
AttributeOp::Contains => "*=",
} }
} }
} }

View File

@ -25,7 +25,7 @@ impl Hash for ExtendedSelector {
// but I haven't managed to find a test case // but I haven't managed to find a test case
// that exhibits it. // that exhibits it.
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
ptr::hash(&*self.0, state) ptr::hash(&*self.0, state);
// in case we need to hash the actual value: // in case we need to hash the actual value:
// self.0.borrow().hash(state); // self.0.borrow().hash(state);
} }
@ -66,8 +66,13 @@ impl SelectorHashSet {
pub fn insert(&mut self, selector: ExtendedSelector) { pub fn insert(&mut self, selector: ExtendedSelector) {
self.0.insert(selector); self.0.insert(selector);
} }
}
pub fn into_iter(self) -> IntoIter<ExtendedSelector> { impl IntoIterator for SelectorHashSet {
type Item = ExtendedSelector;
type IntoIter = IntoIter<ExtendedSelector>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter() self.0.into_iter()
} }
} }

View File

@ -59,6 +59,7 @@ impl Extension {
// todo: this should return a `Result`. it currently does not because the cascade effect // todo: this should return a `Result`. it currently does not because the cascade effect
// from this returning a `Result` will make some code returning `Option`s much uglier (we can't // from this returning a `Result` will make some code returning `Option`s much uglier (we can't
// use `?` to return both `Option` and `Result` from the same function) // use `?` to return both `Option` and `Result` from the same function)
#[allow(clippy::needless_return)]
pub fn assert_compatible_media_context(&self, media_context: &Option<Vec<CssMediaQuery>>) { pub fn assert_compatible_media_context(&self, media_context: &Option<Vec<CssMediaQuery>>) {
if &self.media_context == media_context { if &self.media_context == media_context {
return; return;

View File

@ -416,12 +416,12 @@ fn merge_final_combinators(
result.push_front(vec![vec![ result.push_front(vec![vec![
ComplexSelectorComponent::Compound(compound_two), ComplexSelectorComponent::Compound(compound_two),
ComplexSelectorComponent::Combinator(Combinator::FollowingSibling), ComplexSelectorComponent::Combinator(Combinator::FollowingSibling),
]]) ]]);
} else if compound_two.is_super_selector(&compound_one, &None) { } else if compound_two.is_super_selector(&compound_one, &None) {
result.push_front(vec![vec![ result.push_front(vec![vec![
ComplexSelectorComponent::Compound(compound_one), ComplexSelectorComponent::Compound(compound_one),
ComplexSelectorComponent::Combinator(Combinator::FollowingSibling), ComplexSelectorComponent::Combinator(Combinator::FollowingSibling),
]]) ]]);
} else { } else {
let mut choices = vec![ let mut choices = vec![
vec![ vec![
@ -442,7 +442,7 @@ fn merge_final_combinators(
choices.push(vec![ choices.push(vec![
ComplexSelectorComponent::Compound(unified), ComplexSelectorComponent::Compound(unified),
ComplexSelectorComponent::Combinator(Combinator::FollowingSibling), ComplexSelectorComponent::Combinator(Combinator::FollowingSibling),
]) ]);
} }
result.push_front(choices); result.push_front(choices);

View File

@ -527,13 +527,7 @@ impl Extender {
}) })
.collect(); .collect();
Some( Some(unified_paths.into_iter().flatten().flatten().collect())
unified_paths
.into_iter()
.filter_map(|complexes| complexes)
.flatten()
.collect(),
)
} }
fn extend_simple( fn extend_simple(
@ -837,7 +831,7 @@ impl Extender {
let mut max_specificity = 0; let mut max_specificity = 0;
for component in &complex1.components { for component in &complex1.components {
if let ComplexSelectorComponent::Compound(compound) = component { if let ComplexSelectorComponent::Compound(compound) = component {
max_specificity = max_specificity.max(self.source_specificity_for(compound)) max_specificity = max_specificity.max(self.source_specificity_for(compound));
} }
} }
@ -920,7 +914,7 @@ impl Extender {
// clone in cases where we have already seen a simple selector (common in // clone in cases where we have already seen a simple selector (common in
// scenarios in which there is a lot of nesting) // scenarios in which there is a lot of nesting)
if let Some(entry) = self.selectors.get_mut(&simple) { if let Some(entry) = self.selectors.get_mut(&simple) {
entry.insert(selector.clone()) entry.insert(selector.clone());
} else { } else {
self.selectors self.selectors
.entry(simple.clone()) .entry(simple.clone())
@ -1146,7 +1140,7 @@ impl Extender {
selectors: SelectorHashSet, selectors: SelectorHashSet,
new_extensions: &HashMap<SimpleSelector, IndexMap<ComplexSelector, Extension>>, new_extensions: &HashMap<SimpleSelector, IndexMap<ComplexSelector, Extension>>,
) { ) {
for mut selector in selectors.into_iter() { for mut selector in selectors {
let old_value = selector.clone().into_selector().0; let old_value = selector.clone().into_selector().0;
selector.set_inner(self.extend_list( selector.set_inner(self.extend_list(
old_value.clone(), old_value.clone(),
@ -1193,7 +1187,7 @@ fn map_add_all_2<K1: Hash + Eq, K2: Hash + Eq, V>(
destination: &mut HashMap<K1, IndexMap<K2, V>>, destination: &mut HashMap<K1, IndexMap<K2, V>>,
source: HashMap<K1, IndexMap<K2, V>>, source: HashMap<K1, IndexMap<K2, V>>,
) { ) {
source.into_iter().for_each(|(key, mut inner)| { for (key, mut inner) in source {
if destination.contains_key(&key) { if destination.contains_key(&key) {
destination destination
.get_mut(&key) .get_mut(&key)
@ -1202,5 +1196,5 @@ fn map_add_all_2<K1: Hash + Eq, K2: Hash + Eq, V>(
} else { } else {
destination.get_mut(&key).replace(&mut inner); destination.get_mut(&key).replace(&mut inner);
} }
}) }
} }

View File

@ -69,9 +69,9 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
span: Span, span: Span,
) -> Self { ) -> Self {
Self { Self {
parser,
allows_parent, allows_parent,
allows_placeholder, allows_placeholder,
parser,
span, span,
} }
} }
@ -144,7 +144,7 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
} }
Some(Token { kind: '>', .. }) => { Some(Token { kind: '>', .. }) => {
self.parser.toks.next(); self.parser.toks.next();
components.push(ComplexSelectorComponent::Combinator(Combinator::Child)) components.push(ComplexSelectorComponent::Combinator(Combinator::Child));
} }
Some(Token { kind: '~', .. }) => { Some(Token { kind: '~', .. }) => {
self.parser.toks.next(); self.parser.toks.next();
@ -350,7 +350,7 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
argument = Some( argument = Some(
self.declaration_value()? self.declaration_value()?
.trim_end() .trim_end()
.to_string() .to_owned()
.into_boxed_str(), .into_boxed_str(),
); );
} }
@ -397,16 +397,16 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
if let Some(Token { kind: '*', .. }) = self.parser.toks.peek() { if let Some(Token { kind: '*', .. }) = self.parser.toks.peek() {
self.parser.toks.next(); self.parser.toks.next();
return Ok(SimpleSelector::Universal(Namespace::Asterisk)); return Ok(SimpleSelector::Universal(Namespace::Asterisk));
} else { }
return Ok(SimpleSelector::Type(QualifiedName { return Ok(SimpleSelector::Type(QualifiedName {
ident: self.parser.parse_identifier()?.node, ident: self.parser.parse_identifier()?.node,
namespace: Namespace::Asterisk, namespace: Namespace::Asterisk,
})); }));
} }
} else {
return Ok(SimpleSelector::Universal(Namespace::None)); return Ok(SimpleSelector::Universal(Namespace::None));
} }
}
Some(Token { kind: '|', pos }) => { Some(Token { kind: '|', pos }) => {
self.parser.span_before = self.parser.span_before.merge(*pos); self.parser.span_before = self.parser.span_before.merge(*pos);
self.parser.toks.next(); self.parser.toks.next();
@ -457,11 +457,11 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
match self.parser.toks.peek() { match self.parser.toks.peek() {
Some(Token { kind: 'e', .. }) | Some(Token { kind: 'E', .. }) => { Some(Token { kind: 'e', .. }) | Some(Token { kind: 'E', .. }) => {
self.expect_identifier("even")?; self.expect_identifier("even")?;
return Ok("even".to_string()); return Ok("even".to_owned());
} }
Some(Token { kind: 'o', .. }) | Some(Token { kind: 'O', .. }) => { Some(Token { kind: 'o', .. }) | Some(Token { kind: 'O', .. }) => {
self.expect_identifier("odd")?; self.expect_identifier("odd")?;
return Ok("odd".to_string()); return Ok("odd".to_owned());
} }
Some(t @ Token { kind: '+', .. }) | Some(t @ Token { kind: '-', .. }) => { Some(t @ Token { kind: '+', .. }) | Some(t @ Token { kind: '-', .. }) => {
buf.push(t.kind); buf.push(t.kind);

View File

@ -28,12 +28,12 @@ pub(crate) fn peek_until_closing_curly_brace(
'}' => { '}' => {
if nesting == 0 { if nesting == 0 {
break; break;
} else { }
nesting -= 1; nesting -= 1;
t.push(tok); t.push(tok);
toks.advance_cursor(); toks.advance_cursor();
} }
}
'/' => { '/' => {
let next = *toks let next = *toks
.peek_forward(1) .peek_forward(1)

View File

@ -67,11 +67,11 @@ pub(crate) fn read_until_closing_curly_brace(
'}' => { '}' => {
if nesting == 0 { if nesting == 0 {
break; break;
} else { }
nesting -= 1; nesting -= 1;
buf.push(toks.next().unwrap()); buf.push(toks.next().unwrap());
} }
}
'/' => { '/' => {
let next = toks.next().unwrap(); let next = toks.next().unwrap();
match toks.peek() { match toks.peek() {
@ -179,11 +179,11 @@ pub(crate) fn read_until_semicolon_or_closing_curly_brace(
'}' => { '}' => {
if nesting == 0 { if nesting == 0 {
break; break;
} else { }
nesting -= 1; nesting -= 1;
t.push(toks.next().unwrap()); t.push(toks.next().unwrap());
} }
}
'/' => { '/' => {
let next = toks.next().unwrap(); let next = toks.next().unwrap();
match toks.peek() { match toks.peek() {
@ -213,9 +213,9 @@ pub(crate) fn read_until_closing_paren(
if scope < 1 { if scope < 1 {
t.push(tok); t.push(tok);
return Ok(t); return Ok(t);
} else {
scope -= 1;
} }
scope -= 1;
} }
'(' => scope += 1, '(' => scope += 1,
'"' | '\'' => { '"' | '\'' => {
@ -231,7 +231,7 @@ pub(crate) fn read_until_closing_paren(
} }
_ => {} _ => {}
} }
t.push(tok) t.push(tok);
} }
Ok(t) Ok(t)
} }

View File

@ -153,7 +153,7 @@ fn visit_quoted_string(buf: &mut String, force_double_quote: bool, string: &str)
'\x00'..='\x08' | '\x0A'..='\x1F' => { '\x00'..='\x08' | '\x0A'..='\x1F' => {
buffer.push('\\'); buffer.push('\\');
if c as u32 > 0xF { if c as u32 > 0xF {
buffer.push(hex_char_for(c as u32 >> 4)) buffer.push(hex_char_for(c as u32 >> 4));
} }
buffer.push(hex_char_for(c as u32 & 0xF)); buffer.push(hex_char_for(c as u32 & 0xF));
@ -205,9 +205,9 @@ impl Value {
return Err( return Err(
(format!("{}{} isn't a valid CSS value.", num, unit), span).into() (format!("{}{} isn't a valid CSS value.", num, unit), span).into()
); );
} else {
return Err((format!("NaN{} isn't a valid CSS value.", unit), span).into());
} }
return Err((format!("NaN{} isn't a valid CSS value.", unit), span).into());
} }
_ => { _ => {
if let Some(num) = num { if let Some(num) = num {
@ -278,7 +278,7 @@ impl Value {
Value::ArgList(args) => Cow::owned( Value::ArgList(args) => Cow::owned(
args.iter() args.iter()
.filter(|x| !x.is_null()) .filter(|x| !x.is_null())
.map(|a| Ok(a.node.to_css_string(span)?)) .map(|a| a.node.to_css_string(span))
.collect::<SassResult<Vec<Cow<'static, str>>>>()? .collect::<SassResult<Vec<Cow<'static, str>>>>()?
.join(", "), .join(", "),
), ),
@ -464,14 +464,14 @@ impl Value {
"({},)", "({},)",
args.iter() args.iter()
.filter(|x| !x.is_null()) .filter(|x| !x.is_null())
.map(|a| Ok(a.node.inspect(span)?)) .map(|a| a.node.inspect(span))
.collect::<SassResult<Vec<Cow<'static, str>>>>()? .collect::<SassResult<Vec<Cow<'static, str>>>>()?
.join(", "), .join(", "),
)), )),
Value::ArgList(args) => Cow::owned( Value::ArgList(args) => Cow::owned(
args.iter() args.iter()
.filter(|x| !x.is_null()) .filter(|x| !x.is_null())
.map(|a| Ok(a.node.inspect(span)?)) .map(|a| a.node.inspect(span))
.collect::<SassResult<Vec<Cow<'static, str>>>>()? .collect::<SassResult<Vec<Cow<'static, str>>>>()?
.join(", "), .join(", "),
), ),