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