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