Skip to content

Commit 3364372

Browse files
glebmxzyfer
authored andcommitted
Fix selector unification ordering
Introduces explicit order for selector unification and simplifies the implementation. Fixes #2681
1 parent ec249e4 commit 3364372

File tree

1 file changed

+19
-27
lines changed

1 file changed

+19
-27
lines changed

src/ast.cpp

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -505,36 +505,28 @@ namespace Sass {
505505
return false;
506506
}
507507

508+
namespace {
509+
510+
int SelectorOrder(Simple_Selector_Ptr sel) {
511+
if (Cast<Element_Selector>(sel)) return 1;
512+
if (Cast<Id_Selector>(sel) || Cast<Class_Selector>(sel)) return 2;
513+
if (Cast<Attribute_Selector>(sel)) return 3;
514+
if (Cast<Pseudo_Selector>(sel)) return Cast<Pseudo_Selector>(sel)->is_pseudo_element() ? 6 : 4;
515+
if (Cast<Wrapped_Selector>(sel)) return 5;
516+
return 7;
517+
}
518+
519+
} // namespace
520+
508521
Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs)
509522
{
510-
for (size_t i = 0, L = rhs->length(); i < L; ++i)
523+
const size_t rsize = rhs->length();
524+
for (size_t i = 0; i < rsize; ++i)
511525
{ if (to_string() == rhs->at(i)->to_string()) return rhs; }
512-
513-
// check for pseudo elements because they are always last
514-
size_t i, L;
515-
bool found = false;
516-
if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector) || typeid(*this) == typeid(Attribute_Selector))
517-
{
518-
for (i = 0, L = rhs->length(); i < L; ++i)
519-
{
520-
if ((Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element())
521-
{ found = true; break; }
522-
}
523-
}
524-
else
525-
{
526-
for (i = 0, L = rhs->length(); i < L; ++i)
527-
{
528-
if (Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i]))
529-
{ found = true; break; }
530-
}
531-
}
532-
if (!found)
533-
{
534-
rhs->append(this);
535-
} else {
536-
rhs->elements().insert(rhs->elements().begin() + i, this);
537-
}
526+
const int lhs_order = SelectorOrder(this);
527+
size_t i = rsize;
528+
while (i > 0 && lhs_order < SelectorOrder(rhs->at(i - 1))) --i;
529+
rhs->elements().insert(rhs->elements().begin() + i, this);
538530
return rhs;
539531
}
540532

0 commit comments

Comments
 (0)