sassc 1.11.4 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +2 -2
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.md +4 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.github/CONTRIBUTING.md +7 -7
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +37 -18
- data/ext/libsass/GNUmakefile.am +23 -37
- data/ext/libsass/Makefile +10 -6
- data/ext/libsass/Makefile.conf +3 -0
- data/ext/libsass/Readme.md +68 -63
- data/ext/libsass/appveyor.yml +7 -3
- data/ext/libsass/configure.ac +10 -14
- data/ext/libsass/docs/api-context-internal.md +29 -21
- data/ext/libsass/docs/api-context.md +26 -6
- data/ext/libsass/docs/api-doc.md +49 -16
- data/ext/libsass/docs/api-function-example.md +1 -1
- data/ext/libsass/docs/api-function.md +31 -7
- data/ext/libsass/docs/api-importer.md +19 -19
- data/ext/libsass/docs/api-value.md +4 -2
- data/ext/libsass/docs/build-on-windows.md +4 -4
- data/ext/libsass/docs/build-with-mingw.md +3 -3
- data/ext/libsass/docs/build.md +9 -9
- data/ext/libsass/docs/custom-functions-internal.md +10 -8
- data/ext/libsass/docs/implementations.md +20 -8
- data/ext/libsass/docs/unicode.md +16 -10
- data/ext/libsass/include/sass/base.h +0 -3
- data/ext/libsass/include/sass/context.h +20 -2
- data/ext/libsass/include/sass/functions.h +31 -0
- data/ext/libsass/include/sass/values.h +3 -1
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass/version.h.in +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/res/resource.rc +6 -6
- data/ext/libsass/script/ci-build-libsass +10 -5
- data/ext/libsass/script/ci-build-plugin +62 -0
- data/ext/libsass/script/ci-install-compiler +1 -1
- data/ext/libsass/script/ci-install-deps +4 -7
- data/ext/libsass/script/ci-report-coverage +13 -3
- data/ext/libsass/script/tap-driver +1 -1
- data/ext/libsass/script/tap-runner +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -1
- data/ext/libsass/src/ast.cpp +537 -762
- data/ext/libsass/src/ast.hpp +377 -419
- data/ext/libsass/src/ast_def_macros.hpp +26 -1
- data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
- data/ext/libsass/src/b64/encode.h +3 -1
- data/ext/libsass/src/backtrace.cpp +46 -0
- data/ext/libsass/src/backtrace.hpp +7 -54
- data/ext/libsass/src/bind.cpp +72 -50
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/cencode.c +6 -0
- data/ext/libsass/src/check_nesting.cpp +157 -135
- data/ext/libsass/src/check_nesting.hpp +11 -10
- data/ext/libsass/src/color_maps.cpp +10 -6
- data/ext/libsass/src/color_maps.hpp +6 -8
- data/ext/libsass/src/constants.cpp +4 -3
- data/ext/libsass/src/constants.hpp +4 -3
- data/ext/libsass/src/context.cpp +110 -47
- data/ext/libsass/src/context.hpp +11 -1
- data/ext/libsass/src/cssize.cpp +105 -94
- data/ext/libsass/src/cssize.hpp +4 -5
- data/ext/libsass/src/debugger.hpp +247 -244
- data/ext/libsass/src/emitter.cpp +30 -6
- data/ext/libsass/src/emitter.hpp +7 -0
- data/ext/libsass/src/environment.cpp +67 -16
- data/ext/libsass/src/environment.hpp +28 -7
- data/ext/libsass/src/error_handling.cpp +92 -64
- data/ext/libsass/src/error_handling.hpp +64 -43
- data/ext/libsass/src/eval.cpp +494 -544
- data/ext/libsass/src/eval.hpp +17 -23
- data/ext/libsass/src/expand.cpp +182 -154
- data/ext/libsass/src/expand.hpp +4 -5
- data/ext/libsass/src/extend.cpp +299 -291
- data/ext/libsass/src/extend.hpp +46 -11
- data/ext/libsass/src/file.cpp +103 -36
- data/ext/libsass/src/file.hpp +21 -4
- data/ext/libsass/src/functions.cpp +561 -312
- data/ext/libsass/src/functions.hpp +8 -5
- data/ext/libsass/src/inspect.cpp +108 -53
- data/ext/libsass/src/inspect.hpp +5 -2
- data/ext/libsass/src/lexer.cpp +15 -7
- data/ext/libsass/src/lexer.hpp +13 -4
- data/ext/libsass/src/listize.cpp +3 -2
- data/ext/libsass/src/listize.hpp +0 -1
- data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
- data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
- data/ext/libsass/src/node.cpp +34 -38
- data/ext/libsass/src/node.hpp +6 -8
- data/ext/libsass/src/operation.hpp +2 -2
- data/ext/libsass/src/operators.cpp +240 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/output.cpp +22 -20
- data/ext/libsass/src/parser.cpp +719 -358
- data/ext/libsass/src/parser.hpp +57 -22
- data/ext/libsass/src/plugins.cpp +28 -10
- data/ext/libsass/src/position.cpp +21 -3
- data/ext/libsass/src/position.hpp +2 -1
- data/ext/libsass/src/prelexer.cpp +104 -19
- data/ext/libsass/src/prelexer.hpp +10 -3
- data/ext/libsass/src/remove_placeholders.cpp +9 -10
- data/ext/libsass/src/remove_placeholders.hpp +1 -5
- data/ext/libsass/src/sass.cpp +62 -4
- data/ext/libsass/src/sass.hpp +5 -2
- data/ext/libsass/src/sass_context.cpp +96 -58
- data/ext/libsass/src/sass_context.hpp +7 -5
- data/ext/libsass/src/sass_functions.cpp +63 -1
- data/ext/libsass/src/sass_functions.hpp +19 -1
- data/ext/libsass/src/sass_util.cpp +3 -3
- data/ext/libsass/src/sass_util.hpp +4 -4
- data/ext/libsass/src/sass_values.cpp +42 -39
- data/ext/libsass/src/sass_values.hpp +2 -1
- data/ext/libsass/src/source_map.cpp +16 -18
- data/ext/libsass/src/subset_map.cpp +6 -8
- data/ext/libsass/src/subset_map.hpp +6 -6
- data/ext/libsass/src/to_c.cpp +2 -2
- data/ext/libsass/src/to_value.cpp +8 -3
- data/ext/libsass/src/to_value.hpp +1 -0
- data/ext/libsass/src/units.cpp +349 -45
- data/ext/libsass/src/units.hpp +39 -22
- data/ext/libsass/src/utf8/checked.h +7 -0
- data/ext/libsass/src/utf8/unchecked.h +7 -0
- data/ext/libsass/src/utf8_string.cpp +1 -1
- data/ext/libsass/src/util.cpp +139 -45
- data/ext/libsass/src/util.hpp +4 -7
- data/ext/libsass/src/values.cpp +15 -23
- data/ext/libsass/win/libsass.sln +13 -2
- data/ext/libsass/win/libsass.sln.DotSettings +9 -0
- data/ext/libsass/win/libsass.targets +3 -0
- data/ext/libsass/win/libsass.vcxproj.filters +9 -0
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +1 -1
- data/test/native_test.rb +1 -1
- metadata +11 -4
data/ext/libsass/src/expand.hpp
CHANGED
@@ -13,18 +13,16 @@ namespace Sass {
|
|
13
13
|
class Listize;
|
14
14
|
class Context;
|
15
15
|
class Eval;
|
16
|
-
typedef Environment<AST_Node_Obj> Env;
|
17
16
|
struct Backtrace;
|
18
17
|
|
19
18
|
class Expand : public Operation_CRTP<Statement_Ptr, Expand> {
|
20
19
|
public:
|
21
20
|
|
22
21
|
Env* environment();
|
23
|
-
Context& context();
|
24
22
|
Selector_List_Obj selector();
|
25
|
-
Backtrace* backtrace();
|
26
23
|
|
27
24
|
Context& ctx;
|
25
|
+
Backtraces& traces;
|
28
26
|
Eval eval;
|
29
27
|
size_t recursions;
|
30
28
|
bool in_keyframes;
|
@@ -37,7 +35,8 @@ namespace Sass {
|
|
37
35
|
std::vector<AST_Node_Obj> call_stack;
|
38
36
|
std::vector<Selector_List_Obj> selector_stack;
|
39
37
|
std::vector<Media_Block_Ptr> media_block_stack;
|
40
|
-
|
38
|
+
|
39
|
+
Boolean_Obj bool_true;
|
41
40
|
|
42
41
|
Statement_Ptr fallback_impl(AST_Node_Ptr n);
|
43
42
|
|
@@ -45,7 +44,7 @@ namespace Sass {
|
|
45
44
|
void expand_selector_list(Selector_Obj, Selector_List_Obj extender);
|
46
45
|
|
47
46
|
public:
|
48
|
-
Expand(Context&, Env*,
|
47
|
+
Expand(Context&, Env*, std::vector<Selector_List_Obj>* stack = NULL);
|
49
48
|
~Expand() { }
|
50
49
|
|
51
50
|
Block_Ptr operator()(Block_Ptr);
|
data/ext/libsass/src/extend.cpp
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "backtrace.hpp"
|
5
5
|
#include "paths.hpp"
|
6
6
|
#include "parser.hpp"
|
7
|
+
#include "expand.hpp"
|
7
8
|
#include "node.hpp"
|
8
9
|
#include "sass_util.hpp"
|
9
10
|
#include "remove_placeholders.hpp"
|
@@ -61,8 +62,6 @@
|
|
61
62
|
namespace Sass {
|
62
63
|
|
63
64
|
|
64
|
-
typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> ExtensionPair;
|
65
|
-
typedef std::vector<ExtensionPair> SubsetMapEntries;
|
66
65
|
|
67
66
|
#ifdef DEBUG
|
68
67
|
|
@@ -111,11 +110,6 @@ namespace Sass {
|
|
111
110
|
}
|
112
111
|
}
|
113
112
|
|
114
|
-
// Print a string representation of a Compound_Selector
|
115
|
-
typedef std::pair<Compound_Selector_Obj, Complex_Selector_Obj> SelsNewSeqPair;
|
116
|
-
typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
|
117
|
-
|
118
|
-
|
119
113
|
// Print a string representation of a Compound_Selector
|
120
114
|
static void printCompoundSelector(Compound_Selector_Ptr pCompoundSelector, const char* message=NULL, bool newline=true) {
|
121
115
|
|
@@ -186,14 +180,14 @@ namespace Sass {
|
|
186
180
|
}
|
187
181
|
}
|
188
182
|
|
189
|
-
static void printSelsNewSeqPairCollection(
|
183
|
+
static void printSelsNewSeqPairCollection(SubSetMapLookups& collection, const char* message=NULL, bool newline=true) {
|
190
184
|
|
191
185
|
if (message) {
|
192
186
|
std::cerr << message;
|
193
187
|
}
|
194
188
|
bool first = true;
|
195
189
|
std::cerr << "[";
|
196
|
-
for(
|
190
|
+
for(SubSetMapLookup& pair : collection) {
|
197
191
|
if (first) {
|
198
192
|
first = false;
|
199
193
|
} else {
|
@@ -212,8 +206,8 @@ namespace Sass {
|
|
212
206
|
}
|
213
207
|
}
|
214
208
|
|
215
|
-
// Print a string representation of a
|
216
|
-
static void printSourcesSet(
|
209
|
+
// Print a string representation of a ComplexSelectorSet
|
210
|
+
static void printSourcesSet(ComplexSelectorSet& sources, const char* message=NULL, bool newline=true) {
|
217
211
|
|
218
212
|
if (message) {
|
219
213
|
std::cerr << message;
|
@@ -223,17 +217,17 @@ namespace Sass {
|
|
223
217
|
// the differences we see when debug printing.
|
224
218
|
typedef std::deque<std::string> SourceStrings;
|
225
219
|
SourceStrings sourceStrings;
|
226
|
-
for (
|
220
|
+
for (ComplexSelectorSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) {
|
227
221
|
Complex_Selector_Ptr pSource = *iterator;
|
228
222
|
std::stringstream sstream;
|
229
|
-
sstream << complexSelectorToNode(pSource
|
223
|
+
sstream << complexSelectorToNode(pSource);
|
230
224
|
sourceStrings.push_back(sstream.str());
|
231
225
|
}
|
232
226
|
|
233
227
|
// Sort to get consistent output
|
234
228
|
std::sort(sourceStrings.begin(), sourceStrings.end());
|
235
229
|
|
236
|
-
std::cerr << "
|
230
|
+
std::cerr << "ComplexSelectorSet[";
|
237
231
|
for (SourceStrings::iterator iterator = sourceStrings.begin(), iteratorEnd = sourceStrings.end(); iterator != iteratorEnd; ++iterator) {
|
238
232
|
std::string source = *iterator;
|
239
233
|
if (iterator != sourceStrings.begin()) {
|
@@ -249,10 +243,10 @@ namespace Sass {
|
|
249
243
|
}
|
250
244
|
|
251
245
|
|
252
|
-
std::ostream& operator<<(std::ostream& os,
|
246
|
+
std::ostream& operator<<(std::ostream& os, SubSetMapPairs& entries) {
|
253
247
|
os << "SUBSET_MAP_ENTRIES[";
|
254
248
|
|
255
|
-
for (
|
249
|
+
for (SubSetMapPairs::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) {
|
256
250
|
Complex_Selector_Obj pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge)
|
257
251
|
Compound_Selector_Obj pExtCompoundSelector = iterator->second; // The stuff after the @extend
|
258
252
|
|
@@ -286,17 +280,16 @@ namespace Sass {
|
|
286
280
|
}
|
287
281
|
#endif
|
288
282
|
|
289
|
-
static bool parentSuperselector(Complex_Selector_Ptr pOne, Complex_Selector_Ptr pTwo
|
283
|
+
static bool parentSuperselector(Complex_Selector_Ptr pOne, Complex_Selector_Ptr pTwo) {
|
290
284
|
// TODO: figure out a better way to create a Complex_Selector from scratch
|
291
285
|
// TODO: There's got to be a better way. This got ugly quick...
|
292
|
-
Position noPosition(-1, -1, -1);
|
293
286
|
Element_Selector_Obj fakeParent = SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp");
|
294
287
|
Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/);
|
295
|
-
fakeHead->elements().push_back(
|
296
|
-
Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF,
|
288
|
+
fakeHead->elements().push_back(fakeParent);
|
289
|
+
Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, NULL /*tail*/);
|
297
290
|
|
298
|
-
pOne->set_innermost(
|
299
|
-
pTwo->set_innermost(
|
291
|
+
pOne->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
|
292
|
+
pTwo->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
|
300
293
|
|
301
294
|
bool isSuperselector = pOne->is_superselector_of(pTwo);
|
302
295
|
|
@@ -306,19 +299,19 @@ namespace Sass {
|
|
306
299
|
return isSuperselector;
|
307
300
|
}
|
308
301
|
|
309
|
-
void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out
|
302
|
+
void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out) {
|
310
303
|
for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
|
311
304
|
Node& child = *iter;
|
312
|
-
out.push_back(nodeToComplexSelector(child
|
305
|
+
out.push_back(nodeToComplexSelector(child));
|
313
306
|
}
|
314
307
|
}
|
315
308
|
|
316
|
-
Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque
|
309
|
+
Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque) {
|
317
310
|
Node result = Node::createCollection();
|
318
311
|
|
319
312
|
for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) {
|
320
313
|
Complex_Selector_Obj pChild = *iter;
|
321
|
-
result.collection()->push_back(complexSelectorToNode(
|
314
|
+
result.collection()->push_back(complexSelectorToNode(pChild));
|
322
315
|
}
|
323
316
|
|
324
317
|
return result;
|
@@ -326,9 +319,7 @@ namespace Sass {
|
|
326
319
|
|
327
320
|
class LcsCollectionComparator {
|
328
321
|
public:
|
329
|
-
LcsCollectionComparator(
|
330
|
-
|
331
|
-
Context& mCtx;
|
322
|
+
LcsCollectionComparator() {}
|
332
323
|
|
333
324
|
bool operator()(Complex_Selector_Obj pOne, Complex_Selector_Obj pTwo, Complex_Selector_Obj& pOut) const {
|
334
325
|
/*
|
@@ -341,7 +332,7 @@ namespace Sass {
|
|
341
332
|
end
|
342
333
|
*/
|
343
334
|
|
344
|
-
if (
|
335
|
+
if (*pOne == *pTwo) {
|
345
336
|
pOut = pOne;
|
346
337
|
return true;
|
347
338
|
}
|
@@ -350,12 +341,12 @@ namespace Sass {
|
|
350
341
|
return false;
|
351
342
|
}
|
352
343
|
|
353
|
-
if (parentSuperselector(
|
344
|
+
if (parentSuperselector(pOne, pTwo)) {
|
354
345
|
pOut = pTwo;
|
355
346
|
return true;
|
356
347
|
}
|
357
348
|
|
358
|
-
if (parentSuperselector(
|
349
|
+
if (parentSuperselector(pTwo, pOne)) {
|
359
350
|
pOut = pOne;
|
360
351
|
return true;
|
361
352
|
}
|
@@ -420,7 +411,7 @@ namespace Sass {
|
|
420
411
|
for (size_t j = 1; j < y.size(); j++) {
|
421
412
|
Complex_Selector_Obj pCompareOut;
|
422
413
|
|
423
|
-
if (comparator(
|
414
|
+
if (comparator(x[i], y[j], pCompareOut)) {
|
424
415
|
c[i][j] = c[i - 1][j - 1] + 1;
|
425
416
|
} else {
|
426
417
|
c[i][j] = std::max(c[i][j - 1], c[i - 1][j]);
|
@@ -445,7 +436,7 @@ namespace Sass {
|
|
445
436
|
|
446
437
|
http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
|
447
438
|
*/
|
448
|
-
void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator,
|
439
|
+
void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) {
|
449
440
|
//DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y)
|
450
441
|
// TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
|
451
442
|
|
@@ -525,7 +516,7 @@ namespace Sass {
|
|
525
516
|
/*
|
526
517
|
- IMPROVEMENT: We could probably work directly in the output trimmed deque.
|
527
518
|
*/
|
528
|
-
|
519
|
+
Node Extend::trim(Node& seqses, bool isReplace) {
|
529
520
|
// See the comments in the above ruby code before embarking on understanding this function.
|
530
521
|
|
531
522
|
// Avoid poor performance in extreme cases.
|
@@ -558,7 +549,7 @@ namespace Sass {
|
|
558
549
|
for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) {
|
559
550
|
Node& seq1 = *seqs1Iter;
|
560
551
|
|
561
|
-
Complex_Selector_Obj pSeq1 = nodeToComplexSelector(seq1
|
552
|
+
Complex_Selector_Obj pSeq1 = nodeToComplexSelector(seq1);
|
562
553
|
|
563
554
|
// Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code
|
564
555
|
// for a good description of sources.
|
@@ -569,12 +560,12 @@ namespace Sass {
|
|
569
560
|
// best guess at this point is that we're cloning an object somewhere and maintaining the sources when we shouldn't be. This is purely
|
570
561
|
// a guess though.
|
571
562
|
unsigned long maxSpecificity = isReplace ? pSeq1->specificity() : 0;
|
572
|
-
|
563
|
+
ComplexSelectorSet sources = pSeq1->sources();
|
573
564
|
|
574
565
|
DEBUG_PRINTLN(TRIM, "TRIM SEQ1: " << seq1)
|
575
|
-
DEBUG_EXEC(TRIM, printSourcesSet(sources,
|
566
|
+
DEBUG_EXEC(TRIM, printSourcesSet(sources, "TRIM SOURCES: "))
|
576
567
|
|
577
|
-
for (
|
568
|
+
for (ComplexSelectorSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
|
578
569
|
const Complex_Selector_Obj& pCurrentSelector = *sourcesSetIterator;
|
579
570
|
maxSpecificity = std::max(maxSpecificity, pCurrentSelector->specificity());
|
580
571
|
}
|
@@ -605,7 +596,7 @@ namespace Sass {
|
|
605
596
|
for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) {
|
606
597
|
Node& seq2 = *seqs2Iter;
|
607
598
|
|
608
|
-
Complex_Selector_Obj pSeq2 = nodeToComplexSelector(seq2
|
599
|
+
Complex_Selector_Obj pSeq2 = nodeToComplexSelector(seq2);
|
609
600
|
|
610
601
|
DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity())
|
611
602
|
DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false"))
|
@@ -649,19 +640,18 @@ namespace Sass {
|
|
649
640
|
|
650
641
|
|
651
642
|
|
652
|
-
static bool parentSuperselector(const Node& one, const Node& two
|
643
|
+
static bool parentSuperselector(const Node& one, const Node& two) {
|
653
644
|
// TODO: figure out a better way to create a Complex_Selector from scratch
|
654
645
|
// TODO: There's got to be a better way. This got ugly quick...
|
655
|
-
Position noPosition(-1, -1, -1);
|
656
646
|
Element_Selector_Obj fakeParent = SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp");
|
657
647
|
Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/);
|
658
|
-
fakeHead->elements().push_back(
|
659
|
-
Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF,
|
648
|
+
fakeHead->elements().push_back(fakeParent);
|
649
|
+
Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, NULL /*tail*/);
|
660
650
|
|
661
|
-
Complex_Selector_Obj pOneWithFakeParent = nodeToComplexSelector(one
|
662
|
-
pOneWithFakeParent->set_innermost(
|
663
|
-
Complex_Selector_Obj pTwoWithFakeParent = nodeToComplexSelector(two
|
664
|
-
pTwoWithFakeParent->set_innermost(
|
651
|
+
Complex_Selector_Obj pOneWithFakeParent = nodeToComplexSelector(one);
|
652
|
+
pOneWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
|
653
|
+
Complex_Selector_Obj pTwoWithFakeParent = nodeToComplexSelector(two);
|
654
|
+
pTwoWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
|
665
655
|
|
666
656
|
return pOneWithFakeParent->is_superselector_of(pTwoWithFakeParent);
|
667
657
|
}
|
@@ -669,14 +659,13 @@ namespace Sass {
|
|
669
659
|
|
670
660
|
class ParentSuperselectorChunker {
|
671
661
|
public:
|
672
|
-
ParentSuperselectorChunker(Node& lcs
|
662
|
+
ParentSuperselectorChunker(Node& lcs) : mLcs(lcs) {}
|
673
663
|
Node& mLcs;
|
674
|
-
Context& mCtx;
|
675
664
|
|
676
665
|
bool operator()(const Node& seq) const {
|
677
666
|
// {|s| parent_superselector?(s.first, lcs.first)}
|
678
667
|
if (seq.collection()->size() == 0) return false;
|
679
|
-
return parentSuperselector(seq.collection()->front(), mLcs.collection()->front()
|
668
|
+
return parentSuperselector(seq.collection()->front(), mLcs.collection()->front());
|
680
669
|
}
|
681
670
|
};
|
682
671
|
|
@@ -730,7 +719,7 @@ namespace Sass {
|
|
730
719
|
}
|
731
720
|
|
732
721
|
Node chunk2 = Node::createCollection();
|
733
|
-
while (!chunker(seq2)) {
|
722
|
+
while (!seq2.collection()->empty() && !chunker(seq2)) {
|
734
723
|
chunk2.collection()->push_back(seq2.collection()->front());
|
735
724
|
seq2.collection()->pop_front();
|
736
725
|
}
|
@@ -772,7 +761,7 @@ namespace Sass {
|
|
772
761
|
}
|
773
762
|
|
774
763
|
|
775
|
-
static Node groupSelectors(Node& seq
|
764
|
+
static Node groupSelectors(Node& seq) {
|
776
765
|
Node newSeq = Node::createCollection();
|
777
766
|
|
778
767
|
Node tail = Node::createCollection();
|
@@ -832,7 +821,7 @@ namespace Sass {
|
|
832
821
|
return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
|
833
822
|
end
|
834
823
|
*/
|
835
|
-
static Node mergeInitialOps(Node& seq1, Node& seq2
|
824
|
+
static Node mergeInitialOps(Node& seq1, Node& seq2) {
|
836
825
|
Node ops1 = Node::createCollection();
|
837
826
|
Node ops2 = Node::createCollection();
|
838
827
|
|
@@ -846,9 +835,9 @@ namespace Sass {
|
|
846
835
|
|
847
836
|
// If neither sequence is a subsequence of the other, they cannot be merged successfully
|
848
837
|
DefaultLcsComparator lcsDefaultComparator;
|
849
|
-
Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator
|
838
|
+
Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator);
|
850
839
|
|
851
|
-
if (!(
|
840
|
+
if (!(opsLcs == ops1 || opsLcs == ops2)) {
|
852
841
|
return Node::createNil();
|
853
842
|
}
|
854
843
|
|
@@ -923,7 +912,7 @@ namespace Sass {
|
|
923
912
|
end
|
924
913
|
end
|
925
914
|
*/
|
926
|
-
static Node mergeFinalOps(Node& seq1, Node& seq2,
|
915
|
+
static Node mergeFinalOps(Node& seq1, Node& seq2, Node& res) {
|
927
916
|
|
928
917
|
Node ops1 = Node::createCollection();
|
929
918
|
Node ops2 = Node::createCollection();
|
@@ -941,11 +930,11 @@ namespace Sass {
|
|
941
930
|
|
942
931
|
if (ops1.collection()->size() > 1 || ops2.collection()->size() > 1) {
|
943
932
|
DefaultLcsComparator lcsDefaultComparator;
|
944
|
-
Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator
|
933
|
+
Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator);
|
945
934
|
|
946
935
|
// If there are multiple operators, something hacky's going on. If one is a supersequence of the other, use that, otherwise give up.
|
947
936
|
|
948
|
-
if (!(
|
937
|
+
if (!(opsLcs == ops1 || opsLcs == ops2)) {
|
949
938
|
return Node::createNil();
|
950
939
|
}
|
951
940
|
|
@@ -988,7 +977,7 @@ namespace Sass {
|
|
988
977
|
|
989
978
|
Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
|
990
979
|
// TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
|
991
|
-
Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(
|
980
|
+
Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head());
|
992
981
|
pMergedWrapper->head(pMerged);
|
993
982
|
|
994
983
|
DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
|
@@ -1011,7 +1000,7 @@ namespace Sass {
|
|
1011
1000
|
|
1012
1001
|
if (pMerged) {
|
1013
1002
|
Node mergedPerm = Node::createCollection();
|
1014
|
-
mergedPerm.collection()->push_back(Node::createSelector(
|
1003
|
+
mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper));
|
1015
1004
|
mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
|
1016
1005
|
newRes.collection()->push_back(mergedPerm);
|
1017
1006
|
}
|
@@ -1025,12 +1014,10 @@ namespace Sass {
|
|
1025
1014
|
} else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) {
|
1026
1015
|
|
1027
1016
|
Node tildeSel = sel1;
|
1028
|
-
Node tildeOp = op1;
|
1029
1017
|
Node plusSel = sel2;
|
1030
1018
|
Node plusOp = op2;
|
1031
1019
|
if (op1.combinator() != Complex_Selector::PRECEDES) {
|
1032
1020
|
tildeSel = sel2;
|
1033
|
-
tildeOp = op2;
|
1034
1021
|
plusSel = sel1;
|
1035
1022
|
plusOp = op1;
|
1036
1023
|
}
|
@@ -1047,7 +1034,7 @@ namespace Sass {
|
|
1047
1034
|
|
1048
1035
|
Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(plusSel.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
|
1049
1036
|
// TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
|
1050
|
-
Compound_Selector_Ptr pMerged = plusSel.selector()->head()->unify_with(
|
1037
|
+
Compound_Selector_Ptr pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head());
|
1051
1038
|
pMergedWrapper->head(pMerged);
|
1052
1039
|
|
1053
1040
|
DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
|
@@ -1063,7 +1050,7 @@ namespace Sass {
|
|
1063
1050
|
|
1064
1051
|
if (pMerged) {
|
1065
1052
|
Node mergedPerm = Node::createCollection();
|
1066
|
-
mergedPerm.collection()->push_back(Node::createSelector(
|
1053
|
+
mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper));
|
1067
1054
|
mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
|
1068
1055
|
newRes.collection()->push_back(mergedPerm);
|
1069
1056
|
}
|
@@ -1096,7 +1083,7 @@ namespace Sass {
|
|
1096
1083
|
|
1097
1084
|
Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
|
1098
1085
|
// TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
|
1099
|
-
Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(
|
1086
|
+
Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head());
|
1100
1087
|
pMergedWrapper->head(pMerged);
|
1101
1088
|
|
1102
1089
|
DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
|
@@ -1106,7 +1093,7 @@ namespace Sass {
|
|
1106
1093
|
}
|
1107
1094
|
|
1108
1095
|
res.collection()->push_front(op1);
|
1109
|
-
res.collection()->push_front(Node::createSelector(
|
1096
|
+
res.collection()->push_front(Node::createSelector(pMergedWrapper));
|
1110
1097
|
|
1111
1098
|
DEBUG_PRINTLN(ALL, "RESULT: " << res)
|
1112
1099
|
|
@@ -1114,7 +1101,7 @@ namespace Sass {
|
|
1114
1101
|
return Node::createNil();
|
1115
1102
|
}
|
1116
1103
|
|
1117
|
-
return mergeFinalOps(seq1, seq2,
|
1104
|
+
return mergeFinalOps(seq1, seq2, res);
|
1118
1105
|
|
1119
1106
|
} else if (!ops1.collection()->empty()) {
|
1120
1107
|
|
@@ -1129,7 +1116,7 @@ namespace Sass {
|
|
1129
1116
|
res.collection()->push_front(seq1.collection()->back());
|
1130
1117
|
seq1.collection()->pop_back();
|
1131
1118
|
|
1132
|
-
return mergeFinalOps(seq1, seq2,
|
1119
|
+
return mergeFinalOps(seq1, seq2, res);
|
1133
1120
|
|
1134
1121
|
} else { // !ops2.collection()->empty()
|
1135
1122
|
|
@@ -1143,7 +1130,7 @@ namespace Sass {
|
|
1143
1130
|
res.collection()->push_front(seq2.collection()->back());
|
1144
1131
|
seq2.collection()->pop_back();
|
1145
1132
|
|
1146
|
-
return mergeFinalOps(seq1, seq2,
|
1133
|
+
return mergeFinalOps(seq1, seq2, res);
|
1147
1134
|
|
1148
1135
|
}
|
1149
1136
|
|
@@ -1186,7 +1173,7 @@ namespace Sass {
|
|
1186
1173
|
result
|
1187
1174
|
end
|
1188
1175
|
*/
|
1189
|
-
Node
|
1176
|
+
Node subweave(Node& one, Node& two) {
|
1190
1177
|
// Check for the simple cases
|
1191
1178
|
if (one.collection()->size() == 0) {
|
1192
1179
|
Node out = Node::createCollection();
|
@@ -1199,8 +1186,6 @@ namespace Sass {
|
|
1199
1186
|
return out;
|
1200
1187
|
}
|
1201
1188
|
|
1202
|
-
|
1203
|
-
|
1204
1189
|
Node seq1 = Node::createCollection();
|
1205
1190
|
seq1.plus(one);
|
1206
1191
|
Node seq2 = Node::createCollection();
|
@@ -1209,7 +1194,7 @@ namespace Sass {
|
|
1209
1194
|
DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE ONE: " << seq1)
|
1210
1195
|
DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE TWO: " << seq2)
|
1211
1196
|
|
1212
|
-
Node init = mergeInitialOps(seq1, seq2
|
1197
|
+
Node init = mergeInitialOps(seq1, seq2);
|
1213
1198
|
if (init.isNil()) {
|
1214
1199
|
return Node::createNil();
|
1215
1200
|
}
|
@@ -1217,7 +1202,7 @@ namespace Sass {
|
|
1217
1202
|
DEBUG_PRINTLN(SUBWEAVE, "INIT: " << init)
|
1218
1203
|
|
1219
1204
|
Node res = Node::createCollection();
|
1220
|
-
Node fin = mergeFinalOps(seq1, seq2,
|
1205
|
+
Node fin = mergeFinalOps(seq1, seq2, res);
|
1221
1206
|
if (fin.isNil()) {
|
1222
1207
|
return Node::createNil();
|
1223
1208
|
}
|
@@ -1245,23 +1230,23 @@ namespace Sass {
|
|
1245
1230
|
|
1246
1231
|
|
1247
1232
|
|
1248
|
-
Node groupSeq1 = groupSelectors(seq1
|
1233
|
+
Node groupSeq1 = groupSelectors(seq1);
|
1249
1234
|
DEBUG_PRINTLN(SUBWEAVE, "SEQ1: " << groupSeq1)
|
1250
1235
|
|
1251
|
-
Node groupSeq2 = groupSelectors(seq2
|
1236
|
+
Node groupSeq2 = groupSelectors(seq2);
|
1252
1237
|
DEBUG_PRINTLN(SUBWEAVE, "SEQ2: " << groupSeq2)
|
1253
1238
|
|
1254
1239
|
|
1255
1240
|
ComplexSelectorDeque groupSeq1Converted;
|
1256
|
-
nodeToComplexSelectorDeque(groupSeq1, groupSeq1Converted
|
1241
|
+
nodeToComplexSelectorDeque(groupSeq1, groupSeq1Converted);
|
1257
1242
|
|
1258
1243
|
ComplexSelectorDeque groupSeq2Converted;
|
1259
|
-
nodeToComplexSelectorDeque(groupSeq2, groupSeq2Converted
|
1244
|
+
nodeToComplexSelectorDeque(groupSeq2, groupSeq2Converted);
|
1260
1245
|
|
1261
1246
|
ComplexSelectorDeque out;
|
1262
|
-
LcsCollectionComparator collectionComparator
|
1263
|
-
lcs(groupSeq2Converted, groupSeq1Converted, collectionComparator,
|
1264
|
-
Node seqLcs = complexSelectorDequeToNode(out
|
1247
|
+
LcsCollectionComparator collectionComparator;
|
1248
|
+
lcs(groupSeq2Converted, groupSeq1Converted, collectionComparator, out);
|
1249
|
+
Node seqLcs = complexSelectorDequeToNode(out);
|
1265
1250
|
|
1266
1251
|
DEBUG_PRINTLN(SUBWEAVE, "SEQLCS: " << seqLcs)
|
1267
1252
|
|
@@ -1275,7 +1260,7 @@ namespace Sass {
|
|
1275
1260
|
|
1276
1261
|
|
1277
1262
|
while (!seqLcs.collection()->empty()) {
|
1278
|
-
ParentSuperselectorChunker superselectorChunker(seqLcs
|
1263
|
+
ParentSuperselectorChunker superselectorChunker(seqLcs);
|
1279
1264
|
Node chunksResult = chunks(groupSeq1, groupSeq2, superselectorChunker);
|
1280
1265
|
diff.collection()->push_back(chunksResult);
|
1281
1266
|
|
@@ -1320,7 +1305,7 @@ namespace Sass {
|
|
1320
1305
|
DEBUG_PRINTLN(SUBWEAVE, "DIFF POST REJECT: " << diff)
|
1321
1306
|
|
1322
1307
|
|
1323
|
-
Node pathsResult = paths(diff
|
1308
|
+
Node pathsResult = paths(diff);
|
1324
1309
|
|
1325
1310
|
DEBUG_PRINTLN(SUBWEAVE, "PATHS: " << pathsResult)
|
1326
1311
|
|
@@ -1330,7 +1315,7 @@ namespace Sass {
|
|
1330
1315
|
pathsIter != pathsEndIter; ++pathsIter) {
|
1331
1316
|
|
1332
1317
|
Node& child = *pathsIter;
|
1333
|
-
child = flatten(child
|
1318
|
+
child = flatten(child);
|
1334
1319
|
}
|
1335
1320
|
|
1336
1321
|
DEBUG_PRINTLN(SUBWEAVE, "FLATTENED: " << pathsResult)
|
@@ -1348,25 +1333,25 @@ namespace Sass {
|
|
1348
1333
|
}
|
1349
1334
|
/*
|
1350
1335
|
// disabled to avoid clang warning [-Wunused-function]
|
1351
|
-
static Node subweaveNaive(const Node& one, const Node& two
|
1336
|
+
static Node subweaveNaive(const Node& one, const Node& two) {
|
1352
1337
|
Node out = Node::createCollection();
|
1353
1338
|
|
1354
1339
|
// Check for the simple cases
|
1355
1340
|
if (one.isNil()) {
|
1356
|
-
out.collection()->push_back(two.klone(
|
1341
|
+
out.collection()->push_back(two.klone());
|
1357
1342
|
} else if (two.isNil()) {
|
1358
|
-
out.collection()->push_back(one.klone(
|
1343
|
+
out.collection()->push_back(one.klone());
|
1359
1344
|
} else {
|
1360
1345
|
// Do the naive implementation. pOne = A B and pTwo = C D ...yields... A B C D and C D A B
|
1361
1346
|
// See https://gist.github.com/nex3/7609394 for details.
|
1362
1347
|
|
1363
|
-
Node firstPerm = one.klone(
|
1364
|
-
Node twoCloned = two.klone(
|
1348
|
+
Node firstPerm = one.klone();
|
1349
|
+
Node twoCloned = two.klone();
|
1365
1350
|
firstPerm.plus(twoCloned);
|
1366
1351
|
out.collection()->push_back(firstPerm);
|
1367
1352
|
|
1368
|
-
Node secondPerm = two.klone(
|
1369
|
-
Node oneCloned = one.klone(
|
1353
|
+
Node secondPerm = two.klone();
|
1354
|
+
Node oneCloned = one.klone();
|
1370
1355
|
secondPerm.plus(oneCloned );
|
1371
1356
|
out.collection()->push_back(secondPerm);
|
1372
1357
|
}
|
@@ -1449,7 +1434,7 @@ namespace Sass {
|
|
1449
1434
|
return befores
|
1450
1435
|
end
|
1451
1436
|
*/
|
1452
|
-
|
1437
|
+
Node Extend::weave(Node& path) {
|
1453
1438
|
|
1454
1439
|
DEBUG_PRINTLN(WEAVE, "WEAVE: " << path)
|
1455
1440
|
|
@@ -1460,7 +1445,7 @@ namespace Sass {
|
|
1460
1445
|
afters.plus(path);
|
1461
1446
|
|
1462
1447
|
while (!afters.collection()->empty()) {
|
1463
|
-
Node current = afters.collection()->front().klone(
|
1448
|
+
Node current = afters.collection()->front().klone();
|
1464
1449
|
afters.collection()->pop_front();
|
1465
1450
|
DEBUG_PRINTLN(WEAVE, "CURRENT: " << current)
|
1466
1451
|
if (current.collection()->size() == 0) continue;
|
@@ -1476,7 +1461,7 @@ namespace Sass {
|
|
1476
1461
|
for (NodeDeque::iterator beforesIter = befores.collection()->begin(), beforesEndIter = befores.collection()->end(); beforesIter != beforesEndIter; beforesIter++) {
|
1477
1462
|
Node& before = *beforesIter;
|
1478
1463
|
|
1479
|
-
Node sub =
|
1464
|
+
Node sub = subweave(before, current);
|
1480
1465
|
|
1481
1466
|
DEBUG_PRINTLN(WEAVE, "SUB: " << sub)
|
1482
1467
|
|
@@ -1491,6 +1476,13 @@ namespace Sass {
|
|
1491
1476
|
toPush.plus(seqs);
|
1492
1477
|
toPush.plus(last_current);
|
1493
1478
|
|
1479
|
+
// move line feed from inner to outer selector (very hacky indeed)
|
1480
|
+
if (last_current.collection() && last_current.collection()->front().selector()) {
|
1481
|
+
toPush.got_line_feed = last_current.collection()->front().got_line_feed;
|
1482
|
+
last_current.collection()->front().selector()->has_line_feed(false);
|
1483
|
+
last_current.collection()->front().got_line_feed = false;
|
1484
|
+
}
|
1485
|
+
|
1494
1486
|
tempResult.collection()->push_back(toPush);
|
1495
1487
|
|
1496
1488
|
}
|
@@ -1505,16 +1497,6 @@ namespace Sass {
|
|
1505
1497
|
|
1506
1498
|
|
1507
1499
|
|
1508
|
-
// This forward declaration is needed since extendComplexSelector calls extendCompoundSelector, which may recursively
|
1509
|
-
// call extendComplexSelector again.
|
1510
|
-
static Node extendComplexSelector(
|
1511
|
-
Complex_Selector_Ptr pComplexSelector,
|
1512
|
-
Context& ctx,
|
1513
|
-
Subset_Map& subset_map,
|
1514
|
-
std::set<Compound_Selector> seen, bool isReplace, bool isOriginal);
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
1500
|
/*
|
1519
1501
|
This is the equivalent of ruby's SimpleSequence.do_extend.
|
1520
1502
|
|
@@ -1530,65 +1512,60 @@ namespace Sass {
|
|
1530
1512
|
template<typename KeyType>
|
1531
1513
|
class GroupByToAFunctor {
|
1532
1514
|
public:
|
1533
|
-
KeyType operator()(
|
1515
|
+
KeyType operator()(SubSetMapPair& extPair) const {
|
1534
1516
|
Complex_Selector_Obj pSelector = extPair.first;
|
1535
|
-
return
|
1517
|
+
return pSelector;
|
1536
1518
|
}
|
1537
1519
|
};
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1520
|
+
Node Extend::extendCompoundSelector(Compound_Selector_Ptr pSelector, CompoundSelectorSet& seen, bool isReplace) {
|
1521
|
+
|
1522
|
+
/* this turned out to be too much overhead
|
1523
|
+
probably due to holding a "Node" object
|
1524
|
+
// check if we already extended this selector
|
1525
|
+
// we can do this since subset_map is "static"
|
1526
|
+
auto memoized = memoizeCompound.find(pSelector);
|
1527
|
+
if (memoized != memoizeCompound.end()) {
|
1528
|
+
return memoized->second.klone();
|
1529
|
+
}
|
1530
|
+
*/
|
1543
1531
|
|
1544
1532
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
|
1545
1533
|
// TODO: Ruby has another loop here to skip certain members?
|
1546
1534
|
|
1547
|
-
|
1535
|
+
// let RESULTS be an empty list of complex selectors
|
1536
|
+
Node results = Node::createCollection();
|
1548
1537
|
// extendedSelectors.got_line_feed = true;
|
1549
1538
|
|
1550
|
-
|
1551
|
-
|
1552
|
-
typedef std::vector<std::pair<Complex_Selector_Obj, std::vector<ExtensionPair> > > GroupedByToAResult;
|
1539
|
+
SubSetMapPairs entries = subset_map.get_v(pSelector);
|
1553
1540
|
|
1554
1541
|
GroupByToAFunctor<Complex_Selector_Obj> extPairKeyFunctor;
|
1555
|
-
|
1542
|
+
SubSetMapResults arr;
|
1556
1543
|
group_by_to_a(entries, extPairKeyFunctor, arr);
|
1557
1544
|
|
1558
|
-
|
1559
|
-
typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
|
1560
|
-
|
1545
|
+
SubSetMapLookups holder;
|
1561
1546
|
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
for (GroupedByToAResult::iterator groupedIter = arr.begin(), groupedIterEnd = arr.end(); groupedIter != groupedIterEnd; groupedIter++) {
|
1566
|
-
std::pair<Complex_Selector_Obj, std::vector<ExtensionPair> >& groupedPair = *groupedIter;
|
1547
|
+
// for each (EXTENDER, TARGET) in MAP.get(COMPOUND):
|
1548
|
+
for (SubSetMapResult& groupedPair : arr) {
|
1567
1549
|
|
1568
1550
|
Complex_Selector_Obj seq = groupedPair.first;
|
1569
|
-
|
1551
|
+
SubSetMapPairs& group = groupedPair.second;
|
1570
1552
|
|
1571
|
-
DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(
|
1553
|
+
DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(seq, "SEQ: "))
|
1572
1554
|
|
1573
|
-
// changing this makes aua
|
1574
1555
|
Compound_Selector_Obj pSels = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate());
|
1575
|
-
for (
|
1576
|
-
|
1577
|
-
|
1578
|
-
for (size_t index = 0; index < pCompound->length(); index++) {
|
1579
|
-
Simple_Selector_Obj pSimpleSelector = (*pCompound)[index];
|
1580
|
-
pSels->append(&pSimpleSelector);
|
1581
|
-
pCompound->extended(true);
|
1582
|
-
}
|
1556
|
+
for (SubSetMapPair& pair : group) {
|
1557
|
+
pair.second->extended(true);
|
1558
|
+
pSels->concat(pair.second);
|
1583
1559
|
}
|
1584
1560
|
|
1585
|
-
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(
|
1561
|
+
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSels, "SELS: "))
|
1586
1562
|
|
1587
|
-
|
1563
|
+
// The selector up to where the @extend is (ie, the thing to merge)
|
1564
|
+
Complex_Selector_Ptr pExtComplexSelector = seq;
|
1588
1565
|
|
1589
1566
|
// TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL?
|
1590
1567
|
// RUBY: self_without_sel = Sass::Util.array_minus(members, sels)
|
1591
|
-
Compound_Selector_Obj pSelectorWithoutExtendSelectors = pSelector->minus(
|
1568
|
+
Compound_Selector_Obj pSelectorWithoutExtendSelectors = pSelector->minus(pSels);
|
1592
1569
|
|
1593
1570
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
|
1594
1571
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: "))
|
@@ -1598,7 +1575,7 @@ namespace Sass {
|
|
1598
1575
|
if (!pInnermostCompoundSelector) {
|
1599
1576
|
pInnermostCompoundSelector = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate());
|
1600
1577
|
}
|
1601
|
-
Compound_Selector_Obj pUnifiedSelector = pInnermostCompoundSelector->unify_with(
|
1578
|
+
Compound_Selector_Obj pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors);
|
1602
1579
|
|
1603
1580
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pInnermostCompoundSelector, "LHS: "))
|
1604
1581
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "RHS: "))
|
@@ -1621,10 +1598,10 @@ namespace Sass {
|
|
1621
1598
|
Complex_Selector_Obj pNewInnerMost = SASS_MEMORY_NEW(Complex_Selector, pSelector->pstate(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
|
1622
1599
|
|
1623
1600
|
Complex_Selector::Combinator combinator = pNewSelector->clear_innermost();
|
1624
|
-
pNewSelector->set_innermost(
|
1601
|
+
pNewSelector->set_innermost(pNewInnerMost, combinator);
|
1625
1602
|
|
1626
1603
|
#ifdef DEBUG
|
1627
|
-
|
1604
|
+
ComplexSelectorSet debugSet;
|
1628
1605
|
debugSet = pNewSelector->sources();
|
1629
1606
|
if (debugSet.size() > 0) {
|
1630
1607
|
throw std::runtime_error("The new selector should start with no sources. Something needs to be cloned to fix this.");
|
@@ -1638,21 +1615,22 @@ namespace Sass {
|
|
1638
1615
|
|
1639
1616
|
// if (pSelector && pSelector->has_line_feed()) pNewInnerMost->has_line_feed(true);
|
1640
1617
|
// Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending.
|
1641
|
-
DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector
|
1618
|
+
DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector))
|
1642
1619
|
|
1643
|
-
DEBUG_EXEC(EXTEND_COMPOUND,
|
1620
|
+
DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, "SOURCES NEW SEQ BEGIN: "))
|
1644
1621
|
|
1645
|
-
|
1646
|
-
|
1622
|
+
// I actually want to create a copy here (performance!)
|
1623
|
+
ComplexSelectorSet newSourcesSet = pSelector->sources(); // XXX
|
1624
|
+
DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, "SOURCES THIS EXTEND: "))
|
1647
1625
|
|
1648
1626
|
newSourcesSet.insert(pExtComplexSelector);
|
1649
|
-
DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet,
|
1627
|
+
DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, "SOURCES WITH NEW SOURCE: "))
|
1650
1628
|
|
1651
1629
|
// RUBY: new_seq.add_sources!(sources + [seq])
|
1652
|
-
pNewSelector->addSources(newSourcesSet
|
1630
|
+
pNewSelector->addSources(newSourcesSet);
|
1653
1631
|
|
1654
|
-
DEBUG_EXEC(EXTEND_COMPOUND,
|
1655
|
-
DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(pSelector->sources(),
|
1632
|
+
DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet newSet = pNewSelector->sources(); printSourcesSet(newSet, "SOURCES ON NEW SELECTOR AFTER ADD: "))
|
1633
|
+
DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(pSelector->sources(), "SOURCES THIS EXTEND WHICH SHOULD BE SAME STILL: "))
|
1656
1634
|
|
1657
1635
|
|
1658
1636
|
if (pSels->has_line_feed()) pNewSelector->has_line_feed(true);
|
@@ -1661,25 +1639,24 @@ namespace Sass {
|
|
1661
1639
|
}
|
1662
1640
|
|
1663
1641
|
|
1664
|
-
for (
|
1665
|
-
SelsNewSeqPair& pair = *holderIter;
|
1642
|
+
for (SubSetMapLookup& pair : holder) {
|
1666
1643
|
|
1667
1644
|
Compound_Selector_Obj pSels = pair.first;
|
1668
1645
|
Complex_Selector_Obj pNewSelector = pair.second;
|
1669
1646
|
|
1670
1647
|
|
1671
1648
|
// RUBY??: next [] if seen.include?(sels)
|
1672
|
-
if (seen.find(
|
1649
|
+
if (seen.find(pSels) != seen.end()) {
|
1673
1650
|
continue;
|
1674
1651
|
}
|
1675
1652
|
|
1676
1653
|
|
1677
|
-
|
1678
|
-
recurseSeen.insert(
|
1654
|
+
CompoundSelectorSet recurseSeen(seen);
|
1655
|
+
recurseSeen.insert(pSels);
|
1679
1656
|
|
1680
1657
|
|
1681
|
-
DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND: " << complexSelectorToNode(pNewSelector
|
1682
|
-
Node recurseExtendedSelectors = extendComplexSelector(
|
1658
|
+
DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND: " << complexSelectorToNode(pNewSelector))
|
1659
|
+
Node recurseExtendedSelectors = extendComplexSelector(pNewSelector, recurseSeen, isReplace, false); // !:isOriginal
|
1683
1660
|
|
1684
1661
|
DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND RETURN: " << recurseExtendedSelectors)
|
1685
1662
|
|
@@ -1687,38 +1664,39 @@ namespace Sass {
|
|
1687
1664
|
iterator != endIterator; ++iterator) {
|
1688
1665
|
Node newSelector = *iterator;
|
1689
1666
|
|
1690
|
-
// DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " <<
|
1691
|
-
// DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " <<
|
1667
|
+
// DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " << results)
|
1668
|
+
// DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " << results.contains(newSelector, false /*simpleSelectorOrderDependent*/));
|
1692
1669
|
|
1693
|
-
if (!
|
1670
|
+
if (!results.contains(newSelector)) {
|
1694
1671
|
// DEBUG_PRINTLN(EXTEND_COMPOUND, "ADDING NEW SELECTOR")
|
1695
|
-
|
1672
|
+
results.collection()->push_back(newSelector);
|
1696
1673
|
}
|
1697
1674
|
}
|
1698
1675
|
}
|
1699
1676
|
|
1700
1677
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND END: "))
|
1701
1678
|
|
1702
|
-
|
1679
|
+
// this turned out to be too much overhead
|
1680
|
+
// memory results in a map table - since extending is very expensive
|
1681
|
+
// memoizeCompound.insert(std::pair<Compound_Selector_Obj, Node>(pSelector, results));
|
1682
|
+
|
1683
|
+
return results;
|
1703
1684
|
}
|
1704
1685
|
|
1705
1686
|
|
1706
|
-
|
1707
|
-
|
1708
|
-
Context& ctx,
|
1709
|
-
Subset_Map& subset_map,
|
1710
|
-
std::set<Compound_Selector>& seen) {
|
1687
|
+
// check if selector has something to be extended by subset_map
|
1688
|
+
bool Extend::complexSelectorHasExtension(Complex_Selector_Ptr selector, CompoundSelectorSet& seen) {
|
1711
1689
|
|
1712
1690
|
bool hasExtension = false;
|
1713
1691
|
|
1714
|
-
Complex_Selector_Obj pIter =
|
1692
|
+
Complex_Selector_Obj pIter = selector;
|
1715
1693
|
|
1716
1694
|
while (!hasExtension && pIter) {
|
1717
1695
|
Compound_Selector_Obj pHead = pIter->head();
|
1718
1696
|
|
1719
1697
|
if (pHead) {
|
1720
|
-
|
1721
|
-
for (
|
1698
|
+
SubSetMapPairs entries = subset_map.get_v(pHead);
|
1699
|
+
for (SubSetMapPair ext : entries) {
|
1722
1700
|
// check if both selectors have the same media block parent
|
1723
1701
|
// if (ext.first->media_block() == pComplexSelector->media_block()) continue;
|
1724
1702
|
if (ext.second->media_block() == 0) continue;
|
@@ -1726,8 +1704,8 @@ namespace Sass {
|
|
1726
1704
|
ext.second->media_block()->media_queries() &&
|
1727
1705
|
pHead->media_block()->media_queries()
|
1728
1706
|
) {
|
1729
|
-
std::string query_left(ext.second->media_block()->media_queries()->to_string(
|
1730
|
-
std::string query_right(pHead->media_block()->media_queries()->to_string(
|
1707
|
+
std::string query_left(ext.second->media_block()->media_queries()->to_string());
|
1708
|
+
std::string query_right(pHead->media_block()->media_queries()->to_string());
|
1731
1709
|
if (query_left == query_right) continue;
|
1732
1710
|
}
|
1733
1711
|
|
@@ -1738,9 +1716,9 @@ namespace Sass {
|
|
1738
1716
|
std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
|
1739
1717
|
err << "You may not @extend an outer selector from within @media.\n";
|
1740
1718
|
err << "You may only @extend selectors within the same directive.\n";
|
1741
|
-
err << "From \"@extend " << ext.second->to_string(
|
1719
|
+
err << "From \"@extend " << ext.second->to_string() << "\"";
|
1742
1720
|
err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
|
1743
|
-
error(err.str(),
|
1721
|
+
error(err.str(), selector->pstate(), eval->exp.traces);
|
1744
1722
|
}
|
1745
1723
|
if (entries.size() > 0) hasExtension = true;
|
1746
1724
|
}
|
@@ -1763,23 +1741,25 @@ namespace Sass {
|
|
1763
1741
|
the combinator and compound selector are one unit
|
1764
1742
|
next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
|
1765
1743
|
*/
|
1766
|
-
|
1767
|
-
Complex_Selector_Ptr pComplexSelector,
|
1768
|
-
Context& ctx,
|
1769
|
-
Subset_Map& subset_map,
|
1770
|
-
std::set<Compound_Selector> seen, bool isReplace, bool isOriginal) {
|
1744
|
+
Node Extend::extendComplexSelector(Complex_Selector_Ptr selector, CompoundSelectorSet& seen, bool isReplace, bool isOriginal) {
|
1771
1745
|
|
1772
|
-
|
1773
|
-
|
1746
|
+
// check if we already extended this selector
|
1747
|
+
// we can do this since subset_map is "static"
|
1748
|
+
auto memoized = memoizeComplex.find(selector);
|
1749
|
+
if (memoized != memoizeComplex.end()) {
|
1750
|
+
return memoized->second;
|
1751
|
+
}
|
1774
1752
|
|
1775
|
-
|
1753
|
+
// convert the input selector to extend node format
|
1754
|
+
Node complexSelector = complexSelectorToNode(selector);
|
1755
|
+
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
|
1776
1756
|
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
{
|
1757
|
+
// let CHOICES be an empty list of selector-lists
|
1758
|
+
// create new collection to hold the results
|
1759
|
+
Node choices = Node::createCollection();
|
1781
1760
|
|
1782
|
-
|
1761
|
+
// for each compound selector COMPOUND in COMPLEX:
|
1762
|
+
for (Node& sseqOrOp : *complexSelector.collection()) {
|
1783
1763
|
|
1784
1764
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "LOOP: " << sseqOrOp)
|
1785
1765
|
|
@@ -1792,94 +1772,93 @@ namespace Sass {
|
|
1792
1772
|
Node inner = Node::createCollection();
|
1793
1773
|
outer.collection()->push_back(inner);
|
1794
1774
|
inner.collection()->push_back(sseqOrOp);
|
1795
|
-
|
1775
|
+
choices.collection()->push_back(outer);
|
1796
1776
|
continue;
|
1797
1777
|
}
|
1798
1778
|
|
1799
|
-
|
1779
|
+
// verified now that node is a valid selector
|
1780
|
+
Complex_Selector_Obj sseqSel = sseqOrOp.selector();
|
1781
|
+
Compound_Selector_Obj sseqHead = sseqSel->head();
|
1800
1782
|
|
1783
|
+
// let EXTENDED be extend_compound(COMPOUND, SEEN)
|
1784
|
+
// extend the compound selector against the given subset_map
|
1801
1785
|
// RUBY: extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)
|
1802
|
-
Node extended = extendCompoundSelector(
|
1786
|
+
Node extended = extendCompoundSelector(sseqHead, seen, isReplace); // slow(17%)!
|
1803
1787
|
if (sseqOrOp.got_line_feed) extended.got_line_feed = true;
|
1804
1788
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
|
1805
1789
|
|
1806
|
-
|
1807
|
-
//
|
1808
|
-
// due to the member mapping: choices = extended.map {|seq| seq.members}
|
1809
|
-
Complex_Selector_Obj pJustCurrentCompoundSelector = sseqOrOp.selector();
|
1810
|
-
|
1790
|
+
// Prepend the Compound_Selector based on the choices logic; choices seems to be extend but with a ruby
|
1791
|
+
// Array instead of a Sequence due to the member mapping: choices = extended.map {|seq| seq.members}
|
1811
1792
|
// RUBY: extended.first.add_sources!([self]) if original && !has_placeholder?
|
1812
|
-
if (isOriginal && !
|
1813
|
-
|
1814
|
-
srcset.insert(
|
1815
|
-
|
1816
|
-
DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
|
1793
|
+
if (isOriginal && !selector->has_placeholder()) {
|
1794
|
+
ComplexSelectorSet srcset;
|
1795
|
+
srcset.insert(selector);
|
1796
|
+
sseqSel->addSources(srcset);
|
1797
|
+
// DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
|
1817
1798
|
}
|
1818
1799
|
|
1819
1800
|
bool isSuperselector = false;
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
if (pExtensionSelector->is_superselector_of(pJustCurrentCompoundSelector)) {
|
1801
|
+
// if no complex selector in EXTENDED is a superselector of COMPOUND:
|
1802
|
+
for (Node& childNode : *extended.collection()) {
|
1803
|
+
Complex_Selector_Obj pExtensionSelector = nodeToComplexSelector(childNode);
|
1804
|
+
if (pExtensionSelector->is_superselector_of(sseqSel)) {
|
1825
1805
|
isSuperselector = true;
|
1826
1806
|
break;
|
1827
1807
|
}
|
1828
1808
|
}
|
1829
1809
|
|
1830
1810
|
if (!isSuperselector) {
|
1831
|
-
|
1832
|
-
|
1811
|
+
// add a complex selector composed only of COMPOUND to EXTENDED
|
1812
|
+
if (sseqOrOp.got_line_feed) sseqSel->has_line_feed(sseqOrOp.got_line_feed);
|
1813
|
+
extended.collection()->push_front(complexSelectorToNode(sseqSel));
|
1833
1814
|
}
|
1834
1815
|
|
1835
1816
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "CHOICES UNSHIFTED: " << extended)
|
1836
1817
|
|
1818
|
+
// add EXTENDED to CHOICES
|
1837
1819
|
// Aggregate our current extensions
|
1838
|
-
|
1820
|
+
choices.collection()->push_back(extended);
|
1839
1821
|
}
|
1840
1822
|
|
1841
1823
|
|
1842
|
-
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED NOT EXPANDED: " <<
|
1824
|
+
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED NOT EXPANDED: " << choices)
|
1843
1825
|
|
1844
1826
|
|
1845
1827
|
|
1846
1828
|
// Ruby Equivalent: paths
|
1847
|
-
Node paths = Sass::paths(
|
1829
|
+
Node paths = Sass::paths(choices);
|
1848
1830
|
|
1849
1831
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "PATHS: " << paths)
|
1850
1832
|
|
1851
|
-
|
1852
|
-
|
1853
|
-
// Ruby Equivalent: weave
|
1833
|
+
// let WEAVES be an empty list of selector lists
|
1854
1834
|
Node weaves = Node::createCollection();
|
1855
1835
|
|
1856
|
-
for
|
1857
|
-
|
1858
|
-
|
1836
|
+
// for each list of complex selectors PATH in paths(CHOICES):
|
1837
|
+
for (Node& path : *paths.collection()) {
|
1838
|
+
// add weave(PATH) to WEAVES
|
1839
|
+
Node weaved = weave(path); // slow(12%)!
|
1859
1840
|
weaved.got_line_feed = path.got_line_feed;
|
1860
1841
|
weaves.collection()->push_back(weaved);
|
1861
1842
|
}
|
1862
1843
|
|
1863
1844
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "WEAVES: " << weaves)
|
1864
1845
|
|
1865
|
-
|
1866
|
-
|
1867
1846
|
// Ruby Equivalent: trim
|
1868
|
-
Node trimmed
|
1847
|
+
Node trimmed(trim(weaves, isReplace)); // slow(19%)!
|
1869
1848
|
|
1870
1849
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "TRIMMED: " << trimmed)
|
1871
1850
|
|
1872
|
-
|
1873
1851
|
// Ruby Equivalent: flatten
|
1874
|
-
Node
|
1852
|
+
Node flattened(flatten(trimmed, 1));
|
1875
1853
|
|
1876
1854
|
DEBUG_PRINTLN(EXTEND_COMPLEX, ">>>>> EXTENDED: " << extendedSelectors)
|
1877
|
-
|
1878
|
-
|
1879
1855
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX END: " << complexSelector)
|
1880
1856
|
|
1857
|
+
// memory results in a map table - since extending is very expensive
|
1858
|
+
memoizeComplex.insert(std::pair<Complex_Selector_Obj, Node>(selector, flattened));
|
1881
1859
|
|
1882
|
-
return
|
1860
|
+
// return trim(WEAVES)
|
1861
|
+
return flattened;
|
1883
1862
|
}
|
1884
1863
|
|
1885
1864
|
|
@@ -1887,20 +1866,23 @@ namespace Sass {
|
|
1887
1866
|
/*
|
1888
1867
|
This is the equivalent of ruby's CommaSequence.do_extend.
|
1889
1868
|
*/
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
}
|
1894
|
-
|
1895
|
-
/*
|
1896
|
-
This is the equivalent of ruby's CommaSequence.do_extend.
|
1897
|
-
*/
|
1898
|
-
Selector_List_Ptr Extend::extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace, bool& extendedSomething, std::set<Compound_Selector>& seen) {
|
1869
|
+
// We get a selector list with has something to extend and a subset_map with
|
1870
|
+
// all extenders. Pick the ones that match our selectors in the list.
|
1871
|
+
Selector_List_Ptr Extend::extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen) {
|
1899
1872
|
|
1900
1873
|
Selector_List_Obj pNewSelectors = SASS_MEMORY_NEW(Selector_List, pSelectorList->pstate(), pSelectorList->length());
|
1901
1874
|
|
1902
|
-
|
1875
|
+
// check if we already extended this selector
|
1876
|
+
// we can do this since subset_map is "static"
|
1877
|
+
auto memoized = memoizeList.find(pSelectorList);
|
1878
|
+
if (memoized != memoizeList.end()) {
|
1879
|
+
extendedSomething = true;
|
1880
|
+
return memoized->second;
|
1881
|
+
}
|
1903
1882
|
|
1883
|
+
extendedSomething = false;
|
1884
|
+
// process each comlplex selector in the selector list.
|
1885
|
+
// Find the ones that can be extended by given subset_map.
|
1904
1886
|
for (size_t index = 0, length = pSelectorList->length(); index < length; index++) {
|
1905
1887
|
Complex_Selector_Obj pSelector = (*pSelectorList)[index];
|
1906
1888
|
|
@@ -1909,89 +1891,100 @@ namespace Sass {
|
|
1909
1891
|
// run through the extend code (which does a data model transformation), check if there is anything to extend before doing
|
1910
1892
|
// the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
|
1911
1893
|
// when debugging).
|
1912
|
-
if (!complexSelectorHasExtension(
|
1913
|
-
pNewSelectors->append(
|
1894
|
+
if (!complexSelectorHasExtension(pSelector, seen)) {
|
1895
|
+
pNewSelectors->append(pSelector);
|
1914
1896
|
continue;
|
1915
1897
|
}
|
1916
1898
|
|
1899
|
+
// complexSelectorHasExtension was true!
|
1917
1900
|
extendedSomething = true;
|
1918
1901
|
|
1919
|
-
|
1902
|
+
// now do the actual extension of the complex selector
|
1903
|
+
Node extendedSelectors = extendComplexSelector(pSelector, seen, isReplace, true);
|
1904
|
+
|
1920
1905
|
if (!pSelector->has_placeholder()) {
|
1921
|
-
|
1906
|
+
Node nSelector(complexSelectorToNode(pSelector));
|
1907
|
+
if (!extendedSelectors.contains(nSelector)) {
|
1922
1908
|
pNewSelectors->append(pSelector);
|
1923
1909
|
continue;
|
1924
1910
|
}
|
1925
1911
|
}
|
1926
1912
|
|
1927
|
-
|
1913
|
+
bool doReplace = isReplace;
|
1914
|
+
for (Node& childNode : *extendedSelectors.collection()) {
|
1928
1915
|
// When it is a replace, skip the first one, unless there is only one
|
1929
|
-
if(
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1916
|
+
if(doReplace && extendedSelectors.collection()->size() > 1 ) {
|
1917
|
+
doReplace = false;
|
1918
|
+
continue;
|
1919
|
+
}
|
1920
|
+
pNewSelectors->append(nodeToComplexSelector(childNode));
|
1933
1921
|
}
|
1934
1922
|
}
|
1935
1923
|
|
1936
|
-
Remove_Placeholders remove_placeholders
|
1924
|
+
Remove_Placeholders remove_placeholders;
|
1937
1925
|
// it seems that we have to remove the place holders early here
|
1938
1926
|
// normally we do this as the very last step (compare to ruby sass)
|
1939
|
-
pNewSelectors = remove_placeholders.remove_placeholders(
|
1927
|
+
pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors);
|
1940
1928
|
|
1941
1929
|
// unwrap all wrapped selectors with inner lists
|
1942
1930
|
for (Complex_Selector_Obj cur : pNewSelectors->elements()) {
|
1943
1931
|
// process tails
|
1944
1932
|
while (cur) {
|
1945
1933
|
// process header
|
1946
|
-
if (cur->head() && seen.find(
|
1947
|
-
|
1948
|
-
recseen.insert(
|
1934
|
+
if (cur->head() && seen.find(cur->head()) == seen.end()) {
|
1935
|
+
CompoundSelectorSet recseen(seen);
|
1936
|
+
recseen.insert(cur->head());
|
1949
1937
|
// create a copy since we add multiple items if stuff get unwrapped
|
1950
1938
|
Compound_Selector_Obj cpy_head = SASS_MEMORY_NEW(Compound_Selector, cur->pstate());
|
1951
1939
|
for (Simple_Selector_Obj hs : *cur->head()) {
|
1952
|
-
if (Wrapped_Selector_Obj ws =
|
1940
|
+
if (Wrapped_Selector_Obj ws = Cast<Wrapped_Selector>(hs)) {
|
1953
1941
|
ws->selector(SASS_MEMORY_CLONE(ws->selector()));
|
1954
|
-
if (Selector_List_Obj sl =
|
1942
|
+
if (Selector_List_Obj sl = Cast<Selector_List>(ws->selector())) {
|
1955
1943
|
// special case for ruby ass
|
1956
1944
|
if (sl->empty()) {
|
1957
1945
|
// this seems inconsistent but it is how ruby sass seems to remove parentheses
|
1958
1946
|
cpy_head->append(SASS_MEMORY_NEW(Element_Selector, hs->pstate(), ws->name()));
|
1959
1947
|
}
|
1960
|
-
// has wrapped selectors
|
1961
|
-
else {
|
1948
|
+
// has wrapped not selectors
|
1949
|
+
else if (ws->name() == ":not") {
|
1962
1950
|
// extend the inner list of wrapped selector
|
1963
|
-
|
1951
|
+
bool extended = false;
|
1952
|
+
Selector_List_Obj ext_sl = extendSelectorList(sl, false, extended, recseen);
|
1964
1953
|
for (size_t i = 0; i < ext_sl->length(); i += 1) {
|
1965
1954
|
if (Complex_Selector_Obj ext_cs = ext_sl->at(i)) {
|
1966
1955
|
// create clones for wrapped selector and the inner list
|
1967
|
-
Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(
|
1956
|
+
Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(ws);
|
1968
1957
|
Selector_List_Obj cpy_ws_sl = SASS_MEMORY_NEW(Selector_List, sl->pstate());
|
1969
1958
|
// remove parent selectors from inner selector
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
Selector_List_Obj ws_cs = SASS_MEMORY_CAST(Selector_List, ext_ws->selector());
|
1974
|
-
Compound_Selector_Obj ws_ss = ws_cs->first()->head();
|
1975
|
-
if (!(
|
1976
|
-
SASS_MEMORY_CAST(Pseudo_Selector, ws_ss->first()) ||
|
1977
|
-
SASS_MEMORY_CAST(Element_Selector, ws_ss->first()) ||
|
1978
|
-
SASS_MEMORY_CAST(Placeholder_Selector, ws_ss->first())
|
1979
|
-
)) continue;
|
1980
|
-
}
|
1959
|
+
Compound_Selector_Obj ext_head = NULL;
|
1960
|
+
if (ext_cs->first()) ext_head = ext_cs->first()->head();
|
1961
|
+
if (ext_head && ext_head && ext_head->length() > 0) {
|
1981
1962
|
cpy_ws_sl->append(ext_cs->first());
|
1982
1963
|
}
|
1983
1964
|
// assign list to clone
|
1984
|
-
cpy_ws->selector(
|
1965
|
+
cpy_ws->selector(cpy_ws_sl);
|
1985
1966
|
// append the clone
|
1986
|
-
cpy_head->append(
|
1967
|
+
cpy_head->append(cpy_ws);
|
1987
1968
|
}
|
1988
1969
|
}
|
1970
|
+
if (eval && extended) {
|
1971
|
+
eval->exp.selector_stack.push_back(pNewSelectors);
|
1972
|
+
cpy_head->perform(eval);
|
1973
|
+
eval->exp.selector_stack.pop_back();
|
1974
|
+
}
|
1975
|
+
}
|
1976
|
+
// has wrapped selectors
|
1977
|
+
else {
|
1978
|
+
Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(ws);
|
1979
|
+
Selector_List_Obj ext_sl = extendSelectorList(sl, recseen);
|
1980
|
+
cpy_ws->selector(ext_sl);
|
1981
|
+
cpy_head->append(cpy_ws);
|
1989
1982
|
}
|
1990
1983
|
} else {
|
1991
|
-
cpy_head->append(
|
1984
|
+
cpy_head->append(hs);
|
1992
1985
|
}
|
1993
1986
|
} else {
|
1994
|
-
cpy_head->append(
|
1987
|
+
cpy_head->append(hs);
|
1995
1988
|
}
|
1996
1989
|
}
|
1997
1990
|
// replace header
|
@@ -2001,6 +1994,10 @@ namespace Sass {
|
|
2001
1994
|
cur = cur->tail();
|
2002
1995
|
}
|
2003
1996
|
}
|
1997
|
+
|
1998
|
+
// memory results in a map table - since extending is very expensive
|
1999
|
+
memoizeList.insert(std::pair<Selector_List_Obj, Selector_List_Obj>(pSelectorList, pNewSelectors));
|
2000
|
+
|
2004
2001
|
return pNewSelectors.detach();
|
2005
2002
|
|
2006
2003
|
}
|
@@ -2024,8 +2021,9 @@ namespace Sass {
|
|
2024
2021
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
2025
2022
|
Statement_Obj stm = b->at(i);
|
2026
2023
|
|
2027
|
-
if (
|
2028
|
-
// Do nothing. This doesn't count as a statement that causes extension since we'll
|
2024
|
+
if (Cast<Ruleset>(stm)) {
|
2025
|
+
// Do nothing. This doesn't count as a statement that causes extension since we'll
|
2026
|
+
// iterate over this rule set in a future visit and try to extend it.
|
2029
2027
|
}
|
2030
2028
|
else {
|
2031
2029
|
return true;
|
@@ -2038,37 +2036,45 @@ namespace Sass {
|
|
2038
2036
|
|
2039
2037
|
|
2040
2038
|
// Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
|
2041
|
-
|
2042
|
-
|
2039
|
+
// Every Ruleset in the whole tree is calling this function. We decide if there
|
2040
|
+
// was is @extend that matches our selector. If we find one, we will go further
|
2041
|
+
// and call the extend magic for our selector. The subset_map contains all blocks
|
2042
|
+
// where @extend was found. Pick the ones that match our selector!
|
2043
|
+
void Extend::extendObjectWithSelectorAndBlock(Ruleset_Ptr pObject) {
|
2043
2044
|
|
2044
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " <<
|
2045
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << Cast<Selector_List>(pObject->selector())->to_string())
|
2045
2046
|
|
2046
|
-
// Ruby sass seems to filter nodes that don't have any content well before we get here.
|
2047
|
-
// of doing so, so for now, let's just not extend things
|
2047
|
+
// Ruby sass seems to filter nodes that don't have any content well before we get here.
|
2048
|
+
// I'm not sure the repercussions of doing so, so for now, let's just not extend things
|
2049
|
+
// that won't be output later. Profiling shows this may us 0.2% or so.
|
2048
2050
|
if (!shouldExtendBlock(pObject->block())) {
|
2049
2051
|
DEBUG_PRINTLN(EXTEND_OBJECT, "RETURNING WITHOUT EXTEND ATTEMPT")
|
2050
2052
|
return;
|
2051
2053
|
}
|
2052
2054
|
|
2053
2055
|
bool extendedSomething = false;
|
2054
|
-
|
2056
|
+
|
2057
|
+
CompoundSelectorSet seen;
|
2058
|
+
Selector_List_Obj pNewSelectorList = extendSelectorList(pObject->selector(), false, extendedSomething, seen);
|
2055
2059
|
|
2056
2060
|
if (extendedSomething && pNewSelectorList) {
|
2057
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " <<
|
2058
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string(
|
2061
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << pObject->selector()->to_string())
|
2062
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string())
|
2059
2063
|
pNewSelectorList->remove_parent_selectors();
|
2060
|
-
pObject->selector(
|
2064
|
+
pObject->selector(pNewSelectorList);
|
2061
2065
|
} else {
|
2062
2066
|
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND DID NOT TRY TO EXTEND ANYTHING")
|
2063
2067
|
}
|
2064
2068
|
}
|
2065
2069
|
|
2066
|
-
|
2067
|
-
|
2068
|
-
Extend::Extend(Context& ctx, Subset_Map& ssm)
|
2069
|
-
: ctx(ctx), subset_map(ssm)
|
2070
|
+
Extend::Extend(Subset_Map& ssm)
|
2071
|
+
: subset_map(ssm), eval(NULL)
|
2070
2072
|
{ }
|
2071
2073
|
|
2074
|
+
void Extend::setEval(Eval& e) {
|
2075
|
+
eval = &e;
|
2076
|
+
}
|
2077
|
+
|
2072
2078
|
void Extend::operator()(Block_Ptr b)
|
2073
2079
|
{
|
2074
2080
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
@@ -2080,17 +2086,19 @@ namespace Sass {
|
|
2080
2086
|
if (b->is_root()) {
|
2081
2087
|
// debug_subset_map(subset_map);
|
2082
2088
|
for(auto const &it : subset_map.values()) {
|
2083
|
-
Complex_Selector_Ptr sel =
|
2084
|
-
Compound_Selector_Ptr ext =
|
2089
|
+
Complex_Selector_Ptr sel = NULL;
|
2090
|
+
Compound_Selector_Ptr ext = NULL;
|
2091
|
+
if (it.first) sel = it.first->first();
|
2092
|
+
if (it.second) ext = it.second;
|
2085
2093
|
if (ext && (ext->extended() || ext->is_optional())) continue;
|
2086
|
-
std::string str_sel(sel->to_string({ NESTED, 5 }));
|
2087
|
-
std::string str_ext(ext->to_string({ NESTED, 5 }));
|
2094
|
+
std::string str_sel(sel ? sel->to_string({ NESTED, 5 }) : "NULL");
|
2095
|
+
std::string str_ext(ext ? ext->to_string({ NESTED, 5 }) : "NULL");
|
2088
2096
|
// debug_ast(sel, "sel: ");
|
2089
2097
|
// debug_ast(ext, "ext: ");
|
2090
2098
|
error("\"" + str_sel + "\" failed to @extend \"" + str_ext + "\".\n"
|
2091
2099
|
"The selector \"" + str_ext + "\" was not found.\n"
|
2092
2100
|
"Use \"@extend " + str_ext + " !optional\" if the"
|
2093
|
-
|
2101
|
+
" extend should be able to fail.", (ext ? ext->pstate() : NULL), eval->exp.traces);
|
2094
2102
|
}
|
2095
2103
|
}
|
2096
2104
|
|
@@ -2098,7 +2106,7 @@ namespace Sass {
|
|
2098
2106
|
|
2099
2107
|
void Extend::operator()(Ruleset_Ptr pRuleset)
|
2100
2108
|
{
|
2101
|
-
extendObjectWithSelectorAndBlock( pRuleset
|
2109
|
+
extendObjectWithSelectorAndBlock( pRuleset );
|
2102
2110
|
pRuleset->block()->perform(this);
|
2103
2111
|
}
|
2104
2112
|
|
@@ -2114,7 +2122,7 @@ namespace Sass {
|
|
2114
2122
|
|
2115
2123
|
void Extend::operator()(Directive_Ptr a)
|
2116
2124
|
{
|
2117
|
-
// Selector_List_Ptr ls =
|
2125
|
+
// Selector_List_Ptr ls = Cast<Selector_List>(a->selector());
|
2118
2126
|
// selector_stack.push_back(ls);
|
2119
2127
|
if (a->block()) a->block()->perform(this);
|
2120
2128
|
// exp.selector_stack.pop_back();
|