Skip to content

Commit 4684b03

Browse files
authored
Merge pull request #2296 from mgreter/refactor/root-flags
Refactor `at_root` and `is_root` flags
2 parents 7eb7b97 + 3fc395e commit 4684b03

File tree

7 files changed

+90
-75
lines changed

7 files changed

+90
-75
lines changed

src/ast.hpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ namespace Sass {
454454
////////////////////////
455455
class Block : public Statement, public Vectorized<Statement_Obj> {
456456
ADD_PROPERTY(bool, is_root)
457-
ADD_PROPERTY(bool, is_at_root);
458457
// needed for properly formatted CSS emission
459458
protected:
460459
void adjust_after_pushing(Statement_Obj s)
@@ -464,14 +463,12 @@ namespace Sass {
464463
Block(ParserState pstate, size_t s = 0, bool r = false)
465464
: Statement(pstate),
466465
Vectorized<Statement_Obj>(s),
467-
is_root_(r),
468-
is_at_root_(false)
466+
is_root_(r)
469467
{ }
470468
Block(const Block* ptr)
471469
: Statement(ptr),
472470
Vectorized<Statement_Obj>(*ptr),
473-
is_root_(ptr->is_root_),
474-
is_at_root_(ptr->is_at_root_)
471+
is_root_(ptr->is_root_)
475472
{ }
476473
virtual bool has_content()
477474
{
@@ -510,16 +507,14 @@ namespace Sass {
510507
/////////////////////////////////////////////////////////////////////////////
511508
class Ruleset : public Has_Block {
512509
ADD_PROPERTY(Selector_Obj, selector)
513-
ADD_PROPERTY(bool, at_root);
514510
ADD_PROPERTY(bool, is_root);
515511
public:
516512
Ruleset(ParserState pstate, Selector_Obj s = 0, Block_Obj b = 0)
517-
: Has_Block(pstate, b), selector_(s), at_root_(false), is_root_(false)
513+
: Has_Block(pstate, b), selector_(s), is_root_(false)
518514
{ statement_type(RULESET); }
519515
Ruleset(const Ruleset* ptr)
520516
: Has_Block(ptr),
521517
selector_(ptr->selector_),
522-
at_root_(ptr->at_root_),
523518
is_root_(ptr->is_root_)
524519
{ statement_type(RULESET); }
525520
bool is_invisible() const;
@@ -2315,15 +2310,17 @@ namespace Sass {
23152310
/////////////////////////////////////////////////////////////////////////
23162311
class Selector_Schema : public Selector {
23172312
ADD_PROPERTY(String_Obj, contents)
2318-
ADD_PROPERTY(bool, at_root);
2313+
ADD_PROPERTY(bool, connect_parent);
23192314
public:
23202315
Selector_Schema(ParserState pstate, String_Obj c)
2321-
: Selector(pstate), contents_(c), at_root_(false)
2316+
: Selector(pstate),
2317+
contents_(c),
2318+
connect_parent_(true)
23222319
{ }
23232320
Selector_Schema(const Selector_Schema* ptr)
23242321
: Selector(ptr),
23252322
contents_(ptr->contents_),
2326-
at_root_(ptr->at_root_)
2323+
connect_parent_(ptr->connect_parent_)
23272324
{ }
23282325
virtual bool has_parent_ref();
23292326
virtual bool has_real_parent_ref();

src/debugger.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,8 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
255255
Selector_Schema_Ptr selector = dynamic_cast<Selector_Schema_Ptr>(node);
256256
std::cerr << ind << "Selector_Schema " << selector;
257257
std::cerr << " (" << pstate_source_position(node) << ")"
258-
<< (selector->at_root() && selector->at_root() ? " [@ROOT]" : "")
259258
<< " [@media:" << selector->media_block() << "]"
259+
<< (selector->connect_parent() ? " [connect-parent]": " -")
260260
<< (selector->has_line_break() ? " [line-break]": " -")
261261
<< (selector->has_line_feed() ? " [line-feed]": " -")
262262
<< std::endl;
@@ -474,7 +474,6 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env)
474474
std::cerr << " (" << pstate_source_position(node) << ")";
475475
std::cerr << " [indent: " << ruleset->tabs() << "]";
476476
std::cerr << (ruleset->is_invisible() ? " [INVISIBLE]" : "");
477-
std::cerr << (ruleset->at_root() ? " [@ROOT]" : "");
478477
std::cerr << (ruleset->is_root() ? " [root]" : "");
479478
std::cerr << std::endl;
480479
debug_ast(&ruleset->selector(), ind + ">");

src/eval.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,11 +1745,12 @@ namespace Sass {
17451745
// the parser will look for a brace to end the selector
17461746
Expression_Obj sel = s->contents()->perform(this);
17471747
std::string result_str(sel->to_string(ctx.c_options));
1748-
result_str = unquote(Util::rtrim(result_str)) + "\n{";
1748+
result_str = unquote(Util::rtrim(result_str));
17491749
Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
17501750
p.last_media_block = s->media_block();
1751-
bool root = exp.block_stack.back()->is_root();
1752-
Selector_List_Obj sl = p.parse_selector_list(root);
1751+
// a selector schema may or may not connect to parent?
1752+
bool chroot = s->connect_parent() == false;
1753+
Selector_List_Obj sl = p.parse_selector_list(chroot);
17531754
return operator()(&sl);
17541755
}
17551756

src/expand.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,27 @@ namespace Sass {
109109
// reset when leaving scope
110110
LOCAL_FLAG(at_root_without_rule, false);
111111

112-
// do some special checks for the base level rules
112+
// `&` is allowed in `@at-root`!
113+
bool has_parent_selector = false;
114+
for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
115+
Selector_List_Obj ll = selector_stack.at(i);
116+
has_parent_selector = ll != 0 && ll->length() > 0;
117+
}
118+
119+
Expression_Obj ex = 0;
120+
if (r->selector()) ex = r->selector()->perform(&eval);
121+
Selector_List_Obj sel = SASS_MEMORY_CAST(Selector_List, ex);
122+
if (sel == 0) throw std::runtime_error("Expanded null selector");
123+
124+
// check for parent selectors in base level rules
113125
if (r->is_root()) {
114126
if (Selector_List_Ptr selector_list = SASS_MEMORY_CAST(Selector_List, r->selector())) {
115127
for (Complex_Selector_Obj complex_selector : selector_list->elements()) {
116128
Complex_Selector_Ptr tail = &complex_selector;
117129
while (tail) {
118130
if (tail->head()) for (Simple_Selector_Obj header : tail->head()->elements()) {
119-
if (SASS_MEMORY_CAST(Parent_Selector, header) == NULL) continue; // skip all others
131+
Parent_Selector_Ptr ptr = SASS_MEMORY_CAST(Parent_Selector, header);
132+
if (ptr == NULL || (!ptr->real() || has_parent_selector)) continue;
120133
std::string sel_str(complex_selector->to_string(ctx.c_options));
121134
error("Base-level rules cannot contain the parent-selector-referencing character '&'.", header->pstate(), backtrace());
122135
}
@@ -125,20 +138,11 @@ namespace Sass {
125138
}
126139
}
127140
}
128-
129-
Expression_Obj ex = 0;
130-
if (r->selector()) ex = r->selector()->perform(&eval);
131-
Selector_List_Obj sel = SASS_MEMORY_CAST(Selector_List, ex);
132-
if (sel == 0) throw std::runtime_error("Expanded null selector");
133-
134-
if (sel->length() == 0 || sel->has_parent_ref()) {
135-
bool has_parent_selector = false;
136-
for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
137-
Selector_List_Obj ll = selector_stack.at(i);
138-
has_parent_selector = ll != 0 && ll->length() > 0;
139-
}
140-
if (sel->has_real_parent_ref() && !has_parent_selector) {
141-
error("Base-level rules cannot contain the parent-selector-referencing character '&'.", sel->pstate(), backtrace());
141+
else {
142+
if (sel->length() == 0 || sel->has_parent_ref()) {
143+
if (sel->has_real_parent_ref() && !has_parent_selector) {
144+
error("Base-level rules cannot contain the parent-selector-referencing character '&'.", sel->pstate(), backtrace());
145+
}
142146
}
143147
}
144148

src/functions.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ namespace Sass {
166166
if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, exp)) {
167167
str->quote_mark(0);
168168
}
169-
std::string exp_src = exp->to_string(ctx.c_options) + "{";
169+
std::string exp_src = exp->to_string(ctx.c_options);
170170
return Parser::parse_selector(exp_src.c_str(), ctx);
171171
}
172172

@@ -181,7 +181,7 @@ namespace Sass {
181181
if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, exp)) {
182182
str->quote_mark(0);
183183
}
184-
std::string exp_src = exp->to_string(ctx.c_options) + "{";
184+
std::string exp_src = exp->to_string(ctx.c_options);
185185
Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx);
186186
return (sel_list->length() > 0) ? &sel_list->first()->tail()->head() : 0;
187187
}
@@ -1772,7 +1772,7 @@ namespace Sass {
17721772
if (String_Constant_Obj str = SASS_MEMORY_CAST(String_Constant, exp)) {
17731773
str->quote_mark(0);
17741774
}
1775-
std::string exp_src = exp->to_string(ctx.c_options) + "{";
1775+
std::string exp_src = exp->to_string(ctx.c_options);
17761776
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx);
17771777
parsedSelectors.push_back(&sel);
17781778
}
@@ -1825,7 +1825,7 @@ namespace Sass {
18251825
if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, exp)) {
18261826
str->quote_mark(0);
18271827
}
1828-
std::string exp_src = exp->to_string() + "{";
1828+
std::string exp_src = exp->to_string();
18291829
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx);
18301830
parsedSelectors.push_back(&sel);
18311831
}

0 commit comments

Comments
 (0)