1use cstree::{RawSyntaxKind, Syntax};
12
13pub mod ident;
14mod keyword;
15mod layer;
16mod selector;
17
18pub use keyword::{CssKeywordText, css_keyword};
19pub use layer::{CanonicalLayerIdentifierKeyV0, LayerPathV0};
20pub use selector::{
21 CanonicalCompoundSelectorV0, CanonicalSelectorAst, CanonicalSelectorBranchV0,
22 CanonicalSelectorCombinatorV0, CanonicalSelectorSpecificityWitnessV0, NestingTokenV0,
23};
24
25pub const TOKEN_START: u32 = 0x0000;
26pub const TOKEN_END: u32 = 0x03ff;
27pub const DIALECT_TOKEN_START: u32 = 0x0400;
28pub const DIALECT_TOKEN_END: u32 = 0x04ff;
29pub const NODE_START: u32 = 0x1000;
30pub const NODE_END: u32 = 0x13ff;
31pub const DIALECT_NODE_START: u32 = 0x1400;
32pub const DIALECT_NODE_END: u32 = 0x14ff;
33pub const BOGUS_START: u32 = 0x2000;
34pub const BOGUS_END: u32 = 0x20ff;
35pub const MARKER_START: u32 = 0x2100;
36pub const MARKER_END: u32 = 0x21ff;
37
38const _: () = {
39 assert!(TOKEN_END < DIALECT_TOKEN_START);
40 assert!(DIALECT_TOKEN_END < NODE_START);
41 assert!(NODE_END < DIALECT_NODE_START);
42 assert!(DIALECT_NODE_END < BOGUS_START);
43 assert!(BOGUS_END < MARKER_START);
44};
45
46pub type SyntaxNode<D = ()> = cstree::syntax::SyntaxNode<SyntaxKind, D>;
47pub type SyntaxToken<D = ()> = cstree::syntax::SyntaxToken<SyntaxKind, D>;
48pub type SyntaxElement<D = ()> = cstree::syntax::SyntaxElement<SyntaxKind, D>;
49pub type SyntaxElementRef<'a, D = ()> = cstree::syntax::SyntaxElementRef<'a, SyntaxKind, D>;
50
51macro_rules! syntax_kinds {
52 ($($name:ident = $value:literal,)+) => {
53 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
54 #[repr(u32)]
55 pub enum SyntaxKind {
56 $($name = $value,)+
57 }
58
59 impl SyntaxKind {
60 pub const ALL: &'static [Self] = &[$(Self::$name,)+];
61
62 pub const fn as_u32(self) -> u32 {
63 self as u32
64 }
65
66 pub fn from_raw_kind(raw: u32) -> Option<Self> {
67 match raw {
68 $($value => Some(Self::$name),)+
69 _ => None,
70 }
71 }
72
73 pub const fn is_token(self) -> bool {
74 let raw = self.as_u32();
75 (raw >= TOKEN_START && raw <= TOKEN_END)
76 || (raw >= DIALECT_TOKEN_START && raw <= DIALECT_TOKEN_END)
77 }
78
79 pub const fn is_node(self) -> bool {
80 let raw = self.as_u32();
81 (raw >= NODE_START && raw <= NODE_END)
82 || (raw >= DIALECT_NODE_START && raw <= DIALECT_NODE_END)
83 }
84
85 pub const fn is_bogus(self) -> bool {
86 let raw = self.as_u32();
87 raw >= BOGUS_START && raw <= BOGUS_END
88 }
89
90 pub const fn is_marker(self) -> bool {
91 let raw = self.as_u32();
92 raw >= MARKER_START && raw <= MARKER_END
93 }
94
95 pub const fn is_dialect_specific(self) -> bool {
96 let raw = self.as_u32();
97 (raw >= DIALECT_TOKEN_START && raw <= DIALECT_TOKEN_END)
98 || (raw >= DIALECT_NODE_START && raw <= DIALECT_NODE_END)
99 }
100
101 pub const fn is_dialect(self) -> bool {
102 self.is_dialect_specific()
103 }
104
105 pub const fn is_trivia(self) -> bool {
106 matches!(
107 self,
108 Self::Whitespace
109 | Self::LineComment
110 | Self::BlockComment
111 | Self::SassIndentedNewline
112 )
113 }
114 }
115 };
116}
117
118syntax_kinds! {
119 Whitespace = 0x0000,
120 LineComment = 0x0001,
121 BlockComment = 0x0002,
122 Ident = 0x0003,
123 Hash = 0x0004,
124 String = 0x0005,
125 BadString = 0x0006,
126 Url = 0x0007,
127 BadUrl = 0x0008,
128 Number = 0x0009,
129 Percentage = 0x000a,
130 Dimension = 0x000b,
131 UnicodeRange = 0x000c,
132 AtKeyword = 0x000d,
133 Delim = 0x000e,
134 Important = 0x000f,
135 Dot = 0x0010,
136 Comma = 0x0011,
137 Colon = 0x0012,
138 Semicolon = 0x0013,
139 LeftBrace = 0x0014,
140 RightBrace = 0x0015,
141 LeftParen = 0x0016,
142 RightParen = 0x0017,
143 LeftBracket = 0x0018,
144 RightBracket = 0x0019,
145 Plus = 0x001a,
146 Minus = 0x001b,
147 Star = 0x001c,
148 Slash = 0x001d,
149 Percent = 0x001e,
150 Equals = 0x001f,
151 Tilde = 0x0020,
152 Pipe = 0x0021,
153 Caret = 0x0022,
154 Dollar = 0x0023,
155 Ampersand = 0x0024,
156 GreaterThan = 0x0025,
157 LessThan = 0x0026,
158 PlusEquals = 0x0027,
159 MinusEquals = 0x0028,
160 StarEquals = 0x0029,
161 SlashEquals = 0x002a,
162 PipeEquals = 0x002b,
163 TildeEquals = 0x002c,
164 CaretEquals = 0x002d,
165 DollarEquals = 0x002e,
166 DoubleColon = 0x002f,
167 DoublePipe = 0x0030,
168 DoubleAmpersand = 0x0031,
169 Arrow = 0x0032,
170 IncludesMatch = 0x0033,
171 DashMatch = 0x0034,
172 PrefixMatch = 0x0035,
173 SuffixMatch = 0x0036,
174 SubstringMatch = 0x0037,
175 ColumnCombinator = 0x0038,
176 NestingSelector = 0x0039,
177 CustomPropertyName = 0x003a,
178 ClassName = 0x003b,
179 IdName = 0x003c,
180 KeywordAnd = 0x003d,
181 KeywordOr = 0x003e,
182 KeywordNot = 0x003f,
183 KeywordOnly = 0x0040,
184 KeywordFrom = 0x0041,
185 KeywordTo = 0x0042,
186 KeywordThrough = 0x0043,
187 KeywordImportant = 0x0044,
188 KeywordGlobal = 0x0045,
189 KeywordLocal = 0x0046,
190 KeywordExport = 0x0047,
191 KeywordImport = 0x0048,
192 KeywordComposes = 0x0049,
193 KeywordAs = 0x004a,
194 KeywordWith = 0x004b,
195 KeywordLayer = 0x004c,
196 KeywordSupports = 0x004d,
197 KeywordContainer = 0x004e,
198 KeywordScope = 0x004f,
199 KeywordMedia = 0x0050,
200 KeywordKeyframes = 0x0051,
201 KeywordCharset = 0x0052,
202 KeywordNamespace = 0x0053,
203 KeywordPage = 0x0054,
204 KeywordFontFace = 0x0055,
205 KeywordProperty = 0x0056,
206 KeywordStartingStyle = 0x0057,
207 KeywordWhen = 0x0058,
208 KeywordElse = 0x0059,
209 KeywordUse = 0x005a,
210 KeywordForward = 0x005b,
211 KeywordMixin = 0x005c,
212 KeywordInclude = 0x005d,
213 KeywordFunction = 0x005e,
214 KeywordReturn = 0x005f,
215 KeywordIf = 0x0060,
216 KeywordEach = 0x0061,
217 KeywordFor = 0x0062,
218 KeywordWhile = 0x0063,
219 KeywordIn = 0x0064,
220 Cdo = 0x0065,
221 Cdc = 0x0066,
222
223 ScssVariable = 0x0400,
224 ScssInterpolationStart = 0x0401,
225 ScssInterpolationEnd = 0x0402,
226 ScssSilentComment = 0x0403,
227 ScssPlaceholder = 0x0404,
228 ScssModuleNamespace = 0x0405,
229 SassIndentedNewline = 0x0406,
230 SassIndent = 0x0407,
231 SassDedent = 0x0408,
232 SassOptionalSemicolon = 0x0409,
233 LessVariable = 0x0410,
234 LessEscapedString = 0x0411,
235 LessDetachedRuleset = 0x0412,
236 LessMixinGuardWhen = 0x0413,
237 LessExtendKeyword = 0x0414,
238 LessNamespaceSeparator = 0x0415,
239 LessInterpolationStart = 0x0416,
240 LessInterpolationEnd = 0x0417,
241 LessPropertyVariableToken = 0x0418,
242 TemplateInterpolationStart = 0x0419,
243 TemplateInterpolationEnd = 0x041a,
244 TemplatePlaceholder = 0x041b,
245
246 Stylesheet = 0x1000,
247 Rule = 0x1001,
248 QualifiedRule = 0x1002,
249 Declaration = 0x1003,
250 DeclarationList = 0x1004,
251 RuleList = 0x1005,
252 SelectorList = 0x1006,
253 Selector = 0x1007,
254 ComplexSelector = 0x1008,
255 CompoundSelector = 0x1009,
256 ClassSelector = 0x100a,
257 IdSelector = 0x100b,
258 TypeSelector = 0x100c,
259 UniversalSelector = 0x100d,
260 AttributeSelector = 0x100e,
261 AttributeMatcher = 0x100f,
262 PseudoClassSelector = 0x1010,
263 PseudoElementSelector = 0x1011,
264 PseudoSelectorArgument = 0x1012,
265 NestingSelectorNode = 0x1013,
266 Combinator = 0x1014,
267 SelectorValue = 0x1015,
268 PropertyName = 0x1016,
269 CustomPropertyDeclaration = 0x1017,
270 Value = 0x1018,
271 ValueList = 0x1019,
272 FunctionCall = 0x101a,
273 FunctionArguments = 0x101b,
274 BinaryExpression = 0x101c,
275 UnaryExpression = 0x101d,
276 ParenthesizedExpression = 0x101e,
277 Interpolation = 0x101f,
278 DimensionValue = 0x1020,
279 ColorValue = 0x1021,
280 UrlValue = 0x1022,
281 VarFunction = 0x1023,
282 CalcFunction = 0x1024,
283 AtRule = 0x1025,
284 MediaRule = 0x1026,
285 SupportsRule = 0x1027,
286 ContainerRule = 0x1028,
287 LayerRule = 0x1029,
288 ScopeRule = 0x102a,
289 KeyframesRule = 0x102b,
290 KeyframeBlock = 0x102c,
291 FontFaceRule = 0x102d,
292 PageRule = 0x102e,
293 NamespaceRule = 0x102f,
294 ImportRule = 0x1030,
295 CharsetRule = 0x1031,
296 PropertyRule = 0x1032,
297 StartingStyleRule = 0x1033,
298 MediaQueryList = 0x1034,
299 MediaQuery = 0x1035,
300 MediaFeature = 0x1036,
301 SupportsCondition = 0x1037,
302 ContainerCondition = 0x1038,
303 LayerName = 0x1039,
304 ScopeRange = 0x103a,
305 CssModuleLocalBlock = 0x103b,
306 CssModuleGlobalBlock = 0x103c,
307 CssModuleExportBlock = 0x103d,
308 CssModuleImportBlock = 0x103e,
309 CssModuleComposesDeclaration = 0x103f,
310 CssModuleComposesTarget = 0x1040,
311 CssModuleFromClause = 0x1041,
312 TokenDefinition = 0x1042,
313 TokenReference = 0x1043,
314 Comment = 0x1044,
315 ErrorNode = 0x1045,
316 EnvFunction = 0x1046,
317 AttrFunction = 0x1047,
318 MathFunction = 0x1048,
319 PageMarginRule = 0x1049,
320 WhenRule = 0x104a,
321 ElseRule = 0x104b,
322 CounterStyleRule = 0x104c,
323 FontPaletteValuesRule = 0x104d,
324 ColorProfileRule = 0x104e,
325 PositionTryRule = 0x104f,
326 FontFeatureValuesRule = 0x1050,
327 FontFeatureValuesStylisticRule = 0x1051,
328 FontFeatureValuesStylesetRule = 0x1052,
329 FontFeatureValuesCharacterVariantRule = 0x1053,
330 FontFeatureValuesSwashRule = 0x1054,
331 FontFeatureValuesOrnamentsRule = 0x1055,
332 FontFeatureValuesAnnotationRule = 0x1056,
333 FontFeatureValuesHistoricalFormsRule = 0x1057,
334 ViewTransitionRule = 0x1058,
335 GradientFunction = 0x1059,
336 TransformFunction = 0x105a,
337 FilterFunction = 0x105b,
338 ImageFunction = 0x105c,
339 ShapeFunction = 0x105d,
340 AtRulePrelude = 0x105e,
341 NestRule = 0x105f,
342 CustomMediaRule = 0x1060,
343 IdentifierValue = 0x1061,
344 StringValue = 0x1062,
345 UnicodeRangeValue = 0x1063,
346 NumberValue = 0x1064,
347 PercentageValue = 0x1065,
348 BracketedValue = 0x1066,
349 ImportantAnnotation = 0x1067,
350 ComponentValue = 0x1068,
351 SimpleBlock = 0x1069,
352 ComponentValueList = 0x106a,
353 CommaSeparatedComponentValueList = 0x106b,
354 CustomPropertyValue = 0x106c,
355 AttributeName = 0x106d,
356 AttributeValue = 0x106e,
357 AttributeModifier = 0x106f,
358 NthSelectorArgument = 0x1070,
359 NthSelectorFormula = 0x1071,
360 NthSelectorOfSelectorList = 0x1072,
361 RelativeSelectorList = 0x1073,
362 RelativeSelector = 0x1074,
363 LanguageSelectorArgument = 0x1075,
364 LanguageTag = 0x1076,
365 DirectionalitySelectorArgument = 0x1077,
366 NamespacePrefix = 0x1078,
367 FunctionRule = 0x1079,
368 IfFunction = 0x107a,
369 IfRule = 0x107b,
370
371 ScssStylesheet = 0x1400,
372 ScssUseRule = 0x1401,
373 ScssForwardRule = 0x1402,
374 ScssMixinDeclaration = 0x1403,
375 ScssIncludeRule = 0x1404,
376 ScssFunctionDeclaration = 0x1405,
377 ScssReturnRule = 0x1406,
378 ScssVariableDeclaration = 0x1407,
379 ScssVariableReference = 0x1408,
380 ScssPlaceholderSelector = 0x1409,
381 ScssExtendRule = 0x140a,
382 ScssControlIf = 0x140b,
383 ScssControlElse = 0x140c,
384 ScssControlEach = 0x140d,
385 ScssControlFor = 0x140e,
386 ScssControlWhile = 0x140f,
387 ScssNestedProperty = 0x1410,
388 ScssModuleConfig = 0x1411,
389 SassIndentedBlock = 0x1412,
390 SassIndentedRule = 0x1413,
391 ScssAtRootRule = 0x1414,
392 ScssErrorRule = 0x1415,
393 ScssWarnRule = 0x1416,
394 ScssDebugRule = 0x1417,
395 ScssContentRule = 0x1418,
396 ScssVariableFlag = 0x1419,
397 LessStylesheet = 0x1420,
398 LessVariableDeclaration = 0x1421,
399 LessVariableReference = 0x1422,
400 LessMixinDeclaration = 0x1423,
401 LessMixinCall = 0x1424,
402 LessMixinGuard = 0x1425,
403 LessDetachedRulesetNode = 0x1426,
404 LessExtendRule = 0x1427,
405 LessNamespaceAccess = 0x1428,
406 LessPropertyVariable = 0x1429,
407 ScssMap = 0x142a,
408 ScssMapEntry = 0x142b,
409 ScssList = 0x142c,
410 ScssCondition = 0x142d,
411 LessCondition = 0x142e,
412
413 BogusToken = 0x2000,
414 BogusTrivia = 0x2001,
415 BogusRule = 0x2002,
416 BogusSelector = 0x2003,
417 BogusSelectorList = 0x2004,
418 BogusCompoundSelector = 0x2005,
419 BogusCombinator = 0x2006,
420 BogusDeclaration = 0x2007,
421 BogusDeclarationList = 0x2008,
422 BogusPropertyName = 0x2009,
423 BogusValue = 0x200a,
424 BogusValueList = 0x200b,
425 BogusFunctionCall = 0x200c,
426 BogusFunctionArguments = 0x200d,
427 BogusAtRule = 0x200e,
428 BogusMediaQuery = 0x200f,
429 BogusSupportsCondition = 0x2010,
430 BogusContainerCondition = 0x2011,
431 BogusLayerName = 0x2012,
432 BogusScopeRange = 0x2013,
433 BogusKeyframeBlock = 0x2014,
434 BogusCssModuleBlock = 0x2015,
435 BogusComposesDeclaration = 0x2016,
436 BogusComposesTarget = 0x2017,
437 BogusFromClause = 0x2018,
438 BogusInterpolation = 0x2019,
439 BogusScssVariable = 0x201a,
440 BogusScssMixin = 0x201b,
441 BogusScssFunction = 0x201c,
442 BogusScssControl = 0x201d,
443 BogusSassIndentation = 0x201e,
444 BogusLessVariable = 0x201f,
445 BogusLessMixin = 0x2020,
446 BogusLessGuard = 0x2021,
447 BogusLessDetachedRuleset = 0x2022,
448 BogusRecovery = 0x2023,
449 BogusScssModuleConfig = 0x2024,
450 BogusAtRulePrelude = 0x2025,
451 BogusBracketedValue = 0x2026,
452 BogusSimpleBlock = 0x2027,
453 BogusScssMap = 0x2028,
454 BogusScssMapEntry = 0x2029,
455 BogusScssList = 0x202a,
456 BogusScssCondition = 0x202b,
457 BogusLessCondition = 0x202c,
458
459 Root = 0x2100,
460 Eof = 0x2101,
461 Unknown = 0x21fe,
462 Tombstone = 0x21ff,
463}
464
465impl Syntax for SyntaxKind {
466 fn from_raw(raw: RawSyntaxKind) -> Self {
467 match Self::from_raw_kind(raw.0) {
468 Some(kind) => kind,
469 None => Self::Unknown,
470 }
471 }
472
473 fn into_raw(self) -> RawSyntaxKind {
474 RawSyntaxKind(self.as_u32())
475 }
476
477 fn static_text(self) -> Option<&'static str> {
478 match self {
479 Self::Dot => Some("."),
480 Self::Comma => Some(","),
481 Self::Colon => Some(":"),
482 Self::Semicolon => Some(";"),
483 Self::LeftBrace => Some("{"),
484 Self::RightBrace => Some("}"),
485 Self::LeftParen => Some("("),
486 Self::RightParen => Some(")"),
487 Self::LeftBracket => Some("["),
488 Self::RightBracket => Some("]"),
489 Self::Plus => Some("+"),
490 Self::Minus => Some("-"),
491 Self::Star => Some("*"),
492 Self::Slash => Some("/"),
493 Self::Percent => Some("%"),
494 Self::Equals => Some("="),
495 Self::Tilde => Some("~"),
496 Self::Pipe => Some("|"),
497 Self::Caret => Some("^"),
498 Self::Dollar => Some("$"),
499 Self::Ampersand => Some("&"),
500 Self::GreaterThan => Some(">"),
501 Self::LessThan => Some("<"),
502 Self::PlusEquals => Some("+="),
503 Self::MinusEquals => Some("-="),
504 Self::StarEquals => Some("*="),
505 Self::SlashEquals => Some("/="),
506 Self::PipeEquals => Some("|="),
507 Self::TildeEquals => Some("~="),
508 Self::CaretEquals => Some("^="),
509 Self::DollarEquals => Some("$="),
510 Self::DoubleColon => Some("::"),
511 Self::DoublePipe => Some("||"),
512 Self::DoubleAmpersand => Some("&&"),
513 Self::Arrow => Some("=>"),
514 Self::IncludesMatch => Some("~="),
515 Self::DashMatch => Some("|="),
516 Self::PrefixMatch => Some("^="),
517 Self::SuffixMatch => Some("$="),
518 Self::SubstringMatch => Some("*="),
519 Self::ColumnCombinator => Some("||"),
520 Self::KeywordAnd => Some("and"),
521 Self::KeywordOr => Some("or"),
522 Self::KeywordNot => Some("not"),
523 Self::KeywordOnly => Some("only"),
524 Self::KeywordFrom => Some("from"),
525 Self::KeywordTo => Some("to"),
526 Self::KeywordThrough => Some("through"),
527 Self::KeywordImportant => Some("important"),
528 Self::Cdo => Some("<!--"),
529 Self::Cdc => Some("-->"),
530 Self::KeywordGlobal => Some("global"),
531 Self::KeywordLocal => Some("local"),
532 Self::KeywordExport => Some("export"),
533 Self::KeywordImport => Some("import"),
534 Self::KeywordComposes => Some("composes"),
535 Self::KeywordAs => Some("as"),
536 Self::KeywordWith => Some("with"),
537 Self::KeywordLayer => Some("layer"),
538 Self::KeywordSupports => Some("supports"),
539 Self::KeywordContainer => Some("container"),
540 Self::KeywordScope => Some("scope"),
541 Self::KeywordMedia => Some("media"),
542 Self::KeywordKeyframes => Some("keyframes"),
543 Self::KeywordCharset => Some("charset"),
544 Self::KeywordNamespace => Some("namespace"),
545 Self::KeywordPage => Some("page"),
546 Self::KeywordFontFace => Some("font-face"),
547 Self::KeywordProperty => Some("property"),
548 Self::KeywordStartingStyle => Some("starting-style"),
549 Self::KeywordWhen => Some("when"),
550 Self::KeywordElse => Some("else"),
551 Self::KeywordUse => Some("use"),
552 Self::KeywordForward => Some("forward"),
553 Self::KeywordMixin => Some("mixin"),
554 Self::KeywordInclude => Some("include"),
555 Self::KeywordFunction => Some("function"),
556 Self::KeywordReturn => Some("return"),
557 Self::KeywordIf => Some("if"),
558 Self::KeywordEach => Some("each"),
559 Self::KeywordFor => Some("for"),
560 Self::KeywordWhile => Some("while"),
561 Self::KeywordIn => Some("in"),
562 Self::Eof => Some(""),
563 _ => None,
564 }
565 }
566}
567
568#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
569pub enum StyleDialect {
570 Css,
571 Scss,
572 Sass,
573 Less,
574}
575
576impl StyleDialect {
577 pub const ALL: &'static [Self] = &[Self::Css, Self::Scss, Self::Sass, Self::Less];
578}
579
580#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
581pub enum ModuleMode {
582 Plain,
583 CssModules,
584}
585
586impl ModuleMode {
587 pub const ALL: &'static [Self] = &[Self::Plain, Self::CssModules];
588}
589
590#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
591pub enum SymbolKind {
592 Class,
593 Id,
594 TypeSelector,
595 PlaceholderSelector,
596 Keyframes,
597 CustomProperty,
598 ScssVariable,
599 LessVariable,
600 Mixin,
601 Function,
602 ValueDeclaration,
603 ComposesTarget,
604 Namespace,
605 Layer,
606 Container,
607 Scope,
608 Import,
609 Export,
610 ModuleLocal,
611 ModuleGlobal,
612}
613
614impl SymbolKind {
615 pub const ALL: &'static [Self] = &[
616 Self::Class,
617 Self::Id,
618 Self::TypeSelector,
619 Self::PlaceholderSelector,
620 Self::Keyframes,
621 Self::CustomProperty,
622 Self::ScssVariable,
623 Self::LessVariable,
624 Self::Mixin,
625 Self::Function,
626 Self::ValueDeclaration,
627 Self::ComposesTarget,
628 Self::Namespace,
629 Self::Layer,
630 Self::Container,
631 Self::Scope,
632 Self::Import,
633 Self::Export,
634 Self::ModuleLocal,
635 Self::ModuleGlobal,
636 ];
637}
638
639#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
640pub enum ScopeKind {
641 File,
642 LocalBlock,
643 GlobalBlock,
644 SelectorBlock,
645 MixinBody,
646 FunctionBody,
647 AtRuleScope,
648 NestedRule,
649 ScopeAtRule,
650 MediaQuery,
651 SupportsQuery,
652 ContainerQuery,
653 CascadeLayer,
654 ModuleNamespace,
655 LessMixin,
656 SassControlFlow,
657 CssModuleExport,
658 CssModuleImport,
659}
660
661impl ScopeKind {
662 pub const ALL: &'static [Self] = &[
663 Self::File,
664 Self::LocalBlock,
665 Self::GlobalBlock,
666 Self::SelectorBlock,
667 Self::MixinBody,
668 Self::FunctionBody,
669 Self::AtRuleScope,
670 Self::NestedRule,
671 Self::ScopeAtRule,
672 Self::MediaQuery,
673 Self::SupportsQuery,
674 Self::ContainerQuery,
675 Self::CascadeLayer,
676 Self::ModuleNamespace,
677 Self::LessMixin,
678 Self::SassControlFlow,
679 Self::CssModuleExport,
680 Self::CssModuleImport,
681 ];
682}
683
684#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
685pub enum ReferenceKind {
686 Class,
687 Id,
688 TypeSelector,
689 PlaceholderSelector,
690 Keyframes,
691 ComposesTarget,
692 ComposesFrom,
693 CustomPropertyRead,
694 VarRead,
695 ValueRead,
696 Import,
697 Export,
698 MixinInclude,
699 FunctionCall,
700 NamespaceMember,
701 Layer,
702 Container,
703 SelectorExtends,
704 CssModuleAccess,
705 CssModuleToken,
706}
707
708impl ReferenceKind {
709 pub const ALL: &'static [Self] = &[
710 Self::Class,
711 Self::Id,
712 Self::TypeSelector,
713 Self::PlaceholderSelector,
714 Self::Keyframes,
715 Self::ComposesTarget,
716 Self::ComposesFrom,
717 Self::CustomPropertyRead,
718 Self::VarRead,
719 Self::ValueRead,
720 Self::Import,
721 Self::Export,
722 Self::MixinInclude,
723 Self::FunctionCall,
724 Self::NamespaceMember,
725 Self::Layer,
726 Self::Container,
727 Self::SelectorExtends,
728 Self::CssModuleAccess,
729 Self::CssModuleToken,
730 ];
731}
732
733#[derive(Debug, Clone, PartialEq, Eq)]
734pub struct OmenaSyntaxBoundarySummaryV0 {
735 pub schema_version: &'static str,
736 pub product: &'static str,
737 pub phase: &'static str,
738 pub syntax_kind_owner_crate: &'static str,
739 pub parser_consumer_policy: &'static str,
740 pub syntax_kind_count: usize,
741 pub token_kind_count: usize,
742 pub node_kind_count: usize,
743 pub bogus_kind_count: usize,
744 pub marker_kind_count: usize,
745 pub dialect_kind_count: usize,
746 pub style_dialect_count: usize,
747 pub module_mode_count: usize,
748 pub symbol_kind_count: usize,
749 pub scope_kind_count: usize,
750 pub reference_kind_count: usize,
751 pub cstree_integration_ready: bool,
752 pub ready_surfaces: Vec<&'static str>,
753 pub next_surfaces: Vec<&'static str>,
754}
755
756pub fn summarize_omena_syntax_boundary() -> OmenaSyntaxBoundarySummaryV0 {
757 OmenaSyntaxBoundarySummaryV0 {
758 schema_version: "0",
759 product: "omena-syntax.boundary",
760 phase: "h1-alpha-syntax-substrate",
761 syntax_kind_owner_crate: "omena-syntax",
762 parser_consumer_policy: "parserConsumesOmenaSyntaxKindNoLocalTaxonomy",
763 syntax_kind_count: SyntaxKind::ALL.len(),
764 token_kind_count: SyntaxKind::ALL
765 .iter()
766 .filter(|kind| kind.is_token())
767 .count(),
768 node_kind_count: SyntaxKind::ALL.iter().filter(|kind| kind.is_node()).count(),
769 bogus_kind_count: SyntaxKind::ALL
770 .iter()
771 .filter(|kind| kind.is_bogus())
772 .count(),
773 marker_kind_count: SyntaxKind::ALL
774 .iter()
775 .filter(|kind| kind.is_marker())
776 .count(),
777 dialect_kind_count: SyntaxKind::ALL
778 .iter()
779 .filter(|kind| kind.is_dialect())
780 .count(),
781 style_dialect_count: StyleDialect::ALL.len(),
782 module_mode_count: ModuleMode::ALL.len(),
783 symbol_kind_count: SymbolKind::ALL.len(),
784 scope_kind_count: ScopeKind::ALL.len(),
785 reference_kind_count: ReferenceKind::ALL.len(),
786 cstree_integration_ready: SyntaxKind::Ident.into_raw()
787 == RawSyntaxKind(SyntaxKind::Ident.as_u32())
788 && SyntaxKind::from_raw(RawSyntaxKind(SyntaxKind::Ident.as_u32())) == SyntaxKind::Ident,
789 ready_surfaces: vec![
790 "rangeDividedSyntaxKind",
791 "symbolScopeReferenceVocabulary",
792 "styleDialectAndModuleMode",
793 "cstreeRawKindBridge",
794 "bogusRecoveryKindSuperset",
795 "semanticSoaTables",
796 "parserCstEquivalence",
797 ],
798 next_surfaces: Vec::new(),
799 }
800}
801
802#[cfg(test)]
803mod tests {
804 use super::*;
805
806 #[test]
807 fn syntax_kind_ranges_are_disjoint() {
808 let mut raws: Vec<u32> = SyntaxKind::ALL.iter().map(|kind| kind.as_u32()).collect();
809 raws.sort_unstable();
810
811 for pair in raws.windows(2) {
812 assert_ne!(pair[0], pair[1]);
813 }
814 }
815
816 #[test]
817 fn classifies_token_node_bogus_marker_ranges() {
818 assert!(SyntaxKind::Ident.is_token());
819 assert!(SyntaxKind::ScssVariable.is_token());
820 assert!(SyntaxKind::Selector.is_node());
821 assert!(SyntaxKind::LessMixinCall.is_node());
822 assert!(SyntaxKind::BogusSelector.is_bogus());
823 assert!(SyntaxKind::Root.is_marker());
824 assert!(SyntaxKind::Whitespace.is_trivia());
825 assert!(SyntaxKind::ScssUseRule.is_dialect_specific());
826 }
827
828 #[test]
829 fn declares_four_style_dialects_and_module_modes() {
830 assert_eq!(StyleDialect::ALL.len(), 4);
831 assert_eq!(ModuleMode::ALL.len(), 2);
832 }
833
834 #[test]
835 fn cstree_round_trip_preserves_known_kinds() {
836 for kind in [
837 SyntaxKind::Ident,
838 SyntaxKind::Selector,
839 SyntaxKind::ScssUseRule,
840 SyntaxKind::BogusLessGuard,
841 SyntaxKind::Root,
842 ] {
843 let raw = kind.into_raw();
844 assert_eq!(SyntaxKind::from_raw(raw), kind);
845 }
846 }
847
848 #[test]
849 fn syntax_kind_raw_decode_round_trips_every_declared_kind() {
850 for kind in SyntaxKind::ALL {
851 assert_eq!(SyntaxKind::from_raw_kind(kind.as_u32()), Some(*kind));
852 assert_eq!(SyntaxKind::from_raw(kind.into_raw()), *kind);
853 }
854 }
855
856 #[test]
857 fn syntax_kind_raw_decode_rejects_unassigned_raw_values() {
858 let assigned: std::collections::BTreeSet<u32> =
859 SyntaxKind::ALL.iter().map(|kind| kind.as_u32()).collect();
860 let rejected: Vec<u32> = (TOKEN_START..=MARKER_END)
861 .filter(|raw| !assigned.contains(raw))
862 .take(8)
863 .collect();
864
865 assert_eq!(rejected.len(), 8);
866 for raw in rejected {
867 assert_eq!(SyntaxKind::from_raw_kind(raw), None);
868 assert_eq!(
869 SyntaxKind::from_raw(RawSyntaxKind(raw)),
870 SyntaxKind::Unknown
871 );
872 }
873 }
874
875 #[test]
876 fn declares_bogus_superset_contract() {
877 let bogus_count = SyntaxKind::ALL
878 .iter()
879 .filter(|kind| kind.is_bogus())
880 .count();
881
882 assert!(bogus_count >= 33);
883 }
884
885 #[test]
886 fn syntax_kind_count_tracks_phase_alpha_contract() {
887 let token_count = SyntaxKind::ALL
888 .iter()
889 .filter(|kind| kind.is_token())
890 .count();
891 let node_count = SyntaxKind::ALL.iter().filter(|kind| kind.is_node()).count();
892
893 assert!(SyntaxKind::ALL.len() >= 160);
894 assert!(token_count >= 80);
895 assert!(node_count >= 80);
896 }
897
898 #[test]
899 fn summarizes_phase_alpha_boundary_contract() {
900 let summary = summarize_omena_syntax_boundary();
901
902 assert_eq!(summary.product, "omena-syntax.boundary");
903 assert_eq!(summary.phase, "h1-alpha-syntax-substrate");
904 assert_eq!(summary.syntax_kind_owner_crate, "omena-syntax");
905 assert_eq!(
906 summary.parser_consumer_policy,
907 "parserConsumesOmenaSyntaxKindNoLocalTaxonomy"
908 );
909 assert!(summary.syntax_kind_count >= 160);
910 assert!(summary.bogus_kind_count >= 33);
911 assert_eq!(summary.style_dialect_count, 4);
912 assert_eq!(summary.module_mode_count, 2);
913 assert_eq!(summary.symbol_kind_count, SymbolKind::ALL.len());
914 assert_eq!(summary.scope_kind_count, ScopeKind::ALL.len());
915 assert_eq!(summary.reference_kind_count, ReferenceKind::ALL.len());
916 assert!(summary.cstree_integration_ready);
917 assert!(SyntaxKind::ScssUseRule.is_dialect());
918 assert!(
919 summary
920 .ready_surfaces
921 .contains(&"symbolScopeReferenceVocabulary")
922 );
923 assert!(summary.ready_surfaces.contains(&"semanticSoaTables"));
924 assert!(summary.ready_surfaces.contains(&"parserCstEquivalence"));
925 assert!(!summary.next_surfaces.contains(&"semanticSoaTables"));
926 assert!(!summary.next_surfaces.contains(&"parserCstEquivalence"));
927 }
928}