Skip to content

Commit 2c0f433

Browse files
bors[bot]Veykril
andauthored
Merge #10699
10699: internal: Make CompletionItem `label` and `lookup` fields `SmolStr`s r=Veykril a=Veykril This replaces a bunch of String clones with SmolStr clones, though also makes a few parts a bit more expensive(mainly things involving `format!`ted strings as labels). Co-authored-by: Lukas Wirth <[email protected]>
2 parents e4ce6c7 + 2f5afba commit 2c0f433

File tree

17 files changed

+94
-109
lines changed

17 files changed

+94
-109
lines changed

crates/cfg/src/lib.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,24 +66,21 @@ impl CfgOptions {
6666
}
6767
}
6868

69-
pub fn get_cfg_keys(&self) -> Vec<&SmolStr> {
70-
self.enabled
71-
.iter()
72-
.map(|x| match x {
73-
CfgAtom::Flag(key) => key,
74-
CfgAtom::KeyValue { key, .. } => key,
75-
})
76-
.collect()
69+
pub fn get_cfg_keys(&self) -> impl Iterator<Item = &SmolStr> {
70+
self.enabled.iter().map(|x| match x {
71+
CfgAtom::Flag(key) => key,
72+
CfgAtom::KeyValue { key, .. } => key,
73+
})
7774
}
7875

79-
pub fn get_cfg_values(&self, cfg_key: &str) -> Vec<&SmolStr> {
80-
self.enabled
81-
.iter()
82-
.filter_map(|x| match x {
83-
CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value),
84-
_ => None,
85-
})
86-
.collect()
76+
pub fn get_cfg_values<'a>(
77+
&'a self,
78+
cfg_key: &'a str,
79+
) -> impl Iterator<Item = &'a SmolStr> + 'a {
80+
self.enabled.iter().filter_map(move |x| match x {
81+
CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value),
82+
_ => None,
83+
})
8784
}
8885
}
8986

crates/ide_completion/src/completions/attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
104104
let mut item = CompletionItem::new(
105105
CompletionItemKind::Attribute,
106106
ctx.source_range(),
107-
name.to_string(),
107+
name.to_smol_str(),
108108
);
109109
if let Some(docs) = mac.docs(ctx.sema.db) {
110110
item.documentation(docs);

crates/ide_completion/src/completions/attribute/cfg.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,21 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
3131
Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
3232
Some(name) => {
3333
if let Some(krate) = ctx.krate {
34-
krate.potential_cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| {
35-
let mut item = CompletionItem::new(
36-
CompletionItemKind::Attribute,
37-
ctx.source_range(),
38-
s.as_str(),
39-
);
40-
item.insert_text(format!(r#""{}""#, s));
34+
krate.potential_cfg(ctx.db).get_cfg_values(&name).cloned().for_each(|s| {
35+
let insert_text = format!(r#""{}""#, s);
36+
let mut item =
37+
CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), s);
38+
item.insert_text(insert_text);
4139

4240
acc.add(item.build());
4341
})
4442
};
4543
}
4644
None => {
4745
if let Some(krate) = ctx.krate {
48-
krate.potential_cfg(ctx.db).get_cfg_keys().iter().for_each(|s| {
49-
let item = CompletionItem::new(
50-
CompletionItemKind::Attribute,
51-
ctx.source_range(),
52-
s.as_str(),
53-
);
46+
krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
47+
let item =
48+
CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), s);
5449
acc.add(item.build());
5550
})
5651
}

crates/ide_completion/src/completions/attribute/derive.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use hir::{HasAttrs, MacroDef, MacroKind};
33
use ide_db::helpers::{import_assets::ImportAssets, insert_use::ImportScope, FamousDefs};
44
use itertools::Itertools;
55
use rustc_hash::FxHashSet;
6-
use syntax::{ast, SyntaxKind};
6+
use syntax::{ast, SmolStr, SyntaxKind};
77

88
use crate::{
99
completions::flyimport::compute_fuzzy_completion_order_key,
@@ -30,7 +30,6 @@ pub(super) fn complete_derive(
3030
}
3131

3232
let name = name.to_smol_str();
33-
let label;
3433
let (label, lookup) = match core.zip(mac.module(ctx.db).map(|it| it.krate())) {
3534
// show derive dependencies for `core`/`std` derives
3635
Some((core, mac_krate)) if core == mac_krate => {
@@ -48,13 +47,13 @@ pub(super) fn complete_derive(
4847
},
4948
));
5049
let lookup = components.join(", ");
51-
label = components.iter().rev().join(", ");
52-
(label.as_str(), Some(lookup))
50+
let label = Itertools::intersperse(components.into_iter().rev(), ", ");
51+
(SmolStr::from_iter(label), Some(lookup))
5352
} else {
54-
(&*name, None)
53+
(name, None)
5554
}
5655
}
57-
_ => (&*name, None),
56+
_ => (name, None),
5857
};
5958

6059
let mut item =
@@ -68,7 +67,7 @@ pub(super) fn complete_derive(
6867
item.add_to(acc);
6968
}
7069

71-
flyimport_attribute(ctx, acc);
70+
flyimport_attribute(acc, ctx);
7271
}
7372

7473
fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> {
@@ -83,7 +82,7 @@ fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> {
8382
result
8483
}
8584

86-
fn flyimport_attribute(ctx: &CompletionContext, acc: &mut Completions) -> Option<()> {
85+
fn flyimport_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
8786
if ctx.token.kind() != SyntaxKind::IDENT {
8887
return None;
8988
};
@@ -115,7 +114,7 @@ fn flyimport_attribute(ctx: &CompletionContext, acc: &mut Completions) -> Option
115114
let mut item = CompletionItem::new(
116115
CompletionItemKind::Attribute,
117116
ctx.source_range(),
118-
mac.name(ctx.db)?.to_string(),
117+
mac.name(ctx.db)?.to_smol_str(),
119118
);
120119
item.add_import(ImportEdit { import, scope: import_scope.clone() });
121120
if let Some(docs) = mac.docs(ctx.db) {

crates/ide_completion/src/completions/fn_param.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
3030
}
3131
func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
3232
if let Some(pat) = param.pat() {
33+
// FIXME: We should be able to turn these into SmolStr without having to allocate a String
3334
let text = param.syntax().text().to_string();
3435
let lookup = pat.syntax().text().to_string();
3536
params.entry(text).or_insert(lookup);
@@ -59,7 +60,7 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
5960

6061
let self_completion_items = ["self", "&self", "mut self", "&mut self"];
6162
if ctx.impl_def.is_some() && me?.param_list()?.params().next().is_none() {
62-
self_completion_items.iter().for_each(|self_item| {
63+
self_completion_items.into_iter().for_each(|self_item| {
6364
add_new_item_to_acc(ctx, acc, self_item.to_string(), self_item.to_string())
6465
});
6566
}

crates/ide_completion/src/completions/keyword.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
2727
return;
2828
}
2929

30-
let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);
30+
let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet);
3131

3232
let expects_assoc_item = ctx.expects_assoc_item();
3333
let has_block_expr_parent = ctx.has_block_expr_parent();
@@ -157,7 +157,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
157157
)
158158
}
159159

160-
fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
160+
fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
161161
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
162162

163163
match ctx.config.snippet_cap {

crates/ide_completion/src/completions/qualified_path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
9393
if ctx.in_use_tree() {
9494
if let hir::ScopeDef::Unknown = def {
9595
if let Some(ast::NameLike::NameRef(name_ref)) = ctx.name_syntax.as_ref() {
96-
if name_ref.syntax().text() == name.to_string().as_str() {
96+
if name_ref.syntax().text() == name.to_smol_str().as_str() {
9797
// for `use self::foo$0`, don't suggest `foo` as a completion
9898
cov_mark::hit!(dont_complete_current_use);
9999
continue;

crates/ide_completion/src/completions/trait_impl.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn add_function_impl(
133133
func: hir::Function,
134134
impl_def: hir::Impl,
135135
) {
136-
let fn_name = func.name(ctx.db).to_string();
136+
let fn_name = func.name(ctx.db).to_smol_str();
137137

138138
let label = if func.assoc_fn_params(ctx.db).is_empty() {
139139
format!("fn {}()", fn_name)
@@ -205,12 +205,12 @@ fn add_type_alias_impl(
205205
ctx: &CompletionContext,
206206
type_alias: hir::TypeAlias,
207207
) {
208-
let alias_name = type_alias.name(ctx.db).to_string();
208+
let alias_name = type_alias.name(ctx.db).to_smol_str();
209209

210210
let snippet = format!("type {} = ", alias_name);
211211

212212
let range = replacement_range(ctx, type_def_node);
213-
let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), snippet.clone());
213+
let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), &snippet);
214214
item.text_edit(TextEdit::replace(range, snippet))
215215
.lookup_by(alias_name)
216216
.set_documentation(type_alias.docs(ctx.db));
@@ -224,7 +224,7 @@ fn add_const_impl(
224224
const_: hir::Const,
225225
impl_def: hir::Impl,
226226
) {
227-
let const_name = const_.name(ctx.db).map(|n| n.to_string());
227+
let const_name = const_.name(ctx.db).map(|n| n.to_smol_str());
228228

229229
if let Some(const_name) = const_name {
230230
if let Some(source) = const_.source(ctx.db) {
@@ -238,8 +238,7 @@ fn add_const_impl(
238238
let snippet = make_const_compl_syntax(&transformed_const);
239239

240240
let range = replacement_range(ctx, const_def_node);
241-
let mut item =
242-
CompletionItem::new(SymbolKind::Const, ctx.source_range(), snippet.clone());
241+
let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), &snippet);
243242
item.text_edit(TextEdit::replace(range, snippet))
244243
.lookup_by(const_name)
245244
.set_documentation(const_.docs(ctx.db));

crates/ide_completion/src/item.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use ide_db::{
1212
SymbolKind,
1313
};
1414
use smallvec::SmallVec;
15-
use stdx::{format_to, impl_from, never};
16-
use syntax::{algo, TextRange};
15+
use stdx::{impl_from, never};
16+
use syntax::{algo, SmolStr, TextRange};
1717
use text_edit::TextEdit;
1818

1919
/// `CompletionItem` describes a single completion variant in the editor pop-up.
@@ -22,7 +22,7 @@ use text_edit::TextEdit;
2222
#[derive(Clone)]
2323
pub struct CompletionItem {
2424
/// Label in the completion pop up which identifies completion.
25-
label: String,
25+
label: SmolStr,
2626
/// Range of identifier that is being completed.
2727
///
2828
/// It should be used primarily for UI, but we also use this to convert
@@ -46,7 +46,7 @@ pub struct CompletionItem {
4646
///
4747
/// That is, in `foo.bar$0` lookup of `abracadabra` will be accepted (it
4848
/// contains `bar` sub sequence), and `quux` will rejected.
49-
lookup: Option<String>,
49+
lookup: Option<SmolStr>,
5050

5151
/// Additional info to show in the UI pop up.
5252
detail: Option<String>,
@@ -268,7 +268,7 @@ impl CompletionItem {
268268
pub(crate) fn new(
269269
kind: impl Into<CompletionItemKind>,
270270
source_range: TextRange,
271-
label: impl Into<String>,
271+
label: impl Into<SmolStr>,
272272
) -> Builder {
273273
let label = label.into();
274274
Builder {
@@ -379,13 +379,13 @@ impl ImportEdit {
379379
pub(crate) struct Builder {
380380
source_range: TextRange,
381381
imports_to_add: SmallVec<[ImportEdit; 1]>,
382-
trait_name: Option<String>,
383-
label: String,
382+
trait_name: Option<SmolStr>,
383+
label: SmolStr,
384384
insert_text: Option<String>,
385385
is_snippet: bool,
386386
detail: Option<String>,
387387
documentation: Option<Documentation>,
388-
lookup: Option<String>,
388+
lookup: Option<SmolStr>,
389389
kind: CompletionItemKind,
390390
text_edit: Option<TextEdit>,
391391
deprecated: bool,
@@ -400,25 +400,21 @@ impl Builder {
400400

401401
let mut label = self.label;
402402
let mut lookup = self.lookup;
403-
let mut insert_text = self.insert_text;
403+
let insert_text = self.insert_text.unwrap_or_else(|| label.to_string());
404404

405405
if let [import_edit] = &*self.imports_to_add {
406406
// snippets can have multiple imports, but normal completions only have up to one
407407
if let Some(original_path) = import_edit.import.original_path.as_ref() {
408408
lookup = lookup.or_else(|| Some(label.clone()));
409-
insert_text = insert_text.or_else(|| Some(label.clone()));
410-
format_to!(label, " (use {})", original_path)
409+
label = SmolStr::from(format!("{} (use {})", label, original_path));
411410
}
412411
} else if let Some(trait_name) = self.trait_name {
413-
insert_text = insert_text.or_else(|| Some(label.clone()));
414-
format_to!(label, " (as {})", trait_name)
412+
label = SmolStr::from(format!("{} (as {})", label, trait_name));
415413
}
416414

417415
let text_edit = match self.text_edit {
418416
Some(it) => it,
419-
None => {
420-
TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone()))
421-
}
417+
None => TextEdit::replace(self.source_range, insert_text),
422418
};
423419

424420
CompletionItem {
@@ -437,16 +433,16 @@ impl Builder {
437433
import_to_add: self.imports_to_add,
438434
}
439435
}
440-
pub(crate) fn lookup_by(&mut self, lookup: impl Into<String>) -> &mut Builder {
436+
pub(crate) fn lookup_by(&mut self, lookup: impl Into<SmolStr>) -> &mut Builder {
441437
self.lookup = Some(lookup.into());
442438
self
443439
}
444-
pub(crate) fn label(&mut self, label: impl Into<String>) -> &mut Builder {
440+
pub(crate) fn label(&mut self, label: impl Into<SmolStr>) -> &mut Builder {
445441
self.label = label.into();
446442
self
447443
}
448-
pub(crate) fn trait_name(&mut self, trait_name: impl Into<String>) -> &mut Builder {
449-
self.trait_name = Some(trait_name.into());
444+
pub(crate) fn trait_name(&mut self, trait_name: SmolStr) -> &mut Builder {
445+
self.trait_name = Some(trait_name);
450446
self
451447
}
452448
pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder {

crates/ide_completion/src/render.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ pub(crate) fn render_field(
8383
ty: &hir::Type,
8484
) -> CompletionItem {
8585
let is_deprecated = ctx.is_deprecated(field);
86-
let name = field.name(ctx.db()).to_string();
86+
let name = field.name(ctx.db()).to_smol_str();
8787
let mut item = CompletionItem::new(
8888
SymbolKind::Field,
8989
ctx.source_range(),
90-
receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)),
90+
receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name).into()),
9191
);
9292
item.set_relevance(CompletionRelevance {
9393
type_match: compute_type_match(ctx.completion, ty),
@@ -97,7 +97,7 @@ pub(crate) fn render_field(
9797
item.detail(ty.display(ctx.db()).to_string())
9898
.set_documentation(field.docs(ctx.db()))
9999
.set_deprecated(is_deprecated)
100-
.lookup_by(name.as_str());
100+
.lookup_by(name.clone());
101101
let is_keyword = SyntaxKind::from_keyword(name.as_str()).is_some();
102102
if is_keyword && !matches!(name.as_str(), "self" | "crate" | "super" | "Self") {
103103
item.insert_text(format!("r#{}", name));
@@ -199,7 +199,7 @@ fn render_resolution_(
199199
let mut item = CompletionItem::new(
200200
CompletionItemKind::UnresolvedReference,
201201
ctx.source_range(),
202-
local_name.to_string(),
202+
local_name.to_smol_str(),
203203
);
204204
if let Some(import_to_add) = import_to_add {
205205
item.add_import(import_to_add);
@@ -208,7 +208,7 @@ fn render_resolution_(
208208
}
209209
};
210210

211-
let local_name = local_name.to_string();
211+
let local_name = local_name.to_smol_str();
212212
let mut item = CompletionItem::new(kind, ctx.source_range(), local_name.clone());
213213
if let hir::ScopeDef::Local(local) = resolution {
214214
let ty = local.ty(ctx.db());

0 commit comments

Comments
 (0)