Skip to content

Commit ad76862

Browse files
committed
Merge pull request #1501 from mgreter/bugfix/extend
Improve extend to match ruby version more closely
2 parents 00f7c0e + b6482fd commit ad76862

File tree

2 files changed

+101
-10
lines changed

2 files changed

+101
-10
lines changed

src/debugger.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88

99
using namespace Sass;
1010

11+
inline void debug_ast(AST_Node* node, std::string ind = "", Env* env = 0);
12+
13+
inline void debug_sources_set(SourcesSet& set, std::string ind = "")
14+
{
15+
if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
16+
for(auto const &pair : set) {
17+
debug_ast(pair, ind + "");
18+
// debug_ast(set[pair], ind + "first: ");
19+
}
20+
if (ind == "") std::cerr << "#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
21+
}
22+
1123
inline std::string str_replace(std::string str, const std::string& oldStr, const std::string& newStr)
1224
{
1325
size_t pos = 0;
@@ -43,7 +55,7 @@ inline std::string pstate_source_position(AST_Node* node)
4355
return str.str();
4456
}
4557

46-
inline void debug_ast(AST_Node* node, std::string ind = "", Env* env = 0)
58+
inline void debug_ast(AST_Node* node, std::string ind, Env* env)
4759
{
4860
if (node == 0) return;
4961
if (ind == "") std::cerr << "####################################################################\n";
@@ -110,6 +122,8 @@ inline void debug_ast(AST_Node* node, std::string ind = "", Env* env = 0)
110122
} else if(del != " ") {
111123
std::cerr << ind << " |" << del << "| {trailing op}" << std::endl;
112124
}
125+
SourcesSet set = selector->sources();
126+
// debug_sources_set(set, ind + " @--> ");
113127
} else if (dynamic_cast<Compound_Selector*>(node)) {
114128
Compound_Selector* selector = dynamic_cast<Compound_Selector*>(node);
115129
std::cerr << ind << "Compound_Selector " << selector;

src/extend.cpp

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,42 @@ namespace Sass {
8686

8787
std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) {
8888
To_String to_string;
89-
os << compoundSelector.perform(&to_string);
89+
for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
90+
if (i > 0) os << ", ";
91+
os << compoundSelector[i]->perform(&to_string);
92+
}
93+
return os;
94+
}
95+
96+
std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) {
97+
To_String to_string;
98+
os << simpleSelector.perform(&to_string);
9099
return os;
91100
}
92101

102+
// Print a string representation of a Compound_Selector
103+
static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
104+
To_String to_string;
105+
106+
if (message) {
107+
std::cerr << message;
108+
}
109+
110+
if (pSimpleSelector) {
111+
std::cerr << "[" << *pSimpleSelector << "]";
112+
} else {
113+
std::cerr << "NULL";
114+
}
115+
116+
if (newline) {
117+
std::cerr << std::endl;
118+
}
119+
}
120+
121+
// Print a string representation of a Compound_Selector
122+
typedef std::pair<Compound_Selector*, Complex_Selector*> SelsNewSeqPair;
123+
typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
124+
93125

94126
// Print a string representation of a Compound_Selector
95127
static void printCompoundSelector(Compound_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
@@ -100,7 +132,7 @@ namespace Sass {
100132
}
101133

102134
if (pCompoundSelector) {
103-
std::cerr << *pCompoundSelector;
135+
std::cerr << "[" << *pCompoundSelector << "]";
104136
} else {
105137
std::cerr << "NULL";
106138
}
@@ -164,6 +196,32 @@ namespace Sass {
164196
}
165197
}
166198

199+
static void printSelsNewSeqPairCollection(SelsNewSeqPairCollection& collection, const char* message=NULL, bool newline=true) {
200+
To_String to_string;
201+
202+
if (message) {
203+
std::cerr << message;
204+
}
205+
bool first = true;
206+
std::cerr << "[";
207+
for(SelsNewSeqPair& pair : collection) {
208+
if (first) {
209+
first = false;
210+
} else {
211+
std::cerr << ", ";
212+
}
213+
std::cerr << "[";
214+
Compound_Selector* pSels = pair.first;
215+
Complex_Selector* pNewSelector = pair.second;
216+
std::cerr << "[" << *pSels << "], ";
217+
printComplexSelector(pNewSelector, NULL, false);
218+
}
219+
std::cerr << "]";
220+
221+
if (newline) {
222+
std::cerr << std::endl;
223+
}
224+
}
167225

168226
// Print a string representation of a SourcesSet
169227
static void printSourcesSet(SourcesSet& sources, Context& ctx, const char* message=NULL, bool newline=true) {
@@ -525,8 +583,8 @@ namespace Sass {
525583
unsigned long maxSpecificity = isReplace ? pSeq1->specificity() : 0;
526584
SourcesSet sources = pSeq1->sources();
527585

528-
DEBUG_PRINTLN(TRIM, "TRIMASDF SEQ1: " << seq1)
529-
DEBUG_EXEC(TRIM, printSourcesSet(sources, ctx, "TRIMASDF SOURCES: "))
586+
DEBUG_PRINTLN(TRIM, "TRIM SEQ1: " << seq1)
587+
DEBUG_EXEC(TRIM, printSourcesSet(sources, ctx, "TRIM SOURCES: "))
530588

531589
for (SourcesSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
532590
const Complex_Selector* const pCurrentSelector = *sourcesSetIterator;
@@ -1464,7 +1522,7 @@ namespace Sass {
14641522
Complex_Selector* pComplexSelector,
14651523
Context& ctx,
14661524
ExtensionSubsetMap& subset_map,
1467-
std::set<Compound_Selector> seen, bool isReplace);
1525+
std::set<Compound_Selector> seen, bool isReplace, bool isOriginal);
14681526

14691527

14701528

@@ -1495,6 +1553,7 @@ namespace Sass {
14951553
std::set<Compound_Selector> seen, bool isReplace) {
14961554

14971555
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
1556+
// TODO: Ruby has another loop here to skip certain members?
14981557

14991558
Node extendedSelectors = Node::createCollection();
15001559
// extendedSelectors.got_line_feed = true;
@@ -1541,6 +1600,7 @@ namespace Sass {
15411600
Compound_Selector* pExtCompoundSelector = pSels; // All the simple selectors to be replaced from the current compound selector from all extensions
15421601

15431602
// TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL?
1603+
// RUBY: self_without_sel = Sass::Util.array_minus(members, sels)
15441604
Compound_Selector* pSelectorWithoutExtendSelectors = pSelector->minus(pExtCompoundSelector, ctx);
15451605

15461606
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
@@ -1560,6 +1620,7 @@ namespace Sass {
15601620
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "RHS: "))
15611621
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pUnifiedSelector, "UNIFIED: "))
15621622

1623+
// RUBY: next unless unified
15631624
if (!pUnifiedSelector || pUnifiedSelector->length() == 0) {
15641625
continue;
15651626
}
@@ -1603,6 +1664,7 @@ namespace Sass {
16031664
newSourcesSet.insert(pExtComplexSelector);
16041665
DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, ctx, "SOURCES WITH NEW SOURCE: "))
16051666

1667+
// RUBY: new_seq.add_sources!(sources + [seq])
16061668
pNewSelector->addSources(newSourcesSet, ctx);
16071669

16081670
DEBUG_EXEC(EXTEND_COMPOUND, SourcesSet newSet = pNewSelector->sources(); printSourcesSet(newSet, ctx, "SOURCES ON NEW SELECTOR AFTER ADD: "))
@@ -1622,6 +1684,7 @@ namespace Sass {
16221684
Complex_Selector* pNewSelector = pair.second;
16231685

16241686

1687+
// RUBY??: next [] if seen.include?(sels)
16251688
if (seen.find(*pSels) != seen.end()) {
16261689
continue;
16271690
}
@@ -1632,7 +1695,7 @@ namespace Sass {
16321695

16331696

16341697
DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND: " << complexSelectorToNode(pNewSelector, ctx))
1635-
Node recurseExtendedSelectors = extendComplexSelector(pNewSelector, ctx, subset_map, recurseSeen, isReplace);
1698+
Node recurseExtendedSelectors = extendComplexSelector(pNewSelector, ctx, subset_map, recurseSeen, isReplace, false); // !:isOriginal
16361699

16371700
DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND RETURN: " << recurseExtendedSelectors)
16381701

@@ -1743,19 +1806,24 @@ namespace Sass {
17431806
Complex_Selector* pComplexSelector,
17441807
Context& ctx,
17451808
ExtensionSubsetMap& subset_map,
1746-
std::set<Compound_Selector> seen, bool isReplace) {
1809+
std::set<Compound_Selector> seen, bool isReplace, bool isOriginal) {
17471810

17481811
Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
17491812
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
17501813

17511814
Node extendedNotExpanded = Node::createCollection();
17521815

1753-
for (NodeDeque::iterator complexSelIter = complexSelector.collection()->begin(), complexSelIterEnd = complexSelector.collection()->end(); complexSelIter != complexSelIterEnd; ++complexSelIter) {
1816+
for (NodeDeque::iterator complexSelIter = complexSelector.collection()->begin(),
1817+
complexSelIterEnd = complexSelector.collection()->end();
1818+
complexSelIter != complexSelIterEnd; ++complexSelIter)
1819+
{
1820+
17541821
Node& sseqOrOp = *complexSelIter;
17551822

17561823
DEBUG_PRINTLN(EXTEND_COMPLEX, "LOOP: " << sseqOrOp)
17571824

17581825
// If it's not a selector (meaning it's a combinator), just include it automatically
1826+
// RUBY: next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
17591827
if (!sseqOrOp.isSelector()) {
17601828
// Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node
17611829
// with one collection child. The collection child represents a Complex_Selector that is only a combinator.
@@ -1769,6 +1837,7 @@ namespace Sass {
17691837

17701838
Compound_Selector* pCompoundSelector = sseqOrOp.selector()->head();
17711839

1840+
// RUBY: extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)
17721841
Node extended = extendCompoundSelector(pCompoundSelector, ctx, subset_map, seen, isReplace);
17731842
if (sseqOrOp.got_line_feed) extended.got_line_feed = true;
17741843
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
@@ -1778,6 +1847,14 @@ namespace Sass {
17781847
// due to the member mapping: choices = extended.map {|seq| seq.members}
17791848
Complex_Selector* pJustCurrentCompoundSelector = sseqOrOp.selector();
17801849

1850+
// RUBY: extended.first.add_sources!([self]) if original && !has_placeholder?
1851+
if (isOriginal && !pComplexSelector->has_placeholder()) {
1852+
SourcesSet srcset;
1853+
srcset.insert(pComplexSelector);
1854+
pJustCurrentCompoundSelector->addSources(srcset, ctx);
1855+
DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
1856+
}
1857+
17811858
bool isSuperselector = false;
17821859
for (NodeDeque::iterator iterator = extended.collection()->begin(), endIterator = extended.collection()->end();
17831860
iterator != endIterator; ++iterator) {
@@ -1874,7 +1951,7 @@ namespace Sass {
18741951

18751952
std::set<Compound_Selector> seen;
18761953

1877-
Node extendedSelectors = extendComplexSelector(pSelector, ctx, subset_map, seen, isReplace);
1954+
Node extendedSelectors = extendComplexSelector(pSelector, ctx, subset_map, seen, isReplace, true);
18781955
if (!pSelector->has_placeholder()) {
18791956
if (!extendedSelectors.contains(complexSelectorToNode(pSelector, ctx), true /*simpleSelectorOrderDependent*/)) {
18801957
*pNewSelectors << pSelector;

0 commit comments

Comments
 (0)