Skip to content

Commit

Permalink
Added various various sass selector functions
Browse files Browse the repository at this point in the history
  • Loading branch information
mgonzalez999 committed Jun 4, 2015
1 parent 25a1d79 commit 0514d01
Show file tree
Hide file tree
Showing 9 changed files with 429 additions and 5 deletions.
102 changes: 102 additions & 0 deletions ast.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ast.hpp"
#include "context.hpp"
#include "node.hpp"
#include "extend.hpp"
#include "to_string.hpp"
#include <set>
#include <algorithm>
Expand Down Expand Up @@ -420,6 +422,43 @@ namespace Sass {
// catch-all
return false;
}

Selector_List* Complex_Selector::unify_with(Complex_Selector* other, Context& ctx) {
To_String to_string;

Compound_Selector* thisBase = base();
Compound_Selector* rhsBase = other->base();

if( thisBase == 0 || rhsBase == 0 ) return 0;

// Not sure about this check, but closest way I could check to see if this is a ruby 'SimpleSequence' equivalent
if( tail()->combinator() != Combinator::ANCESTOR_OF || other->tail()->combinator() != Combinator::ANCESTOR_OF ) return 0;

Compound_Selector* unified = rhsBase->unify_with(thisBase, ctx);
if( unified == 0 ) return 0;

Node lhsNode = complexSelectorToNode(this, ctx);
Node rhsNode = complexSelectorToNode(other, ctx);

// Create a temp Complex_Selector, turn it into a Node, and combine it with the existing RHS node
Complex_Selector* fakeComplexSelector = new (ctx.mem) Complex_Selector(ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, unified, NULL);
Node unifiedNode = complexSelectorToNode(fakeComplexSelector, ctx);
rhsNode.plus(unifiedNode);

Node node = Extend::subweave(lhsNode, rhsNode, ctx);

Selector_List* result = new (ctx.mem) Selector_List(pstate());
for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
Node childNode = *iter;
childNode = Node::naiveTrim(childNode, ctx);

Complex_Selector* childNodeAsComplexSelector = nodeToComplexSelector(childNode, ctx);
if( childNodeAsComplexSelector ) { (*result) << childNodeAsComplexSelector; }
}

return result->length() ? result : 0;
}


size_t Complex_Selector::length()
{
Expand Down Expand Up @@ -558,6 +597,69 @@ namespace Sass {
}
return false;
}

Selector_List* Selector_List::unify_with(Selector_List* rhs, Context& ctx) {

vector<Complex_Selector*> unified_complex_selectors;
// Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
for (size_t lhs_i = 0, lhs_L = length(); lhs_i < lhs_L; ++lhs_i) {
Complex_Selector* seq1 = (*this)[lhs_i];
for(size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) {
Complex_Selector* seq2 = (*rhs)[rhs_i];

Selector_List* result = seq1->unify_with(seq2, ctx);
if( result ) {
for(size_t i = 0, L = result->length(); i < L; ++i) {
unified_complex_selectors.push_back( (*result)[i] );
}
}
}
}

// Creates the final Selector_List by combining all the complex selectors
Selector_List* final_result = new (ctx.mem) Selector_List(pstate());
for (auto itr = unified_complex_selectors.begin(); itr != unified_complex_selectors.end(); ++itr) {
*final_result << *itr;
}

return final_result;
}

void Selector_List::populate_extends(Selector_List* extendee, Context& ctx, ExtensionSubsetMap& extends) {
To_String to_string;

Selector_List* extender = this;
for (auto complex_sel : extendee->elements()) {
Complex_Selector* c = complex_sel;


// Ignore any parent selectors, until we find the first non Selector_Reference head
Compound_Selector* compound_sel = c->head();
Complex_Selector* pIter = complex_sel;
while (pIter) {
Compound_Selector* pHead = pIter->head();
if (pHead && dynamic_cast<Selector_Reference*>(pHead->elements()[0]) == NULL) {
compound_sel = pHead;
break;
}

pIter = pIter->tail();
}

if (!pIter->head() || pIter->tail()) {
error("nested selectors may not be extended", c->pstate());
}

compound_sel->is_optional(extendee->is_optional());

for (size_t i = 0, L = extender->length(); i < L; ++i) {
// let's test this out
cerr << "REGISTERING EXTENSION REQUEST: " << (*extender)[i]->perform(&to_string) << " <- " << compound_sel->perform(&to_string) << endl;
extends.put(compound_sel->to_str_vec(), make_pair((*extender)[i], compound_sel));
}
}
};


/* not used anymore - remove?
Selector_Placeholder* Selector_List::find_placeholder()
Expand Down
10 changes: 10 additions & 0 deletions ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ namespace Sass {
size_t length() const { return elements_.size(); }
bool empty() const { return elements_.empty(); }
T last() { return elements_.back(); }
T first() { return elements_.front(); }
T& operator[](size_t i) { return elements_[i]; }
const T& operator[](size_t i) const { return elements_[i]; }
Vectorized& operator<<(T element)
Expand Down Expand Up @@ -2006,6 +2007,9 @@ namespace Sass {
bool is_superselector_of(Complex_Selector* sub);
bool is_superselector_of(Selector_List* sub);
// virtual Selector_Placeholder* find_placeholder();

Selector_List* unify_with(Complex_Selector* rhs, Context& ctx);

Combinator clear_innermost();
void set_innermost(Complex_Selector*, Combinator);
virtual unsigned long specificity() const
Expand Down Expand Up @@ -2074,6 +2078,8 @@ namespace Sass {

typedef deque<Complex_Selector*> ComplexSelectorDeque;

typedef Subset_Map<string, pair<Complex_Selector*, Compound_Selector*> > ExtensionSubsetMap;

///////////////////////////////////
// Comma-separated selector groups.
///////////////////////////////////
Expand All @@ -2092,6 +2098,10 @@ namespace Sass {
bool is_superselector_of(Compound_Selector* sub);
bool is_superselector_of(Complex_Selector* sub);
bool is_superselector_of(Selector_List* sub);

Selector_List* unify_with(Selector_List*, Context&);
void populate_extends(Selector_List*, Context&, ExtensionSubsetMap&);

virtual unsigned long specificity()
{
unsigned long sum = 0;
Expand Down
7 changes: 7 additions & 0 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,14 @@ namespace Sass {
register_function(ctx, inspect_sig, inspect, env);
register_function(ctx, unique_id_sig, unique_id, env);
// Selector functions
register_function(ctx, selector_nest_sig, selector_nest, env);
register_function(ctx, selector_append_sig, selector_append, env);
register_function(ctx, selector_extend_sig, selector_extend, env);
register_function(ctx, selector_replace_sig, selector_replace, env);
register_function(ctx, selector_unify_sig, selector_unify, env);
register_function(ctx, is_superselector_sig, is_superselector, env);
register_function(ctx, simple_selectors_sig, simple_selectors, env);
register_function(ctx, selector_parse_sig, selector_parse, env);
}

void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs)
Expand Down
13 changes: 8 additions & 5 deletions extend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ namespace Sass {
result
end
*/
static Node subweave(Node& one, Node& two, Context& ctx) {
Node Extend::subweave(Node& one, Node& two, Context& ctx) {
// Check for the simple cases
if (one.collection()->size() == 0) {
Node out = Node::createCollection();
Expand Down Expand Up @@ -1423,7 +1423,7 @@ namespace Sass {
for (NodeDeque::iterator beforesIter = befores.collection()->begin(), beforesEndIter = befores.collection()->end(); beforesIter != beforesEndIter; beforesIter++) {
Node& before = *beforesIter;

Node sub = subweave(before, current, ctx);
Node sub = Extend::subweave(before, current, ctx);

DEBUG_PRINTLN(WEAVE, "SUB: " << sub)

Expand Down Expand Up @@ -1854,7 +1854,7 @@ namespace Sass {
/*
This is the equivalent of ruby's CommaSequence.do_extend.
*/
static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool& extendedSomething) {
Selector_List* Extend::extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool isReplace, bool& extendedSomething) {

To_String to_string(&ctx);

Expand Down Expand Up @@ -1886,7 +1886,10 @@ namespace Sass {
}
}

for (NodeDeque::iterator iterator = extendedSelectors.collection()->begin(), iteratorEnd = extendedSelectors.collection()->end(); iterator != iteratorEnd; ++iterator) {
for (NodeDeque::iterator iterator = extendedSelectors.collection()->begin(), iteratorBegin = extendedSelectors.collection()->begin(), iteratorEnd = extendedSelectors.collection()->end(); iterator != iteratorEnd; ++iterator) {
// When it is a replace, skip the first one, unless there is only one
if(isReplace && iterator == iteratorBegin && extendedSelectors.collection()->size() > 1 ) continue;

Node& childNode = *iterator;
*pNewSelectors << nodeToComplexSelector(childNode, ctx);
}
Expand Down Expand Up @@ -1943,7 +1946,7 @@ namespace Sass {
}

bool extendedSomething = false;
Selector_List* pNewSelectorList = extendSelectorList(static_cast<Selector_List*>(pObject->selector()), ctx, subsetMap, extendedSomething);
Selector_List* pNewSelectorList = Extend::extendSelectorList(static_cast<Selector_List*>(pObject->selector()), ctx, subsetMap, false, extendedSomething);

if (extendedSomething && pNewSelectorList) {
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->perform(&to_string))
Expand Down
4 changes: 4 additions & 0 deletions extend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Sass {
using namespace std;

class Context;
class Node;

typedef Subset_Map<string, pair<Complex_Selector*, Compound_Selector*> > ExtensionSubsetMap;

Expand All @@ -38,6 +39,9 @@ namespace Sass {

template <typename U>
void fallback(U x) { return fallback_impl(x); }

static Node subweave(Node& one, Node& two, Context& ctx);
static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool isReplace, bool& extendedSomething);
};

}
Expand Down
Loading

0 comments on commit 0514d01

Please sign in to comment.