extend.cpp 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962
  1. #include "extend.hpp"
  2. #include "context.hpp"
  3. #include "contextualize.hpp"
  4. #include "to_string.hpp"
  5. #include "backtrace.hpp"
  6. #include "paths.hpp"
  7. #include "parser.hpp"
  8. #ifndef SASS_AST
  9. #include "node.hpp"
  10. #endif
  11. #include "sass_util.hpp"
  12. #include "debug.hpp"
  13. #include <iostream>
  14. #include <deque>
  15. /*
  16. NOTES:
  17. - The print* functions print to cerr. This allows our testing frameworks (like sass-spec) to ignore the output, which
  18. is very helpful when debugging. The format of the output is mainly to wrap things in square brackets to match what
  19. ruby already outputs (to make comparisons easier).
  20. - For the direct porting effort, we're trying to port method-for-method until we get all the tests passing.
  21. Where applicable, I've tried to include the ruby code above the function for reference until all our tests pass.
  22. The ruby code isn't always directly portable, so I've tried to include any modified ruby code that was actually
  23. used for the porting.
  24. - DO NOT try to optimize yet. We get a tremendous benefit out of comparing the output of each stage of the extend to the ruby
  25. output at the same stage. This makes it much easier to determine where problems are. Try to keep as close to
  26. the ruby code as you can until we have all the sass-spec tests passing. Then, we should optimize. However, if you see
  27. something that could probably be optimized, let's not forget it. Add a // TODO: or // IMPROVEMENT: comment.
  28. - Coding conventions in this file (these may need to be changed before merging back into master)
  29. - Very basic hungarian notation:
  30. p prefix for pointers (pSelector)
  31. no prefix for value types and references (selector)
  32. - Use STL iterators where possible
  33. - prefer verbose naming over terse naming
  34. - use typedefs for STL container types for make maintenance easier
  35. - You may see a lot of comments that say "// TODO: is this the correct combinator?". See the comment referring to combinators
  36. in extendCompoundSelector for a more extensive explanation of my confusion. I think our divergence in data model from ruby
  37. sass causes this to be necessary.
  38. GLOBAL TODOS:
  39. - wrap the contents of the print functions in DEBUG preprocesser conditionals so they will be optimized away in non-debug mode.
  40. - consider making the extend* functions member functions to avoid passing around ctx and subsetMap map around. This has the
  41. drawback that the implementation details of the operator are then exposed to the outside world, which is not ideal and
  42. can cause additional compile time dependencies.
  43. - mark the helper methods in this file static to given them compilation unit linkage.
  44. - implement parent directive matching
  45. - fix compilation warnings for unused Extend members if we really don't need those references anymore.
  46. */
  47. namespace Sass {
  48. typedef pair<Complex_Selector*, Compound_Selector*> ExtensionPair;
  49. typedef vector<ExtensionPair> SubsetMapEntries;
  50. #ifdef DEBUG
  51. // TODO: move the ast specific ostream operators into ast.hpp/ast.cpp
  52. ostream& operator<<(ostream& os, const Complex_Selector::Combinator combinator) {
  53. switch (combinator) {
  54. case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
  55. case Complex_Selector::PARENT_OF: os << "\">\""; break;
  56. case Complex_Selector::PRECEDES: os << "\"~\""; break;
  57. case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
  58. }
  59. return os;
  60. }
  61. ostream& operator<<(ostream& os, Compound_Selector& compoundSelector) {
  62. To_String to_string;
  63. os << compoundSelector.perform(&to_string);
  64. return os;
  65. }
  66. // Print a string representation of a Compound_Selector
  67. static void printCompoundSelector(Compound_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
  68. To_String to_string;
  69. if (message) {
  70. cerr << message;
  71. }
  72. if (pCompoundSelector) {
  73. cerr << *pCompoundSelector;
  74. } else {
  75. cerr << "NULL";
  76. }
  77. if (newline) {
  78. cerr << endl;
  79. }
  80. }
  81. ostream& operator<<(ostream& os, Complex_Selector& complexSelector) {
  82. To_String to_string;
  83. os << "[";
  84. Complex_Selector* pIter = &complexSelector;
  85. bool first = true;
  86. while (pIter) {
  87. if (pIter->combinator() != Complex_Selector::ANCESTOR_OF) {
  88. if (!first) {
  89. os << ", ";
  90. }
  91. first = false;
  92. os << pIter->combinator();
  93. }
  94. if (!first) {
  95. os << ", ";
  96. }
  97. first = false;
  98. if (pIter->head()) {
  99. os << pIter->head()->perform(&to_string);
  100. } else {
  101. os << "NULL_HEAD";
  102. }
  103. pIter = pIter->tail();
  104. }
  105. os << "]";
  106. return os;
  107. }
  108. // Print a string representation of a Complex_Selector
  109. static void printComplexSelector(Complex_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
  110. To_String to_string;
  111. if (message) {
  112. cerr << message;
  113. }
  114. if (pComplexSelector) {
  115. cerr << *pComplexSelector;
  116. } else {
  117. cerr << "NULL";
  118. }
  119. if (newline) {
  120. cerr << endl;
  121. }
  122. }
  123. // Print a string representation of a SourcesSet
  124. static void printSourcesSet(SourcesSet& sources, Context& ctx, const char* message=NULL, bool newline=true) {
  125. To_String to_string;
  126. if (message) {
  127. cerr << message;
  128. }
  129. // Convert to a deque of strings so we can sort since order doesn't matter in a set. This should cut down on
  130. // the differences we see when debug printing.
  131. typedef deque<string> SourceStrings;
  132. SourceStrings sourceStrings;
  133. for (SourcesSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) {
  134. Complex_Selector* pSource = *iterator;
  135. stringstream sstream;
  136. sstream << complexSelectorToNode(pSource, ctx);
  137. sourceStrings.push_back(sstream.str());
  138. }
  139. // Sort to get consistent output
  140. std::sort(sourceStrings.begin(), sourceStrings.end());
  141. cerr << "SourcesSet[";
  142. for (SourceStrings::iterator iterator = sourceStrings.begin(), iteratorEnd = sourceStrings.end(); iterator != iteratorEnd; ++iterator) {
  143. string source = *iterator;
  144. if (iterator != sourceStrings.begin()) {
  145. cerr << ", ";
  146. }
  147. cerr << source;
  148. }
  149. cerr << "]";
  150. if (newline) {
  151. cerr << endl;
  152. }
  153. }
  154. ostream& operator<<(ostream& os, SubsetMapEntries& entries) {
  155. os << "SUBSET_MAP_ENTRIES[";
  156. for (SubsetMapEntries::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) {
  157. Complex_Selector* pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge)
  158. Compound_Selector* pExtCompoundSelector = iterator->second; // The stuff after the @extend
  159. if (iterator != entries.begin()) {
  160. os << ", ";
  161. }
  162. os << "(";
  163. if (pExtComplexSelector) {
  164. cerr << *pExtComplexSelector;
  165. } else {
  166. cerr << "NULL";
  167. }
  168. os << " -> ";
  169. if (pExtCompoundSelector) {
  170. cerr << *pExtCompoundSelector;
  171. } else {
  172. cerr << "NULL";
  173. }
  174. os << ")";
  175. }
  176. os << "]";
  177. return os;
  178. }
  179. #endif
  180. static bool parentSuperselector(Complex_Selector* pOne, Complex_Selector* pTwo, Context& ctx) {
  181. // TODO: figure out a better way to create a Complex_Selector from scratch
  182. // TODO: There's got to be a better way. This got ugly quick...
  183. Position noPosition;
  184. Type_Selector fakeParent("", noPosition, "temp");
  185. Compound_Selector fakeHead("", noPosition, 1 /*size*/);
  186. fakeHead.elements().push_back(&fakeParent);
  187. Complex_Selector fakeParentContainer("", noPosition, Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
  188. pOne->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
  189. pTwo->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
  190. bool isSuperselector = pOne->is_superselector_of(pTwo);
  191. pOne->clear_innermost();
  192. pTwo->clear_innermost();
  193. return isSuperselector;
  194. }
  195. void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out, Context& ctx) {
  196. for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
  197. Node& child = *iter;
  198. out.push_back(nodeToComplexSelector(child, ctx));
  199. }
  200. }
  201. Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque, Context& ctx) {
  202. Node result = Node::createCollection();
  203. for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) {
  204. Complex_Selector* pChild = *iter;
  205. result.collection()->push_back(complexSelectorToNode(pChild, ctx));
  206. }
  207. return result;
  208. }
  209. class LcsCollectionComparator {
  210. public:
  211. LcsCollectionComparator(Context& ctx) : mCtx(ctx) {}
  212. Context& mCtx;
  213. bool operator()(Complex_Selector* pOne, Complex_Selector* pTwo, Complex_Selector*& pOut) const {
  214. /*
  215. This code is based on the following block from ruby sass' subweave
  216. do |s1, s2|
  217. next s1 if s1 == s2
  218. next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
  219. next s2 if parent_superselector?(s1, s2)
  220. next s1 if parent_superselector?(s2, s1)
  221. end
  222. */
  223. if (selectors_equal(*pOne, *pTwo, true /*simpleSelectorOrderDependent*/)) {
  224. pOut = pOne;
  225. return true;
  226. }
  227. if (pOne->combinator() != Complex_Selector::ANCESTOR_OF || pTwo->combinator() != Complex_Selector::ANCESTOR_OF) {
  228. return false;
  229. }
  230. if (parentSuperselector(pOne, pTwo, mCtx)) {
  231. pOut = pTwo;
  232. return true;
  233. }
  234. if (parentSuperselector(pTwo, pOne, mCtx)) {
  235. pOut = pOne;
  236. return true;
  237. }
  238. return false;
  239. }
  240. };
  241. /*
  242. This is the equivalent of ruby's Sass::Util.lcs_backtrace.
  243. # Computes a single longest common subsequence for arrays x and y.
  244. # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS
  245. */
  246. void lcs_backtrace(const LCSTable& c, ComplexSelectorDeque& x, ComplexSelectorDeque& y, int i, int j, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) {
  247. //DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j)
  248. // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
  249. if (i == 0 || j == 0) {
  250. DEBUG_PRINTLN(LCS, "RETURNING EMPTY")
  251. return;
  252. }
  253. Complex_Selector* pCompareOut = NULL;
  254. if (comparator(x[i], y[j], pCompareOut)) {
  255. DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE")
  256. lcs_backtrace(c, x, y, i - 1, j - 1, comparator, out);
  257. out.push_back(pCompareOut);
  258. return;
  259. }
  260. if (c[i][j - 1] > c[i - 1][j]) {
  261. DEBUG_PRINTLN(LCS, "RETURNING AFTER TABLE COMPARE")
  262. lcs_backtrace(c, x, y, i, j - 1, comparator, out);
  263. return;
  264. }
  265. DEBUG_PRINTLN(LCS, "FINAL RETURN")
  266. lcs_backtrace(c, x, y, i - 1, j, comparator, out);
  267. return;
  268. }
  269. /*
  270. This is the equivalent of ruby's Sass::Util.lcs_table.
  271. # Calculates the memoization table for the Least Common Subsequence algorithm.
  272. # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS
  273. */
  274. void lcs_table(const ComplexSelectorDeque& x, const ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, LCSTable& out) {
  275. //DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y)
  276. // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
  277. LCSTable c(x.size(), vector<int>(y.size()));
  278. // These shouldn't be necessary since the vector will be initialized to 0 already.
  279. // x.size.times {|i| c[i][0] = 0}
  280. // y.size.times {|j| c[0][j] = 0}
  281. for (size_t i = 1; i < x.size(); i++) {
  282. for (size_t j = 1; j < y.size(); j++) {
  283. Complex_Selector* pCompareOut = NULL;
  284. if (comparator(x[i], y[j], pCompareOut)) {
  285. c[i][j] = c[i - 1][j - 1] + 1;
  286. } else {
  287. c[i][j] = max(c[i][j - 1], c[i - 1][j]);
  288. }
  289. }
  290. }
  291. out = c;
  292. }
  293. /*
  294. This is the equivalent of ruby's Sass::Util.lcs.
  295. # Computes a single longest common subsequence for `x` and `y`.
  296. # If there are more than one longest common subsequences,
  297. # the one returned is that which starts first in `x`.
  298. # @param x [NodeCollection]
  299. # @param y [NodeCollection]
  300. # @comparator An equality check between elements of `x` and `y`.
  301. # @return [NodeCollection] The LCS
  302. http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
  303. */
  304. void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, Context& ctx, ComplexSelectorDeque& out) {
  305. //DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y)
  306. // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
  307. x.push_front(NULL);
  308. y.push_front(NULL);
  309. LCSTable table;
  310. lcs_table(x, y, comparator, table);
  311. return lcs_backtrace(table, x, y, static_cast<int>(x.size()) - 1, static_cast<int>(y.size()) - 1, comparator, out);
  312. }
  313. /*
  314. This is the equivalent of ruby's Sequence.trim.
  315. The following is the modified version of the ruby code that was more portable to C++. You
  316. should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
  317. # Avoid truly horrific quadratic behavior. TODO: I think there
  318. # may be a way to get perfect trimming without going quadratic.
  319. return seqses if seqses.size > 100
  320. # Keep the results in a separate array so we can be sure we aren't
  321. # comparing against an already-trimmed selector. This ensures that two
  322. # identical selectors don't mutually trim one another.
  323. result = seqses.dup
  324. # This is n^2 on the sequences, but only comparing between
  325. # separate sequences should limit the quadratic behavior.
  326. seqses.each_with_index do |seqs1, i|
  327. tempResult = []
  328. for seq1 in seqs1 do
  329. max_spec = 0
  330. for seq in _sources(seq1) do
  331. max_spec = [max_spec, seq.specificity].max
  332. end
  333. isMoreSpecificOuter = false
  334. for seqs2 in result do
  335. if seqs1.equal?(seqs2) then
  336. next
  337. end
  338. # Second Law of Extend: the specificity of a generated selector
  339. # should never be less than the specificity of the extending
  340. # selector.
  341. #
  342. # See https://github.com/nex3/sass/issues/324.
  343. isMoreSpecificInner = false
  344. for seq2 in seqs2 do
  345. isMoreSpecificInner = _specificity(seq2) >= max_spec && _superselector?(seq2, seq1)
  346. if isMoreSpecificInner then
  347. break
  348. end
  349. end
  350. if isMoreSpecificInner then
  351. isMoreSpecificOuter = true
  352. break
  353. end
  354. end
  355. if !isMoreSpecificOuter then
  356. tempResult.push(seq1)
  357. end
  358. end
  359. result[i] = tempResult
  360. end
  361. result
  362. */
  363. /*
  364. - IMPROVEMENT: We could probably work directly in the output trimmed deque.
  365. */
  366. static Node trim(Node& seqses, Context& ctx) {
  367. // See the comments in the above ruby code before embarking on understanding this function.
  368. // Avoid poor performance in extreme cases.
  369. if (seqses.collection()->size() > 100) {
  370. return seqses;
  371. }
  372. DEBUG_PRINTLN(TRIM, "TRIM: " << seqses)
  373. Node result = Node::createCollection();
  374. result.plus(seqses);
  375. DEBUG_PRINTLN(TRIM, "RESULT INITIAL: " << result)
  376. // Normally we use the standard STL iterators, but in this case, we need to access the result collection by index since we're
  377. // iterating the input collection, computing a value, and then setting the result in the output collection. We have to keep track
  378. // of the index manually.
  379. int toTrimIndex = 0;
  380. for (NodeDeque::iterator seqsesIter = seqses.collection()->begin(), seqsesIterEnd = seqses.collection()->end(); seqsesIter != seqsesIterEnd; ++seqsesIter) {
  381. Node& seqs1 = *seqsesIter;
  382. DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1 << " " << toTrimIndex)
  383. Node tempResult = Node::createCollection();
  384. for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) {
  385. Node& seq1 = *seqs1Iter;
  386. Complex_Selector* pSeq1 = nodeToComplexSelector(seq1, ctx);
  387. // Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code
  388. // for a good description of sources.
  389. //
  390. // TODO: I'm pretty sure there's a bug in the sources code. It was implemented for sass-spec's 182_test_nested_extend_loop test.
  391. // While the test passes, I compared the state of each trim call to verify correctness. The last trim call had incorrect sources. We
  392. // had an extra source that the ruby version did not have. Without a failing test case, this is going to be extra hard to find. My
  393. // 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
  394. // a guess though.
  395. int maxSpecificity = 0;
  396. SourcesSet sources = pSeq1->sources();
  397. DEBUG_PRINTLN(TRIM, "TRIMASDF SEQ1: " << seq1)
  398. DEBUG_EXEC(TRIM, printSourcesSet(sources, ctx, "TRIMASDF SOURCES: "))
  399. for (SourcesSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
  400. const Complex_Selector* const pCurrentSelector = *sourcesSetIterator;
  401. maxSpecificity = max(maxSpecificity, pCurrentSelector->specificity());
  402. }
  403. DEBUG_PRINTLN(TRIM, "MAX SPECIFICITY: " << maxSpecificity)
  404. bool isMoreSpecificOuter = false;
  405. int resultIndex = 0;
  406. for (NodeDeque::iterator resultIter = result.collection()->begin(), resultIterEnd = result.collection()->end(); resultIter != resultIterEnd; ++resultIter) {
  407. Node& seqs2 = *resultIter;
  408. DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1)
  409. DEBUG_PRINTLN(TRIM, "SEQS2: " << seqs2)
  410. // Do not compare the same sequence to itself. The ruby call we're trying to
  411. // emulate is: seqs1.equal?(seqs2). equal? is an object comparison, not an equivalency comparision.
  412. // Since we have the same pointers in seqes and results, we can do a pointer comparision. seqs1 is
  413. // derived from seqses and seqs2 is derived from result.
  414. if (seqs1.collection() == seqs2.collection()) {
  415. DEBUG_PRINTLN(TRIM, "CONTINUE")
  416. continue;
  417. }
  418. bool isMoreSpecificInner = false;
  419. for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) {
  420. Node& seq2 = *seqs2Iter;
  421. Complex_Selector* pSeq2 = nodeToComplexSelector(seq2, ctx);
  422. DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity())
  423. DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false"))
  424. DEBUG_PRINTLN(TRIM, "IS SUPER: " << (pSeq2->is_superselector_of(pSeq1) ? "true" : "false"))
  425. isMoreSpecificInner = pSeq2->specificity() >= maxSpecificity && pSeq2->is_superselector_of(pSeq1);
  426. if (isMoreSpecificInner) {
  427. DEBUG_PRINTLN(TRIM, "FOUND MORE SPECIFIC")
  428. break;
  429. }
  430. }
  431. // If we found something more specific, we're done. Let the outer loop know and stop iterating.
  432. if (isMoreSpecificInner) {
  433. isMoreSpecificOuter = true;
  434. break;
  435. }
  436. resultIndex++;
  437. }
  438. if (!isMoreSpecificOuter) {
  439. DEBUG_PRINTLN(TRIM, "PUSHING: " << seq1)
  440. tempResult.collection()->push_back(seq1);
  441. }
  442. }
  443. DEBUG_PRINTLN(TRIM, "RESULT BEFORE ASSIGN: " << result)
  444. DEBUG_PRINTLN(TRIM, "TEMP RESULT: " << toTrimIndex << " " << tempResult)
  445. (*result.collection())[toTrimIndex] = tempResult;
  446. toTrimIndex++;
  447. DEBUG_PRINTLN(TRIM, "RESULT: " << result)
  448. }
  449. return result;
  450. }
  451. static bool parentSuperselector(const Node& one, const Node& two, Context& ctx) {
  452. // TODO: figure out a better way to create a Complex_Selector from scratch
  453. // TODO: There's got to be a better way. This got ugly quick...
  454. Position noPosition;
  455. Type_Selector fakeParent("", noPosition, "temp");
  456. Compound_Selector fakeHead("", noPosition, 1 /*size*/);
  457. fakeHead.elements().push_back(&fakeParent);
  458. Complex_Selector fakeParentContainer("", noPosition, Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
  459. Complex_Selector* pOneWithFakeParent = nodeToComplexSelector(one, ctx);
  460. pOneWithFakeParent->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
  461. Complex_Selector* pTwoWithFakeParent = nodeToComplexSelector(two, ctx);
  462. pTwoWithFakeParent->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
  463. return pOneWithFakeParent->is_superselector_of(pTwoWithFakeParent);
  464. }
  465. class ParentSuperselectorChunker {
  466. public:
  467. ParentSuperselectorChunker(Node& lcs, Context& ctx) : mLcs(lcs), mCtx(ctx) {}
  468. Node& mLcs;
  469. Context& mCtx;
  470. bool operator()(const Node& seq) const {
  471. // {|s| parent_superselector?(s.first, lcs.first)}
  472. return parentSuperselector(seq.collection()->front(), mLcs.collection()->front(), mCtx);
  473. }
  474. };
  475. class SubweaveEmptyChunker {
  476. public:
  477. bool operator()(const Node& seq) const {
  478. // {|s| s.empty?}
  479. return seq.collection()->empty();
  480. }
  481. };
  482. /*
  483. # Takes initial subsequences of `seq1` and `seq2` and returns all
  484. # orderings of those subsequences. The initial subsequences are determined
  485. # by a block.
  486. #
  487. # Destructively removes the initial subsequences of `seq1` and `seq2`.
  488. #
  489. # For example, given `(A B C | D E)` and `(1 2 | 3 4 5)` (with `|`
  490. # denoting the boundary of the initial subsequence), this would return
  491. # `[(A B C 1 2), (1 2 A B C)]`. The sequences would then be `(D E)` and
  492. # `(3 4 5)`.
  493. #
  494. # @param seq1 [Array]
  495. # @param seq2 [Array]
  496. # @yield [a] Used to determine when to cut off the initial subsequences.
  497. # Called repeatedly for each sequence until it returns true.
  498. # @yieldparam a [Array] A final subsequence of one input sequence after
  499. # cutting off some initial subsequence.
  500. # @yieldreturn [Boolean] Whether or not to cut off the initial subsequence
  501. # here.
  502. # @return [Array<Array>] All possible orderings of the initial subsequences.
  503. def chunks(seq1, seq2)
  504. chunk1 = []
  505. chunk1 << seq1.shift until yield seq1
  506. chunk2 = []
  507. chunk2 << seq2.shift until yield seq2
  508. return [] if chunk1.empty? && chunk2.empty?
  509. return [chunk2] if chunk1.empty?
  510. return [chunk1] if chunk2.empty?
  511. [chunk1 + chunk2, chunk2 + chunk1]
  512. end
  513. */
  514. template<typename ChunkerType>
  515. static Node chunks(Node& seq1, Node& seq2, const ChunkerType& chunker) {
  516. Node chunk1 = Node::createCollection();
  517. while (!chunker(seq1)) {
  518. chunk1.collection()->push_back(seq1.collection()->front());
  519. seq1.collection()->pop_front();
  520. }
  521. Node chunk2 = Node::createCollection();
  522. while (!chunker(seq2)) {
  523. chunk2.collection()->push_back(seq2.collection()->front());
  524. seq2.collection()->pop_front();
  525. }
  526. if (chunk1.collection()->empty() && chunk2.collection()->empty()) {
  527. DEBUG_PRINTLN(CHUNKS, "RETURNING BOTH EMPTY")
  528. return Node::createCollection();
  529. }
  530. if (chunk1.collection()->empty()) {
  531. Node chunk2Wrapper = Node::createCollection();
  532. chunk2Wrapper.collection()->push_back(chunk2);
  533. DEBUG_PRINTLN(CHUNKS, "RETURNING ONE EMPTY")
  534. return chunk2Wrapper;
  535. }
  536. if (chunk2.collection()->empty()) {
  537. Node chunk1Wrapper = Node::createCollection();
  538. chunk1Wrapper.collection()->push_back(chunk1);
  539. DEBUG_PRINTLN(CHUNKS, "RETURNING TWO EMPTY")
  540. return chunk1Wrapper;
  541. }
  542. Node perms = Node::createCollection();
  543. Node firstPermutation = Node::createCollection();
  544. firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end());
  545. firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end());
  546. perms.collection()->push_back(firstPermutation);
  547. Node secondPermutation = Node::createCollection();
  548. secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end());
  549. secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end());
  550. perms.collection()->push_back(secondPermutation);
  551. DEBUG_PRINTLN(CHUNKS, "RETURNING PERM")
  552. return perms;
  553. }
  554. static Node groupSelectors(Node& seq, Context& ctx) {
  555. Node newSeq = Node::createCollection();
  556. Node tail = Node::createCollection();
  557. tail.plus(seq);
  558. while (!tail.collection()->empty()) {
  559. Node head = Node::createCollection();
  560. do {
  561. head.collection()->push_back(tail.collection()->front());
  562. tail.collection()->pop_front();
  563. } while (!tail.collection()->empty() && (head.collection()->back().isCombinator() || tail.collection()->front().isCombinator()));
  564. newSeq.collection()->push_back(head);
  565. }
  566. return newSeq;
  567. }
  568. static void getAndRemoveInitialOps(Node& seq, Node& ops) {
  569. NodeDeque& seqCollection = *(seq.collection());
  570. NodeDeque& opsCollection = *(ops.collection());
  571. while (seqCollection.size() > 0 && seqCollection.front().isCombinator()) {
  572. opsCollection.push_back(seqCollection.front());
  573. seqCollection.pop_front();
  574. }
  575. }
  576. static void getAndRemoveFinalOps(Node& seq, Node& ops) {
  577. NodeDeque& seqCollection = *(seq.collection());
  578. NodeDeque& opsCollection = *(ops.collection());
  579. while (seqCollection.size() > 0 && seqCollection.back().isCombinator()) {
  580. opsCollection.push_back(seqCollection.back()); // Purposefully reversed to match ruby code
  581. seqCollection.pop_back();
  582. }
  583. }
  584. /*
  585. def merge_initial_ops(seq1, seq2)
  586. ops1, ops2 = [], []
  587. ops1 << seq1.shift while seq1.first.is_a?(String)
  588. ops2 << seq2.shift while seq2.first.is_a?(String)
  589. newline = false
  590. newline ||= !!ops1.shift if ops1.first == "\n"
  591. newline ||= !!ops2.shift if ops2.first == "\n"
  592. # If neither sequence is a subsequence of the other, they cannot be
  593. # merged successfully
  594. lcs = Sass::Util.lcs(ops1, ops2)
  595. return unless lcs == ops1 || lcs == ops2
  596. return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
  597. end
  598. */
  599. static Node mergeInitialOps(Node& seq1, Node& seq2, Context& ctx) {
  600. Node ops1 = Node::createCollection();
  601. Node ops2 = Node::createCollection();
  602. getAndRemoveInitialOps(seq1, ops1);
  603. getAndRemoveInitialOps(seq2, ops2);
  604. // TODO: Do we have this information available to us?
  605. // newline = false
  606. // newline ||= !!ops1.shift if ops1.first == "\n"
  607. // newline ||= !!ops2.shift if ops2.first == "\n"
  608. // If neither sequence is a subsequence of the other, they cannot be merged successfully
  609. DefaultLcsComparator lcsDefaultComparator;
  610. Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator, ctx);
  611. if (!(opsLcs == ops1 || opsLcs == ops2)) {
  612. return Node::createNil();
  613. }
  614. // TODO: more newline logic
  615. // return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
  616. return (ops1.collection()->size() > ops2.collection()->size() ? ops1 : ops2);
  617. }
  618. /*
  619. def merge_final_ops(seq1, seq2, res = [])
  620. # This code looks complicated, but it's actually just a bunch of special
  621. # cases for interactions between different combinators.
  622. op1, op2 = ops1.first, ops2.first
  623. if op1 && op2
  624. sel1 = seq1.pop
  625. sel2 = seq2.pop
  626. if op1 == '~' && op2 == '~'
  627. if sel1.superselector?(sel2)
  628. res.unshift sel2, '~'
  629. elsif sel2.superselector?(sel1)
  630. res.unshift sel1, '~'
  631. else
  632. merged = sel1.unify(sel2.members, sel2.subject?)
  633. res.unshift [
  634. [sel1, '~', sel2, '~'],
  635. [sel2, '~', sel1, '~'],
  636. ([merged, '~'] if merged)
  637. ].compact
  638. end
  639. elsif (op1 == '~' && op2 == '+') || (op1 == '+' && op2 == '~')
  640. if op1 == '~'
  641. tilde_sel, plus_sel = sel1, sel2
  642. else
  643. tilde_sel, plus_sel = sel2, sel1
  644. end
  645. if tilde_sel.superselector?(plus_sel)
  646. res.unshift plus_sel, '+'
  647. else
  648. merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
  649. res.unshift [
  650. [tilde_sel, '~', plus_sel, '+'],
  651. ([merged, '+'] if merged)
  652. ].compact
  653. end
  654. elsif op1 == '>' && %w[~ +].include?(op2)
  655. res.unshift sel2, op2
  656. seq1.push sel1, op1
  657. elsif op2 == '>' && %w[~ +].include?(op1)
  658. res.unshift sel1, op1
  659. seq2.push sel2, op2
  660. elsif op1 == op2
  661. return unless merged = sel1.unify(sel2.members, sel2.subject?)
  662. res.unshift merged, op1
  663. else
  664. # Unknown selector combinators can't be unified
  665. return
  666. end
  667. return merge_final_ops(seq1, seq2, res)
  668. elsif op1
  669. seq2.pop if op1 == '>' && seq2.last && seq2.last.superselector?(seq1.last)
  670. res.unshift seq1.pop, op1
  671. return merge_final_ops(seq1, seq2, res)
  672. else # op2
  673. seq1.pop if op2 == '>' && seq1.last && seq1.last.superselector?(seq2.last)
  674. res.unshift seq2.pop, op2
  675. return merge_final_ops(seq1, seq2, res)
  676. end
  677. end
  678. */
  679. static Node mergeFinalOps(Node& seq1, Node& seq2, Context& ctx, Node& res) {
  680. Node ops1 = Node::createCollection();
  681. Node ops2 = Node::createCollection();
  682. getAndRemoveFinalOps(seq1, ops1);
  683. getAndRemoveFinalOps(seq2, ops2);
  684. // TODO: do we have newlines to remove?
  685. // ops1.reject! {|o| o == "\n"}
  686. // ops2.reject! {|o| o == "\n"}
  687. if (ops1.collection()->empty() && ops2.collection()->empty()) {
  688. return res;
  689. }
  690. if (ops1.collection()->size() > 1 || ops2.collection()->size() > 1) {
  691. DefaultLcsComparator lcsDefaultComparator;
  692. Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator, ctx);
  693. // If there are multiple operators, something hacky's going on. If one is a supersequence of the other, use that, otherwise give up.
  694. if (!(opsLcs == ops1 || opsLcs == ops2)) {
  695. return Node::createNil();
  696. }
  697. if (ops1.collection()->size() > ops2.collection()->size()) {
  698. res.collection()->insert(res.collection()->begin(), ops1.collection()->rbegin(), ops1.collection()->rend());
  699. } else {
  700. res.collection()->insert(res.collection()->begin(), ops2.collection()->rbegin(), ops2.collection()->rend());
  701. }
  702. return res;
  703. }
  704. if (!ops1.collection()->empty() && !ops2.collection()->empty()) {
  705. Node op1 = ops1.collection()->front();
  706. Node op2 = ops2.collection()->front();
  707. Node sel1 = seq1.collection()->back();
  708. seq1.collection()->pop_back();
  709. Node sel2 = seq2.collection()->back();
  710. seq2.collection()->pop_back();
  711. if (op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::PRECEDES) {
  712. if (sel1.selector()->is_superselector_of(sel2.selector())) {
  713. res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/);
  714. res.collection()->push_front(sel2);
  715. } else if (sel2.selector()->is_superselector_of(sel1.selector())) {
  716. res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/);
  717. res.collection()->push_front(sel1);
  718. } else {
  719. DEBUG_PRINTLN(ALL, "sel1: " << sel1)
  720. DEBUG_PRINTLN(ALL, "sel2: " << sel2)
  721. Complex_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
  722. // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
  723. Compound_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
  724. pMergedWrapper->head(pMerged);
  725. DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
  726. Node newRes = Node::createCollection();
  727. Node firstPerm = Node::createCollection();
  728. firstPerm.collection()->push_back(sel1);
  729. firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
  730. firstPerm.collection()->push_back(sel2);
  731. firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
  732. newRes.collection()->push_back(firstPerm);
  733. Node secondPerm = Node::createCollection();
  734. secondPerm.collection()->push_back(sel2);
  735. secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
  736. secondPerm.collection()->push_back(sel1);
  737. secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
  738. newRes.collection()->push_back(secondPerm);
  739. if (pMerged) {
  740. Node mergedPerm = Node::createCollection();
  741. mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
  742. mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
  743. newRes.collection()->push_back(mergedPerm);
  744. }
  745. res.collection()->push_front(newRes);
  746. DEBUG_PRINTLN(ALL, "RESULT: " << res)
  747. }
  748. } else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) {
  749. Node tildeSel = sel1;
  750. Node tildeOp = op1;
  751. Node plusSel = sel2;
  752. Node plusOp = op2;
  753. if (op1.combinator() != Complex_Selector::PRECEDES) {
  754. tildeSel = sel2;
  755. tildeOp = op2;
  756. plusSel = sel1;
  757. plusOp = op1;
  758. }
  759. if (tildeSel.selector()->is_superselector_of(plusSel.selector())) {
  760. res.collection()->push_front(plusOp);
  761. res.collection()->push_front(plusSel);
  762. } else {
  763. DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel)
  764. DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel)
  765. Complex_Selector* pMergedWrapper = plusSel.selector()->clone(ctx); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
  766. // TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
  767. Compound_Selector* pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head(), ctx);
  768. pMergedWrapper->head(pMerged);
  769. DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
  770. Node newRes = Node::createCollection();
  771. Node firstPerm = Node::createCollection();
  772. firstPerm.collection()->push_back(tildeSel);
  773. firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
  774. firstPerm.collection()->push_back(plusSel);
  775. firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
  776. newRes.collection()->push_back(firstPerm);
  777. if (pMerged) {
  778. Node mergedPerm = Node::createCollection();
  779. mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
  780. mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
  781. newRes.collection()->push_back(mergedPerm);
  782. }
  783. res.collection()->push_front(newRes);
  784. DEBUG_PRINTLN(ALL, "RESULT: " << res)
  785. }
  786. } else if (op1.combinator() == Complex_Selector::PARENT_OF && (op2.combinator() == Complex_Selector::PRECEDES || op2.combinator() == Complex_Selector::ADJACENT_TO)) {
  787. res.collection()->push_front(op2);
  788. res.collection()->push_front(sel2);
  789. seq2.collection()->push_back(sel1);
  790. seq2.collection()->push_back(op1);
  791. } else if (op2.combinator() == Complex_Selector::PARENT_OF && (op1.combinator() == Complex_Selector::PRECEDES || op1.combinator() == Complex_Selector::ADJACENT_TO)) {
  792. res.collection()->push_front(op1);
  793. res.collection()->push_front(sel1);
  794. seq2.collection()->push_back(sel2);
  795. seq2.collection()->push_back(op2);
  796. } else if (op1.combinator() == op2.combinator()) {
  797. DEBUG_PRINTLN(ALL, "sel1: " << sel1)
  798. DEBUG_PRINTLN(ALL, "sel2: " << sel2)
  799. Complex_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
  800. // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
  801. Compound_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
  802. pMergedWrapper->head(pMerged);
  803. DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
  804. if (!pMerged) {
  805. return Node::createNil();
  806. }
  807. res.collection()->push_front(op1);
  808. res.collection()->push_front(Node::createSelector(pMergedWrapper, ctx));
  809. DEBUG_PRINTLN(ALL, "RESULT: " << res)
  810. } else {
  811. return Node::createNil();
  812. }
  813. return mergeFinalOps(seq1, seq2, ctx, res);
  814. } else if (!ops1.collection()->empty()) {
  815. Node op1 = ops1.collection()->front();
  816. if (op1.combinator() == Complex_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) {
  817. seq2.collection()->pop_back();
  818. }
  819. // TODO: consider unshift(NodeCollection, Node)
  820. res.collection()->push_front(op1);
  821. res.collection()->push_front(seq1.collection()->back());
  822. seq1.collection()->pop_back();
  823. return mergeFinalOps(seq1, seq2, ctx, res);
  824. } else { // !ops2.collection()->empty()
  825. Node op2 = ops2.collection()->front();
  826. if (op2.combinator() == Complex_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) {
  827. seq1.collection()->pop_back();
  828. }
  829. res.collection()->push_front(op2);
  830. res.collection()->push_front(seq2.collection()->back());
  831. seq2.collection()->pop_back();
  832. return mergeFinalOps(seq1, seq2, ctx, res);
  833. }
  834. }
  835. /*
  836. This is the equivalent of ruby's Sequence.subweave.
  837. Here is the original subweave code for reference during porting.
  838. def subweave(seq1, seq2)
  839. return [seq2] if seq1.empty?
  840. return [seq1] if seq2.empty?
  841. seq1, seq2 = seq1.dup, seq2.dup
  842. return unless init = merge_initial_ops(seq1, seq2)
  843. return unless fin = merge_final_ops(seq1, seq2)
  844. seq1 = group_selectors(seq1)
  845. seq2 = group_selectors(seq2)
  846. lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
  847. next s1 if s1 == s2
  848. next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
  849. next s2 if parent_superselector?(s1, s2)
  850. next s1 if parent_superselector?(s2, s1)
  851. end
  852. diff = [[init]]
  853. until lcs.empty?
  854. diff << chunks(seq1, seq2) {|s| parent_superselector?(s.first, lcs.first)} << [lcs.shift]
  855. seq1.shift
  856. seq2.shift
  857. end
  858. diff << chunks(seq1, seq2) {|s| s.empty?}
  859. diff += fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
  860. diff.reject! {|c| c.empty?}
  861. result = Sass::Util.paths(diff).map {|p| p.flatten}.reject {|p| path_has_two_subjects?(p)}
  862. result
  863. end
  864. */
  865. static Node subweave(Node& one, Node& two, Context& ctx) {
  866. // Check for the simple cases
  867. if (one.collection()->size() == 0) {
  868. Node out = Node::createCollection();
  869. out.collection()->push_back(two);
  870. return out;
  871. }
  872. if (two.collection()->size() == 0) {
  873. Node out = Node::createCollection();
  874. out.collection()->push_back(one);
  875. return out;
  876. }
  877. Node seq1 = Node::createCollection();
  878. seq1.plus(one);
  879. Node seq2 = Node::createCollection();
  880. seq2.plus(two);
  881. DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE ONE: " << seq1)
  882. DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE TWO: " << seq2)
  883. Node init = mergeInitialOps(seq1, seq2, ctx);
  884. if (init.isNil()) {
  885. return Node::createNil();
  886. }
  887. DEBUG_PRINTLN(SUBWEAVE, "INIT: " << init)
  888. Node res = Node::createCollection();
  889. Node fin = mergeFinalOps(seq1, seq2, ctx, res);
  890. if (fin.isNil()) {
  891. return Node::createNil();
  892. }
  893. DEBUG_PRINTLN(SUBWEAVE, "FIN: " << fin)
  894. // Moving this line up since fin isn't modified between now and when it happened before
  895. // fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
  896. for (NodeDeque::iterator finIter = fin.collection()->begin(), finEndIter = fin.collection()->end();
  897. finIter != finEndIter; ++finIter) {
  898. Node& childNode = *finIter;
  899. if (!childNode.isCollection()) {
  900. Node wrapper = Node::createCollection();
  901. wrapper.collection()->push_back(childNode);
  902. childNode = wrapper;
  903. }
  904. }
  905. DEBUG_PRINTLN(SUBWEAVE, "FIN MAPPED: " << fin)
  906. Node groupSeq1 = groupSelectors(seq1, ctx);
  907. DEBUG_PRINTLN(SUBWEAVE, "SEQ1: " << groupSeq1)
  908. Node groupSeq2 = groupSelectors(seq2, ctx);
  909. DEBUG_PRINTLN(SUBWEAVE, "SEQ2: " << groupSeq2)
  910. ComplexSelectorDeque groupSeq1Converted;
  911. nodeToComplexSelectorDeque(groupSeq1, groupSeq1Converted, ctx);
  912. ComplexSelectorDeque groupSeq2Converted;
  913. nodeToComplexSelectorDeque(groupSeq2, groupSeq2Converted, ctx);
  914. ComplexSelectorDeque out;
  915. LcsCollectionComparator collectionComparator(ctx);
  916. lcs(groupSeq2Converted, groupSeq1Converted, collectionComparator, ctx, out);
  917. Node seqLcs = complexSelectorDequeToNode(out, ctx);
  918. DEBUG_PRINTLN(SUBWEAVE, "SEQLCS: " << seqLcs)
  919. Node initWrapper = Node::createCollection();
  920. initWrapper.collection()->push_back(init);
  921. Node diff = Node::createCollection();
  922. diff.collection()->push_back(initWrapper);
  923. DEBUG_PRINTLN(SUBWEAVE, "DIFF INIT: " << diff)
  924. while (!seqLcs.collection()->empty()) {
  925. ParentSuperselectorChunker superselectorChunker(seqLcs, ctx);
  926. Node chunksResult = chunks(groupSeq1, groupSeq2, superselectorChunker);
  927. diff.collection()->push_back(chunksResult);
  928. Node lcsWrapper = Node::createCollection();
  929. lcsWrapper.collection()->push_back(seqLcs.collection()->front());
  930. seqLcs.collection()->pop_front();
  931. diff.collection()->push_back(lcsWrapper);
  932. groupSeq1.collection()->pop_front();
  933. groupSeq2.collection()->pop_front();
  934. }
  935. DEBUG_PRINTLN(SUBWEAVE, "DIFF POST LCS: " << diff)
  936. DEBUG_PRINTLN(SUBWEAVE, "CHUNKS: ONE=" << groupSeq1 << " TWO=" << groupSeq2)
  937. SubweaveEmptyChunker emptyChunker;
  938. Node chunksResult = chunks(groupSeq1, groupSeq2, emptyChunker);
  939. diff.collection()->push_back(chunksResult);
  940. DEBUG_PRINTLN(SUBWEAVE, "DIFF POST CHUNKS: " << diff)
  941. diff.collection()->insert(diff.collection()->end(), fin.collection()->begin(), fin.collection()->end());
  942. DEBUG_PRINTLN(SUBWEAVE, "DIFF POST FIN MAPPED: " << diff)
  943. // JMA - filter out the empty nodes (use a new collection, since iterator erase() invalidates the old collection)
  944. Node diffFiltered = Node::createCollection();
  945. for (NodeDeque::iterator diffIter = diff.collection()->begin(), diffEndIter = diff.collection()->end();
  946. diffIter != diffEndIter; ++diffIter) {
  947. Node& node = *diffIter;
  948. if (node.collection() && !node.collection()->empty()) {
  949. diffFiltered.collection()->push_back(node);
  950. }
  951. }
  952. diff = diffFiltered;
  953. DEBUG_PRINTLN(SUBWEAVE, "DIFF POST REJECT: " << diff)
  954. Node pathsResult = paths(diff, ctx);
  955. DEBUG_PRINTLN(SUBWEAVE, "PATHS: " << pathsResult)
  956. // We're flattening in place
  957. for (NodeDeque::iterator pathsIter = pathsResult.collection()->begin(), pathsEndIter = pathsResult.collection()->end();
  958. pathsIter != pathsEndIter; ++pathsIter) {
  959. Node& child = *pathsIter;
  960. child = flatten(child, ctx);
  961. }
  962. DEBUG_PRINTLN(SUBWEAVE, "FLATTENED: " << pathsResult)
  963. /*
  964. TODO: implement
  965. rejected = mapped.reject {|p| path_has_two_subjects?(p)}
  966. $stderr.puts "REJECTED: #{rejected}"
  967. */
  968. return pathsResult;
  969. }
  970. /*
  971. // disabled to avoid clang warning [-Wunused-function]
  972. static Node subweaveNaive(const Node& one, const Node& two, Context& ctx) {
  973. Node out = Node::createCollection();
  974. // Check for the simple cases
  975. if (one.isNil()) {
  976. out.collection()->push_back(two.clone(ctx));
  977. } else if (two.isNil()) {
  978. out.collection()->push_back(one.clone(ctx));
  979. } else {
  980. // Do the naive implementation. pOne = A B and pTwo = C D ...yields... A B C D and C D A B
  981. // See https://gist.github.com/nex3/7609394 for details.
  982. Node firstPerm = one.clone(ctx);
  983. Node twoCloned = two.clone(ctx);
  984. firstPerm.plus(twoCloned);
  985. out.collection()->push_back(firstPerm);
  986. Node secondPerm = two.clone(ctx);
  987. Node oneCloned = one.clone(ctx);
  988. secondPerm.plus(oneCloned );
  989. out.collection()->push_back(secondPerm);
  990. }
  991. return out;
  992. }
  993. */
  994. /*
  995. This is the equivalent of ruby's Sequence.weave.
  996. The following is the modified version of the ruby code that was more portable to C++. You
  997. should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
  998. def weave(path)
  999. # This function works by moving through the selector path left-to-right,
  1000. # building all possible prefixes simultaneously. These prefixes are
  1001. # `befores`, while the remaining parenthesized suffixes is `afters`.
  1002. befores = [[]]
  1003. afters = path.dup
  1004. until afters.empty?
  1005. current = afters.shift.dup
  1006. last_current = [current.pop]
  1007. tempResult = []
  1008. for before in befores do
  1009. sub = subweave(before, current)
  1010. if sub.nil?
  1011. next
  1012. end
  1013. for seqs in sub do
  1014. tempResult.push(seqs + last_current)
  1015. end
  1016. end
  1017. befores = tempResult
  1018. end
  1019. return befores
  1020. end
  1021. */
  1022. /*
  1023. def weave(path)
  1024. befores = [[]]
  1025. afters = path.dup
  1026. until afters.empty?
  1027. current = afters.shift.dup
  1028. last_current = [current.pop]
  1029. tempResult = []
  1030. for before in befores do
  1031. sub = subweave(before, current)
  1032. if sub.nil?
  1033. next []
  1034. end
  1035. for seqs in sub do
  1036. toPush = seqs + last_current
  1037. tempResult.push(seqs + last_current)
  1038. end
  1039. end
  1040. befores = tempResult
  1041. end
  1042. return befores
  1043. end
  1044. */
  1045. static Node weave(Node& path, Context& ctx) {
  1046. DEBUG_PRINTLN(WEAVE, "WEAVE: " << path)
  1047. Node befores = Node::createCollection();
  1048. befores.collection()->push_back(Node::createCollection());
  1049. Node afters = Node::createCollection();
  1050. afters.plus(path);
  1051. while (!afters.collection()->empty()) {
  1052. Node current = afters.collection()->front().clone(ctx);
  1053. afters.collection()->pop_front();
  1054. DEBUG_PRINTLN(WEAVE, "CURRENT: " << current)
  1055. Node last_current = Node::createCollection();
  1056. last_current.collection()->push_back(current.collection()->back());
  1057. current.collection()->pop_back();
  1058. DEBUG_PRINTLN(WEAVE, "CURRENT POST POP: " << current)
  1059. DEBUG_PRINTLN(WEAVE, "LAST CURRENT: " << last_current)
  1060. Node tempResult = Node::createCollection();
  1061. for (NodeDeque::iterator beforesIter = befores.collection()->begin(), beforesEndIter = befores.collection()->end(); beforesIter != beforesEndIter; beforesIter++) {
  1062. Node& before = *beforesIter;
  1063. Node sub = subweave(before, current, ctx);
  1064. DEBUG_PRINTLN(WEAVE, "SUB: " << sub)
  1065. if (sub.isNil()) {
  1066. return Node::createCollection();
  1067. }
  1068. for (NodeDeque::iterator subIter = sub.collection()->begin(), subEndIter = sub.collection()->end(); subIter != subEndIter; subIter++) {
  1069. Node& seqs = *subIter;
  1070. Node toPush = Node::createCollection();
  1071. toPush.plus(seqs);
  1072. toPush.plus(last_current);
  1073. tempResult.collection()->push_back(toPush);
  1074. }
  1075. }
  1076. befores = tempResult;
  1077. }
  1078. return befores;
  1079. }
  1080. // This forward declaration is needed since extendComplexSelector calls extendCompoundSelector, which may recursively
  1081. // call extendComplexSelector again.
  1082. static Node extendComplexSelector(
  1083. Complex_Selector* pComplexSelector,
  1084. Context& ctx,
  1085. ExtensionSubsetMap& subsetMap,
  1086. set<Compound_Selector> seen);
  1087. /*
  1088. This is the equivalent of ruby's SimpleSequence.do_extend.
  1089. // TODO: I think I have some modified ruby code to put here. Check.
  1090. */
  1091. /*
  1092. ISSUES:
  1093. - Previous TODO: Do we need to group the results by extender?
  1094. - What does subject do in?: next unless unified = seq.members.last.unify(self_without_sel, subject?)
  1095. - IMPROVEMENT: The search for uniqueness at the end is not ideal since it's has to loop over everything...
  1096. - IMPROVEMENT: Check if the final search for uniqueness is doing anything that extendComplexSelector isn't already doing...
  1097. */
  1098. template<typename KeyType>
  1099. class GroupByToAFunctor {
  1100. public:
  1101. KeyType operator()(ExtensionPair& extPair) const {
  1102. Complex_Selector* pSelector = extPair.first;
  1103. return *pSelector;
  1104. }
  1105. };
  1106. static Node extendCompoundSelector(
  1107. Compound_Selector* pSelector,
  1108. Context& ctx,
  1109. ExtensionSubsetMap& subsetMap,
  1110. set<Compound_Selector> seen) {
  1111. DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
  1112. Node extendedSelectors = Node::createCollection();
  1113. To_String to_string;
  1114. SubsetMapEntries entries = subsetMap.get_v(pSelector->to_str_vec());
  1115. typedef vector<pair<Complex_Selector, vector<ExtensionPair> > > GroupedByToAResult;
  1116. GroupByToAFunctor<Complex_Selector> extPairKeyFunctor;
  1117. GroupedByToAResult arr;
  1118. group_by_to_a(entries, extPairKeyFunctor, arr);
  1119. typedef pair<Compound_Selector*, Complex_Selector*> SelsNewSeqPair;
  1120. typedef vector<SelsNewSeqPair> SelsNewSeqPairCollection;
  1121. SelsNewSeqPairCollection holder;
  1122. for (GroupedByToAResult::iterator groupedIter = arr.begin(), groupedIterEnd = arr.end(); groupedIter != groupedIterEnd; groupedIter++) {
  1123. pair<Complex_Selector, vector<ExtensionPair> >& groupedPair = *groupedIter;
  1124. Complex_Selector& seq = groupedPair.first;
  1125. vector<ExtensionPair>& group = groupedPair.second;
  1126. // DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(&seq, "SEQ: "))
  1127. Compound_Selector* pSels = new (ctx.mem) Compound_Selector(pSelector->path(), pSelector->position());
  1128. for (vector<ExtensionPair>::iterator groupIter = group.begin(), groupIterEnd = group.end(); groupIter != groupIterEnd; groupIter++) {
  1129. ExtensionPair& pair = *groupIter;
  1130. Compound_Selector* pCompound = pair.second;
  1131. for (size_t index = 0; index < pCompound->length(); index++) {
  1132. Simple_Selector* pSimpleSelector = (*pCompound)[index];
  1133. (*pSels) << pSimpleSelector;
  1134. }
  1135. }
  1136. // DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSels, "SELS: "))
  1137. Complex_Selector* pExtComplexSelector = &seq; // The selector up to where the @extend is (ie, the thing to merge)
  1138. Compound_Selector* pExtCompoundSelector = pSels; // All the simple selectors to be replaced from the current compound selector from all extensions
  1139. // TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL?
  1140. Compound_Selector* pSelectorWithoutExtendSelectors = pSelector->minus(pExtCompoundSelector, ctx);
  1141. // DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
  1142. // DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: "))
  1143. Compound_Selector* pInnermostCompoundSelector = pExtComplexSelector->base();
  1144. Compound_Selector* pUnifiedSelector = NULL;
  1145. if (!pInnermostCompoundSelector) {
  1146. pInnermostCompoundSelector = new (ctx.mem) Compound_Selector(pSelector->path(), pSelector->position());
  1147. }
  1148. pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors, ctx);
  1149. // DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pInnermostCompoundSelector, "LHS: "))
  1150. // DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "RHS: "))
  1151. // DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pUnifiedSelector, "UNIFIED: "))
  1152. if (!pUnifiedSelector || pUnifiedSelector->length() == 0) {
  1153. continue;
  1154. }
  1155. // TODO: implement the parent directive match (if necessary based on test failures)
  1156. // next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
  1157. // TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we should be able to just
  1158. // get rid of the last Compound_Selector and replace it with this one. I think the reason this code is more
  1159. // complex is that Complex_Selector contains a combinator, but in ruby combinators have already been filtered
  1160. // out and aren't operated on.
  1161. Complex_Selector* pNewSelector = pExtComplexSelector->cloneFully(ctx);
  1162. Complex_Selector* pNewInnerMost = new (ctx.mem) Complex_Selector(pSelector->path(), pSelector->position(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
  1163. Complex_Selector::Combinator combinator = pNewSelector->clear_innermost();
  1164. pNewSelector->set_innermost(pNewInnerMost, combinator);
  1165. #ifdef DEBUG
  1166. SourcesSet debugSet;
  1167. debugSet = pNewSelector->sources();
  1168. if (debugSet.size() > 0) {
  1169. throw "The new selector should start with no sources. Something needs to be cloned to fix this.";
  1170. }
  1171. debugSet = pExtComplexSelector->sources();
  1172. if (debugSet.size() > 0) {
  1173. throw "The extension selector from our subset map should not have sources. These will bleed to the new selector. Something needs to be cloned to fix this.";
  1174. }
  1175. #endif
  1176. // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending.
  1177. DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector, ctx))
  1178. DEBUG_EXEC(EXTEND_COMPOUND, SourcesSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, ctx, "SOURCES NEW SEQ BEGIN: "))
  1179. SourcesSet newSourcesSet = pSelector->sources();
  1180. DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, ctx, "SOURCES THIS EXTEND: "))
  1181. newSourcesSet.insert(pExtComplexSelector);
  1182. DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, ctx, "SOURCES WITH NEW SOURCE: "))
  1183. pNewSelector->addSources(newSourcesSet, ctx);
  1184. DEBUG_EXEC(EXTEND_COMPOUND, SourcesSet newSet = pNewSelector->sources(); printSourcesSet(newSet, ctx, "SOURCES ON NEW SELECTOR AFTER ADD: "))
  1185. DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(pSelector->sources(), ctx, "SOURCES THIS EXTEND WHICH SHOULD BE SAME STILL: "))
  1186. holder.push_back(make_pair(pSels, pNewSelector));
  1187. }
  1188. for (SelsNewSeqPairCollection::iterator holderIter = holder.begin(), holderIterEnd = holder.end(); holderIter != holderIterEnd; holderIter++) {
  1189. SelsNewSeqPair& pair = *holderIter;
  1190. Compound_Selector* pSels = pair.first;
  1191. Complex_Selector* pNewSelector = pair.second;
  1192. if (seen.find(*pSels) != seen.end()) {
  1193. continue;
  1194. }
  1195. set<Compound_Selector> recurseSeen(seen);
  1196. recurseSeen.insert(*pSels);
  1197. DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND: " << complexSelectorToNode(pNewSelector, ctx))
  1198. Node recurseExtendedSelectors = extendComplexSelector(pNewSelector, ctx, subsetMap, recurseSeen);
  1199. DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND RETURN: " << recurseExtendedSelectors)
  1200. for (NodeDeque::iterator iterator = recurseExtendedSelectors.collection()->begin(), endIterator = recurseExtendedSelectors.collection()->end();
  1201. iterator != endIterator; ++iterator) {
  1202. Node& newSelector = *iterator;
  1203. // DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " << extendedSelectors)
  1204. // DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " << extendedSelectors.contains(newSelector, false /*simpleSelectorOrderDependent*/));
  1205. if (!extendedSelectors.contains(newSelector, false /*simpleSelectorOrderDependent*/)) {
  1206. // DEBUG_PRINTLN(EXTEND_COMPOUND, "ADDING NEW SELECTOR")
  1207. extendedSelectors.collection()->push_back(newSelector);
  1208. }
  1209. }
  1210. }
  1211. DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND END: "))
  1212. return extendedSelectors;
  1213. }
  1214. static bool complexSelectorHasExtension(
  1215. Complex_Selector* pComplexSelector,
  1216. Context& ctx,
  1217. ExtensionSubsetMap& subsetMap) {
  1218. bool hasExtension = false;
  1219. Complex_Selector* pIter = pComplexSelector;
  1220. while (!hasExtension && pIter) {
  1221. Compound_Selector* pHead = pIter->head();
  1222. if (pHead) {
  1223. SubsetMapEntries entries = subsetMap.get_v(pHead->to_str_vec());
  1224. hasExtension = entries.size() > 0;
  1225. }
  1226. pIter = pIter->tail();
  1227. }
  1228. return hasExtension;
  1229. }
  1230. /*
  1231. This is the equivalent of ruby's Sequence.do_extend.
  1232. // TODO: I think I have some modified ruby code to put here. Check.
  1233. */
  1234. /*
  1235. ISSUES:
  1236. - check to automatically include combinators doesn't transfer over to libsass' data model where
  1237. the combinator and compound selector are one unit
  1238. next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
  1239. */
  1240. static Node extendComplexSelector(
  1241. Complex_Selector* pComplexSelector,
  1242. Context& ctx,
  1243. ExtensionSubsetMap& subsetMap,
  1244. set<Compound_Selector> seen) {
  1245. Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
  1246. DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
  1247. Node extendedNotExpanded = Node::createCollection();
  1248. for (NodeDeque::iterator complexSelIter = complexSelector.collection()->begin(), complexSelIterEnd = complexSelector.collection()->end(); complexSelIter != complexSelIterEnd; ++complexSelIter) {
  1249. Node& sseqOrOp = *complexSelIter;
  1250. DEBUG_PRINTLN(EXTEND_COMPLEX, "LOOP: " << sseqOrOp)
  1251. // If it's not a selector (meaning it's a combinator), just include it automatically
  1252. if (!sseqOrOp.isSelector()) {
  1253. // Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node
  1254. // with one collection child. The collection child represents a Complex_Selector that is only a combinator.
  1255. Node outer = Node::createCollection();
  1256. Node inner = Node::createCollection();
  1257. outer.collection()->push_back(inner);
  1258. inner.collection()->push_back(sseqOrOp);
  1259. extendedNotExpanded.collection()->push_back(outer);
  1260. continue;
  1261. }
  1262. Compound_Selector* pCompoundSelector = sseqOrOp.selector()->head();
  1263. Node extended = extendCompoundSelector(pCompoundSelector, ctx, subsetMap, seen);
  1264. DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
  1265. // Prepend the Compound_Selector based on the choices logic; choices seems to be extend but with an ruby Array instead of a Sequence
  1266. // due to the member mapping: choices = extended.map {|seq| seq.members}
  1267. Complex_Selector* pJustCurrentCompoundSelector = sseqOrOp.selector();
  1268. bool isSuperselector = false;
  1269. for (NodeDeque::iterator iterator = extended.collection()->begin(), endIterator = extended.collection()->end();
  1270. iterator != endIterator; ++iterator) {
  1271. Node& childNode = *iterator;
  1272. Complex_Selector* pExtensionSelector = nodeToComplexSelector(childNode, ctx);
  1273. if (pExtensionSelector->is_superselector_of(pJustCurrentCompoundSelector)) {
  1274. isSuperselector = true;
  1275. break;
  1276. }
  1277. }
  1278. if (!isSuperselector) {
  1279. extended.collection()->push_front(complexSelectorToNode(pJustCurrentCompoundSelector, ctx));
  1280. }
  1281. DEBUG_PRINTLN(EXTEND_COMPLEX, "CHOICES UNSHIFTED: " << extended)
  1282. // Aggregate our current extensions
  1283. extendedNotExpanded.collection()->push_back(extended);
  1284. }
  1285. DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED NOT EXPANDED: " << extendedNotExpanded)
  1286. // Ruby Equivalent: paths
  1287. Node paths = Sass::paths(extendedNotExpanded, ctx);
  1288. DEBUG_PRINTLN(EXTEND_COMPLEX, "PATHS: " << paths)
  1289. // Ruby Equivalent: weave
  1290. Node weaves = Node::createCollection();
  1291. for (NodeDeque::iterator pathsIter = paths.collection()->begin(), pathsEndIter = paths.collection()->end(); pathsIter != pathsEndIter; ++pathsIter) {
  1292. Node& path = *pathsIter;
  1293. Node weaved = weave(path, ctx);
  1294. weaves.collection()->push_back(weaved);
  1295. }
  1296. DEBUG_PRINTLN(EXTEND_COMPLEX, "WEAVES: " << weaves)
  1297. // Ruby Equivalent: trim
  1298. Node trimmed = trim(weaves, ctx);
  1299. DEBUG_PRINTLN(EXTEND_COMPLEX, "TRIMMED: " << trimmed)
  1300. // Ruby Equivalent: flatten
  1301. Node extendedSelectors = flatten(trimmed, ctx, 1);
  1302. DEBUG_PRINTLN(EXTEND_COMPLEX, ">>>>> EXTENDED: " << extendedSelectors)
  1303. DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX END: " << complexSelector)
  1304. return extendedSelectors;
  1305. }
  1306. /*
  1307. This is the equivalent of ruby's CommaSequence.do_extend.
  1308. */
  1309. static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool& extendedSomething) {
  1310. To_String to_string;
  1311. Selector_List* pNewSelectors = new (ctx.mem) Selector_List(pSelectorList->path(), pSelectorList->position(), pSelectorList->length());
  1312. extendedSomething = false;
  1313. for (size_t index = 0, length = pSelectorList->length(); index < length; index++) {
  1314. Complex_Selector* pSelector = (*pSelectorList)[index];
  1315. // ruby sass seems to keep a list of things that have extensions and then only extend those. We don't currently do that.
  1316. // Since it's not that expensive to check if an extension exists in the subset map and since it can be relatively expensive to
  1317. // run through the extend code (which does a data model transformation), check if there is anything to extend before doing
  1318. // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
  1319. // when debugging).
  1320. if (!complexSelectorHasExtension(pSelector, ctx, subsetMap)) {
  1321. *pNewSelectors << pSelector;
  1322. continue;
  1323. }
  1324. extendedSomething = true;
  1325. set<Compound_Selector> seen;
  1326. Node extendedSelectors = extendComplexSelector(pSelector, ctx, subsetMap, seen);
  1327. if (!pSelector->has_placeholder()) {
  1328. if (!extendedSelectors.contains(complexSelectorToNode(pSelector, ctx), true /*simpleSelectorOrderDependent*/)) {
  1329. *pNewSelectors << pSelector;
  1330. }
  1331. }
  1332. for (NodeDeque::iterator iterator = extendedSelectors.collection()->begin(), iteratorEnd = extendedSelectors.collection()->end(); iterator != iteratorEnd; ++iterator) {
  1333. Node& childNode = *iterator;
  1334. *pNewSelectors << nodeToComplexSelector(childNode, ctx);
  1335. }
  1336. }
  1337. return pNewSelectors;
  1338. }
  1339. bool shouldExtendBlock(Block* b) {
  1340. // If a block is empty, there's no reason to extend it since any rules placed on this block
  1341. // won't have any output. The main benefit of this is for structures like:
  1342. //
  1343. // .a {
  1344. // .b {
  1345. // x: y;
  1346. // }
  1347. // }
  1348. //
  1349. // We end up visiting two rulesets (one with the selector .a and the other with the selector .a .b).
  1350. // In this case, we don't want to try to pull rules onto .a since they won't get output anyway since
  1351. // there are no child statements. However .a .b should have extensions applied.
  1352. for (size_t i = 0, L = b->length(); i < L; ++i) {
  1353. Statement* stm = (*b)[i];
  1354. if (typeid(*stm) == typeid(Ruleset)) {
  1355. // Do nothing. This doesn't count as a statement that causes extension since we'll iterate over this rule set in a future visit and try to extend it.
  1356. }
  1357. else {
  1358. return true;
  1359. }
  1360. }
  1361. return false;
  1362. }
  1363. // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
  1364. template <typename ObjectType>
  1365. static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, ExtensionSubsetMap& subsetMap) {
  1366. To_String to_string;
  1367. DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->perform(&to_string))
  1368. // Ruby sass seems to filter nodes that don't have any content well before we get here. I'm not sure the repercussions
  1369. // of doing so, so for now, let's just not extend things that won't be output later.
  1370. if (!shouldExtendBlock(pObject->block())) {
  1371. DEBUG_PRINTLN(EXTEND_OBJECT, "RETURNING WITHOUT EXTEND ATTEMPT")
  1372. return;
  1373. }
  1374. bool extendedSomething = false;
  1375. Selector_List* pNewSelectorList = extendSelectorList(static_cast<Selector_List*>(pObject->selector()), ctx, subsetMap, extendedSomething);
  1376. if (extendedSomething && pNewSelectorList) {
  1377. DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->perform(&to_string))
  1378. DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->perform(&to_string))
  1379. // re-parse in order to restructure expanded placeholder nodes correctly.
  1380. //
  1381. // TODO: I don't know if this is needed, but it was in the original C++ implementation, so I kept it. Try running the tests without re-parsing.
  1382. pObject->selector(
  1383. Parser::from_c_str(
  1384. (pNewSelectorList->perform(&to_string) + ";").c_str(),
  1385. ctx,
  1386. pNewSelectorList->path(),
  1387. pNewSelectorList->position()
  1388. ).parse_selector_group()
  1389. );
  1390. } else {
  1391. DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND DID NOT TRY TO EXTEND ANYTHING")
  1392. }
  1393. }
  1394. Extend::Extend(Context& ctx, ExtensionSubsetMap& ssm)
  1395. : ctx(ctx), subset_map(ssm)
  1396. { }
  1397. void Extend::operator()(Block* b)
  1398. {
  1399. for (size_t i = 0, L = b->length(); i < L; ++i) {
  1400. (*b)[i]->perform(this);
  1401. }
  1402. }
  1403. void Extend::operator()(Ruleset* pRuleset)
  1404. {
  1405. extendObjectWithSelectorAndBlock(pRuleset, ctx, subset_map);
  1406. pRuleset->block()->perform(this);
  1407. }
  1408. void Extend::operator()(Feature_Block* pFeatureBlock)
  1409. {
  1410. if (pFeatureBlock->selector()) {
  1411. extendObjectWithSelectorAndBlock(pFeatureBlock, ctx, subset_map);
  1412. }
  1413. pFeatureBlock->block()->perform(this);
  1414. }
  1415. void Extend::operator()(Media_Block* pMediaBlock)
  1416. {
  1417. if (pMediaBlock->selector()) {
  1418. extendObjectWithSelectorAndBlock(pMediaBlock, ctx, subset_map);
  1419. }
  1420. pMediaBlock->block()->perform(this);
  1421. }
  1422. void Extend::operator()(At_Rule* a)
  1423. {
  1424. if (a->block()) a->block()->perform(this);
  1425. }
  1426. }