improve span context in @extend
, removing some potential panics
This commit is contained in:
parent
d56100a324
commit
c2384595e8
@ -753,7 +753,7 @@ impl<'a> Parser<'a> {
|
|||||||
compound.components.first().unwrap(),
|
compound.components.first().unwrap(),
|
||||||
&extend_rule,
|
&extend_rule,
|
||||||
&None,
|
&None,
|
||||||
Some(self.span_before),
|
self.span_before,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,20 +28,24 @@ pub(crate) struct Extension {
|
|||||||
pub media_context: Option<Vec<CssMediaQuery>>,
|
pub media_context: Option<Vec<CssMediaQuery>>,
|
||||||
|
|
||||||
/// The span in which `extender` was defined.
|
/// The span in which `extender` was defined.
|
||||||
// todo: no `Option<>`
|
pub span: Span,
|
||||||
pub span: Option<Span>,
|
|
||||||
|
|
||||||
pub left: Option<Box<Extension>>,
|
pub left: Option<Box<Extension>>,
|
||||||
pub right: Option<Box<Extension>>,
|
pub right: Option<Box<Extension>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
Self {
|
||||||
specificity: specificity.unwrap_or_else(|| extender.max_specificity()),
|
specificity: specificity.unwrap_or_else(|| extender.max_specificity()),
|
||||||
extender,
|
extender,
|
||||||
target: None,
|
target: None,
|
||||||
span: None,
|
span,
|
||||||
is_optional: true,
|
is_optional: true,
|
||||||
is_original,
|
is_original,
|
||||||
media_context: None,
|
media_context: None,
|
||||||
@ -60,7 +64,7 @@ impl Extension {
|
|||||||
return;
|
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)]
|
#[allow(clippy::missing_const_for_fn)]
|
||||||
|
@ -19,20 +19,25 @@ impl MergedExtension {
|
|||||||
/// extender and target.
|
/// extender and target.
|
||||||
pub fn merge(left: Extension, right: Extension) -> SassResult<Extension> {
|
pub fn merge(left: Extension, right: Extension) -> SassResult<Extension> {
|
||||||
if left.extender != right.extender || left.target != right.target {
|
if left.extender != right.extender || left.target != right.target {
|
||||||
todo!("we need a span to throw a proper error")
|
return Err((
|
||||||
// return Err((format!("{} and {} aren't the same extension.", left, right), ))
|
format!(
|
||||||
|
"{} and {} aren't the same extension.",
|
||||||
|
left.extender, right.extender
|
||||||
|
),
|
||||||
|
left.span.merge(right.span),
|
||||||
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if left.media_context.is_some()
|
if left.media_context.is_some()
|
||||||
&& right.media_context.is_some()
|
&& right.media_context.is_some()
|
||||||
&& left.media_context != right.media_context
|
&& left.media_context != right.media_context
|
||||||
{
|
{
|
||||||
todo!()
|
return Err((
|
||||||
// throw SassException(
|
"You may not @extend the same selector from within different media queries.",
|
||||||
// "From ${left.span.message('')}\n"
|
right.span,
|
||||||
// "You may not @extend the same selector from within different media "
|
)
|
||||||
// "queries.",
|
.into());
|
||||||
// right.span);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if right.is_optional && right.media_context.is_none() {
|
if right.is_optional && right.media_context.is_none() {
|
||||||
@ -61,44 +66,5 @@ impl MergedExtension {
|
|||||||
left: None,
|
left: None,
|
||||||
right: 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);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@ -154,7 +154,12 @@ impl Extender {
|
|||||||
let extenders: IndexMap<ComplexSelector, Extension> = source
|
let extenders: IndexMap<ComplexSelector, Extension> = source
|
||||||
.components
|
.components
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|complex| (complex.clone(), Extension::one_off(complex, None, false)))
|
.map(|complex| {
|
||||||
|
(
|
||||||
|
complex.clone(),
|
||||||
|
Extension::one_off(complex, None, false, span),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let compound_targets = targets
|
let compound_targets = targets
|
||||||
@ -164,7 +169,7 @@ impl Extender {
|
|||||||
if complex.components.len() == 1 {
|
if complex.components.len() == 1 {
|
||||||
Ok(complex.components.first().unwrap().as_compound().clone())
|
Ok(complex.components.first().unwrap().as_compound().clone())
|
||||||
} else {
|
} else {
|
||||||
Err(("Can't extend complex selector $complex.", span).into())
|
Err((format!("Can't extend complex selector {}.", complex), span).into())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<SassResult<Vec<CompoundSelector>>>()?;
|
.collect::<SassResult<Vec<CompoundSelector>>>()?;
|
||||||
@ -745,6 +750,7 @@ impl Extender {
|
|||||||
},
|
},
|
||||||
specificity,
|
specificity,
|
||||||
true,
|
true,
|
||||||
|
self.span,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,6 +768,7 @@ impl Extender {
|
|||||||
},
|
},
|
||||||
specificity,
|
specificity,
|
||||||
true,
|
true,
|
||||||
|
self.span,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,7 +956,7 @@ impl Extender {
|
|||||||
target: &SimpleSelector,
|
target: &SimpleSelector,
|
||||||
extend: &ExtendRule,
|
extend: &ExtendRule,
|
||||||
media_context: &Option<Vec<CssMediaQuery>>,
|
media_context: &Option<Vec<CssMediaQuery>>,
|
||||||
span: Option<Span>,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
let selectors = self.selectors.get(target).cloned();
|
let selectors = self.selectors.get(target).cloned();
|
||||||
let existing_extensions = self.extensions_by_extender.get(target).cloned();
|
let existing_extensions = self.extensions_by_extender.get(target).cloned();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user