use mun_syntax::{ast, SmolStr};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(Repr);
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum Repr {
Text(SmolStr),
TupleField(usize),
}
impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.0 {
Repr::Text(text) => fmt::Display::fmt(&text, f),
Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
}
}
}
impl Name {
const fn new_text(text: SmolStr) -> Name {
Name(Repr::Text(text))
}
pub(crate) fn new_tuple_field(idx: usize) -> Name {
Name(Repr::TupleField(idx))
}
const fn new_inline(text: &str) -> Name {
Name::new_text(SmolStr::new_inline(text))
}
fn resolve(raw_text: &str) -> Name {
match raw_text.strip_prefix("r#") {
Some(text) => Name::new_text(SmolStr::new(text)),
None => Name::new_text(raw_text.into()),
}
}
pub(crate) fn new(text: impl AsRef<str>) -> Name {
Name::new_text(SmolStr::new(text))
}
pub(crate) fn missing() -> Name {
Name::new_text("[missing name]".into())
}
pub(crate) fn as_tuple_index(&self) -> Option<usize> {
match self.0 {
Repr::TupleField(idx) => Some(idx),
_ => None,
}
}
}
pub(crate) trait AsName {
fn as_name(&self) -> Name;
}
impl AsName for ast::NameRef {
fn as_name(&self) -> Name {
match self.as_tuple_field() {
Some(idx) => Name::new_tuple_field(idx),
None => Name::resolve(&self.text()),
}
}
}
impl AsName for ast::Name {
fn as_name(&self) -> Name {
Name::resolve(&self.text())
}
}
impl AsName for ast::FieldKind {
fn as_name(&self) -> Name {
match self {
ast::FieldKind::Name(nr) => nr.as_name(),
ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text()[1..].parse().unwrap()),
}
}
}
pub mod known {
macro_rules! known_names {
($($ident:ident),* $(,)?) => {
$(
#[allow(bad_style)]
pub const $ident: super::Name =
super::Name::new_inline(stringify!($ident));
)*
};
}
known_names!(
int, isize, i8, i16, i32, i64, i128, uint, usize, u8, u16, u32, u64, u128, float, f32, f64,
bool,
);
#[macro_export]
macro_rules! name {
($ident:ident) => {
$crate::name::known::$ident
};
}
}
pub use crate::name;