improve span context in @extend, removing some potential panics

This commit is contained in:
Connor Skees 2020-07-12 13:09:16 -04:00
parent d56100a324
commit c2384595e8
4 changed files with 33 additions and 56 deletions

View File

@ -753,7 +753,7 @@ impl<'a> Parser<'a> {
compound.components.first().unwrap(),
&extend_rule,
&None,
Some(self.span_before),
self.span_before,
)
}

View File

@ -28,20 +28,24 @@ pub(crate) struct Extension {
pub media_context: Option<Vec<CssMediaQuery>>,
/// The span in which `extender` was defined.
// todo: no `Option<>`
pub span: Option<Span>,
pub span: Span,
pub left: Option<Box<Extension>>,
pub right: Option<Box<Extension>>,
}
impl Extension {
pub fn one_off(extender: ComplexSelector, specificity: Option<i32>, is_original: bool) -> Self {
pub fn one_off(
extender: ComplexSelector,
specificity: Option<i32>,
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)]

View File

@ -19,20 +19,25 @@ impl MergedExtension {
/// extender and target.
pub fn merge(left: Extension, right: Extension) -> SassResult<Extension> {
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<Extension> {
todo!()
/* Iterable<Extension> 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);
}
*/

View File

@ -154,7 +154,12 @@ impl Extender {
let extenders: IndexMap<ComplexSelector, Extension> = 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::<SassResult<Vec<CompoundSelector>>>()?;
@ -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<Vec<CssMediaQuery>>,
span: Option<Span>,
span: Span,
) {
let selectors = self.selectors.get(target).cloned();
let existing_extensions = self.extensions_by_extender.get(target).cloned();