use std::{
fmt,
hash::{Hash, Hasher},
};
use crate::span::Span;
#[derive(Clone)]
pub struct Ident {
pub name: String,
pub span: Span,
}
impl Ident {
pub fn new(name: String, span: Span) -> Self {
Ident { name, span }
}
pub fn new_str(name: &str, span: Span) -> Self {
Ident {
name: name.to_string(),
span,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn span(&self) -> Span {
self.span
}
pub fn dummy(name: &str) -> Self {
Ident {
name: name.to_string(),
span: Span::call_site(),
}
}
}
impl PartialEq for Ident {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for Ident {}
impl Hash for Ident {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialOrd for Ident {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Ident {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}
impl fmt::Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Ident({:?})", self.name)
}
}
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
impl AsRef<str> for Ident {
fn as_ref(&self) -> &str {
&self.name
}
}
impl std::borrow::Borrow<str> for Ident {
fn borrow(&self) -> &str {
&self.name
}
}
#[macro_export]
macro_rules! format_ident {
($fmt:expr) => {
$crate::Ident::new_str($fmt, $crate::span::Span::call_site())
};
($fmt:expr, $($arg:tt)*) => {{
let s = std::fmt::format(std::format_args!($fmt, $($arg)*));
$crate::Ident::new(s, $crate::span::Span::call_site())
}};
}
pub fn is_java_identifier_start(ch: char) -> bool {
unicode_xid::UnicodeXID::is_xid_start(ch) || ch == '$' || ch == '_'
}
pub fn is_java_identifier_continue(ch: char) -> bool {
unicode_xid::UnicodeXID::is_xid_continue(ch) || ch == '$'
}
#[allow(dead_code)]
pub fn is_valid_java_identifier(s: &str) -> bool {
if s.is_empty() {
return false;
}
let mut chars = s.chars();
if !is_java_identifier_start(chars.next().unwrap()) {
return false;
}
chars.all(is_java_identifier_continue)
}
#[allow(dead_code)]
pub fn is_valid_type_identifier(s: &str) -> bool {
is_valid_java_identifier(s)
&& !matches!(s, "record" | "sealed" | "var" | "yield" | "permits" | "_")
}