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
@@ -4,68 +4,57 @@
4
4
  // sass.hpp must go before all system headers to get the
5
5
  // __EXTENSIONS__ fix on Solaris.
6
6
  #include "sass.hpp"
7
-
8
- #include <set>
9
- #include <deque>
10
- #include <vector>
11
- #include <string>
12
- #include <sstream>
13
- #include <iostream>
14
- #include <typeinfo>
15
- #include <algorithm>
16
- #include "sass/base.h"
17
- #include "ast_fwd_decl.hpp"
18
-
19
- #include "util.hpp"
20
- #include "units.hpp"
21
- #include "context.hpp"
22
- #include "position.hpp"
23
- #include "constants.hpp"
24
- #include "operation.hpp"
25
- #include "position.hpp"
26
- #include "inspect.hpp"
27
- #include "source_map.hpp"
28
- #include "environment.hpp"
29
- #include "error_handling.hpp"
30
- #include "ast_def_macros.hpp"
31
- #include "ast_fwd_decl.hpp"
32
- #include "source_map.hpp"
33
- #include "fn_utils.hpp"
34
-
35
- #include "sass.h"
7
+ #include "ast.hpp"
36
8
 
37
9
  namespace Sass {
38
10
 
11
+ /////////////////////////////////////////////////////////////////////////
12
+ // Some helper functions
13
+ /////////////////////////////////////////////////////////////////////////
14
+
15
+ bool compoundIsSuperselector(
16
+ const CompoundSelectorObj& compound1,
17
+ const CompoundSelectorObj& compound2,
18
+ const std::vector<SelectorComponentObj>& parents);
19
+
20
+ bool complexIsParentSuperselector(
21
+ const std::vector<SelectorComponentObj>& complex1,
22
+ const std::vector<SelectorComponentObj>& complex2);
23
+
24
+ std::vector<std::vector<SelectorComponentObj>> weave(
25
+ const std::vector<std::vector<SelectorComponentObj>>& complexes);
26
+
27
+ std::vector<std::vector<SelectorComponentObj>> weaveParents(
28
+ std::vector<SelectorComponentObj> parents1,
29
+ std::vector<SelectorComponentObj> parents2);
30
+
31
+ std::vector<SimpleSelectorObj> unifyCompound(
32
+ const std::vector<SimpleSelectorObj>& compound1,
33
+ const std::vector<SimpleSelectorObj>& compound2);
34
+
35
+ std::vector<std::vector<SelectorComponentObj>> unifyComplex(
36
+ const std::vector<std::vector<SelectorComponentObj>>& complexes);
37
+
39
38
  /////////////////////////////////////////
40
39
  // Abstract base class for CSS selectors.
41
40
  /////////////////////////////////////////
42
41
  class Selector : public Expression {
43
- // line break before list separator
44
- ADD_PROPERTY(bool, has_line_feed)
45
- // line break after list separator
46
- ADD_PROPERTY(bool, has_line_break)
47
- // maybe we have optional flag
48
- ADD_PROPERTY(bool, is_optional)
49
- // must not be a reference counted object
50
- // otherwise we create circular references
51
- ADD_PROPERTY(Media_Block*, media_block)
52
42
  protected:
53
43
  mutable size_t hash_;
54
44
  public:
55
45
  Selector(ParserState pstate);
56
46
  virtual ~Selector() = 0;
57
47
  size_t hash() const override = 0;
58
- virtual unsigned long specificity() const = 0;
59
- virtual int unification_order() const = 0;
60
- virtual void set_media_block(Media_Block* mb);
61
- virtual bool has_parent_ref() const;
62
48
  virtual bool has_real_parent_ref() const;
49
+ // you should reset this to null on containers
50
+ virtual unsigned long specificity() const = 0;
51
+ // by default we return the regular specificity
52
+ // you must override this for all containers
53
+ virtual size_t maxSpecificity() const { return specificity(); }
54
+ virtual size_t minSpecificity() const { return specificity(); }
63
55
  // dispatch to correct handlers
64
- virtual bool operator<(const Selector& rhs) const = 0;
65
- virtual bool operator==(const Selector& rhs) const = 0;
66
- bool operator>(const Selector& rhs) const { return rhs < *this; };
67
- bool operator!=(const Selector& rhs) const { return !(rhs == *this); };
68
- ATTACH_VIRTUAL_AST_OPERATIONS(Selector);
56
+ ATTACH_VIRTUAL_CMP_OPERATIONS(Selector)
57
+ ATTACH_VIRTUAL_AST_OPERATIONS(Selector)
69
58
  };
70
59
  inline Selector::~Selector() { }
71
60
 
@@ -74,19 +63,14 @@ namespace Sass {
74
63
  // re-parsed into a normal selector class.
75
64
  /////////////////////////////////////////////////////////////////////////
76
65
  class Selector_Schema final : public AST_Node {
77
- ADD_PROPERTY(String_Obj, contents)
66
+ ADD_PROPERTY(String_Schema_Obj, contents)
78
67
  ADD_PROPERTY(bool, connect_parent);
79
- // must not be a reference counted object
80
- // otherwise we create circular references
81
- ADD_PROPERTY(Media_Block*, media_block)
82
68
  // store computed hash
83
69
  mutable size_t hash_;
84
70
  public:
85
71
  Selector_Schema(ParserState pstate, String_Obj c);
86
- bool has_parent_ref() const;
72
+
87
73
  bool has_real_parent_ref() const;
88
- bool operator<(const Selector& rhs) const;
89
- bool operator==(const Selector& rhs) const;
90
74
  // selector schema is not yet a final selector, so we do not
91
75
  // have a specificity for it yet. We need to
92
76
  virtual unsigned long specificity() const;
@@ -98,15 +82,13 @@ namespace Sass {
98
82
  ////////////////////////////////////////////
99
83
  // Abstract base class for simple selectors.
100
84
  ////////////////////////////////////////////
101
- class Simple_Selector : public Selector {
85
+ class SimpleSelector : public Selector {
102
86
  public:
103
87
  enum Simple_Type {
104
88
  ID_SEL,
105
89
  TYPE_SEL,
106
90
  CLASS_SEL,
107
91
  PSEUDO_SEL,
108
- PARENT_SEL,
109
- WRAPPED_SEL,
110
92
  ATTRIBUTE_SEL,
111
93
  PLACEHOLDER_SEL,
112
94
  };
@@ -116,12 +98,12 @@ namespace Sass {
116
98
  ADD_PROPERTY(Simple_Type, simple_type)
117
99
  HASH_PROPERTY(bool, has_ns)
118
100
  public:
119
- Simple_Selector(ParserState pstate, std::string n = "");
101
+ SimpleSelector(ParserState pstate, std::string n = "");
120
102
  virtual std::string ns_name() const;
121
103
  size_t hash() const override;
122
- bool empty() const;
104
+ virtual bool empty() const;
123
105
  // namespace compare functions
124
- bool is_ns_eq(const Simple_Selector& r) const;
106
+ bool is_ns_eq(const SimpleSelector& r) const;
125
107
  // namespace query functions
126
108
  bool is_universal_ns() const;
127
109
  bool is_empty_ns() const;
@@ -131,81 +113,45 @@ namespace Sass {
131
113
  bool is_universal() const;
132
114
  virtual bool has_placeholder();
133
115
 
134
- virtual ~Simple_Selector() = 0;
135
- virtual Compound_Selector* unify_with(Compound_Selector*);
116
+ virtual ~SimpleSelector() = 0;
117
+ virtual CompoundSelector* unifyWith(CompoundSelector*);
136
118
 
137
- virtual bool has_parent_ref() const override;
138
- virtual bool has_real_parent_ref() const override;
119
+ /* helper function for syntax sugar */
120
+ virtual Id_Selector* getIdSelector() { return NULL; }
121
+ virtual Type_Selector* getTypeSelector() { return NULL; }
122
+ virtual Pseudo_Selector* getPseudoSelector() { return NULL; }
123
+
124
+ ComplexSelectorObj wrapInComplex();
125
+ CompoundSelectorObj wrapInCompound();
126
+
127
+ virtual bool isInvisible() const { return false; }
139
128
  virtual bool is_pseudo_element() const;
140
- virtual bool is_superselector_of(const Compound_Selector* sub) const;
129
+ virtual bool has_real_parent_ref() const override;
141
130
 
142
- bool operator<(const Selector& rhs) const final override;
143
131
  bool operator==(const Selector& rhs) const final override;
144
- virtual bool operator<(const Selector_List& rhs) const;
145
- virtual bool operator==(const Selector_List& rhs) const;
146
- virtual bool operator<(const Complex_Selector& rhs) const;
147
- virtual bool operator==(const Complex_Selector& rhs) const;
148
- virtual bool operator<(const Compound_Selector& rhs) const;
149
- virtual bool operator==(const Compound_Selector& rhs) const;
150
- virtual bool operator<(const Simple_Selector& rhs) const;
151
- virtual bool operator==(const Simple_Selector& rhs) const;
152
-
153
- ATTACH_VIRTUAL_AST_OPERATIONS(Simple_Selector);
154
- ATTACH_CRTP_PERFORM_METHODS();
155
132
 
156
- };
157
- inline Simple_Selector::~Simple_Selector() { }
158
-
159
- //////////////////////////////////
160
- // The Parent Selector Expression.
161
- //////////////////////////////////
162
- class Parent_Selector final : public Simple_Selector {
163
- // a real parent selector is given by the user
164
- // others are added implicitly to connect the
165
- // selector scopes automatically when rendered
166
- // a Parent_Reference is never seen in selectors
167
- // and is only used in values (e.g. `prop: #{&};`)
168
- ADD_PROPERTY(bool, real)
169
- public:
170
- Parent_Selector(ParserState pstate, bool r = true);
133
+ virtual bool operator==(const SelectorList& rhs) const;
134
+ virtual bool operator==(const ComplexSelector& rhs) const;
135
+ virtual bool operator==(const CompoundSelector& rhs) const;
171
136
 
172
- virtual bool has_parent_ref() const override;
173
- virtual bool has_real_parent_ref() const override;
137
+ ATTACH_VIRTUAL_CMP_OPERATIONS(SimpleSelector);
138
+ ATTACH_VIRTUAL_AST_OPERATIONS(SimpleSelector);
139
+ ATTACH_CRTP_PERFORM_METHODS();
174
140
 
175
- virtual unsigned long specificity() const override;
176
- int unification_order() const override
177
- {
178
- throw std::runtime_error("unification_order for Parent_Selector is undefined");
179
- }
180
- std::string type() const override { return "selector"; }
181
- static std::string type_name() { return "selector"; }
182
- bool operator<(const Simple_Selector& rhs) const final override;
183
- bool operator==(const Simple_Selector& rhs) const final override;
184
- bool operator<(const Parent_Selector& rhs) const;
185
- bool operator==(const Parent_Selector& rhs) const;
186
- ATTACH_AST_OPERATIONS(Parent_Selector)
187
- ATTACH_CRTP_PERFORM_METHODS()
188
141
  };
189
-
142
+ inline SimpleSelector::~SimpleSelector() { }
190
143
 
191
144
  /////////////////////////////////////////////////////////////////////////
192
145
  // Placeholder selectors (e.g., "%foo") for use in extend-only selectors.
193
146
  /////////////////////////////////////////////////////////////////////////
194
- class Placeholder_Selector final : public Simple_Selector {
147
+ class Placeholder_Selector final : public SimpleSelector {
195
148
  public:
196
149
  Placeholder_Selector(ParserState pstate, std::string n);
197
-
198
- int unification_order() const override
199
- {
200
- return Constants::UnificationOrder_Placeholder;
201
- }
202
- virtual ~Placeholder_Selector() {};
150
+ bool isInvisible() const override { return true; }
203
151
  virtual unsigned long specificity() const override;
204
152
  virtual bool has_placeholder() override;
205
- bool operator<(const Simple_Selector& rhs) const override;
206
- bool operator==(const Simple_Selector& rhs) const override;
207
- bool operator<(const Placeholder_Selector& rhs) const;
208
- bool operator==(const Placeholder_Selector& rhs) const;
153
+ bool operator==(const SimpleSelector& rhs) const override;
154
+ ATTACH_CMP_OPERATIONS(Placeholder_Selector)
209
155
  ATTACH_AST_OPERATIONS(Placeholder_Selector)
210
156
  ATTACH_CRTP_PERFORM_METHODS()
211
157
  };
@@ -213,20 +159,15 @@ namespace Sass {
213
159
  /////////////////////////////////////////////////////////////////////
214
160
  // Type selectors (and the universal selector) -- e.g., div, span, *.
215
161
  /////////////////////////////////////////////////////////////////////
216
- class Type_Selector final : public Simple_Selector {
162
+ class Type_Selector final : public SimpleSelector {
217
163
  public:
218
164
  Type_Selector(ParserState pstate, std::string n);
219
165
  virtual unsigned long specificity() const override;
220
- int unification_order() const override
221
- {
222
- return Constants::UnificationOrder_Element;
223
- }
224
- Simple_Selector* unify_with(Simple_Selector*);
225
- Compound_Selector* unify_with(Compound_Selector*) override;
226
- bool operator<(const Simple_Selector& rhs) const final override;
227
- bool operator==(const Simple_Selector& rhs) const final override;
228
- bool operator<(const Type_Selector& rhs) const;
229
- bool operator==(const Type_Selector& rhs) const;
166
+ SimpleSelector* unifyWith(const SimpleSelector*);
167
+ CompoundSelector* unifyWith(CompoundSelector*) override;
168
+ Type_Selector* getTypeSelector() override { return this; }
169
+ bool operator==(const SimpleSelector& rhs) const final override;
170
+ ATTACH_CMP_OPERATIONS(Type_Selector)
230
171
  ATTACH_AST_OPERATIONS(Type_Selector)
231
172
  ATTACH_CRTP_PERFORM_METHODS()
232
173
  };
@@ -234,19 +175,12 @@ namespace Sass {
234
175
  ////////////////////////////////////////////////
235
176
  // Class selectors -- i.e., .foo.
236
177
  ////////////////////////////////////////////////
237
- class Class_Selector final : public Simple_Selector {
178
+ class Class_Selector final : public SimpleSelector {
238
179
  public:
239
180
  Class_Selector(ParserState pstate, std::string n);
240
181
  virtual unsigned long specificity() const override;
241
- int unification_order() const override
242
- {
243
- return Constants::UnificationOrder_Class;
244
- }
245
- Compound_Selector* unify_with(Compound_Selector*) override;
246
- bool operator<(const Simple_Selector& rhs) const final override;
247
- bool operator==(const Simple_Selector& rhs) const final override;
248
- bool operator<(const Class_Selector& rhs) const;
249
- bool operator==(const Class_Selector& rhs) const;
182
+ bool operator==(const SimpleSelector& rhs) const final override;
183
+ ATTACH_CMP_OPERATIONS(Class_Selector)
250
184
  ATTACH_AST_OPERATIONS(Class_Selector)
251
185
  ATTACH_CRTP_PERFORM_METHODS()
252
186
  };
@@ -254,19 +188,14 @@ namespace Sass {
254
188
  ////////////////////////////////////////////////
255
189
  // ID selectors -- i.e., #foo.
256
190
  ////////////////////////////////////////////////
257
- class Id_Selector final : public Simple_Selector {
191
+ class Id_Selector final : public SimpleSelector {
258
192
  public:
259
193
  Id_Selector(ParserState pstate, std::string n);
260
194
  virtual unsigned long specificity() const override;
261
- int unification_order() const override
262
- {
263
- return Constants::UnificationOrder_Id;
264
- }
265
- Compound_Selector* unify_with(Compound_Selector*) override;
266
- bool operator<(const Simple_Selector& rhs) const final override;
267
- bool operator==(const Simple_Selector& rhs) const final override;
268
- bool operator<(const Id_Selector& rhs) const;
269
- bool operator==(const Id_Selector& rhs) const;
195
+ CompoundSelector* unifyWith(CompoundSelector*) override;
196
+ Id_Selector* getIdSelector() final override { return this; }
197
+ bool operator==(const SimpleSelector& rhs) const final override;
198
+ ATTACH_CMP_OPERATIONS(Id_Selector)
270
199
  ATTACH_AST_OPERATIONS(Id_Selector)
271
200
  ATTACH_CRTP_PERFORM_METHODS()
272
201
  };
@@ -274,7 +203,7 @@ namespace Sass {
274
203
  ///////////////////////////////////////////////////
275
204
  // Attribute selectors -- e.g., [src*=".jpg"], etc.
276
205
  ///////////////////////////////////////////////////
277
- class Attribute_Selector final : public Simple_Selector {
206
+ class Attribute_Selector final : public SimpleSelector {
278
207
  ADD_CONSTREF(std::string, matcher)
279
208
  // this cannot be changed to obj atm!!!!!!????!!!!!!!
280
209
  ADD_PROPERTY(String_Obj, value) // might be interpolated
@@ -283,14 +212,8 @@ namespace Sass {
283
212
  Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o = 0);
284
213
  size_t hash() const override;
285
214
  virtual unsigned long specificity() const override;
286
- int unification_order() const override
287
- {
288
- return Constants::UnificationOrder_Attribute;
289
- }
290
- bool operator<(const Simple_Selector& rhs) const final override;
291
- bool operator==(const Simple_Selector& rhs) const final override;
292
- bool operator<(const Attribute_Selector& rhs) const;
293
- bool operator==(const Attribute_Selector& rhs) const;
215
+ bool operator==(const SimpleSelector& rhs) const final override;
216
+ ATTACH_CMP_OPERATIONS(Attribute_Selector)
294
217
  ATTACH_AST_OPERATIONS(Attribute_Selector)
295
218
  ATTACH_CRTP_PERFORM_METHODS()
296
219
  };
@@ -298,270 +221,291 @@ namespace Sass {
298
221
  //////////////////////////////////////////////////////////////////
299
222
  // Pseudo selectors -- e.g., :first-child, :nth-of-type(...), etc.
300
223
  //////////////////////////////////////////////////////////////////
301
- /* '::' starts a pseudo-element, ':' a pseudo-class */
302
- /* Except :first-line, :first-letter, :before and :after */
303
- /* Note that pseudo-elements are restricted to one per selector */
304
- /* and occur only in the last simple_selector_sequence. */
305
- inline bool is_pseudo_class_element(const std::string& name)
306
- {
307
- return name == ":before" ||
308
- name == ":after" ||
309
- name == ":first-line" ||
310
- name == ":first-letter";
311
- }
312
-
313
224
  // Pseudo Selector cannot have any namespace?
314
- class Pseudo_Selector final : public Simple_Selector {
315
- ADD_PROPERTY(String_Obj, expression)
225
+ class Pseudo_Selector final : public SimpleSelector {
226
+ ADD_PROPERTY(std::string, normalized)
227
+ ADD_PROPERTY(String_Obj, argument)
228
+ ADD_PROPERTY(SelectorListObj, selector)
229
+ ADD_PROPERTY(bool, isSyntacticClass)
230
+ ADD_PROPERTY(bool, isClass)
316
231
  public:
317
- Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr = {});
232
+ Pseudo_Selector(ParserState pstate, std::string n, bool element = false);
318
233
  virtual bool is_pseudo_element() const override;
319
234
  size_t hash() const override;
235
+
236
+ bool empty() const override;
237
+
238
+ bool has_real_parent_ref() const override;
239
+
240
+ // Whether this is a pseudo-element selector.
241
+ // This is `true` if and only if [isClass] is `false`.
242
+ bool isElement() const { return !isClass(); }
243
+
244
+ // Whether this is syntactically a pseudo-element selector.
245
+ // This is `true` if and only if [isSyntacticClass] is `false`.
246
+ bool isSyntacticElement() const { return !isSyntacticClass(); }
247
+
320
248
  virtual unsigned long specificity() const override;
321
- int unification_order() const override
322
- {
323
- if (is_pseudo_element())
324
- return Constants::UnificationOrder_PseudoElement;
325
- return Constants::UnificationOrder_PseudoClass;
326
- }
327
- bool operator<(const Simple_Selector& rhs) const final override;
328
- bool operator==(const Simple_Selector& rhs) const final override;
329
- bool operator<(const Pseudo_Selector& rhs) const;
330
- bool operator==(const Pseudo_Selector& rhs) const;
331
- Compound_Selector* unify_with(Compound_Selector*) override;
249
+ Pseudo_Selector_Obj withSelector(SelectorListObj selector);
250
+
251
+ CompoundSelector* unifyWith(CompoundSelector*) override;
252
+ Pseudo_Selector* getPseudoSelector() final override { return this; }
253
+ bool operator==(const SimpleSelector& rhs) const final override;
254
+ ATTACH_CMP_OPERATIONS(Pseudo_Selector)
332
255
  ATTACH_AST_OPERATIONS(Pseudo_Selector)
256
+ void cloneChildren() override;
333
257
  ATTACH_CRTP_PERFORM_METHODS()
334
258
  };
335
259
 
336
- /////////////////////////////////////////////////
337
- // Wrapped selector -- pseudo selector that takes a list of selectors as argument(s) e.g., :not(:first-of-type), :-moz-any(ol p.blah, ul, menu, dir)
338
- /////////////////////////////////////////////////
339
- class Wrapped_Selector final : public Simple_Selector {
340
- ADD_PROPERTY(Selector_List_Obj, selector)
260
+
261
+ ////////////////////////////////////////////////////////////////////////////
262
+ // Complex Selectors are the most important class of selectors.
263
+ // A Selector List consists of Complex Selectors (separated by comma)
264
+ // Complex Selectors are itself a list of Compounds and Combinators
265
+ // Between each item there is an implicit ancestor of combinator
266
+ ////////////////////////////////////////////////////////////////////////////
267
+ class ComplexSelector final : public Selector, public Vectorized<SelectorComponentObj> {
268
+ ADD_PROPERTY(bool, chroots)
269
+ // line break before list separator
270
+ ADD_PROPERTY(bool, hasPreLineFeed)
341
271
  public:
342
- Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel);
343
- using Simple_Selector::is_superselector_of;
344
- bool is_superselector_of(const Wrapped_Selector* sub) const;
345
- // Selectors inside the negation pseudo-class are counted like any
346
- // other, but the negation itself does not count as a pseudo-class.
272
+ ComplexSelector(ParserState pstate);
273
+
274
+ // Returns true if the first components
275
+ // is a compound selector and fullfills
276
+ // a few other criteria.
277
+ bool isInvisible() const;
278
+
347
279
  size_t hash() const override;
348
- bool has_parent_ref() const override;
349
- bool has_real_parent_ref() const override;
350
- unsigned long specificity() const override;
351
- int unification_order() const override
352
- {
353
- return Constants::UnificationOrder_Wrapped;
354
- }
355
- bool find ( bool (*f)(AST_Node_Obj) ) override;
356
- bool operator<(const Simple_Selector& rhs) const final override;
357
- bool operator==(const Simple_Selector& rhs) const final override;
358
- bool operator<(const Wrapped_Selector& rhs) const;
359
- bool operator==(const Wrapped_Selector& rhs) const;
360
280
  void cloneChildren() override;
361
- ATTACH_AST_OPERATIONS(Wrapped_Selector)
281
+ bool has_placeholder() const;
282
+ bool has_real_parent_ref() const override;
283
+
284
+ SelectorList* resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
285
+ virtual unsigned long specificity() const override;
286
+
287
+ SelectorList* unifyWith(ComplexSelector* rhs);
288
+
289
+ bool isSuperselectorOf(const ComplexSelector* sub) const;
290
+
291
+ SelectorListObj wrapInList();
292
+
293
+ size_t maxSpecificity() const override;
294
+ size_t minSpecificity() const override;
295
+
296
+ bool operator==(const Selector& rhs) const override;
297
+ bool operator==(const SelectorList& rhs) const;
298
+ bool operator==(const CompoundSelector& rhs) const;
299
+ bool operator==(const SimpleSelector& rhs) const;
300
+
301
+ ATTACH_CMP_OPERATIONS(ComplexSelector)
302
+ ATTACH_AST_OPERATIONS(ComplexSelector)
362
303
  ATTACH_CRTP_PERFORM_METHODS()
363
304
  };
364
305
 
365
306
  ////////////////////////////////////////////////////////////////////////////
366
- // Simple selector sequences. Maintains flags indicating whether it contains
367
- // any parent references or placeholders, to simplify expansion.
307
+ // Base class for complex selector components
368
308
  ////////////////////////////////////////////////////////////////////////////
369
- class Compound_Selector final : public Selector, public Vectorized<Simple_Selector_Obj> {
370
- private:
371
- ComplexSelectorSet sources_;
372
- ADD_PROPERTY(bool, extended);
373
- ADD_PROPERTY(bool, has_parent_reference);
374
- protected:
375
- void adjust_after_pushing(Simple_Selector_Obj s) override
376
- {
377
- // if (s->has_reference()) has_reference(true);
378
- // if (s->has_placeholder()) has_placeholder(true);
379
- }
309
+ class SelectorComponent : public Selector {
310
+ // line break after list separator
311
+ ADD_PROPERTY(bool, hasPostLineBreak)
380
312
  public:
381
- Compound_Selector(ParserState pstate, size_t s = 0);
382
- bool contains_placeholder();
383
- void append(Simple_Selector_Obj element) override;
384
- bool is_universal() const;
385
- Complex_Selector_Obj to_complex();
386
- Compound_Selector* unify_with(Compound_Selector* rhs);
387
- // virtual Placeholder_Selector* find_placeholder();
388
- bool has_parent_ref() const override;
389
- bool has_real_parent_ref() const override;
390
- Simple_Selector* base() const;
391
- bool is_superselector_of(const Compound_Selector* sub, std::string wrapped = "") const;
392
- bool is_superselector_of(const Complex_Selector* sub, std::string wrapped = "") const;
393
- bool is_superselector_of(const Selector_List* sub, std::string wrapped = "") const;
394
- size_t hash() const override;
395
- virtual unsigned long specificity() const override;
396
- virtual bool has_placeholder();
397
- bool is_empty_reference();
398
- int unification_order() const override
399
- {
400
- throw std::runtime_error("unification_order for Compound_Selector is undefined");
401
- }
402
- bool find ( bool (*f)(AST_Node_Obj) ) override;
403
-
404
- bool operator<(const Selector& rhs) const override;
405
- bool operator==(const Selector& rhs) const override;
406
- bool operator<(const Selector_List& rhs) const;
407
- bool operator==(const Selector_List& rhs) const;
408
- bool operator<(const Complex_Selector& rhs) const;
409
- bool operator==(const Complex_Selector& rhs) const;
410
- bool operator<(const Compound_Selector& rhs) const;
411
- bool operator==(const Compound_Selector& rhs) const;
412
- bool operator<(const Simple_Selector& rhs) const;
413
- bool operator==(const Simple_Selector& rhs) const;
414
-
415
- ComplexSelectorSet& sources() { return sources_; }
416
- void clearSources() { sources_.clear(); }
417
- void mergeSources(ComplexSelectorSet& sources);
418
-
419
- Compound_Selector* minus(Compound_Selector* rhs);
313
+ SelectorComponent(ParserState pstate, bool postLineBreak = false);
314
+ size_t hash() const override = 0;
420
315
  void cloneChildren() override;
421
- ATTACH_AST_OPERATIONS(Compound_Selector)
422
- ATTACH_CRTP_PERFORM_METHODS()
316
+
317
+
318
+ // By default we consider instances not empty
319
+ virtual bool empty() const { return false; }
320
+
321
+ virtual bool has_placeholder() const = 0;
322
+ bool has_real_parent_ref() const override = 0;
323
+
324
+ ComplexSelector* wrapInComplex();
325
+
326
+ size_t maxSpecificity() const override { return 0; }
327
+ size_t minSpecificity() const override { return 0; }
328
+
329
+ virtual bool isCompound() const { return false; };
330
+ virtual bool isCombinator() const { return false; };
331
+
332
+ /* helper function for syntax sugar */
333
+ virtual CompoundSelector* getCompound() { return NULL; }
334
+ virtual SelectorCombinator* getCombinator() { return NULL; }
335
+ virtual const CompoundSelector* getCompound() const { return NULL; }
336
+ virtual const SelectorCombinator* getCombinator() const { return NULL; }
337
+
338
+ virtual unsigned long specificity() const override;
339
+ bool operator==(const Selector& rhs) const override = 0;
340
+ ATTACH_VIRTUAL_CMP_OPERATIONS(SelectorComponent);
341
+ ATTACH_VIRTUAL_AST_OPERATIONS(SelectorComponent);
423
342
  };
424
343
 
425
344
  ////////////////////////////////////////////////////////////////////////////
426
- // General selectors -- i.e., simple sequences combined with one of the four
427
- // CSS selector combinators (">", "+", "~", and whitespace). Essentially a
428
- // linked list.
345
+ // A specific combinator between compound selectors
429
346
  ////////////////////////////////////////////////////////////////////////////
430
- class Complex_Selector final : public Selector {
347
+ class SelectorCombinator final : public SelectorComponent {
431
348
  public:
432
- enum Combinator { ANCESTOR_OF, PARENT_OF, PRECEDES, ADJACENT_TO, REFERENCE };
349
+
350
+ // Enumerate all possible selector combinators. There is some
351
+ // discrepancy with dart-sass. Opted to name them as in CSS33
352
+ enum Combinator { CHILD /* > */, GENERAL /* ~ */, ADJACENT /* + */};
353
+
433
354
  private:
355
+
356
+ // Store the type of this combinator
434
357
  HASH_CONSTREF(Combinator, combinator)
435
- HASH_PROPERTY(Compound_Selector_Obj, head)
436
- HASH_PROPERTY(Complex_Selector_Obj, tail)
437
- HASH_PROPERTY(String_Obj, reference);
358
+
438
359
  public:
439
- bool contains_placeholder() {
440
- if (head() && head()->contains_placeholder()) return true;
441
- if (tail() && tail()->contains_placeholder()) return true;
442
- return false;
443
- };
444
- Complex_Selector(ParserState pstate,
445
- Combinator c = ANCESTOR_OF,
446
- Compound_Selector_Obj h = {},
447
- Complex_Selector_Obj t = {},
448
- String_Obj r = {});
360
+ SelectorCombinator(ParserState pstate, Combinator combinator, bool postLineBreak = false);
449
361
 
450
- bool empty() const;
362
+ bool has_real_parent_ref() const override { return false; }
363
+ bool has_placeholder() const override { return false; }
451
364
 
452
- bool has_parent_ref() const override;
453
- bool has_real_parent_ref() const override;
454
- Complex_Selector_Obj skip_empty_reference();
365
+ /* helper function for syntax sugar */
366
+ SelectorCombinator* getCombinator() final override { return this; }
367
+ const SelectorCombinator* getCombinator() const final override { return this; }
455
368
 
456
- // can still have a tail
457
- bool is_empty_ancestor() const;
369
+ // Query type of combinator
370
+ bool isCombinator() const override { return true; };
458
371
 
459
- Selector_List* tails(Selector_List* tails);
372
+ // Matches the right-hand selector if it's a direct child of the left-
373
+ // hand selector in the DOM tree. Dart-sass also calls this `child`
374
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator
375
+ bool isChildCombinator() const { return combinator_ == CHILD; } // >
460
376
 
461
- // front returns the first real tail
462
- // skips over parent and empty ones
463
- const Complex_Selector* first() const;
464
- Complex_Selector* mutable_first();
377
+ // Matches the right-hand selector if it comes after the left-hand
378
+ // selector in the DOM tree. Dart-sass class this `followingSibling`
379
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator
380
+ bool isGeneralCombinator() const { return combinator_ == GENERAL; } // ~
465
381
 
466
- // last returns the last real tail
467
- const Complex_Selector* last() const;
468
- Complex_Selector* mutable_last();
382
+ // Matches the right-hand selector if it's immediately adjacent to the
383
+ // left-hand selector in the DOM tree. Dart-sass calls this `nextSibling`
384
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
385
+ bool isAdjacentCombinator() const { return combinator_ == ADJACENT; } // +
469
386
 
470
- size_t length() const;
471
- Selector_List* resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent = true);
472
- bool is_superselector_of(const Compound_Selector* sub, std::string wrapping = "") const;
473
- bool is_superselector_of(const Complex_Selector* sub, std::string wrapping = "") const;
474
- bool is_superselector_of(const Selector_List* sub, std::string wrapping = "") const;
475
- Selector_List* unify_with(Complex_Selector* rhs);
476
- Combinator clear_innermost();
477
- void append(Complex_Selector_Obj, Backtraces& traces);
478
- void set_innermost(Complex_Selector_Obj, Combinator);
387
+ size_t maxSpecificity() const override { return 0; }
388
+ size_t minSpecificity() const override { return 0; }
479
389
 
480
- size_t hash() const override;
390
+ size_t hash() const override {
391
+ return std::hash<int>()(combinator_);
392
+ }
393
+ void cloneChildren() override;
481
394
  virtual unsigned long specificity() const override;
482
- virtual void set_media_block(Media_Block* mb) override;
483
- virtual bool has_placeholder();
484
- int unification_order() const override
485
- {
486
- throw std::runtime_error("unification_order for Complex_Selector is undefined");
395
+ bool operator==(const Selector& rhs) const override;
396
+ bool operator==(const SelectorComponent& rhs) const override;
397
+
398
+ ATTACH_CMP_OPERATIONS(SelectorCombinator)
399
+ ATTACH_AST_OPERATIONS(SelectorCombinator)
400
+ ATTACH_CRTP_PERFORM_METHODS()
401
+ };
402
+
403
+ ////////////////////////////////////////////////////////////////////////////
404
+ // A compound selector consists of multiple simple selectors
405
+ ////////////////////////////////////////////////////////////////////////////
406
+ class CompoundSelector final : public SelectorComponent, public Vectorized<SimpleSelectorObj> {
407
+ ADD_PROPERTY(bool, hasRealParent)
408
+ ADD_PROPERTY(bool, extended)
409
+ public:
410
+ CompoundSelector(ParserState pstate, bool postLineBreak = false);
411
+
412
+ // Returns true if this compound selector
413
+ // fullfills various criteria.
414
+ bool isInvisible() const;
415
+
416
+ bool empty() const override {
417
+ return Vectorized::empty();
487
418
  }
488
- bool find ( bool (*f)(AST_Node_Obj) ) override;
489
419
 
490
- bool operator<(const Selector& rhs) const override;
491
- bool operator==(const Selector& rhs) const override;
492
- bool operator<(const Selector_List& rhs) const;
493
- bool operator==(const Selector_List& rhs) const;
494
- bool operator<(const Complex_Selector& rhs) const;
495
- bool operator==(const Complex_Selector& rhs) const;
496
- bool operator<(const Compound_Selector& rhs) const;
497
- bool operator==(const Compound_Selector& rhs) const;
498
- bool operator<(const Simple_Selector& rhs) const;
499
- bool operator==(const Simple_Selector& rhs) const;
500
-
501
- const ComplexSelectorSet sources();
502
- void addSources(ComplexSelectorSet& sources);
503
- void clearSources();
420
+ size_t hash() const override;
421
+ CompoundSelector* unifyWith(CompoundSelector* rhs);
422
+
423
+ /* helper function for syntax sugar */
424
+ CompoundSelector* getCompound() final override { return this; }
425
+ const CompoundSelector* getCompound() const final override { return this; }
426
+
427
+ bool isSuperselectorOf(const CompoundSelector* sub, std::string wrapped = "") const;
504
428
 
505
429
  void cloneChildren() override;
506
- ATTACH_AST_OPERATIONS(Complex_Selector)
430
+ bool has_real_parent_ref() const override;
431
+ bool has_placeholder() const override;
432
+ std::vector<ComplexSelectorObj> resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
433
+
434
+ virtual bool isCompound() const override { return true; };
435
+ virtual unsigned long specificity() const override;
436
+
437
+ size_t maxSpecificity() const override;
438
+ size_t minSpecificity() const override;
439
+
440
+ bool operator==(const Selector& rhs) const override;
441
+
442
+ bool operator==(const SelectorComponent& rhs) const override;
443
+
444
+ bool operator==(const SelectorList& rhs) const;
445
+ bool operator==(const ComplexSelector& rhs) const;
446
+ bool operator==(const SimpleSelector& rhs) const;
447
+
448
+ ATTACH_CMP_OPERATIONS(CompoundSelector)
449
+ ATTACH_AST_OPERATIONS(CompoundSelector)
507
450
  ATTACH_CRTP_PERFORM_METHODS()
508
451
  };
509
452
 
510
453
  ///////////////////////////////////
511
454
  // Comma-separated selector groups.
512
455
  ///////////////////////////////////
513
- class Selector_List final : public Selector, public Vectorized<Complex_Selector_Obj> {
514
- ADD_PROPERTY(Selector_Schema_Obj, schema)
515
- ADD_CONSTREF(std::vector<std::string>, wspace)
516
- protected:
517
- void adjust_after_pushing(Complex_Selector_Obj c) override;
456
+ class SelectorList final : public Selector, public Vectorized<ComplexSelectorObj> {
457
+ private:
458
+ // maybe we have optional flag
459
+ // ToDo: should be at ExtendRule?
460
+ ADD_PROPERTY(bool, is_optional)
518
461
  public:
519
- Selector_List(ParserState pstate, size_t s = 0);
462
+ SelectorList(ParserState pstate, size_t s = 0);
520
463
  std::string type() const override { return "list"; }
521
- // remove parent selector references
522
- // basically unwraps parsed selectors
523
- bool has_parent_ref() const override;
524
- bool has_real_parent_ref() const override;
525
- void remove_parent_selectors();
526
- Selector_List* resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent = true);
527
- bool is_superselector_of(const Compound_Selector* sub, std::string wrapping = "") const;
528
- bool is_superselector_of(const Complex_Selector* sub, std::string wrapping = "") const;
529
- bool is_superselector_of(const Selector_List* sub, std::string wrapping = "") const;
530
- Selector_List* unify_with(Selector_List*);
531
- void populate_extends(Selector_List_Obj, Subset_Map&);
532
- Selector_List_Obj eval(Eval& eval);
533
-
534
464
  size_t hash() const override;
465
+
466
+ SelectorList* unifyWith(SelectorList*);
467
+
468
+ // Returns true if all complex selectors
469
+ // can have real parents, meaning every
470
+ // first component does allow for it
471
+ bool isInvisible() const;
472
+
473
+ void cloneChildren() override;
474
+ bool has_real_parent_ref() const override;
475
+ SelectorList* resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
535
476
  virtual unsigned long specificity() const override;
536
- virtual void set_media_block(Media_Block* mb) override;
537
- virtual bool has_placeholder();
538
- int unification_order() const override
539
- {
540
- throw std::runtime_error("unification_order for Selector_List is undefined");
541
- }
542
- bool find ( bool (*f)(AST_Node_Obj) ) override;
543
- bool operator<(const Selector& rhs) const override;
477
+
478
+ bool isSuperselectorOf(const SelectorList* sub) const;
479
+
480
+ size_t maxSpecificity() const override;
481
+ size_t minSpecificity() const override;
482
+
544
483
  bool operator==(const Selector& rhs) const override;
545
- bool operator<(const Selector_List& rhs) const;
546
- bool operator==(const Selector_List& rhs) const;
547
- bool operator<(const Complex_Selector& rhs) const;
548
- bool operator==(const Complex_Selector& rhs) const;
549
- bool operator<(const Compound_Selector& rhs) const;
550
- bool operator==(const Compound_Selector& rhs) const;
551
- bool operator<(const Simple_Selector& rhs) const;
552
- bool operator==(const Simple_Selector& rhs) const;
484
+ bool operator==(const ComplexSelector& rhs) const;
485
+ bool operator==(const CompoundSelector& rhs) const;
486
+ bool operator==(const SimpleSelector& rhs) const;
553
487
  // Selector Lists can be compared to comma lists
554
- bool operator<(const Expression& rhs) const override;
555
488
  bool operator==(const Expression& rhs) const override;
556
- void cloneChildren() override;
557
- ATTACH_AST_OPERATIONS(Selector_List)
489
+
490
+ ATTACH_CMP_OPERATIONS(SelectorList)
491
+ ATTACH_AST_OPERATIONS(SelectorList)
558
492
  ATTACH_CRTP_PERFORM_METHODS()
559
493
  };
560
494
 
561
- // compare function for sorting and probably other other uses
562
- struct cmp_complex_selector { inline bool operator() (const Complex_Selector_Obj l, const Complex_Selector_Obj r) { return (*l < *r); } };
563
- struct cmp_compound_selector { inline bool operator() (const Compound_Selector_Obj l, const Compound_Selector_Obj r) { return (*l < *r); } };
564
- struct cmp_simple_selector { inline bool operator() (const Simple_Selector_Obj l, const Simple_Selector_Obj r) { return (*l < *r); } };
495
+ ////////////////////////////////
496
+ // The Sass `@extend` directive.
497
+ ////////////////////////////////
498
+ class ExtendRule final : public Statement {
499
+ ADD_PROPERTY(bool, isOptional)
500
+ // This should be a simple selector only!
501
+ ADD_PROPERTY(SelectorListObj, selector)
502
+ ADD_PROPERTY(Selector_Schema_Obj, schema)
503
+ public:
504
+ ExtendRule(ParserState pstate, SelectorListObj s);
505
+ ExtendRule(ParserState pstate, Selector_Schema_Obj s);
506
+ ATTACH_AST_OPERATIONS(ExtendRule)
507
+ ATTACH_CRTP_PERFORM_METHODS()
508
+ };
565
509
 
566
510
  }
567
511