Skip to content

Commit

Permalink
Merge pull request sass#1599 from mgreter/bugfix/issue_1590
Browse files Browse the repository at this point in the history
Improve parent selector handling
  • Loading branch information
mgreter committed Oct 19, 2015
2 parents aa4dbbf + 4276b96 commit cba7bdc
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 9 deletions.
14 changes: 12 additions & 2 deletions src/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@ namespace Sass {
return this == &rhs;
}

// Selector lists can be compared to comma lists
bool Selector_List::operator==(const Expression& rhs) const
{
// solve the double dispatch problem by using RTTI information via dynamic cast
if (const List* ls = dynamic_cast<const List*>(&rhs)) { return *this == *ls; }
if (const Selector* ls = dynamic_cast<const Selector*>(&rhs)) { return *this == *ls; }
// compare invalid (maybe we should error?)
return false;
}

bool Selector_List::operator== (const Selector_List& rhs) const
{
// for array access
Expand All @@ -258,10 +268,10 @@ namespace Sass {
// skip nulls
if (!l) ++i;
else if (!r) ++n;
// do the check now
// do the check
else if (*l != *r)
{ return false; }
// advance now
// advance
++i; ++n;
}
// no mismatch
Expand Down
4 changes: 4 additions & 0 deletions src/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ namespace Sass {
T last() { return elements_.back(); }
T first() { return elements_.front(); }
T& operator[](size_t i) { return elements_[i]; }
virtual const T& at(size_t i) const { return elements_.at(i); }
const T& operator[](size_t i) const { return elements_[i]; }
Vectorized& operator<<(T element)
{
Expand Down Expand Up @@ -2251,6 +2252,7 @@ namespace Sass {
Selector_List(ParserState pstate, size_t s = 0)
: Selector(pstate), Vectorized<Complex_Selector*>(s), wspace_(0)
{ }
std::string type() { return "list"; }
// remove parent selector references
// basically unwraps parsed selectors
void remove_parent_selectors();
Expand All @@ -2276,6 +2278,8 @@ namespace Sass {
Selector_List* cloneFully(Context&) const; // clones Compound_Selector*s
virtual bool operator==(const Selector& rhs) const;
virtual bool operator==(const Selector_List& rhs) const;
// Selector Lists can be compared to comma lists
virtual bool operator==(const Expression& rhs) const;
ATTACH_OPERATIONS()
};

Expand Down
2 changes: 0 additions & 2 deletions src/bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ namespace Sass {
size_t ia = 0, LA = as->length();
while (ia < LA) {
Argument* a = (*as)[ia];
// this is only needed for selectors
a->value(a->value()->perform(&listize));
if (ip >= LP) {
// skip empty rest arguments
if (a->is_rest_argument()) {
Expand Down
2 changes: 2 additions & 0 deletions src/emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ namespace Sass {
{
if (output_style() == COMPRESSED) return;
if (output_style() == COMPACT) return;
if (in_declaration && in_comma_array) return;
if (scheduled_linefeed && indentation)
scheduled_linefeed = 1;
std::string indent = "";
Expand Down Expand Up @@ -208,6 +209,7 @@ namespace Sass {

void Emitter::append_optional_linefeed()
{
if (in_declaration && in_comma_array) return;
if (output_style() == COMPACT) {
append_mandatory_space();
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ namespace Sass {
value = SASS_MEMORY_NEW(ctx.mem, Null, value->pstate());
}
else if (value->concrete_type() == Expression::SELECTOR) {
value = value->perform(this)->perform(&listize);
value = value->perform(this); // ->perform(&listize);
}

// std::cerr << "\ttype is now: " << typeid(*value).name() << std::endl << std::endl;
Expand Down
23 changes: 19 additions & 4 deletions src/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1188,12 +1188,13 @@ namespace Sass {
Signature length_sig = "length($list)";
BUILT_IN(length)
{
if (Selector_List* sl = dynamic_cast<Selector_List*>(env["$list"])) {
return SASS_MEMORY_NEW(ctx.mem, Number, pstate, (double)sl->length());
}
Expression* v = ARG("$list", Expression);
if (v->concrete_type() == Expression::MAP) {
Map* map = dynamic_cast<Map*>(env["$list"]);
return SASS_MEMORY_NEW(ctx.mem, Number,
pstate,
(double)(map ? map->length() : 1));
return SASS_MEMORY_NEW(ctx.mem, Number, pstate, (double)(map ? map->length() : 1));
}
if (v->concrete_type() == Expression::SELECTOR) {
if (Compound_Selector* h = dynamic_cast<Compound_Selector*>(v)) {
Expand All @@ -1214,9 +1215,19 @@ namespace Sass {
Signature nth_sig = "nth($list, $n)";
BUILT_IN(nth)
{
Number* n = ARG("$n", Number);
Map* m = dynamic_cast<Map*>(env["$list"]);
if (Selector_List* sl = dynamic_cast<Selector_List*>(env["$list"])) {
size_t len = m ? m->length() : sl->length();
bool empty = m ? m->empty() : sl->empty();
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
double index = std::floor(n->value() < 0 ? len + n->value() : n->value() - 1);
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
// return (*sl)[static_cast<int>(index)];
Listize listize(ctx);
return (*sl)[static_cast<int>(index)]->perform(&listize);
}
List* l = dynamic_cast<List*>(env["$list"]);
Number* n = ARG("$n", Number);
if (n->value() == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate);
// if the argument isn't a list, then wrap it in a singleton list
if (!m && !l) {
Expand Down Expand Up @@ -1307,6 +1318,10 @@ namespace Sass {
{
List* l = dynamic_cast<List*>(env["$list"]);
Expression* v = ARG("$val", Expression);
if (Selector_List* sl = dynamic_cast<Selector_List*>(env["$list"])) {
Listize listize(ctx);
l = dynamic_cast<List*>(sl->perform(&listize));
}
String_Constant* sep = ARG("$separator", String_Constant);
if (!l) {
l = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
Expand Down
17 changes: 17 additions & 0 deletions src/inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,10 @@ namespace Sass {
in_wrapped = true;
append_token(s->name(), s);
append_string("(");
bool was_comma_array = in_comma_array;
in_comma_array = false;
s->selector()->perform(this);
in_comma_array = was_comma_array;
append_string(")");
in_wrapped = was;
}
Expand Down Expand Up @@ -816,6 +819,14 @@ namespace Sass {
void Inspect::operator()(Selector_List* g)
{
if (g->empty()) return;

bool was_comma_array = in_comma_array;
if (!in_declaration && in_comma_array) {
append_string("(");
}

if (in_declaration) in_comma_array = true;

for (size_t i = 0, L = g->length(); i < L; ++i) {
if (!in_wrapped && i == 0) append_indentation();
if ((*g)[i] == 0) continue;
Expand All @@ -825,6 +836,12 @@ namespace Sass {
append_comma_separator();
}
}

in_comma_array = was_comma_array;
if (!in_declaration && in_comma_array) {
append_string(")");
}

}

void Inspect::fallback_impl(AST_Node* n)
Expand Down

0 comments on commit cba7bdc

Please sign in to comment.