sassc 2.2.1 → 2.4.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +18 -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 +4 -0
  9. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  10. data/ext/libsass/src/ast.cpp +158 -168
  11. data/ext/libsass/src/ast.hpp +389 -230
  12. data/ext/libsass/src/ast_def_macros.hpp +18 -10
  13. data/ext/libsass/src/ast_fwd_decl.cpp +4 -3
  14. data/ext/libsass/src/ast_fwd_decl.hpp +98 -165
  15. data/ext/libsass/src/ast_helpers.hpp +292 -0
  16. data/ext/libsass/src/ast_sel_cmp.cpp +219 -732
  17. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  18. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  19. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  20. data/ext/libsass/src/ast_selectors.cpp +594 -1026
  21. data/ext/libsass/src/ast_selectors.hpp +339 -385
  22. data/ext/libsass/src/ast_supports.cpp +36 -52
  23. data/ext/libsass/src/ast_supports.hpp +29 -29
  24. data/ext/libsass/src/ast_values.cpp +271 -84
  25. data/ext/libsass/src/ast_values.hpp +116 -107
  26. data/ext/libsass/src/backtrace.cpp +9 -9
  27. data/ext/libsass/src/backtrace.hpp +5 -5
  28. data/ext/libsass/src/base64vlq.cpp +2 -2
  29. data/ext/libsass/src/base64vlq.hpp +1 -1
  30. data/ext/libsass/src/bind.cpp +18 -18
  31. data/ext/libsass/src/bind.hpp +1 -1
  32. data/ext/libsass/src/c2ast.cpp +3 -3
  33. data/ext/libsass/src/c2ast.hpp +1 -1
  34. data/ext/libsass/src/cencode.c +4 -6
  35. data/ext/libsass/src/check_nesting.cpp +40 -41
  36. data/ext/libsass/src/check_nesting.hpp +6 -2
  37. data/ext/libsass/src/color_maps.cpp +14 -13
  38. data/ext/libsass/src/color_maps.hpp +1 -9
  39. data/ext/libsass/src/constants.cpp +5 -0
  40. data/ext/libsass/src/constants.hpp +6 -0
  41. data/ext/libsass/src/context.cpp +92 -119
  42. data/ext/libsass/src/context.hpp +41 -53
  43. data/ext/libsass/src/cssize.cpp +66 -149
  44. data/ext/libsass/src/cssize.hpp +17 -23
  45. data/ext/libsass/src/dart_helpers.hpp +199 -0
  46. data/ext/libsass/src/debugger.hpp +451 -295
  47. data/ext/libsass/src/emitter.cpp +15 -16
  48. data/ext/libsass/src/emitter.hpp +10 -12
  49. data/ext/libsass/src/environment.cpp +27 -27
  50. data/ext/libsass/src/environment.hpp +29 -24
  51. data/ext/libsass/src/error_handling.cpp +62 -41
  52. data/ext/libsass/src/error_handling.hpp +61 -51
  53. data/ext/libsass/src/eval.cpp +167 -281
  54. data/ext/libsass/src/eval.hpp +27 -29
  55. data/ext/libsass/src/eval_selectors.cpp +75 -0
  56. data/ext/libsass/src/expand.cpp +275 -222
  57. data/ext/libsass/src/expand.hpp +36 -16
  58. data/ext/libsass/src/extender.cpp +1188 -0
  59. data/ext/libsass/src/extender.hpp +399 -0
  60. data/ext/libsass/src/extension.cpp +43 -0
  61. data/ext/libsass/src/extension.hpp +89 -0
  62. data/ext/libsass/src/file.cpp +81 -72
  63. data/ext/libsass/src/file.hpp +28 -37
  64. data/ext/libsass/src/fn_colors.cpp +20 -18
  65. data/ext/libsass/src/fn_lists.cpp +30 -29
  66. data/ext/libsass/src/fn_maps.cpp +3 -3
  67. data/ext/libsass/src/fn_miscs.cpp +34 -46
  68. data/ext/libsass/src/fn_numbers.cpp +20 -13
  69. data/ext/libsass/src/fn_selectors.cpp +98 -128
  70. data/ext/libsass/src/fn_strings.cpp +47 -33
  71. data/ext/libsass/src/fn_utils.cpp +31 -29
  72. data/ext/libsass/src/fn_utils.hpp +17 -11
  73. data/ext/libsass/src/inspect.cpp +186 -148
  74. data/ext/libsass/src/inspect.hpp +31 -29
  75. data/ext/libsass/src/lexer.cpp +20 -82
  76. data/ext/libsass/src/lexer.hpp +5 -16
  77. data/ext/libsass/src/listize.cpp +23 -37
  78. data/ext/libsass/src/listize.hpp +8 -9
  79. data/ext/libsass/src/mapping.hpp +1 -0
  80. data/ext/libsass/src/memory/allocator.cpp +48 -0
  81. data/ext/libsass/src/memory/allocator.hpp +138 -0
  82. data/ext/libsass/src/memory/config.hpp +20 -0
  83. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  84. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  85. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
  86. data/ext/libsass/src/memory.hpp +12 -0
  87. data/ext/libsass/src/operation.hpp +71 -61
  88. data/ext/libsass/src/operators.cpp +19 -18
  89. data/ext/libsass/src/operators.hpp +11 -11
  90. data/ext/libsass/src/ordered_map.hpp +112 -0
  91. data/ext/libsass/src/output.cpp +45 -64
  92. data/ext/libsass/src/output.hpp +6 -6
  93. data/ext/libsass/src/parser.cpp +512 -700
  94. data/ext/libsass/src/parser.hpp +89 -97
  95. data/ext/libsass/src/parser_selectors.cpp +189 -0
  96. data/ext/libsass/src/permutate.hpp +164 -0
  97. data/ext/libsass/src/plugins.cpp +7 -7
  98. data/ext/libsass/src/plugins.hpp +8 -8
  99. data/ext/libsass/src/position.cpp +7 -26
  100. data/ext/libsass/src/position.hpp +44 -21
  101. data/ext/libsass/src/prelexer.cpp +6 -6
  102. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  103. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  104. data/ext/libsass/src/sass.cpp +16 -15
  105. data/ext/libsass/src/sass.hpp +10 -5
  106. data/ext/libsass/src/sass2scss.cpp +4 -4
  107. data/ext/libsass/src/sass_context.cpp +91 -122
  108. data/ext/libsass/src/sass_context.hpp +2 -2
  109. data/ext/libsass/src/sass_functions.cpp +1 -1
  110. data/ext/libsass/src/sass_values.cpp +8 -11
  111. data/ext/libsass/src/settings.hpp +19 -0
  112. data/ext/libsass/src/source.cpp +69 -0
  113. data/ext/libsass/src/source.hpp +95 -0
  114. data/ext/libsass/src/source_data.hpp +32 -0
  115. data/ext/libsass/src/source_map.cpp +22 -18
  116. data/ext/libsass/src/source_map.hpp +12 -9
  117. data/ext/libsass/src/stylesheet.cpp +22 -0
  118. data/ext/libsass/src/stylesheet.hpp +57 -0
  119. data/ext/libsass/src/to_value.cpp +2 -2
  120. data/ext/libsass/src/to_value.hpp +1 -1
  121. data/ext/libsass/src/units.cpp +24 -22
  122. data/ext/libsass/src/units.hpp +8 -8
  123. data/ext/libsass/src/utf8_string.cpp +9 -10
  124. data/ext/libsass/src/utf8_string.hpp +7 -6
  125. data/ext/libsass/src/util.cpp +48 -50
  126. data/ext/libsass/src/util.hpp +20 -21
  127. data/ext/libsass/src/util_string.cpp +111 -61
  128. data/ext/libsass/src/util_string.hpp +62 -8
  129. data/ext/libsass/src/values.cpp +12 -12
  130. data/lib/sassc/engine.rb +5 -3
  131. data/lib/sassc/functions_handler.rb +8 -8
  132. data/lib/sassc/native.rb +4 -6
  133. data/lib/sassc/script.rb +4 -4
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/functions_test.rb +18 -1
  136. data/test/native_test.rb +4 -4
  137. metadata +29 -15
  138. data/ext/libsass/src/extend.cpp +0 -2132
  139. data/ext/libsass/src/extend.hpp +0 -86
  140. data/ext/libsass/src/node.cpp +0 -322
  141. data/ext/libsass/src/node.hpp +0 -118
  142. data/ext/libsass/src/paths.hpp +0 -71
  143. data/ext/libsass/src/sass_util.cpp +0 -152
  144. data/ext/libsass/src/sass_util.hpp +0 -256
  145. data/ext/libsass/src/subset_map.cpp +0 -58
  146. data/ext/libsass/src/subset_map.hpp +0 -76
  147. data/lib/sassc/native/lib_c.rb +0 -21
@@ -1,54 +1,26 @@
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
 
22
11
  /////////////////////////////////////////////////////////////////////////
23
12
  /////////////////////////////////////////////////////////////////////////
24
13
 
25
- Selector::Selector(ParserState pstate)
14
+ Selector::Selector(SourceSpan 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
  {
@@ -58,18 +30,16 @@ namespace Sass {
58
30
  /////////////////////////////////////////////////////////////////////////
59
31
  /////////////////////////////////////////////////////////////////////////
60
32
 
61
- Selector_Schema::Selector_Schema(ParserState pstate, String_Obj c)
33
+ Selector_Schema::Selector_Schema(SourceSpan pstate, String_Obj c)
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,181 +55,150 @@ 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(SourceSpan pstate, sass::string n)
112
73
  : Selector(pstate), ns_(""), name_(n), has_ns_(false)
113
74
  {
114
75
  size_t pos = n.find('|');
115
76
  // found some namespace
116
- if (pos != std::string::npos) {
77
+ if (pos != sass::string::npos) {
117
78
  has_ns_ = true;
118
79
  ns_ = n.substr(0, pos);
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
+ sass::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
- Placeholder_Selector::Placeholder_Selector(ParserState pstate, std::string n)
239
- : Simple_Selector(pstate, n)
177
+ PlaceholderSelector::PlaceholderSelector(SourceSpan pstate, sass::string n)
178
+ : SimpleSelector(pstate, n)
240
179
  { simple_type(PLACEHOLDER_SEL); }
241
- Placeholder_Selector::Placeholder_Selector(const Placeholder_Selector* ptr)
242
- : Simple_Selector(ptr)
180
+ PlaceholderSelector::PlaceholderSelector(const PlaceholderSelector* ptr)
181
+ : SimpleSelector(ptr)
243
182
  { simple_type(PLACEHOLDER_SEL); }
244
- unsigned long Placeholder_Selector::specificity() const
183
+ unsigned long PlaceholderSelector::specificity() const
245
184
  {
246
185
  return Constants::Specificity_Base;
247
186
  }
248
- bool Placeholder_Selector::has_placeholder() {
187
+ bool PlaceholderSelector::has_placeholder() {
249
188
  return true;
250
189
  }
251
190
 
252
191
  /////////////////////////////////////////////////////////////////////////
253
192
  /////////////////////////////////////////////////////////////////////////
254
193
 
255
- Type_Selector::Type_Selector(ParserState pstate, std::string n)
256
- : Simple_Selector(pstate, n)
194
+ TypeSelector::TypeSelector(SourceSpan pstate, sass::string n)
195
+ : SimpleSelector(pstate, n)
257
196
  { simple_type(TYPE_SEL); }
258
- Type_Selector::Type_Selector(const Type_Selector* ptr)
259
- : Simple_Selector(ptr)
197
+ TypeSelector::TypeSelector(const TypeSelector* ptr)
198
+ : SimpleSelector(ptr)
260
199
  { simple_type(TYPE_SEL); }
261
200
 
262
- unsigned long Type_Selector::specificity() const
201
+ unsigned long TypeSelector::specificity() const
263
202
  {
264
203
  if (name() == "*") return 0;
265
204
  else return Constants::Specificity_Element;
@@ -268,14 +207,14 @@ namespace Sass {
268
207
  /////////////////////////////////////////////////////////////////////////
269
208
  /////////////////////////////////////////////////////////////////////////
270
209
 
271
- Class_Selector::Class_Selector(ParserState pstate, std::string n)
272
- : Simple_Selector(pstate, n)
210
+ ClassSelector::ClassSelector(SourceSpan pstate, sass::string n)
211
+ : SimpleSelector(pstate, n)
273
212
  { simple_type(CLASS_SEL); }
274
- Class_Selector::Class_Selector(const Class_Selector* ptr)
275
- : Simple_Selector(ptr)
213
+ ClassSelector::ClassSelector(const ClassSelector* ptr)
214
+ : SimpleSelector(ptr)
276
215
  { simple_type(CLASS_SEL); }
277
216
 
278
- unsigned long Class_Selector::specificity() const
217
+ unsigned long ClassSelector::specificity() const
279
218
  {
280
219
  return Constants::Specificity_Class;
281
220
  }
@@ -283,14 +222,14 @@ namespace Sass {
283
222
  /////////////////////////////////////////////////////////////////////////
284
223
  /////////////////////////////////////////////////////////////////////////
285
224
 
286
- Id_Selector::Id_Selector(ParserState pstate, std::string n)
287
- : Simple_Selector(pstate, n)
225
+ IDSelector::IDSelector(SourceSpan pstate, sass::string n)
226
+ : SimpleSelector(pstate, n)
288
227
  { simple_type(ID_SEL); }
289
- Id_Selector::Id_Selector(const Id_Selector* ptr)
290
- : Simple_Selector(ptr)
228
+ IDSelector::IDSelector(const IDSelector* ptr)
229
+ : SimpleSelector(ptr)
291
230
  { simple_type(ID_SEL); }
292
231
 
293
- unsigned long Id_Selector::specificity() const
232
+ unsigned long IDSelector::specificity() const
294
233
  {
295
234
  return Constants::Specificity_ID;
296
235
  }
@@ -298,27 +237,27 @@ namespace Sass {
298
237
  /////////////////////////////////////////////////////////////////////////
299
238
  /////////////////////////////////////////////////////////////////////////
300
239
 
301
- Attribute_Selector::Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o)
302
- : Simple_Selector(pstate, n), matcher_(m), value_(v), modifier_(o)
240
+ AttributeSelector::AttributeSelector(SourceSpan pstate, sass::string n, sass::string m, String_Obj v, char o)
241
+ : SimpleSelector(pstate, n), matcher_(m), value_(v), modifier_(o)
303
242
  { simple_type(ATTRIBUTE_SEL); }
304
- Attribute_Selector::Attribute_Selector(const Attribute_Selector* ptr)
305
- : Simple_Selector(ptr),
243
+ AttributeSelector::AttributeSelector(const AttributeSelector* ptr)
244
+ : SimpleSelector(ptr),
306
245
  matcher_(ptr->matcher_),
307
246
  value_(ptr->value_),
308
247
  modifier_(ptr->modifier_)
309
248
  { simple_type(ATTRIBUTE_SEL); }
310
249
 
311
- size_t Attribute_Selector::hash() const
250
+ size_t AttributeSelector::hash() const
312
251
  {
313
252
  if (hash_ == 0) {
314
- hash_combine(hash_, Simple_Selector::hash());
315
- hash_combine(hash_, std::hash<std::string>()(matcher()));
253
+ hash_combine(hash_, SimpleSelector::hash());
254
+ hash_combine(hash_, std::hash<sass::string>()(matcher()));
316
255
  if (value_) hash_combine(hash_, value_->hash());
317
256
  }
318
257
  return hash_;
319
258
  }
320
259
 
321
- unsigned long Attribute_Selector::specificity() const
260
+ unsigned long AttributeSelector::specificity() const
322
261
  {
323
262
  return Constants::Specificity_Attr;
324
263
  }
@@ -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
+ PseudoSelector::PseudoSelector(SourceSpan pstate, sass::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
- Pseudo_Selector::Pseudo_Selector(const Pseudo_Selector* ptr)
333
- : Simple_Selector(ptr), expression_(ptr->expression_)
276
+ PseudoSelector::PseudoSelector(const PseudoSelector* ptr)
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.
@@ -341,1135 +290,754 @@ namespace Sass {
341
290
  // in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
342
291
  // :after). This compatibility is not allowed for the new pseudo-elements
343
292
  // introduced in this specification.
344
- bool Pseudo_Selector::is_pseudo_element() const
293
+ bool PseudoSelector::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
- size_t Pseudo_Selector::hash() const
298
+ size_t PseudoSelector::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
  }
358
307
 
359
- unsigned long Pseudo_Selector::specificity() const
308
+ unsigned long PseudoSelector::specificity() const
360
309
  {
361
310
  if (is_pseudo_element())
362
311
  return Constants::Specificity_Element;
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
+ PseudoSelectorObj PseudoSelector::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
+ PseudoSelectorObj 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 PseudoSelector::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 PseudoSelector::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 PseudoSelector::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(SourceSpan 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(SourceSpan 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(SourceSpan 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(SourceSpan 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(SourceSpan 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<TypeSelector>(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, sass::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(SourceSpan pstate, Block_Obj block) :
604
+ ParentStatement(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
+ ParentStatement(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(SourceSpan pstate, Block_Obj block) :
621
+ ParentStatement(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
+ ParentStatement(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(SourceSpan 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
+ sass::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
+ sass::string theirType = other->type();
660
+ Util::ascii_str_tolower(&theirType);
1026
661
 
1027
- if (head && head->length() > 0) {
662
+ sass::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
+ sass::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
+ sass::string type;
669
+ sass::string modifier;
670
+ sass::vector<sass::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
+ sass::vector<sass::string> f1(this->features());
675
+ sass::vector<sass::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
+ sass::vector<sass::string> negativeFeatures =
685
+ ourModifier == "not" ? this->features() : other->features();
686
+ sass::vector<sass::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
+ sass::vector<sass::string> f1(this->features());
751
+ sass::vector<sass::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
+ sass::vector<sass::string> f1(this->features());
759
+ sass::vector<sass::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
+ sass::vector<sass::string> f1(this->features());
770
+ sass::vector<sass::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
+ sass::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
+ sass::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 (PseudoSelector * pseudo = Cast<PseudoSelector>(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<TypeSelector>(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
928
 
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;
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);
1344
937
  }
1345
- return false;
1346
- }
1347
938
 
1348
- void Selector_List::adjust_after_pushing(Complex_Selector_Obj c)
1349
- {
1350
- // if (c->has_reference()) has_reference(true);
1351
- }
939
+ return rv;
1352
940
 
1353
- // it's a superselector if every selector of the right side
1354
- // list is a superselector of the given left side selector
1355
- bool Selector_List::is_superselector_of(const Selector_List* sub, std::string wrapping) const
1356
- {
1357
- // Check every rhs selector against left hand list
1358
- for(size_t i = 0, L = sub->length(); i < L; ++i) {
1359
- if (!is_superselector_of((*sub)[i], wrapping)) return false;
1360
- }
1361
- return true;
1362
941
  }
1363
942
 
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
943
+ bool cmpSimpleSelectors(SimpleSelector* a, SimpleSelector* b)
1367
944
  {
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;
945
+ return (a->getSortOrder() < b->getSortOrder());
1373
946
  }
1374
947
 
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
948
+ void CompoundSelector::sortChildren()
1378
949
  {
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;
950
+ std::sort(begin(), end(), cmpSimpleSelectors);
1384
951
  }
1385
952
 
1386
- void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
953
+ /* better return sass::vector? only - is empty container anyway? */
954
+ SelectorList* ComplexSelector::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
1387
955
  {
1388
956
 
1389
- Selector_List* extender = this;
1390
- for (auto complex_sel : extendee->elements()) {
1391
- Complex_Selector_Obj c = complex_sel;
957
+ sass::vector<sass::vector<ComplexSelectorObj>> vars;
1392
958
 
959
+ auto parent = pstack.back();
1393
960
 
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
- }
961
+ if (has_real_parent_ref() && !parent) {
962
+ throw Exception::TopLevelParent(traces, pstate());
963
+ }
1403
964
 
1404
- pIter = pIter->tail();
1405
- }
965
+ if (!chroots() && parent) {
1406
966
 
1407
- if (!pIter->head() || pIter->tail()) {
1408
- coreError("nested selectors may not be extended", c->pstate());
967
+ if (!has_real_parent_ref() && !implicit_parent) {
968
+ SelectorList* retval = SASS_MEMORY_NEW(SelectorList, pstate(), 1);
969
+ retval->append(this);
970
+ return retval;
1409
971
  }
1410
972
 
1411
- compound_sel->is_optional(extendee->is_optional());
973
+ vars.push_back(parent->elements());
974
+ }
1412
975
 
1413
- for (size_t i = 0, L = extender->length(); i < L; ++i) {
1414
- extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
976
+ for (auto sel : elements()) {
977
+ if (CompoundSelectorObj comp = Cast<CompoundSelector>(sel)) {
978
+ auto asd = comp->resolve_parent_refs(pstack, traces, implicit_parent);
979
+ if (asd.size() > 0) vars.push_back(asd);
980
+ }
981
+ else {
982
+ // ToDo: merge together sequences whenever possible
983
+ auto cont = SASS_MEMORY_NEW(ComplexSelector, pstate());
984
+ cont->append(sel);
985
+ vars.push_back({ cont });
1415
986
  }
1416
987
  }
1417
- };
1418
988
 
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());
989
+ // Need complex selectors to preserve linefeeds
990
+ sass::vector<sass::vector<ComplexSelectorObj>> res = permutateAlt(vars);
991
+
992
+ // std::reverse(std::begin(res), std::end(res));
993
+
994
+ auto lst = SASS_MEMORY_NEW(SelectorList, pstate());
995
+ for (auto items : res) {
996
+ if (items.size() > 0) {
997
+ ComplexSelectorObj first = SASS_MEMORY_COPY(items[0]);
998
+ first->hasPreLineFeed(first->hasPreLineFeed() || (!has_real_parent_ref() && hasPreLineFeed()));
999
+ // ToDo: remove once we know how to handle line feeds
1000
+ // ToDo: currently a mashup between ruby and dart sass
1001
+ // if (has_real_parent_ref()) first->has_line_feed(false);
1002
+ // first->has_line_break(first->has_line_break() || has_line_break());
1003
+ first->chroots(true); // has been resolved by now
1004
+ for (size_t i = 1; i < items.size(); i += 1) {
1005
+ first->concat(items[i]);
1006
+ }
1007
+ lst->append(first);
1426
1008
  }
1427
1009
  }
1428
- return Selector::hash_;
1429
- }
1430
1010
 
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
- }
1011
+ return lst;
1442
1012
 
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
1013
  }
1450
1014
 
1451
- bool Selector_List::has_placeholder()
1015
+ SelectorList* SelectorList::resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent)
1452
1016
  {
1453
- for (Complex_Selector_Obj cs : elements()) {
1454
- if (cs->has_placeholder()) return true;
1017
+ SelectorList* rv = SASS_MEMORY_NEW(SelectorList, pstate());
1018
+ for (auto sel : elements()) {
1019
+ // Note: this one is tricky as we get back a pointer from resolve parents ...
1020
+ SelectorListObj res = sel->resolve_parent_refs(pstack, traces, implicit_parent);
1021
+ // Note: ... and concat will only append the items in elements
1022
+ // Therefore by passing it directly, the container will leak!
1023
+ rv->concat(res);
1455
1024
  }
1456
- return false;
1025
+ return rv;
1457
1026
  }
1458
1027
 
1459
1028
  /////////////////////////////////////////////////////////////////////////
1460
1029
  /////////////////////////////////////////////////////////////////////////
1461
1030
 
1462
1031
  IMPLEMENT_AST_OPERATORS(Selector_Schema);
1463
- IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
1464
- IMPLEMENT_AST_OPERATORS(Parent_Selector);
1465
- IMPLEMENT_AST_OPERATORS(Attribute_Selector);
1466
- IMPLEMENT_AST_OPERATORS(Compound_Selector);
1467
- IMPLEMENT_AST_OPERATORS(Complex_Selector);
1468
- IMPLEMENT_AST_OPERATORS(Type_Selector);
1469
- IMPLEMENT_AST_OPERATORS(Class_Selector);
1470
- IMPLEMENT_AST_OPERATORS(Id_Selector);
1471
- IMPLEMENT_AST_OPERATORS(Pseudo_Selector);
1472
- IMPLEMENT_AST_OPERATORS(Wrapped_Selector);
1473
- IMPLEMENT_AST_OPERATORS(Selector_List);
1032
+ IMPLEMENT_AST_OPERATORS(PlaceholderSelector);
1033
+ IMPLEMENT_AST_OPERATORS(AttributeSelector);
1034
+ IMPLEMENT_AST_OPERATORS(TypeSelector);
1035
+ IMPLEMENT_AST_OPERATORS(ClassSelector);
1036
+ IMPLEMENT_AST_OPERATORS(IDSelector);
1037
+ IMPLEMENT_AST_OPERATORS(PseudoSelector);
1038
+ IMPLEMENT_AST_OPERATORS(SelectorCombinator);
1039
+ IMPLEMENT_AST_OPERATORS(CompoundSelector);
1040
+ IMPLEMENT_AST_OPERATORS(ComplexSelector);
1041
+ IMPLEMENT_AST_OPERATORS(SelectorList);
1474
1042
 
1475
1043
  }