#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
#[non_exhaustive]
pub enum SyntaxKind {
Whitespace = 0,
Bom,
LineComment,
BlockComment,
Ident,
Integer,
Float,
String,
RawString,
Char,
TrueKw,
FalseKw,
LParen,
RParen,
LBracket,
RBracket,
LBrace,
RBrace,
Colon,
Comma,
Hash,
Bang,
EnableKw,
LexError,
Root,
Struct,
StructField,
Tuple,
List,
Map,
MapEntry,
EnumVariant,
Unit,
Literal,
ExtensionAttr,
Error,
#[doc(hidden)]
__Last,
}
impl SyntaxKind {
#[inline]
#[must_use]
pub(crate) fn from_raw(raw: u16) -> Option<Self> {
Self::ALL.get(raw as usize).copied()
}
const ALL: &'static [SyntaxKind] = &[
SyntaxKind::Whitespace,
SyntaxKind::Bom,
SyntaxKind::LineComment,
SyntaxKind::BlockComment,
SyntaxKind::Ident,
SyntaxKind::Integer,
SyntaxKind::Float,
SyntaxKind::String,
SyntaxKind::RawString,
SyntaxKind::Char,
SyntaxKind::TrueKw,
SyntaxKind::FalseKw,
SyntaxKind::LParen,
SyntaxKind::RParen,
SyntaxKind::LBracket,
SyntaxKind::RBracket,
SyntaxKind::LBrace,
SyntaxKind::RBrace,
SyntaxKind::Colon,
SyntaxKind::Comma,
SyntaxKind::Hash,
SyntaxKind::Bang,
SyntaxKind::EnableKw,
SyntaxKind::LexError,
SyntaxKind::Root,
SyntaxKind::Struct,
SyntaxKind::StructField,
SyntaxKind::Tuple,
SyntaxKind::List,
SyntaxKind::Map,
SyntaxKind::MapEntry,
SyntaxKind::EnumVariant,
SyntaxKind::Unit,
SyntaxKind::Literal,
SyntaxKind::ExtensionAttr,
SyntaxKind::Error,
];
#[inline]
#[must_use]
pub(crate) fn to_raw(self) -> u16 {
self as u16
}
#[inline]
#[must_use]
pub fn is_trivia(self) -> bool {
matches!(
self,
Self::Whitespace | Self::Bom | Self::LineComment | Self::BlockComment
)
}
#[inline]
#[must_use]
pub fn is_token(self) -> bool {
(self as u16) <= (Self::LexError as u16)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) enum RonLang {}
impl rowan::Language for RonLang {
type Kind = SyntaxKind;
#[inline]
fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
SyntaxKind::from_raw(raw.0).unwrap_or(SyntaxKind::Error)
}
#[inline]
fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
rowan::SyntaxKind(kind.to_raw())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn raw_roundtrip_is_total() {
assert_eq!(
SyntaxKind::ALL.len(),
SyntaxKind::__Last as usize,
"ALL table must list every variant before __Last"
);
let mut raw = 0u16;
while raw < SyntaxKind::__Last as u16 {
let kind = SyntaxKind::from_raw(raw).expect("in-range raw must decode");
assert_eq!(kind.to_raw(), raw, "raw discriminant must round-trip");
raw += 1;
}
}
#[test]
fn out_of_range_raw_is_rejected() {
assert_eq!(SyntaxKind::from_raw(SyntaxKind::__Last as u16), None);
assert_eq!(SyntaxKind::from_raw(u16::MAX), None);
}
#[test]
fn token_node_partition_is_consistent() {
assert!(SyntaxKind::Whitespace.is_token());
assert!(SyntaxKind::LexError.is_token());
assert!(!SyntaxKind::Root.is_token());
assert!(!SyntaxKind::Error.is_token());
}
#[test]
fn trivia_classification() {
assert!(SyntaxKind::Whitespace.is_trivia());
assert!(SyntaxKind::Bom.is_trivia());
assert!(SyntaxKind::LineComment.is_trivia());
assert!(SyntaxKind::BlockComment.is_trivia());
assert!(!SyntaxKind::Ident.is_trivia());
assert!(!SyntaxKind::Comma.is_trivia());
}
}