use serde::Deserialize;
use serde::Serialize;
use strum::Display;
use mago_database::file::FileId;
use mago_span::Position;
use mago_span::Span;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum TypePrecedence {
Lowest,
Conditional,
Union,
Intersection,
Postfix,
Callable,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
pub enum TypeTokenKind {
Int,
Integer,
String,
Float,
Real,
Double,
Bool,
Boolean,
False,
True,
Object,
Callable,
Array,
NonEmptyArray,
NonEmptyString,
NonEmptyLowercaseString,
NonEmptyUppercaseString,
NonFalsyString,
LowercaseString,
UppercaseString,
TruthyString,
Iterable,
Null,
Mixed,
NonEmptyMixed,
NumericString,
ClassString,
InterfaceString,
TraitString,
EnumString,
StringableObject,
PureCallable,
PureClosure,
UnspecifiedLiteralString,
UnspecifiedLiteralInt,
UnspecifiedLiteralFloat,
NonEmptyUnspecifiedLiteralString,
Resource,
Void,
Scalar,
Numeric,
NoReturn,
NeverReturn,
NeverReturns,
Never,
Nothing,
ArrayKey,
List,
NonEmptyList,
OpenResource,
ClosedResource,
AssociativeArray,
KeyOf,
ValueOf,
IntMask,
IntMaskOf,
Min,
Max,
PropertiesOf,
PublicPropertiesOf,
PrivatePropertiesOf,
ProtectedPropertiesOf,
PositiveInt,
NegativeInt,
NonPositiveInt,
NonNegativeInt,
As,
Is,
Not,
Identifier,
QualifiedIdentifier,
FullyQualifiedIdentifier,
Plus,
Minus,
LessThan,
GreaterThan,
Pipe,
Ampersand,
Question,
Exclamation,
Comma,
Colon,
ColonColon,
LeftBrace,
RightBrace,
LeftBracket,
RightBracket,
LeftParenthesis,
RightParenthesis,
Equals,
Ellipsis,
PartialLiteralString,
LiteralString,
LiteralInteger,
LiteralFloat,
Variable,
Whitespace,
SingleLineComment,
Asterisk,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct TypeToken<'input> {
pub kind: TypeTokenKind,
pub start: Position,
pub value: &'input str,
}
impl<'input> TypeToken<'input> {
#[inline]
#[must_use]
pub const fn new(kind: TypeTokenKind, value: &'input str, start: Position) -> Self {
Self { kind, start, value }
}
#[inline]
#[must_use]
pub const fn end(&self) -> Position {
Position::new(self.start.offset + self.value.len() as u32)
}
#[inline]
#[must_use]
pub const fn span_for(&self, file_id: FileId) -> Span {
Span::new(file_id, self.start, self.end())
}
}
impl TypeTokenKind {
#[inline]
#[must_use]
pub const fn is_trivia(&self) -> bool {
matches!(self, Self::SingleLineComment | Self::Whitespace)
}
#[inline]
#[must_use]
pub const fn is_simple_identifier(&self) -> bool {
matches!(self, Self::Identifier)
}
#[inline]
#[must_use]
pub const fn is_identifier(&self) -> bool {
matches!(self, Self::Identifier | Self::QualifiedIdentifier | Self::FullyQualifiedIdentifier)
}
#[inline]
#[must_use]
pub const fn is_keyword(&self) -> bool {
matches!(
self,
Self::Int
| Self::Integer
| Self::Double
| Self::String
| Self::Float
| Self::Real
| Self::Bool
| Self::Boolean
| Self::False
| Self::True
| Self::Object
| Self::Callable
| Self::Array
| Self::NonEmptyArray
| Self::NonEmptyString
| Self::NonEmptyLowercaseString
| Self::LowercaseString
| Self::NonEmptyUppercaseString
| Self::UppercaseString
| Self::TruthyString
| Self::NonFalsyString
| Self::Iterable
| Self::Null
| Self::Mixed
| Self::NonEmptyMixed
| Self::NumericString
| Self::ClassString
| Self::InterfaceString
| Self::TraitString
| Self::EnumString
| Self::StringableObject
| Self::PureCallable
| Self::PureClosure
| Self::UnspecifiedLiteralString
| Self::UnspecifiedLiteralFloat
| Self::NonEmptyUnspecifiedLiteralString
| Self::Resource
| Self::Void
| Self::Scalar
| Self::Numeric
| Self::NoReturn
| Self::NeverReturn
| Self::NeverReturns
| Self::Never
| Self::Nothing
| Self::ArrayKey
| Self::List
| Self::NonEmptyList
| Self::OpenResource
| Self::ClosedResource
| Self::AssociativeArray
| Self::Is
| Self::As
| Self::Not
| Self::KeyOf
| Self::ValueOf
| Self::IntMask
| Self::IntMaskOf
| Self::Min
| Self::Max
| Self::UnspecifiedLiteralInt
| Self::PropertiesOf
| Self::PublicPropertiesOf
| Self::PrivatePropertiesOf
| Self::ProtectedPropertiesOf
| Self::PositiveInt
| Self::NegativeInt
| Self::NonPositiveInt
| Self::NonNegativeInt
)
}
#[inline]
#[must_use]
pub const fn is_array_like(&self) -> bool {
matches!(self, Self::Array | Self::NonEmptyArray | Self::AssociativeArray | Self::List | Self::NonEmptyList)
}
}