This commit is contained in:
Connor Skees 2024-08-04 18:27:24 +00:00
parent e0f0be112a
commit c80ab399aa
7 changed files with 43 additions and 48 deletions

View File

@ -23,7 +23,7 @@ bench = false
rustdoc-args = ["--cfg", "doc_cfg"] rustdoc-args = ["--cfg", "doc_cfg"]
[dependencies] [dependencies]
# todo: use lazy_static # todo: replace with std::cell::LazyCell (msrv 1.80.0)
once_cell = "1.15.0" once_cell = "1.15.0"
# todo: use xorshift for random numbers # todo: use xorshift for random numbers
rand = { version = "0.8", optional = true } rand = { version = "0.8", optional = true }

View File

@ -2,6 +2,7 @@ use std::{
cell::RefCell, cell::RefCell,
collections::{BTreeMap, HashSet}, collections::{BTreeMap, HashSet},
path::PathBuf, path::PathBuf,
rc::Rc,
sync::Arc, sync::Arc,
}; };
@ -301,17 +302,17 @@ pub struct ConfiguredVariable {
pub struct Configuration { pub struct Configuration {
pub(crate) values: Arc<dyn MapView<Value = ConfiguredValue>>, pub(crate) values: Arc<dyn MapView<Value = ConfiguredValue>>,
#[allow(unused)] #[allow(unused)]
pub(crate) original_config: Option<Arc<RefCell<Self>>>, pub(crate) original_config: Option<Rc<RefCell<Self>>>,
pub(crate) span: Option<Span>, pub(crate) span: Option<Span>,
} }
impl Configuration { impl Configuration {
pub fn through_forward( pub fn through_forward(
config: Arc<RefCell<Self>>, config: Rc<RefCell<Self>>,
forward: &AstForwardRule, forward: &AstForwardRule,
) -> Arc<RefCell<Self>> { ) -> Rc<RefCell<Self>> {
if (*config).borrow().is_empty() { if (*config).borrow().is_empty() {
return Arc::new(RefCell::new(Configuration::empty())); return Rc::new(RefCell::new(Configuration::empty()));
} }
let mut new_values = Arc::clone(&(*config).borrow().values); let mut new_values = Arc::clone(&(*config).borrow().values);
@ -330,14 +331,14 @@ impl Configuration {
new_values = Arc::new(LimitedMapView::blocklist(new_values, hidden_variables)); new_values = Arc::new(LimitedMapView::blocklist(new_values, hidden_variables));
} }
Arc::new(RefCell::new(Self::with_values( Rc::new(RefCell::new(Self::with_values(
config, config,
Arc::clone(&new_values), Arc::clone(&new_values),
))) )))
} }
fn with_values( fn with_values(
config: Arc<RefCell<Self>>, config: Rc<RefCell<Self>>,
values: Arc<dyn MapView<Value = ConfiguredValue>>, values: Arc<dyn MapView<Value = ConfiguredValue>>,
) -> Self { ) -> Self {
Self { Self {
@ -394,10 +395,10 @@ impl Configuration {
} }
#[allow(unused)] #[allow(unused)]
pub fn original_config(config: Arc<RefCell<Configuration>>) -> Arc<RefCell<Configuration>> { pub fn original_config(config: Rc<RefCell<Configuration>>) -> Rc<RefCell<Configuration>> {
match (*config).borrow().original_config.as_ref() { match (*config).borrow().original_config.as_ref() {
Some(v) => Arc::clone(v), Some(v) => Rc::clone(v),
None => Arc::clone(&config), None => Rc::clone(&config),
} }
} }
} }

View File

@ -6,6 +6,7 @@ use std::{
iter::FromIterator, iter::FromIterator,
mem, mem,
path::{Path, PathBuf}, path::{Path, PathBuf},
rc::Rc,
sync::Arc, sync::Arc,
}; };
@ -120,7 +121,7 @@ pub struct Visitor<'a> {
pub(crate) active_modules: BTreeSet<PathBuf>, pub(crate) active_modules: BTreeSet<PathBuf>,
css_tree: CssTree, css_tree: CssTree,
parent: Option<CssTreeIdx>, parent: Option<CssTreeIdx>,
configuration: Arc<RefCell<Configuration>>, configuration: Rc<RefCell<Configuration>>,
import_nodes: Vec<CssStmt>, import_nodes: Vec<CssStmt>,
pub options: &'a Options<'a>, pub options: &'a Options<'a>,
pub(crate) map: &'a mut CodeMap, pub(crate) map: &'a mut CodeMap,
@ -159,7 +160,7 @@ impl<'a> Visitor<'a> {
css_tree: CssTree::new(), css_tree: CssTree::new(),
parent: None, parent: None,
current_import_path, current_import_path,
configuration: Arc::new(RefCell::new(Configuration::empty())), configuration: Rc::new(RefCell::new(Configuration::empty())),
is_plain_css: false, is_plain_css: false,
import_nodes: Vec::new(), import_nodes: Vec::new(),
modules: BTreeMap::new(), modules: BTreeMap::new(),
@ -257,17 +258,16 @@ impl<'a> Visitor<'a> {
} }
fn visit_forward_rule(&mut self, forward_rule: AstForwardRule) -> SassResult<()> { fn visit_forward_rule(&mut self, forward_rule: AstForwardRule) -> SassResult<()> {
let old_config = Arc::clone(&self.configuration); let old_config = Rc::clone(&self.configuration);
let adjusted_config = let adjusted_config = Configuration::through_forward(Rc::clone(&old_config), &forward_rule);
Configuration::through_forward(Arc::clone(&old_config), &forward_rule);
if !forward_rule.configuration.is_empty() { if !forward_rule.configuration.is_empty() {
let new_configuration = let new_configuration =
self.add_forward_configuration(Arc::clone(&adjusted_config), &forward_rule)?; self.add_forward_configuration(Rc::clone(&adjusted_config), &forward_rule)?;
self.load_module( self.load_module(
forward_rule.url.as_path(), forward_rule.url.as_path(),
Some(Arc::clone(&new_configuration)), Some(Rc::clone(&new_configuration)),
false, false,
forward_rule.span, forward_rule.span,
|visitor, module, _| { |visitor, module, _| {
@ -334,9 +334,9 @@ impl<'a> Visitor<'a> {
#[allow(clippy::unnecessary_unwrap)] #[allow(clippy::unnecessary_unwrap)]
fn add_forward_configuration( fn add_forward_configuration(
&mut self, &mut self,
config: Arc<RefCell<Configuration>>, config: Rc<RefCell<Configuration>>,
forward_rule: &AstForwardRule, forward_rule: &AstForwardRule,
) -> SassResult<Arc<RefCell<Configuration>>> { ) -> SassResult<Rc<RefCell<Configuration>>> {
let mut new_values = BTreeMap::from_iter((*config).borrow().values.iter()); let mut new_values = BTreeMap::from_iter((*config).borrow().values.iter());
for variable in &forward_rule.configuration { for variable in &forward_rule.configuration {
@ -367,7 +367,7 @@ impl<'a> Visitor<'a> {
); );
} }
Ok(Arc::new(RefCell::new( Ok(Rc::new(RefCell::new(
if !(*config).borrow().is_implicit() || (*config).borrow().is_empty() { if !(*config).borrow().is_implicit() || (*config).borrow().is_empty() {
Configuration::explicit(new_values, forward_rule.span) Configuration::explicit(new_values, forward_rule.span)
} else { } else {
@ -379,8 +379,8 @@ impl<'a> Visitor<'a> {
/// Remove configured values from [upstream] that have been removed from /// Remove configured values from [upstream] that have been removed from
/// [downstream], unless they match a name in [except]. /// [downstream], unless they match a name in [except].
fn remove_used_configuration( fn remove_used_configuration(
upstream: &Arc<RefCell<Configuration>>, upstream: &Rc<RefCell<Configuration>>,
downstream: &Arc<RefCell<Configuration>>, downstream: &Rc<RefCell<Configuration>>,
except: &HashSet<Identifier>, except: &HashSet<Identifier>,
) { ) {
let mut names_to_remove = Vec::new(); let mut names_to_remove = Vec::new();
@ -542,7 +542,7 @@ impl<'a> Visitor<'a> {
fn execute( fn execute(
&mut self, &mut self,
stylesheet: StyleSheet, stylesheet: StyleSheet,
configuration: Option<Arc<RefCell<Configuration>>>, configuration: Option<Rc<RefCell<Configuration>>>,
// todo: different errors based on this // todo: different errors based on this
_names_in_errors: bool, _names_in_errors: bool,
) -> SassResult<Arc<RefCell<Module>>> { ) -> SassResult<Arc<RefCell<Module>>> {
@ -551,7 +551,7 @@ impl<'a> Visitor<'a> {
// todo: use canonical url for modules // todo: use canonical url for modules
if let Some(already_loaded) = self.modules.get(&stylesheet.url) { if let Some(already_loaded) = self.modules.get(&stylesheet.url) {
let current_configuration = let current_configuration =
configuration.unwrap_or_else(|| Arc::clone(&self.configuration)); configuration.unwrap_or_else(|| Rc::clone(&self.configuration));
if !current_configuration.borrow().is_implicit() { if !current_configuration.borrow().is_implicit() {
// if (!_moduleConfigurations[url]!.sameOriginal(currentConfiguration) && // if (!_moduleConfigurations[url]!.sameOriginal(currentConfiguration) &&
@ -643,7 +643,7 @@ impl<'a> Visitor<'a> {
pub(crate) fn load_module( pub(crate) fn load_module(
&mut self, &mut self,
url: &Path, url: &Path,
configuration: Option<Arc<RefCell<Configuration>>>, configuration: Option<Rc<RefCell<Configuration>>>,
names_in_errors: bool, names_in_errors: bool,
span: Span, span: Span,
callback: impl Fn(&mut Self, Arc<RefCell<Module>>, StyleSheet) -> SassResult<()>, callback: impl Fn(&mut Self, Arc<RefCell<Module>>, StyleSheet) -> SassResult<()>,
@ -714,7 +714,7 @@ impl<'a> Visitor<'a> {
fn visit_use_rule(&mut self, use_rule: AstUseRule) -> SassResult<()> { fn visit_use_rule(&mut self, use_rule: AstUseRule) -> SassResult<()> {
let configuration = if use_rule.configuration.is_empty() { let configuration = if use_rule.configuration.is_empty() {
Arc::new(RefCell::new(Configuration::empty())) Rc::new(RefCell::new(Configuration::empty()))
} else { } else {
let mut values = BTreeMap::new(); let mut values = BTreeMap::new();
@ -727,7 +727,7 @@ impl<'a> Visitor<'a> {
); );
} }
Arc::new(RefCell::new(Configuration::explicit(values, use_rule.span))) Rc::new(RefCell::new(Configuration::explicit(values, use_rule.span)))
}; };
let span = use_rule.span; let span = use_rule.span;
@ -739,7 +739,7 @@ impl<'a> Visitor<'a> {
self.load_module( self.load_module(
&use_rule.url, &use_rule.url,
Some(Arc::clone(&configuration)), Some(Rc::clone(&configuration)),
false, false,
span, span,
|visitor, module, _| { |visitor, module, _| {
@ -755,7 +755,7 @@ impl<'a> Visitor<'a> {
} }
pub(crate) fn assert_configuration_is_empty( pub(crate) fn assert_configuration_is_empty(
config: &Arc<RefCell<Configuration>>, config: &Rc<RefCell<Configuration>>,
name_in_error: bool, name_in_error: bool,
) -> SassResult<()> { ) -> SassResult<()> {
let config = (**config).borrow(); let config = (**config).borrow();
@ -960,7 +960,7 @@ impl<'a> Visitor<'a> {
self.with_environment::<SassResult<()>, _>(env.clone(), |visitor| { self.with_environment::<SassResult<()>, _>(env.clone(), |visitor| {
let old_parent = visitor.parent; let old_parent = visitor.parent;
let old_configuration = Arc::clone(&visitor.configuration); let old_configuration = Rc::clone(&visitor.configuration);
if loads_user_defined_modules { if loads_user_defined_modules {
visitor.parent = Some(CssTree::ROOT); visitor.parent = Some(CssTree::ROOT);
@ -969,7 +969,7 @@ impl<'a> Visitor<'a> {
// This configuration is only used if it passes through a `@forward` // This configuration is only used if it passes through a `@forward`
// rule, so we avoid creating unnecessary ones for performance reasons. // rule, so we avoid creating unnecessary ones for performance reasons.
if !stylesheet.forwards.is_empty() { if !stylesheet.forwards.is_empty() {
visitor.configuration = Arc::new(RefCell::new(env.to_implicit_configuration())); visitor.configuration = Rc::new(RefCell::new(env.to_implicit_configuration()));
} }
visitor.visit_stylesheet(stylesheet)?; visitor.visit_stylesheet(stylesheet)?;
@ -2284,7 +2284,7 @@ impl<'a> Visitor<'a> {
visitor.env.scopes_mut().insert_var_last(name, value); visitor.env.scopes_mut().insert_var_last(name, value);
} }
let were_keywords_accessed = Arc::new(Cell::new(false)); let were_keywords_accessed = Rc::new(Cell::new(false));
let num_named_args = evaluated.named.len(); let num_named_args = evaluated.named.len();
@ -2297,7 +2297,7 @@ impl<'a> Visitor<'a> {
let arg_list = Value::ArgList(ArgList::new( let arg_list = Value::ArgList(ArgList::new(
rest, rest,
Arc::clone(&were_keywords_accessed), Rc::clone(&were_keywords_accessed),
// todo: superfluous clone // todo: superfluous clone
evaluated.named.clone(), evaluated.named.clone(),
if evaluated.separator == ListSeparator::Undecided { if evaluated.separator == ListSeparator::Undecided {

View File

@ -47,21 +47,14 @@ grass input.scss
clippy::multiple_crate_versions, clippy::multiple_crate_versions,
clippy::wrong_self_convention, clippy::wrong_self_convention,
clippy::comparison_chain, clippy::comparison_chain,
clippy::unwrap_or_default,
// these features are only available on nightly clippy::manual_unwrap_or_default,
clippy::unnested_or_patterns,
clippy::uninlined_format_args,
// todo: these should be enabled // todo: these should be enabled
clippy::cast_sign_loss, clippy::arc_with_non_send_sync,
clippy::cast_lossless,
clippy::cast_precision_loss,
clippy::float_cmp,
// todo: unignore once we bump MSRV // todo: unignore once we bump MSRV
clippy::format_push_string, clippy::assigning_clones,
clippy::unnecessary_unwrap,
clippy::needless_late_init,
unknown_lints, unknown_lints,
)] )]

View File

@ -18,7 +18,7 @@ pub(crate) struct KeyframesSelectorParser {
toks: Lexer, toks: Lexer,
} }
impl<'a> BaseParser for KeyframesSelectorParser { impl BaseParser for KeyframesSelectorParser {
fn toks(&self) -> &Lexer { fn toks(&self) -> &Lexer {
&self.toks &self.toks
} }

View File

@ -1,4 +1,4 @@
use std::{cell::Cell, collections::BTreeMap, sync::Arc}; use std::{cell::Cell, collections::BTreeMap, rc::Rc};
use crate::common::{Identifier, ListSeparator}; use crate::common::{Identifier, ListSeparator};
@ -7,7 +7,7 @@ use super::Value;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ArgList { pub struct ArgList {
pub elems: Vec<Value>, pub elems: Vec<Value>,
were_keywords_accessed: Arc<Cell<bool>>, were_keywords_accessed: Rc<Cell<bool>>,
// todo: special wrapper around this field to avoid having to make it private? // todo: special wrapper around this field to avoid having to make it private?
keywords: BTreeMap<Identifier, Value>, keywords: BTreeMap<Identifier, Value>,
pub separator: ListSeparator, pub separator: ListSeparator,
@ -26,7 +26,7 @@ impl Eq for ArgList {}
impl ArgList { impl ArgList {
pub fn new( pub fn new(
elems: Vec<Value>, elems: Vec<Value>,
were_keywords_accessed: Arc<Cell<bool>>, were_keywords_accessed: Rc<Cell<bool>>,
keywords: BTreeMap<Identifier, Value>, keywords: BTreeMap<Identifier, Value>,
separator: ListSeparator, separator: ListSeparator,
) -> Self { ) -> Self {

View File

@ -363,6 +363,7 @@ impl SassCalculation {
BinaryOp::Plus BinaryOp::Plus
} }
} else { } else {
// todo: do we need this branch?
} }
right = CalculationArg::Number(n); right = CalculationArg::Number(n);
} }