Statement* Expand::operator()(Extension* e) { To_String to_string; Selector_List* extender = static_cast<Selector_List*>(selector_stack.back()); if (!extender) return 0; Selector_List* extendee = static_cast<Selector_List*>(e->selector()->perform(contextualize->with(0, env, backtrace))); if (extendee->length() != 1) { error("selector groups may not be extended", extendee->path(), extendee->position(), backtrace); } Complex_Selector* c = (*extendee)[0]; if (!c->head() || c->tail()) { error("nested selectors may not be extended", c->path(), c->position(), backtrace); } Compound_Selector* s = c->head(); // // need to convert the compound selector into a by-value data structure // vector<string> target_vec; // for (size_t i = 0, L = s->length(); i < L; ++i) // { target_vec.push_back((*s)[i]->perform(&to_string)); } for (size_t i = 0, L = extender->length(); i < L; ++i) { ctx.extensions.insert(make_pair(*s, (*extender)[i])); // let's test this out // cerr << "REGISTERING EXTENSION REQUEST: " << (*extender)[i]->perform(&to_string) << " <- " << s->perform(&to_string) << endl; ctx.subset_map.put(s->to_str_vec(), make_pair((*extender)[i], s)); } return 0; }
Statement* Expand::operator()(Extension* e) { Selector_List* extender = static_cast<Selector_List*>(selector_stack.back()); if (!extender) return 0; Selector_List* extendee = static_cast<Selector_List*>(e->selector()->perform(contextualize->with(0, env, backtrace))); if (extendee->length() != 1) { error("selector groups may not be extended", extendee->path(), extendee->position(), backtrace); } Complex_Selector* c = (*extendee)[0]; if (!c->head() || c->tail()) { error("nested selectors may not be extended", c->path(), c->position(), backtrace); } Compound_Selector* s = c->head(); for (size_t i = 0, L = extender->length(); i < L; ++i) { extensions.insert(make_pair(*s, (*extender)[i])); To_String to_string; } return 0; }
Selector* Contextualize::operator()(Selector_List* s) { Selector_List* p = static_cast<Selector_List*>(parent); Selector_List* ss = 0; if (p) { ss = new (ctx.mem) Selector_List(s->path(), s->position(), p->length() * s->length()); for (size_t i = 0, L = p->length(); i < L; ++i) { for (size_t j = 0, L = s->length(); j < L; ++j) { parent = (*p)[i]; Complex_Selector* comb = static_cast<Complex_Selector*>((*s)[j]->perform(this)); if (comb) *ss << comb; } } } else { ss = new (ctx.mem) Selector_List(s->path(), s->position(), s->length()); for (size_t j = 0, L = s->length(); j < L; ++j) { Complex_Selector* comb = static_cast<Complex_Selector*>((*s)[j]->perform(this)); if (comb) *ss << comb; } } return ss->length() ? ss : 0; }
void Remove_Placeholders::operator()(Ruleset* r) { // Create a new selector group without placeholders Selector_List* sl = static_cast<Selector_List*>(r->selector()); if (sl) { Selector_List* new_sl = new (ctx.mem) Selector_List(sl->pstate()); for (size_t i = 0, L = sl->length(); i < L; ++i) { if (!(*sl)[i]->contains_placeholder()) { *new_sl << (*sl)[i]; } } // Set the new placeholder selector list r->selector(new_sl); } // Iterate into child blocks Block* b = r->block(); for (size_t i = 0, L = b->length(); i < L; ++i) { if ((*b)[i]) (*b)[i]->perform(this); } }
void Output_Nested::operator()(Ruleset* r) { Selector* s = r->selector(); Block* b = r->block(); bool decls = false; // In case the extend visitor isn't called (if there are no @extend // directives in the entire document), check for placeholders here and // make sure they aren't output. // TODO: investigate why I decided to duplicate this logic in the extend visitor Selector_List* sl = static_cast<Selector_List*>(s); if (!ctx->extensions.size()) { Selector_List* new_sl = new (ctx->mem) Selector_List(sl->path(), sl->position()); for (size_t i = 0, L = sl->length(); i < L; ++i) { if (!(*sl)[i]->has_placeholder()) { *new_sl << (*sl)[i]; } } s = new_sl; sl = new_sl; r->selector(new_sl); } if (sl->length() == 0) return; if (b->has_non_hoistable()) { decls = true; indent(); if (source_comments) { stringstream ss; ss << "/* line " << r->position().line << ", " << r->path() << " */" << endl; append_singleline_part_to_buffer(ss.str()); indent(); } s->perform(this); append_multiline_part_to_buffer(" {\n"); ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; bool bPrintExpression = true; // Check print conditions if (typeid(*stm) == typeid(Declaration)) { Declaration* dec = static_cast<Declaration*>(stm); if (dec->value()->concrete_type() == Expression::STRING) { String_Constant* valConst = static_cast<String_Constant*>(dec->value()); string val(valConst->value()); if (val.empty()) { bPrintExpression = false; } } else if (dec->value()->concrete_type() == Expression::LIST) { List* list = static_cast<List*>(dec->value()); bool all_invisible = true; for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) { Expression* item = (*list)[list_i]; if (!item->is_invisible()) all_invisible = false; } if (all_invisible) bPrintExpression = false; } } // Print if OK if (!stm->is_hoistable() && bPrintExpression) { if (!stm->block()) indent(); stm->perform(this); append_multiline_part_to_buffer("\n"); } } --indentation; buffer.erase(buffer.length()-1); if (ctx) ctx->source_map.remove_line(); append_multiline_part_to_buffer(" }\n"); } if (b->has_hoistable()) { if (decls) ++indentation; // indent(); for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); } } if (decls) --indentation; } }