sassc 2.0.1 → 2.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +7 -3
  5. data/CHANGELOG.md +3 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +23 -8
  9. data/ext/extconf.rb +39 -0
  10. data/ext/libsass/.gitignore +1 -0
  11. data/ext/libsass/GNUmakefile.am +23 -39
  12. data/ext/libsass/Makefile +56 -91
  13. data/ext/libsass/Makefile.conf +16 -2
  14. data/ext/libsass/configure.ac +8 -12
  15. data/ext/libsass/include/sass/base.h +1 -0
  16. data/ext/libsass/include/sass/context.h +1 -1
  17. data/ext/libsass/src/GNUmakefile.am +1 -5
  18. data/ext/libsass/src/ast.cpp +747 -2010
  19. data/ext/libsass/src/ast.hpp +239 -2383
  20. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  21. data/ext/libsass/src/ast2c.hpp +39 -0
  22. data/ext/libsass/src/ast_def_macros.hpp +62 -10
  23. data/ext/libsass/src/ast_fwd_decl.cpp +1 -0
  24. data/ext/libsass/src/ast_fwd_decl.hpp +43 -165
  25. data/ext/libsass/src/ast_sel_cmp.cpp +909 -0
  26. data/ext/libsass/src/ast_sel_unify.cpp +280 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1475 -0
  28. data/ext/libsass/src/ast_selectors.hpp +568 -0
  29. data/ext/libsass/src/ast_supports.cpp +130 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +967 -0
  32. data/ext/libsass/src/ast_values.hpp +489 -0
  33. data/ext/libsass/src/backtrace.cpp +4 -0
  34. data/ext/libsass/src/base64vlq.cpp +3 -0
  35. data/ext/libsass/src/bind.cpp +18 -17
  36. data/ext/libsass/src/bind.hpp +3 -1
  37. data/ext/libsass/src/c2ast.cpp +64 -0
  38. data/ext/libsass/src/c2ast.hpp +14 -0
  39. data/ext/libsass/src/cencode.c +2 -2
  40. data/ext/libsass/src/check_nesting.cpp +52 -56
  41. data/ext/libsass/src/check_nesting.hpp +35 -34
  42. data/ext/libsass/src/color_maps.cpp +156 -153
  43. data/ext/libsass/src/color_maps.hpp +152 -152
  44. data/ext/libsass/src/constants.cpp +15 -0
  45. data/ext/libsass/src/constants.hpp +13 -0
  46. data/ext/libsass/src/context.cpp +24 -14
  47. data/ext/libsass/src/context.hpp +6 -6
  48. data/ext/libsass/src/cssize.cpp +69 -71
  49. data/ext/libsass/src/cssize.hpp +50 -50
  50. data/ext/libsass/src/debugger.hpp +117 -110
  51. data/ext/libsass/src/emitter.cpp +13 -12
  52. data/ext/libsass/src/emitter.hpp +13 -9
  53. data/ext/libsass/src/environment.cpp +15 -1
  54. data/ext/libsass/src/environment.hpp +6 -0
  55. data/ext/libsass/src/error_handling.cpp +36 -59
  56. data/ext/libsass/src/error_handling.hpp +29 -16
  57. data/ext/libsass/src/eval.cpp +302 -323
  58. data/ext/libsass/src/eval.hpp +64 -55
  59. data/ext/libsass/src/expand.cpp +94 -88
  60. data/ext/libsass/src/expand.hpp +33 -37
  61. data/ext/libsass/src/extend.cpp +38 -36
  62. data/ext/libsass/src/extend.hpp +15 -15
  63. data/ext/libsass/src/file.cpp +34 -2
  64. data/ext/libsass/src/fn_colors.cpp +594 -0
  65. data/ext/libsass/src/fn_colors.hpp +85 -0
  66. data/ext/libsass/src/fn_lists.cpp +284 -0
  67. data/ext/libsass/src/fn_lists.hpp +34 -0
  68. data/ext/libsass/src/fn_maps.cpp +94 -0
  69. data/ext/libsass/src/fn_maps.hpp +30 -0
  70. data/ext/libsass/src/fn_miscs.cpp +256 -0
  71. data/ext/libsass/src/fn_miscs.hpp +40 -0
  72. data/ext/libsass/src/fn_numbers.cpp +220 -0
  73. data/ext/libsass/src/fn_numbers.hpp +45 -0
  74. data/ext/libsass/src/fn_selectors.cpp +235 -0
  75. data/ext/libsass/src/fn_selectors.hpp +35 -0
  76. data/ext/libsass/src/fn_strings.cpp +254 -0
  77. data/ext/libsass/src/fn_strings.hpp +34 -0
  78. data/ext/libsass/src/fn_utils.cpp +156 -0
  79. data/ext/libsass/src/fn_utils.hpp +56 -0
  80. data/ext/libsass/src/inspect.cpp +101 -152
  81. data/ext/libsass/src/inspect.hpp +69 -73
  82. data/ext/libsass/src/json.cpp +2 -2
  83. data/ext/libsass/src/lexer.cpp +6 -3
  84. data/ext/libsass/src/listize.cpp +9 -11
  85. data/ext/libsass/src/listize.hpp +11 -7
  86. data/ext/libsass/src/memory/SharedPtr.cpp +2 -83
  87. data/ext/libsass/src/memory/SharedPtr.hpp +127 -143
  88. data/ext/libsass/src/node.cpp +13 -10
  89. data/ext/libsass/src/node.hpp +3 -3
  90. data/ext/libsass/src/operation.hpp +184 -144
  91. data/ext/libsass/src/operators.cpp +43 -17
  92. data/ext/libsass/src/operators.hpp +5 -5
  93. data/ext/libsass/src/output.cpp +21 -18
  94. data/ext/libsass/src/output.hpp +14 -21
  95. data/ext/libsass/src/parser.cpp +215 -183
  96. data/ext/libsass/src/parser.hpp +28 -24
  97. data/ext/libsass/src/plugins.cpp +5 -1
  98. data/ext/libsass/src/position.cpp +3 -0
  99. data/ext/libsass/src/prelexer.cpp +9 -3
  100. data/ext/libsass/src/prelexer.hpp +9 -9
  101. data/ext/libsass/src/remove_placeholders.cpp +14 -11
  102. data/ext/libsass/src/remove_placeholders.hpp +8 -9
  103. data/ext/libsass/src/sass.cpp +9 -3
  104. data/ext/libsass/src/sass.hpp +12 -9
  105. data/ext/libsass/src/sass2scss.cpp +45 -14
  106. data/ext/libsass/src/sass_context.cpp +18 -15
  107. data/ext/libsass/src/sass_functions.cpp +6 -3
  108. data/ext/libsass/src/sass_functions.hpp +1 -1
  109. data/ext/libsass/src/sass_util.cpp +3 -0
  110. data/ext/libsass/src/sass_values.cpp +21 -13
  111. data/ext/libsass/src/source_map.cpp +5 -2
  112. data/ext/libsass/src/source_map.hpp +2 -2
  113. data/ext/libsass/src/subset_map.cpp +4 -1
  114. data/ext/libsass/src/to_value.cpp +23 -21
  115. data/ext/libsass/src/to_value.hpp +18 -22
  116. data/ext/libsass/src/units.cpp +4 -0
  117. data/ext/libsass/src/units.hpp +1 -0
  118. data/ext/libsass/src/utf8/checked.h +12 -10
  119. data/ext/libsass/src/utf8/core.h +3 -0
  120. data/ext/libsass/src/utf8_string.cpp +3 -0
  121. data/ext/libsass/src/util.cpp +67 -75
  122. data/ext/libsass/src/util.hpp +64 -19
  123. data/ext/libsass/src/util_string.cpp +75 -0
  124. data/ext/libsass/src/util_string.hpp +19 -0
  125. data/ext/libsass/src/values.cpp +22 -13
  126. data/ext/libsass/src/values.hpp +2 -2
  127. data/ext/libsass/win/libsass.targets +30 -4
  128. data/ext/libsass/win/libsass.vcxproj.filters +82 -4
  129. data/lib/sassc.rb +24 -0
  130. data/lib/sassc/engine.rb +2 -2
  131. data/lib/sassc/native.rb +8 -1
  132. data/lib/sassc/version.rb +1 -1
  133. data/sassc.gemspec +19 -11
  134. data/test/engine_test.rb +26 -1
  135. data/test/native_test.rb +1 -1
  136. metadata +66 -72
  137. data/ext/Rakefile +0 -3
  138. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  139. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  140. data/ext/libsass/.travis.yml +0 -64
  141. data/ext/libsass/Readme.md +0 -104
  142. data/ext/libsass/SECURITY.md +0 -10
  143. data/ext/libsass/appveyor.yml +0 -91
  144. data/ext/libsass/docs/README.md +0 -20
  145. data/ext/libsass/docs/api-context-example.md +0 -45
  146. data/ext/libsass/docs/api-context-internal.md +0 -163
  147. data/ext/libsass/docs/api-context.md +0 -295
  148. data/ext/libsass/docs/api-doc.md +0 -215
  149. data/ext/libsass/docs/api-function-example.md +0 -67
  150. data/ext/libsass/docs/api-function-internal.md +0 -8
  151. data/ext/libsass/docs/api-function.md +0 -74
  152. data/ext/libsass/docs/api-importer-example.md +0 -112
  153. data/ext/libsass/docs/api-importer-internal.md +0 -20
  154. data/ext/libsass/docs/api-importer.md +0 -86
  155. data/ext/libsass/docs/api-value-example.md +0 -55
  156. data/ext/libsass/docs/api-value-internal.md +0 -76
  157. data/ext/libsass/docs/api-value.md +0 -154
  158. data/ext/libsass/docs/build-on-darwin.md +0 -27
  159. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  160. data/ext/libsass/docs/build-on-windows.md +0 -139
  161. data/ext/libsass/docs/build-shared-library.md +0 -35
  162. data/ext/libsass/docs/build-with-autotools.md +0 -78
  163. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  164. data/ext/libsass/docs/build-with-mingw.md +0 -107
  165. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  166. data/ext/libsass/docs/build.md +0 -97
  167. data/ext/libsass/docs/compatibility-plan.md +0 -48
  168. data/ext/libsass/docs/contributing.md +0 -17
  169. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  170. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  171. data/ext/libsass/docs/implementations.md +0 -56
  172. data/ext/libsass/docs/plugins.md +0 -47
  173. data/ext/libsass/docs/setup-environment.md +0 -68
  174. data/ext/libsass/docs/source-map-internals.md +0 -51
  175. data/ext/libsass/docs/trace.md +0 -26
  176. data/ext/libsass/docs/triage.md +0 -17
  177. data/ext/libsass/docs/unicode.md +0 -39
  178. data/ext/libsass/extconf.rb +0 -6
  179. data/ext/libsass/script/bootstrap +0 -13
  180. data/ext/libsass/script/branding +0 -10
  181. data/ext/libsass/script/ci-build-libsass +0 -134
  182. data/ext/libsass/script/ci-build-plugin +0 -62
  183. data/ext/libsass/script/ci-install-compiler +0 -6
  184. data/ext/libsass/script/ci-install-deps +0 -20
  185. data/ext/libsass/script/ci-report-coverage +0 -42
  186. data/ext/libsass/script/spec +0 -5
  187. data/ext/libsass/script/tap-driver +0 -652
  188. data/ext/libsass/script/tap-runner +0 -1
  189. data/ext/libsass/script/test-leaks.pl +0 -103
  190. data/ext/libsass/src/functions.cpp +0 -2234
  191. data/ext/libsass/src/functions.hpp +0 -198
  192. data/ext/libsass/src/to_c.hpp +0 -39
  193. data/ext/libsass/test/test_node.cpp +0 -94
  194. data/ext/libsass/test/test_paths.cpp +0 -28
  195. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  196. data/ext/libsass/test/test_specificity.cpp +0 -25
  197. data/ext/libsass/test/test_subset_map.cpp +0 -472
  198. data/ext/libsass/test/test_superselector.cpp +0 -69
  199. data/ext/libsass/test/test_unification.cpp +0 -31
  200. data/lib/tasks/libsass.rb +0 -33
@@ -0,0 +1,280 @@
1
+ #include "sass.hpp"
2
+ #include "ast.hpp"
3
+ #include "context.hpp"
4
+ #include "node.hpp"
5
+ #include "eval.hpp"
6
+ #include "extend.hpp"
7
+ #include "emitter.hpp"
8
+ #include "color_maps.hpp"
9
+ #include "ast_fwd_decl.hpp"
10
+ #include <set>
11
+ #include <iomanip>
12
+ #include <iostream>
13
+ #include <algorithm>
14
+ #include <functional>
15
+ #include <cctype>
16
+ #include <locale>
17
+
18
+ #include "ast_selectors.hpp"
19
+
20
+ // #define DEBUG_UNIFY
21
+
22
+ namespace Sass {
23
+
24
+ Compound_Selector* Compound_Selector::unify_with(Compound_Selector* rhs)
25
+ {
26
+ #ifdef DEBUG_UNIFY
27
+ const std::string debug_call = "unify(Compound[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
28
+ std::cerr << debug_call << std::endl;
29
+ #endif
30
+
31
+ if (empty()) return rhs;
32
+ Compound_Selector_Obj unified = SASS_MEMORY_COPY(rhs);
33
+ for (const Simple_Selector_Obj& sel : elements()) {
34
+ unified = sel->unify_with(unified);
35
+ if (unified.isNull()) break;
36
+ }
37
+
38
+ #ifdef DEBUG_UNIFY
39
+ std::cerr << "> " << debug_call << " = Compound[" << unified->to_string() << "]" << std::endl;
40
+ #endif
41
+ return unified.detach();
42
+ }
43
+
44
+ Compound_Selector* Simple_Selector::unify_with(Compound_Selector* rhs)
45
+ {
46
+ #ifdef DEBUG_UNIFY
47
+ const std::string debug_call = "unify(Simple[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
48
+ std::cerr << debug_call << std::endl;
49
+ #endif
50
+
51
+ if (rhs->length() == 1) {
52
+ if (rhs->at(0)->is_universal()) {
53
+ Compound_Selector* this_compound = SASS_MEMORY_NEW(Compound_Selector, pstate(), 1);
54
+ this_compound->append(SASS_MEMORY_COPY(this));
55
+ Compound_Selector* unified = rhs->at(0)->unify_with(this_compound);
56
+ if (unified == nullptr || unified != this_compound) delete this_compound;
57
+
58
+ #ifdef DEBUG_UNIFY
59
+ std::cerr << "> " << debug_call << " = " << "Compound[" << unified->to_string() << "]" << std::endl;
60
+ #endif
61
+ return unified;
62
+ }
63
+ }
64
+ for (const Simple_Selector_Obj& sel : rhs->elements()) {
65
+ if (*this == *sel) {
66
+ #ifdef DEBUG_UNIFY
67
+ std::cerr << "> " << debug_call << " = " << "Compound[" << rhs->to_string() << "]" << std::endl;
68
+ #endif
69
+ return rhs;
70
+ }
71
+ }
72
+ const int lhs_order = this->unification_order();
73
+ size_t i = rhs->length();
74
+ while (i > 0 && lhs_order < rhs->at(i - 1)->unification_order()) --i;
75
+ rhs->insert(rhs->begin() + i, this);
76
+ #ifdef DEBUG_UNIFY
77
+ std::cerr << "> " << debug_call << " = " << "Compound[" << rhs->to_string() << "]" << std::endl;
78
+ #endif
79
+ return rhs;
80
+ }
81
+
82
+ Simple_Selector* Type_Selector::unify_with(Simple_Selector* rhs)
83
+ {
84
+ #ifdef DEBUG_UNIFY
85
+ const std::string debug_call = "unify(Type[" + this->to_string() + "], Simple[" + rhs->to_string() + "])";
86
+ std::cerr << debug_call << std::endl;
87
+ #endif
88
+
89
+ bool rhs_ns = false;
90
+ if (!(is_ns_eq(*rhs) || rhs->is_universal_ns())) {
91
+ if (!is_universal_ns()) {
92
+ #ifdef DEBUG_UNIFY
93
+ std::cerr << "> " << debug_call << " = nullptr" << std::endl;
94
+ #endif
95
+ return nullptr;
96
+ }
97
+ rhs_ns = true;
98
+ }
99
+ bool rhs_name = false;
100
+ if (!(name_ == rhs->name() || rhs->is_universal())) {
101
+ if (!(is_universal())) {
102
+ #ifdef DEBUG_UNIFY
103
+ std::cerr << "> " << debug_call << " = nullptr" << std::endl;
104
+ #endif
105
+ return nullptr;
106
+ }
107
+ rhs_name = true;
108
+ }
109
+ if (rhs_ns) {
110
+ ns(rhs->ns());
111
+ has_ns(rhs->has_ns());
112
+ }
113
+ if (rhs_name) name(rhs->name());
114
+ #ifdef DEBUG_UNIFY
115
+ std::cerr << "> " << debug_call << " = Simple[" << this->to_string() << "]" << std::endl;
116
+ #endif
117
+ return this;
118
+ }
119
+
120
+ Compound_Selector* Type_Selector::unify_with(Compound_Selector* rhs)
121
+ {
122
+ #ifdef DEBUG_UNIFY
123
+ const std::string debug_call = "unify(Type[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
124
+ std::cerr << debug_call << std::endl;
125
+ #endif
126
+
127
+ if (rhs->empty()) {
128
+ rhs->append(this);
129
+ #ifdef DEBUG_UNIFY
130
+ std::cerr << "> " << debug_call << " = Compound[" << rhs->to_string() << "]" << std::endl;
131
+ #endif
132
+ return rhs;
133
+ }
134
+ Type_Selector* rhs_0 = Cast<Type_Selector>(rhs->at(0));
135
+ if (rhs_0 != nullptr) {
136
+ Simple_Selector* unified = unify_with(rhs_0);
137
+ if (unified == nullptr) {
138
+ #ifdef DEBUG_UNIFY
139
+ std::cerr << "> " << debug_call << " = nullptr" << std::endl;
140
+ #endif
141
+ return nullptr;
142
+ }
143
+ rhs->elements()[0] = unified;
144
+ } else if (!is_universal() || (has_ns_ && ns_ != "*")) {
145
+ rhs->insert(rhs->begin(), this);
146
+ }
147
+ #ifdef DEBUG_UNIFY
148
+ std::cerr << "> " << debug_call << " = Compound[" << rhs->to_string() << "]" << std::endl;
149
+ #endif
150
+ return rhs;
151
+ }
152
+
153
+ Compound_Selector* Class_Selector::unify_with(Compound_Selector* rhs)
154
+ {
155
+ rhs->has_line_break(has_line_break());
156
+ return Simple_Selector::unify_with(rhs);
157
+ }
158
+
159
+ Compound_Selector* Id_Selector::unify_with(Compound_Selector* rhs)
160
+ {
161
+ for (const Simple_Selector_Obj& sel : rhs->elements()) {
162
+ if (Id_Selector* id_sel = Cast<Id_Selector>(sel)) {
163
+ if (id_sel->name() != name()) return nullptr;
164
+ }
165
+ }
166
+ rhs->has_line_break(has_line_break());
167
+ return Simple_Selector::unify_with(rhs);
168
+ }
169
+
170
+ Compound_Selector* Pseudo_Selector::unify_with(Compound_Selector* rhs)
171
+ {
172
+ if (is_pseudo_element()) {
173
+ for (const Simple_Selector_Obj& sel : rhs->elements()) {
174
+ if (Pseudo_Selector* pseudo_sel = Cast<Pseudo_Selector>(sel)) {
175
+ if (pseudo_sel->is_pseudo_element() && pseudo_sel->name() != name()) return nullptr;
176
+ }
177
+ }
178
+ }
179
+ return Simple_Selector::unify_with(rhs);
180
+ }
181
+
182
+ Selector_List* Complex_Selector::unify_with(Complex_Selector* rhs)
183
+ {
184
+ #ifdef DEBUG_UNIFY
185
+ const std::string debug_call = "unify(Complex[" + this->to_string() + "], Complex[" + rhs->to_string() + "])";
186
+ std::cerr << debug_call << std::endl;
187
+ #endif
188
+
189
+ // get last tails (on the right side)
190
+ Complex_Selector* l_last = this->mutable_last();
191
+ Complex_Selector* r_last = rhs->mutable_last();
192
+
193
+ // check valid pointers (assertion)
194
+ SASS_ASSERT(l_last, "lhs is null");
195
+ SASS_ASSERT(r_last, "rhs is null");
196
+
197
+ // Not sure about this check, but closest way I could check
198
+ // was to see if this is a ruby 'SimpleSequence' equivalent.
199
+ // It seems to do the job correctly as some specs react to this
200
+ if (l_last->combinator() != Combinator::ANCESTOR_OF) return nullptr;
201
+ if (r_last->combinator() != Combinator::ANCESTOR_OF) return nullptr;
202
+
203
+ // get the headers for the last tails
204
+ Compound_Selector* l_last_head = l_last->head();
205
+ Compound_Selector* r_last_head = r_last->head();
206
+
207
+ // check valid head pointers (assertion)
208
+ SASS_ASSERT(l_last_head, "lhs head is null");
209
+ SASS_ASSERT(r_last_head, "rhs head is null");
210
+
211
+ // get the unification of the last compound selectors
212
+ Compound_Selector_Obj unified = r_last_head->unify_with(l_last_head);
213
+
214
+ // abort if we could not unify heads
215
+ if (unified == nullptr) return nullptr;
216
+
217
+ // move the head
218
+ if (l_last_head->is_universal()) l_last->head({});
219
+ r_last->head(unified);
220
+
221
+ #ifdef DEBUG_UNIFY
222
+ std::cerr << "> " << debug_call << " before weave: lhs=" << this->to_string() << " rhs=" << rhs->to_string() << std::endl;
223
+ #endif
224
+
225
+ // create nodes from both selectors
226
+ Node lhsNode = complexSelectorToNode(this);
227
+ Node rhsNode = complexSelectorToNode(rhs);
228
+
229
+ // Complex_Selector_Obj fake = unified->to_complex();
230
+ // Node unified_node = complexSelectorToNode(fake);
231
+ // // add to permutate the list?
232
+ // rhsNode.plus(unified_node);
233
+
234
+ // do some magic we inherit from node and extend
235
+ Node node = subweave(lhsNode, rhsNode);
236
+ Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate(), node.collection()->size());
237
+ for (auto &item : *node.collection()) {
238
+ result->append(nodeToComplexSelector(Node::naiveTrim(item)));
239
+ }
240
+
241
+ #ifdef DEBUG_UNIFY
242
+ std::cerr << "> " << debug_call << " = " << result->to_string() << std::endl;
243
+ #endif
244
+
245
+ // only return if list has some entries
246
+ return result->length() ? result.detach() : nullptr;
247
+ }
248
+
249
+ Selector_List* Selector_List::unify_with(Selector_List* rhs) {
250
+ #ifdef DEBUG_UNIFY
251
+ const std::string debug_call = "unify(List[" + this->to_string() + "], List[" + rhs->to_string() + "])";
252
+ std::cerr << debug_call << std::endl;
253
+ #endif
254
+
255
+ std::vector<Complex_Selector_Obj> result;
256
+ // Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
257
+ for (Complex_Selector_Obj& seq1 : elements()) {
258
+ for (Complex_Selector_Obj& seq2 : rhs->elements()) {
259
+ Complex_Selector_Obj seq1_copy = SASS_MEMORY_CLONE(seq1);
260
+ Complex_Selector_Obj seq2_copy = SASS_MEMORY_CLONE(seq2);
261
+ Selector_List_Obj unified = seq1_copy->unify_with(seq2_copy);
262
+ if (unified) {
263
+ result.reserve(result.size() + unified->length());
264
+ std::copy(unified->begin(), unified->end(), std::back_inserter(result));
265
+ }
266
+ }
267
+ }
268
+
269
+ // Creates the final Selector_List by combining all the complex selectors
270
+ Selector_List* final_result = SASS_MEMORY_NEW(Selector_List, pstate(), result.size());
271
+ for (Complex_Selector_Obj& sel : result) {
272
+ final_result->append(sel);
273
+ }
274
+ #ifdef DEBUG_UNIFY
275
+ std::cerr << "> " << debug_call << " = " << final_result->to_string() << std::endl;
276
+ #endif
277
+ return final_result;
278
+ }
279
+
280
+ }
@@ -0,0 +1,1475 @@
1
+ #include "sass.hpp"
2
+ #include "ast.hpp"
3
+ #include "context.hpp"
4
+ #include "node.hpp"
5
+ #include "eval.hpp"
6
+ #include "extend.hpp"
7
+ #include "emitter.hpp"
8
+ #include "color_maps.hpp"
9
+ #include "ast_fwd_decl.hpp"
10
+ #include "ast_selectors.hpp"
11
+ #include <array>
12
+ #include <set>
13
+ #include <iomanip>
14
+ #include <iostream>
15
+ #include <algorithm>
16
+ #include <functional>
17
+ #include <cctype>
18
+ #include <locale>
19
+
20
+ namespace Sass {
21
+
22
+ /////////////////////////////////////////////////////////////////////////
23
+ /////////////////////////////////////////////////////////////////////////
24
+
25
+ Selector::Selector(ParserState pstate)
26
+ : Expression(pstate),
27
+ has_line_feed_(false),
28
+ has_line_break_(false),
29
+ is_optional_(false),
30
+ media_block_(0),
31
+ hash_(0)
32
+ { concrete_type(SELECTOR); }
33
+
34
+ Selector::Selector(const Selector* ptr)
35
+ : Expression(ptr),
36
+ has_line_feed_(ptr->has_line_feed_),
37
+ has_line_break_(ptr->has_line_break_),
38
+ is_optional_(ptr->is_optional_),
39
+ media_block_(ptr->media_block_),
40
+ hash_(ptr->hash_)
41
+ { concrete_type(SELECTOR); }
42
+
43
+ void Selector::set_media_block(Media_Block* mb)
44
+ {
45
+ media_block(mb);
46
+ }
47
+
48
+ bool Selector::has_parent_ref() const
49
+ {
50
+ return false;
51
+ }
52
+
53
+ bool Selector::has_real_parent_ref() const
54
+ {
55
+ return false;
56
+ }
57
+
58
+ /////////////////////////////////////////////////////////////////////////
59
+ /////////////////////////////////////////////////////////////////////////
60
+
61
+ Selector_Schema::Selector_Schema(ParserState pstate, String_Obj c)
62
+ : AST_Node(pstate),
63
+ contents_(c),
64
+ connect_parent_(true),
65
+ media_block_(NULL),
66
+ hash_(0)
67
+ { }
68
+ Selector_Schema::Selector_Schema(const Selector_Schema* ptr)
69
+ : AST_Node(ptr),
70
+ contents_(ptr->contents_),
71
+ connect_parent_(ptr->connect_parent_),
72
+ media_block_(ptr->media_block_),
73
+ hash_(ptr->hash_)
74
+ { }
75
+
76
+ unsigned long Selector_Schema::specificity() const
77
+ {
78
+ return 0;
79
+ }
80
+
81
+ size_t Selector_Schema::hash() const {
82
+ if (hash_ == 0) {
83
+ hash_combine(hash_, contents_->hash());
84
+ }
85
+ return hash_;
86
+ }
87
+
88
+ bool Selector_Schema::has_parent_ref() const
89
+ {
90
+ if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
91
+ if (schema->empty()) return false;
92
+ const auto& first = *schema->at(0);
93
+ return typeid(first) == typeid(Parent_Selector);
94
+ }
95
+ return false;
96
+ }
97
+
98
+ bool Selector_Schema::has_real_parent_ref() const
99
+ {
100
+ if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
101
+ if (schema->empty()) return false;
102
+ const auto& first = *schema->at(0);
103
+ return typeid(first) == typeid(Parent_Reference);
104
+ }
105
+ return false;
106
+ }
107
+
108
+ /////////////////////////////////////////////////////////////////////////
109
+ /////////////////////////////////////////////////////////////////////////
110
+
111
+ Simple_Selector::Simple_Selector(ParserState pstate, std::string n)
112
+ : Selector(pstate), ns_(""), name_(n), has_ns_(false)
113
+ {
114
+ size_t pos = n.find('|');
115
+ // found some namespace
116
+ if (pos != std::string::npos) {
117
+ has_ns_ = true;
118
+ ns_ = n.substr(0, pos);
119
+ name_ = n.substr(pos + 1);
120
+ }
121
+ }
122
+ Simple_Selector::Simple_Selector(const Simple_Selector* ptr)
123
+ : Selector(ptr),
124
+ ns_(ptr->ns_),
125
+ name_(ptr->name_),
126
+ has_ns_(ptr->has_ns_)
127
+ { }
128
+
129
+ std::string Simple_Selector::ns_name() const
130
+ {
131
+ std::string name("");
132
+ if (has_ns_)
133
+ name += ns_ + "|";
134
+ return name + name_;
135
+ }
136
+
137
+ size_t Simple_Selector::hash() const
138
+ {
139
+ if (hash_ == 0) {
140
+ hash_combine(hash_, std::hash<int>()(SELECTOR));
141
+ hash_combine(hash_, std::hash<int>()(simple_type()));
142
+ if (!name_.empty()) hash_combine(hash_, std::hash<std::string>()(name()));
143
+ if (has_ns_) hash_combine(hash_, std::hash<std::string>()(ns()));
144
+ }
145
+ return hash_;
146
+ }
147
+
148
+ bool Simple_Selector::empty() const {
149
+ return ns().empty() && name().empty();
150
+ }
151
+
152
+ // namespace compare functions
153
+ bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const
154
+ {
155
+ return has_ns_ == r.has_ns_ && ns_ == r.ns_;
156
+ }
157
+
158
+ // namespace query functions
159
+ bool Simple_Selector::is_universal_ns() const
160
+ {
161
+ return has_ns_ && ns_ == "*";
162
+ }
163
+
164
+ bool Simple_Selector::is_empty_ns() const
165
+ {
166
+ return !has_ns_ || ns_ == "";
167
+ }
168
+
169
+ bool Simple_Selector::has_empty_ns() const
170
+ {
171
+ return has_ns_ && ns_ == "";
172
+ }
173
+
174
+ bool Simple_Selector::has_qualified_ns() const
175
+ {
176
+ return has_ns_ && ns_ != "" && ns_ != "*";
177
+ }
178
+
179
+ // name query functions
180
+ bool Simple_Selector::is_universal() const
181
+ {
182
+ return name_ == "*";
183
+ }
184
+
185
+ bool Simple_Selector::has_placeholder()
186
+ {
187
+ return false;
188
+ }
189
+
190
+ bool Simple_Selector::has_parent_ref() const
191
+ {
192
+ return false;
193
+ };
194
+
195
+ bool Simple_Selector::has_real_parent_ref() const
196
+ {
197
+ return false;
198
+ };
199
+
200
+ bool Simple_Selector::is_pseudo_element() const
201
+ {
202
+ return false;
203
+ }
204
+
205
+ bool Simple_Selector::is_superselector_of(const Compound_Selector* sub) const
206
+ {
207
+ return false;
208
+ }
209
+
210
+ /////////////////////////////////////////////////////////////////////////
211
+ /////////////////////////////////////////////////////////////////////////
212
+
213
+ Parent_Selector::Parent_Selector(ParserState pstate, bool r)
214
+ : Simple_Selector(pstate, "&"), real_(r)
215
+ { simple_type(PARENT_SEL); }
216
+ Parent_Selector::Parent_Selector(const Parent_Selector* ptr)
217
+ : Simple_Selector(ptr), real_(ptr->real_)
218
+ { simple_type(PARENT_SEL); }
219
+
220
+ bool Parent_Selector::has_parent_ref() const
221
+ {
222
+ return true;
223
+ };
224
+
225
+ bool Parent_Selector::has_real_parent_ref() const
226
+ {
227
+ return real();
228
+ };
229
+
230
+ unsigned long Parent_Selector::specificity() const
231
+ {
232
+ return 0;
233
+ }
234
+
235
+ /////////////////////////////////////////////////////////////////////////
236
+ /////////////////////////////////////////////////////////////////////////
237
+
238
+ Placeholder_Selector::Placeholder_Selector(ParserState pstate, std::string n)
239
+ : Simple_Selector(pstate, n)
240
+ { simple_type(PLACEHOLDER_SEL); }
241
+ Placeholder_Selector::Placeholder_Selector(const Placeholder_Selector* ptr)
242
+ : Simple_Selector(ptr)
243
+ { simple_type(PLACEHOLDER_SEL); }
244
+ unsigned long Placeholder_Selector::specificity() const
245
+ {
246
+ return Constants::Specificity_Base;
247
+ }
248
+ bool Placeholder_Selector::has_placeholder() {
249
+ return true;
250
+ }
251
+
252
+ /////////////////////////////////////////////////////////////////////////
253
+ /////////////////////////////////////////////////////////////////////////
254
+
255
+ Type_Selector::Type_Selector(ParserState pstate, std::string n)
256
+ : Simple_Selector(pstate, n)
257
+ { simple_type(TYPE_SEL); }
258
+ Type_Selector::Type_Selector(const Type_Selector* ptr)
259
+ : Simple_Selector(ptr)
260
+ { simple_type(TYPE_SEL); }
261
+
262
+ unsigned long Type_Selector::specificity() const
263
+ {
264
+ if (name() == "*") return 0;
265
+ else return Constants::Specificity_Element;
266
+ }
267
+
268
+ /////////////////////////////////////////////////////////////////////////
269
+ /////////////////////////////////////////////////////////////////////////
270
+
271
+ Class_Selector::Class_Selector(ParserState pstate, std::string n)
272
+ : Simple_Selector(pstate, n)
273
+ { simple_type(CLASS_SEL); }
274
+ Class_Selector::Class_Selector(const Class_Selector* ptr)
275
+ : Simple_Selector(ptr)
276
+ { simple_type(CLASS_SEL); }
277
+
278
+ unsigned long Class_Selector::specificity() const
279
+ {
280
+ return Constants::Specificity_Class;
281
+ }
282
+
283
+ /////////////////////////////////////////////////////////////////////////
284
+ /////////////////////////////////////////////////////////////////////////
285
+
286
+ Id_Selector::Id_Selector(ParserState pstate, std::string n)
287
+ : Simple_Selector(pstate, n)
288
+ { simple_type(ID_SEL); }
289
+ Id_Selector::Id_Selector(const Id_Selector* ptr)
290
+ : Simple_Selector(ptr)
291
+ { simple_type(ID_SEL); }
292
+
293
+ unsigned long Id_Selector::specificity() const
294
+ {
295
+ return Constants::Specificity_ID;
296
+ }
297
+
298
+ /////////////////////////////////////////////////////////////////////////
299
+ /////////////////////////////////////////////////////////////////////////
300
+
301
+ Attribute_Selector::Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o)
302
+ : Simple_Selector(pstate, n), matcher_(m), value_(v), modifier_(o)
303
+ { simple_type(ATTRIBUTE_SEL); }
304
+ Attribute_Selector::Attribute_Selector(const Attribute_Selector* ptr)
305
+ : Simple_Selector(ptr),
306
+ matcher_(ptr->matcher_),
307
+ value_(ptr->value_),
308
+ modifier_(ptr->modifier_)
309
+ { simple_type(ATTRIBUTE_SEL); }
310
+
311
+ size_t Attribute_Selector::hash() const
312
+ {
313
+ if (hash_ == 0) {
314
+ hash_combine(hash_, Simple_Selector::hash());
315
+ hash_combine(hash_, std::hash<std::string>()(matcher()));
316
+ if (value_) hash_combine(hash_, value_->hash());
317
+ }
318
+ return hash_;
319
+ }
320
+
321
+ unsigned long Attribute_Selector::specificity() const
322
+ {
323
+ return Constants::Specificity_Attr;
324
+ }
325
+
326
+ /////////////////////////////////////////////////////////////////////////
327
+ /////////////////////////////////////////////////////////////////////////
328
+
329
+ Pseudo_Selector::Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr)
330
+ : Simple_Selector(pstate, n), expression_(expr)
331
+ { simple_type(PSEUDO_SEL); }
332
+ Pseudo_Selector::Pseudo_Selector(const Pseudo_Selector* ptr)
333
+ : Simple_Selector(ptr), expression_(ptr->expression_)
334
+ { simple_type(PSEUDO_SEL); }
335
+
336
+ // A pseudo-element is made of two colons (::) followed by the name.
337
+ // The `::` notation is introduced by the current document in order to
338
+ // establish a discrimination between pseudo-classes and pseudo-elements.
339
+ // For compatibility with existing style sheets, user agents must also
340
+ // accept the previous one-colon notation for pseudo-elements introduced
341
+ // in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
342
+ // :after). This compatibility is not allowed for the new pseudo-elements
343
+ // introduced in this specification.
344
+ bool Pseudo_Selector::is_pseudo_element() const
345
+ {
346
+ return (name_[0] == ':' && name_[1] == ':')
347
+ || is_pseudo_class_element(name_);
348
+ }
349
+
350
+ size_t Pseudo_Selector::hash() const
351
+ {
352
+ if (hash_ == 0) {
353
+ hash_combine(hash_, Simple_Selector::hash());
354
+ if (expression_) hash_combine(hash_, expression_->hash());
355
+ }
356
+ return hash_;
357
+ }
358
+
359
+ unsigned long Pseudo_Selector::specificity() const
360
+ {
361
+ if (is_pseudo_element())
362
+ return Constants::Specificity_Element;
363
+ return Constants::Specificity_Pseudo;
364
+ }
365
+
366
+ /////////////////////////////////////////////////////////////////////////
367
+ /////////////////////////////////////////////////////////////////////////
368
+
369
+ Wrapped_Selector::Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel)
370
+ : Simple_Selector(pstate, n), selector_(sel)
371
+ { simple_type(WRAPPED_SEL); }
372
+ Wrapped_Selector::Wrapped_Selector(const Wrapped_Selector* ptr)
373
+ : Simple_Selector(ptr), selector_(ptr->selector_)
374
+ { simple_type(WRAPPED_SEL); }
375
+
376
+ bool Wrapped_Selector::is_superselector_of(const Wrapped_Selector* sub) const
377
+ {
378
+ if (this->name() != sub->name()) return false;
379
+ if (this->name() == ":current") return false;
380
+ if (Selector_List_Obj rhs_list = Cast<Selector_List>(sub->selector())) {
381
+ if (Selector_List_Obj lhs_list = Cast<Selector_List>(selector())) {
382
+ return lhs_list->is_superselector_of(rhs_list);
383
+ }
384
+ }
385
+ coreError("is_superselector expected a Selector_List", sub->pstate());
386
+ return false;
387
+ }
388
+
389
+ // Selectors inside the negation pseudo-class are counted like any
390
+ // other, but the negation itself does not count as a pseudo-class.
391
+
392
+ void Wrapped_Selector::cloneChildren()
393
+ {
394
+ selector(SASS_MEMORY_CLONE(selector()));
395
+ }
396
+
397
+ size_t Wrapped_Selector::hash() const
398
+ {
399
+ if (hash_ == 0) {
400
+ hash_combine(hash_, Simple_Selector::hash());
401
+ if (selector_) hash_combine(hash_, selector_->hash());
402
+ }
403
+ return hash_;
404
+ }
405
+
406
+ bool Wrapped_Selector::has_parent_ref() const {
407
+ if (!selector()) return false;
408
+ return selector()->has_parent_ref();
409
+ }
410
+
411
+ bool Wrapped_Selector::has_real_parent_ref() const {
412
+ if (!selector()) return false;
413
+ return selector()->has_real_parent_ref();
414
+ }
415
+
416
+ unsigned long Wrapped_Selector::specificity() const
417
+ {
418
+ return selector_ ? selector_->specificity() : 0;
419
+ }
420
+
421
+ bool Wrapped_Selector::find ( bool (*f)(AST_Node_Obj) )
422
+ {
423
+ // check children first
424
+ if (selector_) {
425
+ if (selector_->find(f)) return true;
426
+ }
427
+ // execute last
428
+ return f(this);
429
+ }
430
+
431
+ /////////////////////////////////////////////////////////////////////////
432
+ /////////////////////////////////////////////////////////////////////////
433
+
434
+ Compound_Selector::Compound_Selector(ParserState pstate, size_t s)
435
+ : Selector(pstate),
436
+ Vectorized<Simple_Selector_Obj>(s),
437
+ extended_(false),
438
+ has_parent_reference_(false)
439
+ { }
440
+
441
+ Compound_Selector::Compound_Selector(const Compound_Selector* ptr)
442
+ : Selector(ptr),
443
+ Vectorized<Simple_Selector_Obj>(*ptr),
444
+ extended_(ptr->extended_),
445
+ has_parent_reference_(ptr->has_parent_reference_)
446
+ { }
447
+
448
+ bool Compound_Selector::contains_placeholder() {
449
+ for (size_t i = 0, L = length(); i < L; ++i) {
450
+ if ((*this)[i]->has_placeholder()) return true;
451
+ }
452
+ return false;
453
+ };
454
+
455
+ void Compound_Selector::cloneChildren()
456
+ {
457
+ for (size_t i = 0, l = length(); i < l; i++) {
458
+ at(i) = SASS_MEMORY_CLONE(at(i));
459
+ }
460
+ }
461
+
462
+ bool Compound_Selector::find ( bool (*f)(AST_Node_Obj) )
463
+ {
464
+ // check children first
465
+ for (Simple_Selector_Obj sel : elements()) {
466
+ if (sel->find(f)) return true;
467
+ }
468
+ // execute last
469
+ return f(this);
470
+ }
471
+
472
+ bool Compound_Selector::has_parent_ref() const
473
+ {
474
+ for (Simple_Selector_Obj s : *this) {
475
+ if (s && s->has_parent_ref()) return true;
476
+ }
477
+ return false;
478
+ }
479
+
480
+ bool Compound_Selector::has_real_parent_ref() const
481
+ {
482
+ for (Simple_Selector_Obj s : *this) {
483
+ if (s && s->has_real_parent_ref()) return true;
484
+ }
485
+ return false;
486
+ }
487
+
488
+ bool Compound_Selector::is_superselector_of(const Selector_List* rhs, std::string wrapped) const
489
+ {
490
+ for (Complex_Selector_Obj item : rhs->elements()) {
491
+ if (is_superselector_of(item, wrapped)) return true;
492
+ }
493
+ return false;
494
+ }
495
+
496
+ bool Compound_Selector::is_superselector_of(const Complex_Selector* rhs, std::string wrapped) const
497
+ {
498
+ if (rhs->head()) return is_superselector_of(rhs->head(), wrapped);
499
+ return false;
500
+ }
501
+
502
+ bool Compound_Selector::is_superselector_of(const Compound_Selector* rhs, std::string wrapping) const
503
+ {
504
+ // Check if pseudo-elements are the same between the selectors
505
+ {
506
+ std::array<std::set<std::string>, 2> pseudosets;
507
+ std::array<const Compound_Selector*, 2> compounds = {{this, rhs}};
508
+ for (int i = 0; i < 2; ++i) {
509
+ for (const Simple_Selector_Obj& el : compounds[i]->elements()) {
510
+ if (el->is_pseudo_element()) {
511
+ std::string pseudo(el->to_string());
512
+ // strip off colons to ensure :after matches ::after since ruby sass is forgiving
513
+ pseudosets[i].insert(pseudo.substr(pseudo.find_first_not_of(":")));
514
+ }
515
+ }
516
+ }
517
+ if (pseudosets[0] != pseudosets[1]) return false;
518
+ }
519
+
520
+ {
521
+ const Simple_Selector* lbase = this->base();
522
+ const Simple_Selector* rbase = rhs->base();
523
+ if (lbase && rbase) {
524
+ return *lbase == *rbase &&
525
+ contains_all(std::unordered_set<const Simple_Selector*, HashPtr, ComparePtrs>(rhs->begin(), rhs->end()),
526
+ std::unordered_set<const Simple_Selector*, HashPtr, ComparePtrs>(this->begin(), this->end()));
527
+ }
528
+ }
529
+
530
+ std::unordered_set<const Selector*, HashPtr, ComparePtrs> lset;
531
+ for (size_t i = 0, iL = length(); i < iL; ++i)
532
+ {
533
+ const Selector* wlhs = (*this)[i].ptr();
534
+ // very special case for wrapped matches selector
535
+ if (const Wrapped_Selector* wrapped = Cast<Wrapped_Selector>(wlhs)) {
536
+ if (wrapped->name() == ":not") {
537
+ if (Selector_List_Obj not_list = Cast<Selector_List>(wrapped->selector())) {
538
+ if (not_list->is_superselector_of(rhs, wrapped->name())) return false;
539
+ } else {
540
+ throw std::runtime_error("wrapped not selector is not a list");
541
+ }
542
+ }
543
+ if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
544
+ wlhs = wrapped->selector();
545
+ if (Selector_List_Obj list = Cast<Selector_List>(wrapped->selector())) {
546
+ if (const Compound_Selector* comp = Cast<Compound_Selector>(rhs)) {
547
+ if (!wrapping.empty() && wrapping != wrapped->name()) return false;
548
+ if (wrapping.empty() || wrapping != wrapped->name()) {;
549
+ if (list->is_superselector_of(comp, wrapped->name())) return true;
550
+ }
551
+ }
552
+ }
553
+ }
554
+ Simple_Selector* rhs_sel = nullptr;
555
+ if (rhs->elements().size() > i) rhs_sel = (*rhs)[i];
556
+ if (Wrapped_Selector* wrapped_r = Cast<Wrapped_Selector>(rhs_sel)) {
557
+ if (wrapped->name() == wrapped_r->name()) {
558
+ if (wrapped->is_superselector_of(wrapped_r)) {
559
+ continue;
560
+ }}
561
+ }
562
+ }
563
+ lset.insert(wlhs);
564
+ }
565
+
566
+ if (lset.empty()) return true;
567
+
568
+ std::unordered_set<const Selector*, HashPtr, ComparePtrs> rset;
569
+ for (size_t n = 0, nL = rhs->length(); n < nL; ++n)
570
+ {
571
+ Selector_Obj r = (*rhs)[n];
572
+ if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(r)) {
573
+ if (wrapped->name() == ":not") {
574
+ if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
575
+ ls->remove_parent_selectors(); // unverified
576
+ if (is_superselector_of(ls, wrapped->name())) return false;
577
+ }
578
+ }
579
+ if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
580
+ if (!wrapping.empty()) {
581
+ if (wrapping != wrapped->name()) return false;
582
+ }
583
+ if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
584
+ ls->remove_parent_selectors(); // unverified
585
+ return (is_superselector_of(ls, wrapped->name()));
586
+ }
587
+ }
588
+ }
589
+ rset.insert(r);
590
+ }
591
+
592
+ return contains_all(rset, lset);
593
+ }
594
+
595
+ bool Compound_Selector::is_universal() const
596
+ {
597
+ return length() == 1 && (*this)[0]->is_universal();
598
+ }
599
+
600
+ // create complex selector (ancestor of) from compound selector
601
+ Complex_Selector_Obj Compound_Selector::to_complex()
602
+ {
603
+ // create an intermediate complex selector
604
+ return SASS_MEMORY_NEW(Complex_Selector,
605
+ pstate(),
606
+ Complex_Selector::ANCESTOR_OF,
607
+ this,
608
+ {});
609
+ }
610
+
611
+ Simple_Selector* Compound_Selector::base() const {
612
+ if (length() == 0) return 0;
613
+ // ToDo: why is this needed?
614
+ if (Cast<Type_Selector>((*this)[0]))
615
+ return (*this)[0];
616
+ return 0;
617
+ }
618
+
619
+ size_t Compound_Selector::hash() const
620
+ {
621
+ if (Selector::hash_ == 0) {
622
+ hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
623
+ if (length()) hash_combine(Selector::hash_, Vectorized::hash());
624
+ }
625
+ return Selector::hash_;
626
+ }
627
+
628
+ unsigned long Compound_Selector::specificity() const
629
+ {
630
+ int sum = 0;
631
+ for (size_t i = 0, L = length(); i < L; ++i)
632
+ { sum += (*this)[i]->specificity(); }
633
+ return sum;
634
+ }
635
+
636
+ bool Compound_Selector::has_placeholder()
637
+ {
638
+ if (length() == 0) return false;
639
+ if (Simple_Selector_Obj ss = elements().front()) {
640
+ if (ss->has_placeholder()) return true;
641
+ }
642
+ return false;
643
+ }
644
+
645
+ bool Compound_Selector::is_empty_reference()
646
+ {
647
+ return length() == 1 &&
648
+ Cast<Parent_Selector>((*this)[0]);
649
+ }
650
+
651
+ void Compound_Selector::append(Simple_Selector_Obj element)
652
+ {
653
+ Vectorized<Simple_Selector_Obj>::append(element);
654
+ pstate_.offset += element->pstate().offset;
655
+ }
656
+
657
+ Compound_Selector* Compound_Selector::minus(Compound_Selector* rhs)
658
+ {
659
+ Compound_Selector* result = SASS_MEMORY_NEW(Compound_Selector, pstate());
660
+ // result->has_parent_reference(has_parent_reference());
661
+
662
+ // not very efficient because it needs to preserve order
663
+ for (size_t i = 0, L = length(); i < L; ++i)
664
+ {
665
+ bool found = false;
666
+ for (size_t j = 0, M = rhs->length(); j < M; ++j)
667
+ {
668
+ if (*get(i) == *rhs->get(j))
669
+ {
670
+ found = true;
671
+ break;
672
+ }
673
+ }
674
+ if (!found) result->append(get(i));
675
+ }
676
+
677
+ return result;
678
+ }
679
+
680
+ void Compound_Selector::mergeSources(ComplexSelectorSet& sources)
681
+ {
682
+ for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
683
+ this->sources_.insert(SASS_MEMORY_CLONE(*iterator));
684
+ }
685
+ }
686
+
687
+ /////////////////////////////////////////////////////////////////////////
688
+ /////////////////////////////////////////////////////////////////////////
689
+
690
+ Complex_Selector::Complex_Selector(ParserState pstate,
691
+ Combinator c,
692
+ Compound_Selector_Obj h,
693
+ Complex_Selector_Obj t,
694
+ String_Obj r)
695
+ : Selector(pstate),
696
+ combinator_(c),
697
+ head_(h), tail_(t),
698
+ reference_(r)
699
+ {}
700
+ Complex_Selector::Complex_Selector(const Complex_Selector* ptr)
701
+ : Selector(ptr),
702
+ combinator_(ptr->combinator_),
703
+ head_(ptr->head_), tail_(ptr->tail_),
704
+ reference_(ptr->reference_)
705
+ {}
706
+
707
+ bool Complex_Selector::empty() const {
708
+ return (!tail() || tail()->empty())
709
+ && (!head() || head()->empty())
710
+ && combinator_ == ANCESTOR_OF;
711
+ }
712
+
713
+ Complex_Selector_Obj Complex_Selector::skip_empty_reference()
714
+ {
715
+ if ((!head_ || !head_->length() || head_->is_empty_reference()) &&
716
+ combinator() == Combinator::ANCESTOR_OF)
717
+ {
718
+ if (!tail_) return {};
719
+ tail_->has_line_feed_ = this->has_line_feed_;
720
+ // tail_->has_line_break_ = this->has_line_break_;
721
+ return tail_->skip_empty_reference();
722
+ }
723
+ return this;
724
+ }
725
+
726
+ bool Complex_Selector::is_empty_ancestor() const
727
+ {
728
+ return (!head() || head()->length() == 0) &&
729
+ combinator() == Combinator::ANCESTOR_OF;
730
+ }
731
+
732
+ size_t Complex_Selector::hash() const
733
+ {
734
+ if (hash_ == 0) {
735
+ if (head_) {
736
+ hash_combine(hash_, head_->hash());
737
+ } else {
738
+ hash_combine(hash_, std::hash<int>()(SELECTOR));
739
+ }
740
+ if (tail_) hash_combine(hash_, tail_->hash());
741
+ if (combinator_ != ANCESTOR_OF) hash_combine(hash_, std::hash<int>()(combinator_));
742
+ }
743
+ return hash_;
744
+ }
745
+
746
+ unsigned long Complex_Selector::specificity() const
747
+ {
748
+ int sum = 0;
749
+ if (head()) sum += head()->specificity();
750
+ if (tail()) sum += tail()->specificity();
751
+ return sum;
752
+ }
753
+
754
+ void Complex_Selector::set_media_block(Media_Block* mb) {
755
+ media_block(mb);
756
+ if (tail_) tail_->set_media_block(mb);
757
+ if (head_) head_->set_media_block(mb);
758
+ }
759
+
760
+ bool Complex_Selector::has_placeholder() {
761
+ if (head_ && head_->has_placeholder()) return true;
762
+ if (tail_ && tail_->has_placeholder()) return true;
763
+ return false;
764
+ }
765
+
766
+ const ComplexSelectorSet Complex_Selector::sources()
767
+ {
768
+ //s = Set.new
769
+ //seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)}
770
+ //s
771
+
772
+ ComplexSelectorSet srcs;
773
+
774
+ Compound_Selector_Obj pHead = head();
775
+ Complex_Selector_Obj pTail = tail();
776
+
777
+ if (pHead) {
778
+ const ComplexSelectorSet& headSources = pHead->sources();
779
+ srcs.insert(headSources.begin(), headSources.end());
780
+ }
781
+
782
+ if (pTail) {
783
+ const ComplexSelectorSet& tailSources = pTail->sources();
784
+ srcs.insert(tailSources.begin(), tailSources.end());
785
+ }
786
+
787
+ return srcs;
788
+ }
789
+
790
+ void Complex_Selector::addSources(ComplexSelectorSet& sources)
791
+ {
792
+ // members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m}
793
+ Complex_Selector* pIter = this;
794
+ while (pIter) {
795
+ Compound_Selector* pHead = pIter->head();
796
+
797
+ if (pHead) {
798
+ pHead->mergeSources(sources);
799
+ }
800
+
801
+ pIter = pIter->tail();
802
+ }
803
+ }
804
+
805
+ void Complex_Selector::clearSources()
806
+ {
807
+ Complex_Selector* pIter = this;
808
+ while (pIter) {
809
+ Compound_Selector* pHead = pIter->head();
810
+
811
+ if (pHead) {
812
+ pHead->clearSources();
813
+ }
814
+
815
+ pIter = pIter->tail();
816
+ }
817
+ }
818
+
819
+ bool Complex_Selector::find ( bool (*f)(AST_Node_Obj) )
820
+ {
821
+ // check children first
822
+ if (head_ && head_->find(f)) return true;
823
+ if (tail_ && tail_->find(f)) return true;
824
+ // execute last
825
+ return f(this);
826
+ }
827
+
828
+ bool Complex_Selector::has_parent_ref() const
829
+ {
830
+ return (head() && head()->has_parent_ref()) ||
831
+ (tail() && tail()->has_parent_ref());
832
+ }
833
+
834
+ bool Complex_Selector::has_real_parent_ref() const
835
+ {
836
+ return (head() && head()->has_real_parent_ref()) ||
837
+ (tail() && tail()->has_real_parent_ref());
838
+ }
839
+
840
+ bool Complex_Selector::is_superselector_of(const Compound_Selector* rhs, std::string wrapping) const
841
+ {
842
+ return last()->head() && last()->head()->is_superselector_of(rhs, wrapping);
843
+ }
844
+
845
+ bool Complex_Selector::is_superselector_of(const Complex_Selector* rhs, std::string wrapping) const
846
+ {
847
+ const Complex_Selector* lhs = this;
848
+ // check for selectors with leading or trailing combinators
849
+ if (!lhs->head() || !rhs->head())
850
+ { return false; }
851
+ const Complex_Selector* l_innermost = lhs->last();
852
+ if (l_innermost->combinator() != Complex_Selector::ANCESTOR_OF)
853
+ { return false; }
854
+ const Complex_Selector* r_innermost = rhs->last();
855
+ if (r_innermost->combinator() != Complex_Selector::ANCESTOR_OF)
856
+ { return false; }
857
+ // more complex (i.e., longer) selectors are always more specific
858
+ size_t l_len = lhs->length(), r_len = rhs->length();
859
+ if (l_len > r_len)
860
+ { return false; }
861
+
862
+ if (l_len == 1)
863
+ { return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); }
864
+
865
+ // we have to look one tail deeper, since we cary the
866
+ // combinator around for it (which is important here)
867
+ if (rhs->tail() && lhs->tail() && combinator() != Complex_Selector::ANCESTOR_OF) {
868
+ Complex_Selector_Obj lhs_tail = lhs->tail();
869
+ Complex_Selector_Obj rhs_tail = rhs->tail();
870
+ if (lhs_tail->combinator() != rhs_tail->combinator()) return false;
871
+ if (lhs_tail->head() && !rhs_tail->head()) return false;
872
+ if (!lhs_tail->head() && rhs_tail->head()) return false;
873
+ if (lhs_tail->head() && rhs_tail->head()) {
874
+ if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false;
875
+ }
876
+ }
877
+
878
+ bool found = false;
879
+ const Complex_Selector* marker = rhs;
880
+ for (size_t i = 0, L = rhs->length(); i < L; ++i) {
881
+ if (i == L-1)
882
+ { return false; }
883
+ if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(marker->head(), wrapping))
884
+ { found = true; break; }
885
+ marker = marker->tail();
886
+ }
887
+ if (!found)
888
+ { return false; }
889
+
890
+ /*
891
+ Hmm, I hope I have the logic right:
892
+
893
+ if lhs has a combinator:
894
+ if !(marker has a combinator) return false
895
+ if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) return false
896
+ return lhs.tail-without-innermost.is_superselector_of(marker.tail-without-innermost)
897
+ else if marker has a combinator:
898
+ if !(marker.combinator == ">") return false
899
+ return lhs.tail.is_superselector_of(marker.tail)
900
+ else
901
+ return lhs.tail.is_superselector_of(marker.tail)
902
+ */
903
+ if (lhs->combinator() != Complex_Selector::ANCESTOR_OF)
904
+ {
905
+ if (marker->combinator() == Complex_Selector::ANCESTOR_OF)
906
+ { return false; }
907
+ if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator()))
908
+ { return false; }
909
+ return lhs->tail()->is_superselector_of(marker->tail());
910
+ }
911
+ else if (marker->combinator() != Complex_Selector::ANCESTOR_OF)
912
+ {
913
+ if (marker->combinator() != Complex_Selector::PARENT_OF)
914
+ { return false; }
915
+ return lhs->tail()->is_superselector_of(marker->tail());
916
+ }
917
+ return lhs->tail()->is_superselector_of(marker->tail());
918
+ }
919
+
920
+ size_t Complex_Selector::length() const
921
+ {
922
+ // TODO: make this iterative
923
+ if (!tail()) return 1;
924
+ return 1 + tail()->length();
925
+ }
926
+
927
+ // append another complex selector at the end
928
+ // check if we need to append some headers
929
+ // then we need to check for the combinator
930
+ // only then we can safely set the new tail
931
+ void Complex_Selector::append(Complex_Selector_Obj ss, Backtraces& traces)
932
+ {
933
+
934
+ Complex_Selector_Obj t = ss->tail();
935
+ Combinator c = ss->combinator();
936
+ String_Obj r = ss->reference();
937
+ Compound_Selector_Obj h = ss->head();
938
+
939
+ if (ss->has_line_feed()) has_line_feed(true);
940
+ if (ss->has_line_break()) has_line_break(true);
941
+
942
+ // append old headers
943
+ if (h && h->length()) {
944
+ if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
945
+ traces.push_back(Backtrace(pstate()));
946
+ throw Exception::InvalidParent(this, traces, ss);
947
+ } else if (last()->head_ && last()->head_->length()) {
948
+ Compound_Selector_Obj rh = last()->head();
949
+ size_t i;
950
+ size_t L = h->length();
951
+ if (Cast<Type_Selector>(h->first())) {
952
+ if (Class_Selector* cs = Cast<Class_Selector>(rh->last())) {
953
+ Class_Selector* sqs = SASS_MEMORY_COPY(cs);
954
+ sqs->name(sqs->name() + (*h)[0]->name());
955
+ sqs->pstate((*h)[0]->pstate());
956
+ (*rh)[rh->length()-1] = sqs;
957
+ rh->pstate(h->pstate());
958
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
959
+ } else if (Id_Selector* is = Cast<Id_Selector>(rh->last())) {
960
+ Id_Selector* sqs = SASS_MEMORY_COPY(is);
961
+ sqs->name(sqs->name() + (*h)[0]->name());
962
+ sqs->pstate((*h)[0]->pstate());
963
+ (*rh)[rh->length()-1] = sqs;
964
+ rh->pstate(h->pstate());
965
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
966
+ } else if (Type_Selector* ts = Cast<Type_Selector>(rh->last())) {
967
+ Type_Selector* tss = SASS_MEMORY_COPY(ts);
968
+ tss->name(tss->name() + (*h)[0]->name());
969
+ tss->pstate((*h)[0]->pstate());
970
+ (*rh)[rh->length()-1] = tss;
971
+ rh->pstate(h->pstate());
972
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
973
+ } else if (Placeholder_Selector* ps = Cast<Placeholder_Selector>(rh->last())) {
974
+ Placeholder_Selector* pss = SASS_MEMORY_COPY(ps);
975
+ pss->name(pss->name() + (*h)[0]->name());
976
+ pss->pstate((*h)[0]->pstate());
977
+ (*rh)[rh->length()-1] = pss;
978
+ rh->pstate(h->pstate());
979
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
980
+ } else {
981
+ last()->head_->concat(h);
982
+ }
983
+ } else {
984
+ last()->head_->concat(h);
985
+ }
986
+ } else if (last()->head_) {
987
+ last()->head_->concat(h);
988
+ }
989
+ } else {
990
+ // std::cerr << "has no or empty head\n";
991
+ }
992
+
993
+ Complex_Selector* last = mutable_last();
994
+ if (last) {
995
+ if (last->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
996
+ Complex_Selector* inter = SASS_MEMORY_NEW(Complex_Selector, pstate());
997
+ inter->reference(r);
998
+ inter->combinator(c);
999
+ inter->tail(t);
1000
+ last->tail(inter);
1001
+ } else {
1002
+ if (last->combinator() == ANCESTOR_OF) {
1003
+ last->combinator(c);
1004
+ last->reference(r);
1005
+ }
1006
+ last->tail(t);
1007
+ }
1008
+ }
1009
+
1010
+ }
1011
+
1012
+ Selector_List* Complex_Selector::resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent)
1013
+ {
1014
+ Complex_Selector_Obj tail = this->tail();
1015
+ Compound_Selector_Obj head = this->head();
1016
+ Selector_List* parents = pstack.back();
1017
+
1018
+ if (!this->has_real_parent_ref() && !implicit_parent) {
1019
+ Selector_List* retval = SASS_MEMORY_NEW(Selector_List, pstate(), 1);
1020
+ retval->append(this);
1021
+ return retval;
1022
+ }
1023
+
1024
+ // first resolve_parent_refs the tail (which may return an expanded list)
1025
+ Selector_List_Obj tails = tail ? tail->resolve_parent_refs(pstack, traces, implicit_parent) : 0;
1026
+
1027
+ if (head && head->length() > 0) {
1028
+
1029
+ Selector_List_Obj retval;
1030
+ // we have a parent selector in a simple compound list
1031
+ // mix parent complex selector into the compound list
1032
+ if (Cast<Parent_Selector>((*head)[0])) {
1033
+ retval = SASS_MEMORY_NEW(Selector_List, pstate());
1034
+
1035
+ // it turns out that real parent references reach
1036
+ // across @at-root rules, which comes unexpected
1037
+ if (parents == NULL && head->has_real_parent_ref()) {
1038
+ int i = pstack.size() - 1;
1039
+ while (!parents && i > -1) {
1040
+ parents = pstack.at(i--);
1041
+ }
1042
+ }
1043
+
1044
+ if (parents && parents->length()) {
1045
+ if (tails && tails->length() > 0) {
1046
+ for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
1047
+ for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
1048
+ Complex_Selector_Obj t = (*tails)[n];
1049
+ Complex_Selector_Obj parent = (*parents)[i];
1050
+ Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
1051
+ Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
1052
+ ss->tail(t ? SASS_MEMORY_CLONE(t) : NULL);
1053
+ Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
1054
+ // remove parent selector from sequence
1055
+ if (h->length()) {
1056
+ h->erase(h->begin());
1057
+ ss->head(h);
1058
+ } else {
1059
+ ss->head({});
1060
+ }
1061
+ // adjust for parent selector (1 char)
1062
+ // if (h->length()) {
1063
+ // ParserState state(h->at(0)->pstate());
1064
+ // state.offset.column += 1;
1065
+ // state.column -= 1;
1066
+ // (*h)[0]->pstate(state);
1067
+ // }
1068
+ // keep old parser state
1069
+ s->pstate(pstate());
1070
+ // append new tail
1071
+ s->append(ss, traces);
1072
+ retval->append(s);
1073
+ }
1074
+ }
1075
+ }
1076
+ // have no tails but parents
1077
+ // loop above is inside out
1078
+ else {
1079
+ for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
1080
+ Complex_Selector_Obj parent = (*parents)[i];
1081
+ Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
1082
+ Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
1083
+ // this is only if valid if the parent has no trailing op
1084
+ // otherwise we cannot append more simple selectors to head
1085
+ if (parent->last()->combinator() != ANCESTOR_OF) {
1086
+ traces.push_back(Backtrace(pstate()));
1087
+ throw Exception::InvalidParent(parent, traces, ss);
1088
+ }
1089
+ ss->tail(tail ? SASS_MEMORY_CLONE(tail) : NULL);
1090
+ Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
1091
+ // remove parent selector from sequence
1092
+ if (h->length()) {
1093
+ h->erase(h->begin());
1094
+ ss->head(h);
1095
+ } else {
1096
+ ss->head({});
1097
+ }
1098
+ // \/ IMO ruby sass bug \/
1099
+ ss->has_line_feed(false);
1100
+ // adjust for parent selector (1 char)
1101
+ // if (h->length()) {
1102
+ // ParserState state(h->at(0)->pstate());
1103
+ // state.offset.column += 1;
1104
+ // state.column -= 1;
1105
+ // (*h)[0]->pstate(state);
1106
+ // }
1107
+ // keep old parser state
1108
+ s->pstate(pstate());
1109
+ // append new tail
1110
+ s->append(ss, traces);
1111
+ retval->append(s);
1112
+ }
1113
+ }
1114
+ }
1115
+ // have no parent but some tails
1116
+ else {
1117
+ if (tails && tails->length() > 0) {
1118
+ for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
1119
+ Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
1120
+ cpy->tail(SASS_MEMORY_CLONE(tails->at(n)));
1121
+ cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
1122
+ for (size_t i = 1, L = this->head()->length(); i < L; ++i)
1123
+ cpy->head()->append((*this->head())[i]);
1124
+ if (!cpy->head()->length()) cpy->head({});
1125
+ retval->append(cpy->skip_empty_reference());
1126
+ }
1127
+ }
1128
+ // have no parent nor tails
1129
+ else {
1130
+ Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
1131
+ cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
1132
+ for (size_t i = 1, L = this->head()->length(); i < L; ++i)
1133
+ cpy->head()->append((*this->head())[i]);
1134
+ if (!cpy->head()->length()) cpy->head({});
1135
+ retval->append(cpy->skip_empty_reference());
1136
+ }
1137
+ }
1138
+ }
1139
+ // no parent selector in head
1140
+ else {
1141
+ retval = this->tails(tails);
1142
+ }
1143
+
1144
+ for (Simple_Selector_Obj ss : head->elements()) {
1145
+ if (Wrapped_Selector* ws = Cast<Wrapped_Selector>(ss)) {
1146
+ if (Selector_List* sl = Cast<Selector_List>(ws->selector())) {
1147
+ if (parents) ws->selector(sl->resolve_parent_refs(pstack, traces, implicit_parent));
1148
+ }
1149
+ }
1150
+ }
1151
+
1152
+ return retval.detach();
1153
+
1154
+ }
1155
+ // has no head
1156
+ return this->tails(tails);
1157
+ }
1158
+
1159
+ Selector_List* Complex_Selector::tails(Selector_List* tails)
1160
+ {
1161
+ Selector_List* rv = SASS_MEMORY_NEW(Selector_List, pstate_);
1162
+ if (tails && tails->length()) {
1163
+ for (size_t i = 0, iL = tails->length(); i < iL; ++i) {
1164
+ Complex_Selector_Obj pr = SASS_MEMORY_CLONE(this);
1165
+ pr->tail(tails->at(i));
1166
+ rv->append(pr);
1167
+ }
1168
+ }
1169
+ else {
1170
+ rv->append(this);
1171
+ }
1172
+ return rv;
1173
+ }
1174
+
1175
+ // return the last tail that is defined
1176
+ const Complex_Selector* Complex_Selector::first() const
1177
+ {
1178
+ // declare variables used in loop
1179
+ const Complex_Selector* cur = this;
1180
+ const Compound_Selector* head;
1181
+ // processing loop
1182
+ while (cur)
1183
+ {
1184
+ // get the head
1185
+ head = cur->head_.ptr();
1186
+ // abort (and return) if it is not a parent selector
1187
+ if (!head || head->length() != 1 || !Cast<Parent_Selector>((*head)[0])) {
1188
+ break;
1189
+ }
1190
+ // advance to next
1191
+ cur = cur->tail_;
1192
+ }
1193
+ // result
1194
+ return cur;
1195
+ }
1196
+
1197
+ Complex_Selector* Complex_Selector::mutable_first()
1198
+ {
1199
+ return const_cast<Complex_Selector*>(first());
1200
+ }
1201
+
1202
+ // return the last tail that is defined
1203
+ const Complex_Selector* Complex_Selector::last() const
1204
+ {
1205
+ const Complex_Selector* cur = this;
1206
+ const Complex_Selector* nxt = cur;
1207
+ // loop until last
1208
+ while (nxt) {
1209
+ cur = nxt;
1210
+ nxt = cur->tail_.ptr();
1211
+ }
1212
+ return cur;
1213
+ }
1214
+
1215
+ Complex_Selector* Complex_Selector::mutable_last()
1216
+ {
1217
+ return const_cast<Complex_Selector*>(last());
1218
+ }
1219
+
1220
+ Complex_Selector::Combinator Complex_Selector::clear_innermost()
1221
+ {
1222
+ Combinator c;
1223
+ if (!tail() || tail()->tail() == nullptr)
1224
+ { c = combinator(); combinator(ANCESTOR_OF); tail({}); }
1225
+ else
1226
+ { c = tail_->clear_innermost(); }
1227
+ return c;
1228
+ }
1229
+
1230
+ void Complex_Selector::set_innermost(Complex_Selector_Obj val, Combinator c)
1231
+ {
1232
+ if (!tail_)
1233
+ { tail_ = val; combinator(c); }
1234
+ else
1235
+ { tail_->set_innermost(val, c); }
1236
+ }
1237
+
1238
+ void Complex_Selector::cloneChildren()
1239
+ {
1240
+ if (head()) head(SASS_MEMORY_CLONE(head()));
1241
+ if (tail()) tail(SASS_MEMORY_CLONE(tail()));
1242
+ }
1243
+
1244
+ // it's a superselector if every selector of the right side
1245
+ // list is a superselector of the given left side selector
1246
+ bool Complex_Selector::is_superselector_of(const Selector_List* sub, std::string wrapping) const
1247
+ {
1248
+ // Check every rhs selector against left hand list
1249
+ for(size_t i = 0, L = sub->length(); i < L; ++i) {
1250
+ if (!is_superselector_of((*sub)[i], wrapping)) return false;
1251
+ }
1252
+ return true;
1253
+ }
1254
+
1255
+ /////////////////////////////////////////////////////////////////////////
1256
+ /////////////////////////////////////////////////////////////////////////
1257
+
1258
+ Selector_List::Selector_List(ParserState pstate, size_t s)
1259
+ : Selector(pstate),
1260
+ Vectorized<Complex_Selector_Obj>(s),
1261
+ schema_({}),
1262
+ wspace_(0)
1263
+ { }
1264
+ Selector_List::Selector_List(const Selector_List* ptr)
1265
+ : Selector(ptr),
1266
+ Vectorized<Complex_Selector_Obj>(*ptr),
1267
+ schema_(ptr->schema_),
1268
+ wspace_(ptr->wspace_)
1269
+ { }
1270
+
1271
+ bool Selector_List::find ( bool (*f)(AST_Node_Obj) )
1272
+ {
1273
+ // check children first
1274
+ for (Complex_Selector_Obj sel : elements()) {
1275
+ if (sel->find(f)) return true;
1276
+ }
1277
+ // execute last
1278
+ return f(this);
1279
+ }
1280
+
1281
+ Selector_List_Obj Selector_List::eval(Eval& eval)
1282
+ {
1283
+ Selector_List_Obj list = schema() ?
1284
+ eval(schema()) : eval(this);
1285
+ list->schema(schema());
1286
+ return list;
1287
+ }
1288
+
1289
+ Selector_List* Selector_List::resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent)
1290
+ {
1291
+ if (!this->has_parent_ref()) return this;
1292
+ Selector_List* ss = SASS_MEMORY_NEW(Selector_List, pstate());
1293
+ for (size_t si = 0, sL = this->length(); si < sL; ++si) {
1294
+ Selector_List_Obj rv = at(si)->resolve_parent_refs(pstack, traces, implicit_parent);
1295
+ ss->concat(rv);
1296
+ }
1297
+ return ss;
1298
+ }
1299
+
1300
+ void Selector_List::cloneChildren()
1301
+ {
1302
+ for (size_t i = 0, l = length(); i < l; i++) {
1303
+ at(i) = SASS_MEMORY_CLONE(at(i));
1304
+ }
1305
+ }
1306
+
1307
+ // remove parent selector references
1308
+ // basically unwraps parsed selectors
1309
+ void Selector_List::remove_parent_selectors()
1310
+ {
1311
+ // Check every rhs selector against left hand list
1312
+ for(size_t i = 0, L = length(); i < L; ++i) {
1313
+ if (!(*this)[i]->head()) continue;
1314
+ if ((*this)[i]->head()->is_empty_reference()) {
1315
+ // simply move to the next tail if we have "no" combinator
1316
+ if ((*this)[i]->combinator() == Complex_Selector::ANCESTOR_OF) {
1317
+ if ((*this)[i]->tail()) {
1318
+ if ((*this)[i]->has_line_feed()) {
1319
+ (*this)[i]->tail()->has_line_feed(true);
1320
+ }
1321
+ (*this)[i] = (*this)[i]->tail();
1322
+ }
1323
+ }
1324
+ // otherwise remove the first item from head
1325
+ else {
1326
+ (*this)[i]->head()->erase((*this)[i]->head()->begin());
1327
+ }
1328
+ }
1329
+ }
1330
+ }
1331
+
1332
+ bool Selector_List::has_parent_ref() const
1333
+ {
1334
+ for (Complex_Selector_Obj s : elements()) {
1335
+ if (s && s->has_parent_ref()) return true;
1336
+ }
1337
+ return false;
1338
+ }
1339
+
1340
+ bool Selector_List::has_real_parent_ref() const
1341
+ {
1342
+ for (Complex_Selector_Obj s : elements()) {
1343
+ if (s && s->has_real_parent_ref()) return true;
1344
+ }
1345
+ return false;
1346
+ }
1347
+
1348
+ void Selector_List::adjust_after_pushing(Complex_Selector_Obj c)
1349
+ {
1350
+ // if (c->has_reference()) has_reference(true);
1351
+ }
1352
+
1353
+ // it's a superselector if every selector of the right side
1354
+ // list is a superselector of the given left side selector
1355
+ bool Selector_List::is_superselector_of(const Selector_List* sub, std::string wrapping) const
1356
+ {
1357
+ // Check every rhs selector against left hand list
1358
+ for(size_t i = 0, L = sub->length(); i < L; ++i) {
1359
+ if (!is_superselector_of((*sub)[i], wrapping)) return false;
1360
+ }
1361
+ return true;
1362
+ }
1363
+
1364
+ // it's a superselector if every selector on the right side
1365
+ // is a superselector of any one of the left side selectors
1366
+ bool Selector_List::is_superselector_of(const Compound_Selector* sub, std::string wrapping) const
1367
+ {
1368
+ // Check every lhs selector against right hand
1369
+ for(size_t i = 0, L = length(); i < L; ++i) {
1370
+ if ((*this)[i]->is_superselector_of(sub, wrapping)) return true;
1371
+ }
1372
+ return false;
1373
+ }
1374
+
1375
+ // it's a superselector if every selector on the right side
1376
+ // is a superselector of any one of the left side selectors
1377
+ bool Selector_List::is_superselector_of(const Complex_Selector* sub, std::string wrapping) const
1378
+ {
1379
+ // Check every lhs selector against right hand
1380
+ for(size_t i = 0, L = length(); i < L; ++i) {
1381
+ if ((*this)[i]->is_superselector_of(sub)) return true;
1382
+ }
1383
+ return false;
1384
+ }
1385
+
1386
+ void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
1387
+ {
1388
+
1389
+ Selector_List* extender = this;
1390
+ for (auto complex_sel : extendee->elements()) {
1391
+ Complex_Selector_Obj c = complex_sel;
1392
+
1393
+
1394
+ // Ignore any parent selectors, until we find the first non Selectorerence head
1395
+ Compound_Selector_Obj compound_sel = c->head();
1396
+ Complex_Selector_Obj pIter = complex_sel;
1397
+ while (pIter) {
1398
+ Compound_Selector_Obj pHead = pIter->head();
1399
+ if (pHead && Cast<Parent_Selector>(pHead->elements()[0]) == NULL) {
1400
+ compound_sel = pHead;
1401
+ break;
1402
+ }
1403
+
1404
+ pIter = pIter->tail();
1405
+ }
1406
+
1407
+ if (!pIter->head() || pIter->tail()) {
1408
+ coreError("nested selectors may not be extended", c->pstate());
1409
+ }
1410
+
1411
+ compound_sel->is_optional(extendee->is_optional());
1412
+
1413
+ for (size_t i = 0, L = extender->length(); i < L; ++i) {
1414
+ extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
1415
+ }
1416
+ }
1417
+ };
1418
+
1419
+ size_t Selector_List::hash() const
1420
+ {
1421
+ if (Selector::hash_ == 0) {
1422
+ if (empty()) {
1423
+ hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
1424
+ } else {
1425
+ hash_combine(Selector::hash_, Vectorized::hash());
1426
+ }
1427
+ }
1428
+ return Selector::hash_;
1429
+ }
1430
+
1431
+ unsigned long Selector_List::specificity() const
1432
+ {
1433
+ unsigned long sum = 0;
1434
+ unsigned long specificity;
1435
+ for (size_t i = 0, L = length(); i < L; ++i)
1436
+ {
1437
+ specificity = (*this)[i]->specificity();
1438
+ if (sum < specificity) sum = specificity;
1439
+ }
1440
+ return sum;
1441
+ }
1442
+
1443
+ void Selector_List::set_media_block(Media_Block* mb)
1444
+ {
1445
+ media_block(mb);
1446
+ for (Complex_Selector_Obj cs : elements()) {
1447
+ cs->set_media_block(mb);
1448
+ }
1449
+ }
1450
+
1451
+ bool Selector_List::has_placeholder()
1452
+ {
1453
+ for (Complex_Selector_Obj cs : elements()) {
1454
+ if (cs->has_placeholder()) return true;
1455
+ }
1456
+ return false;
1457
+ }
1458
+
1459
+ /////////////////////////////////////////////////////////////////////////
1460
+ /////////////////////////////////////////////////////////////////////////
1461
+
1462
+ IMPLEMENT_AST_OPERATORS(Selector_Schema);
1463
+ IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
1464
+ IMPLEMENT_AST_OPERATORS(Parent_Selector);
1465
+ IMPLEMENT_AST_OPERATORS(Attribute_Selector);
1466
+ IMPLEMENT_AST_OPERATORS(Compound_Selector);
1467
+ IMPLEMENT_AST_OPERATORS(Complex_Selector);
1468
+ IMPLEMENT_AST_OPERATORS(Type_Selector);
1469
+ IMPLEMENT_AST_OPERATORS(Class_Selector);
1470
+ IMPLEMENT_AST_OPERATORS(Id_Selector);
1471
+ IMPLEMENT_AST_OPERATORS(Pseudo_Selector);
1472
+ IMPLEMENT_AST_OPERATORS(Wrapped_Selector);
1473
+ IMPLEMENT_AST_OPERATORS(Selector_List);
1474
+
1475
+ }