Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/name.rs')
-rw-r--r--crates/hir-expand/src/name.rs106
1 files changed, 40 insertions, 66 deletions
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index cc53d2e34a..848870c3a3 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -4,8 +4,8 @@ use std::fmt;
use intern::{sym, Symbol};
use span::{Edition, SyntaxContextId};
-use syntax::ast;
use syntax::utils::is_raw_identifier;
+use syntax::{ast, format_smolstr};
/// `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
@@ -51,33 +51,26 @@ impl PartialEq<Symbol> for Name {
}
}
+impl PartialEq<&Symbol> for Name {
+ fn eq(&self, &sym: &&Symbol) -> bool {
+ self.symbol == *sym
+ }
+}
+
impl PartialEq<Name> for Symbol {
fn eq(&self, name: &Name) -> bool {
*self == name.symbol
}
}
-/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct UnescapedName<'a>(&'a Name);
-
-impl<'a> UnescapedName<'a> {
- pub fn display(self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
- _ = db;
- UnescapedDisplay { name: self }
- }
- #[doc(hidden)]
- pub fn display_no_db(self) -> impl fmt::Display + 'a {
- UnescapedDisplay { name: self }
+impl PartialEq<Name> for &Symbol {
+ fn eq(&self, name: &Name) -> bool {
+ **self == name.symbol
}
}
impl Name {
- /// Note: this is private to make creating name from random string hard.
- /// Hopefully, this should allow us to integrate hygiene cleaner in the
- /// future, and to switch to interned representation of names.
fn new_text(text: &str) -> Name {
- debug_assert!(!text.starts_with("r#"));
Name { symbol: Symbol::intern(text), ctx: () }
}
@@ -87,12 +80,15 @@ impl Name {
// Can't do that for all `SyntaxContextId`s because it breaks Salsa.
ctx.remove_root_edition();
_ = ctx;
- Self::new_text(text)
+ match text.strip_prefix("r#") {
+ Some(text) => Self::new_text(text),
+ None => Self::new_text(text),
+ }
}
pub fn new_root(text: &str) -> Name {
// The edition doesn't matter for hygiene.
- Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015))
+ Self::new(text, SyntaxContextId::root(Edition::Edition2015))
}
pub fn new_tuple_field(idx: usize) -> Name {
@@ -119,12 +115,22 @@ impl Name {
}
pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
- Self::new_text(lt.text().as_str().trim_start_matches("r#"))
+ let text = lt.text();
+ match text.strip_prefix("'r#") {
+ Some(text) => Self::new_text(&format_smolstr!("'{text}")),
+ None => Self::new_text(text.as_str()),
+ }
+ }
+
+ pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
+ debug_assert!(!symbol.as_str().starts_with("r#"));
+ _ = ctx;
+ Self { symbol, ctx: () }
}
- /// Resolve a name from the text of token.
- fn resolve(raw_text: &str) -> Name {
- Name::new_text(raw_text.trim_start_matches("r#"))
+ // FIXME: This needs to go once we have hygiene
+ pub fn new_symbol_root(sym: Symbol) -> Self {
+ Self::new_symbol(sym, SyntaxContextId::root(Edition::Edition2015))
}
/// A fake name for things missing in the source code.
@@ -161,22 +167,19 @@ impl Name {
self.symbol.as_str().parse().ok()
}
+ /// Whether this name needs to be escaped in the given edition via `r#`.
+ pub fn needs_escape(&self, edition: Edition) -> bool {
+ is_raw_identifier(self.symbol.as_str(), edition)
+ }
+
/// Returns the text this name represents if it isn't a tuple field.
///
/// Do not use this for user-facing text, use `display` instead to handle editions properly.
+ // FIXME: This should take a database argument to hide the interning
pub fn as_str(&self) -> &str {
self.symbol.as_str()
}
- // FIXME: Remove this
- pub fn unescaped(&self) -> UnescapedName<'_> {
- UnescapedName(self)
- }
-
- pub fn needs_escape(&self, edition: Edition) -> bool {
- is_raw_identifier(self.symbol.as_str(), edition)
- }
-
pub fn display<'a>(
&'a self,
db: &dyn crate::db::ExpandDatabase,
@@ -186,7 +189,7 @@ impl Name {
self.display_no_db(edition)
}
- // FIXME: Remove this
+ // FIXME: Remove this in favor of `display`, see fixme on `as_str`
#[doc(hidden)]
pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ {
Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) }
@@ -195,24 +198,6 @@ impl Name {
pub fn symbol(&self) -> &Symbol {
&self.symbol
}
-
- pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
- debug_assert!(!symbol.as_str().starts_with("r#"));
- _ = ctx;
- Self { symbol, ctx: () }
- }
-
- // FIXME: This needs to go once we have hygiene
- pub fn new_symbol_root(sym: Symbol) -> Self {
- debug_assert!(!sym.as_str().starts_with("r#"));
- Self { symbol: sym, ctx: () }
- }
-
- // FIXME: Remove this
- #[inline]
- pub fn eq_ident(&self, ident: &str) -> bool {
- self.as_str() == ident.trim_start_matches("r#")
- }
}
struct Display<'a> {
@@ -229,17 +214,6 @@ impl fmt::Display for Display<'_> {
}
}
-struct UnescapedDisplay<'a> {
- name: UnescapedName<'a>,
-}
-
-impl fmt::Display for UnescapedDisplay<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let symbol = self.name.0.symbol.as_str();
- fmt::Display::fmt(symbol, f)
- }
-}
-
pub trait AsName {
fn as_name(&self) -> Name;
}
@@ -248,14 +222,14 @@ 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()),
+ None => Name::new_root(&self.text()),
}
}
}
impl AsName for ast::Name {
fn as_name(&self) -> Name {
- Name::resolve(&self.text())
+ Name::new_root(&self.text())
}
}
@@ -270,7 +244,7 @@ impl AsName for ast::NameOrNameRef {
impl<Span> AsName for tt::Ident<Span> {
fn as_name(&self) -> Name {
- Name::resolve(self.sym.as_str())
+ Name::new_root(self.sym.as_str())
}
}
@@ -288,6 +262,6 @@ impl AsName for ast::FieldKind {
impl AsName for base_db::Dependency {
fn as_name(&self) -> Name {
- Name::new_text(&self.name)
+ Name::new_root(&self.name)
}
}