sassc 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }