sassc 2.0.1 → 2.1.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }