From c2384595e8223f12b0e80db9b796af58d1762592 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Sun, 12 Jul 2020 13:09:16 -0400 Subject: [PATCH] improve span context in `@extend`, removing some potential panics --- src/parse/mod.rs | 2 +- src/selector/extend/extension.rs | 14 +++++--- src/selector/extend/merged.rs | 60 +++++++------------------------- src/selector/extend/mod.rs | 13 +++++-- 4 files changed, 33 insertions(+), 56 deletions(-) diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 998d6ce..8e1df55 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -753,7 +753,7 @@ impl<'a> Parser<'a> { compound.components.first().unwrap(), &extend_rule, &None, - Some(self.span_before), + self.span_before, ) } diff --git a/src/selector/extend/extension.rs b/src/selector/extend/extension.rs index e4e5e12..dd737b0 100644 --- a/src/selector/extend/extension.rs +++ b/src/selector/extend/extension.rs @@ -28,20 +28,24 @@ pub(crate) struct Extension { pub media_context: Option>, /// The span in which `extender` was defined. - // todo: no `Option<>` - pub span: Option, + pub span: Span, pub left: Option>, pub right: Option>, } impl Extension { - pub fn one_off(extender: ComplexSelector, specificity: Option, is_original: bool) -> Self { + pub fn one_off( + extender: ComplexSelector, + specificity: Option, + is_original: bool, + span: Span, + ) -> Self { Self { specificity: specificity.unwrap_or_else(|| extender.max_specificity()), extender, target: None, - span: None, + span, is_optional: true, is_original, media_context: None, @@ -60,7 +64,7 @@ impl Extension { return; } - // Err(("You may not @extend selectors across media queries.", self.span.unwrap()).into()) + // Err(("You may not @extend selectors across media queries.", self.span).into()) } #[allow(clippy::missing_const_for_fn)] diff --git a/src/selector/extend/merged.rs b/src/selector/extend/merged.rs index 84a7074..df175dc 100644 --- a/src/selector/extend/merged.rs +++ b/src/selector/extend/merged.rs @@ -19,20 +19,25 @@ impl MergedExtension { /// extender and target. pub fn merge(left: Extension, right: Extension) -> SassResult { if left.extender != right.extender || left.target != right.target { - todo!("we need a span to throw a proper error") - // return Err((format!("{} and {} aren't the same extension.", left, right), )) + return Err(( + format!( + "{} and {} aren't the same extension.", + left.extender, right.extender + ), + left.span.merge(right.span), + ) + .into()); } if left.media_context.is_some() && right.media_context.is_some() && left.media_context != right.media_context { - todo!() - // throw SassException( - // "From ${left.span.message('')}\n" - // "You may not @extend the same selector from within different media " - // "queries.", - // right.span); + return Err(( + "You may not @extend the same selector from within different media queries.", + right.span, + ) + .into()); } if right.is_optional && right.media_context.is_none() { @@ -61,44 +66,5 @@ impl MergedExtension { left: None, right: None, } - // : super(left.extender, left.target, left.extenderSpan, left.span, - // left.mediaContext ?? right.mediaContext, - // specificity: left.specificity, optional: true); - } - - /// Returns all leaf-node `Extension`s in the tree or `MergedExtension`s. - #[allow(dead_code, unused_mut, clippy::unused_self)] - pub fn unmerge(mut self) -> Vec { - todo!() - /* Iterable unmerge() sync* { - if (left is MergedExtension) { - yield* (left as MergedExtension).unmerge(); - } else { - yield left; - } - - if (right is MergedExtension) { - yield* (right as MergedExtension).unmerge(); - } else { - yield right; - } - } - */ } } -/* -class MergedExtension extends Extension { - /// One of the merged extensions. - final Extension left; - - /// The other merged extension. - final Extension right; - - MergedExtension._(this.left, this.right) - : super(left.extender, left.target, left.extenderSpan, left.span, - left.mediaContext ?? right.mediaContext, - specificity: left.specificity, optional: true); - - -} -*/ diff --git a/src/selector/extend/mod.rs b/src/selector/extend/mod.rs index 3fe32bc..0388b75 100644 --- a/src/selector/extend/mod.rs +++ b/src/selector/extend/mod.rs @@ -154,7 +154,12 @@ impl Extender { let extenders: IndexMap = source .components .into_iter() - .map(|complex| (complex.clone(), Extension::one_off(complex, None, false))) + .map(|complex| { + ( + complex.clone(), + Extension::one_off(complex, None, false, span), + ) + }) .collect(); let compound_targets = targets @@ -164,7 +169,7 @@ impl Extender { if complex.components.len() == 1 { Ok(complex.components.first().unwrap().as_compound().clone()) } else { - Err(("Can't extend complex selector $complex.", span).into()) + Err((format!("Can't extend complex selector {}.", complex), span).into()) } }) .collect::>>()?; @@ -745,6 +750,7 @@ impl Extender { }, specificity, true, + self.span, ) } @@ -762,6 +768,7 @@ impl Extender { }, specificity, true, + self.span, ) } @@ -949,7 +956,7 @@ impl Extender { target: &SimpleSelector, extend: &ExtendRule, media_context: &Option>, - span: Option, + span: Span, ) { let selectors = self.selectors.get(target).cloned(); let existing_extensions = self.extensions_by_extender.get(target).cloned();