sassc 2.2.1 → 2.3.0

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Rakefile +1 -3
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +1 -0
  9. data/ext/libsass/src/ast.cpp +49 -59
  10. data/ext/libsass/src/ast.hpp +263 -102
  11. data/ext/libsass/src/ast_def_macros.hpp +8 -0
  12. data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
  13. data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
  14. data/ext/libsass/src/ast_helpers.hpp +292 -0
  15. data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
  16. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  17. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  18. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  19. data/ext/libsass/src/ast_selectors.cpp +559 -1001
  20. data/ext/libsass/src/ast_selectors.hpp +311 -367
  21. data/ext/libsass/src/ast_supports.cpp +1 -17
  22. data/ext/libsass/src/ast_values.cpp +216 -29
  23. data/ext/libsass/src/ast_values.hpp +42 -33
  24. data/ext/libsass/src/bind.cpp +1 -1
  25. data/ext/libsass/src/cencode.c +4 -6
  26. data/ext/libsass/src/check_nesting.cpp +5 -6
  27. data/ext/libsass/src/check_nesting.hpp +4 -0
  28. data/ext/libsass/src/color_maps.cpp +11 -10
  29. data/ext/libsass/src/color_maps.hpp +0 -8
  30. data/ext/libsass/src/constants.cpp +5 -0
  31. data/ext/libsass/src/constants.hpp +6 -0
  32. data/ext/libsass/src/context.cpp +30 -60
  33. data/ext/libsass/src/context.hpp +8 -20
  34. data/ext/libsass/src/cssize.cpp +36 -120
  35. data/ext/libsass/src/cssize.hpp +4 -10
  36. data/ext/libsass/src/dart_helpers.hpp +199 -0
  37. data/ext/libsass/src/debugger.hpp +364 -207
  38. data/ext/libsass/src/emitter.cpp +3 -4
  39. data/ext/libsass/src/emitter.hpp +0 -2
  40. data/ext/libsass/src/environment.hpp +5 -0
  41. data/ext/libsass/src/error_handling.cpp +21 -0
  42. data/ext/libsass/src/error_handling.hpp +25 -3
  43. data/ext/libsass/src/eval.cpp +33 -153
  44. data/ext/libsass/src/eval.hpp +11 -13
  45. data/ext/libsass/src/eval_selectors.cpp +75 -0
  46. data/ext/libsass/src/expand.cpp +214 -167
  47. data/ext/libsass/src/expand.hpp +26 -6
  48. data/ext/libsass/src/extender.cpp +1186 -0
  49. data/ext/libsass/src/extender.hpp +399 -0
  50. data/ext/libsass/src/extension.cpp +43 -0
  51. data/ext/libsass/src/extension.hpp +89 -0
  52. data/ext/libsass/src/file.cpp +15 -14
  53. data/ext/libsass/src/file.hpp +5 -12
  54. data/ext/libsass/src/fn_colors.cpp +12 -10
  55. data/ext/libsass/src/fn_lists.cpp +12 -11
  56. data/ext/libsass/src/fn_miscs.cpp +22 -34
  57. data/ext/libsass/src/fn_numbers.cpp +13 -6
  58. data/ext/libsass/src/fn_selectors.cpp +94 -124
  59. data/ext/libsass/src/fn_strings.cpp +16 -14
  60. data/ext/libsass/src/fn_utils.cpp +5 -6
  61. data/ext/libsass/src/fn_utils.hpp +9 -3
  62. data/ext/libsass/src/inspect.cpp +154 -117
  63. data/ext/libsass/src/inspect.hpp +10 -8
  64. data/ext/libsass/src/lexer.cpp +17 -81
  65. data/ext/libsass/src/lexer.hpp +5 -16
  66. data/ext/libsass/src/listize.cpp +22 -36
  67. data/ext/libsass/src/listize.hpp +8 -9
  68. data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
  69. data/ext/libsass/src/operation.hpp +27 -17
  70. data/ext/libsass/src/operators.cpp +1 -0
  71. data/ext/libsass/src/ordered_map.hpp +112 -0
  72. data/ext/libsass/src/output.cpp +30 -49
  73. data/ext/libsass/src/output.hpp +1 -1
  74. data/ext/libsass/src/parser.cpp +211 -381
  75. data/ext/libsass/src/parser.hpp +17 -15
  76. data/ext/libsass/src/parser_selectors.cpp +189 -0
  77. data/ext/libsass/src/permutate.hpp +140 -0
  78. data/ext/libsass/src/position.hpp +1 -1
  79. data/ext/libsass/src/prelexer.cpp +6 -6
  80. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  81. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  82. data/ext/libsass/src/sass.hpp +1 -0
  83. data/ext/libsass/src/sass2scss.cpp +4 -4
  84. data/ext/libsass/src/sass_context.cpp +42 -91
  85. data/ext/libsass/src/sass_context.hpp +2 -2
  86. data/ext/libsass/src/sass_functions.cpp +1 -1
  87. data/ext/libsass/src/sass_values.cpp +0 -1
  88. data/ext/libsass/src/stylesheet.cpp +22 -0
  89. data/ext/libsass/src/stylesheet.hpp +57 -0
  90. data/ext/libsass/src/to_value.cpp +2 -2
  91. data/ext/libsass/src/to_value.hpp +1 -1
  92. data/ext/libsass/src/units.cpp +5 -3
  93. data/ext/libsass/src/util.cpp +10 -12
  94. data/ext/libsass/src/util.hpp +2 -3
  95. data/ext/libsass/src/util_string.cpp +111 -61
  96. data/ext/libsass/src/util_string.hpp +61 -8
  97. data/lib/sassc/engine.rb +5 -3
  98. data/lib/sassc/functions_handler.rb +8 -8
  99. data/lib/sassc/native.rb +1 -1
  100. data/lib/sassc/script.rb +4 -4
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/functions_test.rb +18 -1
  103. data/test/native_test.rb +1 -1
  104. metadata +17 -12
  105. data/ext/libsass/src/extend.cpp +0 -2132
  106. data/ext/libsass/src/extend.hpp +0 -86
  107. data/ext/libsass/src/node.cpp +0 -322
  108. data/ext/libsass/src/node.hpp +0 -118
  109. data/ext/libsass/src/paths.hpp +0 -71
  110. data/ext/libsass/src/sass_util.cpp +0 -152
  111. data/ext/libsass/src/sass_util.hpp +0 -256
  112. data/ext/libsass/src/subset_map.cpp +0 -58
  113. data/ext/libsass/src/subset_map.hpp +0 -76
@@ -1,21 +1,10 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
1
3
  #include "sass.hpp"
4
+
2
5
  #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>
6
+ #include "permutate.hpp"
7
+ #include "util_string.hpp"
19
8
 
20
9
  namespace Sass {
21
10
 
@@ -24,31 +13,14 @@ namespace Sass {
24
13
 
25
14
  Selector::Selector(ParserState pstate)
26
15
  : Expression(pstate),
27
- has_line_feed_(false),
28
- has_line_break_(false),
29
- is_optional_(false),
30
- media_block_(0),
31
16
  hash_(0)
32
17
  { concrete_type(SELECTOR); }
33
18
 
34
19
  Selector::Selector(const Selector* ptr)
35
20
  : 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
21
  hash_(ptr->hash_)
41
22
  { concrete_type(SELECTOR); }
42
23
 
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
24
 
53
25
  bool Selector::has_real_parent_ref() const
54
26
  {
@@ -62,14 +34,12 @@ namespace Sass {
62
34
  : AST_Node(pstate),
63
35
  contents_(c),
64
36
  connect_parent_(true),
65
- media_block_(NULL),
66
37
  hash_(0)
67
38
  { }
68
39
  Selector_Schema::Selector_Schema(const Selector_Schema* ptr)
69
40
  : AST_Node(ptr),
70
41
  contents_(ptr->contents_),
71
42
  connect_parent_(ptr->connect_parent_),
72
- media_block_(ptr->media_block_),
73
43
  hash_(ptr->hash_)
74
44
  { }
75
45
 
@@ -85,30 +55,21 @@ namespace Sass {
85
55
  return hash_;
86
56
  }
87
57
 
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
58
  bool Selector_Schema::has_real_parent_ref() const
99
59
  {
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
- }
60
+ // Note: disabled since it does not seem to do anything?
61
+ // if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
62
+ // if (schema->empty()) return false;
63
+ // const auto first = schema->first();
64
+ // return Cast<Parent_Reference>(first);
65
+ // }
105
66
  return false;
106
67
  }
107
68
 
108
69
  /////////////////////////////////////////////////////////////////////////
109
70
  /////////////////////////////////////////////////////////////////////////
110
71
 
111
- Simple_Selector::Simple_Selector(ParserState pstate, std::string n)
72
+ SimpleSelector::SimpleSelector(ParserState pstate, std::string n)
112
73
  : Selector(pstate), ns_(""), name_(n), has_ns_(false)
113
74
  {
114
75
  size_t pos = n.find('|');
@@ -119,127 +80,105 @@ namespace Sass {
119
80
  name_ = n.substr(pos + 1);
120
81
  }
121
82
  }
122
- Simple_Selector::Simple_Selector(const Simple_Selector* ptr)
83
+ SimpleSelector::SimpleSelector(const SimpleSelector* ptr)
123
84
  : Selector(ptr),
124
85
  ns_(ptr->ns_),
125
86
  name_(ptr->name_),
126
87
  has_ns_(ptr->has_ns_)
127
88
  { }
128
89
 
129
- std::string Simple_Selector::ns_name() const
90
+ std::string SimpleSelector::ns_name() const
130
91
  {
131
- std::string name("");
132
- if (has_ns_)
133
- name += ns_ + "|";
134
- return name + name_;
92
+ if (!has_ns_) return name_;
93
+ else return ns_ + "|" + name_;
135
94
  }
136
95
 
137
- size_t Simple_Selector::hash() const
96
+ size_t SimpleSelector::hash() const
138
97
  {
139
98
  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()));
99
+ hash_combine(hash_, name());
100
+ hash_combine(hash_, (int)SELECTOR);
101
+ hash_combine(hash_, (int)simple_type());
102
+ if (has_ns_) hash_combine(hash_, ns());
144
103
  }
145
104
  return hash_;
146
105
  }
147
106
 
148
- bool Simple_Selector::empty() const {
107
+ bool SimpleSelector::empty() const {
149
108
  return ns().empty() && name().empty();
150
109
  }
151
110
 
152
111
  // namespace compare functions
153
- bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const
112
+ bool SimpleSelector::is_ns_eq(const SimpleSelector& r) const
154
113
  {
155
114
  return has_ns_ == r.has_ns_ && ns_ == r.ns_;
156
115
  }
157
116
 
158
117
  // namespace query functions
159
- bool Simple_Selector::is_universal_ns() const
118
+ bool SimpleSelector::is_universal_ns() const
160
119
  {
161
120
  return has_ns_ && ns_ == "*";
162
121
  }
163
122
 
164
- bool Simple_Selector::is_empty_ns() const
123
+ bool SimpleSelector::is_empty_ns() const
165
124
  {
166
125
  return !has_ns_ || ns_ == "";
167
126
  }
168
127
 
169
- bool Simple_Selector::has_empty_ns() const
128
+ bool SimpleSelector::has_empty_ns() const
170
129
  {
171
130
  return has_ns_ && ns_ == "";
172
131
  }
173
132
 
174
- bool Simple_Selector::has_qualified_ns() const
133
+ bool SimpleSelector::has_qualified_ns() const
175
134
  {
176
135
  return has_ns_ && ns_ != "" && ns_ != "*";
177
136
  }
178
137
 
179
138
  // name query functions
180
- bool Simple_Selector::is_universal() const
139
+ bool SimpleSelector::is_universal() const
181
140
  {
182
141
  return name_ == "*";
183
142
  }
184
143
 
185
- bool Simple_Selector::has_placeholder()
144
+ bool SimpleSelector::has_placeholder()
186
145
  {
187
146
  return false;
188
147
  }
189
148
 
190
- bool Simple_Selector::has_parent_ref() const
191
- {
192
- return false;
193
- };
194
-
195
- bool Simple_Selector::has_real_parent_ref() const
149
+ bool SimpleSelector::has_real_parent_ref() const
196
150
  {
197
151
  return false;
198
152
  };
199
153
 
200
- bool Simple_Selector::is_pseudo_element() const
154
+ bool SimpleSelector::is_pseudo_element() const
201
155
  {
202
156
  return false;
203
157
  }
204
158
 
205
- bool Simple_Selector::is_superselector_of(const Compound_Selector* sub) const
159
+ CompoundSelectorObj SimpleSelector::wrapInCompound()
206
160
  {
207
- return false;
161
+ CompoundSelectorObj selector =
162
+ SASS_MEMORY_NEW(CompoundSelector, pstate());
163
+ selector->append(this);
164
+ return selector;
208
165
  }
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
166
+ ComplexSelectorObj SimpleSelector::wrapInComplex()
226
167
  {
227
- return real();
228
- };
229
-
230
- unsigned long Parent_Selector::specificity() const
231
- {
232
- return 0;
168
+ ComplexSelectorObj selector =
169
+ SASS_MEMORY_NEW(ComplexSelector, pstate());
170
+ selector->append(wrapInCompound());
171
+ return selector;
233
172
  }
234
173
 
235
174
  /////////////////////////////////////////////////////////////////////////
236
175
  /////////////////////////////////////////////////////////////////////////
237
176
 
238
177
  Placeholder_Selector::Placeholder_Selector(ParserState pstate, std::string n)
239
- : Simple_Selector(pstate, n)
178
+ : SimpleSelector(pstate, n)
240
179
  { simple_type(PLACEHOLDER_SEL); }
241
180
  Placeholder_Selector::Placeholder_Selector(const Placeholder_Selector* ptr)
242
- : Simple_Selector(ptr)
181
+ : SimpleSelector(ptr)
243
182
  { simple_type(PLACEHOLDER_SEL); }
244
183
  unsigned long Placeholder_Selector::specificity() const
245
184
  {
@@ -253,10 +192,10 @@ namespace Sass {
253
192
  /////////////////////////////////////////////////////////////////////////
254
193
 
255
194
  Type_Selector::Type_Selector(ParserState pstate, std::string n)
256
- : Simple_Selector(pstate, n)
195
+ : SimpleSelector(pstate, n)
257
196
  { simple_type(TYPE_SEL); }
258
197
  Type_Selector::Type_Selector(const Type_Selector* ptr)
259
- : Simple_Selector(ptr)
198
+ : SimpleSelector(ptr)
260
199
  { simple_type(TYPE_SEL); }
261
200
 
262
201
  unsigned long Type_Selector::specificity() const
@@ -269,10 +208,10 @@ namespace Sass {
269
208
  /////////////////////////////////////////////////////////////////////////
270
209
 
271
210
  Class_Selector::Class_Selector(ParserState pstate, std::string n)
272
- : Simple_Selector(pstate, n)
211
+ : SimpleSelector(pstate, n)
273
212
  { simple_type(CLASS_SEL); }
274
213
  Class_Selector::Class_Selector(const Class_Selector* ptr)
275
- : Simple_Selector(ptr)
214
+ : SimpleSelector(ptr)
276
215
  { simple_type(CLASS_SEL); }
277
216
 
278
217
  unsigned long Class_Selector::specificity() const
@@ -284,10 +223,10 @@ namespace Sass {
284
223
  /////////////////////////////////////////////////////////////////////////
285
224
 
286
225
  Id_Selector::Id_Selector(ParserState pstate, std::string n)
287
- : Simple_Selector(pstate, n)
226
+ : SimpleSelector(pstate, n)
288
227
  { simple_type(ID_SEL); }
289
228
  Id_Selector::Id_Selector(const Id_Selector* ptr)
290
- : Simple_Selector(ptr)
229
+ : SimpleSelector(ptr)
291
230
  { simple_type(ID_SEL); }
292
231
 
293
232
  unsigned long Id_Selector::specificity() const
@@ -299,10 +238,10 @@ namespace Sass {
299
238
  /////////////////////////////////////////////////////////////////////////
300
239
 
301
240
  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)
241
+ : SimpleSelector(pstate, n), matcher_(m), value_(v), modifier_(o)
303
242
  { simple_type(ATTRIBUTE_SEL); }
304
243
  Attribute_Selector::Attribute_Selector(const Attribute_Selector* ptr)
305
- : Simple_Selector(ptr),
244
+ : SimpleSelector(ptr),
306
245
  matcher_(ptr->matcher_),
307
246
  value_(ptr->value_),
308
247
  modifier_(ptr->modifier_)
@@ -311,7 +250,7 @@ namespace Sass {
311
250
  size_t Attribute_Selector::hash() const
312
251
  {
313
252
  if (hash_ == 0) {
314
- hash_combine(hash_, Simple_Selector::hash());
253
+ hash_combine(hash_, SimpleSelector::hash());
315
254
  hash_combine(hash_, std::hash<std::string>()(matcher()));
316
255
  if (value_) hash_combine(hash_, value_->hash());
317
256
  }
@@ -326,11 +265,21 @@ namespace Sass {
326
265
  /////////////////////////////////////////////////////////////////////////
327
266
  /////////////////////////////////////////////////////////////////////////
328
267
 
329
- Pseudo_Selector::Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr)
330
- : Simple_Selector(pstate, n), expression_(expr)
268
+ Pseudo_Selector::Pseudo_Selector(ParserState pstate, std::string name, bool element)
269
+ : SimpleSelector(pstate, name),
270
+ normalized_(Util::unvendor(name)),
271
+ argument_({}),
272
+ selector_({}),
273
+ isSyntacticClass_(!element),
274
+ isClass_(!element && !isFakePseudoElement(normalized_))
331
275
  { simple_type(PSEUDO_SEL); }
332
276
  Pseudo_Selector::Pseudo_Selector(const Pseudo_Selector* ptr)
333
- : Simple_Selector(ptr), expression_(ptr->expression_)
277
+ : SimpleSelector(ptr),
278
+ normalized_(ptr->normalized()),
279
+ argument_(ptr->argument()),
280
+ selector_(ptr->selector()),
281
+ isSyntacticClass_(ptr->isSyntacticClass()),
282
+ isClass_(ptr->isClass())
334
283
  { simple_type(PSEUDO_SEL); }
335
284
 
336
285
  // A pseudo-element is made of two colons (::) followed by the name.
@@ -343,15 +292,15 @@ namespace Sass {
343
292
  // introduced in this specification.
344
293
  bool Pseudo_Selector::is_pseudo_element() const
345
294
  {
346
- return (name_[0] == ':' && name_[1] == ':')
347
- || is_pseudo_class_element(name_);
295
+ return isElement();
348
296
  }
349
297
 
350
298
  size_t Pseudo_Selector::hash() const
351
299
  {
352
300
  if (hash_ == 0) {
353
- hash_combine(hash_, Simple_Selector::hash());
354
- if (expression_) hash_combine(hash_, expression_->hash());
301
+ hash_combine(hash_, SimpleSelector::hash());
302
+ if (selector_) hash_combine(hash_, selector_->hash());
303
+ if (argument_) hash_combine(hash_, argument_->hash());
355
304
  }
356
305
  return hash_;
357
306
  }
@@ -363,1097 +312,707 @@ namespace Sass {
363
312
  return Constants::Specificity_Pseudo;
364
313
  }
365
314
 
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
315
+ Pseudo_Selector_Obj Pseudo_Selector::withSelector(SelectorListObj selector)
377
316
  {
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;
317
+ Pseudo_Selector_Obj pseudo = SASS_MEMORY_COPY(this);
318
+ pseudo->selector(selector);
319
+ return pseudo;
387
320
  }
388
321
 
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()
322
+ bool Pseudo_Selector::empty() const
393
323
  {
394
- selector(SASS_MEMORY_CLONE(selector()));
324
+ // Only considered empty if selector is
325
+ // available but has no items in it.
326
+ return selector() && selector()->empty();
395
327
  }
396
328
 
397
- size_t Wrapped_Selector::hash() const
329
+ void Pseudo_Selector::cloneChildren()
398
330
  {
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();
331
+ if (selector().isNull()) selector({});
332
+ else selector(SASS_MEMORY_CLONE(selector()));
409
333
  }
410
334
 
411
- bool Wrapped_Selector::has_real_parent_ref() const {
335
+ bool Pseudo_Selector::has_real_parent_ref() const {
412
336
  if (!selector()) return false;
413
337
  return selector()->has_real_parent_ref();
414
338
  }
415
339
 
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
340
  /////////////////////////////////////////////////////////////////////////
432
341
  /////////////////////////////////////////////////////////////////////////
433
342
 
434
- Compound_Selector::Compound_Selector(ParserState pstate, size_t s)
343
+ SelectorList::SelectorList(ParserState pstate, size_t s)
435
344
  : Selector(pstate),
436
- Vectorized<Simple_Selector_Obj>(s),
437
- extended_(false),
438
- has_parent_reference_(false)
345
+ Vectorized<ComplexSelectorObj>(s),
346
+ is_optional_(false)
439
347
  { }
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_)
348
+ SelectorList::SelectorList(const SelectorList* ptr)
349
+ : Selector(ptr),
350
+ Vectorized<ComplexSelectorObj>(*ptr),
351
+ is_optional_(ptr->is_optional_)
446
352
  { }
447
353
 
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()
354
+ size_t SelectorList::hash() const
456
355
  {
457
- for (size_t i = 0, l = length(); i < l; i++) {
458
- at(i) = SASS_MEMORY_CLONE(at(i));
356
+ if (Selector::hash_ == 0) {
357
+ hash_combine(Selector::hash_, Vectorized::hash());
459
358
  }
359
+ return Selector::hash_;
460
360
  }
461
361
 
462
- bool Compound_Selector::find ( bool (*f)(AST_Node_Obj) )
362
+ bool SelectorList::has_real_parent_ref() const
463
363
  {
464
- // check children first
465
- for (Simple_Selector_Obj sel : elements()) {
466
- if (sel->find(f)) return true;
364
+ for (ComplexSelectorObj s : elements()) {
365
+ if (s && s->has_real_parent_ref()) return true;
467
366
  }
468
- // execute last
469
- return f(this);
367
+ return false;
470
368
  }
471
369
 
472
- bool Compound_Selector::has_parent_ref() const
370
+ void SelectorList::cloneChildren()
473
371
  {
474
- for (Simple_Selector_Obj s : *this) {
475
- if (s && s->has_parent_ref()) return true;
372
+ for (size_t i = 0, l = length(); i < l; i++) {
373
+ at(i) = SASS_MEMORY_CLONE(at(i));
476
374
  }
477
- return false;
478
375
  }
479
376
 
480
- bool Compound_Selector::has_real_parent_ref() const
377
+ unsigned long SelectorList::specificity() const
481
378
  {
482
- for (Simple_Selector_Obj s : *this) {
483
- if (s && s->has_real_parent_ref()) return true;
484
- }
485
- return false;
379
+ return 0;
486
380
  }
487
381
 
488
- bool Compound_Selector::is_superselector_of(const Selector_List* rhs, std::string wrapped) const
382
+ bool SelectorList::isInvisible() const
489
383
  {
490
- for (Complex_Selector_Obj item : rhs->elements()) {
491
- if (is_superselector_of(item, wrapped)) return true;
384
+ if (length() == 0) return true;
385
+ for (size_t i = 0; i < length(); i += 1) {
386
+ if (get(i)->isInvisible()) return true;
492
387
  }
493
388
  return false;
494
389
  }
495
390
 
496
- bool Compound_Selector::is_superselector_of(const Complex_Selector* rhs, std::string wrapped) const
391
+ /////////////////////////////////////////////////////////////////////////
392
+ /////////////////////////////////////////////////////////////////////////
393
+
394
+ ComplexSelector::ComplexSelector(ParserState pstate)
395
+ : Selector(pstate),
396
+ Vectorized<SelectorComponentObj>(),
397
+ chroots_(false),
398
+ hasPreLineFeed_(false)
497
399
  {
498
- if (rhs->head()) return is_superselector_of(rhs->head(), wrapped);
499
- return false;
500
400
  }
501
-
502
- bool Compound_Selector::is_superselector_of(const Compound_Selector* rhs, std::string wrapping) const
401
+ ComplexSelector::ComplexSelector(const ComplexSelector* ptr)
402
+ : Selector(ptr),
403
+ Vectorized<SelectorComponentObj>(ptr->elements()),
404
+ chroots_(ptr->chroots()),
405
+ hasPreLineFeed_(ptr->hasPreLineFeed())
503
406
  {
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
- }
407
+ }
565
408
 
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);
409
+ void ComplexSelector::cloneChildren()
410
+ {
411
+ for (size_t i = 0, l = length(); i < l; i++) {
412
+ at(i) = SASS_MEMORY_CLONE(at(i));
590
413
  }
591
-
592
- return contains_all(rset, lset);
593
414
  }
594
415
 
595
- bool Compound_Selector::is_universal() const
416
+ unsigned long ComplexSelector::specificity() const
596
417
  {
597
- return length() == 1 && (*this)[0]->is_universal();
418
+ int sum = 0;
419
+ for (auto component : elements()) {
420
+ sum += component->specificity();
421
+ }
422
+ return sum;
598
423
  }
599
424
 
600
- // create complex selector (ancestor of) from compound selector
601
- Complex_Selector_Obj Compound_Selector::to_complex()
425
+ bool ComplexSelector::isInvisible() const
602
426
  {
603
- // create an intermediate complex selector
604
- return SASS_MEMORY_NEW(Complex_Selector,
605
- pstate(),
606
- Complex_Selector::ANCESTOR_OF,
607
- this,
608
- {});
427
+ if (length() == 0) return true;
428
+ for (size_t i = 0; i < length(); i += 1) {
429
+ if (CompoundSelectorObj compound = get(i)->getCompound()) {
430
+ if (compound->isInvisible()) return true;
431
+ }
432
+ }
433
+ return false;
609
434
  }
610
435
 
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;
436
+ SelectorListObj ComplexSelector::wrapInList()
437
+ {
438
+ SelectorListObj selector =
439
+ SASS_MEMORY_NEW(SelectorList, pstate());
440
+ selector->append(this);
441
+ return selector;
617
442
  }
618
443
 
619
- size_t Compound_Selector::hash() const
444
+ size_t ComplexSelector::hash() const
620
445
  {
621
446
  if (Selector::hash_ == 0) {
622
- hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
623
- if (length()) hash_combine(Selector::hash_, Vectorized::hash());
447
+ hash_combine(Selector::hash_, Vectorized::hash());
448
+ // ToDo: this breaks some extend lookup
449
+ // hash_combine(Selector::hash_, chroots_);
624
450
  }
625
451
  return Selector::hash_;
626
452
  }
627
453
 
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;
454
+ bool ComplexSelector::has_placeholder() const {
455
+ for (size_t i = 0, L = length(); i < L; ++i) {
456
+ if (get(i)->has_placeholder()) return true;
457
+ }
458
+ return false;
634
459
  }
635
460
 
636
- bool Compound_Selector::has_placeholder()
461
+ bool ComplexSelector::has_real_parent_ref() const
637
462
  {
638
- if (length() == 0) return false;
639
- if (Simple_Selector_Obj ss = elements().front()) {
640
- if (ss->has_placeholder()) return true;
463
+ for (auto item : elements()) {
464
+ if (item->has_real_parent_ref()) return true;
641
465
  }
642
466
  return false;
643
467
  }
644
468
 
645
- bool Compound_Selector::is_empty_reference()
469
+ /////////////////////////////////////////////////////////////////////////
470
+ /////////////////////////////////////////////////////////////////////////
471
+
472
+ SelectorComponent::SelectorComponent(ParserState pstate, bool postLineBreak)
473
+ : Selector(pstate),
474
+ hasPostLineBreak_(postLineBreak)
646
475
  {
647
- return length() == 1 &&
648
- Cast<Parent_Selector>((*this)[0]);
649
476
  }
650
477
 
651
- void Compound_Selector::append(Simple_Selector_Obj element)
478
+ SelectorComponent::SelectorComponent(const SelectorComponent* ptr)
479
+ : Selector(ptr),
480
+ hasPostLineBreak_(ptr->hasPostLineBreak())
481
+ { }
482
+
483
+ void SelectorComponent::cloneChildren()
652
484
  {
653
- Vectorized<Simple_Selector_Obj>::append(element);
654
- pstate_.offset += element->pstate().offset;
655
485
  }
656
486
 
657
- Compound_Selector* Compound_Selector::minus(Compound_Selector* rhs)
487
+ unsigned long SelectorComponent::specificity() const
658
488
  {
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;
489
+ return 0;
678
490
  }
679
491
 
680
- void Compound_Selector::mergeSources(ComplexSelectorSet& sources)
492
+ // Wrap the compound selector with a complex selector
493
+ ComplexSelector* SelectorComponent::wrapInComplex()
681
494
  {
682
- for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
683
- this->sources_.insert(SASS_MEMORY_CLONE(*iterator));
684
- }
495
+ auto complex = SASS_MEMORY_NEW(ComplexSelector, pstate());
496
+ complex->append(this);
497
+ return complex;
685
498
  }
686
499
 
687
500
  /////////////////////////////////////////////////////////////////////////
688
501
  /////////////////////////////////////////////////////////////////////////
689
502
 
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;
503
+ SelectorCombinator::SelectorCombinator(ParserState pstate, SelectorCombinator::Combinator combinator, bool postLineBreak)
504
+ : SelectorComponent(pstate, postLineBreak),
505
+ combinator_(combinator)
506
+ {
724
507
  }
508
+ SelectorCombinator::SelectorCombinator(const SelectorCombinator* ptr)
509
+ : SelectorComponent(ptr->pstate(), false),
510
+ combinator_(ptr->combinator())
511
+ { }
725
512
 
726
- bool Complex_Selector::is_empty_ancestor() const
513
+ void SelectorCombinator::cloneChildren()
727
514
  {
728
- return (!head() || head()->length() == 0) &&
729
- combinator() == Combinator::ANCESTOR_OF;
730
515
  }
731
516
 
732
- size_t Complex_Selector::hash() const
517
+ unsigned long SelectorCombinator::specificity() const
733
518
  {
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_;
519
+ return 0;
744
520
  }
745
521
 
746
- unsigned long Complex_Selector::specificity() const
522
+ /////////////////////////////////////////////////////////////////////////
523
+ /////////////////////////////////////////////////////////////////////////
524
+
525
+ CompoundSelector::CompoundSelector(ParserState pstate, bool postLineBreak)
526
+ : SelectorComponent(pstate, postLineBreak),
527
+ Vectorized<SimpleSelectorObj>(),
528
+ hasRealParent_(false),
529
+ extended_(false)
747
530
  {
748
- int sum = 0;
749
- if (head()) sum += head()->specificity();
750
- if (tail()) sum += tail()->specificity();
751
- return sum;
752
531
  }
532
+ CompoundSelector::CompoundSelector(const CompoundSelector* ptr)
533
+ : SelectorComponent(ptr),
534
+ Vectorized<SimpleSelectorObj>(*ptr),
535
+ hasRealParent_(ptr->hasRealParent()),
536
+ extended_(ptr->extended())
537
+ { }
753
538
 
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);
539
+ size_t CompoundSelector::hash() const
540
+ {
541
+ if (Selector::hash_ == 0) {
542
+ hash_combine(Selector::hash_, Vectorized::hash());
543
+ hash_combine(Selector::hash_, hasRealParent_);
544
+ }
545
+ return Selector::hash_;
758
546
  }
759
547
 
760
- bool Complex_Selector::has_placeholder() {
761
- if (head_ && head_->has_placeholder()) return true;
762
- if (tail_ && tail_->has_placeholder()) return true;
548
+ bool CompoundSelector::has_real_parent_ref() const
549
+ {
550
+ if (hasRealParent()) return true;
551
+ // ToDo: dart sass has another check?
552
+ // if (Cast<Type_Selector>(front)) {
553
+ // if (front->ns() != "") return false;
554
+ // }
555
+ for (const SimpleSelector* s : elements()) {
556
+ if (s && s->has_real_parent_ref()) return true;
557
+ }
763
558
  return false;
764
559
  }
765
560
 
766
- const ComplexSelectorSet Complex_Selector::sources()
561
+ bool CompoundSelector::has_placeholder() const
767
562
  {
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());
563
+ if (length() == 0) return false;
564
+ for (SimpleSelectorObj ss : elements()) {
565
+ if (ss->has_placeholder()) return true;
785
566
  }
786
-
787
- return srcs;
567
+ return false;
788
568
  }
789
569
 
790
- void Complex_Selector::addSources(ComplexSelectorSet& sources)
570
+ void CompoundSelector::cloneChildren()
791
571
  {
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();
572
+ for (size_t i = 0, l = length(); i < l; i++) {
573
+ at(i) = SASS_MEMORY_CLONE(at(i));
802
574
  }
803
575
  }
804
576
 
805
- void Complex_Selector::clearSources()
577
+ unsigned long CompoundSelector::specificity() const
806
578
  {
807
- Complex_Selector* pIter = this;
808
- while (pIter) {
809
- Compound_Selector* pHead = pIter->head();
810
-
811
- if (pHead) {
812
- pHead->clearSources();
813
- }
579
+ int sum = 0;
580
+ for (size_t i = 0, L = length(); i < L; ++i)
581
+ { sum += get(i)->specificity(); }
582
+ return sum;
583
+ }
814
584
 
815
- pIter = pIter->tail();
585
+ bool CompoundSelector::isInvisible() const
586
+ {
587
+ for (size_t i = 0; i < length(); i += 1) {
588
+ if (!get(i)->isInvisible()) return false;
816
589
  }
590
+ return true;
817
591
  }
818
592
 
819
- bool Complex_Selector::find ( bool (*f)(AST_Node_Obj) )
593
+ bool CompoundSelector::isSuperselectorOf(const CompoundSelector* sub, std::string wrapped) const
820
594
  {
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);
595
+ CompoundSelector* rhs2 = const_cast<CompoundSelector*>(sub);
596
+ CompoundSelector* lhs2 = const_cast<CompoundSelector*>(this);
597
+ return compoundIsSuperselector(lhs2, rhs2, {});
826
598
  }
827
599
 
828
- bool Complex_Selector::has_parent_ref() const
600
+ /////////////////////////////////////////////////////////////////////////
601
+ /////////////////////////////////////////////////////////////////////////
602
+
603
+ MediaRule::MediaRule(ParserState pstate, Block_Obj block) :
604
+ Has_Block(pstate, block),
605
+ schema_({})
829
606
  {
830
- return (head() && head()->has_parent_ref()) ||
831
- (tail() && tail()->has_parent_ref());
607
+ statement_type(MEDIA);
832
608
  }
833
609
 
834
- bool Complex_Selector::has_real_parent_ref() const
610
+ MediaRule::MediaRule(const MediaRule* ptr) :
611
+ Has_Block(ptr),
612
+ schema_(ptr->schema_)
835
613
  {
836
- return (head() && head()->has_real_parent_ref()) ||
837
- (tail() && tail()->has_real_parent_ref());
614
+ statement_type(MEDIA);
838
615
  }
839
616
 
840
- bool Complex_Selector::is_superselector_of(const Compound_Selector* rhs, std::string wrapping) const
617
+ /////////////////////////////////////////////////////////////////////////
618
+ /////////////////////////////////////////////////////////////////////////
619
+
620
+ CssMediaRule::CssMediaRule(ParserState pstate, Block_Obj block) :
621
+ Has_Block(pstate, block),
622
+ Vectorized()
841
623
  {
842
- return last()->head() && last()->head()->is_superselector_of(rhs, wrapping);
624
+ statement_type(MEDIA);
843
625
  }
844
626
 
845
- bool Complex_Selector::is_superselector_of(const Complex_Selector* rhs, std::string wrapping) const
627
+ CssMediaRule::CssMediaRule(const CssMediaRule* ptr) :
628
+ Has_Block(ptr),
629
+ Vectorized(*ptr)
846
630
  {
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
- }
631
+ statement_type(MEDIA);
632
+ }
877
633
 
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
- }
634
+ CssMediaQuery::CssMediaQuery(ParserState pstate) :
635
+ AST_Node(pstate),
636
+ modifier_(""),
637
+ type_(""),
638
+ features_()
639
+ {
640
+ }
992
641
 
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
- }
642
+ /////////////////////////////////////////////////////////////////////////
643
+ /////////////////////////////////////////////////////////////////////////
1009
644
 
645
+ bool CssMediaQuery::operator==(const CssMediaQuery& rhs) const
646
+ {
647
+ return type_ == rhs.type_
648
+ && modifier_ == rhs.modifier_
649
+ && features_ == rhs.features_;
1010
650
  }
1011
651
 
1012
- Selector_List* Complex_Selector::resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent)
652
+ // Implemented after dart-sass (maybe move to other class?)
653
+ CssMediaQuery_Obj CssMediaQuery::merge(CssMediaQuery_Obj& other)
1013
654
  {
1014
- Complex_Selector_Obj tail = this->tail();
1015
- Compound_Selector_Obj head = this->head();
1016
- Selector_List* parents = pstack.back();
1017
655
 
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
- }
656
+ std::string ourType = this->type();
657
+ Util::ascii_str_tolower(&ourType);
1023
658
 
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;
659
+ std::string theirType = other->type();
660
+ Util::ascii_str_tolower(&theirType);
1026
661
 
1027
- if (head && head->length() > 0) {
662
+ std::string ourModifier = this->modifier();
663
+ Util::ascii_str_tolower(&ourModifier);
1028
664
 
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());
665
+ std::string theirModifier = other->modifier();
666
+ Util::ascii_str_tolower(&theirModifier);
1034
667
 
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
- }
668
+ std::string type;
669
+ std::string modifier;
670
+ std::vector<std::string> features;
1043
671
 
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
- }
672
+ if (ourType.empty() && theirType.empty()) {
673
+ CssMediaQuery_Obj query = SASS_MEMORY_NEW(CssMediaQuery, pstate());
674
+ std::vector<std::string> f1(this->features());
675
+ std::vector<std::string> f2(other->features());
676
+ features.insert(features.end(), f1.begin(), f1.end());
677
+ features.insert(features.end(), f2.begin(), f2.end());
678
+ query->features(features);
679
+ return query;
680
+ }
681
+
682
+ if ((ourModifier == "not") != (theirModifier == "not")) {
683
+ if (ourType == theirType) {
684
+ std::vector<std::string> negativeFeatures =
685
+ ourModifier == "not" ? this->features() : other->features();
686
+ std::vector<std::string> positiveFeatures =
687
+ ourModifier == "not" ? other->features() : this->features();
688
+
689
+ // If the negative features are a subset of the positive features, the
690
+ // query is empty. For example, `not screen and (color)` has no
691
+ // intersection with `screen and (color) and (grid)`.
692
+ // However, `not screen and (color)` *does* intersect with `screen and
693
+ // (grid)`, because it means `not (screen and (color))` and so it allows
694
+ // a screen with no color but with a grid.
695
+ if (listIsSubsetOrEqual(negativeFeatures, positiveFeatures)) {
696
+ return SASS_MEMORY_NEW(CssMediaQuery, pstate());
1114
697
  }
1115
- // have no parent but some tails
1116
698
  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
- }
699
+ return {};
1137
700
  }
1138
701
  }
1139
- // no parent selector in head
1140
- else {
1141
- retval = this->tails(tails);
702
+ else if (this->matchesAllTypes() || other->matchesAllTypes()) {
703
+ return {};
1142
704
  }
1143
705
 
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
- }
706
+ if (ourModifier == "not") {
707
+ modifier = theirModifier;
708
+ type = theirType;
709
+ features = other->features();
710
+ }
711
+ else {
712
+ modifier = ourModifier;
713
+ type = ourType;
714
+ features = this->features();
1150
715
  }
1151
-
1152
- return retval.detach();
1153
-
1154
716
  }
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);
717
+ else if (ourModifier == "not") {
718
+ SASS_ASSERT(theirModifier == "not", "modifiers not is sync");
719
+
720
+ // CSS has no way of representing "neither screen nor print".
721
+ if (ourType != theirType) return {};
722
+
723
+ auto moreFeatures = this->features().size() > other->features().size()
724
+ ? this->features()
725
+ : other->features();
726
+ auto fewerFeatures = this->features().size() > other->features().size()
727
+ ? other->features()
728
+ : this->features();
729
+
730
+ // If one set of features is a superset of the other,
731
+ // use those features because they're strictly narrower.
732
+ if (listIsSubsetOrEqual(fewerFeatures, moreFeatures)) {
733
+ modifier = ourModifier; // "not"
734
+ type = ourType;
735
+ features = moreFeatures;
1167
736
  }
737
+ else {
738
+ // Otherwise, there's no way to
739
+ // represent the intersection.
740
+ return {};
741
+ }
742
+
1168
743
  }
1169
744
  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;
745
+ if (this->matchesAllTypes()) {
746
+ modifier = theirModifier;
747
+ // Omit the type if either input query did, since that indicates that they
748
+ // aren't targeting a browser that requires "all and".
749
+ type = (other->matchesAllTypes() && ourType.empty()) ? "" : theirType;
750
+ std::vector<std::string> f1(this->features());
751
+ std::vector<std::string> f2(other->features());
752
+ features.insert(features.end(), f1.begin(), f1.end());
753
+ features.insert(features.end(), f2.begin(), f2.end());
754
+ }
755
+ else if (other->matchesAllTypes()) {
756
+ modifier = ourModifier;
757
+ type = ourType;
758
+ std::vector<std::string> f1(this->features());
759
+ std::vector<std::string> f2(other->features());
760
+ features.insert(features.end(), f1.begin(), f1.end());
761
+ features.insert(features.end(), f2.begin(), f2.end());
762
+ }
763
+ else if (ourType != theirType) {
764
+ return SASS_MEMORY_NEW(CssMediaQuery, pstate());
765
+ }
766
+ else {
767
+ modifier = ourModifier.empty() ? theirModifier : ourModifier;
768
+ type = ourType;
769
+ std::vector<std::string> f1(this->features());
770
+ std::vector<std::string> f2(other->features());
771
+ features.insert(features.end(), f1.begin(), f1.end());
772
+ features.insert(features.end(), f2.begin(), f2.end());
1189
773
  }
1190
- // advance to next
1191
- cur = cur->tail_;
1192
774
  }
1193
- // result
1194
- return cur;
775
+
776
+ CssMediaQuery_Obj query = SASS_MEMORY_NEW(CssMediaQuery, pstate());
777
+ query->modifier(modifier == ourModifier ? this->modifier() : other->modifier());
778
+ query->type(ourType.empty() ? other->type() : this->type());
779
+ query->features(features);
780
+ return query;
1195
781
  }
1196
782
 
1197
- Complex_Selector* Complex_Selector::mutable_first()
783
+ CssMediaQuery::CssMediaQuery(const CssMediaQuery* ptr) :
784
+ AST_Node(*ptr),
785
+ modifier_(ptr->modifier_),
786
+ type_(ptr->type_),
787
+ features_(ptr->features_)
1198
788
  {
1199
- return const_cast<Complex_Selector*>(first());
1200
789
  }
1201
790
 
1202
- // return the last tail that is defined
1203
- const Complex_Selector* Complex_Selector::last() const
791
+ /////////////////////////////////////////////////////////////////////////
792
+ // ToDo: finalize specificity implementation
793
+ /////////////////////////////////////////////////////////////////////////
794
+
795
+ size_t SelectorList::maxSpecificity() const
1204
796
  {
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();
797
+ size_t specificity = 0;
798
+ for (auto complex : elements()) {
799
+ specificity = std::max(specificity, complex->maxSpecificity());
1211
800
  }
1212
- return cur;
801
+ return specificity;
1213
802
  }
1214
803
 
1215
- Complex_Selector* Complex_Selector::mutable_last()
804
+ size_t SelectorList::minSpecificity() const
1216
805
  {
1217
- return const_cast<Complex_Selector*>(last());
806
+ size_t specificity = 0;
807
+ for (auto complex : elements()) {
808
+ specificity = std::min(specificity, complex->minSpecificity());
809
+ }
810
+ return specificity;
1218
811
  }
1219
812
 
1220
- Complex_Selector::Combinator Complex_Selector::clear_innermost()
813
+ size_t CompoundSelector::maxSpecificity() const
1221
814
  {
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;
815
+ size_t specificity = 0;
816
+ for (auto simple : elements()) {
817
+ specificity += simple->maxSpecificity();
818
+ }
819
+ return specificity;
1228
820
  }
1229
821
 
1230
- void Complex_Selector::set_innermost(Complex_Selector_Obj val, Combinator c)
822
+ size_t CompoundSelector::minSpecificity() const
1231
823
  {
1232
- if (!tail_)
1233
- { tail_ = val; combinator(c); }
1234
- else
1235
- { tail_->set_innermost(val, c); }
824
+ size_t specificity = 0;
825
+ for (auto simple : elements()) {
826
+ specificity += simple->minSpecificity();
827
+ }
828
+ return specificity;
1236
829
  }
1237
830
 
1238
- void Complex_Selector::cloneChildren()
831
+ size_t ComplexSelector::maxSpecificity() const
1239
832
  {
1240
- if (head()) head(SASS_MEMORY_CLONE(head()));
1241
- if (tail()) tail(SASS_MEMORY_CLONE(tail()));
833
+ size_t specificity = 0;
834
+ for (auto component : elements()) {
835
+ specificity += component->maxSpecificity();
836
+ }
837
+ return specificity;
1242
838
  }
1243
839
 
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
840
+ size_t ComplexSelector::minSpecificity() const
1247
841
  {
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;
842
+ size_t specificity = 0;
843
+ for (auto component : elements()) {
844
+ specificity += component->minSpecificity();
1251
845
  }
1252
- return true;
846
+ return specificity;
1253
847
  }
1254
848
 
1255
849
  /////////////////////////////////////////////////////////////////////////
850
+ // ToDo: this might be done easier with new selector format
1256
851
  /////////////////////////////////////////////////////////////////////////
1257
852
 
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) )
853
+ std::vector<ComplexSelectorObj>
854
+ CompoundSelector::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
1272
855
  {
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
856
 
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
- }
857
+ auto parent = pstack.back();
858
+ std::vector<ComplexSelectorObj> rv;
1288
859
 
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);
860
+ for (SimpleSelectorObj simple : elements()) {
861
+ if (Pseudo_Selector * pseudo = Cast<Pseudo_Selector>(simple)) {
862
+ if (SelectorList* sel = Cast<SelectorList>(pseudo->selector())) {
863
+ if (parent) {
864
+ pseudo->selector(sel->resolve_parent_refs(
865
+ pstack, traces, implicit_parent));
866
+ }
867
+ }
868
+ }
1296
869
  }
1297
- return ss;
1298
- }
1299
870
 
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
- }
871
+ // Mix with parents from stack
872
+ if (hasRealParent()) {
1306
873
 
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);
874
+ if (parent.isNull()) {
875
+ return { wrapInComplex() };
876
+ }
877
+ else {
878
+ for (auto complex : parent->elements()) {
879
+ // The parent complex selector has a compound selector
880
+ if (CompoundSelectorObj tail = Cast<CompoundSelector>(complex->last())) {
881
+ // Create a copy to alter it
882
+ complex = SASS_MEMORY_COPY(complex);
883
+ tail = SASS_MEMORY_COPY(tail);
884
+
885
+ // Check if we can merge front with back
886
+ if (length() > 0 && tail->length() > 0) {
887
+ SimpleSelectorObj back = tail->last();
888
+ SimpleSelectorObj front = first();
889
+ auto simple_back = Cast<SimpleSelector>(back);
890
+ auto simple_front = Cast<Type_Selector>(front);
891
+ if (simple_front && simple_back) {
892
+ simple_back = SASS_MEMORY_COPY(simple_back);
893
+ auto name = simple_back->name();
894
+ name += simple_front->name();
895
+ simple_back->name(name);
896
+ tail->elements().back() = simple_back;
897
+ tail->elements().insert(tail->end(),
898
+ begin() + 1, end());
899
+ }
900
+ else {
901
+ tail->concat(this);
902
+ }
903
+ }
904
+ else {
905
+ tail->concat(this);
1320
906
  }
1321
- (*this)[i] = (*this)[i]->tail();
907
+
908
+ complex->elements().back() = tail;
909
+ // Append to results
910
+ rv.push_back(complex);
911
+ }
912
+ else {
913
+ // Can't insert parent that ends with a combinator
914
+ // where the parent selector is followed by something
915
+ if (parent && length() > 0) {
916
+ throw Exception::InvalidParent(parent, traces, this);
917
+ }
918
+ // Create a copy to alter it
919
+ complex = SASS_MEMORY_COPY(complex);
920
+ // Just append ourself
921
+ complex->append(this);
922
+ // Append to results
923
+ rv.push_back(complex);
1322
924
  }
1323
- }
1324
- // otherwise remove the first item from head
1325
- else {
1326
- (*this)[i]->head()->erase((*this)[i]->head()->begin());
1327
925
  }
1328
926
  }
1329
927
  }
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
928
 
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;
929
+ // No parents
930
+ else {
931
+ // Create a new wrapper to wrap ourself
932
+ auto complex = SASS_MEMORY_NEW(ComplexSelector, pstate());
933
+ // Just append ourself
934
+ complex->append(this);
935
+ // Append to results
936
+ rv.push_back(complex);
1360
937
  }
1361
- return true;
1362
- }
1363
938
 
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
- }
939
+ return rv;
1374
940
 
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
941
  }
1385
942
 
1386
- void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
943
+ /* better return std::vector? only - is empty container anyway? */
944
+ SelectorList* ComplexSelector::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
1387
945
  {
1388
946
 
1389
- Selector_List* extender = this;
1390
- for (auto complex_sel : extendee->elements()) {
1391
- Complex_Selector_Obj c = complex_sel;
947
+ std::vector<std::vector<ComplexSelectorObj>> vars;
1392
948
 
949
+ auto parent = pstack.back();
1393
950
 
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
- }
951
+ if (has_real_parent_ref() && !parent) {
952
+ throw Exception::TopLevelParent(traces, pstate());
953
+ }
1403
954
 
1404
- pIter = pIter->tail();
1405
- }
955
+ if (!chroots() && parent) {
1406
956
 
1407
- if (!pIter->head() || pIter->tail()) {
1408
- coreError("nested selectors may not be extended", c->pstate());
957
+ if (!has_real_parent_ref() && !implicit_parent) {
958
+ SelectorList* retval = SASS_MEMORY_NEW(SelectorList, pstate(), 1);
959
+ retval->append(this);
960
+ return retval;
1409
961
  }
1410
962
 
1411
- compound_sel->is_optional(extendee->is_optional());
963
+ vars.push_back(parent->elements());
964
+ }
1412
965
 
1413
- for (size_t i = 0, L = extender->length(); i < L; ++i) {
1414
- extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
966
+ for (auto sel : elements()) {
967
+ if (CompoundSelectorObj comp = Cast<CompoundSelector>(sel)) {
968
+ auto asd = comp->resolve_parent_refs(pstack, traces, implicit_parent);
969
+ if (asd.size() > 0) vars.push_back(asd);
970
+ }
971
+ else {
972
+ // ToDo: merge together sequences whenever possible
973
+ auto cont = SASS_MEMORY_NEW(ComplexSelector, pstate());
974
+ cont->append(sel);
975
+ vars.push_back({ cont });
1415
976
  }
1416
977
  }
1417
- };
1418
978
 
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());
979
+ // Need complex selectors to preserve linefeeds
980
+ std::vector<std::vector<ComplexSelectorObj>> res = permutateAlt(vars);
981
+
982
+ // std::reverse(std::begin(res), std::end(res));
983
+
984
+ auto lst = SASS_MEMORY_NEW(SelectorList, pstate());
985
+ for (auto items : res) {
986
+ if (items.size() > 0) {
987
+ ComplexSelectorObj first = SASS_MEMORY_COPY(items[0]);
988
+ first->hasPreLineFeed(first->hasPreLineFeed() || (!has_real_parent_ref() && hasPreLineFeed()));
989
+ // ToDo: remove once we know how to handle line feeds
990
+ // ToDo: currently a mashup between ruby and dart sass
991
+ // if (has_real_parent_ref()) first->has_line_feed(false);
992
+ // first->has_line_break(first->has_line_break() || has_line_break());
993
+ first->chroots(true); // has been resolved by now
994
+ for (size_t i = 1; i < items.size(); i += 1) {
995
+ first->concat(items[i]);
996
+ }
997
+ lst->append(first);
1426
998
  }
1427
999
  }
1428
- return Selector::hash_;
1429
- }
1430
1000
 
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
- }
1001
+ return lst;
1442
1002
 
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
1003
  }
1450
1004
 
1451
- bool Selector_List::has_placeholder()
1005
+ SelectorList* SelectorList::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
1452
1006
  {
1453
- for (Complex_Selector_Obj cs : elements()) {
1454
- if (cs->has_placeholder()) return true;
1007
+ SelectorList* rv = SASS_MEMORY_NEW(SelectorList, pstate());
1008
+ for (auto sel : elements()) {
1009
+ // Note: this one is tricky as we get back a pointer from resolve parents ...
1010
+ SelectorListObj res = sel->resolve_parent_refs(pstack, traces, implicit_parent);
1011
+ // Note: ... and concat will only append the items in elements
1012
+ // Therefore by passing it directly, the container will leak!
1013
+ rv->concat(res);
1455
1014
  }
1456
- return false;
1015
+ return rv;
1457
1016
  }
1458
1017
 
1459
1018
  /////////////////////////////////////////////////////////////////////////
@@ -1461,15 +1020,14 @@ namespace Sass {
1461
1020
 
1462
1021
  IMPLEMENT_AST_OPERATORS(Selector_Schema);
1463
1022
  IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
1464
- IMPLEMENT_AST_OPERATORS(Parent_Selector);
1465
1023
  IMPLEMENT_AST_OPERATORS(Attribute_Selector);
1466
- IMPLEMENT_AST_OPERATORS(Compound_Selector);
1467
- IMPLEMENT_AST_OPERATORS(Complex_Selector);
1468
1024
  IMPLEMENT_AST_OPERATORS(Type_Selector);
1469
1025
  IMPLEMENT_AST_OPERATORS(Class_Selector);
1470
1026
  IMPLEMENT_AST_OPERATORS(Id_Selector);
1471
1027
  IMPLEMENT_AST_OPERATORS(Pseudo_Selector);
1472
- IMPLEMENT_AST_OPERATORS(Wrapped_Selector);
1473
- IMPLEMENT_AST_OPERATORS(Selector_List);
1028
+ IMPLEMENT_AST_OPERATORS(SelectorCombinator);
1029
+ IMPLEMENT_AST_OPERATORS(CompoundSelector);
1030
+ IMPLEMENT_AST_OPERATORS(ComplexSelector);
1031
+ IMPLEMENT_AST_OPERATORS(SelectorList);
1474
1032
 
1475
1033
  }