diff --git a/src/ast/args.rs b/src/ast/args.rs index c581d55..1233eea 100644 --- a/src/ast/args.rs +++ b/src/ast/args.rs @@ -81,7 +81,8 @@ impl ArgumentDeclaration { } else { "arguments" }, - if num_positional == 1 { "was" } else { "were" } + if num_positional == 1 { "was" } else { "were" }, + num_positional = num_positional, ), span, ) @@ -113,7 +114,7 @@ impl ArgumentDeclaration { to_sentence( unknown_names .into_iter() - .map(|name| format!("${name}")) + .map(|name| format!("${name}", name = name)) .collect(), "or" ) @@ -234,7 +235,7 @@ impl ArgumentResult { if len > max { let mut err = String::with_capacity(50); #[allow(clippy::format_push_string)] - err.push_str(&format!("Only {} argument", max)); + err.push_str(&format!("Only {max} argument", max = max)); if max != 1 { err.push('s'); } diff --git a/src/builtin/functions/color/hsl.rs b/src/builtin/functions/color/hsl.rs index 43b1dd3..9920c3d 100644 --- a/src/builtin/functions/color/hsl.rs +++ b/src/builtin/functions/color/hsl.rs @@ -103,15 +103,15 @@ fn inner_hsl( let saturation = args.get_err(1, "saturation")?; if hue.is_var() || saturation.is_var() { - return Ok(Value::String( + Ok(Value::String( function_string(name, &[hue, saturation], visitor, span)?, QuoteKind::None, - )); + )) } else { - return Err(("Missing argument $lightness.", args.span()).into()); + Err(("Missing argument $lightness.", args.span()).into()) } } else { - return hsl_3_args(name, args, visitor); + hsl_3_args(name, args, visitor) } } diff --git a/src/builtin/functions/color/rgb.rs b/src/builtin/functions/color/rgb.rs index 23a1c01..12ba5e2 100644 --- a/src/builtin/functions/color/rgb.rs +++ b/src/builtin/functions/color/rgb.rs @@ -162,7 +162,8 @@ pub(crate) fn percentage_or_unitless( return Err(( format!( "${name}: Expected {} to have no units or \"%\".", - inspect_number(number, visitor.options, span)? + inspect_number(number, visitor.options, span)?, + name = name, ), span, ) @@ -279,7 +280,11 @@ pub(crate) fn parse_channels( return Ok(ParsedChannels::String(fn_string)); } else { let argument = arg_names[list.len()]; - return Err((format!("Missing element ${argument}."), span).into()); + return Err(( + format!("Missing element ${argument}.", argument = argument), + span, + ) + .into()); } } diff --git a/src/builtin/modules/meta.rs b/src/builtin/modules/meta.rs index 0d66175..9e86e50 100644 --- a/src/builtin/modules/meta.rs +++ b/src/builtin/modules/meta.rs @@ -57,7 +57,7 @@ fn load_css(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult<()> { if values.contains_key(&name) { // todo: write test for this return Err(( - format!("The variable {name} was configured twice."), + format!("The variable {name} was configured twice.", name = name), key.span, ) .into()); diff --git a/src/evaluate/env.rs b/src/evaluate/env.rs index 87e08a4..0fde857 100644 --- a/src/evaluate/env.rs +++ b/src/evaluate/env.rs @@ -263,7 +263,7 @@ impl Environment { for name in (*self.scopes.global_variables()).borrow().keys() { if (*module).borrow().var_exists(*name) { return Err(( - format!("This module and the new module both define a variable named \"{name}\".") + format!("This module and the new module both define a variable named \"{}\".", name = name) , span).into()); } } diff --git a/src/evaluate/visitor.rs b/src/evaluate/visitor.rs index 6f1bec6..bf15e55 100644 --- a/src/evaluate/visitor.rs +++ b/src/evaluate/visitor.rs @@ -474,7 +474,7 @@ impl<'a> Visitor<'a> { let children = supports_rule.children; - self.with_parent::>( + self.with_parent( css_supports_rule, true, |visitor| { @@ -496,7 +496,7 @@ impl<'a> Visitor<'a> { is_group_end: false, }; - visitor.with_parent::>( + visitor.with_parent( ruleset, false, |visitor| { @@ -529,7 +529,7 @@ impl<'a> Visitor<'a> { let env = Environment::new(); let mut extension_store = ExtensionStore::new(self.span_before); - self.with_environment::>(env.new_closure(), |visitor| { + self.with_environment::, _>(env.new_closure(), |visitor| { let old_parent = visitor.parent; mem::swap(&mut visitor.extender, &mut extension_store); let old_style_rule = visitor.style_rule_ignoring_at_root.take(); @@ -698,7 +698,10 @@ impl<'a> Visitor<'a> { let Spanned { node: name, span } = config.first().unwrap(); let msg = if name_in_error { - format!("${name} was not declared with !default in the @used module.") + format!( + "${name} was not declared with !default in the @used module.", + name = name + ) } else { "This variable was not declared with !default in the @used module.".to_owned() }; @@ -907,6 +910,7 @@ impl<'a> Visitor<'a> { fn visit_content_rule(&mut self, content_rule: AstContentRule) -> SassResult> { let span = content_rule.args.span; if let Some(content) = &self.env.content { + #[allow(mutable_borrow_reservation_conflict)] self.run_user_defined_callable( MaybeEvaledArguments::Invocation(content_rule.args), Arc::clone(content), @@ -1008,7 +1012,7 @@ impl<'a> Visitor<'a> { // If we didn't exclude any rules, we don't need to use the copies we might // have created. if Some(root) == self.parent { - self.with_scope::>(false, true, |visitor| { + self.with_scope::, _>(false, true, |visitor| { for stmt in at_root_rule.children { let result = visitor.visit_stmt(stmt)?; debug_assert!(result.is_none()); @@ -1053,7 +1057,7 @@ impl<'a> Visitor<'a> { let body = mem::take(&mut at_root_rule.children); - self.with_scope_for_at_root::>(inner_copy, &query, |visitor| { + self.with_scope_for_at_root::, _>(inner_copy, &query, |visitor| { for stmt in body { let result = visitor.visit_stmt(stmt)?; debug_assert!(result.is_none()); @@ -1065,11 +1069,11 @@ impl<'a> Visitor<'a> { Ok(None) } - fn with_scope_for_at_root( + fn with_scope_for_at_root T>( &mut self, new_parent_idx: Option, query: &AtRootQuery, - callback: impl FnOnce(&mut Self) -> T, + callback: F, ) -> T { let old_parent = self.parent; self.parent = new_parent_idx; @@ -1272,7 +1276,7 @@ impl<'a> Visitor<'a> { false, ); - self.with_parent::>( + self.with_parent( media_rule, true, |visitor| { @@ -1298,7 +1302,7 @@ impl<'a> Visitor<'a> { is_group_end: false, }; - visitor.with_parent::>( + visitor.with_parent( ruleset, false, |visitor| { @@ -1390,7 +1394,7 @@ impl<'a> Visitor<'a> { false, ); - self.with_parent::>( + self.with_parent( stmt, true, |visitor| { @@ -1412,7 +1416,7 @@ impl<'a> Visitor<'a> { is_group_end: false, }; - visitor.with_parent::>( + visitor.with_parent( style_rule, false, |visitor| { @@ -1479,10 +1483,10 @@ impl<'a> Visitor<'a> { result } - fn with_environment( + fn with_environment T>( &mut self, env: Environment, - callback: impl FnOnce(&mut Self) -> T, + callback: F, ) -> T { let mut old_env = env; mem::swap(&mut self.env, &mut old_env); @@ -1491,10 +1495,10 @@ impl<'a> Visitor<'a> { val } - fn add_child( + fn add_child bool>( &mut self, node: CssStmt, - through: Option bool>, + through: Option, ) -> CssTreeIdx { if self.parent.is_none() || self.parent == Some(CssTree::ROOT) { return self.css_tree.add_stmt(node, self.parent); @@ -1530,15 +1534,15 @@ impl<'a> Visitor<'a> { self.css_tree.add_child(node, parent) } - fn with_parent( + fn with_parent SassResult<()>, FT: Fn(&CssStmt) -> bool>( &mut self, parent: CssStmt, // default=true scope_when: bool, - callback: impl FnOnce(&mut Self) -> T, + callback: F, // todo: optional - through: impl Fn(&CssStmt) -> bool, - ) -> T { + through: FT, + ) -> SassResult<()> { let parent_idx = self.add_child(parent, Some(through)); let old_parent = self.parent; self.parent = Some(parent_idx); @@ -1547,13 +1551,13 @@ impl<'a> Visitor<'a> { result } - fn with_scope( + fn with_scope T>( &mut self, // default=false semi_global: bool, // default=true when: bool, - callback: impl FnOnce(&mut Self) -> T, + callback: F, ) -> T { let semi_global = semi_global && self.flags.in_semi_global_scope(); let was_in_semi_global_scope = self.flags.in_semi_global_scope(); @@ -1624,7 +1628,7 @@ impl<'a> Visitor<'a> { }) }); - self.run_user_defined_callable::<_, ()>( + self.run_user_defined_callable::<_, (), _>( MaybeEvaledArguments::Invocation(args), mixin, &env, @@ -1767,7 +1771,7 @@ impl<'a> Visitor<'a> { } fn visit_while_stmt(&mut self, while_stmt: &AstWhile) -> SassResult> { - self.with_scope::>>(true, true, |visitor| { + self.with_scope(true, true, |visitor| { let mut result = None; 'outer: while visitor.visit_expr(while_stmt.condition.clone())?.is_true() { @@ -2094,13 +2098,17 @@ impl<'a> Visitor<'a> { Ok(()) } - fn run_user_defined_callable( + fn run_user_defined_callable< + F: UserDefinedCallable, + V: fmt::Debug, + R: FnOnce(F, &mut Self) -> SassResult, + >( &mut self, arguments: MaybeEvaledArguments, func: F, env: &Environment, span: Span, - run: impl FnOnce(F, &mut Self) -> SassResult, + run: R, ) -> SassResult { let mut evaluated = self.eval_maybe_args(arguments, span)?; @@ -2110,7 +2118,7 @@ impl<'a> Visitor<'a> { name.push_str("()"); } - self.with_environment::>(env.new_closure(), |visitor| { + self.with_environment(env.new_closure(), |visitor| { visitor.with_scope(false, true, move |visitor| { func.arguments().verify( evaluated.positional.len(), @@ -2204,12 +2212,20 @@ impl<'a> Visitor<'a> { evaluated .named .keys() - .map(|key| format!("${key}")) + .map(|key| format!("${key}", key = key)) .collect(), "or", ); - Err((format!("No {argument_word} named {argument_names}."), span).into()) + Err(( + format!( + "No {argument_word} named {argument_names}.", + argument_word = argument_word, + argument_names = argument_names + ), + span, + ) + .into()) }) }) } @@ -2762,7 +2778,7 @@ impl<'a> Visitor<'a> { body: Vec::new(), }); - self.with_parent::>( + self.with_parent( keyframes_ruleset, true, |visitor| { @@ -2813,7 +2829,7 @@ impl<'a> Visitor<'a> { let old_style_rule_ignoring_at_root = self.style_rule_ignoring_at_root.take(); self.style_rule_ignoring_at_root = Some(selector); - self.with_parent::>( + self.with_parent( rule, true, |visitor| { @@ -2910,7 +2926,7 @@ impl<'a> Visitor<'a> { if !children.is_empty() { let old_declaration_name = self.declaration_name.take(); self.declaration_name = Some(name); - self.with_scope::>(false, true, |visitor| { + self.with_scope::, _>(false, true, |visitor| { for stmt in children { let result = visitor.visit_stmt(stmt)?; debug_assert!(result.is_none()); diff --git a/src/lib.rs b/src/lib.rs index ea67dab..a851e56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,8 @@ grass input.scss clippy::wildcard_imports, clippy::comparison_chain, clippy::bool_to_int_with_if, + + unknown_lints, )] use std::path::Path; diff --git a/src/main.rs b/src/main.rs index 63636c3..3546d38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -205,7 +205,7 @@ fn main() -> std::io::Result<()> { .open(path)?; &mut file_write } else { - stdout_write = stdout().lock(); + stdout_write = stdout(); &mut stdout_write }; diff --git a/src/parse/base.rs b/src/parse/base.rs index dc37a3f..17796d6 100644 --- a/src/parse/base.rs +++ b/src/parse/base.rs @@ -330,7 +330,11 @@ pub(crate) trait BaseParser<'a> { } if !found_matching_quote { - return Err((format!("Expected {quote}."), self.toks().current_span()).into()); + return Err(( + format!("Expected {quote}.", quote = quote), + self.toks().current_span(), + ) + .into()); } Ok(buffer) diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 90a0a64..ae9cb92 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -20,6 +20,7 @@ mod stylesheet; mod value; #[derive(Debug, Clone)] +#[allow(clippy::large_enum_variant)] pub(crate) enum DeclarationOrBuffer { Stmt(AstStmt), Buffer(Interpolation), diff --git a/src/parse/sass.rs b/src/parse/sass.rs index 88ae30c..905cd94 100644 --- a/src/parse/sass.rs +++ b/src/parse/sass.rs @@ -511,7 +511,10 @@ impl<'a> SassParser<'a> { if child_indent != indentation { return Err(( - format!("Inconsistent indentation, expected {child_indent} spaces."), + format!( + "Inconsistent indentation, expected {child_indent} spaces.", + child_indent = child_indent + ), self.toks.current_span(), ) .into()); diff --git a/src/parse/stylesheet.rs b/src/parse/stylesheet.rs index 391e5b9..8e6808e 100644 --- a/src/parse/stylesheet.rs +++ b/src/parse/stylesheet.rs @@ -1044,7 +1044,11 @@ pub(crate) trait StylesheetParser<'a>: BaseParser<'a> + Sized { } if !found_match { - return Err((format!("Expected {quote}."), self.toks().current_span()).into()); + return Err(( + format!("Expected {quote}.", quote = quote), + self.toks().current_span(), + ) + .into()); } Ok(Spanned { @@ -1547,7 +1551,10 @@ pub(crate) trait StylesheetParser<'a>: BaseParser<'a> + Sized { (Ok(i), true) => Ok(Some(i)), _ => { Err(( - format!("The default namespace \"{namespace}\" is not a valid Sass identifier.\n\nRecommendation: add an \"as\" clause to define an explicit namespace."), + format!( + "The default namespace \"{namespace}\" is not a valid Sass identifier.\n\nRecommendation: add an \"as\" clause to define an explicit namespace.", + namespace = namespace + ), self.toks_mut().span_from(start) ).into()) } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index caa302c..df49572 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -92,6 +92,7 @@ pub(crate) fn to_sentence>(mut elems: Vec, conjunction: &'sta .map(Into::into) .collect::>() .join(", "), - last.into() + last.into(), + conjunction = conjunction, ) } diff --git a/src/value/calculation.rs b/src/value/calculation.rs index b086376..c938b3c 100644 --- a/src/value/calculation.rs +++ b/src/value/calculation.rs @@ -245,7 +245,9 @@ impl SassCalculation { Err(( format!( "{len} arguments required, but only {} {was_or_were} passed.", - args.len() + args.len(), + len = len, + was_or_were = was_or_were, ), span, ) diff --git a/src/value/mod.rs b/src/value/mod.rs index e4ebd35..ba85034 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -228,7 +228,11 @@ impl Value { match self { Value::Dimension(n) => Ok(n), _ => Err(( - format!("${name}: {} is not a number.", self.inspect(span)?), + format!( + "${name}: {} is not a number.", + self.inspect(span)?, + name = name, + ), span, ) .into()), @@ -239,7 +243,11 @@ impl Value { match self { Value::Color(c) => Ok(*c), _ => Err(( - format!("${name}: {} is not a color.", self.inspect(span)?), + format!( + "${name}: {} is not a color.", + self.inspect(span)?, + name = name, + ), span, ) .into()), diff --git a/src/value/number.rs b/src/value/number.rs index 349a142..6dee36a 100644 --- a/src/value/number.rs +++ b/src/value/number.rs @@ -121,7 +121,11 @@ impl Number { match fuzzy_as_int(self.0) { Some(i) => Ok(i), None => Err(( - format!("${name}: {} is not an int.", self.to_string(false)), + format!( + "${name}: {} is not an int.", + self.to_string(false), + name = name, + ), span, ) .into()), diff --git a/src/value/sass_number.rs b/src/value/sass_number.rs index b18f966..f31378e 100644 --- a/src/value/sass_number.rs +++ b/src/value/sass_number.rs @@ -136,7 +136,8 @@ impl SassNumber { Err(( format!( "${name}: Expected {} to have no units.", - inspect_number(self, &Options::default(), span)? + inspect_number(self, &Options::default(), span)?, + name = name, ), span, ) @@ -151,7 +152,9 @@ impl SassNumber { Err(( format!( "${name}: Expected {} to have unit \"{unit}\".", - inspect_number(self, &Options::default(), span)? + inspect_number(self, &Options::default(), span)?, + name = name, + unit = unit, ), span, ) diff --git a/tests/imports.rs b/tests/imports.rs index 4b6b852..fa40860 100644 --- a/tests/imports.rs +++ b/tests/imports.rs @@ -448,7 +448,6 @@ fn chained_imports_in_directory() { &grass::from_string(input.to_string(), &grass::Options::default()).expect(input) ); } - error!( // note: dart-sass error is "expected more input." missing_input_after_import,