derive Copy for Identifier

This commit is contained in:
Connor Skees 2020-07-08 22:38:56 -04:00
parent 65b281d1f7
commit f9455caeea
11 changed files with 51 additions and 63 deletions

View File

@ -96,7 +96,7 @@ fn variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Va
args.max_args(1)?; args.max_args(1)?;
match parser.arg(&mut args, 0, "name")? { match parser.arg(&mut args, 0, "name")? {
Value::String(s, _) => Ok(Value::bool( Value::String(s, _) => Ok(Value::bool(
parser.scopes.var_exists(&s.into(), parser.global_scope), parser.scopes.var_exists(s.into(), parser.global_scope),
)), )),
v => Err(( v => Err((
format!("$name: {} is not a string.", v.inspect(args.span())?), format!("$name: {} is not a string.", v.inspect(args.span())?),
@ -109,7 +109,7 @@ fn variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Va
fn global_variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> { fn global_variable_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(1)?; args.max_args(1)?;
match parser.arg(&mut args, 0, "name")? { match parser.arg(&mut args, 0, "name")? {
Value::String(s, _) => Ok(Value::bool(parser.global_scope.var_exists(&s.into()))), Value::String(s, _) => Ok(Value::bool(parser.global_scope.var_exists(s.into()))),
v => Err(( v => Err((
format!("$name: {} is not a string.", v.inspect(args.span())?), format!("$name: {} is not a string.", v.inspect(args.span())?),
args.span(), args.span(),
@ -122,7 +122,7 @@ fn mixin_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
args.max_args(2)?; args.max_args(2)?;
match parser.arg(&mut args, 0, "name")? { match parser.arg(&mut args, 0, "name")? {
Value::String(s, _) => Ok(Value::bool( Value::String(s, _) => Ok(Value::bool(
parser.scopes.mixin_exists(&s.into(), parser.global_scope), parser.scopes.mixin_exists(s.into(), parser.global_scope),
)), )),
v => Err(( v => Err((
format!("$name: {} is not a string.", v.inspect(args.span())?), format!("$name: {} is not a string.", v.inspect(args.span())?),
@ -136,7 +136,7 @@ fn function_exists(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Va
args.max_args(2)?; args.max_args(2)?;
match parser.arg(&mut args, 0, "name")? { match parser.arg(&mut args, 0, "name")? {
Value::String(s, _) => Ok(Value::bool( Value::String(s, _) => Ok(Value::bool(
parser.scopes.fn_exists(&s.into(), parser.global_scope), parser.scopes.fn_exists(s.into(), parser.global_scope),
)), )),
v => Err(( v => Err((
format!("$name: {} is not a string.", v.inspect(args.span())?), format!("$name: {} is not a string.", v.inspect(args.span())?),
@ -183,7 +183,7 @@ fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value
let func = match parser.scopes.get_fn( let func = match parser.scopes.get_fn(
Spanned { Spanned {
node: &name, node: name,
span: args.span(), span: args.span(),
}, },
parser.global_scope, parser.global_scope,

View File

@ -112,7 +112,7 @@ impl ListSeparator {
/// ///
/// This struct protects that invariant by normalizing all /// This struct protects that invariant by normalizing all
/// underscores into hypens. /// underscores into hypens.
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Copy)]
pub(crate) struct Identifier(InternedString); pub(crate) struct Identifier(InternedString);
impl From<String> for Identifier { impl From<String> for Identifier {

View File

@ -75,6 +75,8 @@ grass input.scss
clippy::items_after_statements, clippy::items_after_statements,
clippy::shadow_reuse, clippy::shadow_reuse,
clippy::shadow_unrelated, clippy::shadow_unrelated,
// this is only available on nightly
clippy::unnested_or_patterns,
)] )]
#![cfg_attr(feature = "nightly", feature(track_caller))] #![cfg_attr(feature = "nightly", feature(track_caller))]
#![cfg_attr(feature = "profiling", inline(never))] #![cfg_attr(feature = "profiling", inline(never))]
@ -108,6 +110,7 @@ mod builtin;
mod color; mod color;
mod common; mod common;
mod error; mod error;
mod interner;
mod lexer; mod lexer;
mod output; mod output;
mod parse; mod parse;
@ -116,7 +119,6 @@ mod selector;
mod style; mod style;
mod token; mod token;
mod unit; mod unit;
mod interner;
mod utils; mod utils;
mod value; mod value;

View File

@ -363,7 +363,7 @@ impl<'a> Parser<'a> {
let span = args.span(); let span = args.span();
let arg_list = Value::ArgList(self.variadic_args(args)?); let arg_list = Value::ArgList(self.variadic_args(args)?);
scope.insert_var( scope.insert_var(
arg.name.clone(), arg.name,
Spanned { Spanned {
node: arg_list, node: arg_list,
span, span,
@ -371,7 +371,7 @@ impl<'a> Parser<'a> {
); );
break; break;
} }
let val = match args.get(idx, arg.name.clone()) { let val = match args.get(idx, arg.name) {
Some(v) => v, Some(v) => v,
None => match arg.default.as_mut() { None => match arg.default.as_mut() {
Some(v) => self.parse_value_from_vec(mem::take(v)), Some(v) => self.parse_value_from_vec(mem::take(v)),
@ -382,7 +382,7 @@ impl<'a> Parser<'a> {
} }
}, },
}?; }?;
self.scopes.insert_var(arg.name.clone(), val.clone()); self.scopes.insert_var(arg.name, val.clone());
scope.insert_var(arg.name, val); scope.insert_var(arg.name, val);
} }
self.scopes.exit_scope(); self.scopes.exit_scope();

View File

@ -295,7 +295,7 @@ impl<'a> Parser<'a> {
for i in iter { for i in iter {
self.scopes.insert_var( self.scopes.insert_var(
var.node.clone(), var.node,
Spanned { Spanned {
node: Value::Dimension(Number::from(i), Unit::None), node: Value::Dimension(Number::from(i), Unit::None),
span: var.span, span: var.span,
@ -467,7 +467,7 @@ impl<'a> Parser<'a> {
for row in iter { for row in iter {
if vars.len() == 1 { if vars.len() == 1 {
self.scopes.insert_var( self.scopes.insert_var(
vars[0].node.clone(), vars[0].node,
Spanned { Spanned {
node: row, node: row,
span: vars[0].span, span: vars[0].span,
@ -480,7 +480,7 @@ impl<'a> Parser<'a> {
.chain(std::iter::once(Value::Null).cycle()), .chain(std::iter::once(Value::Null).cycle()),
) { ) {
self.scopes.insert_var( self.scopes.insert_var(
var.node.clone(), var.node,
Spanned { Spanned {
node: val, node: val,
span: var.span, span: var.span,

View File

@ -112,13 +112,7 @@ impl<'a> Parser<'a> {
args: fn_args, args: fn_args,
declared_at_root, declared_at_root,
.. ..
} = self.scopes.get_mixin( } = self.scopes.get_mixin(name, self.global_scope)?;
{
let Spanned { ref node, span } = name;
Spanned { node, span }
},
self.global_scope,
)?;
let scope = self.eval_args(fn_args, args)?; let scope = self.eval_args(fn_args, args)?;

View File

@ -218,10 +218,7 @@ impl<'a> Parser<'a> {
styles.push(Style { property, value }); styles.push(Style { property, value });
} }
Some(Token { kind: '{', .. }) => { Some(Token { kind: '{', .. }) => {
styles.push(Style { styles.push(Style { property, value });
property: property.clone(),
value,
});
styles.append(&mut self.parse_style_group(property)?); styles.append(&mut self.parse_style_group(property)?);
} }
Some(..) | None => { Some(..) | None => {
@ -254,7 +251,7 @@ impl<'a> Parser<'a> {
} }
'{' => { '{' => {
let mut v = vec![Style { let mut v = vec![Style {
property: super_property.clone(), property: super_property,
value: Box::new(value), value: Box::new(value),
}]; }];
v.append(&mut self.parse_style_group(super_property)?); v.append(&mut self.parse_style_group(super_property)?);

View File

@ -258,7 +258,7 @@ impl<'a> Parser<'a> {
let as_ident = Identifier::from(&s); let as_ident = Identifier::from(&s);
let func = match self.scopes.get_fn( let func = match self.scopes.get_fn(
Spanned { Spanned {
node: &as_ident, node: as_ident,
span, span,
}, },
self.global_scope, self.global_scope,
@ -528,13 +528,7 @@ impl<'a> Parser<'a> {
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
}; };
IntermediateValue::Value(HigherIntermediateValue::Literal( IntermediateValue::Value(HigherIntermediateValue::Literal(
match self.scopes.get_var( match self.scopes.get_var(val, self.global_scope) {
{
let Spanned { ref node, span } = val;
Spanned { node, span }
},
self.global_scope,
) {
Ok(v) => v.clone(), Ok(v) => v.clone(),
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
}, },

View File

@ -41,25 +41,23 @@ impl<'a> Parser<'a> {
let value = self.parse_variable_value()?; let value = self.parse_variable_value()?;
if value.global && !value.default { if value.global && !value.default {
self.global_scope self.global_scope.insert_var(ident, value.value.clone());
.insert_var(ident.clone(), value.value.clone());
} }
if value.default { if value.default {
if self.at_root && !self.flags.in_control_flow() { if self.at_root && !self.flags.in_control_flow() {
if !self.global_scope.var_exists(&ident) { if !self.global_scope.var_exists(ident) {
self.global_scope.insert_var(ident, value.value); self.global_scope.insert_var(ident, value.value);
} }
} else { } else {
if value.global && !self.global_scope.var_exists(&ident) { if value.global && !self.global_scope.var_exists(ident) {
self.global_scope self.global_scope.insert_var(ident, value.value.clone());
.insert_var(ident.clone(), value.value.clone());
} }
self.scopes.insert_default_var(ident, value.value); self.scopes.insert_default_var(ident, value.value);
} }
} else if self.at_root { } else if self.at_root {
if self.flags.in_control_flow() { if self.flags.in_control_flow() {
if self.global_scope.var_exists(&ident) { if self.global_scope.var_exists(ident) {
self.global_scope.insert_var(ident, value.value); self.global_scope.insert_var(ident, value.value);
} else { } else {
self.scopes.insert_var(ident, value.value); self.scopes.insert_var(ident, value.value);

View File

@ -18,6 +18,8 @@ pub(crate) struct Scope {
} }
impl Scope { impl Scope {
// `BTreeMap::new` is not yet const
#[allow(clippy::missing_const_for_fn)]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -27,8 +29,8 @@ impl Scope {
} }
} }
fn get_var(&self, name: Spanned<&Identifier>) -> SassResult<&Value> { fn get_var(&self, name: Spanned<Identifier>) -> SassResult<&Value> {
match self.vars.get(name.node) { match self.vars.get(&name.node) {
Some(v) => Ok(&v.node), Some(v) => Ok(&v.node),
None => Err(("Undefined variable.", name.span).into()), None => Err(("Undefined variable.", name.span).into()),
} }
@ -38,12 +40,12 @@ impl Scope {
self.vars.insert(s, v) self.vars.insert(s, v)
} }
pub fn var_exists(&self, name: &Identifier) -> bool { pub fn var_exists(&self, name: Identifier) -> bool {
self.vars.contains_key(name) self.vars.contains_key(&name)
} }
fn get_mixin(&self, name: Spanned<&Identifier>) -> SassResult<Mixin> { fn get_mixin(&self, name: Spanned<Identifier>) -> SassResult<Mixin> {
match self.mixins.get(name.node) { match self.mixins.get(&name.node) {
Some(v) => Ok(v.clone()), Some(v) => Ok(v.clone()),
None => Err(("Undefined mixin.", name.span).into()), None => Err(("Undefined mixin.", name.span).into()),
} }
@ -53,23 +55,23 @@ impl Scope {
self.mixins.insert(s.into(), v) self.mixins.insert(s.into(), v)
} }
fn mixin_exists(&self, name: &Identifier) -> bool { fn mixin_exists(&self, name: Identifier) -> bool {
self.mixins.contains_key(name) self.mixins.contains_key(&name)
} }
fn get_fn(&self, name: &Identifier) -> Option<Function> { fn get_fn(&self, name: Identifier) -> Option<Function> {
self.functions.get(name).cloned() self.functions.get(&name).cloned()
} }
pub fn insert_fn<T: Into<Identifier>>(&mut self, s: T, v: Function) -> Option<Function> { pub fn insert_fn<T: Into<Identifier>>(&mut self, s: T, v: Function) -> Option<Function> {
self.functions.insert(s.into(), v) self.functions.insert(s.into(), v)
} }
fn fn_exists(&self, name: &Identifier) -> bool { fn fn_exists(&self, name: Identifier) -> bool {
if self.functions.is_empty() { if self.functions.is_empty() {
return false; return false;
} }
self.functions.contains_key(name) self.functions.contains_key(&name)
} }
fn merge(&mut self, other: Scope) { fn merge(&mut self, other: Scope) {
@ -112,7 +114,7 @@ impl Scopes {
impl Scopes { impl Scopes {
pub fn insert_var(&mut self, s: Identifier, v: Spanned<Value>) -> Option<Spanned<Value>> { pub fn insert_var(&mut self, s: Identifier, v: Spanned<Value>) -> Option<Spanned<Value>> {
for scope in self.0.iter_mut().rev() { for scope in self.0.iter_mut().rev() {
if scope.var_exists(&s) { if scope.var_exists(s) {
return scope.insert_var(s, v); return scope.insert_var(s, v);
} }
} }
@ -132,7 +134,7 @@ impl Scopes {
v: Spanned<Value>, v: Spanned<Value>,
) -> Option<Spanned<Value>> { ) -> Option<Spanned<Value>> {
if let Some(scope) = self.0.last_mut() { if let Some(scope) = self.0.last_mut() {
if scope.var_exists(&s) { if scope.var_exists(s) {
None None
} else { } else {
scope.insert_var(s, v) scope.insert_var(s, v)
@ -144,18 +146,18 @@ impl Scopes {
pub fn get_var<'a>( pub fn get_var<'a>(
&'a self, &'a self,
name: Spanned<&Identifier>, name: Spanned<Identifier>,
global_scope: &'a Scope, global_scope: &'a Scope,
) -> SassResult<&Value> { ) -> SassResult<&Value> {
for scope in self.0.iter().rev() { for scope in self.0.iter().rev() {
if scope.var_exists(&name.node) { if scope.var_exists(name.node) {
return scope.get_var(name); return scope.get_var(name);
} }
} }
global_scope.get_var(name) global_scope.get_var(name)
} }
pub fn var_exists(&self, name: &Identifier, global_scope: &Scope) -> bool { pub fn var_exists(&self, name: Identifier, global_scope: &Scope) -> bool {
for scope in &self.0 { for scope in &self.0 {
if scope.var_exists(name) { if scope.var_exists(name) {
return true; return true;
@ -180,18 +182,18 @@ impl Scopes {
pub fn get_mixin<'a>( pub fn get_mixin<'a>(
&'a self, &'a self,
name: Spanned<&Identifier>, name: Spanned<Identifier>,
global_scope: &'a Scope, global_scope: &'a Scope,
) -> SassResult<Mixin> { ) -> SassResult<Mixin> {
for scope in self.0.iter().rev() { for scope in self.0.iter().rev() {
if scope.mixin_exists(&name.node) { if scope.mixin_exists(name.node) {
return scope.get_mixin(name); return scope.get_mixin(name);
} }
} }
global_scope.get_mixin(name) global_scope.get_mixin(name)
} }
pub fn mixin_exists(&self, name: &Identifier, global_scope: &Scope) -> bool { pub fn mixin_exists(&self, name: Identifier, global_scope: &Scope) -> bool {
for scope in &self.0 { for scope in &self.0 {
if scope.mixin_exists(name) { if scope.mixin_exists(name) {
return true; return true;
@ -216,18 +218,18 @@ impl Scopes {
pub fn get_fn<'a>( pub fn get_fn<'a>(
&'a self, &'a self,
name: Spanned<&Identifier>, name: Spanned<Identifier>,
global_scope: &'a Scope, global_scope: &'a Scope,
) -> Option<Function> { ) -> Option<Function> {
for scope in self.0.iter().rev() { for scope in self.0.iter().rev() {
if scope.fn_exists(&name.node) { if scope.fn_exists(name.node) {
return scope.get_fn(name.node); return scope.get_fn(name.node);
} }
} }
global_scope.get_fn(name.node) global_scope.get_fn(name.node)
} }
pub fn fn_exists(&self, name: &Identifier, global_scope: &Scope) -> bool { pub fn fn_exists(&self, name: Identifier, global_scope: &Scope) -> bool {
for scope in &self.0 { for scope in &self.0 {
if scope.fn_exists(name) { if scope.fn_exists(name) {
return true; return true;

View File

@ -107,6 +107,7 @@ pub(crate) enum Unit {
/// Units multiplied together /// Units multiplied together
/// Boxed under the assumption that mul units are exceedingly rare /// Boxed under the assumption that mul units are exceedingly rare
#[allow(clippy::box_vec)]
Mul(Box<Vec<Unit>>), Mul(Box<Vec<Unit>>),
/// Units divided by each other /// Units divided by each other