Cleanup Name string rendering

This commit is contained in:
Lukas Wirth 2025-01-21 10:05:32 +01:00
parent c78cc2baa9
commit 76585539f5
38 changed files with 145 additions and 249 deletions

View File

@ -10,7 +10,6 @@ use rustc_hash::FxHashSet;
use smallvec::SmallVec;
use span::Edition;
use stdx::{format_to, TupleExt};
use syntax::ToSmolStr;
use triomphe::Arc;
use crate::{
@ -88,9 +87,9 @@ impl ImportMap {
.iter()
// We've only collected items, whose name cannot be tuple field so unwrapping is fine.
.flat_map(|(&item, (info, _))| {
info.iter().enumerate().map(move |(idx, info)| {
(item, info.name.unescaped().display(db.upcast()).to_smolstr(), idx as u32)
})
info.iter()
.enumerate()
.map(move |(idx, info)| (item, info.name.as_str(), idx as u32))
})
.collect();
importables.sort_by(|(_, l_info, _), (_, r_info, _)| {
@ -441,7 +440,7 @@ pub fn search_dependencies(
}
fn search_maps(
db: &dyn DefDatabase,
_db: &dyn DefDatabase,
import_maps: &[Arc<ImportMap>],
mut stream: fst::map::Union<'_>,
query: &Query,
@ -464,11 +463,7 @@ fn search_maps(
.then(|| (item, &import_infos[info_idx as usize]))
})
.filter(|&(_, info)| {
query.search_mode.check(
&query.query,
query.case_sensitive,
&info.name.unescaped().display(db.upcast()).to_smolstr(),
)
query.search_mode.check(&query.query, query.case_sensitive, info.name.as_str())
});
res.extend(iter.map(TupleExt::head));
}

View File

@ -4,7 +4,6 @@ use base_db::AnchoredPath;
use hir_expand::{name::Name, HirFileIdExt};
use limit::Limit;
use span::EditionedFileId;
use syntax::ToSmolStr as _;
use crate::{db::DefDatabase, HirFileId};
@ -35,7 +34,7 @@ impl ModDir {
let path = match attr_path {
None => {
let mut path = self.dir_path.clone();
path.push(&name.unescaped().display_no_db().to_smolstr());
path.push(name.as_str());
path
}
Some(attr_path) => {
@ -66,7 +65,7 @@ impl ModDir {
name: &Name,
attr_path: Option<&str>,
) -> Result<(EditionedFileId, bool, ModDir), Box<[String]>> {
let name = name.unescaped();
let name = name.as_str();
let mut candidate_files = ArrayVec::<_, 2>::new();
match attr_path {
@ -74,16 +73,8 @@ impl ModDir {
candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
}
None => {
candidate_files.push(format!(
"{}{}.rs",
self.dir_path.0,
name.display(db.upcast())
));
candidate_files.push(format!(
"{}{}/mod.rs",
self.dir_path.0,
name.display(db.upcast())
));
candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
}
};
@ -97,7 +88,7 @@ impl ModDir {
let dir_path = if root_dir_owner {
DirPath::empty()
} else {
DirPath::new(format!("{}/", name.display(db.upcast())))
DirPath::new(format!("{}/", name))
};
if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
return Ok((

View File

@ -23,15 +23,6 @@ pub struct ModPath {
segments: SmallVec<[Name; 1]>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UnescapedModPath<'a>(&'a ModPath);
impl<'a> UnescapedModPath<'a> {
pub fn display(&'a self, db: &'a dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
UnescapedDisplay { db, path: self }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PathKind {
Plain,
@ -135,9 +126,11 @@ impl ModPath {
_ => None,
}
}
pub fn unescaped(&self) -> UnescapedModPath<'_> {
UnescapedModPath(self)
pub fn display_verbatim<'a>(
&'a self,
db: &'a dyn crate::db::ExpandDatabase,
) -> impl fmt::Display + 'a {
Display { db, path: self, edition: None }
}
pub fn display<'a>(
@ -145,7 +138,7 @@ impl ModPath {
db: &'a dyn crate::db::ExpandDatabase,
edition: Edition,
) -> impl fmt::Display + 'a {
Display { db, path: self, edition }
Display { db, path: self, edition: Some(edition) }
}
}
@ -158,23 +151,12 @@ impl Extend<Name> for ModPath {
struct Display<'a> {
db: &'a dyn ExpandDatabase,
path: &'a ModPath,
edition: Edition,
edition: Option<Edition>,
}
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
display_fmt_path(self.db, self.path, f, Escape::IfNeeded(self.edition))
}
}
struct UnescapedDisplay<'a> {
db: &'a dyn ExpandDatabase,
path: &'a UnescapedModPath<'a>,
}
impl fmt::Display for UnescapedDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
display_fmt_path(self.db, self.path.0, f, Escape::No)
display_fmt_path(self.db, self.path, f, self.edition)
}
}
@ -184,16 +166,11 @@ impl From<Name> for ModPath {
}
}
enum Escape {
No,
IfNeeded(Edition),
}
fn display_fmt_path(
db: &dyn ExpandDatabase,
path: &ModPath,
f: &mut fmt::Formatter<'_>,
escaped: Escape,
edition: Option<Edition>,
) -> fmt::Result {
let mut first_segment = true;
let mut add_segment = |s| -> fmt::Result {
@ -221,10 +198,10 @@ fn display_fmt_path(
f.write_str("::")?;
}
first_segment = false;
match escaped {
Escape::IfNeeded(edition) => segment.display(db, edition).fmt(f)?,
Escape::No => segment.unescaped().display(db).fmt(f)?,
}
match edition {
Some(edition) => segment.display(db, edition).fmt(f)?,
None => fmt::Display::fmt(segment.as_str(), f)?,
};
}
Ok(())
}

View File

@ -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
@ -69,27 +69,8 @@ impl PartialEq<Name> for &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 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: () }
}
@ -99,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 {
@ -131,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()),
}
}
/// Resolve a name from the text of token.
fn resolve(raw_text: &str) -> Name {
Name::new_text(raw_text.trim_start_matches("r#"))
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 {
Self::new_symbol(sym, SyntaxContextId::root(Edition::Edition2015))
}
/// A fake name for things missing in the source code.
@ -173,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,
@ -198,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) }
@ -207,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> {
@ -241,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;
}
@ -260,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())
}
}
@ -282,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())
}
}
@ -300,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)
}
}

View File

@ -231,8 +231,7 @@ impl<'a> DeclValidator<'a> {
.filter_map(|(pat_id, pat)| match pat {
Pat::Bind { id, .. } => {
let bind_name = &body.bindings[*id].name;
let mut suggested_text =
to_lower_snake_case(&bind_name.unescaped().display_no_db().to_smolstr())?;
let mut suggested_text = to_lower_snake_case(bind_name.as_str())?;
if is_raw_identifier(&suggested_text, edition) {
suggested_text.insert_str(0, "r#");
}

View File

@ -277,7 +277,7 @@ impl CapturedItem {
/// Converts the place to a name that can be inserted into source code.
pub fn place_to_name(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
let body = db.body(owner);
let mut result = body[self.place.local].name.unescaped().display(db.upcast()).to_string();
let mut result = body[self.place.local].name.as_str().to_owned();
for proj in &self.place.projections {
match proj {
ProjectionElem::Deref => {}

View File

@ -159,7 +159,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
};
// Verify this is `bool::then` that is being called.
let func = ctx.sema.resolve_method_call(&mcall)?;
if !func.name(ctx.sema.db).eq_ident("then") {
if func.name(ctx.sema.db) != sym::then {
return None;
}
let assoc = func.as_assoc_item(ctx.sema.db)?;

View File

@ -343,11 +343,9 @@ fn compute_closure_type_params(
let mut mentioned_names = mentioned_generic_params
.iter()
.filter_map(|param| match param {
hir::GenericParam::TypeParam(param) => {
Some(param.name(ctx.db()).unescaped().display(ctx.db()).to_smolstr())
}
hir::GenericParam::TypeParam(param) => Some(param.name(ctx.db()).as_str().to_smolstr()),
hir::GenericParam::ConstParam(param) => {
Some(param.name(ctx.db()).unescaped().display(ctx.db()).to_smolstr())
Some(param.name(ctx.db()).as_str().to_smolstr())
}
hir::GenericParam::LifetimeParam(_) => None,
})
@ -390,7 +388,7 @@ fn compute_closure_type_params(
let has_name = syntax
.descendants()
.filter_map(ast::NameOrNameRef::cast)
.any(|name| mentioned_names.contains(&*name.text()));
.any(|name| mentioned_names.contains(name.text().trim_start_matches("r#")));
let mut has_new_params = false;
if has_name {
syntax

View File

@ -170,7 +170,7 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va
),
_ => false,
})
.any(|(name, _)| name.eq_ident(variant_name.text().as_str()))
.any(|(name, _)| name.as_str() == variant_name.text().trim_start_matches("r#"))
}
fn extract_generic_params(

View File

@ -48,7 +48,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
let (_, def) = module
.scope(ctx.db(), None)
.into_iter()
.find(|(name, _)| name.eq_ident(name_ref.text().as_str()))?;
.find(|(name, _)| name.as_str() == name_ref.text().trim_start_matches("r#"))?;
let ScopeDef::ModuleDef(def) = def else {
return None;
};

View File

@ -2,7 +2,7 @@ use ide_db::{
assists::{AssistId, AssistKind},
base_db::AnchoredPathBuf,
};
use syntax::{ast, AstNode};
use syntax::{ast, AstNode, ToSmolStr};
use crate::{
assist_context::{AssistContext, Assists},
@ -39,7 +39,7 @@ pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
}
let target = source_file.syntax().text_range();
let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
let module_name = module.name(ctx.db())?.as_str().to_smolstr();
let path = format!("../{module_name}.rs");
let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
acc.add(

View File

@ -61,7 +61,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
.string_value_unescape()
.is_none() =>
{
format_to!(buf, "{}/", name.unescaped().display(db))
format_to!(buf, "{}/", name.as_str())
}
_ => (),
}

View File

@ -2,7 +2,7 @@ use ide_db::{
assists::{AssistId, AssistKind},
base_db::AnchoredPathBuf,
};
use syntax::{ast, AstNode};
use syntax::{ast, AstNode, ToSmolStr};
use crate::{
assist_context::{AssistContext, Assists},
@ -39,7 +39,7 @@ pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
}
let target = source_file.syntax().text_range();
let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
let module_name = module.name(ctx.db())?.as_str().to_smolstr();
let path = format!("./{module_name}/mod.rs");
let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
acc.add(

View File

@ -208,7 +208,7 @@ fn find_trait_method(
if let Some(hir::AssocItem::Function(method)) =
trait_.items(db).into_iter().find(|item: &hir::AssocItem| {
item.name(db)
.map(|name| name.eq_ident(trait_method_name.text().as_str()))
.map(|name| name.as_str() == trait_method_name.text().trim_start_matches("r#"))
.unwrap_or(false)
})
{

View File

@ -110,7 +110,7 @@ fn compute_fields_ranks(
.fields(ctx.db())
.into_iter()
.enumerate()
.map(|(idx, field)| (field.name(ctx.db()).unescaped().display(ctx.db()).to_string(), idx))
.map(|(idx, field)| (field.name(ctx.db()).as_str().to_owned(), idx))
.collect();
Some(res)

View File

@ -122,7 +122,7 @@ fn compute_item_ranks(
.iter()
.flat_map(|i| i.name(ctx.db()))
.enumerate()
.map(|(idx, name)| (name.unescaped().display(ctx.db()).to_string(), idx))
.map(|(idx, name)| (name.as_str().to_owned(), idx))
.collect(),
)
}

View File

@ -5,7 +5,7 @@ use ide_db::imports::{
insert_use::ImportScope,
};
use itertools::Itertools;
use syntax::{ast, AstNode, SyntaxNode, ToSmolStr};
use syntax::{ast, AstNode, SyntaxNode};
use crate::{
config::AutoImportExclusionType,
@ -444,7 +444,7 @@ fn compute_fuzzy_completion_order_key(
cov_mark::hit!(certain_fuzzy_order_test);
let import_name = match proposed_mod_path.segments().last() {
// FIXME: nasty alloc, this is a hot path!
Some(name) => name.unescaped().display_no_db().to_smolstr().to_ascii_lowercase(),
Some(name) => name.as_str().to_ascii_lowercase(),
None => return usize::MAX,
};
match import_name.match_indices(user_input_lowercased).next() {

View File

@ -362,7 +362,7 @@ fn add_type_alias_impl(
type_alias: hir::TypeAlias,
impl_def: hir::Impl,
) {
let alias_name = type_alias.name(ctx.db).unescaped().display(ctx.db).to_smolstr();
let alias_name = type_alias.name(ctx.db).as_str().to_smolstr();
let label = format_smolstr!("type {alias_name} =");

View File

@ -7,7 +7,7 @@ use ide_db::{
base_db::{SourceRootDatabase, VfsPath},
FxHashSet, RootDatabase, SymbolKind,
};
use syntax::{ast, AstNode, SyntaxKind, ToSmolStr};
use syntax::{ast, AstNode, SyntaxKind};
use crate::{context::CompletionContext, CompletionItem, Completions};
@ -140,9 +140,7 @@ fn directory_to_look_for_submodules(
module_chain_to_containing_module_file(module, db)
.into_iter()
.filter_map(|module| module.name(db))
.try_fold(base_directory, |path, name| {
path.join(&name.unescaped().display_no_db().to_smolstr())
})
.try_fold(base_directory, |path, name| path.join(name.as_str()))
}
fn module_chain_to_containing_module_file(

View File

@ -1595,11 +1595,11 @@ fn pattern_context_for(
}).map(|enum_| enum_.variants(sema.db))
})
}).map(|variants| variants.iter().filter_map(|variant| {
let variant_name = variant.name(sema.db).unescaped().display(sema.db).to_string();
let variant_name = variant.name(sema.db);
let variant_already_present = match_arm_list.arms().any(|arm| {
arm.pat().and_then(|pat| {
let pat_already_present = pat.syntax().to_string().contains(&variant_name);
let pat_already_present = pat.syntax().to_string().contains(variant_name.as_str());
pat_already_present.then_some(pat_already_present)
}).is_some()
});

View File

@ -130,10 +130,8 @@ pub(crate) fn render_field(
let db = ctx.db();
let is_deprecated = ctx.is_deprecated(field);
let name = field.name(db);
let (name, escaped_name) = (
name.unescaped().display(db).to_smolstr(),
name.display_no_db(ctx.completion.edition).to_smolstr(),
);
let (name, escaped_name) =
(name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
let mut item = CompletionItem::new(
SymbolKind::Field,
ctx.source_range(),
@ -142,7 +140,7 @@ pub(crate) fn render_field(
);
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(ctx.completion, ty),
exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
exact_name_match: compute_exact_name_match(ctx.completion, &name),
..CompletionRelevance::default()
});
item.detail(ty.display(db, ctx.completion.edition).to_string())
@ -512,7 +510,7 @@ fn render_resolution_simple_(
let mut item = CompletionItem::new(
kind,
ctx.source_range(),
local_name.unescaped().display(db).to_smolstr(),
local_name.as_str().to_smolstr(),
ctx.completion.edition,
);
item.set_relevance(ctx.completion_relevance())

View File

@ -14,10 +14,8 @@ pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option
fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
let db = ctx.db();
let name = const_.name(db)?;
let (name, escaped_name) = (
name.unescaped().display(db).to_smolstr(),
name.display(db, ctx.completion.edition).to_smolstr(),
);
let (name, escaped_name) =
(name.as_str().to_smolstr(), name.display(db, ctx.completion.edition).to_smolstr());
let detail = const_.display(db, ctx.completion.edition).to_string();
let mut item =

View File

@ -59,13 +59,10 @@ fn render(
let (call, escaped_call) = match &func_kind {
FuncKind::Method(_, Some(receiver)) => (
format_smolstr!("{}.{}", receiver, name.unescaped().display(ctx.db())),
format_smolstr!("{}.{}", receiver, name.as_str()),
format_smolstr!("{}.{}", receiver, name.display(ctx.db(), completion.edition)),
),
_ => (
name.unescaped().display(db).to_smolstr(),
name.display(db, completion.edition).to_smolstr(),
),
_ => (name.as_str().to_smolstr(), name.display(db, completion.edition).to_smolstr()),
};
let has_self_param = func.self_param(db).is_some();
let mut item = CompletionItem::new(
@ -151,7 +148,7 @@ fn render(
item.set_documentation(ctx.docs(func))
.set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
.detail(detail)
.lookup_by(name.unescaped().display(db).to_smolstr());
.lookup_by(name.as_str().to_smolstr());
if let Some((cap, (self_param, params))) = complete_call_parens {
add_call_parens(

View File

@ -75,7 +75,7 @@ fn render(
None => (name.clone().into(), name.into(), false),
};
let (qualified_name, escaped_qualified_name) = (
qualified_name.unescaped().display(ctx.db()).to_string(),
qualified_name.display_verbatim(ctx.db()).to_string(),
qualified_name.display(ctx.db(), completion.edition).to_string(),
);
let snippet_cap = ctx.snippet_cap();

View File

@ -46,21 +46,19 @@ fn render(
ctx.source_range()
};
let (name, escaped_name) = (
name.unescaped().display(ctx.db()).to_smolstr(),
name.display(ctx.db(), completion.edition).to_smolstr(),
);
let (name, escaped_name) =
(name.as_str(), name.display(ctx.db(), completion.edition).to_smolstr());
let docs = ctx.docs(macro_);
let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default();
let is_fn_like = macro_.is_fn_like(completion.db);
let (bra, ket) = if is_fn_like { guess_macro_braces(&name, docs_str) } else { ("", "") };
let (bra, ket) = if is_fn_like { guess_macro_braces(name, docs_str) } else { ("", "") };
let needs_bang = is_fn_like && !is_use_path && !has_macro_bang;
let mut item = CompletionItem::new(
SymbolKind::from(macro_.kind(completion.db)),
source_range,
label(&ctx, needs_bang, bra, ket, &name),
label(&ctx, needs_bang, bra, ket, &name.to_smolstr()),
completion.edition,
);
item.set_deprecated(ctx.is_deprecated(macro_))
@ -71,11 +69,11 @@ fn render(
match ctx.snippet_cap() {
Some(cap) if needs_bang && !has_call_parens => {
let snippet = format!("{escaped_name}!{bra}$0{ket}");
let lookup = banged_name(&name);
let lookup = banged_name(name);
item.insert_snippet(cap, snippet).lookup_by(lookup);
}
_ if needs_bang => {
item.insert_text(banged_name(&escaped_name)).lookup_by(banged_name(&name));
item.insert_text(banged_name(&escaped_name)).lookup_by(banged_name(name));
}
_ => {
cov_mark::hit!(dont_insert_macro_call_parens_unnecessary);

View File

@ -31,13 +31,11 @@ pub(crate) fn render_struct_pat(
}
let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
let (name, escaped_name) = (
name.unescaped().display(ctx.db()).to_smolstr(),
name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
);
let (name, escaped_name) =
(name.as_str(), name.display(ctx.db(), ctx.completion.edition).to_smolstr());
let kind = strukt.kind(ctx.db());
let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
let lookup = format_literal_lookup(name.as_str(), kind);
let label = format_literal_label(name, kind, ctx.snippet_cap());
let lookup = format_literal_lookup(name, kind);
let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
let db = ctx.db();
@ -61,13 +59,13 @@ pub(crate) fn render_variant_pat(
let (name, escaped_name) = match path {
Some(path) => (
path.unescaped().display(ctx.db()).to_string().into(),
path.display(ctx.db(), ctx.completion.edition).to_string().into(),
path.display_verbatim(ctx.db()).to_smolstr(),
path.display(ctx.db(), ctx.completion.edition).to_smolstr(),
),
None => {
let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
let it = (
name.unescaped().display(ctx.db()).to_smolstr(),
name.as_str().to_smolstr(),
name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
);
it

View File

@ -32,14 +32,11 @@ fn render(
let name = type_alias.name(db);
let (name, escaped_name) = if with_eq {
(
SmolStr::from_iter([&name.unescaped().display(db).to_smolstr(), " = "]),
SmolStr::from_iter([&name.as_str().to_smolstr(), " = "]),
SmolStr::from_iter([&name.display_no_db(ctx.completion.edition).to_smolstr(), " = "]),
)
} else {
(
name.unescaped().display(db).to_smolstr(),
name.display_no_db(ctx.completion.edition).to_smolstr(),
)
(name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr())
};
let detail = type_alias.display(db, ctx.completion.edition).to_string();

View File

@ -23,12 +23,12 @@ pub(crate) fn render_union_literal(
let (qualified_name, escaped_qualified_name) = match path {
Some(p) => (
p.unescaped().display(ctx.db()).to_string(),
p.display(ctx.db(), ctx.completion.edition).to_string(),
p.display_verbatim(ctx.db()).to_smolstr(),
p.display(ctx.db(), ctx.completion.edition).to_smolstr(),
),
None => (
name.unescaped().display(ctx.db()).to_string(),
name.display(ctx.db(), ctx.completion.edition).to_string(),
name.as_str().to_smolstr(),
name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
),
};
let label = format_literal_label(

View File

@ -794,7 +794,7 @@ impl NameRefClass {
hir::AssocItem::TypeAlias(it) => Some(it),
_ => None,
})
.find(|alias| alias.name(sema.db).eq_ident(name_ref.text().as_str()))
.find(|alias| alias.name(sema.db).as_str() == name_ref.text().trim_start_matches("r#"))
{
// No substitution, this can only occur in type position.
return Some(NameRefClass::Definition(Definition::TypeAlias(ty), None));

View File

@ -214,14 +214,15 @@ impl FamousDefs<'_, '_> {
for segment in path {
module = module.children(db).find_map(|child| {
let name = child.name(db)?;
if name.eq_ident(segment) {
if name.as_str() == segment {
Some(child)
} else {
None
}
})?;
}
let def = module.scope(db, None).into_iter().find(|(name, _def)| name.eq_ident(trait_))?.1;
let def =
module.scope(db, None).into_iter().find(|(name, _def)| name.as_str() == trait_)?.1;
Some(def)
}
}

View File

@ -263,13 +263,12 @@ fn rename_mod(
// - Module has submodules defined in separate files
let dir_paths = match (is_mod_rs, has_detached_child, module.name(sema.db)) {
// Go up one level since the anchor is inside the dir we're trying to rename
(true, _, Some(mod_name)) => Some((
format!("../{}", mod_name.unescaped().display(sema.db)),
format!("../{new_name}"),
)),
(true, _, Some(mod_name)) => {
Some((format!("../{}", mod_name.as_str()), format!("../{new_name}")))
}
// The anchor is on the same level as target dir
(false, true, Some(mod_name)) => {
Some((mod_name.unescaped().display(sema.db).to_string(), new_name.to_owned()))
Some((mod_name.as_str().to_owned(), new_name.to_owned()))
}
_ => None,
};

View File

@ -625,7 +625,7 @@ impl<'a> FindUsages<'a> {
let _p = tracing::info_span!("collect_possible_aliases").entered();
let db = sema.db;
let container_name = container.name(db).unescaped().display(db).to_smolstr();
let container_name = container.name(db).as_str().to_smolstr();
let search_scope = Definition::from(container).search_scope(db);
let mut seen = FxHashSet::default();
let mut completed = FxHashSet::default();
@ -925,12 +925,8 @@ impl<'a> FindUsages<'a> {
.or_else(|| ty.as_builtin().map(|builtin| builtin.name()))
})
};
// We need to unescape the name in case it is written without "r#" in earlier
// editions of Rust where it isn't a keyword.
self.def
.name(sema.db)
.or_else(self_kw_refs)
.map(|it| it.unescaped().display(sema.db).to_smolstr())
// We need to search without the `r#`, hence `as_str` access.
self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.as_str().to_smolstr())
}
};
let name = match &name {

View File

@ -26,7 +26,7 @@ impl TryEnum {
_ => return None,
};
TryEnum::ALL.iter().find_map(|&var| {
if enum_.name(sema.db).eq_ident(var.type_name()) {
if enum_.name(sema.db).as_str() == var.type_name() {
return Some(var);
}
None

View File

@ -112,7 +112,7 @@ fn fixes(
// shouldn't occur
_ => continue 'crates,
};
match current.children.iter().find(|(name, _)| name.eq_ident(seg)) {
match current.children.iter().find(|(name, _)| name.as_str() == seg) {
Some((_, &child)) => current = &crate_def_map[child],
None => continue 'crates,
}
@ -161,7 +161,7 @@ fn fixes(
// try finding a parent that has an inline tree from here on
let mut current = module;
for s in stack.iter().rev() {
match module.children.iter().find(|(name, _)| name.eq_ident(s)) {
match module.children.iter().find(|(name, _)| name.as_str() == s) {
Some((_, child)) => {
current = &crate_def_map[*child];
}

View File

@ -413,8 +413,7 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
def.canonical_module_path(db).map(|it| {
let mut path = String::new();
it.flat_map(|it| it.name(db))
.for_each(|name| format_to!(path, "{}/", name.unescaped().display(db)));
it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name.as_str()));
path
})
}
@ -590,10 +589,10 @@ fn filename_and_frag_for_def(
let res = match def {
Definition::Adt(adt) => match adt {
Adt::Struct(s) => {
format!("struct.{}.html", s.name(db).unescaped().display(db.upcast()))
format!("struct.{}.html", s.name(db).as_str())
}
Adt::Enum(e) => format!("enum.{}.html", e.name(db).unescaped().display(db.upcast())),
Adt::Union(u) => format!("union.{}.html", u.name(db).unescaped().display(db.upcast())),
Adt::Enum(e) => format!("enum.{}.html", e.name(db).as_str()),
Adt::Union(u) => format!("union.{}.html", u.name(db).as_str()),
},
Definition::Crate(_) => String::from("index.html"),
Definition::Module(m) => match m.name(db) {
@ -603,48 +602,48 @@ fn filename_and_frag_for_def(
Some(kw) => {
format!("keyword.{}.html", kw)
}
None => format!("{}/index.html", name.unescaped().display(db.upcast())),
None => format!("{}/index.html", name.as_str()),
}
}
None => String::from("index.html"),
},
Definition::Trait(t) => {
format!("trait.{}.html", t.name(db).unescaped().display(db.upcast()))
format!("trait.{}.html", t.name(db).as_str())
}
Definition::TraitAlias(t) => {
format!("traitalias.{}.html", t.name(db).unescaped().display(db.upcast()))
format!("traitalias.{}.html", t.name(db).as_str())
}
Definition::TypeAlias(t) => {
format!("type.{}.html", t.name(db).unescaped().display(db.upcast()))
format!("type.{}.html", t.name(db).as_str())
}
Definition::BuiltinType(t) => {
format!("primitive.{}.html", t.name().unescaped().display(db.upcast()))
format!("primitive.{}.html", t.name().as_str())
}
Definition::Function(f) => {
format!("fn.{}.html", f.name(db).unescaped().display(db.upcast()))
format!("fn.{}.html", f.name(db).as_str())
}
Definition::Variant(ev) => {
format!(
"enum.{}.html#variant.{}",
ev.parent_enum(db).name(db).unescaped().display(db.upcast()),
ev.name(db).unescaped().display(db.upcast())
ev.parent_enum(db).name(db).as_str(),
ev.name(db).as_str()
)
}
Definition::Const(c) => {
format!("const.{}.html", c.name(db)?.unescaped().display(db.upcast()))
format!("const.{}.html", c.name(db)?.as_str())
}
Definition::Static(s) => {
format!("static.{}.html", s.name(db).unescaped().display(db.upcast()))
format!("static.{}.html", s.name(db).as_str())
}
Definition::Macro(mac) => match mac.kind(db) {
hir::MacroKind::Declarative
| hir::MacroKind::BuiltIn
| hir::MacroKind::Attr
| hir::MacroKind::ProcMacro => {
format!("macro.{}.html", mac.name(db).unescaped().display(db.upcast()))
format!("macro.{}.html", mac.name(db).as_str())
}
hir::MacroKind::Derive => {
format!("derive.{}.html", mac.name(db).unescaped().display(db.upcast()))
format!("derive.{}.html", mac.name(db).as_str())
}
},
Definition::Field(field) => {
@ -654,11 +653,7 @@ fn filename_and_frag_for_def(
hir::VariantDef::Variant(it) => Definition::Variant(it),
};
let (_, file, _) = filename_and_frag_for_def(db, def)?;
return Some((
def,
file,
Some(format!("structfield.{}", field.name(db).unescaped().display(db.upcast()))),
));
return Some((def, file, Some(format!("structfield.{}", field.name(db).as_str()))));
}
Definition::SelfType(impl_) => {
let adt = impl_.self_ty(db).as_adt()?.into();
@ -667,7 +662,7 @@ fn filename_and_frag_for_def(
return Some((adt, file, Some(String::from("impl"))));
}
Definition::ExternCrateDecl(it) => {
format!("{}/index.html", it.name(db).unescaped().display(db.upcast()))
format!("{}/index.html", it.name(db).as_str())
}
Definition::Local(_)
| Definition::GenericParam(_)
@ -699,16 +694,16 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) ->
// Rustdoc makes this decision based on whether a method 'has defaultness'.
// Currently this is only the case for provided trait methods.
if is_trait_method && !function.has_body(db) {
format!("tymethod.{}", function.name(db).unescaped().display(db.upcast()))
format!("tymethod.{}", function.name(db).as_str())
} else {
format!("method.{}", function.name(db).unescaped().display(db.upcast()))
format!("method.{}", function.name(db).as_str())
}
}
AssocItem::Const(constant) => {
format!("associatedconstant.{}", constant.name(db)?.unescaped().display(db.upcast()))
format!("associatedconstant.{}", constant.name(db)?.as_str())
}
AssocItem::TypeAlias(ty) => {
format!("associatedtype.{}", ty.name(db).unescaped().display(db.upcast()))
format!("associatedtype.{}", ty.name(db).as_str())
}
})
}

View File

@ -124,9 +124,7 @@ fn should_hide_param_name_hint(
}
let fn_name = match callable.kind() {
hir::CallableKind::Function(it) => {
Some(it.name(sema.db).unescaped().display_no_db().to_smolstr())
}
hir::CallableKind::Function(it) => Some(it.name(sema.db).as_str().to_smolstr()),
_ => None,
};
let fn_name = fn_name.as_deref();

View File

@ -263,7 +263,7 @@ fn find_definitions(
.and_then(|def| {
// if the name differs from the definitions name it has to be an alias
if def
.name(sema.db).is_some_and(|it| !it.eq_ident(name_ref.text().as_str()))
.name(sema.db).is_some_and(|it| it.as_str() != name_ref.text().trim_start_matches("r#"))
{
Err(format_err!("Renaming aliases is currently unsupported"))
} else {

View File

@ -459,6 +459,7 @@ define_symbols! {
termination,
test_case,
test,
then,
thiscall,
trace_macros,
transmute_opts,