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