1#ifndef SASS_AST_SEL_H
2#define SASS_AST_SEL_H
3
4// sass.hpp must go before all system headers to get the
5// __EXTENSIONS__ fix on Solaris.
6#include "sass.hpp"
7#include "ast.hpp"
8
9namespace Sass {
10
11 /////////////////////////////////////////////////////////////////////////
12 // Some helper functions
13 /////////////////////////////////////////////////////////////////////////
14
15 bool compoundIsSuperselector(
16 const CompoundSelectorObj& compound1,
17 const CompoundSelectorObj& compound2,
18 const sass::vector<SelectorComponentObj>& parents);
19
20 bool complexIsParentSuperselector(
21 const sass::vector<SelectorComponentObj>& complex1,
22 const sass::vector<SelectorComponentObj>& complex2);
23
24 sass::vector<sass::vector<SelectorComponentObj>> weave(
25 const sass::vector<sass::vector<SelectorComponentObj>>& complexes);
26
27 sass::vector<sass::vector<SelectorComponentObj>> weaveParents(
28 sass::vector<SelectorComponentObj> parents1,
29 sass::vector<SelectorComponentObj> parents2);
30
31 sass::vector<SimpleSelectorObj> unifyCompound(
32 const sass::vector<SimpleSelectorObj>& compound1,
33 const sass::vector<SimpleSelectorObj>& compound2);
34
35 sass::vector<sass::vector<SelectorComponentObj>> unifyComplex(
36 const sass::vector<sass::vector<SelectorComponentObj>>& complexes);
37
38 /////////////////////////////////////////
39 // Abstract base class for CSS selectors.
40 /////////////////////////////////////////
41 class Selector : public Expression {
42 protected:
43 mutable size_t hash_;
44 public:
45 Selector(SourceSpan pstate);
46 virtual ~Selector() = 0;
47 size_t hash() const override = 0;
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(); }
55 // dispatch to correct handlers
56 ATTACH_VIRTUAL_CMP_OPERATIONS(Selector)
57 ATTACH_VIRTUAL_AST_OPERATIONS(Selector)
58 };
59 inline Selector::~Selector() { }
60
61 /////////////////////////////////////////////////////////////////////////
62 // Interpolated selectors -- the interpolated String will be expanded and
63 // re-parsed into a normal selector class.
64 /////////////////////////////////////////////////////////////////////////
65 class Selector_Schema final : public AST_Node {
66 ADD_PROPERTY(String_Schema_Obj, contents)
67 ADD_PROPERTY(bool, connect_parent);
68 // store computed hash
69 mutable size_t hash_;
70 public:
71 Selector_Schema(SourceSpan pstate, String_Obj c);
72
73 bool has_real_parent_ref() const;
74 // selector schema is not yet a final selector, so we do not
75 // have a specificity for it yet. We need to
76 virtual unsigned long specificity() const;
77 size_t hash() const override;
78 ATTACH_AST_OPERATIONS(Selector_Schema)
79 ATTACH_CRTP_PERFORM_METHODS()
80 };
81
82 ////////////////////////////////////////////
83 // Abstract base class for simple selectors.
84 ////////////////////////////////////////////
85 class SimpleSelector : public Selector {
86 public:
87 enum Simple_Type {
88 ID_SEL,
89 TYPE_SEL,
90 CLASS_SEL,
91 PSEUDO_SEL,
92 ATTRIBUTE_SEL,
93 PLACEHOLDER_SEL,
94 };
95 public:
96 HASH_CONSTREF(sass::string, ns)
97 HASH_CONSTREF(sass::string, name)
98 ADD_PROPERTY(Simple_Type, simple_type)
99 HASH_PROPERTY(bool, has_ns)
100 public:
101 SimpleSelector(SourceSpan pstate, sass::string n = "");
102 // ordering within parent (peudos go last)
103 virtual int getSortOrder() const = 0;
104 virtual sass::string ns_name() const;
105 size_t hash() const override;
106 virtual bool empty() const;
107 // namespace compare functions
108 bool is_ns_eq(const SimpleSelector& r) const;
109 // namespace query functions
110 bool is_universal_ns() const;
111 bool is_empty_ns() const;
112 bool has_empty_ns() const;
113 bool has_qualified_ns() const;
114 // name query functions
115 bool is_universal() const;
116 virtual bool has_placeholder();
117
118 virtual ~SimpleSelector() = 0;
119 virtual CompoundSelector* unifyWith(CompoundSelector*);
120
121 /* helper function for syntax sugar */
122 virtual IDSelector* getIdSelector() { return NULL; }
123 virtual TypeSelector* getTypeSelector() { return NULL; }
124 virtual PseudoSelector* getPseudoSelector() { return NULL; }
125
126 ComplexSelectorObj wrapInComplex();
127 CompoundSelectorObj wrapInCompound();
128
129 virtual bool isInvisible() const { return false; }
130 virtual bool is_pseudo_element() const;
131 virtual bool has_real_parent_ref() const override;
132
133 bool operator==(const Selector& rhs) const final override;
134
135 virtual bool operator==(const SelectorList& rhs) const;
136 virtual bool operator==(const ComplexSelector& rhs) const;
137 virtual bool operator==(const CompoundSelector& rhs) const;
138
139 ATTACH_VIRTUAL_CMP_OPERATIONS(SimpleSelector);
140 ATTACH_VIRTUAL_AST_OPERATIONS(SimpleSelector);
141 ATTACH_CRTP_PERFORM_METHODS();
142
143 };
144 inline SimpleSelector::~SimpleSelector() { }
145
146 /////////////////////////////////////////////////////////////////////////
147 // Placeholder selectors (e.g., "%foo") for use in extend-only selectors.
148 /////////////////////////////////////////////////////////////////////////
149 class PlaceholderSelector final : public SimpleSelector {
150 public:
151 PlaceholderSelector(SourceSpan pstate, sass::string n);
152 int getSortOrder() const override final { return 0; }
153 bool isInvisible() const override { return true; }
154 virtual unsigned long specificity() const override;
155 virtual bool has_placeholder() override;
156 bool operator==(const SimpleSelector& rhs) const override;
157 ATTACH_CMP_OPERATIONS(PlaceholderSelector)
158 ATTACH_AST_OPERATIONS(PlaceholderSelector)
159 ATTACH_CRTP_PERFORM_METHODS()
160 };
161
162 /////////////////////////////////////////////////////////////////////
163 // Type selectors (and the universal selector) -- e.g., div, span, *.
164 /////////////////////////////////////////////////////////////////////
165 class TypeSelector final : public SimpleSelector {
166 public:
167 TypeSelector(SourceSpan pstate, sass::string n);
168 int getSortOrder() const override final { return 1; }
169 virtual unsigned long specificity() const override;
170 SimpleSelector* unifyWith(const SimpleSelector*);
171 CompoundSelector* unifyWith(CompoundSelector*) override;
172 TypeSelector* getTypeSelector() override { return this; }
173 bool operator==(const SimpleSelector& rhs) const final override;
174 ATTACH_CMP_OPERATIONS(TypeSelector)
175 ATTACH_AST_OPERATIONS(TypeSelector)
176 ATTACH_CRTP_PERFORM_METHODS()
177 };
178
179 ////////////////////////////////////////////////
180 // Class selectors -- i.e., .foo.
181 ////////////////////////////////////////////////
182 class ClassSelector final : public SimpleSelector {
183 public:
184 ClassSelector(SourceSpan pstate, sass::string n);
185 int getSortOrder() const override final { return 3; }
186 virtual unsigned long specificity() const override;
187 bool operator==(const SimpleSelector& rhs) const final override;
188 ATTACH_CMP_OPERATIONS(ClassSelector)
189 ATTACH_AST_OPERATIONS(ClassSelector)
190 ATTACH_CRTP_PERFORM_METHODS()
191 };
192
193 ////////////////////////////////////////////////
194 // ID selectors -- i.e., #foo.
195 ////////////////////////////////////////////////
196 class IDSelector final : public SimpleSelector {
197 public:
198 IDSelector(SourceSpan pstate, sass::string n);
199 int getSortOrder() const override final { return 2; }
200 virtual unsigned long specificity() const override;
201 CompoundSelector* unifyWith(CompoundSelector*) override;
202 IDSelector* getIdSelector() final override { return this; }
203 bool operator==(const SimpleSelector& rhs) const final override;
204 ATTACH_CMP_OPERATIONS(IDSelector)
205 ATTACH_AST_OPERATIONS(IDSelector)
206 ATTACH_CRTP_PERFORM_METHODS()
207 };
208
209 ///////////////////////////////////////////////////
210 // Attribute selectors -- e.g., [src*=".jpg"], etc.
211 ///////////////////////////////////////////////////
212 class AttributeSelector final : public SimpleSelector {
213 ADD_CONSTREF(sass::string, matcher)
214 // this cannot be changed to obj atm!!!!!!????!!!!!!!
215 ADD_PROPERTY(String_Obj, value) // might be interpolated
216 ADD_PROPERTY(char, modifier);
217 public:
218 AttributeSelector(SourceSpan pstate, sass::string n, sass::string m, String_Obj v, char o = 0);
219 int getSortOrder() const override final { return 4; }
220 size_t hash() const override;
221 virtual unsigned long specificity() const override;
222 bool operator==(const SimpleSelector& rhs) const final override;
223 ATTACH_CMP_OPERATIONS(AttributeSelector)
224 ATTACH_AST_OPERATIONS(AttributeSelector)
225 ATTACH_CRTP_PERFORM_METHODS()
226 };
227
228 //////////////////////////////////////////////////////////////////
229 // Pseudo selectors -- e.g., :first-child, :nth-of-type(...), etc.
230 //////////////////////////////////////////////////////////////////
231 // Pseudo Selector cannot have any namespace?
232 class PseudoSelector final : public SimpleSelector {
233 ADD_PROPERTY(sass::string, normalized)
234 ADD_PROPERTY(String_Obj, argument)
235 ADD_PROPERTY(SelectorListObj, selector)
236 ADD_PROPERTY(bool, isSyntacticClass)
237 ADD_PROPERTY(bool, isClass)
238 public:
239 PseudoSelector(SourceSpan pstate, sass::string n, bool element = false);
240 int getSortOrder() const override final { return 5; }
241 virtual bool is_pseudo_element() const override;
242 size_t hash() const override;
243
244 bool empty() const override;
245
246 bool has_real_parent_ref() const override;
247
248 // Whether this is a pseudo-element selector.
249 // This is `true` if and only if [isClass] is `false`.
250 bool isElement() const { return !isClass(); }
251
252 // Whether this is syntactically a pseudo-element selector.
253 // This is `true` if and only if [isSyntacticClass] is `false`.
254 bool isSyntacticElement() const { return !isSyntacticClass(); }
255
256 virtual unsigned long specificity() const override;
257 PseudoSelectorObj withSelector(SelectorListObj selector);
258
259 CompoundSelector* unifyWith(CompoundSelector*) override;
260 PseudoSelector* getPseudoSelector() final override { return this; }
261 bool operator==(const SimpleSelector& rhs) const final override;
262 ATTACH_CMP_OPERATIONS(PseudoSelector)
263 ATTACH_AST_OPERATIONS(PseudoSelector)
264 void cloneChildren() override;
265 ATTACH_CRTP_PERFORM_METHODS()
266 };
267
268
269 ////////////////////////////////////////////////////////////////////////////
270 // Complex Selectors are the most important class of selectors.
271 // A Selector List consists of Complex Selectors (separated by comma)
272 // Complex Selectors are itself a list of Compounds and Combinators
273 // Between each item there is an implicit ancestor of combinator
274 ////////////////////////////////////////////////////////////////////////////
275 class ComplexSelector final : public Selector, public Vectorized<SelectorComponentObj> {
276 ADD_PROPERTY(bool, chroots)
277 // line break before list separator
278 ADD_PROPERTY(bool, hasPreLineFeed)
279 public:
280 ComplexSelector(SourceSpan pstate);
281
282 // Returns true if the first components
283 // is a compound selector and fullfills
284 // a few other criteria.
285 bool isInvisible() const;
286
287 size_t hash() const override;
288 void cloneChildren() override;
289 bool has_placeholder() const;
290 bool has_real_parent_ref() const override;
291
292 SelectorList* resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
293 virtual unsigned long specificity() const override;
294
295 SelectorList* unifyWith(ComplexSelector* rhs);
296
297 bool isSuperselectorOf(const ComplexSelector* sub) const;
298
299 SelectorListObj wrapInList();
300
301 size_t maxSpecificity() const override;
302 size_t minSpecificity() const override;
303
304 bool operator==(const Selector& rhs) const override;
305 bool operator==(const SelectorList& rhs) const;
306 bool operator==(const CompoundSelector& rhs) const;
307 bool operator==(const SimpleSelector& rhs) const;
308
309 ATTACH_CMP_OPERATIONS(ComplexSelector)
310 ATTACH_AST_OPERATIONS(ComplexSelector)
311 ATTACH_CRTP_PERFORM_METHODS()
312 };
313
314 ////////////////////////////////////////////////////////////////////////////
315 // Base class for complex selector components
316 ////////////////////////////////////////////////////////////////////////////
317 class SelectorComponent : public Selector {
318 // line break after list separator
319 ADD_PROPERTY(bool, hasPostLineBreak)
320 public:
321 SelectorComponent(SourceSpan pstate, bool postLineBreak = false);
322 size_t hash() const override = 0;
323 void cloneChildren() override;
324
325
326 // By default we consider instances not empty
327 virtual bool empty() const { return false; }
328
329 virtual bool has_placeholder() const = 0;
330 bool has_real_parent_ref() const override = 0;
331
332 ComplexSelector* wrapInComplex();
333
334 size_t maxSpecificity() const override { return 0; }
335 size_t minSpecificity() const override { return 0; }
336
337 virtual bool isCompound() const { return false; };
338 virtual bool isCombinator() const { return false; };
339
340 /* helper function for syntax sugar */
341 virtual CompoundSelector* getCompound() { return NULL; }
342 virtual SelectorCombinator* getCombinator() { return NULL; }
343 virtual const CompoundSelector* getCompound() const { return NULL; }
344 virtual const SelectorCombinator* getCombinator() const { return NULL; }
345
346 virtual unsigned long specificity() const override;
347 bool operator==(const Selector& rhs) const override = 0;
348 ATTACH_VIRTUAL_CMP_OPERATIONS(SelectorComponent);
349 ATTACH_VIRTUAL_AST_OPERATIONS(SelectorComponent);
350 };
351
352 ////////////////////////////////////////////////////////////////////////////
353 // A specific combinator between compound selectors
354 ////////////////////////////////////////////////////////////////////////////
355 class SelectorCombinator final : public SelectorComponent {
356 public:
357
358 // Enumerate all possible selector combinators. There is some
359 // discrepancy with dart-sass. Opted to name them as in CSS33
360 enum Combinator { CHILD /* > */, GENERAL /* ~ */, ADJACENT /* + */};
361
362 private:
363
364 // Store the type of this combinator
365 HASH_CONSTREF(Combinator, combinator)
366
367 public:
368 SelectorCombinator(SourceSpan pstate, Combinator combinator, bool postLineBreak = false);
369
370 bool has_real_parent_ref() const override { return false; }
371 bool has_placeholder() const override { return false; }
372
373 /* helper function for syntax sugar */
374 SelectorCombinator* getCombinator() final override { return this; }
375 const SelectorCombinator* getCombinator() const final override { return this; }
376
377 // Query type of combinator
378 bool isCombinator() const override { return true; };
379
380 // Matches the right-hand selector if it's a direct child of the left-
381 // hand selector in the DOM tree. Dart-sass also calls this `child`
382 // https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator
383 bool isChildCombinator() const { return combinator_ == CHILD; } // >
384
385 // Matches the right-hand selector if it comes after the left-hand
386 // selector in the DOM tree. Dart-sass class this `followingSibling`
387 // https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator
388 bool isGeneralCombinator() const { return combinator_ == GENERAL; } // ~
389
390 // Matches the right-hand selector if it's immediately adjacent to the
391 // left-hand selector in the DOM tree. Dart-sass calls this `nextSibling`
392 // https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
393 bool isAdjacentCombinator() const { return combinator_ == ADJACENT; } // +
394
395 size_t maxSpecificity() const override { return 0; }
396 size_t minSpecificity() const override { return 0; }
397
398 size_t hash() const override {
399 return std::hash<int>()(combinator_);
400 }
401 void cloneChildren() override;
402 virtual unsigned long specificity() const override;
403 bool operator==(const Selector& rhs) const override;
404 bool operator==(const SelectorComponent& rhs) const override;
405
406 ATTACH_CMP_OPERATIONS(SelectorCombinator)
407 ATTACH_AST_OPERATIONS(SelectorCombinator)
408 ATTACH_CRTP_PERFORM_METHODS()
409 };
410
411 ////////////////////////////////////////////////////////////////////////////
412 // A compound selector consists of multiple simple selectors
413 ////////////////////////////////////////////////////////////////////////////
414 class CompoundSelector final : public SelectorComponent, public Vectorized<SimpleSelectorObj> {
415 ADD_PROPERTY(bool, hasRealParent)
416 ADD_PROPERTY(bool, extended)
417 public:
418 CompoundSelector(SourceSpan pstate, bool postLineBreak = false);
419
420 // Returns true if this compound selector
421 // fullfills various criteria.
422 bool isInvisible() const;
423
424 bool empty() const override {
425 return Vectorized::empty();
426 }
427
428 size_t hash() const override;
429 CompoundSelector* unifyWith(CompoundSelector* rhs);
430
431 /* helper function for syntax sugar */
432 CompoundSelector* getCompound() final override { return this; }
433 const CompoundSelector* getCompound() const final override { return this; }
434
435 bool isSuperselectorOf(const CompoundSelector* sub, sass::string wrapped = "") const;
436
437 void cloneChildren() override;
438 bool has_real_parent_ref() const override;
439 bool has_placeholder() const override;
440 sass::vector<ComplexSelectorObj> resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
441
442 virtual bool isCompound() const override { return true; };
443 virtual unsigned long specificity() const override;
444
445 size_t maxSpecificity() const override;
446 size_t minSpecificity() const override;
447
448 bool operator==(const Selector& rhs) const override;
449
450 bool operator==(const SelectorComponent& rhs) const override;
451
452 bool operator==(const SelectorList& rhs) const;
453 bool operator==(const ComplexSelector& rhs) const;
454 bool operator==(const SimpleSelector& rhs) const;
455
456 void sortChildren();
457
458 ATTACH_CMP_OPERATIONS(CompoundSelector)
459 ATTACH_AST_OPERATIONS(CompoundSelector)
460 ATTACH_CRTP_PERFORM_METHODS()
461 };
462
463 ///////////////////////////////////
464 // Comma-separated selector groups.
465 ///////////////////////////////////
466 class SelectorList final : public Selector, public Vectorized<ComplexSelectorObj> {
467 private:
468 // maybe we have optional flag
469 // ToDo: should be at ExtendRule?
470 ADD_PROPERTY(bool, is_optional)
471 public:
472 SelectorList(SourceSpan pstate, size_t s = 0);
473 sass::string type() const override { return "list"; }
474 size_t hash() const override;
475
476 SelectorList* unifyWith(SelectorList*);
477
478 // Returns true if all complex selectors
479 // can have real parents, meaning every
480 // first component does allow for it
481 bool isInvisible() const;
482
483 void cloneChildren() override;
484 bool has_real_parent_ref() const override;
485 SelectorList* resolve_parent_refs(SelectorStack pstack, Backtraces& traces, bool implicit_parent = true);
486 virtual unsigned long specificity() const override;
487
488 bool isSuperselectorOf(const SelectorList* sub) const;
489
490 size_t maxSpecificity() const override;
491 size_t minSpecificity() const override;
492
493 bool operator==(const Selector& rhs) const override;
494 bool operator==(const ComplexSelector& rhs) const;
495 bool operator==(const CompoundSelector& rhs) const;
496 bool operator==(const SimpleSelector& rhs) const;
497 // Selector Lists can be compared to comma lists
498 bool operator==(const Expression& rhs) const override;
499
500 ATTACH_CMP_OPERATIONS(SelectorList)
501 ATTACH_AST_OPERATIONS(SelectorList)
502 ATTACH_CRTP_PERFORM_METHODS()
503 };
504
505 ////////////////////////////////
506 // The Sass `@extend` directive.
507 ////////////////////////////////
508 class ExtendRule final : public Statement {
509 ADD_PROPERTY(bool, isOptional)
510 // This should be a simple selector only!
511 ADD_PROPERTY(SelectorListObj, selector)
512 ADD_PROPERTY(Selector_Schema_Obj, schema)
513 public:
514 ExtendRule(SourceSpan pstate, SelectorListObj s);
515 ExtendRule(SourceSpan pstate, Selector_Schema_Obj s);
516 ATTACH_AST_OPERATIONS(ExtendRule)
517 ATTACH_CRTP_PERFORM_METHODS()
518 };
519
520}
521
522#endif
523

source code of gtk/subprojects/libsass/src/ast_selectors.hpp