Skip to content

Commit 8b97eed

Browse files
committed
Heavily improve wrapped pseudo selector handling
1 parent ed4c693 commit 8b97eed

File tree

8 files changed

+90
-33
lines changed

8 files changed

+90
-33
lines changed

src/context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ namespace Sass {
664664
if (!subset_map.empty()) {
665665
// create crtp visitor object
666666
Extend extend(subset_map);
667+
extend.setEval(expand.eval);
667668
// extend tree nodes
668669
extend(root);
669670
}

src/environment.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ namespace Sass {
219219
}
220220
return get_local(key);
221221
}
222-
222+
/*
223223
#ifdef DEBUG
224224
template <typename T>
225225
size_t Environment<T>::print(std::string prefix)
@@ -238,7 +238,7 @@ namespace Sass {
238238
return indent ;
239239
}
240240
#endif
241-
241+
*/
242242
// compile implementation for AST_Node
243243
template class Environment<AST_Node_Obj>;
244244

src/eval.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,9 +1763,27 @@ namespace Sass {
17631763
if (is_in_selector_schema) exp.selector_stack.push_back(0);
17641764
Selector_List_Obj resolved = s->resolve_parent_refs(exp.selector_stack, implicit_parent);
17651765
if (is_in_selector_schema) exp.selector_stack.pop_back();
1766+
for (size_t i = 0; i < resolved->length(); i++) {
1767+
Complex_Selector_Ptr is = resolved->at(i)->first();
1768+
while (is) {
1769+
if (is->head()) {
1770+
is->head()->perform(this);
1771+
}
1772+
is = is->tail();
1773+
}
1774+
}
17661775
return resolved.detach();
17671776
}
17681777

1778+
Compound_Selector_Ptr Eval::operator()(Compound_Selector_Ptr s)
1779+
{
1780+
for (size_t i = 0; i < s->length(); i++) {
1781+
Simple_Selector_Ptr ss = s->at(i);
1782+
if (ss) ss->perform(this);
1783+
}
1784+
return s;
1785+
}
1786+
17691787
// XXX: this is never hit via spec tests
17701788
Attribute_Selector_Ptr Eval::operator()(Attribute_Selector_Ptr s)
17711789
{
@@ -1821,4 +1839,39 @@ namespace Sass {
18211839
}
18221840
}
18231841

1842+
// hotfix to avoid invalid nested `:not` selectors
1843+
// probably the wrong place, but this should ultimately
1844+
// be fixed by implement superselector correctly for `:not`
1845+
// first use of "find" (ATM only implemented for selectors)
1846+
bool hasNotSelector(AST_Node_Obj obj) {
1847+
if (Wrapped_Selector_Ptr w = Cast<Wrapped_Selector>(obj)) {
1848+
return w->name() == ":not";
1849+
}
1850+
return false;
1851+
}
1852+
1853+
Wrapped_Selector_Ptr Eval::operator()(Wrapped_Selector_Ptr s)
1854+
{
1855+
1856+
if (s->name() == ":not") {
1857+
if (exp.selector_stack.back()) {
1858+
if (s->selector()->find(hasNotSelector)) {
1859+
s->selector()->clear();
1860+
s->name(" ");
1861+
} else if (s->selector()->length() == 1) {
1862+
Complex_Selector_Ptr cs = s->selector()->at(0);
1863+
if (cs->tail()) {
1864+
s->selector()->clear();
1865+
s->name(" ");
1866+
}
1867+
} else if (s->selector()->length() > 1) {
1868+
s->selector()->clear();
1869+
s->name(" ");
1870+
}
1871+
}
1872+
}
1873+
1874+
return s;
1875+
};
1876+
18241877
}

src/eval.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,12 @@ namespace Sass {
7575
// these will return selectors
7676
Selector_List_Ptr operator()(Selector_List_Ptr);
7777
Selector_List_Ptr operator()(Complex_Selector_Ptr);
78+
Compound_Selector_Ptr operator()(Compound_Selector_Ptr);
7879
Attribute_Selector_Ptr operator()(Attribute_Selector_Ptr);
7980
// they don't have any specific implementatio (yet)
8081
Element_Selector_Ptr operator()(Element_Selector_Ptr s) { return s; };
8182
Pseudo_Selector_Ptr operator()(Pseudo_Selector_Ptr s) { return s; };
82-
Wrapped_Selector_Ptr operator()(Wrapped_Selector_Ptr s) { return s; };
83+
Wrapped_Selector_Ptr operator()(Wrapped_Selector_Ptr s);
8384
Class_Selector_Ptr operator()(Class_Selector_Ptr s) { return s; };
8485
Id_Selector_Ptr operator()(Id_Selector_Ptr s) { return s; };
8586
Placeholder_Selector_Ptr operator()(Placeholder_Selector_Ptr s) { return s; };

src/extend.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "backtrace.hpp"
55
#include "paths.hpp"
66
#include "parser.hpp"
7+
#include "expand.hpp"
78
#include "node.hpp"
89
#include "sass_util.hpp"
910
#include "remove_placeholders.hpp"
@@ -1475,6 +1476,13 @@ namespace Sass {
14751476
toPush.plus(seqs);
14761477
toPush.plus(last_current);
14771478

1479+
// move line feed from inner to outer selector (very hacky indeed)
1480+
if (last_current.collection() && last_current.collection()->front().selector()) {
1481+
toPush.got_line_feed = last_current.collection()->front().got_line_feed;
1482+
last_current.collection()->front().selector()->has_line_feed(false);
1483+
last_current.collection()->front().got_line_feed = false;
1484+
}
1485+
14781486
tempResult.collection()->push_back(toPush);
14791487

14801488
}
@@ -1786,7 +1794,7 @@ namespace Sass {
17861794
ComplexSelectorSet srcset;
17871795
srcset.insert(selector);
17881796
sseqSel->addSources(srcset);
1789-
DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
1797+
// DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
17901798
}
17911799

17921800
bool isSuperselector = false;
@@ -1940,7 +1948,8 @@ namespace Sass {
19401948
// has wrapped not selectors
19411949
else if (ws->name() == ":not") {
19421950
// extend the inner list of wrapped selector
1943-
Selector_List_Obj ext_sl = extendSelectorList(sl, recseen);
1951+
bool extended = false;
1952+
Selector_List_Obj ext_sl = extendSelectorList(sl, false, extended, recseen);
19441953
for (size_t i = 0; i < ext_sl->length(); i += 1) {
19451954
if (Complex_Selector_Obj ext_cs = ext_sl->at(i)) {
19461955
// create clones for wrapped selector and the inner list
@@ -1950,18 +1959,6 @@ namespace Sass {
19501959
Compound_Selector_Obj ext_head = NULL;
19511960
if (ext_cs->first()) ext_head = ext_cs->first()->head();
19521961
if (ext_head && ext_head && ext_head->length() > 0) {
1953-
Wrapped_Selector_Ptr ext_ws = Cast<Wrapped_Selector>(ext_head->first());
1954-
if (ext_ws/* && ext_cs->length() == 1*/) {
1955-
Selector_List_Obj ws_cs = Cast<Selector_List>(ext_ws->selector());
1956-
if (ws_cs && !ws_cs->empty() && ws_cs->first()) {
1957-
Compound_Selector_Obj ws_ss = ws_cs->first()->head();
1958-
if (ws_ss && !ws_ss->empty() && !(
1959-
Cast<Pseudo_Selector>(ws_ss->first()) ||
1960-
Cast<Element_Selector>(ws_ss->first()) ||
1961-
Cast<Placeholder_Selector>(ws_ss->first())
1962-
)) continue;
1963-
}
1964-
}
19651962
cpy_ws_sl->append(ext_cs->first());
19661963
}
19671964
// assign list to clone
@@ -1970,6 +1967,11 @@ namespace Sass {
19701967
cpy_head->append(cpy_ws);
19711968
}
19721969
}
1970+
if (eval && extended) {
1971+
eval->exp.selector_stack.push_back(pNewSelectors);
1972+
cpy_head->perform(eval);
1973+
eval->exp.selector_stack.pop_back();
1974+
}
19731975
}
19741976
// has wrapped selectors
19751977
else {
@@ -2066,9 +2068,13 @@ namespace Sass {
20662068
}
20672069

20682070
Extend::Extend(Subset_Map& ssm)
2069-
: subset_map(ssm)
2071+
: subset_map(ssm), eval(NULL)
20702072
{ }
20712073

2074+
void Extend::setEval(Eval& e) {
2075+
eval = &e;
2076+
}
2077+
20722078
void Extend::operator()(Block_Ptr b)
20732079
{
20742080
for (size_t i = 0, L = b->length(); i < L; ++i) {

src/extend.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "ast.hpp"
88
#include "node.hpp"
9+
#include "eval.hpp"
910
#include "operation.hpp"
1011
#include "subset_map.hpp"
1112
#include "ast_fwd_decl.hpp"
@@ -17,6 +18,7 @@ namespace Sass {
1718
class Extend : public Operation_CRTP<void, Extend> {
1819

1920
Subset_Map& subset_map;
21+
Eval* eval;
2022

2123
void fallback_impl(AST_Node_Ptr n) { }
2224

@@ -54,6 +56,7 @@ namespace Sass {
5456
Node weave(Node& path);
5557

5658
public:
59+
void setEval(Eval& eval);
5760
Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen);
5861
Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace = false) {
5962
bool extendedSomething = false;

src/inspect.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -939,20 +939,11 @@ namespace Sass {
939939
}
940940
}
941941

942-
// hotfix to avoid invalid nested `:not` selectors
943-
// probably the wrong place, but this should ultimatively
944-
// be fixed by implement superselector correctly for `:not`
945-
// first use of "find" (ATM only implemented for selectors)
946-
bool hasNotSelector(AST_Node_Obj obj) {
947-
if (Wrapped_Selector_Ptr w = Cast<Wrapped_Selector>(obj)) {
948-
return w->name() == ":not";
949-
}
950-
return false;
951-
}
952-
953942
void Inspect::operator()(Wrapped_Selector_Ptr s)
954943
{
955-
if (!s->selector()->find(hasNotSelector)) {
944+
if (s->name() == " ") {
945+
append_string("");
946+
} else {
956947
bool was = in_wrapped;
957948
in_wrapped = true;
958949
append_token(s->name(), s);

src/node.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,15 @@ namespace Sass {
191191

192192
bool empty_parent_ref = pToConvert->head() && pToConvert->head()->is_empty_reference();
193193

194-
if (pToConvert->head() || empty_parent_ref) {
195-
}
196-
197194
// the first Complex_Selector may contain a dummy head pointer, skip it.
198195
if (pToConvert->head() && !empty_parent_ref) {
199196
node.collection()->push_back(Node::createSelector(*pToConvert));
200197
if (has_lf) node.collection()->back().got_line_feed = has_lf;
198+
if (pToConvert->head() || empty_parent_ref) {
199+
if (pToConvert->tail()) {
200+
pToConvert->tail()->has_line_feed(pToConvert->has_line_feed());
201+
}
202+
}
201203
has_lf = false;
202204
}
203205

0 commit comments

Comments
 (0)