mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
Add UnescapedName
and make Name
hold escaped name
This commit is contained in:
parent
e70681f208
commit
53ec791dc6
1 changed files with 52 additions and 2 deletions
|
@ -7,6 +7,10 @@ use syntax::{ast, SmolStr, SyntaxKind};
|
|||
/// `Name` is a wrapper around string, which is used in hir for both references
|
||||
/// and declarations. In theory, names should also carry hygiene info, but we are
|
||||
/// not there yet!
|
||||
///
|
||||
/// Note that `Name` holds and prints escaped name i.e. prefixed with "r#" when it
|
||||
/// is a raw identifier. Use [`unescaped()`][Name::unescaped] when you need the
|
||||
/// name without "r#".
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Name(Repr);
|
||||
|
||||
|
@ -14,6 +18,10 @@ pub struct Name(Repr);
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct EscapedName<'a>(&'a Name);
|
||||
|
||||
/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct UnescapedName<'a>(&'a Name);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
enum Repr {
|
||||
Text(SmolStr),
|
||||
|
@ -49,6 +57,35 @@ impl<'a> fmt::Display for EscapedName<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for UnescapedName<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.0 .0 {
|
||||
Repr::Text(text) => {
|
||||
let text = text.strip_prefix("r#").unwrap_or(text);
|
||||
fmt::Display::fmt(&text, f)
|
||||
}
|
||||
Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UnescapedName<'a> {
|
||||
/// Returns the textual representation of this name as a [`SmolStr`]. Prefer using this over
|
||||
/// [`ToString::to_string`] if possible as this conversion is cheaper in the general case.
|
||||
pub fn to_smol_str(&self) -> SmolStr {
|
||||
match &self.0 .0 {
|
||||
Repr::Text(it) => {
|
||||
if let Some(stripped) = it.strip_prefix("r#") {
|
||||
SmolStr::new(stripped)
|
||||
} else {
|
||||
it.clone()
|
||||
}
|
||||
}
|
||||
Repr::TupleField(it) => SmolStr::new(&it.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EscapedName<'a> {
|
||||
pub fn is_escaped(&self) -> bool {
|
||||
match &self.0 .0 {
|
||||
|
@ -97,9 +134,11 @@ impl Name {
|
|||
|
||||
/// Resolve a name from the text of token.
|
||||
fn resolve(raw_text: &str) -> Name {
|
||||
// When `raw_text` starts with "r#" but the name does not coincide with any
|
||||
// keyword, we never need the prefix so we strip it.
|
||||
match raw_text.strip_prefix("r#") {
|
||||
Some(text) => Name::new_text(SmolStr::new(text)),
|
||||
None => Name::new_text(raw_text.into()),
|
||||
Some(text) if !is_raw_identifier(text) => Name::new_text(SmolStr::new(text)),
|
||||
_ => Name::new_text(raw_text.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +184,17 @@ impl Name {
|
|||
pub fn escaped(&self) -> EscapedName<'_> {
|
||||
EscapedName(self)
|
||||
}
|
||||
|
||||
pub fn unescaped(&self) -> UnescapedName<'_> {
|
||||
UnescapedName(self)
|
||||
}
|
||||
|
||||
pub fn is_escaped(&self) -> bool {
|
||||
match &self.0 {
|
||||
Repr::Text(it) => it.starts_with("r#"),
|
||||
Repr::TupleField(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsName {
|
||||
|
|
Loading…
Reference in a new issue